Home | History | Annotate | Download | only in osmesa
      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  */
     67 struct 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 
     83 static INLINE OSMesaContext
     84 OSMESA_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 
     96 static const GLubyte *
     97 get_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 
    115 static void
    116 osmesa_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)	\
    133 do {					\
    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)						\
    153 do {								\
    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)					\
    174 do {							\
    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  */
    191 static swrast_line_func
    192 osmesa_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  */
    292 static swrast_tri_func
    293 osmesa_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  */
    329 static void
    330 osmesa_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 
    339 static void
    340 osmesa_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  */
    354 static void
    355 compute_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  */
    389 static void
    390 osmesa_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  */
    401 static GLboolean
    402 osmesa_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  */
    509 static struct swrast_renderbuffer *
    510 new_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 
    533 static void
    534 osmesa_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 
    571 static void
    572 osmesa_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  */
    597 GLAPI OSMesaContext GLAPIENTRY
    598 OSMesaCreateContext( 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  */
    611 GLAPI OSMesaContext GLAPIENTRY
    612 OSMesaCreateContextExt( 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  */
    803 GLAPI void GLAPIENTRY
    804 OSMesaDestroyContext( 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  */
    852 GLAPI GLboolean GLAPIENTRY
    853 OSMesaMakeCurrent( 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 
    934 GLAPI OSMesaContext GLAPIENTRY
    935 OSMesaGetCurrentContext( 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 
    946 GLAPI void GLAPIENTRY
    947 OSMesaPixelStore( 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 
    972 GLAPI void GLAPIENTRY
    973 OSMesaGetIntegerv( 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  */
   1024 GLAPI GLboolean GLAPIENTRY
   1025 OSMesaGetDepthBuffer( 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  */
   1062 GLAPI GLboolean GLAPIENTRY
   1063 OSMesaGetColorBuffer( 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 
   1083 struct name_function
   1084 {
   1085    const char *Name;
   1086    OSMESAproc Function;
   1087 };
   1088 
   1089 static 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 
   1105 GLAPI OSMESAproc GLAPIENTRY
   1106 OSMesaGetProcAddress( 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 
   1117 GLAPI void GLAPIENTRY
   1118 OSMesaColorClamp(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