fakeglx.c

Go to the documentation of this file.
00001 /*
00002  * Mesa 3-D graphics library
00003  * Version:  7.1
00004  *
00005  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
00006  *
00007  * Permission is hereby granted, free of charge, to any person obtaining a
00008  * copy of this software and associated documentation files (the "Software"),
00009  * to deal in the Software without restriction, including without limitation
00010  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
00011  * and/or sell copies of the Software, and to permit persons to whom the
00012  * Software is furnished to do so, subject to the following conditions:
00013  *
00014  * The above copyright notice and this permission notice shall be included
00015  * in all copies or substantial portions of the Software.
00016  *
00017  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00018  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00019  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
00020  * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00021  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00022  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00023  */
00024 
00025 
00026 /*
00027  * This is an emulation of the GLX API which allows Mesa/GLX-based programs
00028  * to run on X servers which do not have the real GLX extension.
00029  *
00030  * Thanks to the contributors:
00031  *
00032  * Initial version:  Philip Brown (phil@bolthole.com)
00033  * Better glXGetConfig() support: Armin Liebchen (liebchen@asylum.cs.utah.edu)
00034  * Further visual-handling refinements: Wolfram Gloger
00035  *    (wmglo@Dent.MED.Uni-Muenchen.DE).
00036  *
00037  * Notes:
00038  *   Don't be fooled, stereo isn't supported yet.
00039  */
00040 
00041 
00042 
00043 #include "glxheader.h"
00044 #include "glxapi.h"
00045 #include "GL/xmesa.h"
00046 #include "context.h"
00047 #include "config.h"
00048 #include "macros.h"
00049 #include "imports.h"
00050 #include "mtypes.h"
00051 #include "version.h"
00052 #include "xfonts.h"
00053 #include "xmesaP.h"
00054 #include "state_tracker/st_context.h"
00055 #include "state_tracker/st_public.h"
00056 
00057 
00058 #ifdef __VMS
00059 #define _mesa_sprintf sprintf
00060 #endif
00061 
00062 /* This indicates the client-side GLX API and GLX encoder version. */
00063 #define CLIENT_MAJOR_VERSION 1
00064 #define CLIENT_MINOR_VERSION 4  /* but don't have 1.3's pbuffers, etc yet */
00065 
00066 /* This indicates the server-side GLX decoder version.
00067  * GLX 1.4 indicates OpenGL 1.3 support
00068  */
00069 #define SERVER_MAJOR_VERSION 1
00070 #define SERVER_MINOR_VERSION 4
00071 
00072 /* This is appended onto the glXGetClient/ServerString version strings. */
00073 #define MESA_GLX_VERSION "Mesa " MESA_VERSION_STRING
00074 
00075 /* Who implemented this GLX? */
00076 #define VENDOR "Brian Paul"
00077 
00078 #define EXTENSIONS \
00079    "GLX_MESA_set_3dfx_mode " \
00080    "GLX_MESA_copy_sub_buffer " \
00081    "GLX_MESA_pixmap_colormap " \
00082    "GLX_MESA_release_buffers " \
00083    "GLX_ARB_get_proc_address " \
00084    "GLX_EXT_texture_from_pixmap " \
00085    "GLX_EXT_visual_info " \
00086    "GLX_EXT_visual_rating " \
00087    /*"GLX_SGI_video_sync "*/ \
00088    "GLX_SGIX_fbconfig " \
00089    "GLX_SGIX_pbuffer "
00090 
00091 /*
00092  * Our fake GLX context will contain a "real" GLX context and an XMesa context.
00093  *
00094  * Note that a pointer to a __GLXcontext is a pointer to a fake_glx_context,
00095  * and vice versa.
00096  *
00097  * We really just need this structure in order to make the libGL functions
00098  * glXGetCurrentContext(), glXGetCurrentDrawable() and glXGetCurrentDisplay()
00099  * work correctly.
00100  */
00101 struct fake_glx_context {
00102    __GLXcontext glxContext;   /* this MUST be first! */
00103    XMesaContext xmesaContext;
00104 };
00105 
00106 
00107 
00108 /**********************************************************************/
00109 /***                       GLX Visual Code                          ***/
00110 /**********************************************************************/
00111 
00112 #define DONT_CARE -1
00113 
00114 
00115 static XMesaVisual *VisualTable = NULL;
00116 static int NumVisuals = 0;
00117 
00118 
00119 /*
00120  * This struct and some code fragments borrowed
00121  * from Mark Kilgard's GLUT library.
00122  */
00123 typedef struct _OverlayInfo {
00124   /* Avoid 64-bit portability problems by being careful to use
00125      longs due to the way XGetWindowProperty is specified. Note
00126      that these parameters are passed as CARD32s over X
00127      protocol. */
00128   unsigned long overlay_visual;
00129   long transparent_type;
00130   long value;
00131   long layer;
00132 } OverlayInfo;
00133 
00134 
00135 
00136 /* Macro to handle c_class vs class field name in XVisualInfo struct */
00137 #if defined(__cplusplus) || defined(c_plusplus)
00138 #define CLASS c_class
00139 #else
00140 #define CLASS class
00141 #endif
00142 
00143 
00144 
00145 /*
00146  * Test if the given XVisualInfo is usable for Mesa rendering.
00147  */
00148 static GLboolean
00149 is_usable_visual( XVisualInfo *vinfo )
00150 {
00151    switch (vinfo->CLASS) {
00152       case StaticGray:
00153       case GrayScale:
00154          /* Any StaticGray/GrayScale visual works in RGB or CI mode */
00155          return GL_TRUE;
00156       case StaticColor:
00157       case PseudoColor:
00158          /* Any StaticColor/PseudoColor visual of at least 4 bits */
00159          if (vinfo->depth>=4) {
00160             return GL_TRUE;
00161          }
00162          else {
00163             return GL_FALSE;
00164          }
00165       case TrueColor:
00166       case DirectColor:
00167          /* Any depth of TrueColor or DirectColor works in RGB mode */
00168          return GL_TRUE;
00169       default:
00170          /* This should never happen */
00171          return GL_FALSE;
00172    }
00173 }
00174 
00175 
00176 
00184 static OverlayInfo *
00185 GetOverlayInfo(Display *dpy, int screen, int *numOverlays)
00186 {
00187    Atom overlayVisualsAtom;
00188    Atom actualType;
00189    Status status;
00190    unsigned char *ovInfo;
00191    unsigned long sizeData, bytesLeft;
00192    int actualFormat;
00193 
00194    /*
00195     * The SERVER_OVERLAY_VISUALS property on the root window contains
00196     * a list of overlay visuals.  Get that list now.
00197     */
00198    overlayVisualsAtom = XInternAtom(dpy,"SERVER_OVERLAY_VISUALS", True);
00199    if (overlayVisualsAtom == None) {
00200       return 0;
00201    }
00202 
00203    status = XGetWindowProperty(dpy, RootWindow(dpy, screen),
00204                                overlayVisualsAtom, 0L, (long) 10000, False,
00205                                overlayVisualsAtom, &actualType, &actualFormat,
00206                                &sizeData, &bytesLeft,
00207                                &ovInfo);
00208 
00209    if (status != Success || actualType != overlayVisualsAtom ||
00210        actualFormat != 32 || sizeData < 4) {
00211       /* something went wrong */
00212       XFree((void *) ovInfo);
00213       *numOverlays = 0;
00214       return NULL;
00215    }
00216 
00217    *numOverlays = sizeData / 4;
00218    return (OverlayInfo *) ovInfo;
00219 }
00220 
00221 
00222 
00232 static int
00233 level_of_visual( Display *dpy, XVisualInfo *vinfo )
00234 {
00235    OverlayInfo *overlay_info;
00236    int numOverlaysPerScreen, i;
00237 
00238    overlay_info = GetOverlayInfo(dpy, vinfo->screen, &numOverlaysPerScreen);
00239    if (!overlay_info) {
00240       return 0;
00241    }
00242 
00243    /* search the overlay visual list for the visual ID of interest */
00244    for (i = 0; i < numOverlaysPerScreen; i++) {
00245       const OverlayInfo *ov = overlay_info + i;
00246       if (ov->overlay_visual == vinfo->visualid) {
00247          /* found the visual */
00248          if (/*ov->transparent_type==1 &&*/ ov->layer!=0) {
00249             int level = ov->layer;
00250             XFree((void *) overlay_info);
00251             return level;
00252          }
00253          else {
00254             XFree((void *) overlay_info);
00255             return 0;
00256          }
00257       }
00258    }
00259 
00260    /* The visual ID was not found in the overlay list. */
00261    XFree((void *) overlay_info);
00262    return 0;
00263 }
00264 
00265 
00266 
00267 
00268 /*
00269  * Given an XVisualInfo and RGB, Double, and Depth buffer flags, save the
00270  * configuration in our list of GLX visuals.
00271  */
00272 static XMesaVisual
00273 save_glx_visual( Display *dpy, XVisualInfo *vinfo,
00274                  GLboolean rgbFlag, GLboolean alphaFlag, GLboolean dbFlag,
00275                  GLboolean stereoFlag,
00276                  GLint depth_size, GLint stencil_size,
00277                  GLint accumRedSize, GLint accumGreenSize,
00278                  GLint accumBlueSize, GLint accumAlphaSize,
00279                  GLint level, GLint numAuxBuffers )
00280 {
00281    GLboolean ximageFlag = GL_TRUE;
00282    XMesaVisual xmvis;
00283    GLint i;
00284    GLboolean comparePointers;
00285 
00286    if (dbFlag) {
00287       /* Check if the MESA_BACK_BUFFER env var is set */
00288       char *backbuffer = _mesa_getenv("MESA_BACK_BUFFER");
00289       if (backbuffer) {
00290          if (backbuffer[0]=='p' || backbuffer[0]=='P') {
00291             ximageFlag = GL_FALSE;
00292          }
00293          else if (backbuffer[0]=='x' || backbuffer[0]=='X') {
00294             ximageFlag = GL_TRUE;
00295          }
00296          else {
00297             _mesa_warning(NULL, "Mesa: invalid value for MESA_BACK_BUFFER environment variable, using an XImage.");
00298          }
00299       }
00300    }
00301 
00302    if (stereoFlag) {
00303       /* stereo not supported */
00304       return NULL;
00305    }
00306 
00307    if (stencil_size > 0 && depth_size > 0)
00308       depth_size = 24;
00309 
00310    /* Comparing IDs uses less memory but sometimes fails. */
00311    /* XXX revisit this after 3.0 is finished. */
00312    if (_mesa_getenv("MESA_GLX_VISUAL_HACK"))
00313       comparePointers = GL_TRUE;
00314    else
00315       comparePointers = GL_FALSE;
00316 
00317    /* Force the visual to have an alpha channel */
00318    if (rgbFlag && _mesa_getenv("MESA_GLX_FORCE_ALPHA"))
00319       alphaFlag = GL_TRUE;
00320 
00321    /* First check if a matching visual is already in the list */
00322    for (i=0; i<NumVisuals; i++) {
00323       XMesaVisual v = VisualTable[i];
00324       if (v->display == dpy
00325           && v->mesa_visual.level == level
00326           && v->mesa_visual.numAuxBuffers == numAuxBuffers
00327           && v->ximage_flag == ximageFlag
00328           && v->mesa_visual.rgbMode == rgbFlag
00329           && v->mesa_visual.doubleBufferMode == dbFlag
00330           && v->mesa_visual.stereoMode == stereoFlag
00331           && (v->mesa_visual.alphaBits > 0) == alphaFlag
00332           && (v->mesa_visual.depthBits >= depth_size || depth_size == 0)
00333           && (v->mesa_visual.stencilBits >= stencil_size || stencil_size == 0)
00334           && (v->mesa_visual.accumRedBits >= accumRedSize || accumRedSize == 0)
00335           && (v->mesa_visual.accumGreenBits >= accumGreenSize || accumGreenSize == 0)
00336           && (v->mesa_visual.accumBlueBits >= accumBlueSize || accumBlueSize == 0)
00337           && (v->mesa_visual.accumAlphaBits >= accumAlphaSize || accumAlphaSize == 0)) {
00338          /* now either compare XVisualInfo pointers or visual IDs */
00339          if ((!comparePointers && v->visinfo->visualid == vinfo->visualid)
00340              || (comparePointers && v->vishandle == vinfo)) {
00341             return v;
00342          }
00343       }
00344    }
00345 
00346    /* Create a new visual and add it to the list. */
00347 
00348    xmvis = XMesaCreateVisual( dpy, vinfo, rgbFlag, alphaFlag, dbFlag,
00349                               stereoFlag, ximageFlag,
00350                               depth_size, stencil_size,
00351                               accumRedSize, accumBlueSize,
00352                               accumBlueSize, accumAlphaSize, 0, level,
00353                               GLX_NONE_EXT );
00354    if (xmvis) {
00355       /* Save a copy of the pointer now so we can find this visual again
00356        * if we need to search for it in find_glx_visual().
00357        */
00358       xmvis->vishandle = vinfo;
00359       /* Allocate more space for additional visual */
00360       VisualTable = (XMesaVisual *) _mesa_realloc( VisualTable, 
00361                                    sizeof(XMesaVisual) * NumVisuals, 
00362                                    sizeof(XMesaVisual) * (NumVisuals + 1));
00363       /* add xmvis to the list */
00364       VisualTable[NumVisuals] = xmvis;
00365       NumVisuals++;
00366       /* XXX minor hack, because XMesaCreateVisual doesn't support an
00367        * aux buffers parameter.
00368        */
00369       xmvis->mesa_visual.numAuxBuffers = numAuxBuffers;
00370    }
00371    return xmvis;
00372 }
00373 
00374 
00381 static GLint
00382 default_depth_bits(void)
00383 {
00384    int zBits;
00385    const char *zEnv = _mesa_getenv("MESA_GLX_DEPTH_BITS");
00386    if (zEnv)
00387       zBits = _mesa_atoi(zEnv);
00388    else
00389       zBits = DEFAULT_SOFTWARE_DEPTH_BITS;
00390    return zBits;
00391 }
00392 
00393 static GLint
00394 default_alpha_bits(void)
00395 {
00396    int aBits;
00397    const char *aEnv = _mesa_getenv("MESA_GLX_ALPHA_BITS");
00398    if (aEnv)
00399       aBits = _mesa_atoi(aEnv);
00400    else
00401       aBits = 0;
00402    return aBits;
00403 }
00404 
00405 static GLint
00406 default_accum_bits(void)
00407 {
00408    return 16;
00409 }
00410 
00411 
00412 
00413 /*
00414  * Create a GLX visual from a regular XVisualInfo.
00415  * This is called when Fake GLX is given an XVisualInfo which wasn't
00416  * returned by glXChooseVisual.  Since this is the first time we're
00417  * considering this visual we'll take a guess at reasonable values
00418  * for depth buffer size, stencil size, accum size, etc.
00419  * This is the best we can do with a client-side emulation of GLX.
00420  */
00421 static XMesaVisual
00422 create_glx_visual( Display *dpy, XVisualInfo *visinfo )
00423 {
00424    int vislevel;
00425    GLint zBits = default_depth_bits();
00426    GLint accBits = default_accum_bits();
00427    GLboolean alphaFlag = default_alpha_bits() > 0;
00428 
00429    vislevel = level_of_visual( dpy, visinfo );
00430    if (vislevel) {
00431       /* Configure this visual as a CI, single-buffered overlay */
00432       return save_glx_visual( dpy, visinfo,
00433                               GL_FALSE,  /* rgb */
00434                               GL_FALSE,  /* alpha */
00435                               GL_FALSE,  /* double */
00436                               GL_FALSE,  /* stereo */
00437                               0,         /* depth bits */
00438                               0,         /* stencil bits */
00439                               0,0,0,0,   /* accum bits */
00440                               vislevel,  /* level */
00441                               0          /* numAux */
00442                             );
00443    }
00444    else if (is_usable_visual( visinfo )) {
00445       if (_mesa_getenv("MESA_GLX_FORCE_CI")) {
00446          /* Configure this visual as a COLOR INDEX visual. */
00447          return save_glx_visual( dpy, visinfo,
00448                                  GL_FALSE,   /* rgb */
00449                                  GL_FALSE,  /* alpha */
00450                                  GL_TRUE,   /* double */
00451                                  GL_FALSE,  /* stereo */
00452                                  zBits,
00453                                  STENCIL_BITS,
00454                                  0, 0, 0, 0, /* accum bits */
00455                                  0,         /* level */
00456                                  0          /* numAux */
00457                                );
00458       }
00459       else {
00460          /* Configure this visual as RGB, double-buffered, depth-buffered. */
00461          /* This is surely wrong for some people's needs but what else */
00462          /* can be done?  They should use glXChooseVisual(). */
00463          return save_glx_visual( dpy, visinfo,
00464                                  GL_TRUE,   /* rgb */
00465                                  alphaFlag, /* alpha */
00466                                  GL_TRUE,   /* double */
00467                                  GL_FALSE,  /* stereo */
00468                                  zBits,
00469                                  STENCIL_BITS,
00470                                  accBits, /* r */
00471                                  accBits, /* g */
00472                                  accBits, /* b */
00473                                  accBits, /* a */
00474                                  0,         /* level */
00475                                  0          /* numAux */
00476                                );
00477       }
00478    }
00479    else {
00480       _mesa_warning(NULL, "Mesa: error in glXCreateContext: bad visual\n");
00481       return NULL;
00482    }
00483 }
00484 
00485 
00486 
00487 /*
00488  * Find the GLX visual associated with an XVisualInfo.
00489  */
00490 static XMesaVisual
00491 find_glx_visual( Display *dpy, XVisualInfo *vinfo )
00492 {
00493    int i;
00494 
00495    /* try to match visual id */
00496    for (i=0;i<NumVisuals;i++) {
00497       if (VisualTable[i]->display==dpy
00498           && VisualTable[i]->visinfo->visualid == vinfo->visualid) {
00499          return VisualTable[i];
00500       }
00501    }
00502 
00503    /* if that fails, try to match pointers */
00504    for (i=0;i<NumVisuals;i++) {
00505       if (VisualTable[i]->display==dpy && VisualTable[i]->vishandle==vinfo) {
00506          return VisualTable[i];
00507       }
00508    }
00509 
00510    return NULL;
00511 }
00512 
00513 
00514 
00520 static int
00521 transparent_pixel( XMesaVisual glxvis )
00522 {
00523    Display *dpy = glxvis->display;
00524    XVisualInfo *vinfo = glxvis->visinfo;
00525    OverlayInfo *overlay_info;
00526    int numOverlaysPerScreen, i;
00527 
00528    overlay_info = GetOverlayInfo(dpy, vinfo->screen, &numOverlaysPerScreen);
00529    if (!overlay_info) {
00530       return -1;
00531    }
00532 
00533    for (i = 0; i < numOverlaysPerScreen; i++) {
00534       const OverlayInfo *ov = overlay_info + i;
00535       if (ov->overlay_visual == vinfo->visualid) {
00536          /* found it! */
00537          if (ov->transparent_type == 0) {
00538             /* type 0 indicates no transparency */
00539             XFree((void *) overlay_info);
00540             return -1;
00541          }
00542          else {
00543             /* ov->value is the transparent pixel */
00544             XFree((void *) overlay_info);
00545             return ov->value;
00546          }
00547       }
00548    }
00549 
00550    /* The visual ID was not found in the overlay list. */
00551    XFree((void *) overlay_info);
00552    return -1;
00553 }
00554 
00555 
00556 
00560 static XVisualInfo *
00561 get_visual( Display *dpy, int scr, unsigned int depth, int xclass )
00562 {
00563    XVisualInfo temp, *vis;
00564    long mask;
00565    int n;
00566    unsigned int default_depth;
00567    int default_class;
00568 
00569    mask = VisualScreenMask | VisualDepthMask | VisualClassMask;
00570    temp.screen = scr;
00571    temp.depth = depth;
00572    temp.CLASS = xclass;
00573 
00574    default_depth = DefaultDepth(dpy,scr);
00575    default_class = DefaultVisual(dpy,scr)->CLASS;
00576 
00577    if (depth==default_depth && xclass==default_class) {
00578       /* try to get root window's visual */
00579       temp.visualid = DefaultVisual(dpy,scr)->visualid;
00580       mask |= VisualIDMask;
00581    }
00582 
00583    vis = XGetVisualInfo( dpy, mask, &temp, &n );
00584 
00585    /* In case bits/pixel > 24, make sure color channels are still <=8 bits.
00586     * An SGI Infinite Reality system, for example, can have 30bpp pixels:
00587     * 10 bits per color channel.  Mesa's limited to a max of 8 bits/channel.
00588     */
00589    if (vis && depth > 24 && (xclass==TrueColor || xclass==DirectColor)) {
00590       if (_mesa_bitcount((GLuint) vis->red_mask  ) <= 8 &&
00591           _mesa_bitcount((GLuint) vis->green_mask) <= 8 &&
00592           _mesa_bitcount((GLuint) vis->blue_mask ) <= 8) {
00593          return vis;
00594       }
00595       else {
00596          XFree((void *) vis);
00597          return NULL;
00598       }
00599    }
00600 
00601    return vis;
00602 }
00603 
00604 
00605 
00606 /*
00607  * Retrieve the value of the given environment variable and find
00608  * the X visual which matches it.
00609  * Input:  dpy - the display
00610  *         screen - the screen number
00611  *         varname - the name of the environment variable
00612  * Return:  an XVisualInfo pointer to NULL if error.
00613  */
00614 static XVisualInfo *
00615 get_env_visual(Display *dpy, int scr, const char *varname)
00616 {
00617    char value[100], type[100];
00618    int depth, xclass = -1;
00619    XVisualInfo *vis;
00620 
00621    if (!_mesa_getenv( varname )) {
00622       return NULL;
00623    }
00624 
00625    _mesa_strncpy( value, _mesa_getenv(varname), 100 );
00626    value[99] = 0;
00627 
00628    sscanf( value, "%s %d", type, &depth );
00629 
00630    if (_mesa_strcmp(type,"TrueColor")==0)          xclass = TrueColor;
00631    else if (_mesa_strcmp(type,"DirectColor")==0)   xclass = DirectColor;
00632    else if (_mesa_strcmp(type,"PseudoColor")==0)   xclass = PseudoColor;
00633    else if (_mesa_strcmp(type,"StaticColor")==0)   xclass = StaticColor;
00634    else if (_mesa_strcmp(type,"GrayScale")==0)     xclass = GrayScale;
00635    else if (_mesa_strcmp(type,"StaticGray")==0)    xclass = StaticGray;
00636 
00637    if (xclass>-1 && depth>0) {
00638       vis = get_visual( dpy, scr, depth, xclass );
00639       if (vis) {
00640          return vis;
00641       }
00642    }
00643 
00644    _mesa_warning(NULL, "GLX unable to find visual class=%s, depth=%d.",
00645                  type, depth);
00646 
00647    return NULL;
00648 }
00649 
00650 
00651 
00652 /*
00653  * Select an X visual which satisfies the RGBA/CI flag and minimum depth.
00654  * Input:  dpy, screen - X display and screen number
00655  *         rgba - GL_TRUE = RGBA mode, GL_FALSE = CI mode
00656  *         min_depth - minimum visual depth
00657  *         preferred_class - preferred GLX visual class or DONT_CARE
00658  * Return:  pointer to an XVisualInfo or NULL.
00659  */
00660 static XVisualInfo *
00661 choose_x_visual( Display *dpy, int screen, GLboolean rgba, int min_depth,
00662                  int preferred_class )
00663 {
00664    XVisualInfo *vis;
00665    int xclass, visclass = 0;
00666    int depth;
00667 
00668    if (rgba) {
00669       Atom hp_cr_maps = XInternAtom(dpy, "_HP_RGB_SMOOTH_MAP_LIST", True);
00670       /* First see if the MESA_RGB_VISUAL env var is defined */
00671       vis = get_env_visual( dpy, screen, "MESA_RGB_VISUAL" );
00672       if (vis) {
00673          return vis;
00674       }
00675       /* Otherwise, search for a suitable visual */
00676       if (preferred_class==DONT_CARE) {
00677          for (xclass=0;xclass<6;xclass++) {
00678             switch (xclass) {
00679                case 0:  visclass = TrueColor;    break;
00680                case 1:  visclass = DirectColor;  break;
00681                case 2:  visclass = PseudoColor;  break;
00682                case 3:  visclass = StaticColor;  break;
00683                case 4:  visclass = GrayScale;    break;
00684                case 5:  visclass = StaticGray;   break;
00685             }
00686             if (min_depth==0) {
00687                /* start with shallowest */
00688                for (depth=0;depth<=32;depth++) {
00689                   if (visclass==TrueColor && depth==8 && !hp_cr_maps) {
00690                      /* Special case:  try to get 8-bit PseudoColor before */
00691                      /* 8-bit TrueColor */
00692                      vis = get_visual( dpy, screen, 8, PseudoColor );
00693                      if (vis) {
00694                         return vis;
00695                      }
00696                   }
00697                   vis = get_visual( dpy, screen, depth, visclass );
00698                   if (vis) {
00699                      return vis;
00700                   }
00701                }
00702             }
00703             else {
00704                /* start with deepest */
00705                for (depth=32;depth>=min_depth;depth--) {
00706                   if (visclass==TrueColor && depth==8 && !hp_cr_maps) {
00707                      /* Special case:  try to get 8-bit PseudoColor before */
00708                      /* 8-bit TrueColor */
00709                      vis = get_visual( dpy, screen, 8, PseudoColor );
00710                      if (vis) {
00711                         return vis;
00712                      }
00713                   }
00714                   vis = get_visual( dpy, screen, depth, visclass );
00715                   if (vis) {
00716                      return vis;
00717                   }
00718                }
00719             }
00720          }
00721       }
00722       else {
00723          /* search for a specific visual class */
00724          switch (preferred_class) {
00725             case GLX_TRUE_COLOR_EXT:    visclass = TrueColor;    break;
00726             case GLX_DIRECT_COLOR_EXT:  visclass = DirectColor;  break;
00727             case GLX_PSEUDO_COLOR_EXT:  visclass = PseudoColor;  break;
00728             case GLX_STATIC_COLOR_EXT:  visclass = StaticColor;  break;
00729             case GLX_GRAY_SCALE_EXT:    visclass = GrayScale;    break;
00730             case GLX_STATIC_GRAY_EXT:   visclass = StaticGray;   break;
00731             default:   return NULL;
00732          }
00733          if (min_depth==0) {
00734             /* start with shallowest */
00735             for (depth=0;depth<=32;depth++) {
00736                vis = get_visual( dpy, screen, depth, visclass );
00737                if (vis) {
00738                   return vis;
00739                }
00740             }
00741          }
00742          else {
00743             /* start with deepest */
00744             for (depth=32;depth>=min_depth;depth--) {
00745                vis = get_visual( dpy, screen, depth, visclass );
00746                if (vis) {
00747                   return vis;
00748                }
00749             }
00750          }
00751       }
00752    }
00753    else {
00754       /* First see if the MESA_CI_VISUAL env var is defined */
00755       vis = get_env_visual( dpy, screen, "MESA_CI_VISUAL" );
00756       if (vis) {
00757          return vis;
00758       }
00759       /* Otherwise, search for a suitable visual, starting with shallowest */
00760       if (preferred_class==DONT_CARE) {
00761          for (xclass=0;xclass<4;xclass++) {
00762             switch (xclass) {
00763                case 0:  visclass = PseudoColor;  break;
00764                case 1:  visclass = StaticColor;  break;
00765                case 2:  visclass = GrayScale;    break;
00766                case 3:  visclass = StaticGray;   break;
00767             }
00768             /* try 8-bit up through 16-bit */
00769             for (depth=8;depth<=16;depth++) {
00770                vis = get_visual( dpy, screen, depth, visclass );
00771                if (vis) {
00772                   return vis;
00773                }
00774             }
00775             /* try min_depth up to 8-bit */
00776             for (depth=min_depth;depth<8;depth++) {
00777                vis = get_visual( dpy, screen, depth, visclass );
00778                if (vis) {
00779                   return vis;
00780                }
00781             }
00782          }
00783       }
00784       else {
00785          /* search for a specific visual class */
00786          switch (preferred_class) {
00787             case GLX_TRUE_COLOR_EXT:    visclass = TrueColor;    break;
00788             case GLX_DIRECT_COLOR_EXT:  visclass = DirectColor;  break;
00789             case GLX_PSEUDO_COLOR_EXT:  visclass = PseudoColor;  break;
00790             case GLX_STATIC_COLOR_EXT:  visclass = StaticColor;  break;
00791             case GLX_GRAY_SCALE_EXT:    visclass = GrayScale;    break;
00792             case GLX_STATIC_GRAY_EXT:   visclass = StaticGray;   break;
00793             default:   return NULL;
00794          }
00795          /* try 8-bit up through 16-bit */
00796          for (depth=8;depth<=16;depth++) {
00797             vis = get_visual( dpy, screen, depth, visclass );
00798             if (vis) {
00799                return vis;
00800             }
00801          }
00802          /* try min_depth up to 8-bit */
00803          for (depth=min_depth;depth<8;depth++) {
00804             vis = get_visual( dpy, screen, depth, visclass );
00805             if (vis) {
00806                return vis;
00807             }
00808          }
00809       }
00810    }
00811 
00812    /* didn't find a visual */
00813    return NULL;
00814 }
00815 
00816 
00817 
00818 /*
00819  * Find the deepest X over/underlay visual of at least min_depth.
00820  * Input:  dpy, screen - X display and screen number
00821  *         level - the over/underlay level
00822  *         trans_type - transparent pixel type: GLX_NONE_EXT,
00823  *                      GLX_TRANSPARENT_RGB_EXT, GLX_TRANSPARENT_INDEX_EXT,
00824  *                      or DONT_CARE
00825  *         trans_value - transparent pixel value or DONT_CARE
00826  *         min_depth - minimum visual depth
00827  *         preferred_class - preferred GLX visual class or DONT_CARE
00828  * Return:  pointer to an XVisualInfo or NULL.
00829  */
00830 static XVisualInfo *
00831 choose_x_overlay_visual( Display *dpy, int scr, GLboolean rgbFlag,
00832                          int level, int trans_type, int trans_value,
00833                          int min_depth, int preferred_class )
00834 {
00835    OverlayInfo *overlay_info;
00836    int numOverlaysPerScreen;
00837    int i;
00838    XVisualInfo *deepvis;
00839    int deepest;
00840 
00841    /*DEBUG int tt, tv; */
00842 
00843    switch (preferred_class) {
00844       case GLX_TRUE_COLOR_EXT:    preferred_class = TrueColor;    break;
00845       case GLX_DIRECT_COLOR_EXT:  preferred_class = DirectColor;  break;
00846       case GLX_PSEUDO_COLOR_EXT:  preferred_class = PseudoColor;  break;
00847       case GLX_STATIC_COLOR_EXT:  preferred_class = StaticColor;  break;
00848       case GLX_GRAY_SCALE_EXT:    preferred_class = GrayScale;    break;
00849       case GLX_STATIC_GRAY_EXT:   preferred_class = StaticGray;   break;
00850       default:                    preferred_class = DONT_CARE;
00851    }
00852 
00853    overlay_info = GetOverlayInfo(dpy, scr, &numOverlaysPerScreen);
00854    if (!overlay_info) {
00855       return NULL;
00856    }
00857 
00858    /* Search for the deepest overlay which satisifies all criteria. */
00859    deepest = min_depth;
00860    deepvis = NULL;
00861 
00862    for (i = 0; i < numOverlaysPerScreen; i++) {
00863       const OverlayInfo *ov = overlay_info + i;
00864       XVisualInfo *vislist, vistemplate;
00865       int count;
00866 
00867       if (ov->layer!=level) {
00868          /* failed overlay level criteria */
00869          continue;
00870       }
00871       if (!(trans_type==DONT_CARE
00872             || (trans_type==GLX_TRANSPARENT_INDEX_EXT
00873                 && ov->transparent_type>0)
00874             || (trans_type==GLX_NONE_EXT && ov->transparent_type==0))) {
00875          /* failed transparent pixel type criteria */
00876          continue;
00877       }
00878       if (trans_value!=DONT_CARE && trans_value!=ov->value) {
00879          /* failed transparent pixel value criteria */
00880          continue;
00881       }
00882 
00883       /* get XVisualInfo and check the depth */
00884       vistemplate.visualid = ov->overlay_visual;
00885       vistemplate.screen = scr;
00886       vislist = XGetVisualInfo( dpy, VisualIDMask | VisualScreenMask,
00887                                 &vistemplate, &count );
00888 
00889       if (count!=1) {
00890          /* something went wrong */
00891          continue;
00892       }
00893       if (preferred_class!=DONT_CARE && preferred_class!=vislist->CLASS) {
00894          /* wrong visual class */
00895          continue;
00896       }
00897 
00898       /* if RGB was requested, make sure we have True/DirectColor */
00899       if (rgbFlag && vislist->CLASS != TrueColor
00900           && vislist->CLASS != DirectColor)
00901          continue;
00902 
00903       /* if CI was requested, make sure we have a color indexed visual */
00904       if (!rgbFlag
00905           && (vislist->CLASS == TrueColor || vislist->CLASS == DirectColor))
00906          continue;
00907 
00908       if (deepvis==NULL || vislist->depth > deepest) {
00909          /* YES!  found a satisfactory visual */
00910          if (deepvis) {
00911             XFree( deepvis );
00912          }
00913          deepest = vislist->depth;
00914          deepvis = vislist;
00915          /* DEBUG  tt = ov->transparent_type;*/
00916          /* DEBUG  tv = ov->value; */
00917       }
00918    }
00919 
00920 /*DEBUG
00921    if (deepvis) {
00922       printf("chose 0x%x:  layer=%d depth=%d trans_type=%d trans_value=%d\n",
00923              deepvis->visualid, level, deepvis->depth, tt, tv );
00924    }
00925 */
00926    return deepvis;
00927 }
00928 
00929 
00930 /**********************************************************************/
00931 /***             Display-related functions                          ***/
00932 /**********************************************************************/
00933 
00934 
00938 static void
00939 destroy_visuals_on_display(Display *dpy)
00940 {
00941    int i;
00942    for (i = 0; i < NumVisuals; i++) {
00943       if (VisualTable[i]->display == dpy) {
00944          /* remove this visual */
00945          int j;
00946          free(VisualTable[i]);
00947          for (j = i; j < NumVisuals - 1; j++)
00948             VisualTable[j] = VisualTable[j + 1];
00949          NumVisuals--;
00950       }
00951    }
00952 }
00953 
00954 
00958 static int
00959 close_display_callback(Display *dpy, XExtCodes *codes)
00960 {
00961    destroy_visuals_on_display(dpy);
00962    xmesa_destroy_buffers_on_display(dpy);
00963    return 0;
00964 }
00965 
00966 
00971 static _XExtension *
00972 lookup_extension(Display *dpy, const char *extName)
00973 {
00974    _XExtension *ext;
00975    for (ext = dpy->ext_procs; ext; ext = ext->next) {
00976       if (ext->name && strcmp(ext->name, extName) == 0) {
00977          return ext;
00978       }
00979    }
00980    return NULL;
00981 }
00982 
00983 
00988 static void
00989 register_with_display(Display *dpy)
00990 {
00991    const char *extName = "MesaGLX";
00992    _XExtension *ext;
00993 
00994    ext = lookup_extension(dpy, extName);
00995    if (!ext) {
00996       XExtCodes *c = XAddExtension(dpy);
00997       ext = dpy->ext_procs;  /* new extension is at head of list */
00998       assert(c->extension == ext->codes.extension);
00999       ext->name = _mesa_strdup(extName);
01000       ext->close_display = close_display_callback;
01001    }
01002 }
01003 
01004 
01005 /**********************************************************************/
01006 /***                  Begin Fake GLX API Functions                  ***/
01007 /**********************************************************************/
01008 
01009 
01016 static XMesaVisual
01017 choose_visual( Display *dpy, int screen, const int *list, GLboolean fbConfig )
01018 {
01019    const GLboolean rgbModeDefault = fbConfig;
01020    const int *parselist;
01021    XVisualInfo *vis;
01022    int min_ci = 0;
01023    int min_red=0, min_green=0, min_blue=0;
01024    GLboolean rgb_flag = rgbModeDefault;
01025    GLboolean alpha_flag = GL_FALSE;
01026    GLboolean double_flag = GL_FALSE;
01027    GLboolean stereo_flag = GL_FALSE;
01028    GLint depth_size = 0;
01029    GLint stencil_size = 0;
01030    GLint accumRedSize = 0;
01031    GLint accumGreenSize = 0;
01032    GLint accumBlueSize = 0;
01033    GLint accumAlphaSize = 0;
01034    int level = 0;
01035    int visual_type = DONT_CARE;
01036    int trans_type = DONT_CARE;
01037    int trans_value = DONT_CARE;
01038    GLint caveat = DONT_CARE;
01039    XMesaVisual xmvis = NULL;
01040    int desiredVisualID = -1;
01041    int numAux = 0;
01042 
01043    parselist = list;
01044 
01045    while (*parselist) {
01046 
01047       switch (*parselist) {
01048          case GLX_USE_GL:
01049             if (fbConfig) {
01050                /* invalid token */
01051                return NULL;
01052             }
01053             else {
01054                /* skip */
01055                parselist++;
01056             }
01057             break;
01058          case GLX_BUFFER_SIZE:
01059             parselist++;
01060             min_ci = *parselist++;
01061             break;
01062          case GLX_LEVEL:
01063             parselist++;
01064             level = *parselist++;
01065             break;
01066          case GLX_RGBA:
01067             if (fbConfig) {
01068                /* invalid token */
01069                return NULL;
01070             }
01071             else {
01072                rgb_flag = GL_TRUE;
01073                parselist++;
01074             }
01075             break;
01076          case GLX_DOUBLEBUFFER:
01077             parselist++;
01078             if (fbConfig) {
01079                double_flag = *parselist++;
01080             }
01081             else {
01082                double_flag = GL_TRUE;
01083             }
01084             break;
01085          case GLX_STEREO:
01086             parselist++;
01087             if (fbConfig) {
01088                stereo_flag = *parselist++;
01089             }
01090             else {
01091                stereo_flag = GL_TRUE;
01092             }
01093             break;
01094          case GLX_AUX_BUFFERS:
01095             parselist++;
01096             numAux = *parselist++;
01097             if (numAux > MAX_AUX_BUFFERS)
01098                return NULL;
01099             break;
01100          case GLX_RED_SIZE:
01101             parselist++;
01102             min_red = *parselist++;
01103             break;
01104          case GLX_GREEN_SIZE:
01105             parselist++;
01106             min_green = *parselist++;
01107             break;
01108          case GLX_BLUE_SIZE:
01109             parselist++;
01110             min_blue = *parselist++;
01111             break;
01112          case GLX_ALPHA_SIZE:
01113             parselist++;
01114             {
01115                GLint size = *parselist++;
01116                alpha_flag = size ? GL_TRUE : GL_FALSE;
01117             }
01118             break;
01119          case GLX_DEPTH_SIZE:
01120             parselist++;
01121             depth_size = *parselist++;
01122             break;
01123          case GLX_STENCIL_SIZE:
01124             parselist++;
01125             stencil_size = *parselist++;
01126             break;
01127          case GLX_ACCUM_RED_SIZE:
01128             parselist++;
01129             {
01130                GLint size = *parselist++;
01131                accumRedSize = MAX2( accumRedSize, size );
01132             }
01133             break;
01134          case GLX_ACCUM_GREEN_SIZE:
01135             parselist++;
01136             {
01137                GLint size = *parselist++;
01138                accumGreenSize = MAX2( accumGreenSize, size );
01139             }
01140             break;
01141          case GLX_ACCUM_BLUE_SIZE:
01142             parselist++;
01143             {
01144                GLint size = *parselist++;
01145                accumBlueSize = MAX2( accumBlueSize, size );
01146             }
01147             break;
01148          case GLX_ACCUM_ALPHA_SIZE:
01149             parselist++;
01150             {
01151                GLint size = *parselist++;
01152                accumAlphaSize = MAX2( accumAlphaSize, size );
01153             }
01154             break;
01155 
01156          /*
01157           * GLX_EXT_visual_info extension
01158           */
01159          case GLX_X_VISUAL_TYPE_EXT:
01160             parselist++;
01161             visual_type = *parselist++;
01162             break;
01163          case GLX_TRANSPARENT_TYPE_EXT:
01164             parselist++;
01165             trans_type = *parselist++;
01166             break;
01167          case GLX_TRANSPARENT_INDEX_VALUE_EXT:
01168             parselist++;
01169             trans_value = *parselist++;
01170             break;
01171          case GLX_TRANSPARENT_RED_VALUE_EXT:
01172          case GLX_TRANSPARENT_GREEN_VALUE_EXT:
01173          case GLX_TRANSPARENT_BLUE_VALUE_EXT:
01174          case GLX_TRANSPARENT_ALPHA_VALUE_EXT:
01175             /* ignore */
01176             parselist++;
01177             parselist++;
01178             break;
01179 
01180          /*
01181           * GLX_EXT_visual_info extension
01182           */
01183          case GLX_VISUAL_CAVEAT_EXT:
01184             parselist++;
01185             caveat = *parselist++; /* ignored for now */
01186             break;
01187 
01188          /*
01189           * GLX_ARB_multisample
01190           */
01191          case GLX_SAMPLE_BUFFERS_ARB:
01192             /* ms not supported */
01193             return NULL;
01194          case GLX_SAMPLES_ARB:
01195             /* ms not supported */
01196             return NULL;
01197 
01198          /*
01199           * FBConfig attribs.
01200           */
01201          case GLX_RENDER_TYPE:
01202             if (!fbConfig)
01203                return NULL;
01204             parselist++;
01205             if (*parselist == GLX_RGBA_BIT) {
01206                rgb_flag = GL_TRUE;
01207             }
01208             else if (*parselist == GLX_COLOR_INDEX_BIT) {
01209                rgb_flag = GL_FALSE;
01210             }
01211             else if (*parselist == 0) {
01212                rgb_flag = GL_TRUE;
01213             }
01214             parselist++;
01215             break;
01216          case GLX_DRAWABLE_TYPE:
01217             if (!fbConfig)
01218                return NULL;
01219             parselist++;
01220             if (*parselist & ~(GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT)) {
01221                return NULL; /* bad bit */
01222             }
01223             parselist++;
01224             break;
01225          case GLX_FBCONFIG_ID:
01226             if (!fbConfig)
01227                return NULL;
01228             parselist++;
01229             desiredVisualID = *parselist++;
01230             break;
01231          case GLX_X_RENDERABLE:
01232             if (!fbConfig)
01233                return NULL;
01234             parselist += 2;
01235             /* ignore */
01236             break;
01237 
01238 #ifdef GLX_EXT_texture_from_pixmap
01239          case GLX_BIND_TO_TEXTURE_RGB_EXT:
01240             parselist++; /*skip*/
01241             break;
01242          case GLX_BIND_TO_TEXTURE_RGBA_EXT:
01243             parselist++; /*skip*/
01244             break;
01245          case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
01246             parselist++; /*skip*/
01247             break;
01248          case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
01249             parselist++;
01250             if (*parselist & ~(GLX_TEXTURE_1D_BIT_EXT |
01251                                GLX_TEXTURE_2D_BIT_EXT |
01252                                GLX_TEXTURE_RECTANGLE_BIT_EXT)) {
01253                /* invalid bit */
01254                return NULL;
01255             }
01256             break;
01257          case GLX_Y_INVERTED_EXT:
01258             parselist++; /*skip*/
01259             break;
01260 #endif
01261 
01262          case None:
01263             /* end of list */
01264             break;
01265 
01266          default:
01267             /* undefined attribute */
01268             _mesa_warning(NULL, "unexpected attrib 0x%x in choose_visual()",
01269                           *parselist);
01270             return NULL;
01271       }
01272    }
01273 
01274    (void) caveat;
01275 
01276    /*
01277     * Since we're only simulating the GLX extension this function will never
01278     * find any real GL visuals.  Instead, all we can do is try to find an RGB
01279     * or CI visual of appropriate depth.  Other requested attributes such as
01280     * double buffering, depth buffer, etc. will be associated with the X
01281     * visual and stored in the VisualTable[].
01282     */
01283    if (desiredVisualID != -1) {
01284       /* try to get a specific visual, by visualID */
01285       XVisualInfo temp;
01286       int n;
01287       temp.visualid = desiredVisualID;
01288       temp.screen = screen;
01289       vis = XGetVisualInfo(dpy, VisualIDMask | VisualScreenMask, &temp, &n);
01290       if (vis) {
01291          /* give the visual some useful GLX attributes */
01292          double_flag = GL_TRUE;
01293          if (vis->depth > 8)
01294             rgb_flag = GL_TRUE;
01295          depth_size = default_depth_bits();
01296          stencil_size = STENCIL_BITS;
01297          /* XXX accum??? */
01298       }
01299    }
01300    else if (level==0) {
01301       /* normal color planes */
01302       if (rgb_flag) {
01303          /* Get an RGB visual */
01304          int min_rgb = min_red + min_green + min_blue;
01305          if (min_rgb>1 && min_rgb<8) {
01306             /* a special case to be sure we can get a monochrome visual */
01307             min_rgb = 1;
01308          }
01309          vis = choose_x_visual( dpy, screen, rgb_flag, min_rgb, visual_type );
01310       }
01311       else {
01312          /* Get a color index visual */
01313          vis = choose_x_visual( dpy, screen, rgb_flag, min_ci, visual_type );
01314          accumRedSize = accumGreenSize = accumBlueSize = accumAlphaSize = 0;
01315       }
01316    }
01317    else {
01318       /* over/underlay planes */
01319       if (rgb_flag) {
01320          /* rgba overlay */
01321          int min_rgb = min_red + min_green + min_blue;
01322          if (min_rgb>1 && min_rgb<8) {
01323             /* a special case to be sure we can get a monochrome visual */
01324             min_rgb = 1;
01325          }
01326          vis = choose_x_overlay_visual( dpy, screen, rgb_flag, level,
01327                               trans_type, trans_value, min_rgb, visual_type );
01328       }
01329       else {
01330          /* color index overlay */
01331          vis = choose_x_overlay_visual( dpy, screen, rgb_flag, level,
01332                               trans_type, trans_value, min_ci, visual_type );
01333       }
01334    }
01335 
01336    if (vis) {
01337       /* Note: we're not exactly obeying the glXChooseVisual rules here.
01338        * When GLX_DEPTH_SIZE = 1 is specified we're supposed to choose the
01339        * largest depth buffer size, which is 32bits/value.  Instead, we
01340        * return 16 to maintain performance with earlier versions of Mesa.
01341        */
01342       if (stencil_size > 0)
01343          depth_size = 24;  /* if Z and stencil, always use 24+8 format */
01344       else if (depth_size > 24)
01345          depth_size = 32;
01346       else if (depth_size > 16)
01347          depth_size = 24;
01348       else if (depth_size > 0) {
01349          depth_size = default_depth_bits();
01350       }
01351 
01352       if (!alpha_flag) {
01353          alpha_flag = default_alpha_bits() > 0;
01354       }
01355 
01356       /* we only support one size of stencil and accum buffers. */
01357       if (stencil_size > 0)
01358          stencil_size = STENCIL_BITS;
01359       if (accumRedSize > 0 || accumGreenSize > 0 || accumBlueSize > 0 ||
01360           accumAlphaSize > 0) {
01361          accumRedSize = 
01362          accumGreenSize = 
01363          accumBlueSize = default_accum_bits();
01364          accumAlphaSize = alpha_flag ? accumRedSize : 0;
01365       }
01366 
01367       xmvis = save_glx_visual( dpy, vis, rgb_flag, alpha_flag, double_flag,
01368                                stereo_flag, depth_size, stencil_size,
01369                                accumRedSize, accumGreenSize,
01370                                accumBlueSize, accumAlphaSize, level, numAux );
01371    }
01372 
01373    return xmvis;
01374 }
01375 
01376 
01377 static XVisualInfo *
01378 Fake_glXChooseVisual( Display *dpy, int screen, int *list )
01379 {
01380    XMesaVisual xmvis;
01381 
01382    /* register ourselves as an extension on this display */
01383    register_with_display(dpy);
01384 
01385    xmvis = choose_visual(dpy, screen, list, GL_FALSE);
01386    if (xmvis) {
01387 #if 0
01388       return xmvis->vishandle;
01389 #else
01390       /* create a new vishandle - the cached one may be stale */
01391       xmvis->vishandle = (XVisualInfo *) _mesa_malloc(sizeof(XVisualInfo));
01392       if (xmvis->vishandle) {
01393          _mesa_memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo));
01394       }
01395       return xmvis->vishandle;
01396 #endif
01397    }
01398    else
01399       return NULL;
01400 }
01401 
01402 
01403 static GLXContext
01404 Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo,
01405                        GLXContext share_list, Bool direct )
01406 {
01407    XMesaVisual xmvis;
01408    struct fake_glx_context *glxCtx;
01409    struct fake_glx_context *shareCtx = (struct fake_glx_context *) share_list;
01410 
01411    if (!dpy || !visinfo)
01412       return 0;
01413 
01414    glxCtx = CALLOC_STRUCT(fake_glx_context);
01415    if (!glxCtx)
01416       return 0;
01417 
01418    /* deallocate unused windows/buffers */
01419 #if 0
01420    XMesaGarbageCollect();
01421 #endif
01422 
01423    xmvis = find_glx_visual( dpy, visinfo );
01424    if (!xmvis) {
01425       /* This visual wasn't found with glXChooseVisual() */
01426       xmvis = create_glx_visual( dpy, visinfo );
01427       if (!xmvis) {
01428          /* unusable visual */
01429          _mesa_free(glxCtx);
01430          return NULL;
01431       }
01432    }
01433 
01434    glxCtx->xmesaContext = XMesaCreateContext(xmvis,
01435                                    shareCtx ? shareCtx->xmesaContext : NULL);
01436    if (!glxCtx->xmesaContext) {
01437       _mesa_free(glxCtx);
01438       return NULL;
01439    }
01440 
01441    glxCtx->glxContext.isDirect = GL_FALSE;
01442    glxCtx->glxContext.currentDpy = dpy;
01443    glxCtx->glxContext.xid = (XID) glxCtx;  /* self pointer */
01444 
01445    assert((void *) glxCtx == (void *) &(glxCtx->glxContext));
01446 
01447    return (GLXContext) glxCtx;
01448 }
01449 
01450 
01451 /* XXX these may have to be removed due to thread-safety issues. */
01452 static GLXContext MakeCurrent_PrevContext = 0;
01453 static GLXDrawable MakeCurrent_PrevDrawable = 0;
01454 static GLXDrawable MakeCurrent_PrevReadable = 0;
01455 static XMesaBuffer MakeCurrent_PrevDrawBuffer = 0;
01456 static XMesaBuffer MakeCurrent_PrevReadBuffer = 0;
01457 
01458 
01459 /* GLX 1.3 and later */
01460 static Bool
01461 Fake_glXMakeContextCurrent( Display *dpy, GLXDrawable draw,
01462                             GLXDrawable read, GLXContext ctx )
01463 {
01464    struct fake_glx_context *glxCtx = (struct fake_glx_context *) ctx;
01465    static boolean firsttime = 1, no_rast = 0;
01466 
01467    if (firsttime) {
01468       no_rast = getenv("SP_NO_RAST") != NULL;
01469       firsttime = 0;
01470    }
01471 
01472 
01473    if (ctx && draw && read) {
01474       XMesaBuffer drawBuffer, readBuffer;
01475       XMesaContext xmctx = glxCtx->xmesaContext;
01476 
01477       /* Find the XMesaBuffer which corresponds to the GLXDrawable 'draw' */
01478       if (ctx == MakeCurrent_PrevContext
01479           && draw == MakeCurrent_PrevDrawable) {
01480          drawBuffer = MakeCurrent_PrevDrawBuffer;
01481       }
01482       else {
01483          drawBuffer = XMesaFindBuffer( dpy, draw );
01484       }
01485       if (!drawBuffer) {
01486          /* drawable must be a new window! */
01487          drawBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, draw );
01488          if (!drawBuffer) {
01489             /* Out of memory, or context/drawable depth mismatch */
01490             return False;
01491          }
01492 #ifdef FX
01493          FXcreateContext( xmctx->xm_visual, draw, xmctx, drawBuffer );
01494 #endif
01495       }
01496 
01497       /* Find the XMesaBuffer which corresponds to the GLXDrawable 'read' */
01498       if (ctx == MakeCurrent_PrevContext
01499           && read == MakeCurrent_PrevReadable) {
01500          readBuffer = MakeCurrent_PrevReadBuffer;
01501       }
01502       else {
01503          readBuffer = XMesaFindBuffer( dpy, read );
01504       }
01505       if (!readBuffer) {
01506          /* drawable must be a new window! */
01507          readBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, read );
01508          if (!readBuffer) {
01509             /* Out of memory, or context/drawable depth mismatch */
01510             return False;
01511          }
01512 #ifdef FX
01513          FXcreateContext( xmctx->xm_visual, read, xmctx, readBuffer );
01514 #endif
01515       }
01516 
01517       if (no_rast &&
01518           MakeCurrent_PrevContext == ctx &&
01519           MakeCurrent_PrevDrawable == draw &&
01520           MakeCurrent_PrevReadable == read &&
01521           MakeCurrent_PrevDrawBuffer == drawBuffer &&
01522           MakeCurrent_PrevReadBuffer == readBuffer)
01523          return True;
01524           
01525       MakeCurrent_PrevContext = ctx;
01526       MakeCurrent_PrevDrawable = draw;
01527       MakeCurrent_PrevReadable = read;
01528       MakeCurrent_PrevDrawBuffer = drawBuffer;
01529       MakeCurrent_PrevReadBuffer = readBuffer;
01530 
01531       /* Now make current! */
01532       if (XMesaMakeCurrent2(xmctx, drawBuffer, readBuffer)) {
01533          ((__GLXcontext *) ctx)->currentDpy = dpy;
01534          ((__GLXcontext *) ctx)->currentDrawable = draw;
01535          ((__GLXcontext *) ctx)->currentReadable = read;
01536          return True;
01537       }
01538       else {
01539          return False;
01540       }
01541    }
01542    else if (!ctx && !draw && !read) {
01543       /* release current context w/out assigning new one. */
01544       XMesaMakeCurrent( NULL, NULL );
01545       MakeCurrent_PrevContext = 0;
01546       MakeCurrent_PrevDrawable = 0;
01547       MakeCurrent_PrevReadable = 0;
01548       MakeCurrent_PrevDrawBuffer = 0;
01549       MakeCurrent_PrevReadBuffer = 0;
01550       return True;
01551    }
01552    else {
01553       /* The args must either all be non-zero or all zero.
01554        * This is an error.
01555        */
01556       return False;
01557    }
01558 }
01559 
01560 
01561 static Bool
01562 Fake_glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx )
01563 {
01564    return Fake_glXMakeContextCurrent( dpy, drawable, drawable, ctx );
01565 }
01566 
01567 
01568 static GLXPixmap
01569 Fake_glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, Pixmap pixmap )
01570 {
01571    XMesaVisual v;
01572    XMesaBuffer b;
01573 
01574    v = find_glx_visual( dpy, visinfo );
01575    if (!v) {
01576       v = create_glx_visual( dpy, visinfo );
01577       if (!v) {
01578          /* unusable visual */
01579          return 0;
01580       }
01581    }
01582 
01583    b = XMesaCreatePixmapBuffer( v, pixmap, 0 );
01584    if (!b) {
01585       return 0;
01586    }
01587    return b->drawable;
01588 }
01589 
01590 
01591 /*** GLX_MESA_pixmap_colormap ***/
01592 
01593 static GLXPixmap
01594 Fake_glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo,
01595                              Pixmap pixmap, Colormap cmap )
01596 {
01597    XMesaVisual v;
01598    XMesaBuffer b;
01599 
01600    v = find_glx_visual( dpy, visinfo );
01601    if (!v) {
01602       v = create_glx_visual( dpy, visinfo );
01603       if (!v) {
01604          /* unusable visual */
01605          return 0;
01606       }
01607    }
01608 
01609    b = XMesaCreatePixmapBuffer( v, pixmap, cmap );
01610    if (!b) {
01611       return 0;
01612    }
01613    return b->drawable;
01614 }
01615 
01616 
01617 static void
01618 Fake_glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap )
01619 {
01620    XMesaBuffer b = XMesaFindBuffer(dpy, pixmap);
01621    if (b) {
01622       XMesaDestroyBuffer(b);
01623    }
01624    else if (_mesa_getenv("MESA_DEBUG")) {
01625       _mesa_warning(NULL, "Mesa: glXDestroyGLXPixmap: invalid pixmap\n");
01626    }
01627 }
01628 
01629 
01630 static void
01631 Fake_glXCopyContext( Display *dpy, GLXContext src, GLXContext dst,
01632                      unsigned long mask )
01633 {
01634    struct fake_glx_context *fakeSrc = (struct fake_glx_context *) src;
01635    struct fake_glx_context *fakeDst = (struct fake_glx_context *) dst;
01636    XMesaContext xm_src = fakeSrc->xmesaContext;
01637    XMesaContext xm_dst = fakeDst->xmesaContext;
01638    (void) dpy;
01639    if (MakeCurrent_PrevContext == src) {
01640       _mesa_Flush();
01641    }
01642    st_copy_context_state( xm_src->st, xm_dst->st, (GLuint) mask );
01643 }
01644 
01645 
01646 static Bool
01647 Fake_glXQueryExtension( Display *dpy, int *errorb, int *event )
01648 {
01649    /* Mesa's GLX isn't really an X extension but we try to act like one. */
01650    (void) dpy;
01651    (void) errorb;
01652    (void) event;
01653    return True;
01654 }
01655 
01656 
01657 extern void _kw_ungrab_all( Display *dpy );
01658 void _kw_ungrab_all( Display *dpy )
01659 {
01660    XUngrabPointer( dpy, CurrentTime );
01661    XUngrabKeyboard( dpy, CurrentTime );
01662 }
01663 
01664 
01665 static void
01666 Fake_glXDestroyContext( Display *dpy, GLXContext ctx )
01667 {
01668    struct fake_glx_context *glxCtx = (struct fake_glx_context *) ctx;
01669    (void) dpy;
01670    MakeCurrent_PrevContext = 0;
01671    MakeCurrent_PrevDrawable = 0;
01672    MakeCurrent_PrevReadable = 0;
01673    MakeCurrent_PrevDrawBuffer = 0;
01674    MakeCurrent_PrevReadBuffer = 0;
01675    XMesaDestroyContext( glxCtx->xmesaContext );
01676    XMesaGarbageCollect();
01677    _mesa_free(glxCtx);
01678 }
01679 
01680 
01681 static Bool
01682 Fake_glXIsDirect( Display *dpy, GLXContext ctx )
01683 {
01684    (void) dpy;
01685    (void) ctx;
01686    return False;
01687 }
01688 
01689 
01690 
01691 static void
01692 Fake_glXSwapBuffers( Display *dpy, GLXDrawable drawable )
01693 {
01694    XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable );
01695    static boolean firsttime = 1, no_rast = 0;
01696 
01697    if (firsttime) {
01698       no_rast = getenv("SP_NO_RAST") != NULL;
01699       firsttime = 0;
01700    }
01701 
01702    if (no_rast)
01703       return;
01704 
01705    if (buffer) {
01706       XMesaSwapBuffers(buffer);
01707    }
01708    else if (_mesa_getenv("MESA_DEBUG")) {
01709       _mesa_warning(NULL, "glXSwapBuffers: invalid drawable 0x%x\n",
01710                     (int) drawable);
01711    }
01712 }
01713 
01714 
01715 
01716 /*** GLX_MESA_copy_sub_buffer ***/
01717 
01718 static void
01719 Fake_glXCopySubBufferMESA( Display *dpy, GLXDrawable drawable,
01720                            int x, int y, int width, int height )
01721 {
01722    XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable );
01723    if (buffer) {
01724       XMesaCopySubBuffer(buffer, x, y, width, height);
01725    }
01726    else if (_mesa_getenv("MESA_DEBUG")) {
01727       _mesa_warning(NULL, "Mesa: glXCopySubBufferMESA: invalid drawable\n");
01728    }
01729 }
01730 
01731 
01732 static Bool
01733 Fake_glXQueryVersion( Display *dpy, int *maj, int *min )
01734 {
01735    (void) dpy;
01736    /* Return GLX version, not Mesa version */
01737    assert(CLIENT_MAJOR_VERSION == SERVER_MAJOR_VERSION);
01738    *maj = CLIENT_MAJOR_VERSION;
01739    *min = MIN2( CLIENT_MINOR_VERSION, SERVER_MINOR_VERSION );
01740    return True;
01741 }
01742 
01743 
01744 /*
01745  * Query the GLX attributes of the given XVisualInfo.
01746  */
01747 static int
01748 get_config( XMesaVisual xmvis, int attrib, int *value, GLboolean fbconfig )
01749 {
01750    ASSERT(xmvis);
01751    switch(attrib) {
01752       case GLX_USE_GL:
01753          if (fbconfig)
01754             return GLX_BAD_ATTRIBUTE;
01755          *value = (int) True;
01756          return 0;
01757       case GLX_BUFFER_SIZE:
01758          *value = xmvis->visinfo->depth;
01759          return 0;
01760       case GLX_LEVEL:
01761          *value = xmvis->mesa_visual.level;
01762          return 0;
01763       case GLX_RGBA:
01764          if (fbconfig)
01765             return GLX_BAD_ATTRIBUTE;
01766          if (xmvis->mesa_visual.rgbMode) {
01767             *value = True;
01768          }
01769          else {
01770             *value = False;
01771          }
01772          return 0;
01773       case GLX_DOUBLEBUFFER:
01774          *value = (int) xmvis->mesa_visual.doubleBufferMode;
01775          return 0;
01776       case GLX_STEREO:
01777          *value = (int) xmvis->mesa_visual.stereoMode;
01778          return 0;
01779       case GLX_AUX_BUFFERS:
01780          *value = xmvis->mesa_visual.numAuxBuffers;
01781          return 0;
01782       case GLX_RED_SIZE:
01783          *value = xmvis->mesa_visual.redBits;
01784          return 0;
01785       case GLX_GREEN_SIZE:
01786          *value = xmvis->mesa_visual.greenBits;
01787          return 0;
01788       case GLX_BLUE_SIZE:
01789          *value = xmvis->mesa_visual.blueBits;
01790          return 0;
01791       case GLX_ALPHA_SIZE:
01792          *value = xmvis->mesa_visual.alphaBits;
01793          return 0;
01794       case GLX_DEPTH_SIZE:
01795          *value = xmvis->mesa_visual.depthBits;
01796          return 0;
01797       case GLX_STENCIL_SIZE:
01798          *value = xmvis->mesa_visual.stencilBits;
01799          return 0;
01800       case GLX_ACCUM_RED_SIZE:
01801          *value = xmvis->mesa_visual.accumRedBits;
01802          return 0;
01803       case GLX_ACCUM_GREEN_SIZE:
01804          *value = xmvis->mesa_visual.accumGreenBits;
01805          return 0;
01806       case GLX_ACCUM_BLUE_SIZE:
01807          *value = xmvis->mesa_visual.accumBlueBits;
01808          return 0;
01809       case GLX_ACCUM_ALPHA_SIZE:
01810          *value = xmvis->mesa_visual.accumAlphaBits;
01811          return 0;
01812 
01813       /*
01814        * GLX_EXT_visual_info extension
01815        */
01816       case GLX_X_VISUAL_TYPE_EXT:
01817          switch (xmvis->visinfo->CLASS) {
01818             case StaticGray:   *value = GLX_STATIC_GRAY_EXT;   return 0;
01819             case GrayScale:    *value = GLX_GRAY_SCALE_EXT;    return 0;
01820             case StaticColor:  *value = GLX_STATIC_GRAY_EXT;   return 0;
01821             case PseudoColor:  *value = GLX_PSEUDO_COLOR_EXT;  return 0;
01822             case TrueColor:    *value = GLX_TRUE_COLOR_EXT;    return 0;
01823             case DirectColor:  *value = GLX_DIRECT_COLOR_EXT;  return 0;
01824          }
01825          return 0;
01826       case GLX_TRANSPARENT_TYPE_EXT:
01827          if (xmvis->mesa_visual.level==0) {
01828             /* normal planes */
01829             *value = GLX_NONE_EXT;
01830          }
01831          else if (xmvis->mesa_visual.level>0) {
01832             /* overlay */
01833             if (xmvis->mesa_visual.rgbMode) {
01834                *value = GLX_TRANSPARENT_RGB_EXT;
01835             }
01836             else {
01837                *value = GLX_TRANSPARENT_INDEX_EXT;
01838             }
01839          }
01840          else if (xmvis->mesa_visual.level<0) {
01841             /* underlay */
01842             *value = GLX_NONE_EXT;
01843          }
01844          return 0;
01845       case GLX_TRANSPARENT_INDEX_VALUE_EXT:
01846          {
01847             int pixel = transparent_pixel( xmvis );
01848             if (pixel>=0) {
01849                *value = pixel;
01850             }
01851             /* else undefined */
01852          }
01853          return 0;
01854       case GLX_TRANSPARENT_RED_VALUE_EXT:
01855          /* undefined */
01856          return 0;
01857       case GLX_TRANSPARENT_GREEN_VALUE_EXT:
01858          /* undefined */
01859          return 0;
01860       case GLX_TRANSPARENT_BLUE_VALUE_EXT:
01861          /* undefined */
01862          return 0;
01863       case GLX_TRANSPARENT_ALPHA_VALUE_EXT:
01864          /* undefined */
01865          return 0;
01866 
01867       /*
01868        * GLX_EXT_visual_info extension
01869        */
01870       case GLX_VISUAL_CAVEAT_EXT:
01871          /* test for zero, just in case */
01872          if (xmvis->mesa_visual.visualRating > 0)
01873             *value = xmvis->mesa_visual.visualRating;
01874          else
01875             *value = GLX_NONE_EXT;
01876          return 0;
01877 
01878       /*
01879        * GLX_ARB_multisample
01880        */
01881       case GLX_SAMPLE_BUFFERS_ARB:
01882          *value = 0;
01883          return 0;
01884       case GLX_SAMPLES_ARB:
01885          *value = 0;
01886          return 0;
01887 
01888       /*
01889        * For FBConfigs:
01890        */
01891       case GLX_SCREEN_EXT:
01892          if (!fbconfig)
01893             return GLX_BAD_ATTRIBUTE;
01894          *value = xmvis->visinfo->screen;
01895          break;
01896       case GLX_DRAWABLE_TYPE: /*SGIX too */
01897          if (!fbconfig)
01898             return GLX_BAD_ATTRIBUTE;
01899          *value = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
01900          break;
01901       case GLX_RENDER_TYPE_SGIX:
01902          if (!fbconfig)
01903             return GLX_BAD_ATTRIBUTE;
01904          if (xmvis->mesa_visual.rgbMode)
01905             *value = GLX_RGBA_BIT;
01906          else
01907             *value = GLX_COLOR_INDEX_BIT;
01908          break;
01909       case GLX_X_RENDERABLE_SGIX:
01910          if (!fbconfig)
01911             return GLX_BAD_ATTRIBUTE;
01912          *value = True; /* XXX really? */
01913          break;
01914       case GLX_FBCONFIG_ID_SGIX:
01915          if (!fbconfig)
01916             return GLX_BAD_ATTRIBUTE;
01917          *value = xmvis->visinfo->visualid;
01918          break;
01919       case GLX_MAX_PBUFFER_WIDTH:
01920          if (!fbconfig)
01921             return GLX_BAD_ATTRIBUTE;
01922          /* XXX or MAX_WIDTH? */
01923          *value = DisplayWidth(xmvis->display, xmvis->visinfo->screen);
01924          break;
01925       case GLX_MAX_PBUFFER_HEIGHT:
01926          if (!fbconfig)
01927             return GLX_BAD_ATTRIBUTE;
01928          *value = DisplayHeight(xmvis->display, xmvis->visinfo->screen);
01929          break;
01930       case GLX_MAX_PBUFFER_PIXELS:
01931          if (!fbconfig)
01932             return GLX_BAD_ATTRIBUTE;
01933          *value = DisplayWidth(xmvis->display, xmvis->visinfo->screen) *
01934                   DisplayHeight(xmvis->display, xmvis->visinfo->screen);
01935          break;
01936       case GLX_VISUAL_ID:
01937          if (!fbconfig)
01938             return GLX_BAD_ATTRIBUTE;
01939          *value = xmvis->visinfo->visualid;
01940          break;
01941 
01942 #ifdef GLX_EXT_texture_from_pixmap
01943       case GLX_BIND_TO_TEXTURE_RGB_EXT:
01944          *value = True; /*XXX*/
01945          break;
01946       case GLX_BIND_TO_TEXTURE_RGBA_EXT:
01947          /* XXX review */
01948          *value = xmvis->mesa_visual.alphaBits > 0 ? True : False;
01949          break;
01950       case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
01951          *value = True; /*XXX*/
01952          break;
01953       case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
01954          *value = (GLX_TEXTURE_1D_BIT_EXT |
01955                    GLX_TEXTURE_2D_BIT_EXT |
01956                    GLX_TEXTURE_RECTANGLE_BIT_EXT); /*XXX*/
01957          break;
01958       case GLX_Y_INVERTED_EXT:
01959          *value = True; /*XXX*/
01960          break;
01961 #endif
01962 
01963       default:
01964          return GLX_BAD_ATTRIBUTE;
01965    }
01966    return Success;
01967 }
01968 
01969 
01970 static int
01971 Fake_glXGetConfig( Display *dpy, XVisualInfo *visinfo,
01972                    int attrib, int *value )
01973 {
01974    XMesaVisual xmvis;
01975    int k;
01976    if (!dpy || !visinfo)
01977       return GLX_BAD_ATTRIBUTE;
01978 
01979    xmvis = find_glx_visual( dpy, visinfo );
01980    if (!xmvis) {
01981       /* this visual wasn't obtained with glXChooseVisual */
01982       xmvis = create_glx_visual( dpy, visinfo );
01983       if (!xmvis) {
01984          /* this visual can't be used for GL rendering */
01985          if (attrib==GLX_USE_GL) {
01986             *value = (int) False;
01987             return 0;
01988          }
01989          else {
01990             return GLX_BAD_VISUAL;
01991          }
01992       }
01993    }
01994 
01995    k = get_config(xmvis, attrib, value, GL_FALSE);
01996    return k;
01997 }
01998 
01999 
02000 static void
02001 Fake_glXWaitGL( void )
02002 {
02003    XMesaContext xmesa = XMesaGetCurrentContext();
02004    XMesaFlush( xmesa );
02005 }
02006 
02007 
02008 
02009 static void
02010 Fake_glXWaitX( void )
02011 {
02012    XMesaContext xmesa = XMesaGetCurrentContext();
02013    XMesaFlush( xmesa );
02014 }
02015 
02016 
02017 static const char *
02018 get_extensions( void )
02019 {
02020 #ifdef FX
02021    const char *fx = _mesa_getenv("MESA_GLX_FX");
02022    if (fx && fx[0] != 'd') {
02023       return EXTENSIONS;
02024    }
02025 #endif
02026    return EXTENSIONS + 23; /* skip "GLX_MESA_set_3dfx_mode" */
02027 }
02028 
02029 
02030 
02031 /* GLX 1.1 and later */
02032 static const char *
02033 Fake_glXQueryExtensionsString( Display *dpy, int screen )
02034 {
02035    (void) dpy;
02036    (void) screen;
02037    return get_extensions();
02038 }
02039 
02040 
02041 
02042 /* GLX 1.1 and later */
02043 static const char *
02044 Fake_glXQueryServerString( Display *dpy, int screen, int name )
02045 {
02046    static char version[1000];
02047    _mesa_sprintf(version, "%d.%d %s",
02048                  SERVER_MAJOR_VERSION, SERVER_MINOR_VERSION, MESA_GLX_VERSION);
02049 
02050    (void) dpy;
02051    (void) screen;
02052 
02053    switch (name) {
02054       case GLX_EXTENSIONS:
02055          return get_extensions();
02056       case GLX_VENDOR:
02057          return VENDOR;
02058       case GLX_VERSION:
02059          return version;
02060       default:
02061          return NULL;
02062    }
02063 }
02064 
02065 
02066 
02067 /* GLX 1.1 and later */
02068 static const char *
02069 Fake_glXGetClientString( Display *dpy, int name )
02070 {
02071    static char version[1000];
02072    _mesa_sprintf(version, "%d.%d %s", CLIENT_MAJOR_VERSION,
02073                  CLIENT_MINOR_VERSION, MESA_GLX_VERSION);
02074 
02075    (void) dpy;
02076 
02077    switch (name) {
02078       case GLX_EXTENSIONS:
02079          return get_extensions();
02080       case GLX_VENDOR:
02081          return VENDOR;
02082       case GLX_VERSION:
02083          return version;
02084       default:
02085          return NULL;
02086    }
02087 }
02088 
02089 
02090 
02091 /*
02092  * GLX 1.3 and later
02093  */
02094 
02095 
02096 static int
02097 Fake_glXGetFBConfigAttrib( Display *dpy, GLXFBConfig config,
02098                            int attribute, int *value )
02099 {
02100    XMesaVisual v = (XMesaVisual) config;
02101    (void) dpy;
02102    (void) config;
02103 
02104    if (!dpy || !config || !value)
02105       return -1;
02106 
02107    return get_config(v, attribute, value, GL_TRUE);
02108 }
02109 
02110 
02111 static GLXFBConfig *
02112 Fake_glXGetFBConfigs( Display *dpy, int screen, int *nelements )
02113 {
02114    XVisualInfo *visuals, visTemplate;
02115    const long visMask = VisualScreenMask;
02116    int i;
02117 
02118    /* Get list of all X visuals */
02119    visTemplate.screen = screen;
02120    visuals = XGetVisualInfo(dpy, visMask, &visTemplate, nelements);
02121    if (*nelements > 0) {
02122       XMesaVisual *results;
02123       results = (XMesaVisual *) _mesa_malloc(*nelements * sizeof(XMesaVisual));
02124       if (!results) {
02125          *nelements = 0;
02126          return NULL;
02127       }
02128       for (i = 0; i < *nelements; i++) {
02129          results[i] = create_glx_visual(dpy, visuals + i);
02130       }
02131       return (GLXFBConfig *) results;
02132    }
02133    return NULL;
02134 }
02135 
02136 
02137 static GLXFBConfig *
02138 Fake_glXChooseFBConfig( Display *dpy, int screen,
02139                         const int *attribList, int *nitems )
02140 {
02141    XMesaVisual xmvis;
02142 
02143    if (!attribList || !attribList[0]) {
02144       /* return list of all configs (per GLX_SGIX_fbconfig spec) */
02145       return Fake_glXGetFBConfigs(dpy, screen, nitems);
02146    }
02147 
02148    xmvis = choose_visual(dpy, screen, attribList, GL_TRUE);
02149    if (xmvis) {
02150       GLXFBConfig *config = (GLXFBConfig *) _mesa_malloc(sizeof(XMesaVisual));
02151       if (!config) {
02152          *nitems = 0;
02153          return NULL;
02154       }
02155       *nitems = 1;
02156       config[0] = (GLXFBConfig) xmvis;
02157       return (GLXFBConfig *) config;
02158    }
02159    else {
02160       *nitems = 0;
02161       return NULL;
02162    }
02163 }
02164 
02165 
02166 static XVisualInfo *
02167 Fake_glXGetVisualFromFBConfig( Display *dpy, GLXFBConfig config )
02168 {
02169    if (dpy && config) {
02170       XMesaVisual xmvis = (XMesaVisual) config;
02171 #if 0      
02172       return xmvis->vishandle;
02173 #else
02174       /* create a new vishandle - the cached one may be stale */
02175       xmvis->vishandle = (XVisualInfo *) _mesa_malloc(sizeof(XVisualInfo));
02176       if (xmvis->vishandle) {
02177          _mesa_memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo));
02178       }
02179       return xmvis->vishandle;
02180 #endif
02181    }
02182    else {
02183       return NULL;
02184    }
02185 }
02186 
02187 
02188 static GLXWindow
02189 Fake_glXCreateWindow( Display *dpy, GLXFBConfig config, Window win,
02190                       const int *attribList )
02191 {
02192    XMesaVisual xmvis = (XMesaVisual) config;
02193    XMesaBuffer xmbuf;
02194    if (!xmvis)
02195       return 0;
02196 
02197    xmbuf = XMesaCreateWindowBuffer(xmvis, win);
02198    if (!xmbuf)
02199       return 0;
02200 
02201 #ifdef FX
02202    /* XXX this will segfault if actually called */
02203    FXcreateContext(xmvis, win, NULL, xmbuf);
02204 #endif
02205 
02206    (void) dpy;
02207    (void) attribList;  /* Ignored in GLX 1.3 */
02208 
02209    return win;  /* A hack for now */
02210 }
02211 
02212 
02213 static void
02214 Fake_glXDestroyWindow( Display *dpy, GLXWindow window )
02215 {
02216    XMesaBuffer b = XMesaFindBuffer(dpy, (XMesaDrawable) window);
02217    if (b)
02218       XMesaDestroyBuffer(b);
02219    /* don't destroy X window */
02220 }
02221 
02222 
02223 /* XXX untested */
02224 static GLXPixmap
02225 Fake_glXCreatePixmap( Display *dpy, GLXFBConfig config, Pixmap pixmap,
02226                       const int *attribList )
02227 {
02228    XMesaVisual v = (XMesaVisual) config;
02229    XMesaBuffer b;
02230    const int *attr;
02231    int target = 0, format = 0, mipmap = 0;
02232    int value;
02233 
02234    if (!dpy || !config || !pixmap)
02235       return 0;
02236 
02237    for (attr = attribList; *attr; attr++) {
02238       switch (*attr) {
02239       case GLX_TEXTURE_FORMAT_EXT:
02240          attr++;
02241          switch (*attr) {
02242          case GLX_TEXTURE_FORMAT_NONE_EXT:
02243          case GLX_TEXTURE_FORMAT_RGB_EXT:
02244          case GLX_TEXTURE_FORMAT_RGBA_EXT:
02245             format = *attr;
02246             break;
02247          default:
02248             /* error */
02249             return 0;
02250          }
02251          break;
02252       case GLX_TEXTURE_TARGET_EXT:
02253          attr++;
02254          switch (*attr) {
02255          case GLX_TEXTURE_1D_EXT:
02256          case GLX_TEXTURE_2D_EXT:
02257          case GLX_TEXTURE_RECTANGLE_EXT:
02258             target = *attr;
02259             break;
02260          default:
02261             /* error */
02262             return 0;
02263          }
02264          break;
02265       case GLX_MIPMAP_TEXTURE_EXT:
02266          attr++;
02267          if (*attr)
02268             mipmap = 1;
02269          break;
02270       default:
02271          /* error */
02272          return 0;
02273       }
02274    }
02275 
02276    if (format == GLX_TEXTURE_FORMAT_RGB_EXT) {
02277       if (get_config(v, GLX_BIND_TO_TEXTURE_RGB_EXT,
02278                      &value, GL_TRUE) != Success
02279           || !value) {
02280          return 0; /* error! */
02281       }
02282    }
02283    else if (format == GLX_TEXTURE_FORMAT_RGBA_EXT) {
02284       if (get_config(v, GLX_BIND_TO_TEXTURE_RGBA_EXT,
02285                      &value, GL_TRUE) != Success
02286           || !value) {
02287          return 0; /* error! */
02288       }
02289    }
02290    if (mipmap) {
02291       if (get_config(v, GLX_BIND_TO_MIPMAP_TEXTURE_EXT,
02292                      &value, GL_TRUE) != Success
02293           || !value) {
02294          return 0; /* error! */
02295       }
02296    }
02297    if (target == GLX_TEXTURE_1D_EXT) {
02298       if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT,
02299                      &value, GL_TRUE) != Success
02300           || (value & GLX_TEXTURE_1D_BIT_EXT) == 0) {
02301          return 0; /* error! */
02302       }
02303    }
02304    else if (target == GLX_TEXTURE_2D_EXT) {
02305       if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT,
02306                      &value, GL_TRUE) != Success
02307           || (value & GLX_TEXTURE_2D_BIT_EXT) == 0) {
02308          return 0; /* error! */
02309       }
02310    }
02311    if (target == GLX_TEXTURE_RECTANGLE_EXT) {
02312       if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT,
02313                      &value, GL_TRUE) != Success
02314           || (value & GLX_TEXTURE_RECTANGLE_BIT_EXT) == 0) {
02315          return 0; /* error! */
02316       }
02317    }
02318 
02319    if (format || target || mipmap) {
02320       /* texture from pixmap */
02321       b = XMesaCreatePixmapTextureBuffer(v, pixmap, 0, format, target, mipmap);
02322    }
02323    else {
02324       b = XMesaCreatePixmapBuffer( v, pixmap, 0 );
02325    }
02326    if (!b) {
02327       return 0;
02328    }
02329 
02330    return pixmap;
02331 }
02332 
02333 
02334 static void
02335 Fake_glXDestroyPixmap( Display *dpy, GLXPixmap pixmap )
02336 {
02337    XMesaBuffer b = XMesaFindBuffer(dpy, (XMesaDrawable)pixmap);
02338    if (b)
02339       XMesaDestroyBuffer(b);
02340    /* don't destroy X pixmap */
02341 }
02342 
02343 
02344 static GLXPbuffer
02345 Fake_glXCreatePbuffer( Display *dpy, GLXFBConfig config,
02346                        const int *attribList )
02347 {
02348    XMesaVisual xmvis = (XMesaVisual) config;
02349    XMesaBuffer xmbuf;
02350    const int *attrib;
02351    int width = 0, height = 0;
02352    GLboolean useLargest = GL_FALSE, preserveContents = GL_FALSE;
02353 
02354    (void) dpy;
02355 
02356    for (attrib = attribList; *attrib; attrib++) {
02357       switch (*attrib) {
02358          case GLX_PBUFFER_WIDTH:
02359             attrib++;
02360             width = *attrib;
02361             break;
02362          case GLX_PBUFFER_HEIGHT:
02363             attrib++;
02364             height = *attrib;
02365             break;
02366          case GLX_PRESERVED_CONTENTS:
02367             attrib++;
02368             preserveContents = *attrib; /* ignored */
02369             break;
02370          case GLX_LARGEST_PBUFFER:
02371             attrib++;
02372             useLargest = *attrib; /* ignored */
02373             break;
02374          default:
02375             return 0;
02376       }
02377    }
02378 
02379    /* not used at this time */
02380    (void) useLargest;
02381    (void) preserveContents;
02382 
02383    if (width == 0 || height == 0)
02384       return 0;
02385 
02386    xmbuf = XMesaCreatePBuffer( xmvis, 0, width, height);
02387    /* A GLXPbuffer handle must be an X Drawable because that's what
02388     * glXMakeCurrent takes.
02389     */
02390    if (xmbuf)
02391       return (GLXPbuffer) xmbuf->drawable;
02392    else
02393       return 0;
02394 }
02395 
02396 
02397 static void
02398 Fake_glXDestroyPbuffer( Display *dpy, GLXPbuffer pbuf )
02399 {
02400    XMesaBuffer b = XMesaFindBuffer(dpy, pbuf);
02401    if (b) {
02402       XMesaDestroyBuffer(b);
02403    }
02404 }
02405 
02406 
02407 static void
02408 Fake_glXQueryDrawable( Display *dpy, GLXDrawable draw, int attribute,
02409                        unsigned int *value )
02410 {
02411    XMesaBuffer xmbuf = XMesaFindBuffer(dpy, draw);
02412    if (!xmbuf)
02413       return;
02414 
02415    switch (attribute) {
02416       case GLX_WIDTH:
02417          *value = xmesa_buffer_width(xmbuf);
02418          break;
02419       case GLX_HEIGHT:
02420          *value = xmesa_buffer_width(xmbuf);
02421          break;
02422       case GLX_PRESERVED_CONTENTS:
02423          *value = True;
02424          break;
02425       case GLX_LARGEST_PBUFFER:
02426          *value = xmesa_buffer_width(xmbuf) * xmesa_buffer_height(xmbuf);
02427          break;
02428       case GLX_FBCONFIG_ID:
02429          *value = xmbuf->xm_visual->visinfo->visualid;
02430          return;
02431 #ifdef GLX_EXT_texture_from_pixmap
02432       case GLX_TEXTURE_FORMAT_EXT:
02433          *value = xmbuf->TextureFormat;
02434          break;
02435       case GLX_TEXTURE_TARGET_EXT:
02436          *value = xmbuf->TextureTarget;
02437          break;
02438       case GLX_MIPMAP_TEXTURE_EXT:
02439          *value = xmbuf->TextureMipmap;
02440          break;
02441 #endif
02442 
02443       default:
02444          return; /* raise BadValue error */
02445    }
02446 }
02447 
02448 
02449 static GLXContext
02450 Fake_glXCreateNewContext( Display *dpy, GLXFBConfig config,
02451                           int renderType, GLXContext shareList, Bool direct )
02452 {
02453    struct fake_glx_context *glxCtx;
02454    struct fake_glx_context *shareCtx = (struct fake_glx_context *) shareList;
02455    XMesaVisual xmvis = (XMesaVisual) config;
02456 
02457    if (!dpy || !config ||
02458        (renderType != GLX_RGBA_TYPE && renderType != GLX_COLOR_INDEX_TYPE))
02459       return 0;
02460 
02461    glxCtx = CALLOC_STRUCT(fake_glx_context);
02462    if (!glxCtx)
02463       return 0;
02464 
02465    /* deallocate unused windows/buffers */
02466    XMesaGarbageCollect();
02467 
02468    glxCtx->xmesaContext = XMesaCreateContext(xmvis,
02469                                    shareCtx ? shareCtx->xmesaContext : NULL);
02470    if (!glxCtx->xmesaContext) {
02471       _mesa_free(glxCtx);
02472       return NULL;
02473    }
02474 
02475    glxCtx->glxContext.isDirect = GL_FALSE;
02476    glxCtx->glxContext.currentDpy = dpy;
02477    glxCtx->glxContext.xid = (XID) glxCtx;  /* self pointer */
02478 
02479    assert((void *) glxCtx == (void *) &(glxCtx->glxContext));
02480 
02481    return (GLXContext) glxCtx;
02482 }
02483 
02484 
02485 static int
02486 Fake_glXQueryContext( Display *dpy, GLXContext ctx, int attribute, int *value )
02487 {
02488    struct fake_glx_context *glxCtx = (struct fake_glx_context *) ctx;
02489    XMesaContext xmctx = glxCtx->xmesaContext;
02490 
02491    (void) dpy;
02492    (void) ctx;
02493 
02494    switch (attribute) {
02495    case GLX_FBCONFIG_ID:
02496       *value = xmctx->xm_visual->visinfo->visualid;
02497       break;
02498    case GLX_RENDER_TYPE:
02499       if (xmctx->xm_visual->mesa_visual.rgbMode)
02500          *value = GLX_RGBA_BIT;
02501       else
02502          *value = GLX_COLOR_INDEX_BIT;
02503       break;
02504    case GLX_SCREEN:
02505       *value = 0;
02506       return Success;
02507    default:
02508       return GLX_BAD_ATTRIBUTE;
02509    }
02510    return 0;
02511 }
02512 
02513 
02514 static void
02515 Fake_glXSelectEvent( Display *dpy, GLXDrawable drawable, unsigned long mask )
02516 {
02517    XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);
02518    if (xmbuf)
02519       xmbuf->selectedEvents = mask;
02520 }
02521 
02522 
02523 static void
02524 Fake_glXGetSelectedEvent( Display *dpy, GLXDrawable drawable,
02525                           unsigned long *mask )
02526 {
02527    XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);
02528    if (xmbuf)
02529       *mask = xmbuf->selectedEvents;
02530    else
02531       *mask = 0;
02532 }
02533 
02534 
02535 
02536 /*** GLX_SGI_swap_control ***/
02537 
02538 static int
02539 Fake_glXSwapIntervalSGI(int interval)
02540 {
02541    (void) interval;
02542    return 0;
02543 }
02544 
02545 
02546 
02547 /*** GLX_SGI_video_sync ***/
02548 
02549 static unsigned int FrameCounter = 0;
02550 
02551 static int
02552 Fake_glXGetVideoSyncSGI(unsigned int *count)
02553 {
02554    /* this is a bogus implementation */
02555    *count = FrameCounter++;
02556    return 0;
02557 }
02558 
02559 static int
02560 Fake_glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count)
02561 {
02562    if (divisor <= 0 || remainder < 0)
02563       return GLX_BAD_VALUE;
02564    /* this is a bogus implementation */
02565    FrameCounter++;
02566    while (FrameCounter % divisor != remainder)
02567       FrameCounter++;
02568    *count = FrameCounter;
02569    return 0;
02570 }
02571 
02572 
02573 
02574 /*** GLX_SGI_make_current_read ***/
02575 
02576 static Bool
02577 Fake_glXMakeCurrentReadSGI(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx)
02578 {
02579    return Fake_glXMakeContextCurrent( dpy, draw, read, ctx );
02580 }
02581 
02582 /* not used
02583 static GLXDrawable
02584 Fake_glXGetCurrentReadDrawableSGI(void)
02585 {
02586    return 0;
02587 }
02588 */
02589 
02590 
02591 /*** GLX_SGIX_video_source ***/
02592 #if defined(_VL_H)
02593 
02594 static GLXVideoSourceSGIX
02595 Fake_glXCreateGLXVideoSourceSGIX(Display *dpy, int screen, VLServer server, VLPath path, int nodeClass, VLNode drainNode)
02596 {
02597    (void) dpy;
02598    (void) screen;
02599    (void) server;
02600    (void) path;
02601    (void) nodeClass;
02602    (void) drainNode;
02603    return 0;
02604 }
02605 
02606 static void
02607 Fake_glXDestroyGLXVideoSourceSGIX(Display *dpy, GLXVideoSourceSGIX src)
02608 {
02609    (void) dpy;
02610    (void) src;
02611 }
02612 
02613 #endif
02614 
02615 
02616 /*** GLX_EXT_import_context ***/
02617 
02618 static void
02619 Fake_glXFreeContextEXT(Display *dpy, GLXContext context)
02620 {
02621    (void) dpy;
02622    (void) context;
02623 }
02624 
02625 static GLXContextID
02626 Fake_glXGetContextIDEXT(const GLXContext context)
02627 {
02628    (void) context;
02629    return 0;
02630 }
02631 
02632 static GLXContext
02633 Fake_glXImportContextEXT(Display *dpy, GLXContextID contextID)
02634 {
02635    (void) dpy;
02636    (void) contextID;
02637    return 0;
02638 }
02639 
02640 static int
02641 Fake_glXQueryContextInfoEXT(Display *dpy, GLXContext context, int attribute, int *value)
02642 {
02643    (void) dpy;
02644    (void) context;
02645    (void) attribute;
02646    (void) value;
02647    return 0;
02648 }
02649 
02650 
02651 
02652 /*** GLX_SGIX_fbconfig ***/
02653 
02654 static int
02655 Fake_glXGetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config, int attribute, int *value)
02656 {
02657    return Fake_glXGetFBConfigAttrib(dpy, config, attribute, value);
02658 }
02659 
02660 static GLXFBConfigSGIX *
02661 Fake_glXChooseFBConfigSGIX(Display *dpy, int screen, int *attrib_list, int *nelements)
02662 {
02663    return (GLXFBConfig *) Fake_glXChooseFBConfig(dpy, screen, attrib_list, nelements);
02664 }
02665 
02666 
02667 static GLXPixmap
02668 Fake_glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, Pixmap pixmap)
02669 {
02670    XMesaVisual xmvis = (XMesaVisual) config;
02671    XMesaBuffer xmbuf = XMesaCreatePixmapBuffer(xmvis, pixmap, 0);
02672    return xmbuf->drawable; /* need to return an X ID */
02673 }
02674 
02675 
02676 static GLXContext
02677 Fake_glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct)
02678 {
02679    XMesaVisual xmvis = (XMesaVisual) config;
02680    struct fake_glx_context *glxCtx;
02681    struct fake_glx_context *shareCtx = (struct fake_glx_context *) share_list;
02682 
02683    glxCtx = CALLOC_STRUCT(fake_glx_context);
02684    if (!glxCtx)
02685       return 0;
02686 
02687    /* deallocate unused windows/buffers */
02688    XMesaGarbageCollect();
02689 
02690    glxCtx->xmesaContext = XMesaCreateContext(xmvis,
02691                                    shareCtx ? shareCtx->xmesaContext : NULL);
02692    if (!glxCtx->xmesaContext) {
02693       _mesa_free(glxCtx);
02694       return NULL;
02695    }
02696 
02697    glxCtx->glxContext.isDirect = GL_FALSE;
02698    glxCtx->glxContext.currentDpy = dpy;
02699    glxCtx->glxContext.xid = (XID) glxCtx;  /* self pointer */
02700 
02701    assert((void *) glxCtx == (void *) &(glxCtx->glxContext));
02702 
02703    return (GLXContext) glxCtx;
02704 }
02705 
02706 
02707 static XVisualInfo *
02708 Fake_glXGetVisualFromFBConfigSGIX(Display *dpy, GLXFBConfigSGIX config)
02709 {
02710    return Fake_glXGetVisualFromFBConfig(dpy, config);
02711 }
02712 
02713 
02714 static GLXFBConfigSGIX
02715 Fake_glXGetFBConfigFromVisualSGIX(Display *dpy, XVisualInfo *vis)
02716 {
02717    XMesaVisual xmvis = find_glx_visual(dpy, vis);
02718    if (!xmvis) {
02719       /* This visual wasn't found with glXChooseVisual() */
02720       xmvis = create_glx_visual(dpy, vis);
02721    }
02722 
02723    return (GLXFBConfigSGIX) xmvis;
02724 }
02725 
02726 
02727 
02728 /*** GLX_SGIX_pbuffer ***/
02729 
02730 static GLXPbufferSGIX
02731 Fake_glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config,
02732                              unsigned int width, unsigned int height,
02733                              int *attribList)
02734 {
02735    XMesaVisual xmvis = (XMesaVisual) config;
02736    XMesaBuffer xmbuf;
02737    const int *attrib;
02738    GLboolean useLargest = GL_FALSE, preserveContents = GL_FALSE;
02739 
02740    (void) dpy;
02741 
02742    for (attrib = attribList; attrib && *attrib; attrib++) {
02743       switch (*attrib) {
02744          case GLX_PRESERVED_CONTENTS_SGIX:
02745             attrib++;
02746             preserveContents = *attrib; /* ignored */
02747             break;
02748          case GLX_LARGEST_PBUFFER_SGIX:
02749             attrib++;
02750             useLargest = *attrib; /* ignored */
02751             break;
02752          default:
02753             return 0;
02754       }
02755    }
02756 
02757    /* not used at this time */
02758    (void) useLargest;
02759    (void) preserveContents;
02760 
02761    xmbuf = XMesaCreatePBuffer( xmvis, 0, width, height);
02762    /* A GLXPbuffer handle must be an X Drawable because that's what
02763     * glXMakeCurrent takes.
02764     */
02765    return (GLXPbuffer) xmbuf->drawable;
02766 }
02767 
02768 
02769 static void
02770 Fake_glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf)
02771 {
02772    XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf);
02773    if (xmbuf) {
02774       XMesaDestroyBuffer(xmbuf);
02775    }
02776 }
02777 
02778 
02779 static int
02780 Fake_glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int *value)
02781 {
02782    const XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf);
02783 
02784    if (!xmbuf) {
02785       /* Generate GLXBadPbufferSGIX for bad pbuffer */
02786       return 0;
02787    }
02788 
02789    switch (attribute) {
02790       case GLX_PRESERVED_CONTENTS_SGIX:
02791          *value = True;
02792          break;
02793       case GLX_LARGEST_PBUFFER_SGIX:
02794          *value = xmesa_buffer_width(xmbuf) * xmesa_buffer_height(xmbuf);
02795          break;
02796       case GLX_WIDTH_SGIX:
02797          *value = xmesa_buffer_width(xmbuf);
02798          break;
02799       case GLX_HEIGHT_SGIX:
02800          *value = xmesa_buffer_height(xmbuf);
02801          break;
02802       case GLX_EVENT_MASK_SGIX:
02803          *value = 0;  /* XXX might be wrong */
02804          break;
02805       default:
02806          *value = 0;
02807    }
02808    return 0;
02809 }
02810 
02811 
02812 static void
02813 Fake_glXSelectEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long mask)
02814 {
02815    XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);
02816    if (xmbuf) {
02817       /* Note: we'll never generate clobber events */
02818       xmbuf->selectedEvents = mask;
02819    }
02820 }
02821 
02822 
02823 static void
02824 Fake_glXGetSelectedEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long *mask)
02825 {
02826    XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);
02827    if (xmbuf) {
02828       *mask = xmbuf->selectedEvents;
02829    }
02830    else {
02831       *mask = 0;
02832    }
02833 }
02834 
02835 
02836 
02837 /*** GLX_SGI_cushion ***/
02838 
02839 static void
02840 Fake_glXCushionSGI(Display *dpy, Window win, float cushion)
02841 {
02842    (void) dpy;
02843    (void) win;
02844    (void) cushion;
02845 }
02846 
02847 
02848 
02849 /*** GLX_SGIX_video_resize ***/
02850 
02851 static int
02852 Fake_glXBindChannelToWindowSGIX(Display *dpy, int screen, int channel , Window window)
02853 {
02854    (void) dpy;
02855    (void) screen;
02856    (void) channel;
02857    (void) window;
02858    return 0;
02859 }
02860 
02861 static int
02862 Fake_glXChannelRectSGIX(Display *dpy, int screen, int channel, int x, int y, int w, int h)
02863 {
02864    (void) dpy;
02865    (void) screen;
02866    (void) channel;
02867    (void) x;
02868    (void) y;
02869    (void) w;
02870    (void) h;
02871    return 0;
02872 }
02873 
02874 static int
02875 Fake_glXQueryChannelRectSGIX(Display *dpy, int screen, int channel, int *x, int *y, int *w, int *h)
02876 {
02877    (void) dpy;
02878    (void) screen;
02879    (void) channel;
02880    (void) x;
02881    (void) y;
02882    (void) w;
02883    (void) h;
02884    return 0;
02885 }
02886 
02887 static int
02888 Fake_glXQueryChannelDeltasSGIX(Display *dpy, int screen, int channel, int *dx, int *dy, int *dw, int *dh)
02889 {
02890    (void) dpy;
02891    (void) screen;
02892    (void) channel;
02893    (void) dx;
02894    (void) dy;
02895    (void) dw;
02896    (void) dh;
02897    return 0;
02898 }
02899 
02900 static int
02901 Fake_glXChannelRectSyncSGIX(Display *dpy, int screen, int channel, GLenum synctype)
02902 {
02903    (void) dpy;
02904    (void) screen;
02905    (void) channel;
02906    (void) synctype;
02907    return 0;
02908 }
02909 
02910 
02911 
02912 /*** GLX_SGIX_dmbuffer **/
02913 
02914 #if defined(_DM_BUFFER_H_)
02915 static Bool
02916 Fake_glXAssociateDMPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuffer, DMparams *params, DMbuffer dmbuffer)
02917 {
02918    (void) dpy;
02919    (void) pbuffer;
02920    (void) params;
02921    (void) dmbuffer;
02922    return False;
02923 }
02924 #endif
02925 
02926 
02927 /*** GLX_SGIX_swap_group ***/
02928 
02929 static void
02930 Fake_glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable, GLXDrawable member)
02931 {
02932    (void) dpy;
02933    (void) drawable;
02934    (void) member;
02935 }
02936 
02937 
02938 
02939 /*** GLX_SGIX_swap_barrier ***/
02940 
02941 static void
02942 Fake_glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable, int barrier)
02943 {
02944    (void) dpy;
02945    (void) drawable;
02946    (void) barrier;
02947 }
02948 
02949 static Bool
02950 Fake_glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max)
02951 {
02952    (void) dpy;
02953    (void) screen;
02954    (void) max;
02955    return False;
02956 }
02957 
02958 
02959 
02960 /*** GLX_SUN_get_transparent_index ***/
02961 
02962 static Status
02963 Fake_glXGetTransparentIndexSUN(Display *dpy, Window overlay, Window underlay, long *pTransparent)
02964 {
02965    (void) dpy;
02966    (void) overlay;
02967    (void) underlay;
02968    (void) pTransparent;
02969    return 0;
02970 }
02971 
02972 
02973 
02974 /*** GLX_MESA_release_buffers ***/
02975 
02976 /*
02977  * Release the depth, stencil, accum buffers attached to a GLXDrawable
02978  * (a window or pixmap) prior to destroying the GLXDrawable.
02979  */
02980 static Bool
02981 Fake_glXReleaseBuffersMESA( Display *dpy, GLXDrawable d )
02982 {
02983    XMesaBuffer b = XMesaFindBuffer(dpy, d);
02984    if (b) {
02985       XMesaDestroyBuffer(b);
02986       return True;
02987    }
02988    return False;
02989 }
02990 
02991 
02992 
02993 /*** GLX_MESA_set_3dfx_mode ***/
02994 
02995 static Bool
02996 Fake_glXSet3DfxModeMESA( int mode )
02997 {
02998    return XMesaSetFXmode( mode );
02999 }
03000 
03001 
03002 
03003 /*** GLX_NV_vertex_array range ***/
03004 static void *
03005 Fake_glXAllocateMemoryNV( GLsizei size,
03006                           GLfloat readFrequency,
03007                           GLfloat writeFrequency,
03008                           GLfloat priority )
03009 {
03010    (void) size;
03011    (void) readFrequency;
03012    (void) writeFrequency;
03013    (void) priority;
03014    return NULL;
03015 }
03016 
03017 
03018 static void 
03019 Fake_glXFreeMemoryNV( GLvoid *pointer )
03020 {
03021    (void) pointer;
03022 }
03023 
03024 
03025 /*** GLX_MESA_agp_offset ***/
03026 
03027 static GLuint
03028 Fake_glXGetAGPOffsetMESA( const GLvoid *pointer )
03029 {
03030    (void) pointer;
03031    return ~0;
03032 }
03033 
03034 
03035 /*** GLX_EXT_texture_from_pixmap ***/
03036 
03037 static void
03038 Fake_glXBindTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer,
03039                         const int *attrib_list)
03040 {
03041    XMesaBuffer b = XMesaFindBuffer(dpy, drawable);
03042    if (b)
03043       XMesaBindTexImage(dpy, b, buffer, attrib_list);
03044 }
03045 
03046 static void
03047 Fake_glXReleaseTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer)
03048 {
03049    XMesaBuffer b = XMesaFindBuffer(dpy, drawable);
03050    if (b)
03051       XMesaReleaseTexImage(dpy, b, buffer);
03052 }
03053 
03054 
03055 /* silence warning */
03056 extern struct _glxapi_table *_mesa_GetGLXDispatchTable(void);
03057 
03058 
03066 struct _glxapi_table *
03067 _mesa_GetGLXDispatchTable(void)
03068 {
03069    static struct _glxapi_table glx;
03070 
03071    /* be sure our dispatch table size <= libGL's table */
03072    {
03073       GLuint size = sizeof(struct _glxapi_table) / sizeof(void *);
03074       (void) size;
03075       assert(_glxapi_get_dispatch_table_size() >= size);
03076    }
03077 
03078    /* initialize the whole table to no-ops */
03079    _glxapi_set_no_op_table(&glx);
03080 
03081    /* now initialize the table with the functions I implement */
03082    glx.ChooseVisual = Fake_glXChooseVisual;
03083    glx.CopyContext = Fake_glXCopyContext;
03084    glx.CreateContext = Fake_glXCreateContext;
03085    glx.CreateGLXPixmap = Fake_glXCreateGLXPixmap;
03086    glx.DestroyContext = Fake_glXDestroyContext;
03087    glx.DestroyGLXPixmap = Fake_glXDestroyGLXPixmap;
03088    glx.GetConfig = Fake_glXGetConfig;
03089    /*glx.GetCurrentContext = Fake_glXGetCurrentContext;*/
03090    /*glx.GetCurrentDrawable = Fake_glXGetCurrentDrawable;*/
03091    glx.IsDirect = Fake_glXIsDirect;
03092    glx.MakeCurrent = Fake_glXMakeCurrent;
03093    glx.QueryExtension = Fake_glXQueryExtension;
03094    glx.QueryVersion = Fake_glXQueryVersion;
03095    glx.SwapBuffers = Fake_glXSwapBuffers;
03096    glx.UseXFont = Fake_glXUseXFont;
03097    glx.WaitGL = Fake_glXWaitGL;
03098    glx.WaitX = Fake_glXWaitX;
03099 
03100    /*** GLX_VERSION_1_1 ***/
03101    glx.GetClientString = Fake_glXGetClientString;
03102    glx.QueryExtensionsString = Fake_glXQueryExtensionsString;
03103    glx.QueryServerString = Fake_glXQueryServerString;
03104 
03105    /*** GLX_VERSION_1_2 ***/
03106    /*glx.GetCurrentDisplay = Fake_glXGetCurrentDisplay;*/
03107 
03108    /*** GLX_VERSION_1_3 ***/
03109    glx.ChooseFBConfig = Fake_glXChooseFBConfig;
03110    glx.CreateNewContext = Fake_glXCreateNewContext;
03111    glx.CreatePbuffer = Fake_glXCreatePbuffer;
03112    glx.CreatePixmap = Fake_glXCreatePixmap;
03113    glx.CreateWindow = Fake_glXCreateWindow;
03114    glx.DestroyPbuffer = Fake_glXDestroyPbuffer;
03115    glx.DestroyPixmap = Fake_glXDestroyPixmap;
03116    glx.DestroyWindow = Fake_glXDestroyWindow;
03117    /*glx.GetCurrentReadDrawable = Fake_glXGetCurrentReadDrawable;*/
03118    glx.GetFBConfigAttrib = Fake_glXGetFBConfigAttrib;
03119    glx.GetFBConfigs = Fake_glXGetFBConfigs;
03120    glx.GetSelectedEvent = Fake_glXGetSelectedEvent;
03121    glx.GetVisualFromFBConfig = Fake_glXGetVisualFromFBConfig;
03122    glx.MakeContextCurrent = Fake_glXMakeContextCurrent;
03123    glx.QueryContext = Fake_glXQueryContext;
03124    glx.QueryDrawable = Fake_glXQueryDrawable;
03125    glx.SelectEvent = Fake_glXSelectEvent;
03126 
03127    /*** GLX_SGI_swap_control ***/
03128    glx.SwapIntervalSGI = Fake_glXSwapIntervalSGI;
03129 
03130    /*** GLX_SGI_video_sync ***/
03131    glx.GetVideoSyncSGI = Fake_glXGetVideoSyncSGI;
03132    glx.WaitVideoSyncSGI = Fake_glXWaitVideoSyncSGI;
03133 
03134    /*** GLX_SGI_make_current_read ***/
03135    glx.MakeCurrentReadSGI = Fake_glXMakeCurrentReadSGI;
03136    /*glx.GetCurrentReadDrawableSGI = Fake_glXGetCurrentReadDrawableSGI;*/
03137 
03138 /*** GLX_SGIX_video_source ***/
03139 #if defined(_VL_H)
03140    glx.CreateGLXVideoSourceSGIX = Fake_glXCreateGLXVideoSourceSGIX;
03141    glx.DestroyGLXVideoSourceSGIX = Fake_glXDestroyGLXVideoSourceSGIX;
03142 #endif
03143 
03144    /*** GLX_EXT_import_context ***/
03145    glx.FreeContextEXT = Fake_glXFreeContextEXT;
03146    glx.GetContextIDEXT = Fake_glXGetContextIDEXT;
03147    /*glx.GetCurrentDisplayEXT = Fake_glXGetCurrentDisplayEXT;*/
03148    glx.ImportContextEXT = Fake_glXImportContextEXT;
03149    glx.QueryContextInfoEXT = Fake_glXQueryContextInfoEXT;
03150 
03151    /*** GLX_SGIX_fbconfig ***/
03152    glx.GetFBConfigAttribSGIX = Fake_glXGetFBConfigAttribSGIX;
03153    glx.ChooseFBConfigSGIX = Fake_glXChooseFBConfigSGIX;
03154    glx.CreateGLXPixmapWithConfigSGIX = Fake_glXCreateGLXPixmapWithConfigSGIX;
03155    glx.CreateContextWithConfigSGIX = Fake_glXCreateContextWithConfigSGIX;
03156    glx.GetVisualFromFBConfigSGIX = Fake_glXGetVisualFromFBConfigSGIX;
03157    glx.GetFBConfigFromVisualSGIX = Fake_glXGetFBConfigFromVisualSGIX;
03158 
03159    /*** GLX_SGIX_pbuffer ***/
03160    glx.CreateGLXPbufferSGIX = Fake_glXCreateGLXPbufferSGIX;
03161    glx.DestroyGLXPbufferSGIX = Fake_glXDestroyGLXPbufferSGIX;
03162    glx.QueryGLXPbufferSGIX = Fake_glXQueryGLXPbufferSGIX;
03163    glx.SelectEventSGIX = Fake_glXSelectEventSGIX;
03164    glx.GetSelectedEventSGIX = Fake_glXGetSelectedEventSGIX;
03165 
03166    /*** GLX_SGI_cushion ***/
03167    glx.CushionSGI = Fake_glXCushionSGI;
03168 
03169    /*** GLX_SGIX_video_resize ***/
03170    glx.BindChannelToWindowSGIX = Fake_glXBindChannelToWindowSGIX;
03171    glx.ChannelRectSGIX = Fake_glXChannelRectSGIX;
03172    glx.QueryChannelRectSGIX = Fake_glXQueryChannelRectSGIX;
03173    glx.QueryChannelDeltasSGIX = Fake_glXQueryChannelDeltasSGIX;
03174    glx.ChannelRectSyncSGIX = Fake_glXChannelRectSyncSGIX;
03175 
03176    /*** GLX_SGIX_dmbuffer **/
03177 #if defined(_DM_BUFFER_H_)
03178    glx.AssociateDMPbufferSGIX = NULL;
03179 #endif
03180 
03181    /*** GLX_SGIX_swap_group ***/
03182    glx.JoinSwapGroupSGIX = Fake_glXJoinSwapGroupSGIX;
03183 
03184    /*** GLX_SGIX_swap_barrier ***/
03185    glx.BindSwapBarrierSGIX = Fake_glXBindSwapBarrierSGIX;
03186    glx.QueryMaxSwapBarriersSGIX = Fake_glXQueryMaxSwapBarriersSGIX;
03187 
03188    /*** GLX_SUN_get_transparent_index ***/
03189    glx.GetTransparentIndexSUN = Fake_glXGetTransparentIndexSUN;
03190 
03191    /*** GLX_MESA_copy_sub_buffer ***/
03192    glx.CopySubBufferMESA = Fake_glXCopySubBufferMESA;
03193 
03194    /*** GLX_MESA_release_buffers ***/
03195    glx.ReleaseBuffersMESA = Fake_glXReleaseBuffersMESA;
03196 
03197    /*** GLX_MESA_pixmap_colormap ***/
03198    glx.CreateGLXPixmapMESA = Fake_glXCreateGLXPixmapMESA;
03199 
03200    /*** GLX_MESA_set_3dfx_mode ***/
03201    glx.Set3DfxModeMESA = Fake_glXSet3DfxModeMESA;
03202 
03203    /*** GLX_NV_vertex_array_range ***/
03204    glx.AllocateMemoryNV = Fake_glXAllocateMemoryNV;
03205    glx.FreeMemoryNV = Fake_glXFreeMemoryNV;
03206 
03207    /*** GLX_MESA_agp_offset ***/
03208    glx.GetAGPOffsetMESA = Fake_glXGetAGPOffsetMESA;
03209 
03210    /*** GLX_EXT_texture_from_pixmap ***/
03211    glx.BindTexImageEXT = Fake_glXBindTexImageEXT;
03212    glx.ReleaseTexImageEXT = Fake_glXReleaseTexImageEXT;
03213 
03214    return &glx;
03215 }

Generated on Tue Sep 29 06:25:17 2009 for Gallium3D by  doxygen 1.5.4