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