osmesa.c revision b100484145d3518e4896d756b1ceccf61382c569
1/*
2 * Mesa 3-D graphics library
3 * Version:  6.5
4 *
5 * Copyright (C) 1999-2006  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] + 3 * (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] + 3 * (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/**
584 * Don't use _mesa_delete_renderbuffer since we can't free rb->Data.
585 */
586static void
587osmesa_delete_renderbuffer(struct gl_renderbuffer *rb)
588{
589   _mesa_free(rb);
590}
591
592
593/**
594 * Allocate renderbuffer storage.  We don't actually allocate any storage
595 * since we're using a user-provided buffer.
596 * Just set up all the gl_renderbuffer methods.
597 */
598static GLboolean
599osmesa_renderbuffer_storage(GLcontext *ctx, struct gl_renderbuffer *rb,
600                            GLenum internalFormat, GLuint width, GLuint height)
601{
602   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
603
604   /* Note: we can ignoring internalFormat for "window-system" renderbuffers */
605   if (osmesa->format == OSMESA_RGBA) {
606      rb->GetRow = get_row_RGBA;
607      rb->GetValues = get_values_RGBA;
608      rb->PutRow = put_row_RGBA;
609      rb->PutRowRGB = put_row_rgb_RGBA;
610      rb->PutMonoRow = put_mono_row_RGBA;
611      rb->PutValues = put_values_RGBA;
612      rb->PutMonoValues = put_mono_values_RGBA;
613      rb->RedBits =
614      rb->GreenBits =
615      rb->BlueBits =
616      rb->AlphaBits = 8 * sizeof(GLchan);
617   }
618   else if (osmesa->format == OSMESA_BGRA) {
619      rb->GetRow = get_row_BGRA;
620      rb->GetValues = get_values_BGRA;
621      rb->PutRow = put_row_BGRA;
622      rb->PutRowRGB = put_row_rgb_BGRA;
623      rb->PutMonoRow = put_mono_row_BGRA;
624      rb->PutValues = put_values_BGRA;
625      rb->PutMonoValues = put_mono_values_BGRA;
626      rb->RedBits =
627      rb->GreenBits =
628      rb->BlueBits =
629      rb->AlphaBits = 8 * sizeof(GLchan);
630   }
631   else if (osmesa->format == OSMESA_ARGB) {
632      rb->GetRow = get_row_ARGB;
633      rb->GetValues = get_values_ARGB;
634      rb->PutRow = put_row_ARGB;
635      rb->PutRowRGB = put_row_rgb_ARGB;
636      rb->PutMonoRow = put_mono_row_ARGB;
637      rb->PutValues = put_values_ARGB;
638      rb->PutMonoValues = put_mono_values_ARGB;
639      rb->RedBits =
640      rb->GreenBits =
641      rb->BlueBits =
642      rb->AlphaBits = 8 * sizeof(GLchan);
643   }
644   else if (osmesa->format == OSMESA_RGB) {
645      rb->GetRow = get_row_RGB;
646      rb->GetValues = get_values_RGB;
647      rb->PutRow = put_row_RGB;
648      rb->PutRowRGB = put_row_rgb_RGB;
649      rb->PutMonoRow = put_mono_row_RGB;
650      rb->PutValues = put_values_RGB;
651      rb->PutMonoValues = put_mono_values_RGB;
652      rb->RedBits =
653      rb->GreenBits =
654      rb->BlueBits = 8 * sizeof(GLchan);
655   }
656   else if (osmesa->format == OSMESA_BGR) {
657      rb->GetRow = get_row_BGR;
658      rb->GetValues = get_values_BGR;
659      rb->PutRow = put_row_BGR;
660      rb->PutRowRGB = put_row_rgb_BGR;
661      rb->PutMonoRow = put_mono_row_BGR;
662      rb->PutValues = put_values_BGR;
663      rb->PutMonoValues = put_mono_values_BGR;
664      rb->RedBits =
665      rb->GreenBits =
666      rb->BlueBits = 8 * sizeof(GLchan);
667   }
668#if CHAN_TYPE == GL_UNSIGNED_BYTE
669   else if (osmesa->format == OSMESA_RGB_565) {
670      rb->GetRow = get_row_RGB_565;
671      rb->GetValues = get_values_RGB_565;
672      rb->PutRow = put_row_RGB_565;
673      rb->PutRowRGB = put_row_rgb_RGB_565;
674      rb->PutMonoRow = put_mono_row_RGB_565;
675      rb->PutValues = put_values_RGB_565;
676      rb->PutMonoValues = put_mono_values_RGB_565;
677      rb->RedBits = 5;
678      rb->GreenBits = 6;
679      rb->BlueBits = 5;
680   }
681#endif
682   else if (osmesa->format == OSMESA_COLOR_INDEX) {
683      rb->GetRow = get_row_CI;
684      rb->GetValues = get_values_CI;
685      rb->PutRow = put_row_CI;
686      rb->PutMonoRow = put_mono_row_CI;
687      rb->PutValues = put_values_CI;
688      rb->PutMonoValues = put_mono_values_CI;
689      rb->IndexBits = 8;
690   }
691   else {
692      _mesa_problem(ctx, "bad pixel format in osmesa renderbuffer_storage");
693   }
694
695   rb->Width = width;
696   rb->Height = height;
697
698   return GL_TRUE;
699}
700
701
702/**
703 * Allocate a new renderbuffer tpo describe the user-provided color buffer.
704 */
705static struct gl_renderbuffer *
706new_osmesa_renderbuffer(GLenum format)
707{
708   struct gl_renderbuffer *rb = CALLOC_STRUCT(gl_renderbuffer);
709   if (rb) {
710      const GLuint name = 0;
711      _mesa_init_renderbuffer(rb, name);
712
713      rb->Delete = osmesa_delete_renderbuffer;
714      rb->AllocStorage = osmesa_renderbuffer_storage;
715
716      if (format == OSMESA_COLOR_INDEX) {
717         rb->_BaseFormat = GL_COLOR_INDEX;
718         rb->InternalFormat = GL_COLOR_INDEX;
719         rb->DataType = GL_UNSIGNED_BYTE;
720      }
721      else {
722         rb->_BaseFormat = GL_RGBA;
723         rb->InternalFormat = GL_RGBA;
724         rb->DataType = CHAN_TYPE;
725      }
726   }
727   return rb;
728}
729
730
731
732/**********************************************************************/
733/*****                    Public Functions                        *****/
734/**********************************************************************/
735
736
737/*
738 * Create an Off-Screen Mesa rendering context.  The only attribute needed is
739 * an RGBA vs Color-Index mode flag.
740 *
741 * Input:  format - either GL_RGBA or GL_COLOR_INDEX
742 *         sharelist - specifies another OSMesaContext with which to share
743 *                     display lists.  NULL indicates no sharing.
744 * Return:  an OSMesaContext or 0 if error
745 */
746GLAPI OSMesaContext GLAPIENTRY
747OSMesaCreateContext( GLenum format, OSMesaContext sharelist )
748{
749   const GLint accumBits = (format == OSMESA_COLOR_INDEX) ? 0 : 16;
750   return OSMesaCreateContextExt(format, DEFAULT_SOFTWARE_DEPTH_BITS,
751                                 8, accumBits, sharelist);
752}
753
754
755
756/*
757 * New in Mesa 3.5
758 *
759 * Create context and specify size of ancillary buffers.
760 */
761GLAPI OSMesaContext GLAPIENTRY
762OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
763                        GLint accumBits, OSMesaContext sharelist )
764{
765   OSMesaContext osmesa;
766   struct dd_function_table functions;
767   GLint rind, gind, bind, aind;
768   GLint indexBits = 0, redBits = 0, greenBits = 0, blueBits = 0, alphaBits =0;
769   GLboolean rgbmode;
770
771   rind = gind = bind = aind = 0;
772   if (format==OSMESA_COLOR_INDEX) {
773      indexBits = 8;
774      rgbmode = GL_FALSE;
775   }
776   else if (format==OSMESA_RGBA) {
777      indexBits = 0;
778      redBits = CHAN_BITS;
779      greenBits = CHAN_BITS;
780      blueBits = CHAN_BITS;
781      alphaBits = CHAN_BITS;
782      rind = 0;
783      gind = 1;
784      bind = 2;
785      aind = 3;
786      rgbmode = GL_TRUE;
787   }
788   else if (format==OSMESA_BGRA) {
789      indexBits = 0;
790      redBits = CHAN_BITS;
791      greenBits = CHAN_BITS;
792      blueBits = CHAN_BITS;
793      alphaBits = CHAN_BITS;
794      bind = 0;
795      gind = 1;
796      rind = 2;
797      aind = 3;
798      rgbmode = GL_TRUE;
799   }
800   else if (format==OSMESA_ARGB) {
801      indexBits = 0;
802      redBits = CHAN_BITS;
803      greenBits = CHAN_BITS;
804      blueBits = CHAN_BITS;
805      alphaBits = CHAN_BITS;
806      aind = 0;
807      rind = 1;
808      gind = 2;
809      bind = 3;
810      rgbmode = GL_TRUE;
811   }
812   else if (format==OSMESA_RGB) {
813      indexBits = 0;
814      redBits = CHAN_BITS;
815      greenBits = CHAN_BITS;
816      blueBits = CHAN_BITS;
817      alphaBits = 0;
818      rind = 0;
819      gind = 1;
820      bind = 2;
821      rgbmode = GL_TRUE;
822   }
823   else if (format==OSMESA_BGR) {
824      indexBits = 0;
825      redBits = CHAN_BITS;
826      greenBits = CHAN_BITS;
827      blueBits = CHAN_BITS;
828      alphaBits = 0;
829      rind = 2;
830      gind = 1;
831      bind = 0;
832      rgbmode = GL_TRUE;
833   }
834#if CHAN_TYPE == GL_UNSIGNED_BYTE
835   else if (format==OSMESA_RGB_565) {
836      indexBits = 0;
837      redBits = 5;
838      greenBits = 6;
839      blueBits = 5;
840      alphaBits = 0;
841      rind = 0; /* not used */
842      gind = 0;
843      bind = 0;
844      rgbmode = GL_TRUE;
845   }
846#endif
847   else {
848      return NULL;
849   }
850
851   osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context);
852   if (osmesa) {
853      osmesa->gl_visual = _mesa_create_visual( rgbmode,
854                                               GL_FALSE,    /* double buffer */
855                                               GL_FALSE,    /* stereo */
856                                               redBits,
857                                               greenBits,
858                                               blueBits,
859                                               alphaBits,
860                                               indexBits,
861                                               depthBits,
862                                               stencilBits,
863                                               accumBits,
864                                               accumBits,
865                                               accumBits,
866                                               alphaBits ? accumBits : 0,
867                                               1            /* num samples */
868                                               );
869      if (!osmesa->gl_visual) {
870         FREE(osmesa);
871         return NULL;
872      }
873
874      /* Initialize device driver function table */
875      _mesa_init_driver_functions(&functions);
876      /* override with our functions */
877      functions.GetString = get_string;
878      functions.UpdateState = osmesa_update_state;
879      functions.GetBufferSize = get_buffer_size;
880
881      if (!_mesa_initialize_context(&osmesa->mesa,
882                                    osmesa->gl_visual,
883                                    sharelist ? &sharelist->mesa
884                                              : (GLcontext *) NULL,
885                                    &functions, (void *) osmesa)) {
886         _mesa_destroy_visual( osmesa->gl_visual );
887         FREE(osmesa);
888         return NULL;
889      }
890
891      _mesa_enable_sw_extensions(&(osmesa->mesa));
892      _mesa_enable_1_3_extensions(&(osmesa->mesa));
893      _mesa_enable_1_4_extensions(&(osmesa->mesa));
894      _mesa_enable_1_5_extensions(&(osmesa->mesa));
895
896      osmesa->gl_buffer = _mesa_create_framebuffer(osmesa->gl_visual);
897      if (!osmesa->gl_buffer) {
898         _mesa_destroy_visual( osmesa->gl_visual );
899         _mesa_free_context_data( &osmesa->mesa );
900         FREE(osmesa);
901         return NULL;
902      }
903
904      /* create front color buffer in user-provided memory (no back buffer) */
905      _mesa_add_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT,
906                             new_osmesa_renderbuffer(format));
907      _mesa_add_soft_renderbuffers(osmesa->gl_buffer,
908                                   GL_FALSE, /* color */
909                                   osmesa->gl_visual->haveDepthBuffer,
910                                   osmesa->gl_visual->haveStencilBuffer,
911                                   osmesa->gl_visual->haveAccumBuffer,
912                                   GL_FALSE, /* alpha */
913                                   GL_FALSE /* aux */ );
914
915      osmesa->format = format;
916      osmesa->buffer = NULL;
917      osmesa->width = 0;
918      osmesa->height = 0;
919      osmesa->userRowLength = 0;
920      osmesa->rowlength = 0;
921      osmesa->yup = GL_TRUE;
922      osmesa->rInd = rind;
923      osmesa->gInd = gind;
924      osmesa->bInd = bind;
925      osmesa->aInd = aind;
926
927      /* Initialize the software rasterizer and helper modules. */
928      {
929	 GLcontext *ctx = &osmesa->mesa;
930         SWcontext *swrast;
931         TNLcontext *tnl;
932
933	 if (!_swrast_CreateContext( ctx ) ||
934             !_ac_CreateContext( ctx ) ||
935             !_tnl_CreateContext( ctx ) ||
936             !_swsetup_CreateContext( ctx )) {
937            _mesa_destroy_visual(osmesa->gl_visual);
938            _mesa_free_context_data(ctx);
939            _mesa_free(osmesa);
940            return NULL;
941         }
942
943	 _swsetup_Wakeup( ctx );
944
945         /* use default TCL pipeline */
946         tnl = TNL_CONTEXT(ctx);
947         tnl->Driver.RunPipeline = _tnl_run_pipeline;
948
949         /* Extend the software rasterizer with our optimized line and triangle
950          * drawing functions.
951          */
952         swrast = SWRAST_CONTEXT( ctx );
953         swrast->choose_line = osmesa_choose_line;
954         swrast->choose_triangle = osmesa_choose_triangle;
955      }
956   }
957   return osmesa;
958}
959
960
961/*
962 * Destroy an Off-Screen Mesa rendering context.
963 *
964 * Input:  ctx - the context to destroy
965 */
966GLAPI void GLAPIENTRY
967OSMesaDestroyContext( OSMesaContext ctx )
968{
969   if (ctx) {
970      _swsetup_DestroyContext( &ctx->mesa );
971      _tnl_DestroyContext( &ctx->mesa );
972      _ac_DestroyContext( &ctx->mesa );
973      _swrast_DestroyContext( &ctx->mesa );
974
975      _mesa_destroy_visual( ctx->gl_visual );
976      _mesa_destroy_framebuffer( ctx->gl_buffer );
977      _mesa_free_context_data( &ctx->mesa );
978      FREE( ctx );
979   }
980}
981
982
983/*
984 * Recompute the values of the context's rowaddr array.
985 */
986static void
987compute_row_addresses( OSMesaContext ctx )
988{
989   GLint bytesPerPixel, bytesPerRow, i;
990   GLubyte *origin = (GLubyte *) ctx->buffer;
991
992   if (ctx->format == OSMESA_COLOR_INDEX) {
993      /* CI mode */
994      bytesPerPixel = 1 * sizeof(GLubyte);
995   }
996   else if ((ctx->format == OSMESA_RGB) || (ctx->format == OSMESA_BGR)) {
997      /* RGB mode */
998      bytesPerPixel = 3 * sizeof(GLchan);
999   }
1000   else if (ctx->format == OSMESA_RGB_565) {
1001      /* 5/6/5 RGB pixel in 16 bits */
1002      bytesPerPixel = 2;
1003   }
1004   else {
1005      /* RGBA mode */
1006      bytesPerPixel = 4 * sizeof(GLchan);
1007   }
1008
1009   bytesPerRow = ctx->rowlength * bytesPerPixel;
1010
1011   if (ctx->yup) {
1012      /* Y=0 is bottom line of window */
1013      for (i = 0; i < MAX_HEIGHT; i++) {
1014         ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + i * bytesPerRow);
1015      }
1016   }
1017   else {
1018      /* Y=0 is top line of window */
1019      for (i = 0; i < MAX_HEIGHT; i++) {
1020         GLint j = ctx->height - i - 1;
1021         ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + j * bytesPerRow);
1022      }
1023   }
1024}
1025
1026
1027/*
1028 * Bind an OSMesaContext to an image buffer.  The image buffer is just a
1029 * block of memory which the client provides.  Its size must be at least
1030 * as large as width*height*sizeof(type).  Its address should be a multiple
1031 * of 4 if using RGBA mode.
1032 *
1033 * Image data is stored in the order of glDrawPixels:  row-major order
1034 * with the lower-left image pixel stored in the first array position
1035 * (ie. bottom-to-top).
1036 *
1037 * If the context's viewport hasn't been initialized yet, it will now be
1038 * initialized to (0,0,width,height).
1039 *
1040 * Input:  ctx - the rendering context
1041 *         buffer - the image buffer memory
1042 *         type - data type for pixel components
1043 *            Normally, only GL_UNSIGNED_BYTE and GL_UNSIGNED_SHORT_5_6_5
1044 *            are supported.  But if Mesa's been compiled with CHAN_BITS==16
1045 *            then type must be GL_UNSIGNED_SHORT.  And if Mesa's been build
1046 *            with CHAN_BITS==32 then type must be GL_FLOAT.
1047 *         width, height - size of image buffer in pixels, at least 1
1048 * Return:  GL_TRUE if success, GL_FALSE if error because of invalid ctx,
1049 *          invalid buffer address, invalid type, width<1, height<1,
1050 *          width>internal limit or height>internal limit.
1051 */
1052GLAPI GLboolean GLAPIENTRY
1053OSMesaMakeCurrent( OSMesaContext ctx, void *buffer, GLenum type,
1054                   GLsizei width, GLsizei height )
1055{
1056   if (!ctx || !buffer ||
1057       width < 1 || height < 1 ||
1058       width > MAX_WIDTH || height > MAX_HEIGHT) {
1059      return GL_FALSE;
1060   }
1061
1062   if (ctx->format == OSMESA_RGB_565) {
1063      if (type != GL_UNSIGNED_SHORT_5_6_5)
1064         return GL_FALSE;
1065   }
1066   else if (type != CHAN_TYPE) {
1067      return GL_FALSE;
1068   }
1069
1070   /* Need to set these before calling _mesa_make_current() since the first
1071    * time the context is bound, _mesa_make_current() will call our
1072    * get_buffer_size() function to initialize the viewport.  These are the
1073    * values returned by get_buffer_size():
1074    */
1075   ctx->buffer = buffer;
1076   ctx->width = width;
1077   ctx->height = height;
1078
1079   osmesa_update_state( &ctx->mesa, 0 );
1080
1081   /* Call this periodically to detect when the user has begun using
1082    * GL rendering from multiple threads.
1083    */
1084   _glapi_check_multithread();
1085
1086   _mesa_make_current( &ctx->mesa, ctx->gl_buffer, ctx->gl_buffer );
1087
1088   if (ctx->userRowLength)
1089      ctx->rowlength = ctx->userRowLength;
1090   else
1091      ctx->rowlength = width;
1092
1093   compute_row_addresses( ctx );
1094
1095   /* this will make ensure we recognize the new buffer size */
1096   _mesa_resize_framebuffer(&ctx->mesa, ctx->gl_buffer, width, height);
1097
1098   return GL_TRUE;
1099}
1100
1101
1102
1103GLAPI OSMesaContext GLAPIENTRY
1104OSMesaGetCurrentContext( void )
1105{
1106   GLcontext *ctx = _mesa_get_current_context();
1107   if (ctx)
1108      return (OSMesaContext) ctx;
1109   else
1110      return NULL;
1111}
1112
1113
1114
1115GLAPI void GLAPIENTRY
1116OSMesaPixelStore( GLint pname, GLint value )
1117{
1118   OSMesaContext osmesa = OSMesaGetCurrentContext();
1119
1120   switch (pname) {
1121      case OSMESA_ROW_LENGTH:
1122         if (value<0) {
1123            _mesa_error( &osmesa->mesa, GL_INVALID_VALUE,
1124                      "OSMesaPixelStore(value)" );
1125            return;
1126         }
1127         osmesa->userRowLength = value;
1128         osmesa->rowlength = value ? value : osmesa->width;
1129         break;
1130      case OSMESA_Y_UP:
1131         osmesa->yup = value ? GL_TRUE : GL_FALSE;
1132         break;
1133      default:
1134         _mesa_error( &osmesa->mesa, GL_INVALID_ENUM, "OSMesaPixelStore(pname)" );
1135         return;
1136   }
1137
1138   compute_row_addresses( osmesa );
1139}
1140
1141
1142GLAPI void GLAPIENTRY
1143OSMesaGetIntegerv( GLint pname, GLint *value )
1144{
1145   OSMesaContext osmesa = OSMesaGetCurrentContext();
1146
1147   switch (pname) {
1148      case OSMESA_WIDTH:
1149         *value = osmesa->width;
1150         return;
1151      case OSMESA_HEIGHT:
1152         *value = osmesa->height;
1153         return;
1154      case OSMESA_FORMAT:
1155         *value = osmesa->format;
1156         return;
1157      case OSMESA_TYPE:
1158         *value = CHAN_TYPE;
1159         return;
1160      case OSMESA_ROW_LENGTH:
1161         *value = osmesa->userRowLength;
1162         return;
1163      case OSMESA_Y_UP:
1164         *value = osmesa->yup;
1165         return;
1166      case OSMESA_MAX_WIDTH:
1167         *value = MAX_WIDTH;
1168         return;
1169      case OSMESA_MAX_HEIGHT:
1170         *value = MAX_HEIGHT;
1171         return;
1172      default:
1173         _mesa_error(&osmesa->mesa, GL_INVALID_ENUM, "OSMesaGetIntergerv(pname)");
1174         return;
1175   }
1176}
1177
1178/*
1179 * Return the depth buffer associated with an OSMesa context.
1180 * Input:  c - the OSMesa context
1181 * Output:  width, height - size of buffer in pixels
1182 *          bytesPerValue - bytes per depth value (2 or 4)
1183 *          buffer - pointer to depth buffer values
1184 * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
1185 */
1186GLAPI GLboolean GLAPIENTRY
1187OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height,
1188                      GLint *bytesPerValue, void **buffer )
1189{
1190   struct gl_renderbuffer *rb = NULL;
1191
1192   if (c->gl_buffer)
1193      rb = c->gl_buffer->Attachment[BUFFER_DEPTH].Renderbuffer;
1194
1195   if (!rb || !rb->Data) {
1196      /*if ((!c->gl_buffer) || (!c->gl_buffer->DepthBuffer)) {*/
1197      *width = 0;
1198      *height = 0;
1199      *bytesPerValue = 0;
1200      *buffer = 0;
1201      return GL_FALSE;
1202   }
1203   else {
1204      *width = c->gl_buffer->Width;
1205      *height = c->gl_buffer->Height;
1206      if (c->gl_visual->depthBits <= 16)
1207         *bytesPerValue = sizeof(GLushort);
1208      else
1209         *bytesPerValue = sizeof(GLuint);
1210      *buffer = rb->Data;
1211      return GL_TRUE;
1212   }
1213}
1214
1215/*
1216 * Return the color buffer associated with an OSMesa context.
1217 * Input:  c - the OSMesa context
1218 * Output:  width, height - size of buffer in pixels
1219 *          format - the pixel format (OSMESA_FORMAT)
1220 *          buffer - pointer to color buffer values
1221 * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
1222 */
1223GLAPI GLboolean GLAPIENTRY
1224OSMesaGetColorBuffer( OSMesaContext c, GLint *width,
1225                      GLint *height, GLint *format, void **buffer )
1226{
1227   if (!c->buffer) {
1228      *width = 0;
1229      *height = 0;
1230      *format = 0;
1231      *buffer = 0;
1232      return GL_FALSE;
1233   }
1234   else {
1235      *width = c->width;
1236      *height = c->height;
1237      *format = c->format;
1238      *buffer = c->buffer;
1239      return GL_TRUE;
1240   }
1241}
1242
1243
1244struct name_function
1245{
1246   const char *Name;
1247   OSMESAproc Function;
1248};
1249
1250static struct name_function functions[] = {
1251   { "OSMesaCreateContext", (OSMESAproc) OSMesaCreateContext },
1252   { "OSMesaCreateContextExt", (OSMESAproc) OSMesaCreateContextExt },
1253   { "OSMesaDestroyContext", (OSMESAproc) OSMesaDestroyContext },
1254   { "OSMesaMakeCurrent", (OSMESAproc) OSMesaMakeCurrent },
1255   { "OSMesaGetCurrentContext", (OSMESAproc) OSMesaGetCurrentContext },
1256   { "OSMesaPixelsStore", (OSMESAproc) OSMesaPixelStore },
1257   { "OSMesaGetIntegerv", (OSMESAproc) OSMesaGetIntegerv },
1258   { "OSMesaGetDepthBuffer", (OSMESAproc) OSMesaGetDepthBuffer },
1259   { "OSMesaGetColorBuffer", (OSMESAproc) OSMesaGetColorBuffer },
1260   { "OSMesaGetProcAddress", (OSMESAproc) OSMesaGetProcAddress },
1261   { NULL, NULL }
1262};
1263
1264
1265GLAPI OSMESAproc GLAPIENTRY
1266OSMesaGetProcAddress( const char *funcName )
1267{
1268   int i;
1269   for (i = 0; functions[i].Name; i++) {
1270      if (_mesa_strcmp(functions[i].Name, funcName) == 0)
1271         return functions[i].Function;
1272   }
1273   return _glapi_get_proc_address(funcName);
1274}
1275
1276
1277GLAPI void GLAPIENTRY
1278OSMesaColorClamp(GLboolean enable)
1279{
1280   OSMesaContext osmesa = OSMesaGetCurrentContext();
1281
1282   if (enable == GL_TRUE) {
1283      osmesa->mesa.Color.ClampFragmentColor = GL_TRUE;
1284   }
1285   else {
1286      osmesa->mesa.Color.ClampFragmentColor = GL_FIXED_ONLY_ARB;
1287   }
1288}
1289
1290
1291