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