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