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