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