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