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