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