Home | History | Annotate | Download | only in xlib
      1 /*
      2  * Mesa 3-D graphics library
      3  * Version:  7.6
      4  *
      5  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
      6  * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
      7  *
      8  * Permission is hereby granted, free of charge, to any person obtaining a
      9  * copy of this software and associated documentation files (the "Software"),
     10  * to deal in the Software without restriction, including without limitation
     11  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     12  * and/or sell copies of the Software, and to permit persons to whom the
     13  * Software is furnished to do so, subject to the following conditions:
     14  *
     15  * The above copyright notice and this permission notice shall be included
     16  * in all copies or substantial portions of the Software.
     17  *
     18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     21  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     22  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     23  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     24  */
     25 
     26 
     27 /**
     28  * "Fake" GLX API implemented in terms of the XMesa*() functions.
     29  */
     30 
     31 
     32 
     33 #define GLX_GLXEXT_PROTOTYPES
     34 #include "GL/glx.h"
     35 
     36 #include "xm_api.h"
     37 
     38 
     39 /* This indicates the client-side GLX API and GLX encoder version. */
     40 #define CLIENT_MAJOR_VERSION 1
     41 #define CLIENT_MINOR_VERSION 4  /* but don't have 1.3's pbuffers, etc yet */
     42 
     43 /* This indicates the server-side GLX decoder version.
     44  * GLX 1.4 indicates OpenGL 1.3 support
     45  */
     46 #define SERVER_MAJOR_VERSION 1
     47 #define SERVER_MINOR_VERSION 4
     48 
     49 /* Who implemented this GLX? */
     50 #define VENDOR "Brian Paul"
     51 
     52 #define EXTENSIONS \
     53    "GLX_MESA_copy_sub_buffer " \
     54    "GLX_MESA_pixmap_colormap " \
     55    "GLX_MESA_release_buffers " \
     56    "GLX_ARB_create_context " \
     57    "GLX_ARB_create_context_profile " \
     58    "GLX_ARB_get_proc_address " \
     59    "GLX_EXT_texture_from_pixmap " \
     60    "GLX_EXT_visual_info " \
     61    "GLX_EXT_visual_rating " \
     62    /*"GLX_SGI_video_sync "*/ \
     63    "GLX_SGIX_fbconfig " \
     64    "GLX_SGIX_pbuffer "
     65 
     66 #define DEFAULT_DIRECT GL_TRUE
     67 
     68 
     69 /** XXX this could be based on gallium's max texture size */
     70 #define PBUFFER_MAX_SIZE 16384
     71 
     72 
     73 /**
     74  * The GLXContext typedef is defined as a pointer to this structure.
     75  */
     76 struct __GLXcontextRec
     77 {
     78    Display *currentDpy;
     79    GLboolean isDirect;
     80    GLXDrawable currentDrawable;
     81    GLXDrawable currentReadable;
     82    XID xid;
     83 
     84    XMesaContext xmesaContext;
     85 };
     86 
     87 
     88 
     89 static pipe_tsd ContextTSD;
     90 
     91 /** Set current context for calling thread */
     92 static void
     93 SetCurrentContext(GLXContext c)
     94 {
     95    pipe_tsd_set(&ContextTSD, c);
     96 }
     97 
     98 /** Get current context for calling thread */
     99 static GLXContext
    100 GetCurrentContext(void)
    101 {
    102    return pipe_tsd_get(&ContextTSD);
    103 }
    104 
    105 
    106 
    107 /**********************************************************************/
    108 /***                       GLX Visual Code                          ***/
    109 /**********************************************************************/
    110 
    111 #define DONT_CARE -1
    112 
    113 
    114 static XMesaVisual *VisualTable = NULL;
    115 static int NumVisuals = 0;
    116 
    117 
    118 
    119 /* Macro to handle c_class vs class field name in XVisualInfo struct */
    120 #if defined(__cplusplus) || defined(c_plusplus)
    121 #define CLASS c_class
    122 #else
    123 #define CLASS class
    124 #endif
    125 
    126 
    127 
    128 /*
    129  * Test if the given XVisualInfo is usable for Mesa rendering.
    130  */
    131 static GLboolean
    132 is_usable_visual( XVisualInfo *vinfo )
    133 {
    134    switch (vinfo->CLASS) {
    135       case StaticGray:
    136       case GrayScale:
    137          /* Any StaticGray/GrayScale visual works in RGB or CI mode */
    138          return GL_TRUE;
    139       case StaticColor:
    140       case PseudoColor:
    141 	 /* Any StaticColor/PseudoColor visual of at least 4 bits */
    142 	 if (vinfo->depth>=4) {
    143 	    return GL_TRUE;
    144 	 }
    145 	 else {
    146 	    return GL_FALSE;
    147 	 }
    148       case TrueColor:
    149       case DirectColor:
    150 	 /* Any depth of TrueColor or DirectColor works in RGB mode */
    151 	 return GL_TRUE;
    152       default:
    153 	 /* This should never happen */
    154 	 return GL_FALSE;
    155    }
    156 }
    157 
    158 
    159 /*
    160  * Given an XVisualInfo and RGB, Double, and Depth buffer flags, save the
    161  * configuration in our list of GLX visuals.
    162  */
    163 static XMesaVisual
    164 save_glx_visual( Display *dpy, XVisualInfo *vinfo,
    165                  GLboolean rgbFlag, GLboolean alphaFlag, GLboolean dbFlag,
    166                  GLboolean stereoFlag,
    167                  GLint depth_size, GLint stencil_size,
    168                  GLint accumRedSize, GLint accumGreenSize,
    169                  GLint accumBlueSize, GLint accumAlphaSize,
    170                  GLint level, GLint numAuxBuffers )
    171 {
    172    GLboolean ximageFlag = GL_TRUE;
    173    XMesaVisual xmvis;
    174    GLint i;
    175    GLboolean comparePointers;
    176 
    177    if (dbFlag) {
    178       /* Check if the MESA_BACK_BUFFER env var is set */
    179       char *backbuffer = _mesa_getenv("MESA_BACK_BUFFER");
    180       if (backbuffer) {
    181          if (backbuffer[0]=='p' || backbuffer[0]=='P') {
    182             ximageFlag = GL_FALSE;
    183          }
    184          else if (backbuffer[0]=='x' || backbuffer[0]=='X') {
    185             ximageFlag = GL_TRUE;
    186          }
    187          else {
    188             _mesa_warning(NULL, "Mesa: invalid value for MESA_BACK_BUFFER environment variable, using an XImage.");
    189          }
    190       }
    191    }
    192 
    193    if (stereoFlag) {
    194       /* stereo not supported */
    195       return NULL;
    196    }
    197 
    198    if (stencil_size > 0 && depth_size > 0)
    199       depth_size = 24;
    200 
    201    /* Comparing IDs uses less memory but sometimes fails. */
    202    /* XXX revisit this after 3.0 is finished. */
    203    if (_mesa_getenv("MESA_GLX_VISUAL_HACK"))
    204       comparePointers = GL_TRUE;
    205    else
    206       comparePointers = GL_FALSE;
    207 
    208    /* Force the visual to have an alpha channel */
    209    if (rgbFlag && _mesa_getenv("MESA_GLX_FORCE_ALPHA"))
    210       alphaFlag = GL_TRUE;
    211 
    212    /* First check if a matching visual is already in the list */
    213    for (i=0; i<NumVisuals; i++) {
    214       XMesaVisual v = VisualTable[i];
    215       if (v->display == dpy
    216           && v->mesa_visual.level == level
    217           && v->mesa_visual.numAuxBuffers == numAuxBuffers
    218           && v->ximage_flag == ximageFlag
    219           && v->mesa_visual.rgbMode == rgbFlag
    220           && v->mesa_visual.doubleBufferMode == dbFlag
    221           && v->mesa_visual.stereoMode == stereoFlag
    222           && (v->mesa_visual.alphaBits > 0) == alphaFlag
    223           && (v->mesa_visual.depthBits >= depth_size || depth_size == 0)
    224           && (v->mesa_visual.stencilBits >= stencil_size || stencil_size == 0)
    225           && (v->mesa_visual.accumRedBits >= accumRedSize || accumRedSize == 0)
    226           && (v->mesa_visual.accumGreenBits >= accumGreenSize || accumGreenSize == 0)
    227           && (v->mesa_visual.accumBlueBits >= accumBlueSize || accumBlueSize == 0)
    228           && (v->mesa_visual.accumAlphaBits >= accumAlphaSize || accumAlphaSize == 0)) {
    229          /* now either compare XVisualInfo pointers or visual IDs */
    230          if ((!comparePointers && v->visinfo->visualid == vinfo->visualid)
    231              || (comparePointers && v->vishandle == vinfo)) {
    232             return v;
    233          }
    234       }
    235    }
    236 
    237    /* Create a new visual and add it to the list. */
    238 
    239    xmvis = XMesaCreateVisual( dpy, vinfo, rgbFlag, alphaFlag, dbFlag,
    240                               stereoFlag, ximageFlag,
    241                               depth_size, stencil_size,
    242                               accumRedSize, accumBlueSize,
    243                               accumBlueSize, accumAlphaSize, 0, level,
    244                               GLX_NONE_EXT );
    245    if (xmvis) {
    246       /* Save a copy of the pointer now so we can find this visual again
    247        * if we need to search for it in find_glx_visual().
    248        */
    249       xmvis->vishandle = vinfo;
    250       /* Allocate more space for additional visual */
    251       VisualTable = (XMesaVisual *) _mesa_realloc( VisualTable,
    252                                    sizeof(XMesaVisual) * NumVisuals,
    253                                    sizeof(XMesaVisual) * (NumVisuals + 1));
    254       /* add xmvis to the list */
    255       VisualTable[NumVisuals] = xmvis;
    256       NumVisuals++;
    257       /* XXX minor hack, because XMesaCreateVisual doesn't support an
    258        * aux buffers parameter.
    259        */
    260       xmvis->mesa_visual.numAuxBuffers = numAuxBuffers;
    261    }
    262    return xmvis;
    263 }
    264 
    265 
    266 /**
    267  * Return the default number of bits for the Z buffer.
    268  * If defined, use the MESA_GLX_DEPTH_BITS env var value.
    269  * Otherwise, use the DEFAULT_SOFTWARE_DEPTH_BITS constant.
    270  * XXX probably do the same thing for stencil, accum, etc.
    271  */
    272 static GLint
    273 default_depth_bits(void)
    274 {
    275    int zBits;
    276    const char *zEnv = _mesa_getenv("MESA_GLX_DEPTH_BITS");
    277    if (zEnv)
    278       zBits = atoi(zEnv);
    279    else
    280       zBits = 24;
    281    return zBits;
    282 }
    283 
    284 static GLint
    285 default_alpha_bits(void)
    286 {
    287    int aBits;
    288    const char *aEnv = _mesa_getenv("MESA_GLX_ALPHA_BITS");
    289    if (aEnv)
    290       aBits = atoi(aEnv);
    291    else
    292       aBits = 0;
    293    return aBits;
    294 }
    295 
    296 static GLint
    297 default_accum_bits(void)
    298 {
    299    return 16;
    300 }
    301 
    302 
    303 
    304 /*
    305  * Create a GLX visual from a regular XVisualInfo.
    306  * This is called when Fake GLX is given an XVisualInfo which wasn't
    307  * returned by glXChooseVisual.  Since this is the first time we're
    308  * considering this visual we'll take a guess at reasonable values
    309  * for depth buffer size, stencil size, accum size, etc.
    310  * This is the best we can do with a client-side emulation of GLX.
    311  */
    312 static XMesaVisual
    313 create_glx_visual( Display *dpy, XVisualInfo *visinfo )
    314 {
    315    GLint zBits = default_depth_bits();
    316    GLint accBits = default_accum_bits();
    317    GLboolean alphaFlag = default_alpha_bits() > 0;
    318 
    319    if (is_usable_visual( visinfo )) {
    320       /* Configure this visual as RGB, double-buffered, depth-buffered. */
    321       /* This is surely wrong for some people's needs but what else */
    322       /* can be done?  They should use glXChooseVisual(). */
    323       return save_glx_visual( dpy, visinfo,
    324                               GL_TRUE,   /* rgb */
    325                               alphaFlag, /* alpha */
    326                               GL_TRUE,   /* double */
    327                               GL_FALSE,  /* stereo */
    328                               zBits,
    329                               8,       /* stencil bits */
    330                               accBits, /* r */
    331                               accBits, /* g */
    332                               accBits, /* b */
    333                               accBits, /* a */
    334                               0,         /* level */
    335                               0          /* numAux */
    336          );
    337    }
    338    else {
    339       _mesa_warning(NULL, "Mesa: error in glXCreateContext: bad visual\n");
    340       return NULL;
    341    }
    342 }
    343 
    344 
    345 
    346 /*
    347  * Find the GLX visual associated with an XVisualInfo.
    348  */
    349 static XMesaVisual
    350 find_glx_visual( Display *dpy, XVisualInfo *vinfo )
    351 {
    352    int i;
    353 
    354    /* try to match visual id */
    355    for (i=0;i<NumVisuals;i++) {
    356       if (VisualTable[i]->display==dpy
    357           && VisualTable[i]->visinfo->visualid == vinfo->visualid) {
    358          return VisualTable[i];
    359       }
    360    }
    361 
    362    /* if that fails, try to match pointers */
    363    for (i=0;i<NumVisuals;i++) {
    364       if (VisualTable[i]->display==dpy && VisualTable[i]->vishandle==vinfo) {
    365          return VisualTable[i];
    366       }
    367    }
    368 
    369    return NULL;
    370 }
    371 
    372 
    373 /**
    374  * Try to get an X visual which matches the given arguments.
    375  */
    376 static XVisualInfo *
    377 get_visual( Display *dpy, int scr, unsigned int depth, int xclass )
    378 {
    379    XVisualInfo temp, *vis;
    380    long mask;
    381    int n;
    382    unsigned int default_depth;
    383    int default_class;
    384 
    385    mask = VisualScreenMask | VisualDepthMask | VisualClassMask;
    386    temp.screen = scr;
    387    temp.depth = depth;
    388    temp.CLASS = xclass;
    389 
    390    default_depth = DefaultDepth(dpy,scr);
    391    default_class = DefaultVisual(dpy,scr)->CLASS;
    392 
    393    if (depth==default_depth && xclass==default_class) {
    394       /* try to get root window's visual */
    395       temp.visualid = DefaultVisual(dpy,scr)->visualid;
    396       mask |= VisualIDMask;
    397    }
    398 
    399    vis = XGetVisualInfo( dpy, mask, &temp, &n );
    400 
    401    /* In case bits/pixel > 24, make sure color channels are still <=8 bits.
    402     * An SGI Infinite Reality system, for example, can have 30bpp pixels:
    403     * 10 bits per color channel.  Mesa's limited to a max of 8 bits/channel.
    404     */
    405    if (vis && depth > 24 && (xclass==TrueColor || xclass==DirectColor)) {
    406       if (_mesa_bitcount((GLuint) vis->red_mask  ) <= 8 &&
    407           _mesa_bitcount((GLuint) vis->green_mask) <= 8 &&
    408           _mesa_bitcount((GLuint) vis->blue_mask ) <= 8) {
    409          return vis;
    410       }
    411       else {
    412          XFree((void *) vis);
    413          return NULL;
    414       }
    415    }
    416 
    417    return vis;
    418 }
    419 
    420 
    421 /*
    422  * Retrieve the value of the given environment variable and find
    423  * the X visual which matches it.
    424  * Input:  dpy - the display
    425  *         screen - the screen number
    426  *         varname - the name of the environment variable
    427  * Return:  an XVisualInfo pointer to NULL if error.
    428  */
    429 static XVisualInfo *
    430 get_env_visual(Display *dpy, int scr, const char *varname)
    431 {
    432    char value[100], type[100];
    433    int depth, xclass = -1;
    434    XVisualInfo *vis;
    435 
    436    if (!_mesa_getenv( varname )) {
    437       return NULL;
    438    }
    439 
    440    strncpy( value, _mesa_getenv(varname), 100 );
    441    value[99] = 0;
    442 
    443    sscanf( value, "%s %d", type, &depth );
    444 
    445    if (strcmp(type,"TrueColor")==0)          xclass = TrueColor;
    446    else if (strcmp(type,"DirectColor")==0)   xclass = DirectColor;
    447    else if (strcmp(type,"PseudoColor")==0)   xclass = PseudoColor;
    448    else if (strcmp(type,"StaticColor")==0)   xclass = StaticColor;
    449    else if (strcmp(type,"GrayScale")==0)     xclass = GrayScale;
    450    else if (strcmp(type,"StaticGray")==0)    xclass = StaticGray;
    451 
    452    if (xclass>-1 && depth>0) {
    453       vis = get_visual( dpy, scr, depth, xclass );
    454       if (vis) {
    455 	 return vis;
    456       }
    457    }
    458 
    459    _mesa_warning(NULL, "GLX unable to find visual class=%s, depth=%d.",
    460                  type, depth);
    461 
    462    return NULL;
    463 }
    464 
    465 
    466 
    467 /*
    468  * Select an X visual which satisfies the RGBA flag and minimum depth.
    469  * Input:  dpy,
    470  *         screen - X display and screen number
    471  *         min_depth - minimum visual depth
    472  *         preferred_class - preferred GLX visual class or DONT_CARE
    473  * Return:  pointer to an XVisualInfo or NULL.
    474  */
    475 static XVisualInfo *
    476 choose_x_visual( Display *dpy, int screen, int min_depth,
    477                  int preferred_class )
    478 {
    479    XVisualInfo *vis;
    480    int xclass, visclass = 0;
    481    int depth;
    482 
    483    /* First see if the MESA_RGB_VISUAL env var is defined */
    484    vis = get_env_visual( dpy, screen, "MESA_RGB_VISUAL" );
    485    if (vis) {
    486       return vis;
    487    }
    488    /* Otherwise, search for a suitable visual */
    489    if (preferred_class==DONT_CARE) {
    490       for (xclass=0;xclass<6;xclass++) {
    491          switch (xclass) {
    492          case 0:  visclass = TrueColor;    break;
    493          case 1:  visclass = DirectColor;  break;
    494          case 2:  visclass = PseudoColor;  break;
    495          case 3:  visclass = StaticColor;  break;
    496          case 4:  visclass = GrayScale;    break;
    497          case 5:  visclass = StaticGray;   break;
    498          }
    499          if (min_depth==0) {
    500             /* start with shallowest */
    501             for (depth=0;depth<=32;depth++) {
    502                if (visclass==TrueColor && depth==8) {
    503                   /* Special case:  try to get 8-bit PseudoColor before */
    504                   /* 8-bit TrueColor */
    505                   vis = get_visual( dpy, screen, 8, PseudoColor );
    506                   if (vis) {
    507                      return vis;
    508                   }
    509                }
    510                vis = get_visual( dpy, screen, depth, visclass );
    511                if (vis) {
    512                   return vis;
    513                }
    514             }
    515          }
    516          else {
    517             /* start with deepest */
    518             for (depth=32;depth>=min_depth;depth--) {
    519                if (visclass==TrueColor && depth==8) {
    520                   /* Special case:  try to get 8-bit PseudoColor before */
    521                   /* 8-bit TrueColor */
    522                   vis = get_visual( dpy, screen, 8, PseudoColor );
    523                   if (vis) {
    524                      return vis;
    525                   }
    526                }
    527                vis = get_visual( dpy, screen, depth, visclass );
    528                if (vis) {
    529                   return vis;
    530                }
    531             }
    532          }
    533       }
    534    }
    535    else {
    536       /* search for a specific visual class */
    537       switch (preferred_class) {
    538       case GLX_TRUE_COLOR_EXT:    visclass = TrueColor;    break;
    539       case GLX_DIRECT_COLOR_EXT:  visclass = DirectColor;  break;
    540       case GLX_PSEUDO_COLOR_EXT:  visclass = PseudoColor;  break;
    541       case GLX_STATIC_COLOR_EXT:  visclass = StaticColor;  break;
    542       case GLX_GRAY_SCALE_EXT:    visclass = GrayScale;    break;
    543       case GLX_STATIC_GRAY_EXT:   visclass = StaticGray;   break;
    544       default:   return NULL;
    545       }
    546       if (min_depth==0) {
    547          /* start with shallowest */
    548          for (depth=0;depth<=32;depth++) {
    549             vis = get_visual( dpy, screen, depth, visclass );
    550             if (vis) {
    551                return vis;
    552             }
    553          }
    554       }
    555       else {
    556          /* start with deepest */
    557          for (depth=32;depth>=min_depth;depth--) {
    558             vis = get_visual( dpy, screen, depth, visclass );
    559             if (vis) {
    560                return vis;
    561             }
    562          }
    563       }
    564    }
    565 
    566    /* didn't find a visual */
    567    return NULL;
    568 }
    569 
    570 
    571 
    572 
    573 /**********************************************************************/
    574 /***             Display-related functions                          ***/
    575 /**********************************************************************/
    576 
    577 
    578 /**
    579  * Free all XMesaVisuals which are associated with the given display.
    580  */
    581 static void
    582 destroy_visuals_on_display(Display *dpy)
    583 {
    584    int i;
    585    for (i = 0; i < NumVisuals; i++) {
    586       if (VisualTable[i]->display == dpy) {
    587          /* remove this visual */
    588          int j;
    589          free(VisualTable[i]);
    590          for (j = i; j < NumVisuals - 1; j++)
    591             VisualTable[j] = VisualTable[j + 1];
    592          NumVisuals--;
    593       }
    594    }
    595 }
    596 
    597 
    598 /**
    599  * Called from XCloseDisplay() to let us free our display-related data.
    600  */
    601 static int
    602 close_display_callback(Display *dpy, XExtCodes *codes)
    603 {
    604    xmesa_destroy_buffers_on_display(dpy);
    605    destroy_visuals_on_display(dpy);
    606    return 0;
    607 }
    608 
    609 
    610 /**
    611  * Look for the named extension on given display and return a pointer
    612  * to the _XExtension data, or NULL if extension not found.
    613  */
    614 static _XExtension *
    615 lookup_extension(Display *dpy, const char *extName)
    616 {
    617    _XExtension *ext;
    618    for (ext = dpy->ext_procs; ext; ext = ext->next) {
    619       if (ext->name && strcmp(ext->name, extName) == 0) {
    620          return ext;
    621       }
    622    }
    623    return NULL;
    624 }
    625 
    626 
    627 /**
    628  * Whenever we're given a new Display pointer, call this function to
    629  * register our close_display_callback function.
    630  */
    631 static void
    632 register_with_display(Display *dpy)
    633 {
    634    const char *extName = "MesaGLX";
    635    _XExtension *ext;
    636 
    637    ext = lookup_extension(dpy, extName);
    638    if (!ext) {
    639       XExtCodes *c = XAddExtension(dpy);
    640       ext = dpy->ext_procs;  /* new extension is at head of list */
    641       assert(c->extension == ext->codes.extension);
    642       (void) c;
    643       ext->name = _mesa_strdup(extName);
    644       ext->close_display = close_display_callback;
    645    }
    646 }
    647 
    648 
    649 /**********************************************************************/
    650 /***                  Begin Fake GLX API Functions                  ***/
    651 /**********************************************************************/
    652 
    653 
    654 /**
    655  * Helper used by glXChooseVisual and glXChooseFBConfig.
    656  * The fbConfig parameter must be GL_FALSE for the former and GL_TRUE for
    657  * the later.
    658  * In either case, the attribute list is terminated with the value 'None'.
    659  */
    660 static XMesaVisual
    661 choose_visual( Display *dpy, int screen, const int *list, GLboolean fbConfig )
    662 {
    663    const GLboolean rgbModeDefault = fbConfig;
    664    const int *parselist;
    665    XVisualInfo *vis;
    666    int min_red=0, min_green=0, min_blue=0;
    667    GLboolean rgb_flag = rgbModeDefault;
    668    GLboolean alpha_flag = GL_FALSE;
    669    GLboolean double_flag = GL_FALSE;
    670    GLboolean stereo_flag = GL_FALSE;
    671    GLint depth_size = 0;
    672    GLint stencil_size = 0;
    673    GLint accumRedSize = 0;
    674    GLint accumGreenSize = 0;
    675    GLint accumBlueSize = 0;
    676    GLint accumAlphaSize = 0;
    677    int level = 0;
    678    int visual_type = DONT_CARE;
    679    GLint caveat = DONT_CARE;
    680    XMesaVisual xmvis = NULL;
    681    int desiredVisualID = -1;
    682    int numAux = 0;
    683 
    684    xmesa_init( dpy );
    685 
    686    parselist = list;
    687 
    688    while (*parselist) {
    689 
    690       if (fbConfig &&
    691           parselist[1] == GLX_DONT_CARE &&
    692           parselist[0] != GLX_LEVEL) {
    693          /* For glXChooseFBConfig(), skip attributes whose value is
    694           * GLX_DONT_CARE, unless it's GLX_LEVEL (which can legitimately be
    695           * a negative value).
    696           *
    697           * From page 17 (23 of the pdf) of the GLX 1.4 spec:
    698           * GLX DONT CARE may be specified for all attributes except GLX LEVEL.
    699           */
    700          parselist += 2;
    701          continue;
    702       }
    703 
    704       switch (*parselist) {
    705 	 case GLX_USE_GL:
    706             if (fbConfig) {
    707                /* invalid token */
    708                return NULL;
    709             }
    710             else {
    711                /* skip */
    712                parselist++;
    713             }
    714 	    break;
    715 	 case GLX_BUFFER_SIZE:
    716 	    parselist++;
    717 	    parselist++;
    718 	    break;
    719 	 case GLX_LEVEL:
    720 	    parselist++;
    721             level = *parselist++;
    722 	    break;
    723 	 case GLX_RGBA:
    724             if (fbConfig) {
    725                /* invalid token */
    726                return NULL;
    727             }
    728             else {
    729                rgb_flag = GL_TRUE;
    730                parselist++;
    731             }
    732 	    break;
    733 	 case GLX_DOUBLEBUFFER:
    734             parselist++;
    735             if (fbConfig) {
    736                double_flag = *parselist++;
    737             }
    738             else {
    739                double_flag = GL_TRUE;
    740             }
    741 	    break;
    742 	 case GLX_STEREO:
    743             parselist++;
    744             if (fbConfig) {
    745                stereo_flag = *parselist++;
    746             }
    747             else {
    748                stereo_flag = GL_TRUE;
    749             }
    750             break;
    751 	 case GLX_AUX_BUFFERS:
    752 	    parselist++;
    753             numAux = *parselist++;
    754             if (numAux > MAX_AUX_BUFFERS)
    755                return NULL;
    756 	    break;
    757 	 case GLX_RED_SIZE:
    758 	    parselist++;
    759 	    min_red = *parselist++;
    760 	    break;
    761 	 case GLX_GREEN_SIZE:
    762 	    parselist++;
    763 	    min_green = *parselist++;
    764 	    break;
    765 	 case GLX_BLUE_SIZE:
    766 	    parselist++;
    767 	    min_blue = *parselist++;
    768 	    break;
    769 	 case GLX_ALPHA_SIZE:
    770 	    parselist++;
    771             {
    772                GLint size = *parselist++;
    773                alpha_flag = size ? GL_TRUE : GL_FALSE;
    774             }
    775 	    break;
    776 	 case GLX_DEPTH_SIZE:
    777 	    parselist++;
    778 	    depth_size = *parselist++;
    779 	    break;
    780 	 case GLX_STENCIL_SIZE:
    781 	    parselist++;
    782 	    stencil_size = *parselist++;
    783 	    break;
    784 	 case GLX_ACCUM_RED_SIZE:
    785 	    parselist++;
    786             {
    787                GLint size = *parselist++;
    788                accumRedSize = MAX2( accumRedSize, size );
    789             }
    790             break;
    791 	 case GLX_ACCUM_GREEN_SIZE:
    792 	    parselist++;
    793             {
    794                GLint size = *parselist++;
    795                accumGreenSize = MAX2( accumGreenSize, size );
    796             }
    797             break;
    798 	 case GLX_ACCUM_BLUE_SIZE:
    799 	    parselist++;
    800             {
    801                GLint size = *parselist++;
    802                accumBlueSize = MAX2( accumBlueSize, size );
    803             }
    804             break;
    805 	 case GLX_ACCUM_ALPHA_SIZE:
    806 	    parselist++;
    807             {
    808                GLint size = *parselist++;
    809                accumAlphaSize = MAX2( accumAlphaSize, size );
    810             }
    811 	    break;
    812 
    813          /*
    814           * GLX_EXT_visual_info extension
    815           */
    816          case GLX_X_VISUAL_TYPE_EXT:
    817             parselist++;
    818             visual_type = *parselist++;
    819             break;
    820          case GLX_TRANSPARENT_TYPE_EXT:
    821             parselist++;
    822             parselist++;
    823             break;
    824          case GLX_TRANSPARENT_INDEX_VALUE_EXT:
    825             parselist++;
    826             parselist++;
    827             break;
    828          case GLX_TRANSPARENT_RED_VALUE_EXT:
    829          case GLX_TRANSPARENT_GREEN_VALUE_EXT:
    830          case GLX_TRANSPARENT_BLUE_VALUE_EXT:
    831          case GLX_TRANSPARENT_ALPHA_VALUE_EXT:
    832 	    /* ignore */
    833 	    parselist++;
    834 	    parselist++;
    835 	    break;
    836 
    837          /*
    838           * GLX_EXT_visual_info extension
    839           */
    840          case GLX_VISUAL_CAVEAT_EXT:
    841             parselist++;
    842             caveat = *parselist++; /* ignored for now */
    843             break;
    844 
    845          /*
    846           * GLX_ARB_multisample
    847           */
    848          case GLX_SAMPLE_BUFFERS_ARB:
    849          case GLX_SAMPLES_ARB:
    850             parselist++;
    851             if (*parselist++ != 0) {
    852                /* ms not supported */
    853                return NULL;
    854             }
    855             break;
    856 
    857          /*
    858           * FBConfig attribs.
    859           */
    860          case GLX_RENDER_TYPE:
    861             if (!fbConfig)
    862                return NULL;
    863             parselist++;
    864             if (*parselist & GLX_RGBA_BIT) {
    865                rgb_flag = GL_TRUE;
    866             }
    867             else if (*parselist & GLX_COLOR_INDEX_BIT) {
    868                rgb_flag = GL_FALSE;
    869             }
    870             else if (*parselist == 0) {
    871                rgb_flag = GL_TRUE;
    872             }
    873             parselist++;
    874             break;
    875          case GLX_DRAWABLE_TYPE:
    876             if (!fbConfig)
    877                return NULL;
    878             parselist++;
    879             if (*parselist & ~(GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT)) {
    880                return NULL; /* bad bit */
    881             }
    882             parselist++;
    883             break;
    884          case GLX_FBCONFIG_ID:
    885          case GLX_VISUAL_ID:
    886             if (!fbConfig)
    887                return NULL;
    888             parselist++;
    889             desiredVisualID = *parselist++;
    890             break;
    891          case GLX_X_RENDERABLE:
    892          case GLX_MAX_PBUFFER_WIDTH:
    893          case GLX_MAX_PBUFFER_HEIGHT:
    894          case GLX_MAX_PBUFFER_PIXELS:
    895             if (!fbConfig)
    896                return NULL; /* invalid config option */
    897             parselist += 2; /* ignore the parameter */
    898             break;
    899 
    900 #ifdef GLX_EXT_texture_from_pixmap
    901          case GLX_BIND_TO_TEXTURE_RGB_EXT:
    902             parselist++; /*skip*/
    903             break;
    904          case GLX_BIND_TO_TEXTURE_RGBA_EXT:
    905             parselist++; /*skip*/
    906             break;
    907          case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
    908             parselist++; /*skip*/
    909             break;
    910          case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
    911             parselist++;
    912             if (*parselist & ~(GLX_TEXTURE_1D_BIT_EXT |
    913                                GLX_TEXTURE_2D_BIT_EXT |
    914                                GLX_TEXTURE_RECTANGLE_BIT_EXT)) {
    915                /* invalid bit */
    916                return NULL;
    917             }
    918             break;
    919          case GLX_Y_INVERTED_EXT:
    920             parselist++; /*skip*/
    921             break;
    922 #endif
    923 
    924 	 case None:
    925             /* end of list */
    926 	    break;
    927 
    928 	 default:
    929 	    /* undefined attribute */
    930             _mesa_warning(NULL, "unexpected attrib 0x%x in choose_visual()",
    931                           *parselist);
    932 	    return NULL;
    933       }
    934    }
    935 
    936    (void) caveat;
    937 
    938 
    939    /*
    940     * Since we're only simulating the GLX extension this function will never
    941     * find any real GL visuals.  Instead, all we can do is try to find an RGB
    942     * or CI visual of appropriate depth.  Other requested attributes such as
    943     * double buffering, depth buffer, etc. will be associated with the X
    944     * visual and stored in the VisualTable[].
    945     */
    946    if (desiredVisualID != -1) {
    947       /* try to get a specific visual, by visualID */
    948       XVisualInfo temp;
    949       int n;
    950       temp.visualid = desiredVisualID;
    951       temp.screen = screen;
    952       vis = XGetVisualInfo(dpy, VisualIDMask | VisualScreenMask, &temp, &n);
    953       if (vis) {
    954          /* give the visual some useful GLX attributes */
    955          double_flag = GL_TRUE;
    956          rgb_flag = GL_TRUE;
    957       }
    958    }
    959    else if (level==0) {
    960       /* normal color planes */
    961       /* Get an RGB visual */
    962       int min_rgb = min_red + min_green + min_blue;
    963       if (min_rgb>1 && min_rgb<8) {
    964          /* a special case to be sure we can get a monochrome visual */
    965          min_rgb = 1;
    966       }
    967       vis = choose_x_visual( dpy, screen, min_rgb, visual_type );
    968    }
    969    else {
    970       _mesa_warning(NULL, "overlay not supported");
    971       return NULL;
    972    }
    973 
    974    if (vis) {
    975       /* Note: we're not exactly obeying the glXChooseVisual rules here.
    976        * When GLX_DEPTH_SIZE = 1 is specified we're supposed to choose the
    977        * largest depth buffer size, which is 32bits/value.  Instead, we
    978        * return 16 to maintain performance with earlier versions of Mesa.
    979        */
    980       if (stencil_size > 0)
    981          depth_size = 24;  /* if Z and stencil, always use 24+8 format */
    982       else if (depth_size > 24)
    983          depth_size = 32;
    984       else if (depth_size > 16)
    985          depth_size = 24;
    986       else if (depth_size > 0) {
    987          depth_size = default_depth_bits();
    988       }
    989 
    990       if (!alpha_flag) {
    991          alpha_flag = default_alpha_bits() > 0;
    992       }
    993 
    994       /* we only support one size of stencil and accum buffers. */
    995       if (stencil_size > 0)
    996          stencil_size = 8;
    997 
    998       if (accumRedSize > 0 ||
    999           accumGreenSize > 0 ||
   1000           accumBlueSize > 0 ||
   1001           accumAlphaSize > 0) {
   1002 
   1003          accumRedSize =
   1004             accumGreenSize =
   1005             accumBlueSize = default_accum_bits();
   1006 
   1007          accumAlphaSize = alpha_flag ? accumRedSize : 0;
   1008       }
   1009 
   1010       xmvis = save_glx_visual( dpy, vis, rgb_flag, alpha_flag, double_flag,
   1011                                stereo_flag, depth_size, stencil_size,
   1012                                accumRedSize, accumGreenSize,
   1013                                accumBlueSize, accumAlphaSize, level, numAux );
   1014    }
   1015 
   1016    return xmvis;
   1017 }
   1018 
   1019 
   1020 PUBLIC XVisualInfo *
   1021 glXChooseVisual( Display *dpy, int screen, int *list )
   1022 {
   1023    XMesaVisual xmvis;
   1024 
   1025    /* register ourselves as an extension on this display */
   1026    register_with_display(dpy);
   1027 
   1028    xmvis = choose_visual(dpy, screen, list, GL_FALSE);
   1029    if (xmvis) {
   1030       /* create a new vishandle - the cached one may be stale */
   1031       xmvis->vishandle = (XVisualInfo *) malloc(sizeof(XVisualInfo));
   1032       if (xmvis->vishandle) {
   1033          memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo));
   1034       }
   1035       return xmvis->vishandle;
   1036    }
   1037    else
   1038       return NULL;
   1039 }
   1040 
   1041 
   1042 /**
   1043  * Helper function used by other glXCreateContext functions.
   1044  */
   1045 static GLXContext
   1046 create_context(Display *dpy, XMesaVisual xmvis,
   1047                XMesaContext shareCtx, Bool direct,
   1048                unsigned major, unsigned minor,
   1049                unsigned profileMask, unsigned contextFlags)
   1050 {
   1051    GLXContext glxCtx;
   1052 
   1053    if (!dpy || !xmvis)
   1054       return 0;
   1055 
   1056    glxCtx = CALLOC_STRUCT(__GLXcontextRec);
   1057    if (!glxCtx)
   1058       return 0;
   1059 
   1060    /* deallocate unused windows/buffers */
   1061 #if 0
   1062    XMesaGarbageCollect();
   1063 #endif
   1064 
   1065    glxCtx->xmesaContext = XMesaCreateContext(xmvis, shareCtx, major, minor,
   1066                                              profileMask, contextFlags);
   1067    if (!glxCtx->xmesaContext) {
   1068       free(glxCtx);
   1069       return NULL;
   1070    }
   1071 
   1072    glxCtx->isDirect = DEFAULT_DIRECT;
   1073    glxCtx->currentDpy = dpy;
   1074    glxCtx->xid = (XID) glxCtx;  /* self pointer */
   1075 
   1076    return glxCtx;
   1077 }
   1078 
   1079 
   1080 PUBLIC GLXContext
   1081 glXCreateContext( Display *dpy, XVisualInfo *visinfo,
   1082                   GLXContext shareCtx, Bool direct )
   1083 {
   1084    XMesaVisual xmvis;
   1085 
   1086    xmvis = find_glx_visual( dpy, visinfo );
   1087    if (!xmvis) {
   1088       /* This visual wasn't found with glXChooseVisual() */
   1089       xmvis = create_glx_visual( dpy, visinfo );
   1090       if (!xmvis) {
   1091          /* unusable visual */
   1092          return NULL;
   1093       }
   1094    }
   1095 
   1096    return create_context(dpy, xmvis,
   1097                          shareCtx ? shareCtx->xmesaContext : NULL,
   1098                          direct,
   1099                          1, 0, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, 0x0);
   1100 }
   1101 
   1102 
   1103 /* XXX these may have to be removed due to thread-safety issues. */
   1104 static GLXContext MakeCurrent_PrevContext = 0;
   1105 static GLXDrawable MakeCurrent_PrevDrawable = 0;
   1106 static GLXDrawable MakeCurrent_PrevReadable = 0;
   1107 static XMesaBuffer MakeCurrent_PrevDrawBuffer = 0;
   1108 static XMesaBuffer MakeCurrent_PrevReadBuffer = 0;
   1109 
   1110 
   1111 /* GLX 1.3 and later */
   1112 PUBLIC Bool
   1113 glXMakeContextCurrent( Display *dpy, GLXDrawable draw,
   1114                        GLXDrawable read, GLXContext ctx )
   1115 {
   1116    GLXContext glxCtx = ctx;
   1117    static boolean firsttime = 1, no_rast = 0;
   1118 
   1119    if (firsttime) {
   1120       no_rast = getenv("SP_NO_RAST") != NULL;
   1121       firsttime = 0;
   1122    }
   1123 
   1124    if (ctx && draw && read) {
   1125       XMesaBuffer drawBuffer, readBuffer;
   1126       XMesaContext xmctx = glxCtx->xmesaContext;
   1127 
   1128       /* Find the XMesaBuffer which corresponds to the GLXDrawable 'draw' */
   1129       if (ctx == MakeCurrent_PrevContext
   1130           && draw == MakeCurrent_PrevDrawable) {
   1131          drawBuffer = MakeCurrent_PrevDrawBuffer;
   1132       }
   1133       else {
   1134          drawBuffer = XMesaFindBuffer( dpy, draw );
   1135       }
   1136       if (!drawBuffer) {
   1137          /* drawable must be a new window! */
   1138          drawBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, draw );
   1139          if (!drawBuffer) {
   1140             /* Out of memory, or context/drawable depth mismatch */
   1141             return False;
   1142          }
   1143       }
   1144 
   1145       /* Find the XMesaBuffer which corresponds to the GLXDrawable 'read' */
   1146       if (ctx == MakeCurrent_PrevContext
   1147           && read == MakeCurrent_PrevReadable) {
   1148          readBuffer = MakeCurrent_PrevReadBuffer;
   1149       }
   1150       else {
   1151          readBuffer = XMesaFindBuffer( dpy, read );
   1152       }
   1153       if (!readBuffer) {
   1154          /* drawable must be a new window! */
   1155          readBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, read );
   1156          if (!readBuffer) {
   1157             /* Out of memory, or context/drawable depth mismatch */
   1158             return False;
   1159          }
   1160       }
   1161 
   1162       if (no_rast &&
   1163           MakeCurrent_PrevContext == ctx &&
   1164           MakeCurrent_PrevDrawable == draw &&
   1165           MakeCurrent_PrevReadable == read &&
   1166           MakeCurrent_PrevDrawBuffer == drawBuffer &&
   1167           MakeCurrent_PrevReadBuffer == readBuffer)
   1168          return True;
   1169 
   1170       MakeCurrent_PrevContext = ctx;
   1171       MakeCurrent_PrevDrawable = draw;
   1172       MakeCurrent_PrevReadable = read;
   1173       MakeCurrent_PrevDrawBuffer = drawBuffer;
   1174       MakeCurrent_PrevReadBuffer = readBuffer;
   1175 
   1176       /* Now make current! */
   1177       if (XMesaMakeCurrent2(xmctx, drawBuffer, readBuffer)) {
   1178          ctx->currentDpy = dpy;
   1179          ctx->currentDrawable = draw;
   1180          ctx->currentReadable = read;
   1181          SetCurrentContext(ctx);
   1182          return True;
   1183       }
   1184       else {
   1185          return False;
   1186       }
   1187    }
   1188    else if (!ctx && !draw && !read) {
   1189       /* release current context w/out assigning new one. */
   1190       XMesaMakeCurrent2( NULL, NULL, NULL );
   1191       MakeCurrent_PrevContext = 0;
   1192       MakeCurrent_PrevDrawable = 0;
   1193       MakeCurrent_PrevReadable = 0;
   1194       MakeCurrent_PrevDrawBuffer = 0;
   1195       MakeCurrent_PrevReadBuffer = 0;
   1196       SetCurrentContext(NULL);
   1197       return True;
   1198    }
   1199    else {
   1200       /* The args must either all be non-zero or all zero.
   1201        * This is an error.
   1202        */
   1203       return False;
   1204    }
   1205 }
   1206 
   1207 
   1208 PUBLIC Bool
   1209 glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx )
   1210 {
   1211    return glXMakeContextCurrent( dpy, drawable, drawable, ctx );
   1212 }
   1213 
   1214 
   1215 PUBLIC GLXContext
   1216 glXGetCurrentContext(void)
   1217 {
   1218    return GetCurrentContext();
   1219 }
   1220 
   1221 
   1222 PUBLIC Display *
   1223 glXGetCurrentDisplay(void)
   1224 {
   1225    GLXContext glxCtx = glXGetCurrentContext();
   1226 
   1227    return glxCtx ? glxCtx->currentDpy : NULL;
   1228 }
   1229 
   1230 
   1231 PUBLIC Display *
   1232 glXGetCurrentDisplayEXT(void)
   1233 {
   1234    return glXGetCurrentDisplay();
   1235 }
   1236 
   1237 
   1238 PUBLIC GLXDrawable
   1239 glXGetCurrentDrawable(void)
   1240 {
   1241    GLXContext gc = glXGetCurrentContext();
   1242    return gc ? gc->currentDrawable : 0;
   1243 }
   1244 
   1245 
   1246 PUBLIC GLXDrawable
   1247 glXGetCurrentReadDrawable(void)
   1248 {
   1249    GLXContext gc = glXGetCurrentContext();
   1250    return gc ? gc->currentReadable : 0;
   1251 }
   1252 
   1253 
   1254 PUBLIC GLXDrawable
   1255 glXGetCurrentReadDrawableSGI(void)
   1256 {
   1257    return glXGetCurrentReadDrawable();
   1258 }
   1259 
   1260 
   1261 PUBLIC GLXPixmap
   1262 glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, Pixmap pixmap )
   1263 {
   1264    XMesaVisual v;
   1265    XMesaBuffer b;
   1266 
   1267    v = find_glx_visual( dpy, visinfo );
   1268    if (!v) {
   1269       v = create_glx_visual( dpy, visinfo );
   1270       if (!v) {
   1271          /* unusable visual */
   1272          return 0;
   1273       }
   1274    }
   1275 
   1276    b = XMesaCreatePixmapBuffer( v, pixmap, 0 );
   1277    if (!b) {
   1278       return 0;
   1279    }
   1280    return b->ws.drawable;
   1281 }
   1282 
   1283 
   1284 /*** GLX_MESA_pixmap_colormap ***/
   1285 
   1286 PUBLIC GLXPixmap
   1287 glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo,
   1288                         Pixmap pixmap, Colormap cmap )
   1289 {
   1290    XMesaVisual v;
   1291    XMesaBuffer b;
   1292 
   1293    v = find_glx_visual( dpy, visinfo );
   1294    if (!v) {
   1295       v = create_glx_visual( dpy, visinfo );
   1296       if (!v) {
   1297          /* unusable visual */
   1298          return 0;
   1299       }
   1300    }
   1301 
   1302    b = XMesaCreatePixmapBuffer( v, pixmap, cmap );
   1303    if (!b) {
   1304       return 0;
   1305    }
   1306    return b->ws.drawable;
   1307 }
   1308 
   1309 
   1310 PUBLIC void
   1311 glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap )
   1312 {
   1313    XMesaBuffer b = XMesaFindBuffer(dpy, pixmap);
   1314    if (b) {
   1315       XMesaDestroyBuffer(b);
   1316    }
   1317    else if (_mesa_getenv("MESA_DEBUG")) {
   1318       _mesa_warning(NULL, "Mesa: glXDestroyGLXPixmap: invalid pixmap\n");
   1319    }
   1320 }
   1321 
   1322 
   1323 PUBLIC void
   1324 glXCopyContext( Display *dpy, GLXContext src, GLXContext dst,
   1325                 unsigned long mask )
   1326 {
   1327    XMesaContext xm_src = src->xmesaContext;
   1328    XMesaContext xm_dst = dst->xmesaContext;
   1329    (void) dpy;
   1330    if (MakeCurrent_PrevContext == src) {
   1331       glFlush();
   1332    }
   1333    XMesaCopyContext(xm_src, xm_dst, mask);
   1334 }
   1335 
   1336 
   1337 PUBLIC Bool
   1338 glXQueryExtension( Display *dpy, int *errorBase, int *eventBase )
   1339 {
   1340    int op, ev, err;
   1341    /* Mesa's GLX isn't really an X extension but we try to act like one. */
   1342    if (!XQueryExtension(dpy, GLX_EXTENSION_NAME, &op, &ev, &err))
   1343       ev = err = 0;
   1344    if (errorBase)
   1345       *errorBase = err;
   1346    if (eventBase)
   1347       *eventBase = ev;
   1348    return True; /* we're faking GLX so always return success */
   1349 }
   1350 
   1351 
   1352 PUBLIC void
   1353 glXDestroyContext( Display *dpy, GLXContext ctx )
   1354 {
   1355    GLXContext glxCtx = ctx;
   1356    (void) dpy;
   1357    MakeCurrent_PrevContext = 0;
   1358    MakeCurrent_PrevDrawable = 0;
   1359    MakeCurrent_PrevReadable = 0;
   1360    MakeCurrent_PrevDrawBuffer = 0;
   1361    MakeCurrent_PrevReadBuffer = 0;
   1362    XMesaDestroyContext( glxCtx->xmesaContext );
   1363    XMesaGarbageCollect();
   1364    free(glxCtx);
   1365 }
   1366 
   1367 
   1368 PUBLIC Bool
   1369 glXIsDirect( Display *dpy, GLXContext ctx )
   1370 {
   1371    GLXContext glxCtx = ctx;
   1372    (void) ctx;
   1373    return glxCtx->isDirect;
   1374 }
   1375 
   1376 
   1377 
   1378 PUBLIC void
   1379 glXSwapBuffers( Display *dpy, GLXDrawable drawable )
   1380 {
   1381    XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable );
   1382    static boolean firsttime = 1, no_rast = 0;
   1383 
   1384    if (firsttime) {
   1385       no_rast = getenv("SP_NO_RAST") != NULL;
   1386       firsttime = 0;
   1387    }
   1388 
   1389    if (no_rast)
   1390       return;
   1391 
   1392    if (buffer) {
   1393       XMesaSwapBuffers(buffer);
   1394    }
   1395    else if (_mesa_getenv("MESA_DEBUG")) {
   1396       _mesa_warning(NULL, "glXSwapBuffers: invalid drawable 0x%x\n",
   1397                     (int) drawable);
   1398    }
   1399 }
   1400 
   1401 
   1402 
   1403 /*** GLX_MESA_copy_sub_buffer ***/
   1404 
   1405 PUBLIC void
   1406 glXCopySubBufferMESA(Display *dpy, GLXDrawable drawable,
   1407                      int x, int y, int width, int height)
   1408 {
   1409    XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable );
   1410    if (buffer) {
   1411       XMesaCopySubBuffer(buffer, x, y, width, height);
   1412    }
   1413    else if (_mesa_getenv("MESA_DEBUG")) {
   1414       _mesa_warning(NULL, "Mesa: glXCopySubBufferMESA: invalid drawable\n");
   1415    }
   1416 }
   1417 
   1418 
   1419 PUBLIC Bool
   1420 glXQueryVersion( Display *dpy, int *maj, int *min )
   1421 {
   1422    (void) dpy;
   1423    /* Return GLX version, not Mesa version */
   1424    assert(CLIENT_MAJOR_VERSION == SERVER_MAJOR_VERSION);
   1425    *maj = CLIENT_MAJOR_VERSION;
   1426    *min = MIN2( CLIENT_MINOR_VERSION, SERVER_MINOR_VERSION );
   1427    return True;
   1428 }
   1429 
   1430 
   1431 /*
   1432  * Query the GLX attributes of the given XVisualInfo.
   1433  */
   1434 static int
   1435 get_config( XMesaVisual xmvis, int attrib, int *value, GLboolean fbconfig )
   1436 {
   1437    ASSERT(xmvis);
   1438    switch(attrib) {
   1439       case GLX_USE_GL:
   1440          if (fbconfig)
   1441             return GLX_BAD_ATTRIBUTE;
   1442          *value = (int) True;
   1443 	 return 0;
   1444       case GLX_BUFFER_SIZE:
   1445 	 *value = xmvis->visinfo->depth;
   1446 	 return 0;
   1447       case GLX_LEVEL:
   1448 	 *value = xmvis->mesa_visual.level;
   1449 	 return 0;
   1450       case GLX_RGBA:
   1451          if (fbconfig)
   1452             return GLX_BAD_ATTRIBUTE;
   1453 	 if (xmvis->mesa_visual.rgbMode) {
   1454 	    *value = True;
   1455 	 }
   1456 	 else {
   1457 	    *value = False;
   1458 	 }
   1459 	 return 0;
   1460       case GLX_DOUBLEBUFFER:
   1461 	 *value = (int) xmvis->mesa_visual.doubleBufferMode;
   1462 	 return 0;
   1463       case GLX_STEREO:
   1464 	 *value = (int) xmvis->mesa_visual.stereoMode;
   1465 	 return 0;
   1466       case GLX_AUX_BUFFERS:
   1467 	 *value = xmvis->mesa_visual.numAuxBuffers;
   1468 	 return 0;
   1469       case GLX_RED_SIZE:
   1470          *value = xmvis->mesa_visual.redBits;
   1471 	 return 0;
   1472       case GLX_GREEN_SIZE:
   1473          *value = xmvis->mesa_visual.greenBits;
   1474 	 return 0;
   1475       case GLX_BLUE_SIZE:
   1476          *value = xmvis->mesa_visual.blueBits;
   1477 	 return 0;
   1478       case GLX_ALPHA_SIZE:
   1479          *value = xmvis->mesa_visual.alphaBits;
   1480 	 return 0;
   1481       case GLX_DEPTH_SIZE:
   1482          *value = xmvis->mesa_visual.depthBits;
   1483 	 return 0;
   1484       case GLX_STENCIL_SIZE:
   1485 	 *value = xmvis->mesa_visual.stencilBits;
   1486 	 return 0;
   1487       case GLX_ACCUM_RED_SIZE:
   1488 	 *value = xmvis->mesa_visual.accumRedBits;
   1489 	 return 0;
   1490       case GLX_ACCUM_GREEN_SIZE:
   1491 	 *value = xmvis->mesa_visual.accumGreenBits;
   1492 	 return 0;
   1493       case GLX_ACCUM_BLUE_SIZE:
   1494 	 *value = xmvis->mesa_visual.accumBlueBits;
   1495 	 return 0;
   1496       case GLX_ACCUM_ALPHA_SIZE:
   1497          *value = xmvis->mesa_visual.accumAlphaBits;
   1498 	 return 0;
   1499 
   1500       /*
   1501        * GLX_EXT_visual_info extension
   1502        */
   1503       case GLX_X_VISUAL_TYPE_EXT:
   1504          switch (xmvis->visinfo->CLASS) {
   1505             case StaticGray:   *value = GLX_STATIC_GRAY_EXT;   return 0;
   1506             case GrayScale:    *value = GLX_GRAY_SCALE_EXT;    return 0;
   1507             case StaticColor:  *value = GLX_STATIC_GRAY_EXT;   return 0;
   1508             case PseudoColor:  *value = GLX_PSEUDO_COLOR_EXT;  return 0;
   1509             case TrueColor:    *value = GLX_TRUE_COLOR_EXT;    return 0;
   1510             case DirectColor:  *value = GLX_DIRECT_COLOR_EXT;  return 0;
   1511          }
   1512          return 0;
   1513       case GLX_TRANSPARENT_TYPE_EXT:
   1514          /* normal planes */
   1515          *value = GLX_NONE_EXT;
   1516          return 0;
   1517       case GLX_TRANSPARENT_INDEX_VALUE_EXT:
   1518          /* undefined */
   1519          return 0;
   1520       case GLX_TRANSPARENT_RED_VALUE_EXT:
   1521          /* undefined */
   1522          return 0;
   1523       case GLX_TRANSPARENT_GREEN_VALUE_EXT:
   1524          /* undefined */
   1525          return 0;
   1526       case GLX_TRANSPARENT_BLUE_VALUE_EXT:
   1527          /* undefined */
   1528          return 0;
   1529       case GLX_TRANSPARENT_ALPHA_VALUE_EXT:
   1530          /* undefined */
   1531          return 0;
   1532 
   1533       /*
   1534        * GLX_EXT_visual_info extension
   1535        */
   1536       case GLX_VISUAL_CAVEAT_EXT:
   1537          /* test for zero, just in case */
   1538          if (xmvis->mesa_visual.visualRating > 0)
   1539             *value = xmvis->mesa_visual.visualRating;
   1540          else
   1541             *value = GLX_NONE_EXT;
   1542          return 0;
   1543 
   1544       /*
   1545        * GLX_ARB_multisample
   1546        */
   1547       case GLX_SAMPLE_BUFFERS_ARB:
   1548          *value = 0;
   1549          return 0;
   1550       case GLX_SAMPLES_ARB:
   1551          *value = 0;
   1552          return 0;
   1553 
   1554       /*
   1555        * For FBConfigs:
   1556        */
   1557       case GLX_SCREEN_EXT:
   1558          if (!fbconfig)
   1559             return GLX_BAD_ATTRIBUTE;
   1560          *value = xmvis->visinfo->screen;
   1561          break;
   1562       case GLX_DRAWABLE_TYPE: /*SGIX too */
   1563          if (!fbconfig)
   1564             return GLX_BAD_ATTRIBUTE;
   1565          *value = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
   1566          break;
   1567       case GLX_RENDER_TYPE_SGIX:
   1568          if (!fbconfig)
   1569             return GLX_BAD_ATTRIBUTE;
   1570          if (xmvis->mesa_visual.rgbMode)
   1571             *value = GLX_RGBA_BIT;
   1572          else
   1573             *value = GLX_COLOR_INDEX_BIT;
   1574          break;
   1575       case GLX_X_RENDERABLE_SGIX:
   1576          if (!fbconfig)
   1577             return GLX_BAD_ATTRIBUTE;
   1578          *value = True; /* XXX really? */
   1579          break;
   1580       case GLX_FBCONFIG_ID_SGIX:
   1581          if (!fbconfig)
   1582             return GLX_BAD_ATTRIBUTE;
   1583          *value = xmvis->visinfo->visualid;
   1584          break;
   1585       case GLX_MAX_PBUFFER_WIDTH:
   1586          if (!fbconfig)
   1587             return GLX_BAD_ATTRIBUTE;
   1588          /* XXX or MAX_WIDTH? */
   1589          *value = DisplayWidth(xmvis->display, xmvis->visinfo->screen);
   1590          break;
   1591       case GLX_MAX_PBUFFER_HEIGHT:
   1592          if (!fbconfig)
   1593             return GLX_BAD_ATTRIBUTE;
   1594          *value = DisplayHeight(xmvis->display, xmvis->visinfo->screen);
   1595          break;
   1596       case GLX_MAX_PBUFFER_PIXELS:
   1597          if (!fbconfig)
   1598             return GLX_BAD_ATTRIBUTE;
   1599          *value = DisplayWidth(xmvis->display, xmvis->visinfo->screen) *
   1600                   DisplayHeight(xmvis->display, xmvis->visinfo->screen);
   1601          break;
   1602       case GLX_VISUAL_ID:
   1603          if (!fbconfig)
   1604             return GLX_BAD_ATTRIBUTE;
   1605          *value = xmvis->visinfo->visualid;
   1606          break;
   1607 
   1608 #ifdef GLX_EXT_texture_from_pixmap
   1609       case GLX_BIND_TO_TEXTURE_RGB_EXT:
   1610          *value = True; /*XXX*/
   1611          break;
   1612       case GLX_BIND_TO_TEXTURE_RGBA_EXT:
   1613          /* XXX review */
   1614          *value = xmvis->mesa_visual.alphaBits > 0 ? True : False;
   1615          break;
   1616       case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
   1617          *value = True; /*XXX*/
   1618          break;
   1619       case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
   1620          *value = (GLX_TEXTURE_1D_BIT_EXT |
   1621                    GLX_TEXTURE_2D_BIT_EXT |
   1622                    GLX_TEXTURE_RECTANGLE_BIT_EXT); /*XXX*/
   1623          break;
   1624       case GLX_Y_INVERTED_EXT:
   1625          *value = True; /*XXX*/
   1626          break;
   1627 #endif
   1628 
   1629       default:
   1630 	 return GLX_BAD_ATTRIBUTE;
   1631    }
   1632    return Success;
   1633 }
   1634 
   1635 
   1636 PUBLIC int
   1637 glXGetConfig( Display *dpy, XVisualInfo *visinfo,
   1638                    int attrib, int *value )
   1639 {
   1640    XMesaVisual xmvis;
   1641    int k;
   1642    if (!dpy || !visinfo)
   1643       return GLX_BAD_ATTRIBUTE;
   1644 
   1645    xmvis = find_glx_visual( dpy, visinfo );
   1646    if (!xmvis) {
   1647       /* this visual wasn't obtained with glXChooseVisual */
   1648       xmvis = create_glx_visual( dpy, visinfo );
   1649       if (!xmvis) {
   1650 	 /* this visual can't be used for GL rendering */
   1651 	 if (attrib==GLX_USE_GL) {
   1652 	    *value = (int) False;
   1653 	    return 0;
   1654 	 }
   1655 	 else {
   1656 	    return GLX_BAD_VISUAL;
   1657 	 }
   1658       }
   1659    }
   1660 
   1661    k = get_config(xmvis, attrib, value, GL_FALSE);
   1662    return k;
   1663 }
   1664 
   1665 
   1666 PUBLIC void
   1667 glXWaitGL( void )
   1668 {
   1669    XMesaContext xmesa = XMesaGetCurrentContext();
   1670    XMesaFlush( xmesa );
   1671 }
   1672 
   1673 
   1674 
   1675 PUBLIC void
   1676 glXWaitX( void )
   1677 {
   1678    XMesaContext xmesa = XMesaGetCurrentContext();
   1679    XMesaFlush( xmesa );
   1680 }
   1681 
   1682 
   1683 static const char *
   1684 get_extensions( void )
   1685 {
   1686    return EXTENSIONS;
   1687 }
   1688 
   1689 
   1690 
   1691 /* GLX 1.1 and later */
   1692 PUBLIC const char *
   1693 glXQueryExtensionsString( Display *dpy, int screen )
   1694 {
   1695    (void) dpy;
   1696    (void) screen;
   1697    return get_extensions();
   1698 }
   1699 
   1700 
   1701 
   1702 /* GLX 1.1 and later */
   1703 PUBLIC const char *
   1704 glXQueryServerString( Display *dpy, int screen, int name )
   1705 {
   1706    static char version[1000];
   1707    sprintf(version, "%d.%d %s",
   1708 	   SERVER_MAJOR_VERSION, SERVER_MINOR_VERSION, xmesa_get_name());
   1709 
   1710    (void) dpy;
   1711    (void) screen;
   1712 
   1713    switch (name) {
   1714       case GLX_EXTENSIONS:
   1715          return get_extensions();
   1716       case GLX_VENDOR:
   1717 	 return VENDOR;
   1718       case GLX_VERSION:
   1719 	 return version;
   1720       default:
   1721          return NULL;
   1722    }
   1723 }
   1724 
   1725 
   1726 
   1727 /* GLX 1.1 and later */
   1728 PUBLIC const char *
   1729 glXGetClientString( Display *dpy, int name )
   1730 {
   1731    static char version[1000];
   1732    sprintf(version, "%d.%d %s", CLIENT_MAJOR_VERSION,
   1733 	   CLIENT_MINOR_VERSION, xmesa_get_name());
   1734 
   1735    (void) dpy;
   1736 
   1737    switch (name) {
   1738       case GLX_EXTENSIONS:
   1739          return get_extensions();
   1740       case GLX_VENDOR:
   1741 	 return VENDOR;
   1742       case GLX_VERSION:
   1743 	 return version;
   1744       default:
   1745          return NULL;
   1746    }
   1747 }
   1748 
   1749 
   1750 
   1751 /*
   1752  * GLX 1.3 and later
   1753  */
   1754 
   1755 
   1756 PUBLIC int
   1757 glXGetFBConfigAttrib(Display *dpy, GLXFBConfig config,
   1758                      int attribute, int *value)
   1759 {
   1760    XMesaVisual v = (XMesaVisual) config;
   1761    (void) dpy;
   1762    (void) config;
   1763 
   1764    if (!dpy || !config || !value)
   1765       return -1;
   1766 
   1767    return get_config(v, attribute, value, GL_TRUE);
   1768 }
   1769 
   1770 
   1771 PUBLIC GLXFBConfig *
   1772 glXGetFBConfigs( Display *dpy, int screen, int *nelements )
   1773 {
   1774    XVisualInfo *visuals, visTemplate;
   1775    const long visMask = VisualScreenMask;
   1776    int i;
   1777 
   1778    /* Get list of all X visuals */
   1779    visTemplate.screen = screen;
   1780    visuals = XGetVisualInfo(dpy, visMask, &visTemplate, nelements);
   1781    if (*nelements > 0) {
   1782       XMesaVisual *results;
   1783       results = (XMesaVisual *) malloc(*nelements * sizeof(XMesaVisual));
   1784       if (!results) {
   1785          *nelements = 0;
   1786          return NULL;
   1787       }
   1788       for (i = 0; i < *nelements; i++) {
   1789          results[i] = create_glx_visual(dpy, visuals + i);
   1790          if (!results[i]) {
   1791             *nelements = i;
   1792             break;
   1793          }
   1794       }
   1795       return (GLXFBConfig *) results;
   1796    }
   1797    return NULL;
   1798 }
   1799 
   1800 
   1801 PUBLIC GLXFBConfig *
   1802 glXChooseFBConfig(Display *dpy, int screen,
   1803                   const int *attribList, int *nitems)
   1804 {
   1805    XMesaVisual xmvis;
   1806 
   1807    /* register ourselves as an extension on this display */
   1808    register_with_display(dpy);
   1809 
   1810    if (!attribList || !attribList[0]) {
   1811       /* return list of all configs (per GLX_SGIX_fbconfig spec) */
   1812       return glXGetFBConfigs(dpy, screen, nitems);
   1813    }
   1814 
   1815    xmvis = choose_visual(dpy, screen, attribList, GL_TRUE);
   1816    if (xmvis) {
   1817       GLXFBConfig *config = (GLXFBConfig *) malloc(sizeof(XMesaVisual));
   1818       if (!config) {
   1819          *nitems = 0;
   1820          return NULL;
   1821       }
   1822       *nitems = 1;
   1823       config[0] = (GLXFBConfig) xmvis;
   1824       return (GLXFBConfig *) config;
   1825    }
   1826    else {
   1827       *nitems = 0;
   1828       return NULL;
   1829    }
   1830 }
   1831 
   1832 
   1833 PUBLIC XVisualInfo *
   1834 glXGetVisualFromFBConfig( Display *dpy, GLXFBConfig config )
   1835 {
   1836    if (dpy && config) {
   1837       XMesaVisual xmvis = (XMesaVisual) config;
   1838 #if 0
   1839       return xmvis->vishandle;
   1840 #else
   1841       /* create a new vishandle - the cached one may be stale */
   1842       xmvis->vishandle = (XVisualInfo *) malloc(sizeof(XVisualInfo));
   1843       if (xmvis->vishandle) {
   1844          memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo));
   1845       }
   1846       return xmvis->vishandle;
   1847 #endif
   1848    }
   1849    else {
   1850       return NULL;
   1851    }
   1852 }
   1853 
   1854 
   1855 PUBLIC GLXWindow
   1856 glXCreateWindow(Display *dpy, GLXFBConfig config, Window win,
   1857                 const int *attribList)
   1858 {
   1859    XMesaVisual xmvis = (XMesaVisual) config;
   1860    XMesaBuffer xmbuf;
   1861    if (!xmvis)
   1862       return 0;
   1863 
   1864    xmbuf = XMesaCreateWindowBuffer(xmvis, win);
   1865    if (!xmbuf)
   1866       return 0;
   1867 
   1868    (void) dpy;
   1869    (void) attribList;  /* Ignored in GLX 1.3 */
   1870 
   1871    return win;  /* A hack for now */
   1872 }
   1873 
   1874 
   1875 PUBLIC void
   1876 glXDestroyWindow( Display *dpy, GLXWindow window )
   1877 {
   1878    XMesaBuffer b = XMesaFindBuffer(dpy, (Drawable) window);
   1879    if (b)
   1880       XMesaDestroyBuffer(b);
   1881    /* don't destroy X window */
   1882 }
   1883 
   1884 
   1885 /* XXX untested */
   1886 PUBLIC GLXPixmap
   1887 glXCreatePixmap(Display *dpy, GLXFBConfig config, Pixmap pixmap,
   1888                 const int *attribList)
   1889 {
   1890    XMesaVisual v = (XMesaVisual) config;
   1891    XMesaBuffer b;
   1892    const int *attr;
   1893    int target = 0, format = 0, mipmap = 0;
   1894    int value;
   1895 
   1896    if (!dpy || !config || !pixmap)
   1897       return 0;
   1898 
   1899    for (attr = attribList; attr && *attr; attr++) {
   1900       switch (*attr) {
   1901       case GLX_TEXTURE_FORMAT_EXT:
   1902          attr++;
   1903          switch (*attr) {
   1904          case GLX_TEXTURE_FORMAT_NONE_EXT:
   1905          case GLX_TEXTURE_FORMAT_RGB_EXT:
   1906          case GLX_TEXTURE_FORMAT_RGBA_EXT:
   1907             format = *attr;
   1908             break;
   1909          default:
   1910             /* error */
   1911             return 0;
   1912          }
   1913          break;
   1914       case GLX_TEXTURE_TARGET_EXT:
   1915          attr++;
   1916          switch (*attr) {
   1917          case GLX_TEXTURE_1D_EXT:
   1918          case GLX_TEXTURE_2D_EXT:
   1919          case GLX_TEXTURE_RECTANGLE_EXT:
   1920             target = *attr;
   1921             break;
   1922          default:
   1923             /* error */
   1924             return 0;
   1925          }
   1926          break;
   1927       case GLX_MIPMAP_TEXTURE_EXT:
   1928          attr++;
   1929          if (*attr)
   1930             mipmap = 1;
   1931          break;
   1932       default:
   1933          /* error */
   1934          return 0;
   1935       }
   1936    }
   1937 
   1938    if (format == GLX_TEXTURE_FORMAT_RGB_EXT) {
   1939       if (get_config(v, GLX_BIND_TO_TEXTURE_RGB_EXT,
   1940                      &value, GL_TRUE) != Success
   1941           || !value) {
   1942          return 0; /* error! */
   1943       }
   1944    }
   1945    else if (format == GLX_TEXTURE_FORMAT_RGBA_EXT) {
   1946       if (get_config(v, GLX_BIND_TO_TEXTURE_RGBA_EXT,
   1947                      &value, GL_TRUE) != Success
   1948           || !value) {
   1949          return 0; /* error! */
   1950       }
   1951    }
   1952    if (mipmap) {
   1953       if (get_config(v, GLX_BIND_TO_MIPMAP_TEXTURE_EXT,
   1954                      &value, GL_TRUE) != Success
   1955           || !value) {
   1956          return 0; /* error! */
   1957       }
   1958    }
   1959    if (target == GLX_TEXTURE_1D_EXT) {
   1960       if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT,
   1961                      &value, GL_TRUE) != Success
   1962           || (value & GLX_TEXTURE_1D_BIT_EXT) == 0) {
   1963          return 0; /* error! */
   1964       }
   1965    }
   1966    else if (target == GLX_TEXTURE_2D_EXT) {
   1967       if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT,
   1968                      &value, GL_TRUE) != Success
   1969           || (value & GLX_TEXTURE_2D_BIT_EXT) == 0) {
   1970          return 0; /* error! */
   1971       }
   1972    }
   1973    if (target == GLX_TEXTURE_RECTANGLE_EXT) {
   1974       if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT,
   1975                      &value, GL_TRUE) != Success
   1976           || (value & GLX_TEXTURE_RECTANGLE_BIT_EXT) == 0) {
   1977          return 0; /* error! */
   1978       }
   1979    }
   1980 
   1981    if (format || target || mipmap) {
   1982       /* texture from pixmap */
   1983       b = XMesaCreatePixmapTextureBuffer(v, pixmap, 0, format, target, mipmap);
   1984    }
   1985    else {
   1986       b = XMesaCreatePixmapBuffer( v, pixmap, 0 );
   1987    }
   1988    if (!b) {
   1989       return 0;
   1990    }
   1991 
   1992    return pixmap;
   1993 }
   1994 
   1995 
   1996 PUBLIC void
   1997 glXDestroyPixmap( Display *dpy, GLXPixmap pixmap )
   1998 {
   1999    XMesaBuffer b = XMesaFindBuffer(dpy, (Drawable)pixmap);
   2000    if (b)
   2001       XMesaDestroyBuffer(b);
   2002    /* don't destroy X pixmap */
   2003 }
   2004 
   2005 
   2006 PUBLIC GLXPbuffer
   2007 glXCreatePbuffer(Display *dpy, GLXFBConfig config, const int *attribList)
   2008 {
   2009    XMesaVisual xmvis = (XMesaVisual) config;
   2010    XMesaBuffer xmbuf;
   2011    const int *attrib;
   2012    int width = 0, height = 0;
   2013    GLboolean useLargest = GL_FALSE, preserveContents = GL_FALSE;
   2014 
   2015    (void) dpy;
   2016 
   2017    for (attrib = attribList; *attrib; attrib++) {
   2018       switch (*attrib) {
   2019          case GLX_PBUFFER_WIDTH:
   2020             attrib++;
   2021             width = *attrib;
   2022             break;
   2023          case GLX_PBUFFER_HEIGHT:
   2024             attrib++;
   2025             height = *attrib;
   2026             break;
   2027          case GLX_PRESERVED_CONTENTS:
   2028             attrib++;
   2029             preserveContents = *attrib;
   2030             break;
   2031          case GLX_LARGEST_PBUFFER:
   2032             attrib++;
   2033             useLargest = *attrib;
   2034             break;
   2035          default:
   2036             return 0;
   2037       }
   2038    }
   2039 
   2040    if (width == 0 || height == 0)
   2041       return 0;
   2042 
   2043    if (width > PBUFFER_MAX_SIZE || height > PBUFFER_MAX_SIZE) {
   2044       /* If allocation would have failed and GLX_LARGEST_PBUFFER is set,
   2045        * allocate the largest possible buffer.
   2046        */
   2047       if (useLargest) {
   2048          width = PBUFFER_MAX_SIZE;
   2049          height = PBUFFER_MAX_SIZE;
   2050       }
   2051    }
   2052 
   2053    xmbuf = XMesaCreatePBuffer( xmvis, 0, width, height);
   2054    /* A GLXPbuffer handle must be an X Drawable because that's what
   2055     * glXMakeCurrent takes.
   2056     */
   2057    if (xmbuf) {
   2058       xmbuf->largestPbuffer = useLargest;
   2059       xmbuf->preservedContents = preserveContents;
   2060       return (GLXPbuffer) xmbuf->ws.drawable;
   2061    }
   2062    else {
   2063       return 0;
   2064    }
   2065 }
   2066 
   2067 
   2068 PUBLIC void
   2069 glXDestroyPbuffer( Display *dpy, GLXPbuffer pbuf )
   2070 {
   2071    XMesaBuffer b = XMesaFindBuffer(dpy, pbuf);
   2072    if (b) {
   2073       XMesaDestroyBuffer(b);
   2074    }
   2075 }
   2076 
   2077 
   2078 PUBLIC void
   2079 glXQueryDrawable(Display *dpy, GLXDrawable draw, int attribute,
   2080                  unsigned int *value)
   2081 {
   2082    GLuint width, height;
   2083    XMesaBuffer xmbuf = XMesaFindBuffer(dpy, draw);
   2084    if (!xmbuf)
   2085       return;
   2086 
   2087    /* make sure buffer's dimensions are up to date */
   2088    xmesa_get_window_size(dpy, xmbuf, &width, &height);
   2089 
   2090    switch (attribute) {
   2091       case GLX_WIDTH:
   2092          *value = width;
   2093          break;
   2094       case GLX_HEIGHT:
   2095          *value = height;
   2096          break;
   2097       case GLX_PRESERVED_CONTENTS:
   2098          *value = xmbuf->preservedContents;
   2099          break;
   2100       case GLX_LARGEST_PBUFFER:
   2101          *value = xmbuf->largestPbuffer;
   2102          break;
   2103       case GLX_FBCONFIG_ID:
   2104          *value = xmbuf->xm_visual->visinfo->visualid;
   2105          return;
   2106 #ifdef GLX_EXT_texture_from_pixmap
   2107       case GLX_TEXTURE_FORMAT_EXT:
   2108          *value = xmbuf->TextureFormat;
   2109          break;
   2110       case GLX_TEXTURE_TARGET_EXT:
   2111          *value = xmbuf->TextureTarget;
   2112          break;
   2113       case GLX_MIPMAP_TEXTURE_EXT:
   2114          *value = xmbuf->TextureMipmap;
   2115          break;
   2116 #endif
   2117 
   2118       default:
   2119          return; /* raise BadValue error */
   2120    }
   2121 }
   2122 
   2123 
   2124 PUBLIC GLXContext
   2125 glXCreateNewContext( Display *dpy, GLXFBConfig config,
   2126                      int renderType, GLXContext shareCtx, Bool direct )
   2127 {
   2128    XMesaVisual xmvis = (XMesaVisual) config;
   2129 
   2130    if (!dpy || !config ||
   2131        (renderType != GLX_RGBA_TYPE && renderType != GLX_COLOR_INDEX_TYPE))
   2132       return 0;
   2133 
   2134    return create_context(dpy, xmvis,
   2135                          shareCtx ? shareCtx->xmesaContext : NULL,
   2136                          direct,
   2137                          1, 0, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, 0x0);
   2138 }
   2139 
   2140 
   2141 PUBLIC int
   2142 glXQueryContext( Display *dpy, GLXContext ctx, int attribute, int *value )
   2143 {
   2144    GLXContext glxCtx = ctx;
   2145    XMesaContext xmctx = glxCtx->xmesaContext;
   2146 
   2147    (void) dpy;
   2148    (void) ctx;
   2149 
   2150    switch (attribute) {
   2151    case GLX_FBCONFIG_ID:
   2152       *value = xmctx->xm_visual->visinfo->visualid;
   2153       break;
   2154    case GLX_RENDER_TYPE:
   2155       if (xmctx->xm_visual->mesa_visual.rgbMode)
   2156          *value = GLX_RGBA_TYPE;
   2157       else
   2158          *value = GLX_COLOR_INDEX_TYPE;
   2159       break;
   2160    case GLX_SCREEN:
   2161       *value = 0;
   2162       return Success;
   2163    default:
   2164       return GLX_BAD_ATTRIBUTE;
   2165    }
   2166    return 0;
   2167 }
   2168 
   2169 
   2170 PUBLIC void
   2171 glXSelectEvent( Display *dpy, GLXDrawable drawable, unsigned long mask )
   2172 {
   2173    XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);
   2174    if (xmbuf)
   2175       xmbuf->selectedEvents = mask;
   2176 }
   2177 
   2178 
   2179 PUBLIC void
   2180 glXGetSelectedEvent(Display *dpy, GLXDrawable drawable, unsigned long *mask)
   2181 {
   2182    XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);
   2183    if (xmbuf)
   2184       *mask = xmbuf->selectedEvents;
   2185    else
   2186       *mask = 0;
   2187 }
   2188 
   2189 
   2190 
   2191 /*** GLX_SGI_swap_control ***/
   2192 
   2193 PUBLIC int
   2194 glXSwapIntervalSGI(int interval)
   2195 {
   2196    (void) interval;
   2197    return 0;
   2198 }
   2199 
   2200 
   2201 
   2202 /*** GLX_SGI_video_sync ***/
   2203 
   2204 static unsigned int FrameCounter = 0;
   2205 
   2206 PUBLIC int
   2207 glXGetVideoSyncSGI(unsigned int *count)
   2208 {
   2209    /* this is a bogus implementation */
   2210    *count = FrameCounter++;
   2211    return 0;
   2212 }
   2213 
   2214 PUBLIC int
   2215 glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count)
   2216 {
   2217    if (divisor <= 0 || remainder < 0)
   2218       return GLX_BAD_VALUE;
   2219    /* this is a bogus implementation */
   2220    FrameCounter++;
   2221    while (FrameCounter % divisor != remainder)
   2222       FrameCounter++;
   2223    *count = FrameCounter;
   2224    return 0;
   2225 }
   2226 
   2227 
   2228 
   2229 /*** GLX_SGI_make_current_read ***/
   2230 
   2231 PUBLIC Bool
   2232 glXMakeCurrentReadSGI(Display *dpy, GLXDrawable draw, GLXDrawable read,
   2233                       GLXContext ctx)
   2234 {
   2235    return glXMakeContextCurrent( dpy, draw, read, ctx );
   2236 }
   2237 
   2238 /* not used
   2239 static GLXDrawable
   2240 glXGetCurrentReadDrawableSGI(void)
   2241 {
   2242    return 0;
   2243 }
   2244 */
   2245 
   2246 
   2247 /*** GLX_SGIX_video_source ***/
   2248 #if defined(_VL_H)
   2249 
   2250 PUBLIC GLXVideoSourceSGIX
   2251 glXCreateGLXVideoSourceSGIX(Display *dpy, int screen, VLServer server,
   2252                             VLPath path, int nodeClass, VLNode drainNode)
   2253 {
   2254    (void) dpy;
   2255    (void) screen;
   2256    (void) server;
   2257    (void) path;
   2258    (void) nodeClass;
   2259    (void) drainNode;
   2260    return 0;
   2261 }
   2262 
   2263 PUBLIC void
   2264 glXDestroyGLXVideoSourceSGIX(Display *dpy, GLXVideoSourceSGIX src)
   2265 {
   2266    (void) dpy;
   2267    (void) src;
   2268 }
   2269 
   2270 #endif
   2271 
   2272 
   2273 /*** GLX_EXT_import_context ***/
   2274 
   2275 PUBLIC void
   2276 glXFreeContextEXT(Display *dpy, GLXContext context)
   2277 {
   2278    (void) dpy;
   2279    (void) context;
   2280 }
   2281 
   2282 PUBLIC GLXContextID
   2283 glXGetContextIDEXT(const GLXContext context)
   2284 {
   2285    (void) context;
   2286    return 0;
   2287 }
   2288 
   2289 PUBLIC GLXContext
   2290 glXImportContextEXT(Display *dpy, GLXContextID contextID)
   2291 {
   2292    (void) dpy;
   2293    (void) contextID;
   2294    return 0;
   2295 }
   2296 
   2297 PUBLIC int
   2298 glXQueryContextInfoEXT(Display *dpy, GLXContext context, int attribute,
   2299                        int *value)
   2300 {
   2301    (void) dpy;
   2302    (void) context;
   2303    (void) attribute;
   2304    (void) value;
   2305    return 0;
   2306 }
   2307 
   2308 
   2309 
   2310 /*** GLX_SGIX_fbconfig ***/
   2311 
   2312 PUBLIC int
   2313 glXGetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config,
   2314                          int attribute, int *value)
   2315 {
   2316    return glXGetFBConfigAttrib(dpy, config, attribute, value);
   2317 }
   2318 
   2319 PUBLIC GLXFBConfigSGIX *
   2320 glXChooseFBConfigSGIX(Display *dpy, int screen, int *attrib_list,
   2321                       int *nelements)
   2322 {
   2323    return (GLXFBConfig *) glXChooseFBConfig(dpy, screen,
   2324                                             attrib_list, nelements);
   2325 }
   2326 
   2327 
   2328 PUBLIC GLXPixmap
   2329 glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config,
   2330                                  Pixmap pixmap)
   2331 {
   2332    XMesaVisual xmvis = (XMesaVisual) config;
   2333    XMesaBuffer xmbuf = XMesaCreatePixmapBuffer(xmvis, pixmap, 0);
   2334    return xmbuf->ws.drawable; /* need to return an X ID */
   2335 }
   2336 
   2337 
   2338 PUBLIC GLXContext
   2339 glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config,
   2340                                int renderType, GLXContext shareCtx,
   2341                                Bool direct)
   2342 {
   2343    XMesaVisual xmvis = (XMesaVisual) config;
   2344 
   2345    if (!dpy || !config ||
   2346        (renderType != GLX_RGBA_TYPE && renderType != GLX_COLOR_INDEX_TYPE))
   2347       return 0;
   2348 
   2349    return create_context(dpy, xmvis,
   2350                          shareCtx ? shareCtx->xmesaContext : NULL,
   2351                          direct,
   2352                          1, 0, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, 0x0);
   2353 }
   2354 
   2355 
   2356 PUBLIC XVisualInfo *
   2357 glXGetVisualFromFBConfigSGIX(Display *dpy, GLXFBConfigSGIX config)
   2358 {
   2359    return glXGetVisualFromFBConfig(dpy, config);
   2360 }
   2361 
   2362 
   2363 PUBLIC GLXFBConfigSGIX
   2364 glXGetFBConfigFromVisualSGIX(Display *dpy, XVisualInfo *vis)
   2365 {
   2366    XMesaVisual xmvis = find_glx_visual(dpy, vis);
   2367    if (!xmvis) {
   2368       /* This visual wasn't found with glXChooseVisual() */
   2369       xmvis = create_glx_visual(dpy, vis);
   2370    }
   2371 
   2372    return (GLXFBConfigSGIX) xmvis;
   2373 }
   2374 
   2375 
   2376 
   2377 /*** GLX_SGIX_pbuffer ***/
   2378 
   2379 PUBLIC GLXPbufferSGIX
   2380 glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config,
   2381                         unsigned int width, unsigned int height,
   2382                         int *attribList)
   2383 {
   2384    XMesaVisual xmvis = (XMesaVisual) config;
   2385    XMesaBuffer xmbuf;
   2386    const int *attrib;
   2387    GLboolean useLargest = GL_FALSE, preserveContents = GL_FALSE;
   2388 
   2389    (void) dpy;
   2390 
   2391    for (attrib = attribList; attrib && *attrib; attrib++) {
   2392       switch (*attrib) {
   2393          case GLX_PRESERVED_CONTENTS_SGIX:
   2394             attrib++;
   2395             preserveContents = *attrib; /* ignored */
   2396             break;
   2397          case GLX_LARGEST_PBUFFER_SGIX:
   2398             attrib++;
   2399             useLargest = *attrib; /* ignored */
   2400             break;
   2401          default:
   2402             return 0;
   2403       }
   2404    }
   2405 
   2406    /* not used at this time */
   2407    (void) useLargest;
   2408    (void) preserveContents;
   2409 
   2410    xmbuf = XMesaCreatePBuffer( xmvis, 0, width, height);
   2411    /* A GLXPbuffer handle must be an X Drawable because that's what
   2412     * glXMakeCurrent takes.
   2413     */
   2414    return (GLXPbuffer) xmbuf->ws.drawable;
   2415 }
   2416 
   2417 
   2418 PUBLIC void
   2419 glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf)
   2420 {
   2421    XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf);
   2422    if (xmbuf) {
   2423       XMesaDestroyBuffer(xmbuf);
   2424    }
   2425 }
   2426 
   2427 
   2428 PUBLIC int
   2429 glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute,
   2430                        unsigned int *value)
   2431 {
   2432    const XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf);
   2433 
   2434    if (!xmbuf) {
   2435       /* Generate GLXBadPbufferSGIX for bad pbuffer */
   2436       return 0;
   2437    }
   2438 
   2439    switch (attribute) {
   2440       case GLX_PRESERVED_CONTENTS_SGIX:
   2441          *value = True;
   2442          break;
   2443       case GLX_LARGEST_PBUFFER_SGIX:
   2444          *value = xmesa_buffer_width(xmbuf) * xmesa_buffer_height(xmbuf);
   2445          break;
   2446       case GLX_WIDTH_SGIX:
   2447          *value = xmesa_buffer_width(xmbuf);
   2448          break;
   2449       case GLX_HEIGHT_SGIX:
   2450          *value = xmesa_buffer_height(xmbuf);
   2451          break;
   2452       case GLX_EVENT_MASK_SGIX:
   2453          *value = 0;  /* XXX might be wrong */
   2454          break;
   2455       default:
   2456          *value = 0;
   2457    }
   2458    return 0;
   2459 }
   2460 
   2461 
   2462 PUBLIC void
   2463 glXSelectEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long mask)
   2464 {
   2465    XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);
   2466    if (xmbuf) {
   2467       /* Note: we'll never generate clobber events */
   2468       xmbuf->selectedEvents = mask;
   2469    }
   2470 }
   2471 
   2472 
   2473 PUBLIC void
   2474 glXGetSelectedEventSGIX(Display *dpy, GLXDrawable drawable,
   2475                         unsigned long *mask)
   2476 {
   2477    XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);
   2478    if (xmbuf) {
   2479       *mask = xmbuf->selectedEvents;
   2480    }
   2481    else {
   2482       *mask = 0;
   2483    }
   2484 }
   2485 
   2486 
   2487 
   2488 /*** GLX_SGI_cushion ***/
   2489 
   2490 PUBLIC void
   2491 glXCushionSGI(Display *dpy, Window win, float cushion)
   2492 {
   2493    (void) dpy;
   2494    (void) win;
   2495    (void) cushion;
   2496 }
   2497 
   2498 
   2499 
   2500 /*** GLX_SGIX_video_resize ***/
   2501 
   2502 PUBLIC int
   2503 glXBindChannelToWindowSGIX(Display *dpy, int screen, int channel,
   2504                            Window window)
   2505 {
   2506    (void) dpy;
   2507    (void) screen;
   2508    (void) channel;
   2509    (void) window;
   2510    return 0;
   2511 }
   2512 
   2513 PUBLIC int
   2514 glXChannelRectSGIX(Display *dpy, int screen, int channel,
   2515                    int x, int y, int w, int h)
   2516 {
   2517    (void) dpy;
   2518    (void) screen;
   2519    (void) channel;
   2520    (void) x;
   2521    (void) y;
   2522    (void) w;
   2523    (void) h;
   2524    return 0;
   2525 }
   2526 
   2527 PUBLIC int
   2528 glXQueryChannelRectSGIX(Display *dpy, int screen, int channel,
   2529                         int *x, int *y, int *w, int *h)
   2530 {
   2531    (void) dpy;
   2532    (void) screen;
   2533    (void) channel;
   2534    (void) x;
   2535    (void) y;
   2536    (void) w;
   2537    (void) h;
   2538    return 0;
   2539 }
   2540 
   2541 PUBLIC int
   2542 glXQueryChannelDeltasSGIX(Display *dpy, int screen, int channel,
   2543                           int *dx, int *dy, int *dw, int *dh)
   2544 {
   2545    (void) dpy;
   2546    (void) screen;
   2547    (void) channel;
   2548    (void) dx;
   2549    (void) dy;
   2550    (void) dw;
   2551    (void) dh;
   2552    return 0;
   2553 }
   2554 
   2555 PUBLIC int
   2556 glXChannelRectSyncSGIX(Display *dpy, int screen, int channel, GLenum synctype)
   2557 {
   2558    (void) dpy;
   2559    (void) screen;
   2560    (void) channel;
   2561    (void) synctype;
   2562    return 0;
   2563 }
   2564 
   2565 
   2566 
   2567 /*** GLX_SGIX_dmbuffer **/
   2568 
   2569 #if defined(_DM_BUFFER_H_)
   2570 PUBLIC Bool
   2571 glXAssociateDMPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuffer,
   2572                           DMparams *params, DMbuffer dmbuffer)
   2573 {
   2574    (void) dpy;
   2575    (void) pbuffer;
   2576    (void) params;
   2577    (void) dmbuffer;
   2578    return False;
   2579 }
   2580 #endif
   2581 
   2582 
   2583 /*** GLX_SGIX_swap_group ***/
   2584 
   2585 PUBLIC void
   2586 glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable, GLXDrawable member)
   2587 {
   2588    (void) dpy;
   2589    (void) drawable;
   2590    (void) member;
   2591 }
   2592 
   2593 
   2594 
   2595 /*** GLX_SGIX_swap_barrier ***/
   2596 
   2597 PUBLIC void
   2598 glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable, int barrier)
   2599 {
   2600    (void) dpy;
   2601    (void) drawable;
   2602    (void) barrier;
   2603 }
   2604 
   2605 PUBLIC Bool
   2606 glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max)
   2607 {
   2608    (void) dpy;
   2609    (void) screen;
   2610    (void) max;
   2611    return False;
   2612 }
   2613 
   2614 
   2615 
   2616 /*** GLX_SUN_get_transparent_index ***/
   2617 
   2618 PUBLIC Status
   2619 glXGetTransparentIndexSUN(Display *dpy, Window overlay, Window underlay,
   2620                           long *pTransparent)
   2621 {
   2622    (void) dpy;
   2623    (void) overlay;
   2624    (void) underlay;
   2625    (void) pTransparent;
   2626    return 0;
   2627 }
   2628 
   2629 
   2630 
   2631 /*** GLX_MESA_release_buffers ***/
   2632 
   2633 /*
   2634  * Release the depth, stencil, accum buffers attached to a GLXDrawable
   2635  * (a window or pixmap) prior to destroying the GLXDrawable.
   2636  */
   2637 PUBLIC Bool
   2638 glXReleaseBuffersMESA( Display *dpy, GLXDrawable d )
   2639 {
   2640    XMesaBuffer b = XMesaFindBuffer(dpy, d);
   2641    if (b) {
   2642       XMesaDestroyBuffer(b);
   2643       return True;
   2644    }
   2645    return False;
   2646 }
   2647 
   2648 /*** GLX_EXT_texture_from_pixmap ***/
   2649 
   2650 PUBLIC void
   2651 glXBindTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer,
   2652                         const int *attrib_list)
   2653 {
   2654    XMesaBuffer b = XMesaFindBuffer(dpy, drawable);
   2655    if (b)
   2656       XMesaBindTexImage(dpy, b, buffer, attrib_list);
   2657 }
   2658 
   2659 PUBLIC void
   2660 glXReleaseTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer)
   2661 {
   2662    XMesaBuffer b = XMesaFindBuffer(dpy, drawable);
   2663    if (b)
   2664       XMesaReleaseTexImage(dpy, b, buffer);
   2665 }
   2666 
   2667 
   2668 
   2669 /*** GLX_ARB_create_context ***/
   2670 
   2671 GLXContext
   2672 glXCreateContextAttribsARB(Display *dpy, GLXFBConfig config,
   2673                            GLXContext shareCtx, Bool direct,
   2674                            const int *attrib_list)
   2675 {
   2676    XMesaVisual xmvis = (XMesaVisual) config;
   2677    int majorVersion = 1, minorVersion = 0;
   2678    int contextFlags = 0x0;
   2679    int profileMask = GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
   2680    int renderType = GLX_RGBA_TYPE;
   2681    unsigned i;
   2682    Bool done = False;
   2683    const int contextFlagsAll = (GLX_CONTEXT_DEBUG_BIT_ARB |
   2684                                 GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB);
   2685 
   2686    /* parse attrib_list */
   2687    for (i = 0; !done && attrib_list && attrib_list[i]; i++) {
   2688       switch (attrib_list[i]) {
   2689       case GLX_CONTEXT_MAJOR_VERSION_ARB:
   2690          majorVersion = attrib_list[++i];
   2691          break;
   2692       case GLX_CONTEXT_MINOR_VERSION_ARB:
   2693          minorVersion = attrib_list[++i];
   2694          break;
   2695       case GLX_CONTEXT_FLAGS_ARB:
   2696          contextFlags = attrib_list[++i];
   2697          break;
   2698       case GLX_CONTEXT_PROFILE_MASK_ARB:
   2699          profileMask = attrib_list[++i];
   2700          break;
   2701       case GLX_RENDER_TYPE:
   2702          renderType = attrib_list[++i];
   2703          break;
   2704       case 0:
   2705          /* end of list */
   2706          done = True;
   2707          break;
   2708       default:
   2709          /* bad attribute */
   2710          /* XXX generate BadValue X Error */
   2711          return NULL;
   2712       }
   2713    }
   2714 
   2715    /* check contextFlags */
   2716    if (contextFlags & ~contextFlagsAll) {
   2717       return NULL; /* generate BadValue X Error */
   2718    }
   2719 
   2720    /* check profileMask */
   2721    if (profileMask != GLX_CONTEXT_CORE_PROFILE_BIT_ARB &&
   2722        profileMask != GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB) {
   2723       return NULL; /* generate BadValue X Error */
   2724    }
   2725 
   2726    /* check version (generate BadMatch if bad) */
   2727    switch (majorVersion) {
   2728    case 1:
   2729       if (minorVersion < 0 || minorVersion > 5)
   2730          return NULL;
   2731       break;
   2732    case 2:
   2733       if (minorVersion < 0 || minorVersion > 1)
   2734          return NULL;
   2735       break;
   2736    case 3:
   2737       if (minorVersion < 0 || minorVersion > 2)
   2738          return NULL;
   2739       break;
   2740    case 4:
   2741       if (minorVersion < 0 || minorVersion > 0)
   2742          return NULL;
   2743       break;
   2744    default:
   2745       return NULL;
   2746    }
   2747 
   2748    if ((contextFlags & GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB) &&
   2749        majorVersion < 3)
   2750       return NULL; /* generate GLXBadProfileARB */
   2751 
   2752    if (renderType == GLX_COLOR_INDEX_TYPE && majorVersion >= 3)
   2753       return NULL; /* generate BadMatch */
   2754 
   2755    return create_context(dpy, xmvis,
   2756                          shareCtx ? shareCtx->xmesaContext : NULL,
   2757                          direct,
   2758                          majorVersion, minorVersion,
   2759                          profileMask, contextFlags);
   2760 }
   2761