OSDN Git Service

mesa: remove outdated version lines in comments
[android-x86/external-mesa.git] / src / gallium / state_trackers / glx / xlib / glx_api.c
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 "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  */
76 struct __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
89 static pipe_tsd ContextTSD;
90
91 /** Set current context for calling thread */
92 static void
93 SetCurrentContext(GLXContext c)
94 {
95    pipe_tsd_set(&ContextTSD, c);
96 }
97
98 /** Get current context for calling thread */
99 static GLXContext
100 GetCurrentContext(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
114 static XMesaVisual *VisualTable = NULL;
115 static 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  */
131 static GLboolean
132 is_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  */
163 static XMesaVisual
164 save_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  */
272 static GLint
273 default_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
284 static GLint
285 default_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
296 static GLint
297 default_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  */
312 static XMesaVisual
313 create_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  */
349 static XMesaVisual
350 find_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  */
376 static XVisualInfo *
377 get_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          free((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  */
429 static XVisualInfo *
430 get_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  */
475 static XVisualInfo *
476 choose_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  */
581 static void
582 destroy_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  */
601 static int
602 close_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  */
614 static _XExtension *
615 lookup_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  */
631 static void
632 register_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  */
660 static XMesaVisual
661 choose_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
1020 PUBLIC XVisualInfo *
1021 glXChooseVisual( 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  */
1045 static GLXContext
1046 create_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
1080 PUBLIC GLXContext
1081 glXCreateContext( 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. */
1104 static GLXContext MakeCurrent_PrevContext = 0;
1105 static GLXDrawable MakeCurrent_PrevDrawable = 0;
1106 static GLXDrawable MakeCurrent_PrevReadable = 0;
1107 static XMesaBuffer MakeCurrent_PrevDrawBuffer = 0;
1108 static XMesaBuffer MakeCurrent_PrevReadBuffer = 0;
1109
1110
1111 /* GLX 1.3 and later */
1112 PUBLIC Bool
1113 glXMakeContextCurrent( 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
1208 PUBLIC Bool
1209 glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx )
1210 {
1211    return glXMakeContextCurrent( dpy, drawable, drawable, ctx );
1212 }
1213
1214
1215 PUBLIC GLXContext
1216 glXGetCurrentContext(void)
1217 {
1218    return GetCurrentContext();
1219 }
1220
1221
1222 PUBLIC Display *
1223 glXGetCurrentDisplay(void)
1224 {
1225    GLXContext glxCtx = glXGetCurrentContext();
1226
1227    return glxCtx ? glxCtx->currentDpy : NULL;
1228 }
1229
1230
1231 PUBLIC Display *
1232 glXGetCurrentDisplayEXT(void)
1233 {
1234    return glXGetCurrentDisplay();
1235 }
1236
1237
1238 PUBLIC GLXDrawable
1239 glXGetCurrentDrawable(void)
1240 {
1241    GLXContext gc = glXGetCurrentContext();
1242    return gc ? gc->currentDrawable : 0;
1243 }
1244
1245
1246 PUBLIC GLXDrawable
1247 glXGetCurrentReadDrawable(void)
1248 {
1249    GLXContext gc = glXGetCurrentContext();
1250    return gc ? gc->currentReadable : 0;
1251 }
1252
1253
1254 PUBLIC GLXDrawable
1255 glXGetCurrentReadDrawableSGI(void)
1256 {
1257    return glXGetCurrentReadDrawable();
1258 }
1259
1260
1261 PUBLIC GLXPixmap
1262 glXCreateGLXPixmap( 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
1286 PUBLIC GLXPixmap
1287 glXCreateGLXPixmapMESA( 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
1310 PUBLIC void
1311 glXDestroyGLXPixmap( 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
1323 PUBLIC void
1324 glXCopyContext( 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
1337 PUBLIC Bool
1338 glXQueryExtension( 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
1352 PUBLIC void
1353 glXDestroyContext( Display *dpy, GLXContext ctx )
1354 {
1355    if (ctx) {
1356       GLXContext glxCtx = ctx;
1357       (void) dpy;
1358       MakeCurrent_PrevContext = 0;
1359       MakeCurrent_PrevDrawable = 0;
1360       MakeCurrent_PrevReadable = 0;
1361       MakeCurrent_PrevDrawBuffer = 0;
1362       MakeCurrent_PrevReadBuffer = 0;
1363       XMesaDestroyContext( glxCtx->xmesaContext );
1364       XMesaGarbageCollect();
1365       free(glxCtx);
1366    }
1367 }
1368
1369
1370 PUBLIC Bool
1371 glXIsDirect( Display *dpy, GLXContext ctx )
1372 {
1373    return ctx ? ctx->isDirect : False;
1374 }
1375
1376
1377
1378 PUBLIC void
1379 glXSwapBuffers( 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
1405 PUBLIC void
1406 glXCopySubBufferMESA(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
1419 PUBLIC Bool
1420 glXQueryVersion( 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  */
1434 static int
1435 get_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
1636 PUBLIC int
1637 glXGetConfig( 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
1666 PUBLIC void
1667 glXWaitGL( void )
1668 {
1669    XMesaContext xmesa = XMesaGetCurrentContext();
1670    XMesaFlush( xmesa );
1671 }
1672
1673
1674
1675 PUBLIC void
1676 glXWaitX( void )
1677 {
1678    XMesaContext xmesa = XMesaGetCurrentContext();
1679    XMesaFlush( xmesa );
1680 }
1681
1682
1683 static const char *
1684 get_extensions( void )
1685 {
1686    return EXTENSIONS;
1687 }
1688
1689
1690
1691 /* GLX 1.1 and later */
1692 PUBLIC const char *
1693 glXQueryExtensionsString( 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 */
1703 PUBLIC const char *
1704 glXQueryServerString( 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 */
1728 PUBLIC const char *
1729 glXGetClientString( 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
1756 PUBLIC int
1757 glXGetFBConfigAttrib(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
1771 PUBLIC GLXFBConfig *
1772 glXGetFBConfigs( 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
1801 PUBLIC GLXFBConfig *
1802 glXChooseFBConfig(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
1833 PUBLIC XVisualInfo *
1834 glXGetVisualFromFBConfig( 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
1855 PUBLIC GLXWindow
1856 glXCreateWindow(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
1875 PUBLIC void
1876 glXDestroyWindow( 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 */
1886 PUBLIC GLXPixmap
1887 glXCreatePixmap(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
1996 PUBLIC void
1997 glXDestroyPixmap( 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
2006 PUBLIC GLXPbuffer
2007 glXCreatePbuffer(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
2068 PUBLIC void
2069 glXDestroyPbuffer( Display *dpy, GLXPbuffer pbuf )
2070 {
2071    XMesaBuffer b = XMesaFindBuffer(dpy, pbuf);
2072    if (b) {
2073       XMesaDestroyBuffer(b);
2074    }
2075 }
2076
2077
2078 PUBLIC void
2079 glXQueryDrawable(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
2124 PUBLIC GLXContext
2125 glXCreateNewContext( 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
2141 PUBLIC int
2142 glXQueryContext( 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
2170 PUBLIC void
2171 glXSelectEvent( Display *dpy, GLXDrawable drawable, unsigned long mask )
2172 {
2173    XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);
2174    if (xmbuf)
2175       xmbuf->selectedEvents = mask;
2176 }
2177
2178
2179 PUBLIC void
2180 glXGetSelectedEvent(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
2193 PUBLIC int
2194 glXSwapIntervalSGI(int interval)
2195 {
2196    (void) interval;
2197    return 0;
2198 }
2199
2200
2201
2202 /*** GLX_SGI_video_sync ***/
2203
2204 static unsigned int FrameCounter = 0;
2205
2206 PUBLIC int
2207 glXGetVideoSyncSGI(unsigned int *count)
2208 {
2209    /* this is a bogus implementation */
2210    *count = FrameCounter++;
2211    return 0;
2212 }
2213
2214 PUBLIC int
2215 glXWaitVideoSyncSGI(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
2231 PUBLIC Bool
2232 glXMakeCurrentReadSGI(Display *dpy, GLXDrawable draw, GLXDrawable read,
2233                       GLXContext ctx)
2234 {
2235    return glXMakeContextCurrent( dpy, draw, read, ctx );
2236 }
2237
2238 /* not used
2239 static GLXDrawable
2240 glXGetCurrentReadDrawableSGI(void)
2241 {
2242    return 0;
2243 }
2244 */
2245
2246
2247 /*** GLX_SGIX_video_source ***/
2248 #if defined(_VL_H)
2249
2250 PUBLIC GLXVideoSourceSGIX
2251 glXCreateGLXVideoSourceSGIX(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
2263 PUBLIC void
2264 glXDestroyGLXVideoSourceSGIX(Display *dpy, GLXVideoSourceSGIX src)
2265 {
2266    (void) dpy;
2267    (void) src;
2268 }
2269
2270 #endif
2271
2272
2273 /*** GLX_EXT_import_context ***/
2274
2275 PUBLIC void
2276 glXFreeContextEXT(Display *dpy, GLXContext context)
2277 {
2278    (void) dpy;
2279    (void) context;
2280 }
2281
2282 PUBLIC GLXContextID
2283 glXGetContextIDEXT(const GLXContext context)
2284 {
2285    (void) context;
2286    return 0;
2287 }
2288
2289 PUBLIC GLXContext
2290 glXImportContextEXT(Display *dpy, GLXContextID contextID)
2291 {
2292    (void) dpy;
2293    (void) contextID;
2294    return 0;
2295 }
2296
2297 PUBLIC int
2298 glXQueryContextInfoEXT(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
2312 PUBLIC int
2313 glXGetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config,
2314                          int attribute, int *value)
2315 {
2316    return glXGetFBConfigAttrib(dpy, config, attribute, value);
2317 }
2318
2319 PUBLIC GLXFBConfigSGIX *
2320 glXChooseFBConfigSGIX(Display *dpy, int screen, int *attrib_list,
2321                       int *nelements)
2322 {
2323    return (GLXFBConfig *) glXChooseFBConfig(dpy, screen,
2324                                             attrib_list, nelements);
2325 }
2326
2327
2328 PUBLIC GLXPixmap
2329 glXCreateGLXPixmapWithConfigSGIX(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
2338 PUBLIC GLXContext
2339 glXCreateContextWithConfigSGIX(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
2356 PUBLIC XVisualInfo *
2357 glXGetVisualFromFBConfigSGIX(Display *dpy, GLXFBConfigSGIX config)
2358 {
2359    return glXGetVisualFromFBConfig(dpy, config);
2360 }
2361
2362
2363 PUBLIC GLXFBConfigSGIX
2364 glXGetFBConfigFromVisualSGIX(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
2379 PUBLIC GLXPbufferSGIX
2380 glXCreateGLXPbufferSGIX(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
2418 PUBLIC void
2419 glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf)
2420 {
2421    XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf);
2422    if (xmbuf) {
2423       XMesaDestroyBuffer(xmbuf);
2424    }
2425 }
2426
2427
2428 PUBLIC int
2429 glXQueryGLXPbufferSGIX(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
2462 PUBLIC void
2463 glXSelectEventSGIX(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
2473 PUBLIC void
2474 glXGetSelectedEventSGIX(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
2490 PUBLIC void
2491 glXCushionSGI(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
2502 PUBLIC int
2503 glXBindChannelToWindowSGIX(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
2513 PUBLIC int
2514 glXChannelRectSGIX(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
2527 PUBLIC int
2528 glXQueryChannelRectSGIX(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
2541 PUBLIC int
2542 glXQueryChannelDeltasSGIX(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
2555 PUBLIC int
2556 glXChannelRectSyncSGIX(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_)
2570 PUBLIC Bool
2571 glXAssociateDMPbufferSGIX(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
2585 PUBLIC void
2586 glXJoinSwapGroupSGIX(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
2597 PUBLIC void
2598 glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable, int barrier)
2599 {
2600    (void) dpy;
2601    (void) drawable;
2602    (void) barrier;
2603 }
2604
2605 PUBLIC Bool
2606 glXQueryMaxSwapBarriersSGIX(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
2618 PUBLIC Status
2619 glXGetTransparentIndexSUN(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  */
2637 PUBLIC Bool
2638 glXReleaseBuffersMESA( 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
2650 PUBLIC void
2651 glXBindTexImageEXT(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
2659 PUBLIC void
2660 glXReleaseTexImageEXT(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
2671 GLXContext
2672 glXCreateContextAttribsARB(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 }