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