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      if (fbConfig &&
691          parselist[1] == GLX_DONT_CARE &&
692          parselist[0] != GLX_LEVEL) {
693         /* For glXChooseFBConfig(), skip attributes whose value is
694          * GLX_DONT_CARE, unless it's GLX_LEVEL (which can legitimately be
695          * a negative value).
696          *
697          * From page 17 (23 of the pdf) of the GLX 1.4 spec:
698          * GLX DONT CARE may be specified for all attributes except GLX LEVEL.
699          */
700         parselist += 2;
701         continue;
702      }
703
704      switch (*parselist) {
705	 case GLX_USE_GL:
706            if (fbConfig) {
707               /* invalid token */
708               return NULL;
709            }
710            else {
711               /* skip */
712               parselist++;
713            }
714	    break;
715	 case GLX_BUFFER_SIZE:
716	    parselist++;
717	    parselist++;
718	    break;
719	 case GLX_LEVEL:
720	    parselist++;
721            level = *parselist++;
722	    break;
723	 case GLX_RGBA:
724            if (fbConfig) {
725               /* invalid token */
726               return NULL;
727            }
728            else {
729               rgb_flag = GL_TRUE;
730               parselist++;
731            }
732	    break;
733	 case GLX_DOUBLEBUFFER:
734            parselist++;
735            if (fbConfig) {
736               double_flag = *parselist++;
737            }
738            else {
739               double_flag = GL_TRUE;
740            }
741	    break;
742	 case GLX_STEREO:
743            parselist++;
744            if (fbConfig) {
745               stereo_flag = *parselist++;
746            }
747            else {
748               stereo_flag = GL_TRUE;
749            }
750            break;
751	 case GLX_AUX_BUFFERS:
752	    parselist++;
753            numAux = *parselist++;
754            if (numAux > MAX_AUX_BUFFERS)
755               return NULL;
756	    break;
757	 case GLX_RED_SIZE:
758	    parselist++;
759	    min_red = *parselist++;
760	    break;
761	 case GLX_GREEN_SIZE:
762	    parselist++;
763	    min_green = *parselist++;
764	    break;
765	 case GLX_BLUE_SIZE:
766	    parselist++;
767	    min_blue = *parselist++;
768	    break;
769	 case GLX_ALPHA_SIZE:
770	    parselist++;
771            {
772               GLint size = *parselist++;
773               alpha_flag = size ? GL_TRUE : GL_FALSE;
774            }
775	    break;
776	 case GLX_DEPTH_SIZE:
777	    parselist++;
778	    depth_size = *parselist++;
779	    break;
780	 case GLX_STENCIL_SIZE:
781	    parselist++;
782	    stencil_size = *parselist++;
783	    break;
784	 case GLX_ACCUM_RED_SIZE:
785	    parselist++;
786            {
787               GLint size = *parselist++;
788               accumRedSize = MAX2( accumRedSize, size );
789            }
790            break;
791	 case GLX_ACCUM_GREEN_SIZE:
792	    parselist++;
793            {
794               GLint size = *parselist++;
795               accumGreenSize = MAX2( accumGreenSize, size );
796            }
797            break;
798	 case GLX_ACCUM_BLUE_SIZE:
799	    parselist++;
800            {
801               GLint size = *parselist++;
802               accumBlueSize = MAX2( accumBlueSize, size );
803            }
804            break;
805	 case GLX_ACCUM_ALPHA_SIZE:
806	    parselist++;
807            {
808               GLint size = *parselist++;
809               accumAlphaSize = MAX2( accumAlphaSize, size );
810            }
811	    break;
812
813         /*
814          * GLX_EXT_visual_info extension
815          */
816         case GLX_X_VISUAL_TYPE_EXT:
817            parselist++;
818            visual_type = *parselist++;
819            break;
820         case GLX_TRANSPARENT_TYPE_EXT:
821            parselist++;
822            parselist++;
823            break;
824         case GLX_TRANSPARENT_INDEX_VALUE_EXT:
825            parselist++;
826            parselist++;
827            break;
828         case GLX_TRANSPARENT_RED_VALUE_EXT:
829         case GLX_TRANSPARENT_GREEN_VALUE_EXT:
830         case GLX_TRANSPARENT_BLUE_VALUE_EXT:
831         case GLX_TRANSPARENT_ALPHA_VALUE_EXT:
832	    /* ignore */
833	    parselist++;
834	    parselist++;
835	    break;
836
837         /*
838          * GLX_EXT_visual_info extension
839          */
840         case GLX_VISUAL_CAVEAT_EXT:
841            parselist++;
842            caveat = *parselist++; /* ignored for now */
843            break;
844
845         /*
846          * GLX_ARB_multisample
847          */
848         case GLX_SAMPLE_BUFFERS_ARB:
849         case GLX_SAMPLES_ARB:
850            parselist++;
851            if (*parselist++ != 0) {
852               /* ms not supported */
853               return NULL;
854            }
855            break;
856
857         /*
858          * FBConfig attribs.
859          */
860         case GLX_RENDER_TYPE:
861            if (!fbConfig)
862               return NULL;
863            parselist++;
864            if (*parselist & GLX_RGBA_BIT) {
865               rgb_flag = GL_TRUE;
866            }
867            else if (*parselist & GLX_COLOR_INDEX_BIT) {
868               rgb_flag = GL_FALSE;
869            }
870            else if (*parselist == 0) {
871               rgb_flag = GL_TRUE;
872            }
873            parselist++;
874            break;
875         case GLX_DRAWABLE_TYPE:
876            if (!fbConfig)
877               return NULL;
878            parselist++;
879            if (*parselist & ~(GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT)) {
880               return NULL; /* bad bit */
881            }
882            parselist++;
883            break;
884         case GLX_FBCONFIG_ID:
885         case GLX_VISUAL_ID:
886            if (!fbConfig)
887               return NULL;
888            parselist++;
889            desiredVisualID = *parselist++;
890            break;
891         case GLX_X_RENDERABLE:
892         case GLX_MAX_PBUFFER_WIDTH:
893         case GLX_MAX_PBUFFER_HEIGHT:
894         case GLX_MAX_PBUFFER_PIXELS:
895            if (!fbConfig)
896               return NULL; /* invalid config option */
897            parselist += 2; /* ignore the parameter */
898            break;
899
900#ifdef GLX_EXT_texture_from_pixmap
901         case GLX_BIND_TO_TEXTURE_RGB_EXT:
902            parselist++; /*skip*/
903            break;
904         case GLX_BIND_TO_TEXTURE_RGBA_EXT:
905            parselist++; /*skip*/
906            break;
907         case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
908            parselist++; /*skip*/
909            break;
910         case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
911            parselist++;
912            if (*parselist & ~(GLX_TEXTURE_1D_BIT_EXT |
913                               GLX_TEXTURE_2D_BIT_EXT |
914                               GLX_TEXTURE_RECTANGLE_BIT_EXT)) {
915               /* invalid bit */
916               return NULL;
917            }
918            break;
919         case GLX_Y_INVERTED_EXT:
920            parselist++; /*skip*/
921            break;
922#endif
923
924	 case None:
925            /* end of list */
926	    break;
927
928	 default:
929	    /* undefined attribute */
930            _mesa_warning(NULL, "unexpected attrib 0x%x in choose_visual()",
931                          *parselist);
932	    return NULL;
933      }
934   }
935
936   (void) caveat;
937
938
939   /*
940    * Since we're only simulating the GLX extension this function will never
941    * find any real GL visuals.  Instead, all we can do is try to find an RGB
942    * or CI visual of appropriate depth.  Other requested attributes such as
943    * double buffering, depth buffer, etc. will be associated with the X
944    * visual and stored in the VisualTable[].
945    */
946   if (desiredVisualID != -1) {
947      /* try to get a specific visual, by visualID */
948      XVisualInfo temp;
949      int n;
950      temp.visualid = desiredVisualID;
951      temp.screen = screen;
952      vis = XGetVisualInfo(dpy, VisualIDMask | VisualScreenMask, &temp, &n);
953      if (vis) {
954         /* give the visual some useful GLX attributes */
955         double_flag = GL_TRUE;
956         rgb_flag = GL_TRUE;
957      }
958   }
959   else if (level==0) {
960      /* normal color planes */
961      /* Get an RGB visual */
962      int min_rgb = min_red + min_green + min_blue;
963      if (min_rgb>1 && min_rgb<8) {
964         /* a special case to be sure we can get a monochrome visual */
965         min_rgb = 1;
966      }
967      vis = choose_x_visual( dpy, screen, min_rgb, visual_type );
968   }
969   else {
970      _mesa_warning(NULL, "overlay not supported");
971      return NULL;
972   }
973
974   if (vis) {
975      /* Note: we're not exactly obeying the glXChooseVisual rules here.
976       * When GLX_DEPTH_SIZE = 1 is specified we're supposed to choose the
977       * largest depth buffer size, which is 32bits/value.  Instead, we
978       * return 16 to maintain performance with earlier versions of Mesa.
979       */
980      if (stencil_size > 0)
981         depth_size = 24;  /* if Z and stencil, always use 24+8 format */
982      else if (depth_size > 24)
983         depth_size = 32;
984      else if (depth_size > 16)
985         depth_size = 24;
986      else if (depth_size > 0) {
987         depth_size = default_depth_bits();
988      }
989
990      if (!alpha_flag) {
991         alpha_flag = default_alpha_bits() > 0;
992      }
993
994      /* we only support one size of stencil and accum buffers. */
995      if (stencil_size > 0)
996         stencil_size = 8;
997
998      if (accumRedSize > 0 ||
999          accumGreenSize > 0 ||
1000          accumBlueSize > 0 ||
1001          accumAlphaSize > 0) {
1002
1003         accumRedSize =
1004            accumGreenSize =
1005            accumBlueSize = default_accum_bits();
1006
1007         accumAlphaSize = alpha_flag ? accumRedSize : 0;
1008      }
1009
1010      xmvis = save_glx_visual( dpy, vis, rgb_flag, alpha_flag, double_flag,
1011                               stereo_flag, depth_size, stencil_size,
1012                               accumRedSize, accumGreenSize,
1013                               accumBlueSize, accumAlphaSize, level, numAux );
1014   }
1015
1016   return xmvis;
1017}
1018
1019
1020PUBLIC XVisualInfo *
1021glXChooseVisual( Display *dpy, int screen, int *list )
1022{
1023   XMesaVisual xmvis;
1024
1025   /* register ourselves as an extension on this display */
1026   register_with_display(dpy);
1027
1028   xmvis = choose_visual(dpy, screen, list, GL_FALSE);
1029   if (xmvis) {
1030      /* create a new vishandle - the cached one may be stale */
1031      xmvis->vishandle = (XVisualInfo *) malloc(sizeof(XVisualInfo));
1032      if (xmvis->vishandle) {
1033         memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo));
1034      }
1035      return xmvis->vishandle;
1036   }
1037   else
1038      return NULL;
1039}
1040
1041
1042/**
1043 * Helper function used by other glXCreateContext functions.
1044 */
1045static GLXContext
1046create_context(Display *dpy, XMesaVisual xmvis,
1047               XMesaContext shareCtx, Bool direct,
1048               unsigned major, unsigned minor,
1049               unsigned profileMask, unsigned contextFlags)
1050{
1051   GLXContext glxCtx;
1052
1053   if (!dpy || !xmvis)
1054      return 0;
1055
1056   glxCtx = CALLOC_STRUCT(__GLXcontextRec);
1057   if (!glxCtx)
1058      return 0;
1059
1060   /* deallocate unused windows/buffers */
1061#if 0
1062   XMesaGarbageCollect();
1063#endif
1064
1065   glxCtx->xmesaContext = XMesaCreateContext(xmvis, shareCtx, major, minor,
1066                                             profileMask, contextFlags);
1067   if (!glxCtx->xmesaContext) {
1068      free(glxCtx);
1069      return NULL;
1070   }
1071
1072   glxCtx->isDirect = DEFAULT_DIRECT;
1073   glxCtx->currentDpy = dpy;
1074   glxCtx->xid = (XID) glxCtx;  /* self pointer */
1075
1076   return glxCtx;
1077}
1078
1079
1080PUBLIC GLXContext
1081glXCreateContext( Display *dpy, XVisualInfo *visinfo,
1082                  GLXContext shareCtx, Bool direct )
1083{
1084   XMesaVisual xmvis;
1085
1086   xmvis = find_glx_visual( dpy, visinfo );
1087   if (!xmvis) {
1088      /* This visual wasn't found with glXChooseVisual() */
1089      xmvis = create_glx_visual( dpy, visinfo );
1090      if (!xmvis) {
1091         /* unusable visual */
1092         return NULL;
1093      }
1094   }
1095
1096   return create_context(dpy, xmvis,
1097                         shareCtx ? shareCtx->xmesaContext : NULL,
1098                         direct,
1099                         1, 0, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, 0x0);
1100}
1101
1102
1103/* XXX these may have to be removed due to thread-safety issues. */
1104static GLXContext MakeCurrent_PrevContext = 0;
1105static GLXDrawable MakeCurrent_PrevDrawable = 0;
1106static GLXDrawable MakeCurrent_PrevReadable = 0;
1107static XMesaBuffer MakeCurrent_PrevDrawBuffer = 0;
1108static XMesaBuffer MakeCurrent_PrevReadBuffer = 0;
1109
1110
1111/* GLX 1.3 and later */
1112PUBLIC Bool
1113glXMakeContextCurrent( Display *dpy, GLXDrawable draw,
1114                       GLXDrawable read, GLXContext ctx )
1115{
1116   GLXContext glxCtx = ctx;
1117   static boolean firsttime = 1, no_rast = 0;
1118
1119   if (firsttime) {
1120      no_rast = getenv("SP_NO_RAST") != NULL;
1121      firsttime = 0;
1122   }
1123
1124   if (ctx && draw && read) {
1125      XMesaBuffer drawBuffer, readBuffer;
1126      XMesaContext xmctx = glxCtx->xmesaContext;
1127
1128      /* Find the XMesaBuffer which corresponds to the GLXDrawable 'draw' */
1129      if (ctx == MakeCurrent_PrevContext
1130          && draw == MakeCurrent_PrevDrawable) {
1131         drawBuffer = MakeCurrent_PrevDrawBuffer;
1132      }
1133      else {
1134         drawBuffer = XMesaFindBuffer( dpy, draw );
1135      }
1136      if (!drawBuffer) {
1137         /* drawable must be a new window! */
1138         drawBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, draw );
1139         if (!drawBuffer) {
1140            /* Out of memory, or context/drawable depth mismatch */
1141            return False;
1142         }
1143      }
1144
1145      /* Find the XMesaBuffer which corresponds to the GLXDrawable 'read' */
1146      if (ctx == MakeCurrent_PrevContext
1147          && read == MakeCurrent_PrevReadable) {
1148         readBuffer = MakeCurrent_PrevReadBuffer;
1149      }
1150      else {
1151         readBuffer = XMesaFindBuffer( dpy, read );
1152      }
1153      if (!readBuffer) {
1154         /* drawable must be a new window! */
1155         readBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, read );
1156         if (!readBuffer) {
1157            /* Out of memory, or context/drawable depth mismatch */
1158            return False;
1159         }
1160      }
1161
1162      if (no_rast &&
1163          MakeCurrent_PrevContext == ctx &&
1164          MakeCurrent_PrevDrawable == draw &&
1165          MakeCurrent_PrevReadable == read &&
1166          MakeCurrent_PrevDrawBuffer == drawBuffer &&
1167          MakeCurrent_PrevReadBuffer == readBuffer)
1168         return True;
1169
1170      MakeCurrent_PrevContext = ctx;
1171      MakeCurrent_PrevDrawable = draw;
1172      MakeCurrent_PrevReadable = read;
1173      MakeCurrent_PrevDrawBuffer = drawBuffer;
1174      MakeCurrent_PrevReadBuffer = readBuffer;
1175
1176      /* Now make current! */
1177      if (XMesaMakeCurrent2(xmctx, drawBuffer, readBuffer)) {
1178         ctx->currentDpy = dpy;
1179         ctx->currentDrawable = draw;
1180         ctx->currentReadable = read;
1181         SetCurrentContext(ctx);
1182         return True;
1183      }
1184      else {
1185         return False;
1186      }
1187   }
1188   else if (!ctx && !draw && !read) {
1189      /* release current context w/out assigning new one. */
1190      XMesaMakeCurrent2( NULL, NULL, NULL );
1191      MakeCurrent_PrevContext = 0;
1192      MakeCurrent_PrevDrawable = 0;
1193      MakeCurrent_PrevReadable = 0;
1194      MakeCurrent_PrevDrawBuffer = 0;
1195      MakeCurrent_PrevReadBuffer = 0;
1196      SetCurrentContext(NULL);
1197      return True;
1198   }
1199   else {
1200      /* The args must either all be non-zero or all zero.
1201       * This is an error.
1202       */
1203      return False;
1204   }
1205}
1206
1207
1208PUBLIC Bool
1209glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx )
1210{
1211   return glXMakeContextCurrent( dpy, drawable, drawable, ctx );
1212}
1213
1214
1215PUBLIC GLXContext
1216glXGetCurrentContext(void)
1217{
1218   return GetCurrentContext();
1219}
1220
1221
1222PUBLIC Display *
1223glXGetCurrentDisplay(void)
1224{
1225   GLXContext glxCtx = glXGetCurrentContext();
1226
1227   return glxCtx ? glxCtx->currentDpy : NULL;
1228}
1229
1230
1231PUBLIC Display *
1232glXGetCurrentDisplayEXT(void)
1233{
1234   return glXGetCurrentDisplay();
1235}
1236
1237
1238PUBLIC GLXDrawable
1239glXGetCurrentDrawable(void)
1240{
1241   GLXContext gc = glXGetCurrentContext();
1242   return gc ? gc->currentDrawable : 0;
1243}
1244
1245
1246PUBLIC GLXDrawable
1247glXGetCurrentReadDrawable(void)
1248{
1249   GLXContext gc = glXGetCurrentContext();
1250   return gc ? gc->currentReadable : 0;
1251}
1252
1253
1254PUBLIC GLXDrawable
1255glXGetCurrentReadDrawableSGI(void)
1256{
1257   return glXGetCurrentReadDrawable();
1258}
1259
1260
1261PUBLIC GLXPixmap
1262glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, Pixmap pixmap )
1263{
1264   XMesaVisual v;
1265   XMesaBuffer b;
1266
1267   v = find_glx_visual( dpy, visinfo );
1268   if (!v) {
1269      v = create_glx_visual( dpy, visinfo );
1270      if (!v) {
1271         /* unusable visual */
1272         return 0;
1273      }
1274   }
1275
1276   b = XMesaCreatePixmapBuffer( v, pixmap, 0 );
1277   if (!b) {
1278      return 0;
1279   }
1280   return b->ws.drawable;
1281}
1282
1283
1284/*** GLX_MESA_pixmap_colormap ***/
1285
1286PUBLIC GLXPixmap
1287glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo,
1288                        Pixmap pixmap, Colormap cmap )
1289{
1290   XMesaVisual v;
1291   XMesaBuffer b;
1292
1293   v = find_glx_visual( dpy, visinfo );
1294   if (!v) {
1295      v = create_glx_visual( dpy, visinfo );
1296      if (!v) {
1297         /* unusable visual */
1298         return 0;
1299      }
1300   }
1301
1302   b = XMesaCreatePixmapBuffer( v, pixmap, cmap );
1303   if (!b) {
1304      return 0;
1305   }
1306   return b->ws.drawable;
1307}
1308
1309
1310PUBLIC void
1311glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap )
1312{
1313   XMesaBuffer b = XMesaFindBuffer(dpy, pixmap);
1314   if (b) {
1315      XMesaDestroyBuffer(b);
1316   }
1317   else if (_mesa_getenv("MESA_DEBUG")) {
1318      _mesa_warning(NULL, "Mesa: glXDestroyGLXPixmap: invalid pixmap\n");
1319   }
1320}
1321
1322
1323PUBLIC void
1324glXCopyContext( Display *dpy, GLXContext src, GLXContext dst,
1325                unsigned long mask )
1326{
1327   XMesaContext xm_src = src->xmesaContext;
1328   XMesaContext xm_dst = dst->xmesaContext;
1329   (void) dpy;
1330   if (MakeCurrent_PrevContext == src) {
1331      glFlush();
1332   }
1333   XMesaCopyContext(xm_src, xm_dst, mask);
1334}
1335
1336
1337PUBLIC Bool
1338glXQueryExtension( Display *dpy, int *errorBase, int *eventBase )
1339{
1340   int op, ev, err;
1341   /* Mesa's GLX isn't really an X extension but we try to act like one. */
1342   if (!XQueryExtension(dpy, GLX_EXTENSION_NAME, &op, &ev, &err))
1343      ev = err = 0;
1344   if (errorBase)
1345      *errorBase = err;
1346   if (eventBase)
1347      *eventBase = ev;
1348   return True; /* we're faking GLX so always return success */
1349}
1350
1351
1352PUBLIC void
1353glXDestroyContext( Display *dpy, GLXContext ctx )
1354{
1355   GLXContext glxCtx = ctx;
1356   (void) dpy;
1357   MakeCurrent_PrevContext = 0;
1358   MakeCurrent_PrevDrawable = 0;
1359   MakeCurrent_PrevReadable = 0;
1360   MakeCurrent_PrevDrawBuffer = 0;
1361   MakeCurrent_PrevReadBuffer = 0;
1362   XMesaDestroyContext( glxCtx->xmesaContext );
1363   XMesaGarbageCollect();
1364   free(glxCtx);
1365}
1366
1367
1368PUBLIC Bool
1369glXIsDirect( Display *dpy, GLXContext ctx )
1370{
1371   GLXContext glxCtx = ctx;
1372   (void) ctx;
1373   return glxCtx->isDirect;
1374}
1375
1376
1377
1378PUBLIC void
1379glXSwapBuffers( Display *dpy, GLXDrawable drawable )
1380{
1381   XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable );
1382   static boolean firsttime = 1, no_rast = 0;
1383
1384   if (firsttime) {
1385      no_rast = getenv("SP_NO_RAST") != NULL;
1386      firsttime = 0;
1387   }
1388
1389   if (no_rast)
1390      return;
1391
1392   if (buffer) {
1393      XMesaSwapBuffers(buffer);
1394   }
1395   else if (_mesa_getenv("MESA_DEBUG")) {
1396      _mesa_warning(NULL, "glXSwapBuffers: invalid drawable 0x%x\n",
1397                    (int) drawable);
1398   }
1399}
1400
1401
1402
1403/*** GLX_MESA_copy_sub_buffer ***/
1404
1405PUBLIC void
1406glXCopySubBufferMESA(Display *dpy, GLXDrawable drawable,
1407                     int x, int y, int width, int height)
1408{
1409   XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable );
1410   if (buffer) {
1411      XMesaCopySubBuffer(buffer, x, y, width, height);
1412   }
1413   else if (_mesa_getenv("MESA_DEBUG")) {
1414      _mesa_warning(NULL, "Mesa: glXCopySubBufferMESA: invalid drawable\n");
1415   }
1416}
1417
1418
1419PUBLIC Bool
1420glXQueryVersion( Display *dpy, int *maj, int *min )
1421{
1422   (void) dpy;
1423   /* Return GLX version, not Mesa version */
1424   assert(CLIENT_MAJOR_VERSION == SERVER_MAJOR_VERSION);
1425   *maj = CLIENT_MAJOR_VERSION;
1426   *min = MIN2( CLIENT_MINOR_VERSION, SERVER_MINOR_VERSION );
1427   return True;
1428}
1429
1430
1431/*
1432 * Query the GLX attributes of the given XVisualInfo.
1433 */
1434static int
1435get_config( XMesaVisual xmvis, int attrib, int *value, GLboolean fbconfig )
1436{
1437   ASSERT(xmvis);
1438   switch(attrib) {
1439      case GLX_USE_GL:
1440         if (fbconfig)
1441            return GLX_BAD_ATTRIBUTE;
1442         *value = (int) True;
1443	 return 0;
1444      case GLX_BUFFER_SIZE:
1445	 *value = xmvis->visinfo->depth;
1446	 return 0;
1447      case GLX_LEVEL:
1448	 *value = xmvis->mesa_visual.level;
1449	 return 0;
1450      case GLX_RGBA:
1451         if (fbconfig)
1452            return GLX_BAD_ATTRIBUTE;
1453	 if (xmvis->mesa_visual.rgbMode) {
1454	    *value = True;
1455	 }
1456	 else {
1457	    *value = False;
1458	 }
1459	 return 0;
1460      case GLX_DOUBLEBUFFER:
1461	 *value = (int) xmvis->mesa_visual.doubleBufferMode;
1462	 return 0;
1463      case GLX_STEREO:
1464	 *value = (int) xmvis->mesa_visual.stereoMode;
1465	 return 0;
1466      case GLX_AUX_BUFFERS:
1467	 *value = xmvis->mesa_visual.numAuxBuffers;
1468	 return 0;
1469      case GLX_RED_SIZE:
1470         *value = xmvis->mesa_visual.redBits;
1471	 return 0;
1472      case GLX_GREEN_SIZE:
1473         *value = xmvis->mesa_visual.greenBits;
1474	 return 0;
1475      case GLX_BLUE_SIZE:
1476         *value = xmvis->mesa_visual.blueBits;
1477	 return 0;
1478      case GLX_ALPHA_SIZE:
1479         *value = xmvis->mesa_visual.alphaBits;
1480	 return 0;
1481      case GLX_DEPTH_SIZE:
1482         *value = xmvis->mesa_visual.depthBits;
1483	 return 0;
1484      case GLX_STENCIL_SIZE:
1485	 *value = xmvis->mesa_visual.stencilBits;
1486	 return 0;
1487      case GLX_ACCUM_RED_SIZE:
1488	 *value = xmvis->mesa_visual.accumRedBits;
1489	 return 0;
1490      case GLX_ACCUM_GREEN_SIZE:
1491	 *value = xmvis->mesa_visual.accumGreenBits;
1492	 return 0;
1493      case GLX_ACCUM_BLUE_SIZE:
1494	 *value = xmvis->mesa_visual.accumBlueBits;
1495	 return 0;
1496      case GLX_ACCUM_ALPHA_SIZE:
1497         *value = xmvis->mesa_visual.accumAlphaBits;
1498	 return 0;
1499
1500      /*
1501       * GLX_EXT_visual_info extension
1502       */
1503      case GLX_X_VISUAL_TYPE_EXT:
1504         switch (xmvis->visinfo->CLASS) {
1505            case StaticGray:   *value = GLX_STATIC_GRAY_EXT;   return 0;
1506            case GrayScale:    *value = GLX_GRAY_SCALE_EXT;    return 0;
1507            case StaticColor:  *value = GLX_STATIC_GRAY_EXT;   return 0;
1508            case PseudoColor:  *value = GLX_PSEUDO_COLOR_EXT;  return 0;
1509            case TrueColor:    *value = GLX_TRUE_COLOR_EXT;    return 0;
1510            case DirectColor:  *value = GLX_DIRECT_COLOR_EXT;  return 0;
1511         }
1512         return 0;
1513      case GLX_TRANSPARENT_TYPE_EXT:
1514         /* normal planes */
1515         *value = GLX_NONE_EXT;
1516         return 0;
1517      case GLX_TRANSPARENT_INDEX_VALUE_EXT:
1518         /* undefined */
1519         return 0;
1520      case GLX_TRANSPARENT_RED_VALUE_EXT:
1521         /* undefined */
1522         return 0;
1523      case GLX_TRANSPARENT_GREEN_VALUE_EXT:
1524         /* undefined */
1525         return 0;
1526      case GLX_TRANSPARENT_BLUE_VALUE_EXT:
1527         /* undefined */
1528         return 0;
1529      case GLX_TRANSPARENT_ALPHA_VALUE_EXT:
1530         /* undefined */
1531         return 0;
1532
1533      /*
1534       * GLX_EXT_visual_info extension
1535       */
1536      case GLX_VISUAL_CAVEAT_EXT:
1537         /* test for zero, just in case */
1538         if (xmvis->mesa_visual.visualRating > 0)
1539            *value = xmvis->mesa_visual.visualRating;
1540         else
1541            *value = GLX_NONE_EXT;
1542         return 0;
1543
1544      /*
1545       * GLX_ARB_multisample
1546       */
1547      case GLX_SAMPLE_BUFFERS_ARB:
1548         *value = 0;
1549         return 0;
1550      case GLX_SAMPLES_ARB:
1551         *value = 0;
1552         return 0;
1553
1554      /*
1555       * For FBConfigs:
1556       */
1557      case GLX_SCREEN_EXT:
1558         if (!fbconfig)
1559            return GLX_BAD_ATTRIBUTE;
1560         *value = xmvis->visinfo->screen;
1561         break;
1562      case GLX_DRAWABLE_TYPE: /*SGIX too */
1563         if (!fbconfig)
1564            return GLX_BAD_ATTRIBUTE;
1565         *value = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
1566         break;
1567      case GLX_RENDER_TYPE_SGIX:
1568         if (!fbconfig)
1569            return GLX_BAD_ATTRIBUTE;
1570         if (xmvis->mesa_visual.rgbMode)
1571            *value = GLX_RGBA_BIT;
1572         else
1573            *value = GLX_COLOR_INDEX_BIT;
1574         break;
1575      case GLX_X_RENDERABLE_SGIX:
1576         if (!fbconfig)
1577            return GLX_BAD_ATTRIBUTE;
1578         *value = True; /* XXX really? */
1579         break;
1580      case GLX_FBCONFIG_ID_SGIX:
1581         if (!fbconfig)
1582            return GLX_BAD_ATTRIBUTE;
1583         *value = xmvis->visinfo->visualid;
1584         break;
1585      case GLX_MAX_PBUFFER_WIDTH:
1586         if (!fbconfig)
1587            return GLX_BAD_ATTRIBUTE;
1588         /* XXX or MAX_WIDTH? */
1589         *value = DisplayWidth(xmvis->display, xmvis->visinfo->screen);
1590         break;
1591      case GLX_MAX_PBUFFER_HEIGHT:
1592         if (!fbconfig)
1593            return GLX_BAD_ATTRIBUTE;
1594         *value = DisplayHeight(xmvis->display, xmvis->visinfo->screen);
1595         break;
1596      case GLX_MAX_PBUFFER_PIXELS:
1597         if (!fbconfig)
1598            return GLX_BAD_ATTRIBUTE;
1599         *value = DisplayWidth(xmvis->display, xmvis->visinfo->screen) *
1600                  DisplayHeight(xmvis->display, xmvis->visinfo->screen);
1601         break;
1602      case GLX_VISUAL_ID:
1603         if (!fbconfig)
1604            return GLX_BAD_ATTRIBUTE;
1605         *value = xmvis->visinfo->visualid;
1606         break;
1607
1608#ifdef GLX_EXT_texture_from_pixmap
1609      case GLX_BIND_TO_TEXTURE_RGB_EXT:
1610         *value = True; /*XXX*/
1611         break;
1612      case GLX_BIND_TO_TEXTURE_RGBA_EXT:
1613         /* XXX review */
1614         *value = xmvis->mesa_visual.alphaBits > 0 ? True : False;
1615         break;
1616      case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
1617         *value = True; /*XXX*/
1618         break;
1619      case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
1620         *value = (GLX_TEXTURE_1D_BIT_EXT |
1621                   GLX_TEXTURE_2D_BIT_EXT |
1622                   GLX_TEXTURE_RECTANGLE_BIT_EXT); /*XXX*/
1623         break;
1624      case GLX_Y_INVERTED_EXT:
1625         *value = True; /*XXX*/
1626         break;
1627#endif
1628
1629      default:
1630	 return GLX_BAD_ATTRIBUTE;
1631   }
1632   return Success;
1633}
1634
1635
1636PUBLIC int
1637glXGetConfig( Display *dpy, XVisualInfo *visinfo,
1638                   int attrib, int *value )
1639{
1640   XMesaVisual xmvis;
1641   int k;
1642   if (!dpy || !visinfo)
1643      return GLX_BAD_ATTRIBUTE;
1644
1645   xmvis = find_glx_visual( dpy, visinfo );
1646   if (!xmvis) {
1647      /* this visual wasn't obtained with glXChooseVisual */
1648      xmvis = create_glx_visual( dpy, visinfo );
1649      if (!xmvis) {
1650	 /* this visual can't be used for GL rendering */
1651	 if (attrib==GLX_USE_GL) {
1652	    *value = (int) False;
1653	    return 0;
1654	 }
1655	 else {
1656	    return GLX_BAD_VISUAL;
1657	 }
1658      }
1659   }
1660
1661   k = get_config(xmvis, attrib, value, GL_FALSE);
1662   return k;
1663}
1664
1665
1666PUBLIC void
1667glXWaitGL( void )
1668{
1669   XMesaContext xmesa = XMesaGetCurrentContext();
1670   XMesaFlush( xmesa );
1671}
1672
1673
1674
1675PUBLIC void
1676glXWaitX( void )
1677{
1678   XMesaContext xmesa = XMesaGetCurrentContext();
1679   XMesaFlush( xmesa );
1680}
1681
1682
1683static const char *
1684get_extensions( void )
1685{
1686   return EXTENSIONS;
1687}
1688
1689
1690
1691/* GLX 1.1 and later */
1692PUBLIC const char *
1693glXQueryExtensionsString( Display *dpy, int screen )
1694{
1695   (void) dpy;
1696   (void) screen;
1697   return get_extensions();
1698}
1699
1700
1701
1702/* GLX 1.1 and later */
1703PUBLIC const char *
1704glXQueryServerString( Display *dpy, int screen, int name )
1705{
1706   static char version[1000];
1707   sprintf(version, "%d.%d %s",
1708	   SERVER_MAJOR_VERSION, SERVER_MINOR_VERSION, xmesa_get_name());
1709
1710   (void) dpy;
1711   (void) screen;
1712
1713   switch (name) {
1714      case GLX_EXTENSIONS:
1715         return get_extensions();
1716      case GLX_VENDOR:
1717	 return VENDOR;
1718      case GLX_VERSION:
1719	 return version;
1720      default:
1721         return NULL;
1722   }
1723}
1724
1725
1726
1727/* GLX 1.1 and later */
1728PUBLIC const char *
1729glXGetClientString( Display *dpy, int name )
1730{
1731   static char version[1000];
1732   sprintf(version, "%d.%d %s", CLIENT_MAJOR_VERSION,
1733	   CLIENT_MINOR_VERSION, xmesa_get_name());
1734
1735   (void) dpy;
1736
1737   switch (name) {
1738      case GLX_EXTENSIONS:
1739         return get_extensions();
1740      case GLX_VENDOR:
1741	 return VENDOR;
1742      case GLX_VERSION:
1743	 return version;
1744      default:
1745         return NULL;
1746   }
1747}
1748
1749
1750
1751/*
1752 * GLX 1.3 and later
1753 */
1754
1755
1756PUBLIC int
1757glXGetFBConfigAttrib(Display *dpy, GLXFBConfig config,
1758                     int attribute, int *value)
1759{
1760   XMesaVisual v = (XMesaVisual) config;
1761   (void) dpy;
1762   (void) config;
1763
1764   if (!dpy || !config || !value)
1765      return -1;
1766
1767   return get_config(v, attribute, value, GL_TRUE);
1768}
1769
1770
1771PUBLIC GLXFBConfig *
1772glXGetFBConfigs( Display *dpy, int screen, int *nelements )
1773{
1774   XVisualInfo *visuals, visTemplate;
1775   const long visMask = VisualScreenMask;
1776   int i;
1777
1778   /* Get list of all X visuals */
1779   visTemplate.screen = screen;
1780   visuals = XGetVisualInfo(dpy, visMask, &visTemplate, nelements);
1781   if (*nelements > 0) {
1782      XMesaVisual *results;
1783      results = (XMesaVisual *) malloc(*nelements * sizeof(XMesaVisual));
1784      if (!results) {
1785         *nelements = 0;
1786         return NULL;
1787      }
1788      for (i = 0; i < *nelements; i++) {
1789         results[i] = create_glx_visual(dpy, visuals + i);
1790         if (!results[i]) {
1791            *nelements = i;
1792            break;
1793         }
1794      }
1795      return (GLXFBConfig *) results;
1796   }
1797   return NULL;
1798}
1799
1800
1801PUBLIC GLXFBConfig *
1802glXChooseFBConfig(Display *dpy, int screen,
1803                  const int *attribList, int *nitems)
1804{
1805   XMesaVisual xmvis;
1806
1807   /* register ourselves as an extension on this display */
1808   register_with_display(dpy);
1809
1810   if (!attribList || !attribList[0]) {
1811      /* return list of all configs (per GLX_SGIX_fbconfig spec) */
1812      return glXGetFBConfigs(dpy, screen, nitems);
1813   }
1814
1815   xmvis = choose_visual(dpy, screen, attribList, GL_TRUE);
1816   if (xmvis) {
1817      GLXFBConfig *config = (GLXFBConfig *) malloc(sizeof(XMesaVisual));
1818      if (!config) {
1819         *nitems = 0;
1820         return NULL;
1821      }
1822      *nitems = 1;
1823      config[0] = (GLXFBConfig) xmvis;
1824      return (GLXFBConfig *) config;
1825   }
1826   else {
1827      *nitems = 0;
1828      return NULL;
1829   }
1830}
1831
1832
1833PUBLIC XVisualInfo *
1834glXGetVisualFromFBConfig( Display *dpy, GLXFBConfig config )
1835{
1836   if (dpy && config) {
1837      XMesaVisual xmvis = (XMesaVisual) config;
1838#if 0
1839      return xmvis->vishandle;
1840#else
1841      /* create a new vishandle - the cached one may be stale */
1842      xmvis->vishandle = (XVisualInfo *) malloc(sizeof(XVisualInfo));
1843      if (xmvis->vishandle) {
1844         memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo));
1845      }
1846      return xmvis->vishandle;
1847#endif
1848   }
1849   else {
1850      return NULL;
1851   }
1852}
1853
1854
1855PUBLIC GLXWindow
1856glXCreateWindow(Display *dpy, GLXFBConfig config, Window win,
1857                const int *attribList)
1858{
1859   XMesaVisual xmvis = (XMesaVisual) config;
1860   XMesaBuffer xmbuf;
1861   if (!xmvis)
1862      return 0;
1863
1864   xmbuf = XMesaCreateWindowBuffer(xmvis, win);
1865   if (!xmbuf)
1866      return 0;
1867
1868   (void) dpy;
1869   (void) attribList;  /* Ignored in GLX 1.3 */
1870
1871   return win;  /* A hack for now */
1872}
1873
1874
1875PUBLIC void
1876glXDestroyWindow( Display *dpy, GLXWindow window )
1877{
1878   XMesaBuffer b = XMesaFindBuffer(dpy, (Drawable) window);
1879   if (b)
1880      XMesaDestroyBuffer(b);
1881   /* don't destroy X window */
1882}
1883
1884
1885/* XXX untested */
1886PUBLIC GLXPixmap
1887glXCreatePixmap(Display *dpy, GLXFBConfig config, Pixmap pixmap,
1888                const int *attribList)
1889{
1890   XMesaVisual v = (XMesaVisual) config;
1891   XMesaBuffer b;
1892   const int *attr;
1893   int target = 0, format = 0, mipmap = 0;
1894   int value;
1895
1896   if (!dpy || !config || !pixmap)
1897      return 0;
1898
1899   for (attr = attribList; attr && *attr; attr++) {
1900      switch (*attr) {
1901      case GLX_TEXTURE_FORMAT_EXT:
1902         attr++;
1903         switch (*attr) {
1904         case GLX_TEXTURE_FORMAT_NONE_EXT:
1905         case GLX_TEXTURE_FORMAT_RGB_EXT:
1906         case GLX_TEXTURE_FORMAT_RGBA_EXT:
1907            format = *attr;
1908            break;
1909         default:
1910            /* error */
1911            return 0;
1912         }
1913         break;
1914      case GLX_TEXTURE_TARGET_EXT:
1915         attr++;
1916         switch (*attr) {
1917         case GLX_TEXTURE_1D_EXT:
1918         case GLX_TEXTURE_2D_EXT:
1919         case GLX_TEXTURE_RECTANGLE_EXT:
1920            target = *attr;
1921            break;
1922         default:
1923            /* error */
1924            return 0;
1925         }
1926         break;
1927      case GLX_MIPMAP_TEXTURE_EXT:
1928         attr++;
1929         if (*attr)
1930            mipmap = 1;
1931         break;
1932      default:
1933         /* error */
1934         return 0;
1935      }
1936   }
1937
1938   if (format == GLX_TEXTURE_FORMAT_RGB_EXT) {
1939      if (get_config(v, GLX_BIND_TO_TEXTURE_RGB_EXT,
1940                     &value, GL_TRUE) != Success
1941          || !value) {
1942         return 0; /* error! */
1943      }
1944   }
1945   else if (format == GLX_TEXTURE_FORMAT_RGBA_EXT) {
1946      if (get_config(v, GLX_BIND_TO_TEXTURE_RGBA_EXT,
1947                     &value, GL_TRUE) != Success
1948          || !value) {
1949         return 0; /* error! */
1950      }
1951   }
1952   if (mipmap) {
1953      if (get_config(v, GLX_BIND_TO_MIPMAP_TEXTURE_EXT,
1954                     &value, GL_TRUE) != Success
1955          || !value) {
1956         return 0; /* error! */
1957      }
1958   }
1959   if (target == GLX_TEXTURE_1D_EXT) {
1960      if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT,
1961                     &value, GL_TRUE) != Success
1962          || (value & GLX_TEXTURE_1D_BIT_EXT) == 0) {
1963         return 0; /* error! */
1964      }
1965   }
1966   else if (target == GLX_TEXTURE_2D_EXT) {
1967      if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT,
1968                     &value, GL_TRUE) != Success
1969          || (value & GLX_TEXTURE_2D_BIT_EXT) == 0) {
1970         return 0; /* error! */
1971      }
1972   }
1973   if (target == GLX_TEXTURE_RECTANGLE_EXT) {
1974      if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT,
1975                     &value, GL_TRUE) != Success
1976          || (value & GLX_TEXTURE_RECTANGLE_BIT_EXT) == 0) {
1977         return 0; /* error! */
1978      }
1979   }
1980
1981   if (format || target || mipmap) {
1982      /* texture from pixmap */
1983      b = XMesaCreatePixmapTextureBuffer(v, pixmap, 0, format, target, mipmap);
1984   }
1985   else {
1986      b = XMesaCreatePixmapBuffer( v, pixmap, 0 );
1987   }
1988   if (!b) {
1989      return 0;
1990   }
1991
1992   return pixmap;
1993}
1994
1995
1996PUBLIC void
1997glXDestroyPixmap( Display *dpy, GLXPixmap pixmap )
1998{
1999   XMesaBuffer b = XMesaFindBuffer(dpy, (Drawable)pixmap);
2000   if (b)
2001      XMesaDestroyBuffer(b);
2002   /* don't destroy X pixmap */
2003}
2004
2005
2006PUBLIC GLXPbuffer
2007glXCreatePbuffer(Display *dpy, GLXFBConfig config, const int *attribList)
2008{
2009   XMesaVisual xmvis = (XMesaVisual) config;
2010   XMesaBuffer xmbuf;
2011   const int *attrib;
2012   int width = 0, height = 0;
2013   GLboolean useLargest = GL_FALSE, preserveContents = GL_FALSE;
2014
2015   (void) dpy;
2016
2017   for (attrib = attribList; *attrib; attrib++) {
2018      switch (*attrib) {
2019         case GLX_PBUFFER_WIDTH:
2020            attrib++;
2021            width = *attrib;
2022            break;
2023         case GLX_PBUFFER_HEIGHT:
2024            attrib++;
2025            height = *attrib;
2026            break;
2027         case GLX_PRESERVED_CONTENTS:
2028            attrib++;
2029            preserveContents = *attrib;
2030            break;
2031         case GLX_LARGEST_PBUFFER:
2032            attrib++;
2033            useLargest = *attrib;
2034            break;
2035         default:
2036            return 0;
2037      }
2038   }
2039
2040   if (width == 0 || height == 0)
2041      return 0;
2042
2043   if (width > PBUFFER_MAX_SIZE || height > PBUFFER_MAX_SIZE) {
2044      /* If allocation would have failed and GLX_LARGEST_PBUFFER is set,
2045       * allocate the largest possible buffer.
2046       */
2047      if (useLargest) {
2048         width = PBUFFER_MAX_SIZE;
2049         height = PBUFFER_MAX_SIZE;
2050      }
2051   }
2052
2053   xmbuf = XMesaCreatePBuffer( xmvis, 0, width, height);
2054   /* A GLXPbuffer handle must be an X Drawable because that's what
2055    * glXMakeCurrent takes.
2056    */
2057   if (xmbuf) {
2058      xmbuf->largestPbuffer = useLargest;
2059      xmbuf->preservedContents = preserveContents;
2060      return (GLXPbuffer) xmbuf->ws.drawable;
2061   }
2062   else {
2063      return 0;
2064   }
2065}
2066
2067
2068PUBLIC void
2069glXDestroyPbuffer( Display *dpy, GLXPbuffer pbuf )
2070{
2071   XMesaBuffer b = XMesaFindBuffer(dpy, pbuf);
2072   if (b) {
2073      XMesaDestroyBuffer(b);
2074   }
2075}
2076
2077
2078PUBLIC void
2079glXQueryDrawable(Display *dpy, GLXDrawable draw, int attribute,
2080                 unsigned int *value)
2081{
2082   GLuint width, height;
2083   XMesaBuffer xmbuf = XMesaFindBuffer(dpy, draw);
2084   if (!xmbuf)
2085      return;
2086
2087   /* make sure buffer's dimensions are up to date */
2088   xmesa_get_window_size(dpy, xmbuf, &width, &height);
2089
2090   switch (attribute) {
2091      case GLX_WIDTH:
2092         *value = width;
2093         break;
2094      case GLX_HEIGHT:
2095         *value = height;
2096         break;
2097      case GLX_PRESERVED_CONTENTS:
2098         *value = xmbuf->preservedContents;
2099         break;
2100      case GLX_LARGEST_PBUFFER:
2101         *value = xmbuf->largestPbuffer;
2102         break;
2103      case GLX_FBCONFIG_ID:
2104         *value = xmbuf->xm_visual->visinfo->visualid;
2105         return;
2106#ifdef GLX_EXT_texture_from_pixmap
2107      case GLX_TEXTURE_FORMAT_EXT:
2108         *value = xmbuf->TextureFormat;
2109         break;
2110      case GLX_TEXTURE_TARGET_EXT:
2111         *value = xmbuf->TextureTarget;
2112         break;
2113      case GLX_MIPMAP_TEXTURE_EXT:
2114         *value = xmbuf->TextureMipmap;
2115         break;
2116#endif
2117
2118      default:
2119         return; /* raise BadValue error */
2120   }
2121}
2122
2123
2124PUBLIC GLXContext
2125glXCreateNewContext( Display *dpy, GLXFBConfig config,
2126                     int renderType, GLXContext shareCtx, Bool direct )
2127{
2128   XMesaVisual xmvis = (XMesaVisual) config;
2129
2130   if (!dpy || !config ||
2131       (renderType != GLX_RGBA_TYPE && renderType != GLX_COLOR_INDEX_TYPE))
2132      return 0;
2133
2134   return create_context(dpy, xmvis,
2135                         shareCtx ? shareCtx->xmesaContext : NULL,
2136                         direct,
2137                         1, 0, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, 0x0);
2138}
2139
2140
2141PUBLIC int
2142glXQueryContext( Display *dpy, GLXContext ctx, int attribute, int *value )
2143{
2144   GLXContext glxCtx = ctx;
2145   XMesaContext xmctx = glxCtx->xmesaContext;
2146
2147   (void) dpy;
2148   (void) ctx;
2149
2150   switch (attribute) {
2151   case GLX_FBCONFIG_ID:
2152      *value = xmctx->xm_visual->visinfo->visualid;
2153      break;
2154   case GLX_RENDER_TYPE:
2155      if (xmctx->xm_visual->mesa_visual.rgbMode)
2156         *value = GLX_RGBA_TYPE;
2157      else
2158         *value = GLX_COLOR_INDEX_TYPE;
2159      break;
2160   case GLX_SCREEN:
2161      *value = 0;
2162      return Success;
2163   default:
2164      return GLX_BAD_ATTRIBUTE;
2165   }
2166   return 0;
2167}
2168
2169
2170PUBLIC void
2171glXSelectEvent( Display *dpy, GLXDrawable drawable, unsigned long mask )
2172{
2173   XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);
2174   if (xmbuf)
2175      xmbuf->selectedEvents = mask;
2176}
2177
2178
2179PUBLIC void
2180glXGetSelectedEvent(Display *dpy, GLXDrawable drawable, unsigned long *mask)
2181{
2182   XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);
2183   if (xmbuf)
2184      *mask = xmbuf->selectedEvents;
2185   else
2186      *mask = 0;
2187}
2188
2189
2190
2191/*** GLX_SGI_swap_control ***/
2192
2193PUBLIC int
2194glXSwapIntervalSGI(int interval)
2195{
2196   (void) interval;
2197   return 0;
2198}
2199
2200
2201
2202/*** GLX_SGI_video_sync ***/
2203
2204static unsigned int FrameCounter = 0;
2205
2206PUBLIC int
2207glXGetVideoSyncSGI(unsigned int *count)
2208{
2209   /* this is a bogus implementation */
2210   *count = FrameCounter++;
2211   return 0;
2212}
2213
2214PUBLIC int
2215glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count)
2216{
2217   if (divisor <= 0 || remainder < 0)
2218      return GLX_BAD_VALUE;
2219   /* this is a bogus implementation */
2220   FrameCounter++;
2221   while (FrameCounter % divisor != remainder)
2222      FrameCounter++;
2223   *count = FrameCounter;
2224   return 0;
2225}
2226
2227
2228
2229/*** GLX_SGI_make_current_read ***/
2230
2231PUBLIC Bool
2232glXMakeCurrentReadSGI(Display *dpy, GLXDrawable draw, GLXDrawable read,
2233                      GLXContext ctx)
2234{
2235   return glXMakeContextCurrent( dpy, draw, read, ctx );
2236}
2237
2238/* not used
2239static GLXDrawable
2240glXGetCurrentReadDrawableSGI(void)
2241{
2242   return 0;
2243}
2244*/
2245
2246
2247/*** GLX_SGIX_video_source ***/
2248#if defined(_VL_H)
2249
2250PUBLIC GLXVideoSourceSGIX
2251glXCreateGLXVideoSourceSGIX(Display *dpy, int screen, VLServer server,
2252                            VLPath path, int nodeClass, VLNode drainNode)
2253{
2254   (void) dpy;
2255   (void) screen;
2256   (void) server;
2257   (void) path;
2258   (void) nodeClass;
2259   (void) drainNode;
2260   return 0;
2261}
2262
2263PUBLIC void
2264glXDestroyGLXVideoSourceSGIX(Display *dpy, GLXVideoSourceSGIX src)
2265{
2266   (void) dpy;
2267   (void) src;
2268}
2269
2270#endif
2271
2272
2273/*** GLX_EXT_import_context ***/
2274
2275PUBLIC void
2276glXFreeContextEXT(Display *dpy, GLXContext context)
2277{
2278   (void) dpy;
2279   (void) context;
2280}
2281
2282PUBLIC GLXContextID
2283glXGetContextIDEXT(const GLXContext context)
2284{
2285   (void) context;
2286   return 0;
2287}
2288
2289PUBLIC GLXContext
2290glXImportContextEXT(Display *dpy, GLXContextID contextID)
2291{
2292   (void) dpy;
2293   (void) contextID;
2294   return 0;
2295}
2296
2297PUBLIC int
2298glXQueryContextInfoEXT(Display *dpy, GLXContext context, int attribute,
2299                       int *value)
2300{
2301   (void) dpy;
2302   (void) context;
2303   (void) attribute;
2304   (void) value;
2305   return 0;
2306}
2307
2308
2309
2310/*** GLX_SGIX_fbconfig ***/
2311
2312PUBLIC int
2313glXGetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config,
2314                         int attribute, int *value)
2315{
2316   return glXGetFBConfigAttrib(dpy, config, attribute, value);
2317}
2318
2319PUBLIC GLXFBConfigSGIX *
2320glXChooseFBConfigSGIX(Display *dpy, int screen, int *attrib_list,
2321                      int *nelements)
2322{
2323   return (GLXFBConfig *) glXChooseFBConfig(dpy, screen,
2324                                            attrib_list, nelements);
2325}
2326
2327
2328PUBLIC GLXPixmap
2329glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config,
2330                                 Pixmap pixmap)
2331{
2332   XMesaVisual xmvis = (XMesaVisual) config;
2333   XMesaBuffer xmbuf = XMesaCreatePixmapBuffer(xmvis, pixmap, 0);
2334   return xmbuf->ws.drawable; /* need to return an X ID */
2335}
2336
2337
2338PUBLIC GLXContext
2339glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config,
2340                               int renderType, GLXContext shareCtx,
2341                               Bool direct)
2342{
2343   XMesaVisual xmvis = (XMesaVisual) config;
2344
2345   if (!dpy || !config ||
2346       (renderType != GLX_RGBA_TYPE && renderType != GLX_COLOR_INDEX_TYPE))
2347      return 0;
2348
2349   return create_context(dpy, xmvis,
2350                         shareCtx ? shareCtx->xmesaContext : NULL,
2351                         direct,
2352                         1, 0, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, 0x0);
2353}
2354
2355
2356PUBLIC XVisualInfo *
2357glXGetVisualFromFBConfigSGIX(Display *dpy, GLXFBConfigSGIX config)
2358{
2359   return glXGetVisualFromFBConfig(dpy, config);
2360}
2361
2362
2363PUBLIC GLXFBConfigSGIX
2364glXGetFBConfigFromVisualSGIX(Display *dpy, XVisualInfo *vis)
2365{
2366   XMesaVisual xmvis = find_glx_visual(dpy, vis);
2367   if (!xmvis) {
2368      /* This visual wasn't found with glXChooseVisual() */
2369      xmvis = create_glx_visual(dpy, vis);
2370   }
2371
2372   return (GLXFBConfigSGIX) xmvis;
2373}
2374
2375
2376
2377/*** GLX_SGIX_pbuffer ***/
2378
2379PUBLIC GLXPbufferSGIX
2380glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config,
2381                        unsigned int width, unsigned int height,
2382                        int *attribList)
2383{
2384   XMesaVisual xmvis = (XMesaVisual) config;
2385   XMesaBuffer xmbuf;
2386   const int *attrib;
2387   GLboolean useLargest = GL_FALSE, preserveContents = GL_FALSE;
2388
2389   (void) dpy;
2390
2391   for (attrib = attribList; attrib && *attrib; attrib++) {
2392      switch (*attrib) {
2393         case GLX_PRESERVED_CONTENTS_SGIX:
2394            attrib++;
2395            preserveContents = *attrib; /* ignored */
2396            break;
2397         case GLX_LARGEST_PBUFFER_SGIX:
2398            attrib++;
2399            useLargest = *attrib; /* ignored */
2400            break;
2401         default:
2402            return 0;
2403      }
2404   }
2405
2406   /* not used at this time */
2407   (void) useLargest;
2408   (void) preserveContents;
2409
2410   xmbuf = XMesaCreatePBuffer( xmvis, 0, width, height);
2411   /* A GLXPbuffer handle must be an X Drawable because that's what
2412    * glXMakeCurrent takes.
2413    */
2414   return (GLXPbuffer) xmbuf->ws.drawable;
2415}
2416
2417
2418PUBLIC void
2419glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf)
2420{
2421   XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf);
2422   if (xmbuf) {
2423      XMesaDestroyBuffer(xmbuf);
2424   }
2425}
2426
2427
2428PUBLIC int
2429glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute,
2430                       unsigned int *value)
2431{
2432   const XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf);
2433
2434   if (!xmbuf) {
2435      /* Generate GLXBadPbufferSGIX for bad pbuffer */
2436      return 0;
2437   }
2438
2439   switch (attribute) {
2440      case GLX_PRESERVED_CONTENTS_SGIX:
2441         *value = True;
2442         break;
2443      case GLX_LARGEST_PBUFFER_SGIX:
2444         *value = xmesa_buffer_width(xmbuf) * xmesa_buffer_height(xmbuf);
2445         break;
2446      case GLX_WIDTH_SGIX:
2447         *value = xmesa_buffer_width(xmbuf);
2448         break;
2449      case GLX_HEIGHT_SGIX:
2450         *value = xmesa_buffer_height(xmbuf);
2451         break;
2452      case GLX_EVENT_MASK_SGIX:
2453         *value = 0;  /* XXX might be wrong */
2454         break;
2455      default:
2456         *value = 0;
2457   }
2458   return 0;
2459}
2460
2461
2462PUBLIC void
2463glXSelectEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long mask)
2464{
2465   XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);
2466   if (xmbuf) {
2467      /* Note: we'll never generate clobber events */
2468      xmbuf->selectedEvents = mask;
2469   }
2470}
2471
2472
2473PUBLIC void
2474glXGetSelectedEventSGIX(Display *dpy, GLXDrawable drawable,
2475                        unsigned long *mask)
2476{
2477   XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);
2478   if (xmbuf) {
2479      *mask = xmbuf->selectedEvents;
2480   }
2481   else {
2482      *mask = 0;
2483   }
2484}
2485
2486
2487
2488/*** GLX_SGI_cushion ***/
2489
2490PUBLIC void
2491glXCushionSGI(Display *dpy, Window win, float cushion)
2492{
2493   (void) dpy;
2494   (void) win;
2495   (void) cushion;
2496}
2497
2498
2499
2500/*** GLX_SGIX_video_resize ***/
2501
2502PUBLIC int
2503glXBindChannelToWindowSGIX(Display *dpy, int screen, int channel,
2504                           Window window)
2505{
2506   (void) dpy;
2507   (void) screen;
2508   (void) channel;
2509   (void) window;
2510   return 0;
2511}
2512
2513PUBLIC int
2514glXChannelRectSGIX(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
2528glXQueryChannelRectSGIX(Display *dpy, int screen, int channel,
2529                        int *x, int *y, int *w, int *h)
2530{
2531   (void) dpy;
2532   (void) screen;
2533   (void) channel;
2534   (void) x;
2535   (void) y;
2536   (void) w;
2537   (void) h;
2538   return 0;
2539}
2540
2541PUBLIC int
2542glXQueryChannelDeltasSGIX(Display *dpy, int screen, int channel,
2543                          int *dx, int *dy, int *dw, int *dh)
2544{
2545   (void) dpy;
2546   (void) screen;
2547   (void) channel;
2548   (void) dx;
2549   (void) dy;
2550   (void) dw;
2551   (void) dh;
2552   return 0;
2553}
2554
2555PUBLIC int
2556glXChannelRectSyncSGIX(Display *dpy, int screen, int channel, GLenum synctype)
2557{
2558   (void) dpy;
2559   (void) screen;
2560   (void) channel;
2561   (void) synctype;
2562   return 0;
2563}
2564
2565
2566
2567/*** GLX_SGIX_dmbuffer **/
2568
2569#if defined(_DM_BUFFER_H_)
2570PUBLIC Bool
2571glXAssociateDMPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuffer,
2572                          DMparams *params, DMbuffer dmbuffer)
2573{
2574   (void) dpy;
2575   (void) pbuffer;
2576   (void) params;
2577   (void) dmbuffer;
2578   return False;
2579}
2580#endif
2581
2582
2583/*** GLX_SGIX_swap_group ***/
2584
2585PUBLIC void
2586glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable, GLXDrawable member)
2587{
2588   (void) dpy;
2589   (void) drawable;
2590   (void) member;
2591}
2592
2593
2594
2595/*** GLX_SGIX_swap_barrier ***/
2596
2597PUBLIC void
2598glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable, int barrier)
2599{
2600   (void) dpy;
2601   (void) drawable;
2602   (void) barrier;
2603}
2604
2605PUBLIC Bool
2606glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max)
2607{
2608   (void) dpy;
2609   (void) screen;
2610   (void) max;
2611   return False;
2612}
2613
2614
2615
2616/*** GLX_SUN_get_transparent_index ***/
2617
2618PUBLIC Status
2619glXGetTransparentIndexSUN(Display *dpy, Window overlay, Window underlay,
2620                          long *pTransparent)
2621{
2622   (void) dpy;
2623   (void) overlay;
2624   (void) underlay;
2625   (void) pTransparent;
2626   return 0;
2627}
2628
2629
2630
2631/*** GLX_MESA_release_buffers ***/
2632
2633/*
2634 * Release the depth, stencil, accum buffers attached to a GLXDrawable
2635 * (a window or pixmap) prior to destroying the GLXDrawable.
2636 */
2637PUBLIC Bool
2638glXReleaseBuffersMESA( Display *dpy, GLXDrawable d )
2639{
2640   XMesaBuffer b = XMesaFindBuffer(dpy, d);
2641   if (b) {
2642      XMesaDestroyBuffer(b);
2643      return True;
2644   }
2645   return False;
2646}
2647
2648/*** GLX_EXT_texture_from_pixmap ***/
2649
2650PUBLIC void
2651glXBindTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer,
2652                        const int *attrib_list)
2653{
2654   XMesaBuffer b = XMesaFindBuffer(dpy, drawable);
2655   if (b)
2656      XMesaBindTexImage(dpy, b, buffer, attrib_list);
2657}
2658
2659PUBLIC void
2660glXReleaseTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer)
2661{
2662   XMesaBuffer b = XMesaFindBuffer(dpy, drawable);
2663   if (b)
2664      XMesaReleaseTexImage(dpy, b, buffer);
2665}
2666
2667
2668
2669/*** GLX_ARB_create_context ***/
2670
2671GLXContext
2672glXCreateContextAttribsARB(Display *dpy, GLXFBConfig config,
2673                           GLXContext shareCtx, Bool direct,
2674                           const int *attrib_list)
2675{
2676   XMesaVisual xmvis = (XMesaVisual) config;
2677   int majorVersion = 1, minorVersion = 0;
2678   int contextFlags = 0x0;
2679   int profileMask = GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
2680   int renderType = GLX_RGBA_TYPE;
2681   unsigned i;
2682   Bool done = False;
2683   const int contextFlagsAll = (GLX_CONTEXT_DEBUG_BIT_ARB |
2684                                GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB);
2685
2686   /* parse attrib_list */
2687   for (i = 0; !done && attrib_list && attrib_list[i]; i++) {
2688      switch (attrib_list[i]) {
2689      case GLX_CONTEXT_MAJOR_VERSION_ARB:
2690         majorVersion = attrib_list[++i];
2691         break;
2692      case GLX_CONTEXT_MINOR_VERSION_ARB:
2693         minorVersion = attrib_list[++i];
2694         break;
2695      case GLX_CONTEXT_FLAGS_ARB:
2696         contextFlags = attrib_list[++i];
2697         break;
2698      case GLX_CONTEXT_PROFILE_MASK_ARB:
2699         profileMask = attrib_list[++i];
2700         break;
2701      case GLX_RENDER_TYPE:
2702         renderType = attrib_list[++i];
2703         break;
2704      case 0:
2705         /* end of list */
2706         done = True;
2707         break;
2708      default:
2709         /* bad attribute */
2710         /* XXX generate BadValue X Error */
2711         return NULL;
2712      }
2713   }
2714
2715   /* check contextFlags */
2716   if (contextFlags & ~contextFlagsAll) {
2717      return NULL; /* generate BadValue X Error */
2718   }
2719
2720   /* check profileMask */
2721   if (profileMask != GLX_CONTEXT_CORE_PROFILE_BIT_ARB &&
2722       profileMask != GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB) {
2723      return NULL; /* generate BadValue X Error */
2724   }
2725
2726   /* check version (generate BadMatch if bad) */
2727   switch (majorVersion) {
2728   case 1:
2729      if (minorVersion < 0 || minorVersion > 5)
2730         return NULL;
2731      break;
2732   case 2:
2733      if (minorVersion < 0 || minorVersion > 1)
2734         return NULL;
2735      break;
2736   case 3:
2737      if (minorVersion < 0 || minorVersion > 2)
2738         return NULL;
2739      break;
2740   case 4:
2741      if (minorVersion < 0 || minorVersion > 0)
2742         return NULL;
2743      break;
2744   default:
2745      return NULL;
2746   }
2747
2748   if ((contextFlags & GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB) &&
2749       majorVersion < 3)
2750      return NULL; /* generate GLXBadProfileARB */
2751
2752   if (renderType == GLX_COLOR_INDEX_TYPE && majorVersion >= 3)
2753      return NULL; /* generate BadMatch */
2754
2755   return create_context(dpy, xmvis,
2756                         shareCtx ? shareCtx->xmesaContext : NULL,
2757                         direct,
2758                         majorVersion, minorVersion,
2759                         profileMask, contextFlags);
2760}
2761