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