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