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 "util/u_math.h"
44 #include "util/u_memory.h"
45 
46 /* An "Atrribs/Attribs" typo was fixed in glxproto.h in Nov 2014.
47  * This is in case we don't have the updated header.
48  */
49 #if !defined(X_GLXCreateContextAttribsARB) && \
50      defined(X_GLXCreateContextAtrribsARB)
51 #define X_GLXCreateContextAttribsARB X_GLXCreateContextAtrribsARB
52 #endif
53 
54 /* This indicates the client-side GLX API and GLX encoder version. */
55 #define CLIENT_MAJOR_VERSION 1
56 #define CLIENT_MINOR_VERSION 4  /* but don't have 1.3's pbuffers, etc yet */
57 
58 /* This indicates the server-side GLX decoder version.
59  * GLX 1.4 indicates OpenGL 1.3 support
60  */
61 #define SERVER_MAJOR_VERSION 1
62 #define SERVER_MINOR_VERSION 4
63 
64 /* Who implemented this GLX? */
65 #define VENDOR "Brian Paul"
66 
67 #define EXTENSIONS \
68    "GLX_MESA_copy_sub_buffer " \
69    "GLX_MESA_pixmap_colormap " \
70    "GLX_MESA_release_buffers " \
71    "GLX_ARB_create_context " \
72    "GLX_ARB_create_context_profile " \
73    "GLX_ARB_get_proc_address " \
74    "GLX_EXT_create_context_es_profile " \
75    "GLX_EXT_create_context_es2_profile " \
76    "GLX_EXT_texture_from_pixmap " \
77    "GLX_EXT_visual_info " \
78    "GLX_EXT_visual_rating " \
79    /*"GLX_SGI_video_sync "*/ \
80    "GLX_SGIX_fbconfig " \
81    "GLX_SGIX_pbuffer "
82 
83 #define DEFAULT_DIRECT GL_TRUE
84 
85 
86 /** XXX this could be based on gallium's max texture size */
87 #define PBUFFER_MAX_SIZE 16384
88 
89 
90 /**
91  * The GLXContext typedef is defined as a pointer to this structure.
92  */
93 struct __GLXcontextRec
94 {
95    Display *currentDpy;
96    GLboolean isDirect;
97    GLXDrawable currentDrawable;
98    GLXDrawable currentReadable;
99    XID xid;
100 
101    XMesaContext xmesaContext;
102 };
103 
104 
105 
106 static pipe_tsd ContextTSD;
107 
108 /** Set current context for calling thread */
109 static void
SetCurrentContext(GLXContext c)110 SetCurrentContext(GLXContext c)
111 {
112    pipe_tsd_set(&ContextTSD, c);
113 }
114 
115 /** Get current context for calling thread */
116 static GLXContext
GetCurrentContext(void)117 GetCurrentContext(void)
118 {
119    return pipe_tsd_get(&ContextTSD);
120 }
121 
122 
123 
124 /**********************************************************************/
125 /***                       GLX Visual Code                          ***/
126 /**********************************************************************/
127 
128 #define DONT_CARE -1
129 
130 
131 static XMesaVisual *VisualTable = NULL;
132 static 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  */
148 static GLboolean
is_usable_visual(XVisualInfo * vinfo)149 is_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  */
180 static XMesaVisual
save_glx_visual(Display * dpy,XVisualInfo * vinfo,GLboolean rgbFlag,GLboolean alphaFlag,GLboolean dbFlag,GLboolean stereoFlag,GLint depth_size,GLint stencil_size,GLint accumRedSize,GLint accumGreenSize,GLint accumBlueSize,GLint accumAlphaSize,GLint level,GLint numAuxBuffers,GLuint num_samples)181 save_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 the DEFAULT_SOFTWARE_DEPTH_BITS constant.
282  * XXX probably do the same thing for stencil, accum, etc.
283  */
284 static GLint
default_depth_bits(void)285 default_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 
296 static GLint
default_alpha_bits(void)297 default_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 
308 static GLint
default_accum_bits(void)309 default_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  */
324 static XMesaVisual
create_glx_visual(Display * dpy,XVisualInfo * visinfo)325 create_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  */
362 static XMesaVisual
find_glx_visual(Display * dpy,XVisualInfo * vinfo)363 find_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  */
389 static XVisualInfo *
get_visual(Display * dpy,int scr,unsigned int depth,int xclass)390 get_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  */
442 static XVisualInfo *
get_env_visual(Display * dpy,int scr,const char * varname)443 get_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  */
488 static XVisualInfo *
choose_x_visual(Display * dpy,int screen,int min_depth,int preferred_class)489 choose_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  */
594 static void
destroy_visuals_on_display(Display * dpy)595 destroy_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  */
614 static int
close_display_callback(Display * dpy,XExtCodes * codes)615 close_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  */
628 static _XExtension *
lookup_extension(Display * dpy,const char * extName)629 lookup_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  */
645 static void
register_with_display(Display * dpy)646 register_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  */
666 static int
generate_error(Display * dpy,unsigned char error_code,XID resourceid,unsigned char minor_code,Bool core)667 generate_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  */
720 static XMesaVisual
choose_visual(Display * dpy,int screen,const int * list,GLboolean fbConfig)721 choose_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 
1088 PUBLIC XVisualInfo *
glXChooseVisual(Display * dpy,int screen,int * list)1089 glXChooseVisual( 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  */
1113 static GLXContext
create_context(Display * dpy,XMesaVisual xmvis,XMesaContext shareCtx,Bool direct,unsigned major,unsigned minor,unsigned profileMask,unsigned contextFlags)1114 create_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 
1148 PUBLIC GLXContext
glXCreateContext(Display * dpy,XVisualInfo * visinfo,GLXContext shareCtx,Bool direct)1149 glXCreateContext( 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 */
1172 PUBLIC Bool
glXMakeContextCurrent(Display * dpy,GLXDrawable draw,GLXDrawable read,GLXContext ctx)1173 glXMakeContextCurrent( 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 
1247 PUBLIC Bool
glXMakeCurrent(Display * dpy,GLXDrawable drawable,GLXContext ctx)1248 glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx )
1249 {
1250    return glXMakeContextCurrent( dpy, drawable, drawable, ctx );
1251 }
1252 
1253 
1254 PUBLIC GLXContext
glXGetCurrentContext(void)1255 glXGetCurrentContext(void)
1256 {
1257    return GetCurrentContext();
1258 }
1259 
1260 
1261 PUBLIC Display *
glXGetCurrentDisplay(void)1262 glXGetCurrentDisplay(void)
1263 {
1264    GLXContext glxCtx = glXGetCurrentContext();
1265 
1266    return glxCtx ? glxCtx->currentDpy : NULL;
1267 }
1268 
1269 
1270 PUBLIC Display *
glXGetCurrentDisplayEXT(void)1271 glXGetCurrentDisplayEXT(void)
1272 {
1273    return glXGetCurrentDisplay();
1274 }
1275 
1276 
1277 PUBLIC GLXDrawable
glXGetCurrentDrawable(void)1278 glXGetCurrentDrawable(void)
1279 {
1280    GLXContext gc = glXGetCurrentContext();
1281    return gc ? gc->currentDrawable : 0;
1282 }
1283 
1284 
1285 PUBLIC GLXDrawable
glXGetCurrentReadDrawable(void)1286 glXGetCurrentReadDrawable(void)
1287 {
1288    GLXContext gc = glXGetCurrentContext();
1289    return gc ? gc->currentReadable : 0;
1290 }
1291 
1292 
1293 PUBLIC GLXDrawable
glXGetCurrentReadDrawableSGI(void)1294 glXGetCurrentReadDrawableSGI(void)
1295 {
1296    return glXGetCurrentReadDrawable();
1297 }
1298 
1299 
1300 PUBLIC GLXPixmap
glXCreateGLXPixmap(Display * dpy,XVisualInfo * visinfo,Pixmap pixmap)1301 glXCreateGLXPixmap( 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 
1325 PUBLIC GLXPixmap
glXCreateGLXPixmapMESA(Display * dpy,XVisualInfo * visinfo,Pixmap pixmap,Colormap cmap)1326 glXCreateGLXPixmapMESA( 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 
1349 PUBLIC void
glXDestroyGLXPixmap(Display * dpy,GLXPixmap pixmap)1350 glXDestroyGLXPixmap( 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 
1362 PUBLIC void
glXCopyContext(Display * dpy,GLXContext src,GLXContext dst,unsigned long mask)1363 glXCopyContext( 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 
1376 PUBLIC Bool
glXQueryExtension(Display * dpy,int * errorBase,int * eventBase)1377 glXQueryExtension( 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 
1391 PUBLIC void
glXDestroyContext(Display * dpy,GLXContext ctx)1392 glXDestroyContext( 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 
1404 PUBLIC Bool
glXIsDirect(Display * dpy,GLXContext ctx)1405 glXIsDirect( Display *dpy, GLXContext ctx )
1406 {
1407    return ctx ? ctx->isDirect : False;
1408 }
1409 
1410 
1411 
1412 PUBLIC void
glXSwapBuffers(Display * dpy,GLXDrawable drawable)1413 glXSwapBuffers( 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 
1439 PUBLIC void
glXCopySubBufferMESA(Display * dpy,GLXDrawable drawable,int x,int y,int width,int height)1440 glXCopySubBufferMESA(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 
1453 PUBLIC Bool
glXQueryVersion(Display * dpy,int * maj,int * min)1454 glXQueryVersion( 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  */
1468 static int
get_config(XMesaVisual xmvis,int attrib,int * value,GLboolean fbconfig)1469 get_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 
1656 PUBLIC int
glXGetConfig(Display * dpy,XVisualInfo * visinfo,int attrib,int * value)1657 glXGetConfig( 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 
1686 PUBLIC void
glXWaitGL(void)1687 glXWaitGL( void )
1688 {
1689    XMesaContext xmesa = XMesaGetCurrentContext();
1690    XMesaFlush( xmesa );
1691 }
1692 
1693 
1694 
1695 PUBLIC void
glXWaitX(void)1696 glXWaitX( void )
1697 {
1698    XMesaContext xmesa = XMesaGetCurrentContext();
1699    XMesaFlush( xmesa );
1700 }
1701 
1702 
1703 static const char *
get_extensions(void)1704 get_extensions( void )
1705 {
1706    return EXTENSIONS;
1707 }
1708 
1709 
1710 
1711 /* GLX 1.1 and later */
1712 PUBLIC const char *
glXQueryExtensionsString(Display * dpy,int screen)1713 glXQueryExtensionsString( 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 */
1723 PUBLIC const char *
glXQueryServerString(Display * dpy,int screen,int name)1724 glXQueryServerString( 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 */
1748 PUBLIC const char *
glXGetClientString(Display * dpy,int name)1749 glXGetClientString( 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 
1776 PUBLIC int
glXGetFBConfigAttrib(Display * dpy,GLXFBConfig config,int attribute,int * value)1777 glXGetFBConfigAttrib(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 
1791 PUBLIC GLXFBConfig *
glXGetFBConfigs(Display * dpy,int screen,int * nelements)1792 glXGetFBConfigs( 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 
1820 PUBLIC GLXFBConfig *
glXChooseFBConfig(Display * dpy,int screen,const int * attribList,int * nitems)1821 glXChooseFBConfig(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 
1852 PUBLIC XVisualInfo *
glXGetVisualFromFBConfig(Display * dpy,GLXFBConfig config)1853 glXGetVisualFromFBConfig( 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 
1874 PUBLIC GLXWindow
glXCreateWindow(Display * dpy,GLXFBConfig config,Window win,const int * attribList)1875 glXCreateWindow(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 
1894 PUBLIC void
glXDestroyWindow(Display * dpy,GLXWindow window)1895 glXDestroyWindow( 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 */
1905 PUBLIC GLXPixmap
glXCreatePixmap(Display * dpy,GLXFBConfig config,Pixmap pixmap,const int * attribList)1906 glXCreatePixmap(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 
2015 PUBLIC void
glXDestroyPixmap(Display * dpy,GLXPixmap pixmap)2016 glXDestroyPixmap( 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 
2025 PUBLIC GLXPbuffer
glXCreatePbuffer(Display * dpy,GLXFBConfig config,const int * attribList)2026 glXCreatePbuffer(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 
2087 PUBLIC void
glXDestroyPbuffer(Display * dpy,GLXPbuffer pbuf)2088 glXDestroyPbuffer( Display *dpy, GLXPbuffer pbuf )
2089 {
2090    XMesaBuffer b = XMesaFindBuffer(dpy, pbuf);
2091    if (b) {
2092       XMesaDestroyBuffer(b);
2093    }
2094 }
2095 
2096 
2097 PUBLIC void
glXQueryDrawable(Display * dpy,GLXDrawable draw,int attribute,unsigned int * value)2098 glXQueryDrawable(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 
2144 PUBLIC GLXContext
glXCreateNewContext(Display * dpy,GLXFBConfig config,int renderType,GLXContext shareCtx,Bool direct)2145 glXCreateNewContext( 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 
2161 PUBLIC int
glXQueryContext(Display * dpy,GLXContext ctx,int attribute,int * value)2162 glXQueryContext( 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 
2187 PUBLIC void
glXSelectEvent(Display * dpy,GLXDrawable drawable,unsigned long mask)2188 glXSelectEvent( Display *dpy, GLXDrawable drawable, unsigned long mask )
2189 {
2190    XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);
2191    if (xmbuf)
2192       xmbuf->selectedEvents = mask;
2193 }
2194 
2195 
2196 PUBLIC void
glXGetSelectedEvent(Display * dpy,GLXDrawable drawable,unsigned long * mask)2197 glXGetSelectedEvent(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 
2210 PUBLIC int
glXSwapIntervalSGI(int interval)2211 glXSwapIntervalSGI(int interval)
2212 {
2213    (void) interval;
2214    return 0;
2215 }
2216 
2217 
2218 
2219 /*** GLX_SGI_video_sync ***/
2220 
2221 static unsigned int FrameCounter = 0;
2222 
2223 PUBLIC int
glXGetVideoSyncSGI(unsigned int * count)2224 glXGetVideoSyncSGI(unsigned int *count)
2225 {
2226    /* this is a bogus implementation */
2227    *count = FrameCounter++;
2228    return 0;
2229 }
2230 
2231 PUBLIC int
glXWaitVideoSyncSGI(int divisor,int remainder,unsigned int * count)2232 glXWaitVideoSyncSGI(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 
2248 PUBLIC Bool
glXMakeCurrentReadSGI(Display * dpy,GLXDrawable draw,GLXDrawable read,GLXContext ctx)2249 glXMakeCurrentReadSGI(Display *dpy, GLXDrawable draw, GLXDrawable read,
2250                       GLXContext ctx)
2251 {
2252    return glXMakeContextCurrent( dpy, draw, read, ctx );
2253 }
2254 
2255 /* not used
2256 static GLXDrawable
2257 glXGetCurrentReadDrawableSGI(void)
2258 {
2259    return 0;
2260 }
2261 */
2262 
2263 
2264 /*** GLX_SGIX_video_source ***/
2265 #if defined(_VL_H)
2266 
2267 PUBLIC GLXVideoSourceSGIX
glXCreateGLXVideoSourceSGIX(Display * dpy,int screen,VLServer server,VLPath path,int nodeClass,VLNode drainNode)2268 glXCreateGLXVideoSourceSGIX(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 
2280 PUBLIC void
glXDestroyGLXVideoSourceSGIX(Display * dpy,GLXVideoSourceSGIX src)2281 glXDestroyGLXVideoSourceSGIX(Display *dpy, GLXVideoSourceSGIX src)
2282 {
2283    (void) dpy;
2284    (void) src;
2285 }
2286 
2287 #endif
2288 
2289 
2290 /*** GLX_EXT_import_context ***/
2291 
2292 PUBLIC void
glXFreeContextEXT(Display * dpy,GLXContext context)2293 glXFreeContextEXT(Display *dpy, GLXContext context)
2294 {
2295    (void) dpy;
2296    (void) context;
2297 }
2298 
2299 PUBLIC GLXContextID
glXGetContextIDEXT(const GLXContext context)2300 glXGetContextIDEXT(const GLXContext context)
2301 {
2302    (void) context;
2303    return 0;
2304 }
2305 
2306 PUBLIC GLXContext
glXImportContextEXT(Display * dpy,GLXContextID contextID)2307 glXImportContextEXT(Display *dpy, GLXContextID contextID)
2308 {
2309    (void) dpy;
2310    (void) contextID;
2311    return 0;
2312 }
2313 
2314 PUBLIC int
glXQueryContextInfoEXT(Display * dpy,GLXContext context,int attribute,int * value)2315 glXQueryContextInfoEXT(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 
2329 PUBLIC int
glXGetFBConfigAttribSGIX(Display * dpy,GLXFBConfigSGIX config,int attribute,int * value)2330 glXGetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config,
2331                          int attribute, int *value)
2332 {
2333    return glXGetFBConfigAttrib(dpy, config, attribute, value);
2334 }
2335 
2336 PUBLIC GLXFBConfigSGIX *
glXChooseFBConfigSGIX(Display * dpy,int screen,int * attrib_list,int * nelements)2337 glXChooseFBConfigSGIX(Display *dpy, int screen, int *attrib_list,
2338                       int *nelements)
2339 {
2340    return (GLXFBConfig *) glXChooseFBConfig(dpy, screen,
2341                                             attrib_list, nelements);
2342 }
2343 
2344 
2345 PUBLIC GLXPixmap
glXCreateGLXPixmapWithConfigSGIX(Display * dpy,GLXFBConfigSGIX config,Pixmap pixmap)2346 glXCreateGLXPixmapWithConfigSGIX(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 
2355 PUBLIC GLXContext
glXCreateContextWithConfigSGIX(Display * dpy,GLXFBConfigSGIX config,int renderType,GLXContext shareCtx,Bool direct)2356 glXCreateContextWithConfigSGIX(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 
2373 PUBLIC XVisualInfo *
glXGetVisualFromFBConfigSGIX(Display * dpy,GLXFBConfigSGIX config)2374 glXGetVisualFromFBConfigSGIX(Display *dpy, GLXFBConfigSGIX config)
2375 {
2376    return glXGetVisualFromFBConfig(dpy, config);
2377 }
2378 
2379 
2380 PUBLIC GLXFBConfigSGIX
glXGetFBConfigFromVisualSGIX(Display * dpy,XVisualInfo * vis)2381 glXGetFBConfigFromVisualSGIX(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 
2396 PUBLIC GLXPbufferSGIX
glXCreateGLXPbufferSGIX(Display * dpy,GLXFBConfigSGIX config,unsigned int width,unsigned int height,int * attribList)2397 glXCreateGLXPbufferSGIX(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 
2435 PUBLIC void
glXDestroyGLXPbufferSGIX(Display * dpy,GLXPbufferSGIX pbuf)2436 glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf)
2437 {
2438    XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf);
2439    if (xmbuf) {
2440       XMesaDestroyBuffer(xmbuf);
2441    }
2442 }
2443 
2444 
2445 PUBLIC void
glXQueryGLXPbufferSGIX(Display * dpy,GLXPbufferSGIX pbuf,int attribute,unsigned int * value)2446 glXQueryGLXPbufferSGIX(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 
2478 PUBLIC void
glXSelectEventSGIX(Display * dpy,GLXDrawable drawable,unsigned long mask)2479 glXSelectEventSGIX(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 
2489 PUBLIC void
glXGetSelectedEventSGIX(Display * dpy,GLXDrawable drawable,unsigned long * mask)2490 glXGetSelectedEventSGIX(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 
2506 PUBLIC void
glXCushionSGI(Display * dpy,Window win,float cushion)2507 glXCushionSGI(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 
2518 PUBLIC int
glXBindChannelToWindowSGIX(Display * dpy,int screen,int channel,Window window)2519 glXBindChannelToWindowSGIX(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 
2529 PUBLIC int
glXChannelRectSGIX(Display * dpy,int screen,int channel,int x,int y,int w,int h)2530 glXChannelRectSGIX(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 
2543 PUBLIC int
glXQueryChannelRectSGIX(Display * dpy,int screen,int channel,int * x,int * y,int * w,int * h)2544 glXQueryChannelRectSGIX(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 
2557 PUBLIC int
glXQueryChannelDeltasSGIX(Display * dpy,int screen,int channel,int * dx,int * dy,int * dw,int * dh)2558 glXQueryChannelDeltasSGIX(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 
2571 PUBLIC int
glXChannelRectSyncSGIX(Display * dpy,int screen,int channel,GLenum synctype)2572 glXChannelRectSyncSGIX(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_)
2586 PUBLIC Bool
glXAssociateDMPbufferSGIX(Display * dpy,GLXPbufferSGIX pbuffer,DMparams * params,DMbuffer dmbuffer)2587 glXAssociateDMPbufferSGIX(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 
2601 PUBLIC Status
glXGetTransparentIndexSUN(Display * dpy,Window overlay,Window underlay,unsigned long * pTransparent)2602 glXGetTransparentIndexSUN(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  */
2620 PUBLIC Bool
glXReleaseBuffersMESA(Display * dpy,GLXDrawable d)2621 glXReleaseBuffersMESA( 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 
2633 PUBLIC void
glXBindTexImageEXT(Display * dpy,GLXDrawable drawable,int buffer,const int * attrib_list)2634 glXBindTexImageEXT(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 
2642 PUBLIC void
glXReleaseTexImageEXT(Display * dpy,GLXDrawable drawable,int buffer)2643 glXReleaseTexImageEXT(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 
2655 GLXContext
glXCreateContextAttribsARB(Display * dpy,GLXFBConfig config,GLXContext shareCtx,Bool direct,const int * attrib_list)2656 glXCreateContextAttribsARB(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