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