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