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