1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
5 * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26
27 /**
28 * "Fake" GLX API implemented in terms of the XMesa*() functions.
29 */
30
31
32
33 #define GLX_GLXEXT_PROTOTYPES
34 #include "GL/glx.h"
35
36 #include <stdio.h>
37 #include <string.h>
38 #include <X11/Xmd.h>
39 #include <GL/glxproto.h>
40
41 #include "xm_api.h"
42 #include "main/errors.h"
43 #include "main/config.h"
44 #include "util/u_math.h"
45 #include "util/u_memory.h"
46
47 /* An "Atrribs/Attribs" typo was fixed in glxproto.h in Nov 2014.
48 * This is in case we don't have the updated header.
49 */
50 #if !defined(X_GLXCreateContextAttribsARB) && \
51 defined(X_GLXCreateContextAtrribsARB)
52 #define X_GLXCreateContextAttribsARB X_GLXCreateContextAtrribsARB
53 #endif
54
55 /* This indicates the client-side GLX API and GLX encoder version. */
56 #define CLIENT_MAJOR_VERSION 1
57 #define CLIENT_MINOR_VERSION 4 /* but don't have 1.3's pbuffers, etc yet */
58
59 /* This indicates the server-side GLX decoder version.
60 * GLX 1.4 indicates OpenGL 1.3 support
61 */
62 #define SERVER_MAJOR_VERSION 1
63 #define SERVER_MINOR_VERSION 4
64
65 /* Who implemented this GLX? */
66 #define VENDOR "Brian Paul"
67
68 #define EXTENSIONS \
69 "GLX_MESA_copy_sub_buffer " \
70 "GLX_MESA_pixmap_colormap " \
71 "GLX_MESA_release_buffers " \
72 "GLX_ARB_create_context " \
73 "GLX_ARB_create_context_profile " \
74 "GLX_ARB_get_proc_address " \
75 "GLX_EXT_create_context_es_profile " \
76 "GLX_EXT_create_context_es2_profile " \
77 "GLX_EXT_texture_from_pixmap " \
78 "GLX_EXT_visual_info " \
79 "GLX_EXT_visual_rating " \
80 /*"GLX_SGI_video_sync "*/ \
81 "GLX_SGIX_fbconfig " \
82 "GLX_SGIX_pbuffer "
83
84 #define DEFAULT_DIRECT GL_TRUE
85
86
87 /** XXX this could be based on gallium's max texture size */
88 #define PBUFFER_MAX_SIZE 16384
89
90
91 /**
92 * The GLXContext typedef is defined as a pointer to this structure.
93 */
94 struct __GLXcontextRec
95 {
96 Display *currentDpy;
97 GLboolean isDirect;
98 GLXDrawable currentDrawable;
99 GLXDrawable currentReadable;
100 XID xid;
101
102 XMesaContext xmesaContext;
103 };
104
105
106 thread_local GLXContext ContextTSD;
107
108 /** Set current context for calling thread */
109 static void
SetCurrentContext(GLXContext c)110 SetCurrentContext(GLXContext c)
111 {
112 ContextTSD = c;
113 }
114
115 /** Get current context for calling thread */
116 static GLXContext
GetCurrentContext(void)117 GetCurrentContext(void)
118 {
119 return 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 24.
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