osmesa.c revision 894844a8d956a0ee5f95836331dc318f49fdb845
1/*
2 * Mesa 3-D graphics library
3 * Version:  6.1
4 *
5 * Copyright (C) 1999-2004  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 "buffers.h"
39#include "bufferobj.h"
40#include "context.h"
41#include "colormac.h"
42#include "depth.h"
43#include "extensions.h"
44#include "imports.h"
45#include "macros.h"
46#include "matrix.h"
47#include "mtypes.h"
48#include "texformat.h"
49#include "texobj.h"
50#include "teximage.h"
51#include "texstore.h"
52#include "array_cache/acache.h"
53#include "swrast/swrast.h"
54#include "swrast_setup/swrast_setup.h"
55#include "swrast/s_context.h"
56#include "swrast/s_depth.h"
57#include "swrast/s_lines.h"
58#include "swrast/s_triangle.h"
59#include "tnl/tnl.h"
60#include "tnl/t_context.h"
61#include "tnl/t_pipeline.h"
62#include "drivers/common/driverfuncs.h"
63
64
65
66/*
67 * This is the OS/Mesa context struct.
68 * Notice how it includes a GLcontext.  By doing this we're mimicking
69 * C++ inheritance/derivation.
70 * Later, we can cast a GLcontext pointer into an OSMesaContext pointer
71 * or vice versa.
72 */
73struct osmesa_context {
74   GLcontext mesa;		/* The core GL/Mesa context */
75   GLvisual *gl_visual;		/* Describes the buffers */
76   GLframebuffer *gl_buffer;	/* Depth, stencil, accum, etc buffers */
77   GLenum format;		/* either GL_RGBA or GL_COLOR_INDEX */
78   void *buffer;		/* the image buffer */
79   GLint width, height;		/* size of image buffer */
80   GLint rowlength;		/* number of pixels per row */
81   GLint userRowLength;		/* user-specified number of pixels per row */
82   GLint rshift, gshift;	/* bit shifts for RGBA formats */
83   GLint bshift, ashift;
84   GLint rInd, gInd, bInd, aInd;/* index offsets for RGBA formats */
85   GLchan *rowaddr[MAX_HEIGHT];	/* address of first pixel in each image row */
86   GLboolean yup;		/* TRUE  -> Y increases upward */
87				/* FALSE -> Y increases downward */
88};
89
90
91/* Just cast, since we're using structure containment */
92#define OSMESA_CONTEXT(ctx)  ((OSMesaContext) (ctx->DriverCtx))
93
94
95
96/**********************************************************************/
97/*** Private Device Driver Functions                                ***/
98/**********************************************************************/
99
100
101static const GLubyte *
102get_string( GLcontext *ctx, GLenum name )
103{
104   (void) ctx;
105   switch (name) {
106      case GL_RENDERER:
107#if CHAN_BITS == 32
108         return (const GLubyte *) "Mesa OffScreen32";
109#elif CHAN_BITS == 16
110         return (const GLubyte *) "Mesa OffScreen16";
111#else
112         return (const GLubyte *) "Mesa OffScreen";
113#endif
114      default:
115         return NULL;
116   }
117}
118
119
120static void
121osmesa_update_state( GLcontext *ctx, GLuint new_state )
122{
123   /* easy - just propogate */
124   _swrast_InvalidateState( ctx, new_state );
125   _swsetup_InvalidateState( ctx, new_state );
126   _ac_InvalidateState( ctx, new_state );
127   _tnl_InvalidateState( ctx, new_state );
128}
129
130
131static void
132set_buffer( GLcontext *ctx, GLframebuffer *buffer, GLuint bufferBit )
133{
134   /* separate read buffer not supported */
135   ASSERT(buffer == ctx->DrawBuffer);
136   ASSERT(bufferBit == DD_FRONT_LEFT_BIT);
137}
138
139
140static void
141get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height )
142{
143   /* don't use GET_CURRENT_CONTEXT(ctx) here - it's a problem on Windows */
144   GLcontext *ctx = (GLcontext *) _glapi_get_context();
145   (void) buffer;
146   if (ctx) {
147      OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
148      *width = osmesa->width;
149      *height = osmesa->height;
150   }
151}
152
153
154static void
155clear( GLcontext *ctx, GLbitfield mask, GLboolean all,
156       GLint x, GLint y, GLint width, GLint height )
157{
158   OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
159   const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask;
160
161   /* sanity check - we only have a front-left buffer */
162   ASSERT((mask & (DD_FRONT_RIGHT_BIT |
163                   DD_BACK_LEFT_BIT |
164                   DD_BACK_RIGHT_BIT)) == 0);
165
166   /* use optimized clear for common cases (clear whole buffer to black) */
167   if (mask & DD_FRONT_LEFT_BIT) {
168      if (osmesa->format == OSMESA_COLOR_INDEX) {
169         if (ctx->Color.ClearIndex == 0 &&
170             ctx->Color.IndexMask == (GLuint) ~0 &&
171             osmesa->rowlength == osmesa->width &&
172             all) {
173            /* clear whole buffer to zeros */
174            _mesa_bzero(osmesa->buffer,
175                        osmesa->width * osmesa->height * sizeof(GLchan));
176            mask &= ~DD_FRONT_LEFT_BIT;
177         }
178      }
179      else {
180         /* RGB[A] format */
181         if (*colorMask == 0xffffffff &&
182             ctx->Color.ClearColor[0] == 0.0F &&
183             ctx->Color.ClearColor[1] == 0.0F &&
184             ctx->Color.ClearColor[2] == 0.0F &&
185             ctx->Color.ClearColor[3] == 0.0F &&
186             osmesa->rowlength == osmesa->width &&
187             all) {
188            GLint bytesPerPixel;
189            /* clear whole buffer to black */
190            if (osmesa->format == OSMESA_RGBA ||
191                osmesa->format == OSMESA_BGRA ||
192                osmesa->format == OSMESA_ARGB)
193               bytesPerPixel = 4 * sizeof(GLchan);
194            else if (osmesa->format == OSMESA_RGB ||
195                     osmesa->format == OSMESA_BGR)
196               bytesPerPixel = 3 * sizeof(GLchan);
197            else if (osmesa->format == OSMESA_RGB_565)
198               bytesPerPixel = sizeof(GLushort);
199            else {
200               _mesa_problem(ctx, "bad pixel format in osmesa_clear()");
201               return;
202            }
203            _mesa_bzero(osmesa->buffer,
204                        bytesPerPixel * osmesa->width * osmesa->height);
205            mask &= ~DD_FRONT_LEFT_BIT;
206         }
207      }
208   }
209
210   if (mask) {
211      /* software fallback (spans) for everything else. */
212      _swrast_Clear(ctx, mask, all, x, y, width, height);
213   }
214}
215
216
217/**********************************************************************/
218/*****        Read/write spans/arrays of pixels                   *****/
219/**********************************************************************/
220
221
222/* RGBA */
223#define NAME(PREFIX) PREFIX##_RGBA
224#define SPAN_VARS \
225   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
226#define INIT_PIXEL_PTR(P, X, Y) \
227   GLchan *P = osmesa->rowaddr[Y] + 4 * (X)
228#define INC_PIXEL_PTR(P) P += 4
229#if CHAN_TYPE == GL_FLOAT
230#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
231   P[0] = MAX2((R), 0.0F); \
232   P[1] = MAX2((G), 0.0F); \
233   P[2] = MAX2((B), 0.0F); \
234   P[3] = CHAN_MAXF
235#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
236   P[0] = MAX2((R), 0.0F); \
237   P[1] = MAX2((G), 0.0F); \
238   P[2] = MAX2((B), 0.0F); \
239   P[3] = CLAMP((A), 0.0F, CHAN_MAXF)
240#else
241#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
242   P[0] = R;  P[1] = G;  P[2] = B;  P[3] = CHAN_MAX
243#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
244   P[0] = R;  P[1] = G;  P[2] = B;  P[3] = A
245#endif
246#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
247   R = P[0];  G = P[1];  B = P[2];  A = P[3]
248#include "swrast/s_spantemp.h"
249
250/* BGRA */
251#define NAME(PREFIX) PREFIX##_BGRA
252#define SPAN_VARS \
253   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
254#define INIT_PIXEL_PTR(P, X, Y) \
255   GLchan *P = osmesa->rowaddr[Y] + 4 * (X)
256#define INC_PIXEL_PTR(P) P += 4
257#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
258   P[2] = R;  P[1] = G;  P[0] = B;  P[3] = CHAN_MAX
259#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
260   P[2] = R;  P[1] = G;  P[0] = B;  P[3] = A
261#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
262   R = P[2];  G = P[1];  B = P[0];  A = P[3]
263#include "swrast/s_spantemp.h"
264
265/* ARGB */
266#define NAME(PREFIX) PREFIX##_ARGB
267#define SPAN_VARS \
268   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
269#define INIT_PIXEL_PTR(P, X, Y) \
270   GLchan *P = osmesa->rowaddr[Y] + 4 * (X)
271#define INC_PIXEL_PTR(P) P += 4
272#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
273   P[1] = R;  P[2] = G;  P[3] = B;  P[0] = CHAN_MAX
274#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
275   P[1] = R;  P[2] = G;  P[3] = B;  P[0] = A
276#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
277   R = P[1];  G = P[2];  B = P[3];  A = P[0]
278#include "swrast/s_spantemp.h"
279
280/* RGB */
281#define NAME(PREFIX) PREFIX##_RGB
282#define SPAN_VARS \
283   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
284#define INIT_PIXEL_PTR(P, X, Y) \
285   GLchan *P = osmesa->rowaddr[Y] + 3 * (X)
286#define INC_PIXEL_PTR(P) P += 3
287#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
288   P[0] = R;  P[1] = G;  P[2] = B
289#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
290   P[0] = R;  P[1] = G;  P[2] = B
291#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
292   R = P[0];  G = P[1];  B = P[2];  A = CHAN_MAX
293#include "swrast/s_spantemp.h"
294
295/* BGR */
296#define NAME(PREFIX) PREFIX##_BGR
297#define SPAN_VARS \
298   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
299#define INIT_PIXEL_PTR(P, X, Y) \
300   GLchan *P = osmesa->rowaddr[Y] + 3 * (X)
301#define INC_PIXEL_PTR(P) P += 3
302#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
303   P[0] = B;  P[1] = G;  P[2] = R
304#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
305   P[0] = B;  P[1] = G;  P[2] = R
306#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
307   B = P[0];  G = P[1];  R = P[2];  A = CHAN_MAX
308#include "swrast/s_spantemp.h"
309
310/* 16-bit BGR */
311#if CHAN_TYPE == GL_UNSIGNED_BYTE
312#define NAME(PREFIX) PREFIX##_RGB_565
313#define SPAN_VARS \
314   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
315#define INIT_PIXEL_PTR(P, X, Y) \
316   GLushort *P = (GLushort *) osmesa->rowaddr[Y] + (X)
317#define INC_PIXEL_PTR(P) P += 1
318#define STORE_RGB_PIXEL(P, X, Y, R, G, B) \
319   *P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) )
320#define STORE_RGBA_PIXEL(P, X, Y, R, G, B, A) \
321   *P = ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) )
322#define FETCH_RGBA_PIXEL(R, G, B, A, P) \
323   R = ( (((*P) >> 8) & 0xf8) | (((*P) >> 11) & 0x7) ); \
324   G = ( (((*P) >> 3) & 0xfc) | (((*P) >>  5) & 0x3) ); \
325   B = ( (((*P) << 3) & 0xf8) | (((*P)      ) & 0x7) ); \
326   A = CHAN_MAX
327#include "swrast/s_spantemp.h"
328#endif
329
330/* color index */
331#define NAME(PREFIX) PREFIX##_CI
332#define SPAN_VARS \
333   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
334#define INIT_PIXEL_PTR(P, X, Y) \
335   GLchan *P = osmesa->rowaddr[Y] + (X)
336#define INC_PIXEL_PTR(P) P += 1
337#define STORE_CI_PIXEL(P, CI) \
338   P[0] = CI
339#define FETCH_CI_PIXEL(CI, P) \
340   CI = P[0]
341#include "swrast/s_spantemp.h"
342
343
344/**********************************************************************/
345/*****                   Optimized line rendering                 *****/
346/**********************************************************************/
347
348
349#if CHAN_TYPE == GL_FLOAT
350#define PACK_RGBA(DST, R, G, B, A)	\
351do {					\
352   (DST)[0] = MAX2( R, 0.0F );		\
353   (DST)[1] = MAX2( G, 0.0F );		\
354   (DST)[2] = MAX2( B, 0.0F );		\
355   (DST)[3] = CLAMP(A, 0.0F, CHAN_MAXF);\
356} while (0)
357#else
358#define PACK_RGBA(DST, R, G, B, A)	\
359do {					\
360   (DST)[osmesa->rInd] = R;		\
361   (DST)[osmesa->gInd] = G;		\
362   (DST)[osmesa->bInd] = B;		\
363   (DST)[osmesa->aInd] = A;		\
364} while (0)
365#endif
366
367#define PACK_RGB(DST, R, G, B)  \
368do {				\
369   (DST)[0] = R;		\
370   (DST)[1] = G;		\
371   (DST)[2] = B;		\
372} while (0)
373
374#define PACK_BGR(DST, R, G, B)  \
375do {				\
376   (DST)[0] = B;		\
377   (DST)[1] = G;		\
378   (DST)[2] = R;		\
379} while (0)
380
381#define PACK_RGB_565(DST, R, G, B)					\
382do {									\
383   (DST) = (((int) (R) << 8) & 0xf800) | (((int) (G) << 3) & 0x7e0) | ((int) (B) >> 3);\
384} while (0)
385
386#define UNPACK_RED(P)      ( (P)[osmesa->rInd] )
387#define UNPACK_GREEN(P)    ( (P)[osmesa->gInd] )
388#define UNPACK_BLUE(P)     ( (P)[osmesa->bInd] )
389#define UNPACK_ALPHA(P)    ( (P)[osmesa->aInd] )
390
391#define PIXELADDR1(X,Y)  (osmesa->rowaddr[Y] + (X))
392#define PIXELADDR2(X,Y)  (osmesa->rowaddr[Y] + 2 * (X))
393#define PIXELADDR3(X,Y)  (osmesa->rowaddr[Y] + 3 * (X))
394#define PIXELADDR4(X,Y)  (osmesa->rowaddr[Y] + 4 * (X))
395
396
397/*
398 * Draw a flat-shaded, RGB line into an osmesa buffer.
399 */
400#define NAME flat_rgba_line
401#define CLIP_HACK 1
402#define SETUP_CODE						\
403   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);		\
404   const GLchan *color = vert1->color;
405
406#define PLOT(X, Y)						\
407do {								\
408   GLchan *p = PIXELADDR4(X, Y);				\
409   PACK_RGBA(p, color[0], color[1], color[2], color[3]);	\
410} while (0)
411
412#ifdef WIN32
413#include "..\swrast\s_linetemp.h"
414#else
415#include "swrast/s_linetemp.h"
416#endif
417
418
419
420/*
421 * Draw a flat-shaded, Z-less, RGB line into an osmesa buffer.
422 */
423#define NAME flat_rgba_z_line
424#define CLIP_HACK 1
425#define INTERP_Z 1
426#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
427#define SETUP_CODE					\
428   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);	\
429   const GLchan *color = vert1->color;
430
431#define PLOT(X, Y)					\
432do {							\
433   if (Z < *zPtr) {					\
434      GLchan *p = PIXELADDR4(X, Y);			\
435      PACK_RGBA(p, color[RCOMP], color[GCOMP],		\
436                   color[BCOMP], color[ACOMP]);		\
437      *zPtr = Z;					\
438   }							\
439} while (0)
440
441#ifdef WIN32
442#include "..\swrast\s_linetemp.h"
443#else
444#include "swrast/s_linetemp.h"
445#endif
446
447
448
449/*
450 * Analyze context state to see if we can provide a fast line drawing
451 * function, like those in lines.c.  Otherwise, return NULL.
452 */
453static swrast_line_func
454osmesa_choose_line_function( GLcontext *ctx )
455{
456   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
457   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
458
459   if (CHAN_BITS != 8)                    return NULL;
460   if (ctx->RenderMode != GL_RENDER)      return NULL;
461   if (ctx->Line.SmoothFlag)              return NULL;
462   if (ctx->Texture._EnabledUnits)        return NULL;
463   if (ctx->Light.ShadeModel != GL_FLAT)  return NULL;
464   if (ctx->Line.Width != 1.0F)           return NULL;
465   if (ctx->Line.StippleFlag)             return NULL;
466   if (ctx->Line.SmoothFlag)              return NULL;
467   if (osmesa->format != OSMESA_RGBA &&
468       osmesa->format != OSMESA_BGRA &&
469       osmesa->format != OSMESA_ARGB)     return NULL;
470
471   if (swrast->_RasterMask==DEPTH_BIT
472       && ctx->Depth.Func==GL_LESS
473       && ctx->Depth.Mask==GL_TRUE
474       && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) {
475      return (swrast_line_func) flat_rgba_z_line;
476   }
477
478   if (swrast->_RasterMask == 0) {
479      return (swrast_line_func) flat_rgba_line;
480   }
481
482   return (swrast_line_func) NULL;
483}
484
485
486/**********************************************************************/
487/*****                 Optimized triangle rendering               *****/
488/**********************************************************************/
489
490
491/*
492 * Smooth-shaded, z-less triangle, RGBA color.
493 */
494#define NAME smooth_rgba_z_triangle
495#define INTERP_Z 1
496#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
497#define INTERP_RGB 1
498#define INTERP_ALPHA 1
499#define SETUP_CODE \
500   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
501#define RENDER_SPAN( span )					\
502   GLuint i;							\
503   GLchan *img = PIXELADDR4(span.x, span.y); 			\
504   for (i = 0; i < span.end; i++, img += 4) {			\
505      const GLdepth z = FixedToDepth(span.z);			\
506      if (z < zRow[i]) {					\
507         PACK_RGBA(img, FixedToChan(span.red),			\
508            FixedToChan(span.green), FixedToChan(span.blue),	\
509            FixedToChan(span.alpha));				\
510         zRow[i] = z;						\
511      }								\
512      span.red += span.redStep;					\
513      span.green += span.greenStep;				\
514      span.blue += span.blueStep;				\
515      span.alpha += span.alphaStep;				\
516      span.z += span.zStep;					\
517   }
518#ifdef WIN32
519#include "..\swrast\s_tritemp.h"
520#else
521#include "swrast/s_tritemp.h"
522#endif
523
524
525
526/*
527 * Flat-shaded, z-less triangle, RGBA color.
528 */
529#define NAME flat_rgba_z_triangle
530#define INTERP_Z 1
531#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
532#define SETUP_CODE						\
533   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);		\
534   GLuint pixel;						\
535   PACK_RGBA((GLchan *) &pixel, v2->color[0], v2->color[1],	\
536                                v2->color[2], v2->color[3]);
537
538#define RENDER_SPAN( span )				\
539   GLuint i;						\
540   GLuint *img = (GLuint *) PIXELADDR4(span.x, span.y);	\
541   for (i = 0; i < span.end; i++) {			\
542      const GLdepth z = FixedToDepth(span.z);		\
543      if (z < zRow[i]) {				\
544         img[i] = pixel;				\
545         zRow[i] = z;					\
546      }							\
547      span.z += span.zStep;				\
548   }
549#ifdef WIN32
550#include "..\swrast\s_tritemp.h"
551#else
552#include "swrast/s_tritemp.h"
553#endif
554
555
556
557/*
558 * Return pointer to an accelerated triangle function if possible.
559 */
560static swrast_tri_func
561osmesa_choose_triangle_function( GLcontext *ctx )
562{
563   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
564   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
565
566   if (CHAN_BITS != 8)                  return (swrast_tri_func) NULL;
567   if (ctx->RenderMode != GL_RENDER)    return (swrast_tri_func) NULL;
568   if (ctx->Polygon.SmoothFlag)         return (swrast_tri_func) NULL;
569   if (ctx->Polygon.StippleFlag)        return (swrast_tri_func) NULL;
570   if (ctx->Texture._EnabledUnits)      return (swrast_tri_func) NULL;
571   if (osmesa->format != OSMESA_RGBA &&
572       osmesa->format != OSMESA_BGRA &&
573       osmesa->format != OSMESA_ARGB)   return (swrast_tri_func) NULL;
574   if (ctx->Polygon.CullFlag &&
575       ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK)
576                                        return (swrast_tri_func) NULL;
577
578   if (swrast->_RasterMask == DEPTH_BIT &&
579       ctx->Depth.Func == GL_LESS &&
580       ctx->Depth.Mask == GL_TRUE &&
581       ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) {
582      if (ctx->Light.ShadeModel == GL_SMOOTH) {
583         return (swrast_tri_func) smooth_rgba_z_triangle;
584      }
585      else {
586         return (swrast_tri_func) flat_rgba_z_triangle;
587      }
588   }
589   return (swrast_tri_func) NULL;
590}
591
592
593
594/* Override for the swrast triangle-selection function.  Try to use one
595 * of our internal triangle functions, otherwise fall back to the
596 * standard swrast functions.
597 */
598static void
599osmesa_choose_triangle( GLcontext *ctx )
600{
601   SWcontext *swrast = SWRAST_CONTEXT(ctx);
602
603   swrast->Triangle = osmesa_choose_triangle_function( ctx );
604   if (!swrast->Triangle)
605      _swrast_choose_triangle( ctx );
606}
607
608static void
609osmesa_choose_line( GLcontext *ctx )
610{
611   SWcontext *swrast = SWRAST_CONTEXT(ctx);
612
613   swrast->Line = osmesa_choose_line_function( ctx );
614   if (!swrast->Line)
615      _swrast_choose_line( ctx );
616}
617
618
619#define OSMESA_NEW_LINE   (_NEW_LINE | \
620                           _NEW_TEXTURE | \
621                           _NEW_LIGHT | \
622                           _NEW_DEPTH | \
623                           _NEW_RENDERMODE | \
624                           _SWRAST_NEW_RASTERMASK)
625
626#define OSMESA_NEW_TRIANGLE (_NEW_POLYGON | \
627                             _NEW_TEXTURE | \
628                             _NEW_LIGHT | \
629                             _NEW_DEPTH | \
630                             _NEW_RENDERMODE | \
631                             _SWRAST_NEW_RASTERMASK)
632
633
634/* one-time, per-context initialization */
635static void
636hook_in_driver_functions( GLcontext *ctx )
637{
638   OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
639   SWcontext *swrast = SWRAST_CONTEXT( ctx );
640   struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference( ctx );
641   TNLcontext *tnl = TNL_CONTEXT(ctx);
642
643   ASSERT((void *) osmesa == (void *) ctx->DriverCtx);
644
645   /* use default TCL pipeline */
646   tnl->Driver.RunPipeline = _tnl_run_pipeline;
647
648   swdd->SetBuffer = set_buffer;
649
650   /* RGB(A) span/pixel functions */
651   if (osmesa->format == OSMESA_RGB) {
652      swdd->WriteRGBASpan = write_rgba_span_RGB;
653      swdd->WriteRGBSpan = write_rgb_span_RGB;
654      swdd->WriteMonoRGBASpan = write_monorgba_span_RGB;
655      swdd->WriteRGBAPixels = write_rgba_pixels_RGB;
656      swdd->WriteMonoRGBAPixels = write_monorgba_pixels_RGB;
657      swdd->ReadRGBASpan = read_rgba_span_RGB;
658      swdd->ReadRGBAPixels = read_rgba_pixels_RGB;
659   }
660   else if (osmesa->format == OSMESA_BGR) {
661      swdd->WriteRGBASpan = write_rgba_span_BGR;
662      swdd->WriteRGBSpan = write_rgb_span_BGR;
663      swdd->WriteMonoRGBASpan = write_monorgba_span_BGR;
664      swdd->WriteRGBAPixels = write_rgba_pixels_BGR;
665      swdd->WriteMonoRGBAPixels = write_monorgba_pixels_BGR;
666      swdd->ReadRGBASpan = read_rgba_span_BGR;
667      swdd->ReadRGBAPixels = read_rgba_pixels_BGR;
668   }
669#if CHAN_TYPE == GL_UNSIGNED_BYTE
670   else if (osmesa->format == OSMESA_RGB_565) {
671      swdd->WriteRGBASpan = write_rgba_span_RGB_565;
672      swdd->WriteRGBSpan = write_rgb_span_RGB_565;
673      swdd->WriteMonoRGBASpan = write_monorgba_span_RGB_565;
674      swdd->WriteRGBAPixels = write_rgba_pixels_RGB_565;
675      swdd->WriteMonoRGBAPixels = write_monorgba_pixels_RGB_565;
676      swdd->ReadRGBASpan = read_rgba_span_RGB_565;
677      swdd->ReadRGBAPixels = read_rgba_pixels_RGB_565;
678   }
679#endif
680   else if (osmesa->format == OSMESA_RGBA) {
681      swdd->WriteRGBASpan = write_rgba_span_RGBA;
682      swdd->WriteRGBSpan = write_rgb_span_RGBA;
683      swdd->WriteMonoRGBASpan = write_monorgba_span_RGBA;
684      swdd->WriteRGBAPixels = write_rgba_pixels_RGBA;
685      swdd->WriteMonoRGBAPixels = write_monorgba_pixels_RGBA;
686      swdd->ReadRGBASpan = read_rgba_span_RGBA;
687      swdd->ReadRGBAPixels = read_rgba_pixels_RGBA;
688   }
689   else if (osmesa->format == OSMESA_BGRA) {
690      swdd->WriteRGBASpan = write_rgba_span_BGRA;
691      swdd->WriteRGBSpan = write_rgb_span_BGRA;
692      swdd->WriteMonoRGBASpan = write_monorgba_span_BGRA;
693      swdd->WriteRGBAPixels = write_rgba_pixels_BGRA;
694      swdd->WriteMonoRGBAPixels = write_monorgba_pixels_BGRA;
695      swdd->ReadRGBASpan = read_rgba_span_BGRA;
696      swdd->ReadRGBAPixels = read_rgba_pixels_BGRA;
697   }
698   else if (osmesa->format == OSMESA_ARGB) {
699      swdd->WriteRGBASpan = write_rgba_span_ARGB;
700      swdd->WriteRGBSpan = write_rgb_span_ARGB;
701      swdd->WriteMonoRGBASpan = write_monorgba_span_ARGB;
702      swdd->WriteRGBAPixels = write_rgba_pixels_ARGB;
703      swdd->WriteMonoRGBAPixels = write_monorgba_pixels_ARGB;
704      swdd->ReadRGBASpan = read_rgba_span_ARGB;
705      swdd->ReadRGBAPixels = read_rgba_pixels_ARGB;
706   }
707   else if (osmesa->format == OSMESA_COLOR_INDEX) {
708      swdd->WriteCI32Span = write_index32_span_CI;
709      swdd->WriteCI8Span = write_index8_span_CI;
710      swdd->WriteMonoCISpan = write_monoindex_span_CI;
711      swdd->WriteCI32Pixels = write_index_pixels_CI;
712      swdd->WriteMonoCIPixels = write_monoindex_pixels_CI;
713      swdd->ReadCI32Span = read_index_span_CI;
714      swdd->ReadCI32Pixels = read_index_pixels_CI;
715   }
716   else {
717      _mesa_problem(ctx, "bad pixel format in osmesa_update_state!\n");
718   }
719
720   /* Extend the software rasterizer with our optimized line and triangle
721    * drawin functions.
722    */
723   swrast->choose_line = osmesa_choose_line;
724   swrast->choose_triangle = osmesa_choose_triangle;
725   swrast->invalidate_line |= OSMESA_NEW_LINE;
726   swrast->invalidate_triangle |= OSMESA_NEW_TRIANGLE;
727}
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 rshift, gshift, bshift, ashift;
768   GLint rind, gind, bind, aind;
769   GLint indexBits = 0, redBits = 0, greenBits = 0, blueBits = 0, alphaBits =0;
770   GLboolean rgbmode;
771   const GLuint i4 = 1;
772   const GLubyte *i1 = (GLubyte *) &i4;
773   const GLint little_endian = *i1;
774
775   rind = gind = bind = aind = 0;
776   if (format==OSMESA_COLOR_INDEX) {
777      indexBits = 8;
778      rshift = gshift = bshift = ashift = 0;
779      rgbmode = GL_FALSE;
780   }
781   else if (format==OSMESA_RGBA) {
782      indexBits = 0;
783      redBits = CHAN_BITS;
784      greenBits = CHAN_BITS;
785      blueBits = CHAN_BITS;
786      alphaBits = CHAN_BITS;
787      rind = 0;
788      gind = 1;
789      bind = 2;
790      aind = 3;
791      if (little_endian) {
792         rshift = 0;
793         gshift = 8;
794         bshift = 16;
795         ashift = 24;
796      }
797      else {
798         rshift = 24;
799         gshift = 16;
800         bshift = 8;
801         ashift = 0;
802      }
803      rgbmode = GL_TRUE;
804   }
805   else if (format==OSMESA_BGRA) {
806      indexBits = 0;
807      redBits = CHAN_BITS;
808      greenBits = CHAN_BITS;
809      blueBits = CHAN_BITS;
810      alphaBits = CHAN_BITS;
811      bind = 0;
812      gind = 1;
813      rind = 2;
814      aind = 3;
815      if (little_endian) {
816         bshift = 0;
817         gshift = 8;
818         rshift = 16;
819         ashift = 24;
820      }
821      else {
822         bshift = 24;
823         gshift = 16;
824         rshift = 8;
825         ashift = 0;
826      }
827      rgbmode = GL_TRUE;
828   }
829   else if (format==OSMESA_ARGB) {
830      indexBits = 0;
831      redBits = CHAN_BITS;
832      greenBits = CHAN_BITS;
833      blueBits = CHAN_BITS;
834      alphaBits = CHAN_BITS;
835      aind = 0;
836      rind = 1;
837      gind = 2;
838      bind = 3;
839      if (little_endian) {
840         ashift = 0;
841         rshift = 8;
842         gshift = 16;
843         bshift = 24;
844      }
845      else {
846         ashift = 24;
847         rshift = 16;
848         gshift = 8;
849         bshift = 0;
850      }
851      rgbmode = GL_TRUE;
852   }
853   else if (format==OSMESA_RGB) {
854      indexBits = 0;
855      redBits = CHAN_BITS;
856      greenBits = CHAN_BITS;
857      blueBits = CHAN_BITS;
858      alphaBits = 0;
859      bshift = 0;
860      gshift = 8;
861      rshift = 16;
862      ashift = 24;
863      rind = 0;
864      gind = 1;
865      bind = 2;
866      rgbmode = GL_TRUE;
867   }
868   else if (format==OSMESA_BGR) {
869      indexBits = 0;
870      redBits = CHAN_BITS;
871      greenBits = CHAN_BITS;
872      blueBits = CHAN_BITS;
873      alphaBits = 0;
874      bshift = 0;
875      gshift = 8;
876      rshift = 16;
877      ashift = 24;
878      rind = 2;
879      gind = 1;
880      bind = 0;
881      rgbmode = GL_TRUE;
882   }
883#if CHAN_TYPE == GL_UNSIGNED_BYTE
884   else if (format==OSMESA_RGB_565) {
885      indexBits = 0;
886      redBits = 5;
887      greenBits = 6;
888      blueBits = 5;
889      alphaBits = 0;
890      rshift = 11;
891      gshift = 5;
892      bshift = 0;
893      ashift = 0;
894      rind = 0; /* not used */
895      gind = 0;
896      bind = 0;
897      rgbmode = GL_TRUE;
898   }
899#endif
900   else {
901      return NULL;
902   }
903
904
905   osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context);
906   if (osmesa) {
907      osmesa->gl_visual = _mesa_create_visual( rgbmode,
908                                               GL_FALSE,    /* double buffer */
909                                               GL_FALSE,    /* stereo */
910                                               redBits,
911                                               greenBits,
912                                               blueBits,
913                                               alphaBits,
914                                               indexBits,
915                                               depthBits,
916                                               stencilBits,
917                                               accumBits,
918                                               accumBits,
919                                               accumBits,
920                                               alphaBits ? accumBits : 0,
921                                               1            /* num samples */
922                                               );
923      if (!osmesa->gl_visual) {
924         FREE(osmesa);
925         return NULL;
926      }
927
928      /* Initialize device driver function table */
929      _mesa_init_driver_functions(&functions);
930      /* override with our functions */
931      functions.GetString = get_string;
932      functions.UpdateState = osmesa_update_state;
933      functions.GetBufferSize = get_buffer_size;
934      functions.Clear = clear;
935
936      if (!_mesa_initialize_context(&osmesa->mesa,
937                                    osmesa->gl_visual,
938                                    sharelist ? &sharelist->mesa
939                                              : (GLcontext *) NULL,
940                                    &functions, (void *) osmesa)) {
941         _mesa_destroy_visual( osmesa->gl_visual );
942         FREE(osmesa);
943         return NULL;
944      }
945
946      _mesa_enable_sw_extensions(&(osmesa->mesa));
947      _mesa_enable_1_3_extensions(&(osmesa->mesa));
948      _mesa_enable_1_4_extensions(&(osmesa->mesa));
949      _mesa_enable_1_5_extensions(&(osmesa->mesa));
950
951      osmesa->gl_buffer = _mesa_create_framebuffer( osmesa->gl_visual,
952                           (GLboolean) ( osmesa->gl_visual->depthBits > 0 ),
953                           (GLboolean) ( osmesa->gl_visual->stencilBits > 0 ),
954                           (GLboolean) ( osmesa->gl_visual->accumRedBits > 0 ),
955                           GL_FALSE /* s/w alpha */ );
956
957      if (!osmesa->gl_buffer) {
958         _mesa_destroy_visual( osmesa->gl_visual );
959         _mesa_free_context_data( &osmesa->mesa );
960         FREE(osmesa);
961         return NULL;
962      }
963      osmesa->format = format;
964      osmesa->buffer = NULL;
965      osmesa->width = 0;
966      osmesa->height = 0;
967      osmesa->userRowLength = 0;
968      osmesa->rowlength = 0;
969      osmesa->yup = GL_TRUE;
970      osmesa->rshift = rshift;
971      osmesa->gshift = gshift;
972      osmesa->bshift = bshift;
973      osmesa->ashift = ashift;
974      osmesa->rInd = rind;
975      osmesa->gInd = gind;
976      osmesa->bInd = bind;
977      osmesa->aInd = aind;
978
979      /* Initialize the software rasterizer and helper modules. */
980      {
981	 GLcontext *ctx = &osmesa->mesa;
982
983	 _swrast_CreateContext( ctx );
984	 _ac_CreateContext( ctx );
985	 _tnl_CreateContext( ctx );
986	 _swsetup_CreateContext( ctx );
987
988	 _swsetup_Wakeup( ctx );
989         hook_in_driver_functions( ctx );
990      }
991   }
992   return osmesa;
993}
994
995
996/*
997 * Destroy an Off-Screen Mesa rendering context.
998 *
999 * Input:  ctx - the context to destroy
1000 */
1001GLAPI void GLAPIENTRY
1002OSMesaDestroyContext( OSMesaContext ctx )
1003{
1004   if (ctx) {
1005      _swsetup_DestroyContext( &ctx->mesa );
1006      _tnl_DestroyContext( &ctx->mesa );
1007      _ac_DestroyContext( &ctx->mesa );
1008      _swrast_DestroyContext( &ctx->mesa );
1009
1010      _mesa_destroy_visual( ctx->gl_visual );
1011      _mesa_destroy_framebuffer( ctx->gl_buffer );
1012      _mesa_free_context_data( &ctx->mesa );
1013      FREE( ctx );
1014   }
1015}
1016
1017
1018/*
1019 * Recompute the values of the context's rowaddr array.
1020 */
1021static void
1022compute_row_addresses( OSMesaContext ctx )
1023{
1024   GLint bytesPerPixel, bytesPerRow, i;
1025   GLubyte *origin = (GLubyte *) ctx->buffer;
1026
1027   if (ctx->format == OSMESA_COLOR_INDEX) {
1028      /* CI mode */
1029      bytesPerPixel = 1 * sizeof(GLchan);
1030   }
1031   else if ((ctx->format == OSMESA_RGB) || (ctx->format == OSMESA_BGR)) {
1032      /* RGB mode */
1033      bytesPerPixel = 3 * sizeof(GLchan);
1034   }
1035   else if (ctx->format == OSMESA_RGB_565) {
1036      /* 5/6/5 RGB pixel in 16 bits */
1037      bytesPerPixel = 2;
1038   }
1039   else {
1040      /* RGBA mode */
1041      bytesPerPixel = 4 * sizeof(GLchan);
1042   }
1043
1044   bytesPerRow = ctx->rowlength * bytesPerPixel;
1045
1046   if (ctx->yup) {
1047      /* Y=0 is bottom line of window */
1048      for (i = 0; i < MAX_HEIGHT; i++) {
1049         ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + i * bytesPerRow);
1050      }
1051   }
1052   else {
1053      /* Y=0 is top line of window */
1054      for (i = 0; i < MAX_HEIGHT; i++) {
1055         GLint j = ctx->height - i - 1;
1056         ctx->rowaddr[i] = (GLchan *) ((GLubyte *) origin + j * bytesPerRow);
1057      }
1058   }
1059}
1060
1061
1062/*
1063 * Bind an OSMesaContext to an image buffer.  The image buffer is just a
1064 * block of memory which the client provides.  Its size must be at least
1065 * as large as width*height*sizeof(type).  Its address should be a multiple
1066 * of 4 if using RGBA mode.
1067 *
1068 * Image data is stored in the order of glDrawPixels:  row-major order
1069 * with the lower-left image pixel stored in the first array position
1070 * (ie. bottom-to-top).
1071 *
1072 * If the context's viewport hasn't been initialized yet, it will now be
1073 * initialized to (0,0,width,height).
1074 *
1075 * Input:  ctx - the rendering context
1076 *         buffer - the image buffer memory
1077 *         type - data type for pixel components
1078 *            Normally, only GL_UNSIGNED_BYTE and GL_UNSIGNED_SHORT_5_6_5
1079 *            are supported.  But if Mesa's been compiled with CHAN_BITS==16
1080 *            then type must be GL_UNSIGNED_SHORT.  And if Mesa's been build
1081 *            with CHAN_BITS==32 then type must be GL_FLOAT.
1082 *         width, height - size of image buffer in pixels, at least 1
1083 * Return:  GL_TRUE if success, GL_FALSE if error because of invalid ctx,
1084 *          invalid buffer address, invalid type, width<1, height<1,
1085 *          width>internal limit or height>internal limit.
1086 */
1087GLAPI GLboolean GLAPIENTRY
1088OSMesaMakeCurrent( OSMesaContext ctx, void *buffer, GLenum type,
1089                   GLsizei width, GLsizei height )
1090{
1091   if (!ctx || !buffer ||
1092       width < 1 || height < 1 ||
1093       width > MAX_WIDTH || height > MAX_HEIGHT) {
1094      return GL_FALSE;
1095   }
1096
1097   if (ctx->format == OSMESA_RGB_565) {
1098      if (type != GL_UNSIGNED_SHORT_5_6_5)
1099         return GL_FALSE;
1100   }
1101   else if (type != CHAN_TYPE) {
1102      return GL_FALSE;
1103   }
1104
1105   osmesa_update_state( &ctx->mesa, 0 );
1106   _mesa_make_current( &ctx->mesa, ctx->gl_buffer );
1107
1108   ctx->buffer = buffer;
1109   ctx->width = width;
1110   ctx->height = height;
1111   if (ctx->userRowLength)
1112      ctx->rowlength = ctx->userRowLength;
1113   else
1114      ctx->rowlength = width;
1115
1116   compute_row_addresses( ctx );
1117
1118   /* init viewport */
1119   if (ctx->mesa.Viewport.Width == 0) {
1120      /* initialize viewport and scissor box to buffer size */
1121      _mesa_Viewport( 0, 0, width, height );
1122      ctx->mesa.Scissor.Width = width;
1123      ctx->mesa.Scissor.Height = height;
1124   }
1125   else {
1126      /* this will make ensure we recognize the new buffer size */
1127      _mesa_ResizeBuffersMESA();
1128   }
1129
1130   /* Added by Gerk Huisma: */
1131   _tnl_MakeCurrent( &ctx->mesa, ctx->mesa.DrawBuffer,
1132                     ctx->mesa.ReadBuffer );
1133
1134   return GL_TRUE;
1135}
1136
1137
1138
1139GLAPI OSMesaContext GLAPIENTRY OSMesaGetCurrentContext( void )
1140{
1141   GLcontext *ctx = _mesa_get_current_context();
1142   if (ctx)
1143      return (OSMesaContext) ctx;
1144   else
1145      return NULL;
1146}
1147
1148
1149
1150GLAPI void GLAPIENTRY OSMesaPixelStore( GLint pname, GLint value )
1151{
1152   OSMesaContext osmesa = OSMesaGetCurrentContext();
1153
1154   switch (pname) {
1155      case OSMESA_ROW_LENGTH:
1156         if (value<0) {
1157            _mesa_error( &osmesa->mesa, GL_INVALID_VALUE,
1158                      "OSMesaPixelStore(value)" );
1159            return;
1160         }
1161         osmesa->userRowLength = value;
1162         osmesa->rowlength = value ? value : osmesa->width;
1163         break;
1164      case OSMESA_Y_UP:
1165         osmesa->yup = value ? GL_TRUE : GL_FALSE;
1166         break;
1167      default:
1168         _mesa_error( &osmesa->mesa, GL_INVALID_ENUM, "OSMesaPixelStore(pname)" );
1169         return;
1170   }
1171
1172   compute_row_addresses( osmesa );
1173}
1174
1175
1176GLAPI void GLAPIENTRY OSMesaGetIntegerv( GLint pname, GLint *value )
1177{
1178   OSMesaContext osmesa = OSMesaGetCurrentContext();
1179
1180   switch (pname) {
1181      case OSMESA_WIDTH:
1182         *value = osmesa->width;
1183         return;
1184      case OSMESA_HEIGHT:
1185         *value = osmesa->height;
1186         return;
1187      case OSMESA_FORMAT:
1188         *value = osmesa->format;
1189         return;
1190      case OSMESA_TYPE:
1191         *value = CHAN_TYPE;
1192         return;
1193      case OSMESA_ROW_LENGTH:
1194         *value = osmesa->userRowLength;
1195         return;
1196      case OSMESA_Y_UP:
1197         *value = osmesa->yup;
1198         return;
1199      case OSMESA_MAX_WIDTH:
1200         *value = MAX_WIDTH;
1201         return;
1202      case OSMESA_MAX_HEIGHT:
1203         *value = MAX_HEIGHT;
1204         return;
1205      default:
1206         _mesa_error(&osmesa->mesa, GL_INVALID_ENUM, "OSMesaGetIntergerv(pname)");
1207         return;
1208   }
1209}
1210
1211/*
1212 * Return the depth buffer associated with an OSMesa context.
1213 * Input:  c - the OSMesa context
1214 * Output:  width, height - size of buffer in pixels
1215 *          bytesPerValue - bytes per depth value (2 or 4)
1216 *          buffer - pointer to depth buffer values
1217 * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
1218 */
1219GLAPI GLboolean GLAPIENTRY
1220OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height,
1221                      GLint *bytesPerValue, void **buffer )
1222{
1223   if ((!c->gl_buffer) || (!c->gl_buffer->DepthBuffer)) {
1224      *width = 0;
1225      *height = 0;
1226      *bytesPerValue = 0;
1227      *buffer = 0;
1228      return GL_FALSE;
1229   }
1230   else {
1231      *width = c->gl_buffer->Width;
1232      *height = c->gl_buffer->Height;
1233      if (c->gl_visual->depthBits <= 16)
1234         *bytesPerValue = sizeof(GLushort);
1235      else
1236         *bytesPerValue = sizeof(GLuint);
1237      *buffer = c->gl_buffer->DepthBuffer;
1238      return GL_TRUE;
1239   }
1240}
1241
1242/*
1243 * Return the color buffer associated with an OSMesa context.
1244 * Input:  c - the OSMesa context
1245 * Output:  width, height - size of buffer in pixels
1246 *          format - the pixel format (OSMESA_FORMAT)
1247 *          buffer - pointer to color buffer values
1248 * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
1249 */
1250GLAPI GLboolean GLAPIENTRY
1251OSMesaGetColorBuffer( OSMesaContext c, GLint *width,
1252                      GLint *height, GLint *format, void **buffer )
1253{
1254   if (!c->buffer) {
1255      *width = 0;
1256      *height = 0;
1257      *format = 0;
1258      *buffer = 0;
1259      return GL_FALSE;
1260   }
1261   else {
1262      *width = c->width;
1263      *height = c->height;
1264      *format = c->format;
1265      *buffer = c->buffer;
1266      return GL_TRUE;
1267   }
1268}
1269
1270
1271
1272struct name_address {
1273   const char *Name;
1274   GLvoid *Address;
1275};
1276
1277static struct name_address functions[] = {
1278   { "OSMesaCreateContext", (void *) OSMesaCreateContext },
1279   { "OSMesaCreateContextExt", (void *) OSMesaCreateContextExt },
1280   { "OSMesaDestroyContext", (void *) OSMesaDestroyContext },
1281   { "OSMesaMakeCurrent", (void *) OSMesaMakeCurrent },
1282   { "OSMesaGetCurrentContext", (void *) OSMesaGetCurrentContext },
1283   { "OSMesaPixelsStore", (void *) OSMesaPixelStore },
1284   { "OSMesaGetIntegerv", (void *) OSMesaGetIntegerv },
1285   { "OSMesaGetDepthBuffer", (void *) OSMesaGetDepthBuffer },
1286   { "OSMesaGetColorBuffer", (void *) OSMesaGetColorBuffer },
1287   { "OSMesaGetProcAddress", (void *) OSMesaGetProcAddress },
1288   { NULL, NULL }
1289};
1290
1291GLAPI void * GLAPIENTRY
1292OSMesaGetProcAddress( const char *funcName )
1293{
1294   int i;
1295   for (i = 0; functions[i].Name; i++) {
1296      if (_mesa_strcmp(functions[i].Name, funcName) == 0)
1297         return (void *) functions[i].Address;
1298   }
1299   return (void *) _glapi_get_proc_address(funcName);
1300}
1301