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