1/*
2 * Mesa 3-D graphics library
3 * Version:  6.5.3
4 *
5 * Copyright (C) 1999-2007  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 "main/glheader.h"
37#include "GL/osmesa.h"
38#include "main/context.h"
39#include "main/extensions.h"
40#include "main/formats.h"
41#include "main/framebuffer.h"
42#include "main/imports.h"
43#include "main/macros.h"
44#include "main/mipmap.h"
45#include "main/mtypes.h"
46#include "main/renderbuffer.h"
47#include "swrast/swrast.h"
48#include "swrast_setup/swrast_setup.h"
49#include "swrast/s_context.h"
50#include "swrast/s_lines.h"
51#include "swrast/s_renderbuffer.h"
52#include "swrast/s_triangle.h"
53#include "tnl/tnl.h"
54#include "tnl/t_context.h"
55#include "tnl/t_pipeline.h"
56#include "drivers/common/driverfuncs.h"
57#include "drivers/common/meta.h"
58#include "vbo/vbo.h"
59
60
61#define OSMESA_RENDERBUFFER_CLASS 0x053
62
63
64/**
65 * OSMesa rendering context, derived from core Mesa struct gl_context.
66 */
67struct osmesa_context
68{
69   struct gl_context mesa;		/*< Base class - this must be first */
70   struct gl_config *gl_visual;		/*< Describes the buffers */
71   struct swrast_renderbuffer *srb;     /*< The user's colorbuffer */
72   struct gl_framebuffer *gl_buffer;	/*< The framebuffer, containing user's rb */
73   GLenum format;		/*< User-specified context format */
74   GLint userRowLength;		/*< user-specified number of pixels per row */
75   GLint rInd, gInd, bInd, aInd;/*< index offsets for RGBA formats */
76   GLvoid *rowaddr[SWRAST_MAX_HEIGHT];	/*< address of first pixel in each image row */
77   GLboolean yup;		/*< TRUE  -> Y increases upward */
78				/*< FALSE -> Y increases downward */
79   GLenum DataType;
80};
81
82
83static INLINE OSMesaContext
84OSMESA_CONTEXT(struct gl_context *ctx)
85{
86   /* Just cast, since we're using structure containment */
87   return (OSMesaContext) ctx;
88}
89
90
91/**********************************************************************/
92/*** Private Device Driver Functions                                ***/
93/**********************************************************************/
94
95
96static const GLubyte *
97get_string( struct gl_context *ctx, GLenum name )
98{
99   (void) ctx;
100   switch (name) {
101      case GL_RENDERER:
102#if CHAN_BITS == 32
103         return (const GLubyte *) "Mesa OffScreen32";
104#elif CHAN_BITS == 16
105         return (const GLubyte *) "Mesa OffScreen16";
106#else
107         return (const GLubyte *) "Mesa OffScreen";
108#endif
109      default:
110         return NULL;
111   }
112}
113
114
115static void
116osmesa_update_state( struct gl_context *ctx, GLuint new_state )
117{
118   /* easy - just propogate */
119   _swrast_InvalidateState( ctx, new_state );
120   _swsetup_InvalidateState( ctx, new_state );
121   _tnl_InvalidateState( ctx, new_state );
122   _vbo_InvalidateState( ctx, new_state );
123}
124
125
126
127/**
128 * Macros for optimized line/triangle rendering.
129 * Only for 8-bit channel, RGBA, BGRA, ARGB formats.
130 */
131
132#define PACK_RGBA(DST, R, G, B, A)	\
133do {					\
134   (DST)[osmesa->rInd] = R;		\
135   (DST)[osmesa->gInd] = G;		\
136   (DST)[osmesa->bInd] = B;		\
137   (DST)[osmesa->aInd] = A;		\
138} while (0)
139
140#define PIXELADDR4(X,Y)  ((GLchan *) osmesa->rowaddr[Y] + 4 * (X))
141
142
143/**
144 * Draw a flat-shaded, RGB line into an osmesa buffer.
145 */
146#define NAME flat_rgba_line
147#define CLIP_HACK 1
148#define SETUP_CODE						\
149   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);		\
150   const GLchan *color = vert1->color;
151
152#define PLOT(X, Y)						\
153do {								\
154   GLchan *p = PIXELADDR4(X, Y);				\
155   PACK_RGBA(p, color[0], color[1], color[2], color[3]);	\
156} while (0)
157
158#include "swrast/s_linetemp.h"
159
160
161
162/**
163 * Draw a flat-shaded, Z-less, RGB line into an osmesa buffer.
164 */
165#define NAME flat_rgba_z_line
166#define CLIP_HACK 1
167#define INTERP_Z 1
168#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
169#define SETUP_CODE					\
170   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);	\
171   const GLchan *color = vert1->color;
172
173#define PLOT(X, Y)					\
174do {							\
175   if (Z < *zPtr) {					\
176      GLchan *p = PIXELADDR4(X, Y);			\
177      PACK_RGBA(p, color[RCOMP], color[GCOMP],		\
178                   color[BCOMP], color[ACOMP]);		\
179      *zPtr = Z;					\
180   }							\
181} while (0)
182
183#include "swrast/s_linetemp.h"
184
185
186
187/**
188 * Analyze context state to see if we can provide a fast line drawing
189 * function.  Otherwise, return NULL.
190 */
191static swrast_line_func
192osmesa_choose_line_function( struct gl_context *ctx )
193{
194   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
195   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
196
197   if (ctx->RenderMode != GL_RENDER)      return NULL;
198   if (ctx->Line.SmoothFlag)              return NULL;
199   if (ctx->Texture._EnabledUnits)        return NULL;
200   if (ctx->Light.ShadeModel != GL_FLAT)  return NULL;
201   if (ctx->Line.Width != 1.0F)           return NULL;
202   if (ctx->Line.StippleFlag)             return NULL;
203   if (ctx->Line.SmoothFlag)              return NULL;
204   if (osmesa->format != OSMESA_RGBA &&
205       osmesa->format != OSMESA_BGRA &&
206       osmesa->format != OSMESA_ARGB)     return NULL;
207
208   if (swrast->_RasterMask==DEPTH_BIT
209       && ctx->Depth.Func==GL_LESS
210       && ctx->Depth.Mask==GL_TRUE
211       && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) {
212      return (swrast_line_func) flat_rgba_z_line;
213   }
214
215   if (swrast->_RasterMask == 0) {
216      return (swrast_line_func) flat_rgba_line;
217   }
218
219   return (swrast_line_func) NULL;
220}
221
222
223/**********************************************************************/
224/*****                 Optimized triangle rendering               *****/
225/**********************************************************************/
226
227
228/*
229 * Smooth-shaded, z-less triangle, RGBA color.
230 */
231#define NAME smooth_rgba_z_triangle
232#define INTERP_Z 1
233#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
234#define INTERP_RGB 1
235#define INTERP_ALPHA 1
236#define SETUP_CODE \
237   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
238#define RENDER_SPAN( span ) {					\
239   GLuint i;							\
240   GLchan *img = PIXELADDR4(span.x, span.y); 			\
241   for (i = 0; i < span.end; i++, img += 4) {			\
242      const GLuint z = FixedToDepth(span.z);			\
243      if (z < zRow[i]) {					\
244         PACK_RGBA(img, FixedToChan(span.red),			\
245            FixedToChan(span.green), FixedToChan(span.blue),	\
246            FixedToChan(span.alpha));				\
247         zRow[i] = z;						\
248      }								\
249      span.red += span.redStep;					\
250      span.green += span.greenStep;				\
251      span.blue += span.blueStep;				\
252      span.alpha += span.alphaStep;				\
253      span.z += span.zStep;					\
254   }                                                            \
255}
256#include "swrast/s_tritemp.h"
257
258
259
260/*
261 * Flat-shaded, z-less triangle, RGBA color.
262 */
263#define NAME flat_rgba_z_triangle
264#define INTERP_Z 1
265#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE
266#define SETUP_CODE						\
267   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);		\
268   GLuint pixel;						\
269   PACK_RGBA((GLchan *) &pixel, v2->color[0], v2->color[1],	\
270                                v2->color[2], v2->color[3]);
271
272#define RENDER_SPAN( span ) {				\
273   GLuint i;						\
274   GLuint *img = (GLuint *) PIXELADDR4(span.x, span.y);	\
275   for (i = 0; i < span.end; i++) {			\
276      const GLuint z = FixedToDepth(span.z);		\
277      if (z < zRow[i]) {				\
278         img[i] = pixel;				\
279         zRow[i] = z;					\
280      }							\
281      span.z += span.zStep;				\
282   }                                                    \
283}
284
285#include "swrast/s_tritemp.h"
286
287
288
289/**
290 * Return pointer to an optimized triangle function if possible.
291 */
292static swrast_tri_func
293osmesa_choose_triangle_function( struct gl_context *ctx )
294{
295   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
296   const SWcontext *swrast = SWRAST_CONTEXT(ctx);
297
298   if (ctx->RenderMode != GL_RENDER)    return (swrast_tri_func) NULL;
299   if (ctx->Polygon.SmoothFlag)         return (swrast_tri_func) NULL;
300   if (ctx->Polygon.StippleFlag)        return (swrast_tri_func) NULL;
301   if (ctx->Texture._EnabledUnits)      return (swrast_tri_func) NULL;
302   if (osmesa->format != OSMESA_RGBA &&
303       osmesa->format != OSMESA_BGRA &&
304       osmesa->format != OSMESA_ARGB)   return (swrast_tri_func) NULL;
305   if (ctx->Polygon.CullFlag &&
306       ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK)
307                                        return (swrast_tri_func) NULL;
308
309   if (swrast->_RasterMask == DEPTH_BIT &&
310       ctx->Depth.Func == GL_LESS &&
311       ctx->Depth.Mask == GL_TRUE &&
312       ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS) {
313      if (ctx->Light.ShadeModel == GL_SMOOTH) {
314         return (swrast_tri_func) smooth_rgba_z_triangle;
315      }
316      else {
317         return (swrast_tri_func) flat_rgba_z_triangle;
318      }
319   }
320   return (swrast_tri_func) NULL;
321}
322
323
324
325/* Override for the swrast triangle-selection function.  Try to use one
326 * of our internal triangle functions, otherwise fall back to the
327 * standard swrast functions.
328 */
329static void
330osmesa_choose_triangle( struct gl_context *ctx )
331{
332   SWcontext *swrast = SWRAST_CONTEXT(ctx);
333
334   swrast->Triangle = osmesa_choose_triangle_function( ctx );
335   if (!swrast->Triangle)
336      _swrast_choose_triangle( ctx );
337}
338
339static void
340osmesa_choose_line( struct gl_context *ctx )
341{
342   SWcontext *swrast = SWRAST_CONTEXT(ctx);
343
344   swrast->Line = osmesa_choose_line_function( ctx );
345   if (!swrast->Line)
346      _swrast_choose_line( ctx );
347}
348
349
350
351/**
352 * Recompute the values of the context's rowaddr array.
353 */
354static void
355compute_row_addresses( OSMesaContext osmesa )
356{
357   GLint bytesPerRow, i;
358   GLubyte *origin = (GLubyte *) osmesa->srb->Buffer;
359   GLint rowlength; /* in pixels */
360   GLint height = osmesa->srb->Base.Height;
361
362   if (osmesa->userRowLength)
363      rowlength = osmesa->userRowLength;
364   else
365      rowlength = osmesa->srb->Base.Width;
366
367   bytesPerRow = rowlength * _mesa_get_format_bytes(osmesa->srb->Base.Format);
368
369   if (osmesa->yup) {
370      /* Y=0 is bottom line of window */
371      for (i = 0; i < height; i++) {
372         osmesa->rowaddr[i] = (GLvoid *) ((GLubyte *) origin + i * bytesPerRow);
373      }
374   }
375   else {
376      /* Y=0 is top line of window */
377      for (i = 0; i < height; i++) {
378         GLint j = height - i - 1;
379         osmesa->rowaddr[i] = (GLvoid *) ((GLubyte *) origin + j * bytesPerRow);
380      }
381   }
382}
383
384
385
386/**
387 * Don't use _mesa_delete_renderbuffer since we can't free rb->Buffer.
388 */
389static void
390osmesa_delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
391{
392   _mesa_delete_renderbuffer(ctx, rb);
393}
394
395
396/**
397 * Allocate renderbuffer storage.  We don't actually allocate any storage
398 * since we're using a user-provided buffer.
399 * Just set up all the gl_renderbuffer methods.
400 */
401static GLboolean
402osmesa_renderbuffer_storage(struct gl_context *ctx, struct gl_renderbuffer *rb,
403                            GLenum internalFormat, GLuint width, GLuint height)
404{
405   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
406
407   /* Note: we can ignoring internalFormat for "window-system" renderbuffers */
408   (void) internalFormat;
409
410   /* Given the user-provided format and type, figure out which MESA_FORMAT_x
411    * to use.
412    * XXX There aren't Mesa formats for all the possible combinations here!
413    * XXX Specifically, there's only RGBA-order 16-bit/channel and float
414    * XXX formats.
415    * XXX The 8-bit/channel formats should all be OK.
416    */
417   if (osmesa->format == OSMESA_RGBA) {
418      if (osmesa->DataType == GL_UNSIGNED_BYTE) {
419         if (_mesa_little_endian())
420            rb->Format = MESA_FORMAT_RGBA8888_REV;
421         else
422            rb->Format = MESA_FORMAT_RGBA8888;
423      }
424      else if (osmesa->DataType == GL_UNSIGNED_SHORT) {
425         rb->Format = MESA_FORMAT_RGBA_16;
426      }
427      else {
428         rb->Format = MESA_FORMAT_RGBA_FLOAT32;
429      }
430   }
431   else if (osmesa->format == OSMESA_BGRA) {
432      if (osmesa->DataType == GL_UNSIGNED_BYTE) {
433         if (_mesa_little_endian())
434            rb->Format = MESA_FORMAT_ARGB8888;
435         else
436            rb->Format = MESA_FORMAT_ARGB8888_REV;
437      }
438      else if (osmesa->DataType == GL_UNSIGNED_SHORT) {
439         _mesa_warning(ctx, "Unsupported OSMesa format BGRA/GLushort");
440         rb->Format = MESA_FORMAT_RGBA_16; /* not exactly right */
441      }
442      else {
443         _mesa_warning(ctx, "Unsupported OSMesa format BGRA/GLfloat");
444         rb->Format = MESA_FORMAT_RGBA_FLOAT32; /* not exactly right */
445      }
446   }
447   else if (osmesa->format == OSMESA_ARGB) {
448      if (osmesa->DataType == GL_UNSIGNED_BYTE) {
449         if (_mesa_little_endian())
450            rb->Format = MESA_FORMAT_ARGB8888_REV;
451         else
452            rb->Format = MESA_FORMAT_ARGB8888;
453      }
454      else if (osmesa->DataType == GL_UNSIGNED_SHORT) {
455         _mesa_warning(ctx, "Unsupported OSMesa format ARGB/GLushort");
456         rb->Format = MESA_FORMAT_RGBA_16; /* not exactly right */
457      }
458      else {
459         _mesa_warning(ctx, "Unsupported OSMesa format ARGB/GLfloat");
460         rb->Format = MESA_FORMAT_RGBA_FLOAT32; /* not exactly right */
461      }
462   }
463   else if (osmesa->format == OSMESA_RGB) {
464      if (osmesa->DataType == GL_UNSIGNED_BYTE) {
465         rb->Format = MESA_FORMAT_RGB888;
466      }
467      else if (osmesa->DataType == GL_UNSIGNED_SHORT) {
468         _mesa_warning(ctx, "Unsupported OSMesa format RGB/GLushort");
469         rb->Format = MESA_FORMAT_RGBA_16; /* not exactly right */
470      }
471      else {
472         _mesa_warning(ctx, "Unsupported OSMesa format RGB/GLfloat");
473         rb->Format = MESA_FORMAT_RGBA_FLOAT32; /* not exactly right */
474      }
475   }
476   else if (osmesa->format == OSMESA_BGR) {
477      if (osmesa->DataType == GL_UNSIGNED_BYTE) {
478         rb->Format = MESA_FORMAT_BGR888;
479      }
480      else if (osmesa->DataType == GL_UNSIGNED_SHORT) {
481         _mesa_warning(ctx, "Unsupported OSMesa format BGR/GLushort");
482         rb->Format = MESA_FORMAT_RGBA_16; /* not exactly right */
483      }
484      else {
485         _mesa_warning(ctx, "Unsupported OSMesa format BGR/GLfloat");
486         rb->Format = MESA_FORMAT_RGBA_FLOAT32; /* not exactly right */
487      }
488   }
489   else if (osmesa->format == OSMESA_RGB_565) {
490      ASSERT(osmesa->DataType == GL_UNSIGNED_BYTE);
491      rb->Format = MESA_FORMAT_RGB565;
492   }
493   else {
494      _mesa_problem(ctx, "bad pixel format in osmesa renderbuffer_storage");
495   }
496
497   rb->Width = width;
498   rb->Height = height;
499
500   compute_row_addresses( osmesa );
501
502   return GL_TRUE;
503}
504
505
506/**
507 * Allocate a new renderbuffer to describe the user-provided color buffer.
508 */
509static struct swrast_renderbuffer *
510new_osmesa_renderbuffer(struct gl_context *ctx, GLenum format, GLenum type)
511{
512   const GLuint name = 0;
513   struct swrast_renderbuffer *srb = CALLOC_STRUCT(swrast_renderbuffer);
514
515   if (srb) {
516      _mesa_init_renderbuffer(&srb->Base, name);
517
518      srb->Base.ClassID = OSMESA_RENDERBUFFER_CLASS;
519      srb->Base.RefCount = 1;
520      srb->Base.Delete = osmesa_delete_renderbuffer;
521      srb->Base.AllocStorage = osmesa_renderbuffer_storage;
522
523      srb->Base.InternalFormat = GL_RGBA;
524      srb->Base._BaseFormat = GL_RGBA;
525
526      return srb;
527   }
528   return NULL;
529}
530
531
532
533static void
534osmesa_MapRenderbuffer(struct gl_context *ctx,
535                       struct gl_renderbuffer *rb,
536                       GLuint x, GLuint y, GLuint w, GLuint h,
537                       GLbitfield mode,
538                       GLubyte **mapOut, GLint *rowStrideOut)
539{
540   const OSMesaContext osmesa = OSMESA_CONTEXT(ctx);
541
542   if (rb->ClassID == OSMESA_RENDERBUFFER_CLASS) {
543      /* this is an OSMesa renderbuffer which wraps user memory */
544      struct swrast_renderbuffer *srb = swrast_renderbuffer(rb);
545      const GLuint bpp = _mesa_get_format_bytes(rb->Format);
546      GLint rowStride; /* in bytes */
547
548      if (osmesa->userRowLength)
549         rowStride = osmesa->userRowLength * bpp;
550      else
551         rowStride = rb->Width * bpp;
552
553      if (!osmesa->yup) {
554         /* Y=0 is top line of window */
555         y = rb->Height - y - 1;
556         *rowStrideOut = -rowStride;
557      }
558      else {
559         *rowStrideOut = rowStride;
560      }
561
562      *mapOut = (GLubyte *) srb->Buffer + y * rowStride + x * bpp;
563   }
564   else {
565      _swrast_map_soft_renderbuffer(ctx, rb, x, y, w, h, mode,
566                                    mapOut, rowStrideOut);
567   }
568}
569
570
571static void
572osmesa_UnmapRenderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
573{
574   if (rb->ClassID == OSMESA_RENDERBUFFER_CLASS) {
575      /* no-op */
576   }
577   else {
578      _swrast_unmap_soft_renderbuffer(ctx, rb);
579   }
580}
581
582
583/**********************************************************************/
584/*****                    Public Functions                        *****/
585/**********************************************************************/
586
587
588/**
589 * Create an Off-Screen Mesa rendering context.  The only attribute needed is
590 * an RGBA vs Color-Index mode flag.
591 *
592 * Input:  format - Must be GL_RGBA
593 *         sharelist - specifies another OSMesaContext with which to share
594 *                     display lists.  NULL indicates no sharing.
595 * Return:  an OSMesaContext or 0 if error
596 */
597GLAPI OSMesaContext GLAPIENTRY
598OSMesaCreateContext( GLenum format, OSMesaContext sharelist )
599{
600   return OSMesaCreateContextExt(format, DEFAULT_SOFTWARE_DEPTH_BITS,
601                                 8, 0, sharelist);
602}
603
604
605
606/**
607 * New in Mesa 3.5
608 *
609 * Create context and specify size of ancillary buffers.
610 */
611GLAPI OSMesaContext GLAPIENTRY
612OSMesaCreateContextExt( GLenum format, GLint depthBits, GLint stencilBits,
613                        GLint accumBits, OSMesaContext sharelist )
614{
615   OSMesaContext osmesa;
616   struct dd_function_table functions;
617   GLint rind, gind, bind, aind;
618   GLint redBits = 0, greenBits = 0, blueBits = 0, alphaBits =0;
619
620   rind = gind = bind = aind = 0;
621   if (format==OSMESA_RGBA) {
622      redBits = CHAN_BITS;
623      greenBits = CHAN_BITS;
624      blueBits = CHAN_BITS;
625      alphaBits = CHAN_BITS;
626      rind = 0;
627      gind = 1;
628      bind = 2;
629      aind = 3;
630   }
631   else if (format==OSMESA_BGRA) {
632      redBits = CHAN_BITS;
633      greenBits = CHAN_BITS;
634      blueBits = CHAN_BITS;
635      alphaBits = CHAN_BITS;
636      bind = 0;
637      gind = 1;
638      rind = 2;
639      aind = 3;
640   }
641   else if (format==OSMESA_ARGB) {
642      redBits = CHAN_BITS;
643      greenBits = CHAN_BITS;
644      blueBits = CHAN_BITS;
645      alphaBits = CHAN_BITS;
646      aind = 0;
647      rind = 1;
648      gind = 2;
649      bind = 3;
650   }
651   else if (format==OSMESA_RGB) {
652      redBits = CHAN_BITS;
653      greenBits = CHAN_BITS;
654      blueBits = CHAN_BITS;
655      alphaBits = 0;
656      rind = 0;
657      gind = 1;
658      bind = 2;
659   }
660   else if (format==OSMESA_BGR) {
661      redBits = CHAN_BITS;
662      greenBits = CHAN_BITS;
663      blueBits = CHAN_BITS;
664      alphaBits = 0;
665      rind = 2;
666      gind = 1;
667      bind = 0;
668   }
669#if CHAN_TYPE == GL_UNSIGNED_BYTE
670   else if (format==OSMESA_RGB_565) {
671      redBits = 5;
672      greenBits = 6;
673      blueBits = 5;
674      alphaBits = 0;
675      rind = 0; /* not used */
676      gind = 0;
677      bind = 0;
678   }
679#endif
680   else {
681      return NULL;
682   }
683
684   osmesa = (OSMesaContext) CALLOC_STRUCT(osmesa_context);
685   if (osmesa) {
686      osmesa->gl_visual = _mesa_create_visual( GL_FALSE,    /* double buffer */
687                                               GL_FALSE,    /* stereo */
688                                               redBits,
689                                               greenBits,
690                                               blueBits,
691                                               alphaBits,
692                                               depthBits,
693                                               stencilBits,
694                                               accumBits,
695                                               accumBits,
696                                               accumBits,
697                                               alphaBits ? accumBits : 0,
698                                               1            /* num samples */
699                                               );
700      if (!osmesa->gl_visual) {
701         free(osmesa);
702         return NULL;
703      }
704
705      /* Initialize device driver function table */
706      _mesa_init_driver_functions(&functions);
707      /* override with our functions */
708      functions.GetString = get_string;
709      functions.UpdateState = osmesa_update_state;
710      functions.GetBufferSize = NULL;
711
712      if (!_mesa_initialize_context(&osmesa->mesa,
713                                    API_OPENGL,
714                                    osmesa->gl_visual,
715                                    sharelist ? &sharelist->mesa
716                                              : (struct gl_context *) NULL,
717                                    &functions, (void *) osmesa)) {
718         _mesa_destroy_visual( osmesa->gl_visual );
719         free(osmesa);
720         return NULL;
721      }
722
723      _mesa_enable_sw_extensions(&(osmesa->mesa));
724      _mesa_enable_1_3_extensions(&(osmesa->mesa));
725      _mesa_enable_1_4_extensions(&(osmesa->mesa));
726      _mesa_enable_1_5_extensions(&(osmesa->mesa));
727      _mesa_enable_2_0_extensions(&(osmesa->mesa));
728      _mesa_enable_2_1_extensions(&(osmesa->mesa));
729
730      osmesa->gl_buffer = _mesa_create_framebuffer(osmesa->gl_visual);
731      if (!osmesa->gl_buffer) {
732         _mesa_destroy_visual( osmesa->gl_visual );
733         _mesa_free_context_data( &osmesa->mesa );
734         free(osmesa);
735         return NULL;
736      }
737
738      /* Create depth/stencil/accum buffers.  We'll create the color
739       * buffer later in OSMesaMakeCurrent().
740       */
741      _swrast_add_soft_renderbuffers(osmesa->gl_buffer,
742                                     GL_FALSE, /* color */
743                                     osmesa->gl_visual->haveDepthBuffer,
744                                     osmesa->gl_visual->haveStencilBuffer,
745                                     osmesa->gl_visual->haveAccumBuffer,
746                                     GL_FALSE, /* alpha */
747                                     GL_FALSE /* aux */ );
748
749      osmesa->format = format;
750      osmesa->userRowLength = 0;
751      osmesa->yup = GL_TRUE;
752      osmesa->rInd = rind;
753      osmesa->gInd = gind;
754      osmesa->bInd = bind;
755      osmesa->aInd = aind;
756
757      _mesa_meta_init(&osmesa->mesa);
758
759      /* Initialize the software rasterizer and helper modules. */
760      {
761	 struct gl_context *ctx = &osmesa->mesa;
762         SWcontext *swrast;
763         TNLcontext *tnl;
764
765	 if (!_swrast_CreateContext( ctx ) ||
766             !_vbo_CreateContext( ctx ) ||
767             !_tnl_CreateContext( ctx ) ||
768             !_swsetup_CreateContext( ctx )) {
769            _mesa_destroy_visual(osmesa->gl_visual);
770            _mesa_free_context_data(ctx);
771            free(osmesa);
772            return NULL;
773         }
774
775	 _swsetup_Wakeup( ctx );
776
777         /* use default TCL pipeline */
778         tnl = TNL_CONTEXT(ctx);
779         tnl->Driver.RunPipeline = _tnl_run_pipeline;
780
781         ctx->Driver.MapRenderbuffer = osmesa_MapRenderbuffer;
782         ctx->Driver.UnmapRenderbuffer = osmesa_UnmapRenderbuffer;
783
784         ctx->Driver.GenerateMipmap = _mesa_generate_mipmap;
785
786         /* Extend the software rasterizer with our optimized line and triangle
787          * drawing functions.
788          */
789         swrast = SWRAST_CONTEXT( ctx );
790         swrast->choose_line = osmesa_choose_line;
791         swrast->choose_triangle = osmesa_choose_triangle;
792      }
793   }
794   return osmesa;
795}
796
797
798/**
799 * Destroy an Off-Screen Mesa rendering context.
800 *
801 * \param osmesa  the context to destroy
802 */
803GLAPI void GLAPIENTRY
804OSMesaDestroyContext( OSMesaContext osmesa )
805{
806   if (osmesa) {
807      if (osmesa->srb)
808         _mesa_reference_renderbuffer((struct gl_renderbuffer **) &osmesa->srb, NULL);
809
810      _mesa_meta_free( &osmesa->mesa );
811
812      _swsetup_DestroyContext( &osmesa->mesa );
813      _tnl_DestroyContext( &osmesa->mesa );
814      _vbo_DestroyContext( &osmesa->mesa );
815      _swrast_DestroyContext( &osmesa->mesa );
816
817      _mesa_destroy_visual( osmesa->gl_visual );
818      _mesa_reference_framebuffer( &osmesa->gl_buffer, NULL );
819
820      _mesa_free_context_data( &osmesa->mesa );
821      free( osmesa );
822   }
823}
824
825
826/**
827 * Bind an OSMesaContext to an image buffer.  The image buffer is just a
828 * block of memory which the client provides.  Its size must be at least
829 * as large as width*height*sizeof(type).  Its address should be a multiple
830 * of 4 if using RGBA mode.
831 *
832 * Image data is stored in the order of glDrawPixels:  row-major order
833 * with the lower-left image pixel stored in the first array position
834 * (ie. bottom-to-top).
835 *
836 * If the context's viewport hasn't been initialized yet, it will now be
837 * initialized to (0,0,width,height).
838 *
839 * Input:  osmesa - the rendering context
840 *         buffer - the image buffer memory
841 *         type - data type for pixel components
842 *            Normally, only GL_UNSIGNED_BYTE and GL_UNSIGNED_SHORT_5_6_5
843 *            are supported.  But if Mesa's been compiled with CHAN_BITS==16
844 *            then type may be GL_UNSIGNED_SHORT or GL_UNSIGNED_BYTE.  And if
845 *            Mesa's been build with CHAN_BITS==32 then type may be GL_FLOAT,
846 *            GL_UNSIGNED_SHORT or GL_UNSIGNED_BYTE.
847 *         width, height - size of image buffer in pixels, at least 1
848 * Return:  GL_TRUE if success, GL_FALSE if error because of invalid osmesa,
849 *          invalid buffer address, invalid type, width<1, height<1,
850 *          width>internal limit or height>internal limit.
851 */
852GLAPI GLboolean GLAPIENTRY
853OSMesaMakeCurrent( OSMesaContext osmesa, void *buffer, GLenum type,
854                   GLsizei width, GLsizei height )
855{
856   if (!osmesa || !buffer ||
857       width < 1 || height < 1 ||
858       width > SWRAST_MAX_WIDTH || height > SWRAST_MAX_HEIGHT) {
859      return GL_FALSE;
860   }
861
862   if (osmesa->format == OSMESA_RGB_565 && type != GL_UNSIGNED_SHORT_5_6_5) {
863      return GL_FALSE;
864   }
865
866#if 0
867   if (!(type == GL_UNSIGNED_BYTE ||
868         (type == GL_UNSIGNED_SHORT && CHAN_BITS >= 16) ||
869         (type == GL_FLOAT && CHAN_BITS == 32))) {
870      /* i.e. is sizeof(type) * 8 > CHAN_BITS? */
871      return GL_FALSE;
872   }
873#endif
874
875   osmesa_update_state( &osmesa->mesa, 0 );
876
877   /* Call this periodically to detect when the user has begun using
878    * GL rendering from multiple threads.
879    */
880   _glapi_check_multithread();
881
882
883   /* Create a front/left color buffer which wraps the user-provided buffer.
884    * There is no back color buffer.
885    * If the user tries to use a 8, 16 or 32-bit/channel buffer that
886    * doesn't match what Mesa was compiled for (CHAN_BITS) the
887    * _mesa_add_renderbuffer() function will create a "wrapper" renderbuffer
888    * that converts rendering from CHAN_BITS to the user-requested channel
889    * size.
890    */
891   if (!osmesa->srb) {
892      osmesa->srb = new_osmesa_renderbuffer(&osmesa->mesa, osmesa->format, type);
893      _mesa_remove_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT);
894      _mesa_add_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT,
895                             &osmesa->srb->Base);
896      assert(osmesa->srb->Base.RefCount == 2);
897   }
898
899   osmesa->DataType = type;
900
901   /* Set renderbuffer fields.  Set width/height = 0 to force
902    * osmesa_renderbuffer_storage() being called by _mesa_resize_framebuffer()
903    */
904   osmesa->srb->Buffer = buffer;
905   osmesa->srb->Base.Width = osmesa->srb->Base.Height = 0;
906
907   /* Set the framebuffer's size.  This causes the
908    * osmesa_renderbuffer_storage() function to get called.
909    */
910   _mesa_resize_framebuffer(&osmesa->mesa, osmesa->gl_buffer, width, height);
911   osmesa->gl_buffer->Initialized = GL_TRUE; /* XXX TEMPORARY? */
912
913   _mesa_make_current( &osmesa->mesa, osmesa->gl_buffer, osmesa->gl_buffer );
914
915   /* Remove renderbuffer attachment, then re-add.  This installs the
916    * renderbuffer adaptor/wrapper if needed (for bpp conversion).
917    */
918   _mesa_remove_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT);
919   _mesa_add_renderbuffer(osmesa->gl_buffer, BUFFER_FRONT_LEFT,
920                          &osmesa->srb->Base);
921
922
923   /* this updates the visual's red/green/blue/alphaBits fields */
924   _mesa_update_framebuffer_visual(&osmesa->mesa, osmesa->gl_buffer);
925
926   /* update the framebuffer size */
927   _mesa_resize_framebuffer(&osmesa->mesa, osmesa->gl_buffer, width, height);
928
929   return GL_TRUE;
930}
931
932
933
934GLAPI OSMesaContext GLAPIENTRY
935OSMesaGetCurrentContext( void )
936{
937   struct gl_context *ctx = _mesa_get_current_context();
938   if (ctx)
939      return (OSMesaContext) ctx;
940   else
941      return NULL;
942}
943
944
945
946GLAPI void GLAPIENTRY
947OSMesaPixelStore( GLint pname, GLint value )
948{
949   OSMesaContext osmesa = OSMesaGetCurrentContext();
950
951   switch (pname) {
952      case OSMESA_ROW_LENGTH:
953         if (value<0) {
954            _mesa_error( &osmesa->mesa, GL_INVALID_VALUE,
955                      "OSMesaPixelStore(value)" );
956            return;
957         }
958         osmesa->userRowLength = value;
959         break;
960      case OSMESA_Y_UP:
961         osmesa->yup = value ? GL_TRUE : GL_FALSE;
962         break;
963      default:
964         _mesa_error( &osmesa->mesa, GL_INVALID_ENUM, "OSMesaPixelStore(pname)" );
965         return;
966   }
967
968   compute_row_addresses( osmesa );
969}
970
971
972GLAPI void GLAPIENTRY
973OSMesaGetIntegerv( GLint pname, GLint *value )
974{
975   OSMesaContext osmesa = OSMesaGetCurrentContext();
976
977   switch (pname) {
978      case OSMESA_WIDTH:
979         if (osmesa->gl_buffer)
980            *value = osmesa->gl_buffer->Width;
981         else
982            *value = 0;
983         return;
984      case OSMESA_HEIGHT:
985         if (osmesa->gl_buffer)
986            *value = osmesa->gl_buffer->Height;
987         else
988            *value = 0;
989         return;
990      case OSMESA_FORMAT:
991         *value = osmesa->format;
992         return;
993      case OSMESA_TYPE:
994         /* current color buffer's data type */
995         *value = osmesa->DataType;
996         return;
997      case OSMESA_ROW_LENGTH:
998         *value = osmesa->userRowLength;
999         return;
1000      case OSMESA_Y_UP:
1001         *value = osmesa->yup;
1002         return;
1003      case OSMESA_MAX_WIDTH:
1004         *value = SWRAST_MAX_WIDTH;
1005         return;
1006      case OSMESA_MAX_HEIGHT:
1007         *value = SWRAST_MAX_HEIGHT;
1008         return;
1009      default:
1010         _mesa_error(&osmesa->mesa, GL_INVALID_ENUM, "OSMesaGetIntergerv(pname)");
1011         return;
1012   }
1013}
1014
1015
1016/**
1017 * Return the depth buffer associated with an OSMesa context.
1018 * Input:  c - the OSMesa context
1019 * Output:  width, height - size of buffer in pixels
1020 *          bytesPerValue - bytes per depth value (2 or 4)
1021 *          buffer - pointer to depth buffer values
1022 * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
1023 */
1024GLAPI GLboolean GLAPIENTRY
1025OSMesaGetDepthBuffer( OSMesaContext c, GLint *width, GLint *height,
1026                      GLint *bytesPerValue, void **buffer )
1027{
1028   struct swrast_renderbuffer *srb = NULL;
1029
1030   if (c->gl_buffer)
1031      srb = swrast_renderbuffer(c->gl_buffer->
1032                                Attachment[BUFFER_DEPTH].Renderbuffer);
1033
1034   if (!srb || !srb->Buffer) {
1035      *width = 0;
1036      *height = 0;
1037      *bytesPerValue = 0;
1038      *buffer = 0;
1039      return GL_FALSE;
1040   }
1041   else {
1042      *width = srb->Base.Width;
1043      *height = srb->Base.Height;
1044      if (c->gl_visual->depthBits <= 16)
1045         *bytesPerValue = sizeof(GLushort);
1046      else
1047         *bytesPerValue = sizeof(GLuint);
1048      *buffer = (void *) srb->Buffer;
1049      return GL_TRUE;
1050   }
1051}
1052
1053
1054/**
1055 * Return the color buffer associated with an OSMesa context.
1056 * Input:  c - the OSMesa context
1057 * Output:  width, height - size of buffer in pixels
1058 *          format - the pixel format (OSMESA_FORMAT)
1059 *          buffer - pointer to color buffer values
1060 * Return:  GL_TRUE or GL_FALSE to indicate success or failure.
1061 */
1062GLAPI GLboolean GLAPIENTRY
1063OSMesaGetColorBuffer( OSMesaContext osmesa, GLint *width,
1064                      GLint *height, GLint *format, void **buffer )
1065{
1066   if (osmesa->srb && osmesa->srb->Buffer) {
1067      *width = osmesa->srb->Base.Width;
1068      *height = osmesa->srb->Base.Height;
1069      *format = osmesa->format;
1070      *buffer = (void *) osmesa->srb->Buffer;
1071      return GL_TRUE;
1072   }
1073   else {
1074      *width = 0;
1075      *height = 0;
1076      *format = 0;
1077      *buffer = 0;
1078      return GL_FALSE;
1079   }
1080}
1081
1082
1083struct name_function
1084{
1085   const char *Name;
1086   OSMESAproc Function;
1087};
1088
1089static struct name_function functions[] = {
1090   { "OSMesaCreateContext", (OSMESAproc) OSMesaCreateContext },
1091   { "OSMesaCreateContextExt", (OSMESAproc) OSMesaCreateContextExt },
1092   { "OSMesaDestroyContext", (OSMESAproc) OSMesaDestroyContext },
1093   { "OSMesaMakeCurrent", (OSMESAproc) OSMesaMakeCurrent },
1094   { "OSMesaGetCurrentContext", (OSMESAproc) OSMesaGetCurrentContext },
1095   { "OSMesaPixelsStore", (OSMESAproc) OSMesaPixelStore },
1096   { "OSMesaGetIntegerv", (OSMESAproc) OSMesaGetIntegerv },
1097   { "OSMesaGetDepthBuffer", (OSMESAproc) OSMesaGetDepthBuffer },
1098   { "OSMesaGetColorBuffer", (OSMESAproc) OSMesaGetColorBuffer },
1099   { "OSMesaGetProcAddress", (OSMESAproc) OSMesaGetProcAddress },
1100   { "OSMesaColorClamp", (OSMESAproc) OSMesaColorClamp },
1101   { NULL, NULL }
1102};
1103
1104
1105GLAPI OSMESAproc GLAPIENTRY
1106OSMesaGetProcAddress( const char *funcName )
1107{
1108   int i;
1109   for (i = 0; functions[i].Name; i++) {
1110      if (strcmp(functions[i].Name, funcName) == 0)
1111         return functions[i].Function;
1112   }
1113   return _glapi_get_proc_address(funcName);
1114}
1115
1116
1117GLAPI void GLAPIENTRY
1118OSMesaColorClamp(GLboolean enable)
1119{
1120   OSMesaContext osmesa = OSMesaGetCurrentContext();
1121
1122   if (enable == GL_TRUE) {
1123      osmesa->mesa.Color.ClampFragmentColor = GL_TRUE;
1124   }
1125   else {
1126      osmesa->mesa.Color.ClampFragmentColor = GL_FIXED_ONLY_ARB;
1127   }
1128}
1129
1130
1131/**
1132 * When GLX_INDIRECT_RENDERING is defined, some symbols are missing in
1133 * libglapi.a.  We need to define them here.
1134 */
1135#ifdef GLX_INDIRECT_RENDERING
1136
1137#define GL_GLEXT_PROTOTYPES
1138#include "GL/gl.h"
1139#include "glapi/glapi.h"
1140#include "glapi/glapitable.h"
1141
1142#if defined(USE_MGL_NAMESPACE)
1143#define NAME(func)  mgl##func
1144#else
1145#define NAME(func)  gl##func
1146#endif
1147
1148#define DISPATCH(FUNC, ARGS, MESSAGE)		\
1149   GET_DISPATCH()->FUNC ARGS
1150
1151#define RETURN_DISPATCH(FUNC, ARGS, MESSAGE) 	\
1152   return GET_DISPATCH()->FUNC ARGS
1153
1154/* skip normal ones */
1155#define _GLAPI_SKIP_NORMAL_ENTRY_POINTS
1156#include "glapi/glapitemp.h"
1157
1158#endif /* GLX_INDIRECT_RENDERING */
1159