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