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