osmesa.c revision 5bdec89da520f763b6d0faad1781f64566a97fdd
1/*
2 * Mesa 3-D graphics library
3 * Version:  6.5
4 *
5 * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26/*
27 * Off-Screen Mesa rendering / Rendering into client memory space
28 *
29 * Note on thread safety:  this driver is thread safe.  All
30 * functions are reentrant.  The notion of current context is
31 * managed by the core _mesa_make_current() and _mesa_get_current_context()
32 * functions.  Those functions are thread-safe.
33 */
34
35
36#include "glheader.h"
37#include "GL/osmesa.h"
38#include "context.h"
39#include "extensions.h"
40#include "framebuffer.h"
41#include "fbobject.h"
42#include "imports.h"
43#include "mtypes.h"
44#include "renderbuffer.h"
45#include "array_cache/acache.h"
46#include "swrast/swrast.h"
47#include "swrast_setup/swrast_setup.h"
48#include "swrast/s_context.h"
49#include "swrast/s_depth.h"
50#include "swrast/s_lines.h"
51#include "swrast/s_triangle.h"
52#include "tnl/tnl.h"
53#include "tnl/t_context.h"
54#include "tnl/t_pipeline.h"
55#include "drivers/common/driverfuncs.h"
56
57
58
59/*
60 * This is the OS/Mesa context struct.
61 * Notice how it includes a GLcontext.  By doing this we're mimicking
62 * C++ inheritance/derivation.
63 * Later, we can cast a GLcontext pointer into an OSMesaContext pointer
64 * or vice versa.
65 */
66struct osmesa_context {
67   GLcontext mesa;		/* The core GL/Mesa context */
68   GLvisual *gl_visual;		/* Describes the buffers */
69   GLframebuffer *gl_buffer;	/* Depth, stencil, accum, etc buffers */
70   GLenum format;		/* either GL_RGBA or GL_COLOR_INDEX */
71   void *buffer;		/* the image buffer */
72   GLint width, height;		/* size of image buffer */
73   GLint rowlength;		/* number of pixels per row */
74   GLint userRowLength;		/* user-specified number of pixels per row */
75   GLint rInd, gInd, bInd, aInd;/* index offsets for RGBA formats */
76   GLchan *rowaddr[MAX_HEIGHT];	/* address of first pixel in each image row */
77   GLboolean yup;		/* TRUE  -> Y increases upward */
78				/* FALSE -> Y increases downward */
79};
80
81
82/* Just cast, since we're using structure containment */
83#define OSMESA_CONTEXT(ctx)  ((OSMesaContext) (ctx->DriverCtx))
84
85
86
87/**********************************************************************/
88/*** Private Device Driver Functions                                ***/
89/**********************************************************************/
90
91
92static const GLubyte *
93get_string( GLcontext *ctx, GLenum name )
94{
95   (void) ctx;
96   switch (name) {
97      case GL_RENDERER:
98#if CHAN_BITS == 32
99         return (const GLubyte *) "Mesa OffScreen32";
100#elif CHAN_BITS == 16
101         return (const GLubyte *) "Mesa OffScreen16";
102#else
103         return (const GLubyte *) "Mesa OffScreen";
104#endif
105      default:
106         return NULL;
107   }
108}
109
110
111static void
112osmesa_update_state( GLcontext *ctx, GLuint new_state )
113{
114   /* easy - just propogate */
115   _swrast_InvalidateState( ctx, new_state );
116   _swsetup_InvalidateState( ctx, new_state );
117   _ac_InvalidateState( ctx, new_state );
118   _tnl_InvalidateState( ctx, new_state );
119}
120
121
122/*
123 * Just return the current buffer size.
124 * There's no window to track the size of.
125 */
126static void
127get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height )
128{
129   /* don't use GET_CURRENT_CONTEXT(ctx) here - it's a problem on Windows */
130   GLcontext *ctx = (GLcontext *) _glapi_get_context();
131   (void) buffer;
132   if (ctx) {
133      OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
134      *width = osmesa->width;
135      *height = osmesa->height;
136   }
137}
138
139
140/**********************************************************************/
141/*****        Read/write spans/arrays of pixels                   *****/
142/**********************************************************************/
143
144/* RGBA */
145#define NAME(PREFIX) PREFIX##_RGBA
146#define FORMAT GL_RGBA
147#define SPAN_VARS \
148   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
149#define INIT_PIXEL_PTR(P, X, Y) \
150   GLchan *P = osmesa->rowaddr[Y] + 4 * (X)
151#define INC_PIXEL_PTR(P) P += 4
152#if CHAN_TYPE == GL_FLOAT
153#define STORE_PIXEL(DST, X, Y, VALUE) \
154   DST[0] = MAX2((VALUE[RCOMP]), 0.0F); \
155   DST[1] = MAX2((VALUE[GCOMP]), 0.0F); \
156   DST[2] = MAX2((VALUE[BCOMP]), 0.0F); \
157   DST[3] = CLAMP((VALUE[ACOMP]), 0.0F, CHAN_MAXF)
158#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
159   DST[0] = MAX2((VALUE[RCOMP]), 0.0F); \
160   DST[1] = MAX2((VALUE[GCOMP]), 0.0F); \
161   DST[2] = MAX2((VALUE[BCOMP]), 0.0F); \
162   DST[3] = CHAN_MAXF
163#else
164#define STORE_PIXEL(DST, X, Y, VALUE) \
165   DST[0] = VALUE[RCOMP];  \
166   DST[1] = VALUE[GCOMP];  \
167   DST[2] = VALUE[BCOMP];  \
168   DST[3] = VALUE[ACOMP]
169#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
170   DST[0] = VALUE[RCOMP];  \
171   DST[1] = VALUE[GCOMP];  \
172   DST[2] = VALUE[BCOMP];  \
173   DST[3] = CHAN_MAX
174#endif
175#define FETCH_PIXEL(DST, SRC) \
176   DST[RCOMP] = SRC[0];  \
177   DST[GCOMP] = SRC[1];  \
178   DST[BCOMP] = SRC[2];  \
179   DST[ACOMP] = SRC[3]
180#include "swrast/s_spantemp.h"
181
182/* BGRA */
183#define NAME(PREFIX) PREFIX##_BGRA
184#define FORMAT GL_RGBA
185#define SPAN_VARS \
186   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
187#define INIT_PIXEL_PTR(P, X, Y) \
188   GLchan *P = osmesa->rowaddr[Y] + 4 * (X)
189#define INC_PIXEL_PTR(P) P += 4
190#define STORE_PIXEL(DST, X, Y, VALUE) \
191   DST[2] = VALUE[RCOMP];  \
192   DST[1] = VALUE[GCOMP];  \
193   DST[0] = VALUE[BCOMP];  \
194   DST[3] = VALUE[ACOMP]
195#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
196   DST[2] = VALUE[RCOMP];  \
197   DST[1] = VALUE[GCOMP];  \
198   DST[0] = VALUE[BCOMP];  \
199   DST[3] = CHAN_MAX
200#define FETCH_PIXEL(DST, SRC) \
201   DST[RCOMP] = SRC[2];  \
202   DST[GCOMP] = SRC[1];  \
203   DST[BCOMP] = SRC[0];  \
204   DST[ACOMP] = SRC[3]
205#include "swrast/s_spantemp.h"
206
207/* ARGB */
208#define NAME(PREFIX) PREFIX##_ARGB
209#define FORMAT GL_RGBA
210#define SPAN_VARS \
211   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
212#define INIT_PIXEL_PTR(P, X, Y) \
213   GLchan *P = osmesa->rowaddr[Y] + 4 * (X)
214#define INC_PIXEL_PTR(P) P += 4
215#define STORE_PIXEL(DST, X, Y, VALUE) \
216   DST[1] = VALUE[RCOMP];  \
217   DST[2] = VALUE[GCOMP];  \
218   DST[3] = VALUE[BCOMP];  \
219   DST[0] = VALUE[ACOMP]
220#define STORE_PIXEL_RGB(DST, X, Y, VALUE) \
221   DST[1] = VALUE[RCOMP];  \
222   DST[2] = VALUE[GCOMP];  \
223   DST[3] = VALUE[BCOMP];  \
224   DST[0] = CHAN_MAX
225#define FETCH_PIXEL(DST, SRC) \
226   DST[RCOMP] = SRC[1];  \
227   DST[GCOMP] = SRC[2];  \
228   DST[BCOMP] = SRC[3];  \
229   DST[ACOMP] = SRC[0]
230#include "swrast/s_spantemp.h"
231
232/* RGB */
233#define NAME(PREFIX) PREFIX##_RGB
234#define FORMAT GL_RGBA
235#define SPAN_VARS \
236   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
237#define INIT_PIXEL_PTR(P, X, Y) \
238   GLchan *P = osmesa->rowaddr[Y] + 4 * (X)
239#define INC_PIXEL_PTR(P) P += 3
240#define STORE_PIXEL(DST, X, Y, VALUE) \
241   DST[0] = VALUE[RCOMP];  \
242   DST[1] = VALUE[GCOMP];  \
243   DST[2] = VALUE[BCOMP]
244#define FETCH_PIXEL(DST, SRC) \
245   DST[RCOMP] = SRC[0];  \
246   DST[GCOMP] = SRC[1];  \
247   DST[BCOMP] = SRC[2];  \
248   DST[ACOMP] = CHAN_MAX
249#include "swrast/s_spantemp.h"
250
251/* BGR */
252#define NAME(PREFIX) PREFIX##_BGR
253#define FORMAT GL_RGBA
254#define SPAN_VARS \
255   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
256#define INIT_PIXEL_PTR(P, X, Y) \
257   GLchan *P = osmesa->rowaddr[Y] + 4 * (X)
258#define INC_PIXEL_PTR(P) P += 3
259#define STORE_PIXEL(DST, X, Y, VALUE) \
260   DST[2] = VALUE[RCOMP];  \
261   DST[1] = VALUE[GCOMP];  \
262   DST[0] = VALUE[BCOMP]
263#define FETCH_PIXEL(DST, SRC) \
264   DST[RCOMP] = SRC[2];  \
265   DST[GCOMP] = SRC[1];  \
266   DST[BCOMP] = SRC[0];  \
267   DST[ACOMP] = CHAN_MAX
268#include "swrast/s_spantemp.h"
269
270/* 16-bit RGB */
271#if CHAN_TYPE == GL_UNSIGNED_BYTE
272#define NAME(PREFIX) PREFIX##_RGB_565
273#define FORMAT GL_RGBA
274#define SPAN_VARS \
275   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
276#define INIT_PIXEL_PTR(P, X, Y) \
277   GLushort *P = (GLushort *) osmesa->rowaddr[Y] + (X)
278#define INC_PIXEL_PTR(P) P += 1
279#define STORE_PIXEL(DST, X, Y, VALUE) \
280   *DST = ( (((VALUE[RCOMP]) & 0xf8) << 8) | (((VALUE[GCOMP]) & 0xfc) << 3) | ((VALUE[BCOMP]) >> 3) )
281#define FETCH_PIXEL(DST, SRC) \
282   DST[RCOMP] = ( (((*SRC) >> 8) & 0xf8) | (((*SRC) >> 11) & 0x7) ); \
283   DST[GCOMP] = ( (((*SRC) >> 3) & 0xfc) | (((*SRC) >>  5) & 0x3) ); \
284   DST[BCOMP] = ( (((*SRC) << 3) & 0xf8) | (((*SRC)      ) & 0x7) ); \
285   DST[ACOMP] = CHAN_MAX
286#include "swrast/s_spantemp.h"
287#endif /* CHAN_TYPE == GL_UNSIGNED_BYTE */
288
289/* color index */
290#define NAME(PREFIX) PREFIX##_CI
291#define FORMAT GL_COLOR_INDEX8_EXT
292#define SPAN_VARS \
293   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
294#define INIT_PIXEL_PTR(P, X, Y) \
295   GLubyte *P = (GLubyte *) osmesa->rowaddr[Y] + (X)
296#define INC_PIXEL_PTR(P) P += 1
297#define STORE_PIXEL(DST, X, Y, VALUE) \
298   *DST = VALUE[0]
299#define FETCH_PIXEL(DST, SRC) \
300   DST = SRC[0]
301#include "swrast/s_spantemp.h"
302
303
304
305
306/**********************************************************************/
307/*****                   Optimized line rendering                 *****/
308/**********************************************************************/
309
310
311#if CHAN_TYPE == GL_FLOAT
312#define PACK_RGBA(DST, R, G, B, A)	\
313do {					\
314   (DST)[0] = MAX2( R, 0.0F );		\
315   (DST)[1] = MAX2( G, 0.0F );		\
316   (DST)[2] = MAX2( B, 0.0F );		\
317   (DST)[3] = CLAMP(A, 0.0F, CHAN_MAXF);\
318} while (0)
319#else
320#define PACK_RGBA(DST, R, G, B, A)	\
321do {					\
322   (DST)[osmesa->rInd] = R;		\
323   (DST)[osmesa->gInd] = G;		\
324   (DST)[osmesa->bInd] = B;		\
325   (DST)[osmesa->aInd] = A;		\
326} while (0)
327#endif
328
329#define PACK_RGB(DST, R, G, B)  \
330do {				\
331   (DST)[0] = R;		\
332   (DST)[1] = G;		\
333   (DST)[2] = B;		\
334} while (0)
335
336#define PACK_BGR(DST, R, G, B)  \
337do {				\
338   (DST)[0] = B;		\
339   (DST)[1] = G;		\
340   (DST)[2] = R;		\
341} while (0)
342
343#define PACK_RGB_565(DST, R, G, B)					\
344do {									\
345   (DST) = (((int) (R) << 8) & 0xf800) | (((int) (G) << 3) & 0x7e0) | ((int) (B) >> 3);\
346} while (0)
347
348#define UNPACK_RED(P)      ( (P)[osmesa->rInd] )
349#define UNPACK_GREEN(P)    ( (P)[osmesa->gInd] )
350#define UNPACK_BLUE(P)     ( (P)[osmesa->bInd] )
351#define UNPACK_ALPHA(P)    ( (P)[osmesa->aInd] )
352
353#define PIXELADDR1(X,Y)  (osmesa->rowaddr[Y] + (X))
354#define PIXELADDR2(X,Y)  (osmesa->rowaddr[Y] + 2 * (X))
355#define PIXELADDR3(X,Y)  (osmesa->rowaddr[Y] + 3 * (X))
356#define PIXELADDR4(X,Y)  (osmesa->rowaddr[Y] + 4 * (X))
357
358
359/*
360 * Draw a flat-shaded, RGB line into an osmesa buffer.
361 */
362#define NAME flat_rgba_line
363#define CLIP_HACK 1
364#define SETUP_CODE						\
365   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);		\
366   const GLchan *color = vert1->color;
367
368#define PLOT(X, Y)						\
369do {								\
370   GLchan *p = PIXELADDR4(X, Y);				\
371   PACK_RGBA(p, color[0], color[1], color[2], color[3]);	\
372} while (0)
373
374#ifdef WIN32
375#include "..\swrast\s_linetemp.h"
376#else
377#include "swrast/s_linetemp.h"
378#endif
379
380
381
382/*
383 * Draw a flat-shaded, Z-less, RGB line into an osmesa buffer.
384 */
385#define NAME flat_rgba_z_line
386#define CLIP_HACK 1
387#define INTERP_Z 1
388#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
389#define SETUP_CODE					\
390   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);	\
391   const GLchan *color = vert1->color;
392
393#define PLOT(X, Y)					\
394do {							\
395   if (Z < *zPtr) {					\
396      GLchan *p = PIXELADDR4(X, Y);			\
397      PACK_RGBA(p, color[RCOMP], color[GCOMP],		\
398                   color[BCOMP], color[ACOMP]);		\
399      *zPtr = Z;					\
400   }							\
401} while (0)
402
403#ifdef WIN32
404#include "..\swrast\s_linetemp.h"
405#else
406#include "swrast/s_linetemp.h"
407#endif
408
409
410
411/*
412 * Analyze context state to see if we can provide a fast line drawing
413 * function, like those in lines.c.  Otherwise, return NULL.
414 */
415static swrast_line_func
416osmesa_choose_line_function( GLcontext *ctx )
417{
418   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
419   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
420
421   if (CHAN_BITS != 8)                    return NULL;
422   if (ctx->RenderMode != GL_RENDER)      return NULL;
423   if (ctx->Line.SmoothFlag)              return NULL;
424   if (ctx->Texture._EnabledUnits)        return NULL;
425   if (ctx->Light.ShadeModel != GL_FLAT)  return NULL;
426   if (ctx->Line.Width != 1.0F)           return NULL;
427   if (ctx->Line.StippleFlag)             return NULL;
428   if (ctx->Line.SmoothFlag)              return NULL;
429   if (osmesa->format != OSMESA_RGBA &&
430       osmesa->format != OSMESA_BGRA &&
431       osmesa->format != OSMESA_ARGB)     return NULL;
432
433   if (swrast->_RasterMask==DEPTH_BIT
434       && ctx->Depth.Func==GL_LESS
435       && ctx->Depth.Mask==GL_TRUE
436       && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) {
437      return (swrast_line_func) flat_rgba_z_line;
438   }
439
440   if (swrast->_RasterMask == 0) {
441      return (swrast_line_func) flat_rgba_line;
442   }
443
444   return (swrast_line_func) NULL;
445}
446
447
448/**********************************************************************/
449/*****                 Optimized triangle rendering               *****/
450/**********************************************************************/
451
452
453/*
454 * Smooth-shaded, z-less triangle, RGBA color.
455 */
456#define NAME smooth_rgba_z_triangle
457#define INTERP_Z 1
458#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
459#define INTERP_RGB 1
460#define INTERP_ALPHA 1
461#define SETUP_CODE \
462   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
463#define RENDER_SPAN( span ) {					\
464   GLuint i;							\
465   GLchan *img = PIXELADDR4(span.x, span.y); 			\
466   for (i = 0; i < span.end; i++, img += 4) {			\
467      const GLuint z = FixedToDepth(span.z);			\
468      if (z < zRow[i]) {					\
469         PACK_RGBA(img, FixedToChan(span.red),			\
470            FixedToChan(span.green), FixedToChan(span.blue),	\
471            FixedToChan(span.alpha));				\
472         zRow[i] = z;						\
473      }								\
474      span.red += span.redStep;					\
475      span.green += span.greenStep;				\
476      span.blue += span.blueStep;				\
477      span.alpha += span.alphaStep;				\
478      span.z += span.zStep;					\
479   }                                                            \
480}
481#ifdef WIN32
482#include "..\swrast\s_tritemp.h"
483#else
484#include "swrast/s_tritemp.h"
485#endif
486
487
488
489/*
490 * Flat-shaded, z-less triangle, RGBA color.
491 */
492#define NAME flat_rgba_z_triangle
493#define INTERP_Z 1
494#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
495#define SETUP_CODE						\
496   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);		\
497   GLuint pixel;						\
498   PACK_RGBA((GLchan *) &pixel, v2->color[0], v2->color[1],	\
499                                v2->color[2], v2->color[3]);
500
501#define RENDER_SPAN( span ) {				\
502   GLuint i;						\
503   GLuint *img = (GLuint *) PIXELADDR4(span.x, span.y);	\
504   for (i = 0; i < span.end; i++) {			\
505      const GLuint z = FixedToDepth(span.z);		\
506      if (z < zRow[i]) {				\
507         img[i] = pixel;				\
508         zRow[i] = z;					\
509      }							\
510      span.z += span.zStep;				\
511   }                                                    \
512}
513#ifdef WIN32
514#include "..\swrast\s_tritemp.h"
515#else
516#include "swrast/s_tritemp.h"
517#endif
518
519
520
521/*
522 * Return pointer to an accelerated triangle function if possible.
523 */
524static swrast_tri_func
525osmesa_choose_triangle_function( GLcontext *ctx )
526{
527   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
528   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
529
530   if (CHAN_BITS != 8)                  return (swrast_tri_func) NULL;
531   if (ctx->RenderMode != GL_RENDER)    return (swrast_tri_func) NULL;
532   if (ctx->Polygon.SmoothFlag)         return (swrast_tri_func) NULL;
533   if (ctx->Polygon.StippleFlag)        return (swrast_tri_func) NULL;
534   if (ctx->Texture._EnabledUnits)      return (swrast_tri_func) NULL;
535   if (osmesa->format != OSMESA_RGBA &&
536       osmesa->format != OSMESA_BGRA &&
537       osmesa->format != OSMESA_ARGB)   return (swrast_tri_func) NULL;
538   if (ctx->Polygon.CullFlag &&
539       ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK)
540                                        return (swrast_tri_func) NULL;
541
542   if (swrast->_RasterMask == DEPTH_BIT &&
543       ctx->Depth.Func == GL_LESS &&
544       ctx->Depth.Mask == GL_TRUE &&
545       ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) {
546      if (ctx->Light.ShadeModel == GL_SMOOTH) {
547         return (swrast_tri_func) smooth_rgba_z_triangle;
548      }
549      else {
550         return (swrast_tri_func) flat_rgba_z_triangle;
551      }
552   }
553   return (swrast_tri_func) NULL;
554}
555
556
557
558/* Override for the swrast triangle-selection function.  Try to use one
559 * of our internal triangle functions, otherwise fall back to the
560 * standard swrast functions.
561 */
562static void
563osmesa_choose_triangle( GLcontext *ctx )
564{
565   SWcontext *swrast = SWRAST_CONTEXT(ctx);
566
567   swrast->Triangle = osmesa_choose_triangle_function( ctx );
568   if (!swrast->Triangle)
569      _swrast_choose_triangle( ctx );
570}
571
572static void
573osmesa_choose_line( GLcontext *ctx )
574{
575   SWcontext *swrast = SWRAST_CONTEXT(ctx);
576
577   swrast->Line = osmesa_choose_line_function( ctx );
578   if (!swrast->Line)
579      _swrast_choose_line( ctx );
580}
581
582
583#define OSMESA_NEW_LINE   (_NEW_LINE | \
584                           _NEW_TEXTURE | \
585                           _NEW_LIGHT | \
586                           _NEW_DEPTH | \
587                           _NEW_RENDERMODE | \
588                           _SWRAST_NEW_RASTERMASK)
589
590#define OSMESA_NEW_TRIANGLE (_NEW_POLYGON | \
591                             _NEW_TEXTURE | \
592                             _NEW_LIGHT | \
593                             _NEW_DEPTH | \
594                             _NEW_RENDERMODE | \
595                             _SWRAST_NEW_RASTERMASK)
596
597
598/**
599 * Don't use _mesa_delete_renderbuffer since we can't free rb->Data.
600 */
601static void
602osmesa_delete_renderbuffer(struct gl_renderbuffer *rb)
603{
604   _mesa_free(rb);
605}
606
607
608/**
609 * Allocate renderbuffer storage.  We don't actually allocate any storage
610 * since we're using a user-provided buffer.
611 * Just set up all the gl_renderbuffer methods.
612 */
613static GLboolean
614osmesa_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
615                            GLenum internalFormat, GLuint width, GLuint height)
616{
617   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
618
619   if (osmesa->format == OSMESA_RGBA) {
620      rb->GetRow = get_row_RGBA;
621      rb->GetValues = get_values_RGBA;
622      rb->PutRow = put_row_RGBA;
623      rb->PutRowRGB = put_row_rgb_RGBA;
624      rb->PutMonoRow = put_mono_row_RGBA;
625      rb->PutValues = put_values_RGBA;
626      rb->PutMonoValues = put_mono_values_RGBA;
627   }
628   else if (osmesa->format == OSMESA_BGRA) {
629      rb->GetRow = get_row_BGRA;
630      rb->GetValues = get_values_BGRA;
631      rb->PutRow = put_row_BGRA;
632      rb->PutRowRGB = put_row_rgb_BGRA;
633      rb->PutMonoRow = put_mono_row_BGRA;
634      rb->PutValues = put_values_BGRA;
635      rb->PutMonoValues = put_mono_values_BGRA;
636   }
637   else if (osmesa->format == OSMESA_ARGB) {
638      rb->GetRow = get_row_ARGB;
639      rb->GetValues = get_values_ARGB;
640      rb->PutRow = put_row_ARGB;
641      rb->PutRowRGB = put_row_rgb_ARGB;
642      rb->PutMonoRow = put_mono_row_ARGB;
643      rb->PutValues = put_values_ARGB;
644      rb->PutMonoValues = put_mono_values_ARGB;
645   }
646   else if (osmesa->format == OSMESA_RGB) {
647      rb->GetRow = get_row_RGB;
648      rb->GetValues = get_values_RGB;
649      rb->PutRow = put_row_RGB;
650      rb->PutRowRGB = put_row_rgb_RGB;
651      rb->PutMonoRow = put_mono_row_RGB;
652      rb->PutValues = put_values_RGB;
653      rb->PutMonoValues = put_mono_values_RGB;
654   }
655   else if (osmesa->format == OSMESA_BGR) {
656      rb->GetRow = get_row_BGR;
657      rb->GetValues = get_values_BGR;
658      rb->PutRow = put_row_BGR;
659      rb->PutRowRGB = put_row_rgb_BGR;
660      rb->PutMonoRow = put_mono_row_BGR;
661      rb->PutValues = put_values_BGR;
662      rb->PutMonoValues = put_mono_values_BGR;
663   }
664#if CHAN_TYPE == GL_UNSIGNED_BYTE
665   else if (osmesa->format == OSMESA_RGB_565) {
666      rb->GetRow = get_row_RGB_565;
667      rb->GetValues = get_values_RGB_565;
668      rb->PutRow = put_row_RGB_565;
669      rb->PutRow = put_row_rgb_RGB_565;
670      rb->PutMonoRow = put_mono_row_RGB_565;
671      rb->PutValues = put_values_RGB_565;
672      rb->PutMonoValues = put_mono_values_RGB_565;
673   }
674#endif
675   else if (osmesa->format == OSMESA_COLOR_INDEX) {
676      rb->GetRow = get_row_CI;
677      rb->GetValues = get_values_CI;
678      rb->PutRow = put_row_CI;
679      rb->PutMonoRow = put_mono_row_CI;
680      rb->PutValues = put_values_CI;
681      rb->PutMonoValues = put_mono_values_CI;
682   }
683   else {
684      _mesa_problem(ctx, "bad pixel format in osmesa renderbuffer_storage");
685   }
686
687   return GL_TRUE;
688}
689
690
691/**
692 * Allocate a new renderbuffer tpo describe the user-provided color buffer.
693 */
694static struct gl_renderbuffer *
695new_osmesa_renderbuffer(GLenum format)
696{
697   struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer);
698   if (rb) {
699      const GLuint name = 0;
700      _mesa_init_renderbuffer(rb, name);
701
702      rb->Delete = osmesa_delete_renderbuffer;
703      rb->AllocStorage = osmesa_renderbuffer_storage;
704
705      if (format == OSMESA_COLOR_INDEX) {
706         rb->_BaseFormat = GL_COLOR_INDEX;
707         rb->InternalFormat = GL_COLOR_INDEX;
708         rb->DataType = GL_UNSIGNED_BYTE;
709      }
710      else {
711         rb->_BaseFormat = GL_RGBA;
712         rb->InternalFormat = GL_RGBA;
713         rb->DataType = CHAN_TYPE;
714      }
715   }
716   return rb;
717}
718
719
720
721/**********************************************************************/
722/*****                    Public Functions                        *****/
723/**********************************************************************/
724
725
726/*
727 * Create an Off-Screen Mesa rendering context.  The only attribute needed is
728 * an RGBA vs Color-Index mode flag.
729 *
730 * Input:  format - either GL_RGBA or GL_COLOR_INDEX
731 *         sharelist - specifies another OSMesaContext with which to share
732 *                     display lists.  NULL indicates no sharing.
733 * Return:  an OSMesaContext or 0 if error
734 */
735GLAPI OSMesaContext GLAPIENTRY
736OSMesaCreateContext( GLenum format, OSMesaContext sharelist )
737{
738   const GLint accumBits = (format == OSMESA_COLOR_INDEX) ? 0 : 16;
739   return OSMesaCreateContextExt(format, DEFAULT_SOFTWARE_DEPTH_BITS,
740                                 8, accumBits, sharelist);
741}
742
743
744
745/*
746 * New in Mesa 3.5
747 *
748 * Create context and specify size of ancillary buffers.
749 */
750GLAPI OSMesaContext GLAPIENTRY
751OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
752                        GLint accumBits, OSMesaContext sharelist )
753{
754   OSMesaContext osmesa;
755   struct dd_function_table functions;
756   GLint rind, gind, bind, aind;
757   GLint indexBits = 0, redBits = 0, greenBits = 0, blueBits = 0, alphaBits =0;
758   GLboolean rgbmode;
759
760   rind = gind = bind = aind = 0;
761   if (format==OSMESA_COLOR_INDEX) {
762      indexBits = 8;
763      rgbmode = GL_FALSE;
764   }
765   else if (format==OSMESA_RGBA) {
766      indexBits = 0;
767      redBits = CHAN_BITS;
768      greenBits = CHAN_BITS;
769      blueBits = CHAN_BITS;
770      alphaBits = CHAN_BITS;
771      rind = 0;
772      gind = 1;
773      bind = 2;
774      aind = 3;
775      rgbmode = GL_TRUE;
776   }
777   else if (format==OSMESA_BGRA) {
778      indexBits = 0;
779      redBits = CHAN_BITS;
780      greenBits = CHAN_BITS;
781      blueBits = CHAN_BITS;
782      alphaBits = CHAN_BITS;
783      bind = 0;
784      gind = 1;
785      rind = 2;
786      aind = 3;
787      rgbmode = GL_TRUE;
788   }
789   else if (format==OSMESA_ARGB) {
790      indexBits = 0;
791      redBits = CHAN_BITS;
792      greenBits = CHAN_BITS;
793      blueBits = CHAN_BITS;
794      alphaBits = CHAN_BITS;
795      aind = 0;
796      rind = 1;
797      gind = 2;
798      bind = 3;
799      rgbmode = GL_TRUE;
800   }
801   else if (format==OSMESA_RGB) {
802      indexBits = 0;
803      redBits = CHAN_BITS;
804      greenBits = CHAN_BITS;
805      blueBits = CHAN_BITS;
806      alphaBits = 0;
807      rind = 0;
808      gind = 1;
809      bind = 2;
810      rgbmode = GL_TRUE;
811   }
812   else if (format==OSMESA_BGR) {
813      indexBits = 0;
814      redBits = CHAN_BITS;
815      greenBits = CHAN_BITS;
816      blueBits = CHAN_BITS;
817      alphaBits = 0;
818      rind = 2;
819      gind = 1;
820      bind = 0;
821      rgbmode = GL_TRUE;
822   }
823#if CHAN_TYPE == GL_UNSIGNED_BYTE
824   else if (format==OSMESA_RGB_565) {
825      indexBits = 0;
826      redBits = 5;
827      greenBits = 6;
828      blueBits = 5;
829      alphaBits = 0;
830      rind = 0; /* not used */
831      gind = 0;
832      bind = 0;
833      rgbmode = GL_TRUE;
834   }
835#endif
836   else {
837      return NULL;
838   }
839
840   osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context);
841   if (osmesa) {
842      osmesa->gl_visual = _mesa_create_visual( rgbmode,
843                                               GL_FALSE,    /* double buffer */
844                                               GL_FALSE,    /* stereo */
845                                               redBits,
846                                               greenBits,
847                                               blueBits,
848                                               alphaBits,
849                                               indexBits,
850                                               depthBits,
851                                               stencilBits,
852                                               accumBits,
853                                               accumBits,
854                                               accumBits,
855                                               alphaBits ? accumBits : 0,
856                                               1            /* num samples */
857                                               );
858      if (!osmesa->gl_visual) {
859         FREE(osmesa);
860         return NULL;
861      }
862
863      /* Initialize device driver function table */
864      _mesa_init_driver_functions(&functions);
865      /* override with our functions */
866      functions.GetString = get_string;
867      functions.UpdateState = osmesa_update_state;
868      functions.GetBufferSize = get_buffer_size;
869
870      if (!_mesa_initialize_context(&osmesa->mesa,
871                                    osmesa->gl_visual,
872                                    sharelist ? &sharelist->mesa
873                                              : (GLcontext *) NULL,
874                                    &functions, (void *) osmesa)) {
875         _mesa_destroy_visual( osmesa->gl_visual );
876         FREE(osmesa);
877         return NULL;
878      }
879
880      _mesa_enable_sw_extensions(&(osmesa->mesa));
881      _mesa_enable_1_3_extensions(&(osmesa->mesa));
882      _mesa_enable_1_4_extensions(&(osmesa->mesa));
883      _mesa_enable_1_5_extensions(&(osmesa->mesa));
884
885      osmesa->gl_buffer = _mesa_create_framebuffer(osmesa->gl_visual);
886      if (!osmesa->gl_buffer) {
887         _mesa_destroy_visual( osmesa->gl_visual );
888         _mesa_free_context_data( &osmesa->mesa );
889         FREE(osmesa);
890         return NULL;
891      }
892
893      /* create front color buffer in user-provided memory (no back buffer) */
894      _mesa_add_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT,
895                             new_osmesa_renderbuffer(format));
896      _mesa_add_soft_renderbuffers(osmesa->gl_buffer,
897                                   GL_FALSE, /* color */
898                                   osmesa->gl_visual->haveDepthBuffer,
899                                   osmesa->gl_visual->haveStencilBuffer,
900                                   osmesa->gl_visual->haveAccumBuffer,
901                                   GL_FALSE, /* alpha */
902                                   GL_FALSE /* aux */ );
903
904      osmesa->format = format;
905      osmesa->buffer = NULL;
906      osmesa->width = 0;
907      osmesa->height = 0;
908      osmesa->userRowLength = 0;
909      osmesa->rowlength = 0;
910      osmesa->yup = GL_TRUE;
911      osmesa->rInd = rind;
912      osmesa->gInd = gind;
913      osmesa->bInd = bind;
914      osmesa->aInd = aind;
915
916      /* Initialize the software rasterizer and helper modules. */
917      {
918	 GLcontext *ctx = &osmesa->mesa;
919         SWcontext *swrast;
920         TNLcontext *tnl;
921
922	 if (!_swrast_CreateContext( ctx ) ||
923             !_ac_CreateContext( ctx ) ||
924             !_tnl_CreateContext( ctx ) ||
925             !_swsetup_CreateContext( ctx )) {
926            _mesa_destroy_visual(osmesa->gl_visual);
927            _mesa_free_context_data(ctx);
928            _mesa_free(osmesa);
929            return NULL;
930         }
931
932	 _swsetup_Wakeup( ctx );
933
934         /* use default TCL pipeline */
935         tnl = TNL_CONTEXT(ctx);
936         tnl->Driver.RunPipeline = _tnl_run_pipeline;
937
938         /* Extend the software rasterizer with our optimized line and triangle
939          * drawing functions.
940          */
941         swrast = SWRAST_CONTEXT( ctx );
942         swrast->choose_line = osmesa_choose_line;
943         swrast->choose_triangle = osmesa_choose_triangle;
944         swrast->invalidate_line |= OSMESA_NEW_LINE;
945         swrast->invalidate_triangle |= OSMESA_NEW_TRIANGLE;
946      }
947   }
948   return osmesa;
949}
950
951
952/*
953 * Destroy an Off-Screen Mesa rendering context.
954 *
955 * Input:  ctx - the context to destroy
956 */
957GLAPI void GLAPIENTRY
958OSMesaDestroyContext( OSMesaContext ctx )
959{
960   if (ctx) {
961      _swsetup_DestroyContext( &ctx->mesa );
962      _tnl_DestroyContext( &ctx->mesa );
963      _ac_DestroyContext( &ctx->mesa );
964      _swrast_DestroyContext( &ctx->mesa );
965
966      _mesa_destroy_visual( ctx->gl_visual );
967      _mesa_destroy_framebuffer( ctx->gl_buffer );
968      _mesa_free_context_data( &ctx->mesa );
969      FREE( ctx );
970   }
971}
972
973
974/*
975 * Recompute the values of the context's rowaddr array.
976 */
977static void
978compute_row_addresses( OSMesaContext ctx )
979{
980   GLint bytesPerPixel, bytesPerRow, i;
981   GLubyte *origin = (GLubyte *) ctx->buffer;
982
983   if (ctx->format == OSMESA_COLOR_INDEX) {
984      /* CI mode */
985      bytesPerPixel = 1 * sizeof(GLubyte);
986   }
987   else if ((ctx->format == OSMESA_RGB) || (ctx->format == OSMESA_BGR)) {
988      /* RGB mode */
989      bytesPerPixel = 3 * sizeof(GLchan);
990   }
991   else if (ctx->format == OSMESA_RGB_565) {
992      /* 5/6/5 RGB pixel in 16 bits */
993      bytesPerPixel = 2;
994   }
995   else {
996      /* RGBA mode */
997      bytesPerPixel = 4 * sizeof(GLchan);
998   }
999
1000   bytesPerRow = ctx->rowlength * bytesPerPixel;
1001
1002   if (ctx->yup) {
1003      /* Y=0 is bottom line of window */
1004      for (i = 0; i < MAX_HEIGHT; i++) {
1005         ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + i * bytesPerRow);
1006      }
1007   }
1008   else {
1009      /* Y=0 is top line of window */
1010      for (i = 0; i < MAX_HEIGHT; i++) {
1011         GLint j = ctx->height - i - 1;
1012         ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + j * bytesPerRow);
1013      }
1014   }
1015}
1016
1017
1018/*
1019 * Bind an OSMesaContext to an image buffer.  The image buffer is just a
1020 * block of memory which the client provides.  Its size must be at least
1021 * as large as width*height*sizeof(type).  Its address should be a multiple
1022 * of 4 if using RGBA mode.
1023 *
1024 * Image data is stored in the order of glDrawPixels:  row-major order
1025 * with the lower-left image pixel stored in the first array position
1026 * (ie. bottom-to-top).
1027 *
1028 * If the context's viewport hasn't been initialized yet, it will now be
1029 * initialized to (0,0,width,height).
1030 *
1031 * Input:  ctx - the rendering context
1032 *         buffer - the image buffer memory
1033 *         type - data type for pixel components
1034 *            Normally, only GL_UNSIGNED_BYTE and GL_UNSIGNED_SHORT_5_6_5
1035 *            are supported.  But if Mesa's been compiled with CHAN_BITS==16
1036 *            then type must be GL_UNSIGNED_SHORT.  And if Mesa's been build
1037 *            with CHAN_BITS==32 then type must be GL_FLOAT.
1038 *         width, height - size of image buffer in pixels, at least 1
1039 * Return:  GL_TRUE if success, GL_FALSE if error because of invalid ctx,
1040 *          invalid buffer address, invalid type, width<1, height<1,
1041 *          width>internal limit or height>internal limit.
1042 */
1043GLAPI GLboolean GLAPIENTRY
1044OSMesaMakeCurrent( OSMesaContext ctx, void *buffer, GLenum type,
1045                   GLsizei width, GLsizei height )
1046{
1047   if (!ctx || !buffer ||
1048       width < 1 || height < 1 ||
1049       width > MAX_WIDTH || height > MAX_HEIGHT) {
1050      return GL_FALSE;
1051   }
1052
1053   if (ctx->format == OSMESA_RGB_565) {
1054      if (type != GL_UNSIGNED_SHORT_5_6_5)
1055         return GL_FALSE;
1056   }
1057   else if (type != CHAN_TYPE) {
1058      return GL_FALSE;
1059   }
1060
1061   /* Need to set these before calling _mesa_make_current() since the first
1062    * time the context is bound, _mesa_make_current() will call our
1063    * get_buffer_size() function to initialize the viewport.  These are the
1064    * values returned by get_buffer_size():
1065    */
1066   ctx->buffer = buffer;
1067   ctx->width = width;
1068   ctx->height = height;
1069
1070   osmesa_update_state( &ctx->mesa, 0 );
1071   _mesa_make_current( &ctx->mesa, ctx->gl_buffer, ctx->gl_buffer );
1072
1073   if (ctx->userRowLength)
1074      ctx->rowlength = ctx->userRowLength;
1075   else
1076      ctx->rowlength = width;
1077
1078   compute_row_addresses( ctx );
1079
1080   /* this will make ensure we recognize the new buffer size */
1081   _mesa_resize_framebuffer(&ctx->mesa, ctx->gl_buffer, width, height);
1082
1083   return GL_TRUE;
1084}
1085
1086
1087
1088GLAPI OSMesaContext GLAPIENTRY
1089OSMesaGetCurrentContext( void )
1090{
1091   GLcontext *ctx = _mesa_get_current_context();
1092   if (ctx)
1093      return (OSMesaContext) ctx;
1094   else
1095      return NULL;
1096}
1097
1098
1099
1100GLAPI void GLAPIENTRY
1101OSMesaPixelStore( GLint pname, GLint value )
1102{
1103   OSMesaContext osmesa = OSMesaGetCurrentContext();
1104
1105   switch (pname) {
1106      case OSMESA_ROW_LENGTH:
1107         if (value<0) {
1108            _mesa_error( &osmesa->mesa, GL_INVALID_VALUE,
1109                      "OSMesaPixelStore(value)" );
1110            return;
1111         }
1112         osmesa->userRowLength = value;
1113         osmesa->rowlength = value ? value : osmesa->width;
1114         break;
1115      case OSMESA_Y_UP:
1116         osmesa->yup = value ? GL_TRUE : GL_FALSE;
1117         break;
1118      default:
1119         _mesa_error( &osmesa->mesa, GL_INVALID_ENUM, "OSMesaPixelStore(pname)" );
1120         return;
1121   }
1122
1123   compute_row_addresses( osmesa );
1124}
1125
1126
1127GLAPI void GLAPIENTRY
1128OSMesaGetIntegerv( GLint pname, GLint *value )
1129{
1130   OSMesaContext osmesa = OSMesaGetCurrentContext();
1131
1132   switch (pname) {
1133      case OSMESA_WIDTH:
1134         *value = osmesa->width;
1135         return;
1136      case OSMESA_HEIGHT:
1137         *value = osmesa->height;
1138         return;
1139      case OSMESA_FORMAT:
1140         *value = osmesa->format;
1141         return;
1142      case OSMESA_TYPE:
1143         *value = CHAN_TYPE;
1144         return;
1145      case OSMESA_ROW_LENGTH:
1146         *value = osmesa->userRowLength;
1147         return;
1148      case OSMESA_Y_UP:
1149         *value = osmesa->yup;
1150         return;
1151      case OSMESA_MAX_WIDTH:
1152         *value = MAX_WIDTH;
1153         return;
1154      case OSMESA_MAX_HEIGHT:
1155         *value = MAX_HEIGHT;
1156         return;
1157      default:
1158         _mesa_error(&osmesa->mesa, GL_INVALID_ENUM, "OSMesaGetIntergerv(pname)");
1159         return;
1160   }
1161}
1162
1163/*
1164 * Return the depth buffer associated with an OSMesa context.
1165 * Input:  c - the OSMesa context
1166 * Output:  width, height - size of buffer in pixels
1167 *          bytesPerValue - bytes per depth value (2 or 4)
1168 *          buffer - pointer to depth buffer values
1169 * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
1170 */
1171GLAPI GLboolean GLAPIENTRY
1172OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height,
1173                      GLint *bytesPerValue, void **buffer )
1174{
1175   struct gl_renderbuffer *rb = NULL;
1176
1177   if (c->gl_buffer)
1178      rb = c->gl_buffer->Attachment[BUFFER_DEPTH].Renderbuffer;
1179
1180   if (!rb || !rb->Data) {
1181      /*if ((!c->gl_buffer) || (!c->gl_buffer->DepthBuffer)) {*/
1182      *width = 0;
1183      *height = 0;
1184      *bytesPerValue = 0;
1185      *buffer = 0;
1186      return GL_FALSE;
1187   }
1188   else {
1189      *width = c->gl_buffer->Width;
1190      *height = c->gl_buffer->Height;
1191      if (c->gl_visual->depthBits <= 16)
1192         *bytesPerValue = sizeof(GLushort);
1193      else
1194         *bytesPerValue = sizeof(GLuint);
1195      *buffer = rb->Data;
1196      return GL_TRUE;
1197   }
1198}
1199
1200/*
1201 * Return the color buffer associated with an OSMesa context.
1202 * Input:  c - the OSMesa context
1203 * Output:  width, height - size of buffer in pixels
1204 *          format - the pixel format (OSMESA_FORMAT)
1205 *          buffer - pointer to color buffer values
1206 * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
1207 */
1208GLAPI GLboolean GLAPIENTRY
1209OSMesaGetColorBuffer( OSMesaContext c, GLint *width,
1210                      GLint *height, GLint *format, void **buffer )
1211{
1212   if (!c->buffer) {
1213      *width = 0;
1214      *height = 0;
1215      *format = 0;
1216      *buffer = 0;
1217      return GL_FALSE;
1218   }
1219   else {
1220      *width = c->width;
1221      *height = c->height;
1222      *format = c->format;
1223      *buffer = c->buffer;
1224      return GL_TRUE;
1225   }
1226}
1227
1228
1229struct name_function
1230{
1231   const char *Name;
1232   OSMESAproc Function;
1233};
1234
1235static struct name_function functions[] = {
1236   { "OSMesaCreateContext", (OSMESAproc) OSMesaCreateContext },
1237   { "OSMesaCreateContextExt", (OSMESAproc) OSMesaCreateContextExt },
1238   { "OSMesaDestroyContext", (OSMESAproc) OSMesaDestroyContext },
1239   { "OSMesaMakeCurrent", (OSMESAproc) OSMesaMakeCurrent },
1240   { "OSMesaGetCurrentContext", (OSMESAproc) OSMesaGetCurrentContext },
1241   { "OSMesaPixelsStore", (OSMESAproc) OSMesaPixelStore },
1242   { "OSMesaGetIntegerv", (OSMESAproc) OSMesaGetIntegerv },
1243   { "OSMesaGetDepthBuffer", (OSMESAproc) OSMesaGetDepthBuffer },
1244   { "OSMesaGetColorBuffer", (OSMESAproc) OSMesaGetColorBuffer },
1245   { "OSMesaGetProcAddress", (OSMESAproc) OSMesaGetProcAddress },
1246   { NULL, NULL }
1247};
1248
1249
1250GLAPI OSMESAproc GLAPIENTRY
1251OSMesaGetProcAddress( const char *funcName )
1252{
1253   int i;
1254   for (i = 0; functions[i].Name; i++) {
1255      if (_mesa_strcmp(functions[i].Name, funcName) == 0)
1256         return functions[i].Function;
1257   }
1258   return _glapi_get_proc_address(funcName);
1259}
1260
1261
1262GLAPI void GLAPIENTRY
1263OSMesaColorClamp(GLboolean enable)
1264{
1265   OSMesaContext osmesa = OSMesaGetCurrentContext();
1266
1267   if (enable == GL_TRUE) {
1268      osmesa->mesa.Color.ClampFragmentColor = GL_TRUE;
1269   }
1270   else {
1271      osmesa->mesa.Color.ClampFragmentColor = GL_FIXED_ONLY_ARB;
1272   }
1273}
1274
1275
1276