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