"Fossies" - the Fresh Open Source Software Archive

Member "mesa-20.1.8/src/gallium/state_trackers/glx/xlib/glx_api.c" (16 Sep 2020, 71196 Bytes) of package /linux/misc/mesa-20.1.8.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "glx_api.c" see the Fossies "Dox" file reference documentation.

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