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