st/glx: use strdup() instead of _mesa_strdup()
[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 <stdio.h>
37 #include <string.h>
38 #include <X11/Xmd.h>
39 #include <GL/glxproto.h>
40
41 #include "xm_api.h"
42
43
44 /* This indicates the client-side GLX API and GLX encoder version. */
45 #define CLIENT_MAJOR_VERSION 1
46 #define CLIENT_MINOR_VERSION 4 /* but don't have 1.3's pbuffers, etc yet */
47
48 /* This indicates the server-side GLX decoder version.
49 * GLX 1.4 indicates OpenGL 1.3 support
50 */
51 #define SERVER_MAJOR_VERSION 1
52 #define SERVER_MINOR_VERSION 4
53
54 /* Who implemented this GLX? */
55 #define VENDOR "Brian Paul"
56
57 #define EXTENSIONS \
58 "GLX_MESA_copy_sub_buffer " \
59 "GLX_MESA_pixmap_colormap " \
60 "GLX_MESA_release_buffers " \
61 "GLX_ARB_create_context " \
62 "GLX_ARB_create_context_profile " \
63 "GLX_ARB_get_proc_address " \
64 "GLX_EXT_create_context_es_profile " \
65 "GLX_EXT_create_context_es2_profile " \
66 "GLX_EXT_texture_from_pixmap " \
67 "GLX_EXT_visual_info " \
68 "GLX_EXT_visual_rating " \
69 /*"GLX_SGI_video_sync "*/ \
70 "GLX_SGIX_fbconfig " \
71 "GLX_SGIX_pbuffer "
72
73 #define DEFAULT_DIRECT GL_TRUE
74
75
76 /** XXX this could be based on gallium's max texture size */
77 #define PBUFFER_MAX_SIZE 16384
78
79
80 /**
81 * The GLXContext typedef is defined as a pointer to this structure.
82 */
83 struct __GLXcontextRec
84 {
85 Display *currentDpy;
86 GLboolean isDirect;
87 GLXDrawable currentDrawable;
88 GLXDrawable currentReadable;
89 XID xid;
90
91 XMesaContext xmesaContext;
92 };
93
94
95
96 static pipe_tsd ContextTSD;
97
98 /** Set current context for calling thread */
99 static void
100 SetCurrentContext(GLXContext c)
101 {
102 pipe_tsd_set(&ContextTSD, c);
103 }
104
105 /** Get current context for calling thread */
106 static GLXContext
107 GetCurrentContext(void)
108 {
109 return pipe_tsd_get(&ContextTSD);
110 }
111
112
113
114 /**********************************************************************/
115 /*** GLX Visual Code ***/
116 /**********************************************************************/
117
118 #define DONT_CARE -1
119
120
121 static XMesaVisual *VisualTable = NULL;
122 static int NumVisuals = 0;
123
124
125
126 /* Macro to handle c_class vs class field name in XVisualInfo struct */
127 #if defined(__cplusplus) || defined(c_plusplus)
128 #define CLASS c_class
129 #else
130 #define CLASS class
131 #endif
132
133
134
135 /*
136 * Test if the given XVisualInfo is usable for Mesa rendering.
137 */
138 static GLboolean
139 is_usable_visual( XVisualInfo *vinfo )
140 {
141 switch (vinfo->CLASS) {
142 case StaticGray:
143 case GrayScale:
144 /* Any StaticGray/GrayScale visual works in RGB or CI mode */
145 return GL_TRUE;
146 case StaticColor:
147 case PseudoColor:
148 /* Any StaticColor/PseudoColor visual of at least 4 bits */
149 if (vinfo->depth>=4) {
150 return GL_TRUE;
151 }
152 else {
153 return GL_FALSE;
154 }
155 case TrueColor:
156 case DirectColor:
157 /* Any depth of TrueColor or DirectColor works in RGB mode */
158 return GL_TRUE;
159 default:
160 /* This should never happen */
161 return GL_FALSE;
162 }
163 }
164
165
166 /*
167 * Given an XVisualInfo and RGB, Double, and Depth buffer flags, save the
168 * configuration in our list of GLX visuals.
169 */
170 static XMesaVisual
171 save_glx_visual( Display *dpy, XVisualInfo *vinfo,
172 GLboolean rgbFlag, GLboolean alphaFlag, GLboolean dbFlag,
173 GLboolean stereoFlag,
174 GLint depth_size, GLint stencil_size,
175 GLint accumRedSize, GLint accumGreenSize,
176 GLint accumBlueSize, GLint accumAlphaSize,
177 GLint level, GLint numAuxBuffers )
178 {
179 GLboolean ximageFlag = GL_TRUE;
180 XMesaVisual xmvis;
181 GLint i;
182 GLboolean comparePointers;
183
184 if (dbFlag) {
185 /* Check if the MESA_BACK_BUFFER env var is set */
186 char *backbuffer = getenv("MESA_BACK_BUFFER");
187 if (backbuffer) {
188 if (backbuffer[0]=='p' || backbuffer[0]=='P') {
189 ximageFlag = GL_FALSE;
190 }
191 else if (backbuffer[0]=='x' || backbuffer[0]=='X') {
192 ximageFlag = GL_TRUE;
193 }
194 else {
195 _mesa_warning(NULL, "Mesa: invalid value for MESA_BACK_BUFFER environment variable, using an XImage.");
196 }
197 }
198 }
199
200 if (stereoFlag) {
201 /* stereo not supported */
202 return NULL;
203 }
204
205 if (stencil_size > 0 && depth_size > 0)
206 depth_size = 24;
207
208 /* Comparing IDs uses less memory but sometimes fails. */
209 /* XXX revisit this after 3.0 is finished. */
210 if (getenv("MESA_GLX_VISUAL_HACK"))
211 comparePointers = GL_TRUE;
212 else
213 comparePointers = GL_FALSE;
214
215 /* Force the visual to have an alpha channel */
216 if (rgbFlag && getenv("MESA_GLX_FORCE_ALPHA"))
217 alphaFlag = GL_TRUE;
218
219 /* First check if a matching visual is already in the list */
220 for (i=0; i<NumVisuals; i++) {
221 XMesaVisual v = VisualTable[i];
222 if (v->display == dpy
223 && v->mesa_visual.level == level
224 && v->mesa_visual.numAuxBuffers == numAuxBuffers
225 && v->ximage_flag == ximageFlag
226 && v->mesa_visual.rgbMode == rgbFlag
227 && v->mesa_visual.doubleBufferMode == dbFlag
228 && v->mesa_visual.stereoMode == stereoFlag
229 && (v->mesa_visual.alphaBits > 0) == alphaFlag
230 && (v->mesa_visual.depthBits >= depth_size || depth_size == 0)
231 && (v->mesa_visual.stencilBits >= stencil_size || stencil_size == 0)
232 && (v->mesa_visual.accumRedBits >= accumRedSize || accumRedSize == 0)
233 && (v->mesa_visual.accumGreenBits >= accumGreenSize || accumGreenSize == 0)
234 && (v->mesa_visual.accumBlueBits >= accumBlueSize || accumBlueSize == 0)
235 && (v->mesa_visual.accumAlphaBits >= accumAlphaSize || accumAlphaSize == 0)) {
236 /* now either compare XVisualInfo pointers or visual IDs */
237 if ((!comparePointers && v->visinfo->visualid == vinfo->visualid)
238 || (comparePointers && v->vishandle == vinfo)) {
239 return v;
240 }
241 }
242 }
243
244 /* Create a new visual and add it to the list. */
245
246 xmvis = XMesaCreateVisual( dpy, vinfo, rgbFlag, alphaFlag, dbFlag,
247 stereoFlag, ximageFlag,
248 depth_size, stencil_size,
249 accumRedSize, accumBlueSize,
250 accumBlueSize, accumAlphaSize, 0, level,
251 GLX_NONE_EXT );
252 if (xmvis) {
253 /* Save a copy of the pointer now so we can find this visual again
254 * if we need to search for it in find_glx_visual().
255 */
256 xmvis->vishandle = vinfo;
257 /* Allocate more space for additional visual */
258 VisualTable = realloc(VisualTable, sizeof(XMesaVisual) * (NumVisuals + 1));
259 /* add xmvis to the list */
260 VisualTable[NumVisuals] = xmvis;
261 NumVisuals++;
262 /* XXX minor hack, because XMesaCreateVisual doesn't support an
263 * aux buffers parameter.
264 */
265 xmvis->mesa_visual.numAuxBuffers = numAuxBuffers;
266 }
267 return xmvis;
268 }
269
270
271 /**
272 * Return the default number of bits for the Z buffer.
273 * If defined, use the MESA_GLX_DEPTH_BITS env var value.
274 * Otherwise, use the DEFAULT_SOFTWARE_DEPTH_BITS constant.
275 * XXX probably do the same thing for stencil, accum, etc.
276 */
277 static GLint
278 default_depth_bits(void)
279 {
280 int zBits;
281 const char *zEnv = getenv("MESA_GLX_DEPTH_BITS");
282 if (zEnv)
283 zBits = atoi(zEnv);
284 else
285 zBits = 24;
286 return zBits;
287 }
288
289 static GLint
290 default_alpha_bits(void)
291 {
292 int aBits;
293 const char *aEnv = getenv("MESA_GLX_ALPHA_BITS");
294 if (aEnv)
295 aBits = atoi(aEnv);
296 else
297 aBits = 0;
298 return aBits;
299 }
300
301 static GLint
302 default_accum_bits(void)
303 {
304 return 16;
305 }
306
307
308
309 /*
310 * Create a GLX visual from a regular XVisualInfo.
311 * This is called when Fake GLX is given an XVisualInfo which wasn't
312 * returned by glXChooseVisual. Since this is the first time we're
313 * considering this visual we'll take a guess at reasonable values
314 * for depth buffer size, stencil size, accum size, etc.
315 * This is the best we can do with a client-side emulation of GLX.
316 */
317 static XMesaVisual
318 create_glx_visual( Display *dpy, XVisualInfo *visinfo )
319 {
320 GLint zBits = default_depth_bits();
321 GLint accBits = default_accum_bits();
322 GLboolean alphaFlag = default_alpha_bits() > 0;
323
324 if (is_usable_visual( visinfo )) {
325 /* Configure this visual as RGB, double-buffered, depth-buffered. */
326 /* This is surely wrong for some people's needs but what else */
327 /* can be done? They should use glXChooseVisual(). */
328 return save_glx_visual( dpy, visinfo,
329 GL_TRUE, /* rgb */
330 alphaFlag, /* alpha */
331 GL_TRUE, /* double */
332 GL_FALSE, /* stereo */
333 zBits,
334 8, /* stencil bits */
335 accBits, /* r */
336 accBits, /* g */
337 accBits, /* b */
338 accBits, /* a */
339 0, /* level */
340 0 /* numAux */
341 );
342 }
343 else {
344 _mesa_warning(NULL, "Mesa: error in glXCreateContext: bad visual\n");
345 return NULL;
346 }
347 }
348
349
350
351 /*
352 * Find the GLX visual associated with an XVisualInfo.
353 */
354 static XMesaVisual
355 find_glx_visual( Display *dpy, XVisualInfo *vinfo )
356 {
357 int i;
358
359 /* try to match visual id */
360 for (i=0;i<NumVisuals;i++) {
361 if (VisualTable[i]->display==dpy
362 && VisualTable[i]->visinfo->visualid == vinfo->visualid) {
363 return VisualTable[i];
364 }
365 }
366
367 /* if that fails, try to match pointers */
368 for (i=0;i<NumVisuals;i++) {
369 if (VisualTable[i]->display==dpy && VisualTable[i]->vishandle==vinfo) {
370 return VisualTable[i];
371 }
372 }
373
374 return NULL;
375 }
376
377
378 /**
379 * Try to get an X visual which matches the given arguments.
380 */
381 static XVisualInfo *
382 get_visual( Display *dpy, int scr, unsigned int depth, int xclass )
383 {
384 XVisualInfo temp, *vis;
385 long mask;
386 int n;
387 unsigned int default_depth;
388 int default_class;
389
390 mask = VisualScreenMask | VisualDepthMask | VisualClassMask;
391 temp.screen = scr;
392 temp.depth = depth;
393 temp.CLASS = xclass;
394
395 default_depth = DefaultDepth(dpy,scr);
396 default_class = DefaultVisual(dpy,scr)->CLASS;
397
398 if (depth==default_depth && xclass==default_class) {
399 /* try to get root window's visual */
400 temp.visualid = DefaultVisual(dpy,scr)->visualid;
401 mask |= VisualIDMask;
402 }
403
404 vis = XGetVisualInfo( dpy, mask, &temp, &n );
405
406 /* In case bits/pixel > 24, make sure color channels are still <=8 bits.
407 * An SGI Infinite Reality system, for example, can have 30bpp pixels:
408 * 10 bits per color channel. Mesa's limited to a max of 8 bits/channel.
409 */
410 if (vis && depth > 24 && (xclass==TrueColor || xclass==DirectColor)) {
411 if (_mesa_bitcount((GLuint) vis->red_mask ) <= 8 &&
412 _mesa_bitcount((GLuint) vis->green_mask) <= 8 &&
413 _mesa_bitcount((GLuint) vis->blue_mask ) <= 8) {
414 return vis;
415 }
416 else {
417 free((void *) vis);
418 return NULL;
419 }
420 }
421
422 return vis;
423 }
424
425
426 /*
427 * Retrieve the value of the given environment variable and find
428 * the X visual which matches it.
429 * Input: dpy - the display
430 * screen - the screen number
431 * varname - the name of the environment variable
432 * Return: an XVisualInfo pointer to NULL if error.
433 */
434 static XVisualInfo *
435 get_env_visual(Display *dpy, int scr, const char *varname)
436 {
437 char value[100], type[100];
438 int depth, xclass = -1;
439 XVisualInfo *vis;
440
441 if (!getenv( varname )) {
442 return NULL;
443 }
444
445 strncpy( value, getenv(varname), 100 );
446 value[99] = 0;
447
448 sscanf( value, "%s %d", type, &depth );
449
450 if (strcmp(type,"TrueColor")==0) xclass = TrueColor;
451 else if (strcmp(type,"DirectColor")==0) xclass = DirectColor;
452 else if (strcmp(type,"PseudoColor")==0) xclass = PseudoColor;
453 else if (strcmp(type,"StaticColor")==0) xclass = StaticColor;
454 else if (strcmp(type,"GrayScale")==0) xclass = GrayScale;
455 else if (strcmp(type,"StaticGray")==0) xclass = StaticGray;
456
457 if (xclass>-1 && depth>0) {
458 vis = get_visual( dpy, scr, depth, xclass );
459 if (vis) {
460 return vis;
461 }
462 }
463
464 _mesa_warning(NULL, "GLX unable to find visual class=%s, depth=%d.",
465 type, depth);
466
467 return NULL;
468 }
469
470
471
472 /*
473 * Select an X visual which satisfies the RGBA flag and minimum depth.
474 * Input: dpy,
475 * screen - X display and screen number
476 * min_depth - minimum visual depth
477 * preferred_class - preferred GLX visual class or DONT_CARE
478 * Return: pointer to an XVisualInfo or NULL.
479 */
480 static XVisualInfo *
481 choose_x_visual( Display *dpy, int screen, int min_depth,
482 int preferred_class )
483 {
484 XVisualInfo *vis;
485 int xclass, visclass = 0;
486 int depth;
487
488 /* First see if the MESA_RGB_VISUAL env var is defined */
489 vis = get_env_visual( dpy, screen, "MESA_RGB_VISUAL" );
490 if (vis) {
491 return vis;
492 }
493 /* Otherwise, search for a suitable visual */
494 if (preferred_class==DONT_CARE) {
495 for (xclass=0;xclass<6;xclass++) {
496 switch (xclass) {
497 case 0: visclass = TrueColor; break;
498 case 1: visclass = DirectColor; break;
499 case 2: visclass = PseudoColor; break;
500 case 3: visclass = StaticColor; break;
501 case 4: visclass = GrayScale; break;
502 case 5: visclass = StaticGray; break;
503 }
504 if (min_depth==0) {
505 /* start with shallowest */
506 for (depth=0;depth<=32;depth++) {
507 if (visclass==TrueColor && depth==8) {
508 /* Special case: try to get 8-bit PseudoColor before */
509 /* 8-bit TrueColor */
510 vis = get_visual( dpy, screen, 8, PseudoColor );
511 if (vis) {
512 return vis;
513 }
514 }
515 vis = get_visual( dpy, screen, depth, visclass );
516 if (vis) {
517 return vis;
518 }
519 }
520 }
521 else {
522 /* start with deepest */
523 for (depth=32;depth>=min_depth;depth--) {
524 if (visclass==TrueColor && depth==8) {
525 /* Special case: try to get 8-bit PseudoColor before */
526 /* 8-bit TrueColor */
527 vis = get_visual( dpy, screen, 8, PseudoColor );
528 if (vis) {
529 return vis;
530 }
531 }
532 vis = get_visual( dpy, screen, depth, visclass );
533 if (vis) {
534 return vis;
535 }
536 }
537 }
538 }
539 }
540 else {
541 /* search for a specific visual class */
542 switch (preferred_class) {
543 case GLX_TRUE_COLOR_EXT: visclass = TrueColor; break;
544 case GLX_DIRECT_COLOR_EXT: visclass = DirectColor; break;
545 case GLX_PSEUDO_COLOR_EXT: visclass = PseudoColor; break;
546 case GLX_STATIC_COLOR_EXT: visclass = StaticColor; break;
547 case GLX_GRAY_SCALE_EXT: visclass = GrayScale; break;
548 case GLX_STATIC_GRAY_EXT: visclass = StaticGray; break;
549 default: return NULL;
550 }
551 if (min_depth==0) {
552 /* start with shallowest */
553 for (depth=0;depth<=32;depth++) {
554 vis = get_visual( dpy, screen, depth, visclass );
555 if (vis) {
556 return vis;
557 }
558 }
559 }
560 else {
561 /* start with deepest */
562 for (depth=32;depth>=min_depth;depth--) {
563 vis = get_visual( dpy, screen, depth, visclass );
564 if (vis) {
565 return vis;
566 }
567 }
568 }
569 }
570
571 /* didn't find a visual */
572 return NULL;
573 }
574
575
576
577
578 /**********************************************************************/
579 /*** Display-related functions ***/
580 /**********************************************************************/
581
582
583 /**
584 * Free all XMesaVisuals which are associated with the given display.
585 */
586 static void
587 destroy_visuals_on_display(Display *dpy)
588 {
589 int i;
590 for (i = 0; i < NumVisuals; i++) {
591 if (VisualTable[i]->display == dpy) {
592 /* remove this visual */
593 int j;
594 free(VisualTable[i]);
595 for (j = i; j < NumVisuals - 1; j++)
596 VisualTable[j] = VisualTable[j + 1];
597 NumVisuals--;
598 }
599 }
600 }
601
602
603 /**
604 * Called from XCloseDisplay() to let us free our display-related data.
605 */
606 static int
607 close_display_callback(Display *dpy, XExtCodes *codes)
608 {
609 xmesa_destroy_buffers_on_display(dpy);
610 destroy_visuals_on_display(dpy);
611 return 0;
612 }
613
614
615 /**
616 * Look for the named extension on given display and return a pointer
617 * to the _XExtension data, or NULL if extension not found.
618 */
619 static _XExtension *
620 lookup_extension(Display *dpy, const char *extName)
621 {
622 _XExtension *ext;
623 for (ext = dpy->ext_procs; ext; ext = ext->next) {
624 if (ext->name && strcmp(ext->name, extName) == 0) {
625 return ext;
626 }
627 }
628 return NULL;
629 }
630
631
632 /**
633 * Whenever we're given a new Display pointer, call this function to
634 * register our close_display_callback function.
635 */
636 static void
637 register_with_display(Display *dpy)
638 {
639 const char *extName = "MesaGLX";
640 _XExtension *ext;
641
642 ext = lookup_extension(dpy, extName);
643 if (!ext) {
644 XExtCodes *c = XAddExtension(dpy);
645 ext = dpy->ext_procs; /* new extension is at head of list */
646 assert(c->extension == ext->codes.extension);
647 (void) c;
648 ext->name = strdup(extName);
649 ext->close_display = close_display_callback;
650 }
651 }
652
653
654 /**
655 * Fake an error.
656 */
657 static int
658 generate_error(Display *dpy,
659 unsigned char error_code,
660 XID resourceid,
661 unsigned char minor_code,
662 Bool core)
663 {
664 XErrorHandler handler;
665 int major_opcode;
666 int first_event;
667 int first_error;
668 XEvent event;
669
670 handler = XSetErrorHandler(NULL);
671 XSetErrorHandler(handler);
672 if (!handler) {
673 return 0;
674 }
675
676 if (!XQueryExtension(dpy, GLX_EXTENSION_NAME, &major_opcode, &first_event, &first_error)) {
677 major_opcode = 0;
678 first_event = 0;
679 first_error = 0;
680 }
681
682 if (!core) {
683 error_code += first_error;
684 }
685
686 memset(&event, 0, sizeof event);
687
688 event.xerror.type = X_Error;
689 event.xerror.display = dpy;
690 event.xerror.resourceid = resourceid;
691 event.xerror.serial = NextRequest(dpy) - 1;
692 event.xerror.error_code = error_code;
693 event.xerror.request_code = major_opcode;
694 event.xerror.minor_code = minor_code;
695
696 return handler(dpy, &event.xerror);
697 }
698
699
700 /**********************************************************************/
701 /*** Begin Fake GLX API Functions ***/
702 /**********************************************************************/
703
704
705 /**
706 * Helper used by glXChooseVisual and glXChooseFBConfig.
707 * The fbConfig parameter must be GL_FALSE for the former and GL_TRUE for
708 * the later.
709 * In either case, the attribute list is terminated with the value 'None'.
710 */
711 static XMesaVisual
712 choose_visual( Display *dpy, int screen, const int *list, GLboolean fbConfig )
713 {
714 const GLboolean rgbModeDefault = fbConfig;
715 const int *parselist;
716 XVisualInfo *vis;
717 int min_red=0, min_green=0, min_blue=0;
718 GLboolean rgb_flag = rgbModeDefault;
719 GLboolean alpha_flag = GL_FALSE;
720 GLboolean double_flag = GL_FALSE;
721 GLboolean stereo_flag = GL_FALSE;
722 GLint depth_size = 0;
723 GLint stencil_size = 0;
724 GLint accumRedSize = 0;
725 GLint accumGreenSize = 0;
726 GLint accumBlueSize = 0;
727 GLint accumAlphaSize = 0;
728 int level = 0;
729 int visual_type = DONT_CARE;
730 GLint caveat = DONT_CARE;
731 XMesaVisual xmvis = NULL;
732 int desiredVisualID = -1;
733 int numAux = 0;
734
735 xmesa_init( dpy );
736
737 parselist = list;
738
739 while (*parselist) {
740
741 if (fbConfig &&
742 parselist[1] == GLX_DONT_CARE &&
743 parselist[0] != GLX_LEVEL) {
744 /* For glXChooseFBConfig(), skip attributes whose value is
745 * GLX_DONT_CARE, unless it's GLX_LEVEL (which can legitimately be
746 * a negative value).
747 *
748 * From page 17 (23 of the pdf) of the GLX 1.4 spec:
749 * GLX DONT CARE may be specified for all attributes except GLX LEVEL.
750 */
751 parselist += 2;
752 continue;
753 }
754
755 switch (*parselist) {
756 case GLX_USE_GL:
757 if (fbConfig) {
758 /* invalid token */
759 return NULL;
760 }
761 else {
762 /* skip */
763 parselist++;
764 }
765 break;
766 case GLX_BUFFER_SIZE:
767 parselist++;
768 parselist++;
769 break;
770 case GLX_LEVEL:
771 parselist++;
772 level = *parselist++;
773 break;
774 case GLX_RGBA:
775 if (fbConfig) {
776 /* invalid token */
777 return NULL;
778 }
779 else {
780 rgb_flag = GL_TRUE;
781 parselist++;
782 }
783 break;
784 case GLX_DOUBLEBUFFER:
785 parselist++;
786 if (fbConfig) {
787 double_flag = *parselist++;
788 }
789 else {
790 double_flag = GL_TRUE;
791 }
792 break;
793 case GLX_STEREO:
794 parselist++;
795 if (fbConfig) {
796 stereo_flag = *parselist++;
797 }
798 else {
799 stereo_flag = GL_TRUE;
800 }
801 break;
802 case GLX_AUX_BUFFERS:
803 parselist++;
804 numAux = *parselist++;
805 if (numAux > MAX_AUX_BUFFERS)
806 return NULL;
807 break;
808 case GLX_RED_SIZE:
809 parselist++;
810 min_red = *parselist++;
811 break;
812 case GLX_GREEN_SIZE:
813 parselist++;
814 min_green = *parselist++;
815 break;
816 case GLX_BLUE_SIZE:
817 parselist++;
818 min_blue = *parselist++;
819 break;
820 case GLX_ALPHA_SIZE:
821 parselist++;
822 {
823 GLint size = *parselist++;
824 alpha_flag = size ? GL_TRUE : GL_FALSE;
825 }
826 break;
827 case GLX_DEPTH_SIZE:
828 parselist++;
829 depth_size = *parselist++;
830 break;
831 case GLX_STENCIL_SIZE:
832 parselist++;
833 stencil_size = *parselist++;
834 break;
835 case GLX_ACCUM_RED_SIZE:
836 parselist++;
837 {
838 GLint size = *parselist++;
839 accumRedSize = MAX2( accumRedSize, size );
840 }
841 break;
842 case GLX_ACCUM_GREEN_SIZE:
843 parselist++;
844 {
845 GLint size = *parselist++;
846 accumGreenSize = MAX2( accumGreenSize, size );
847 }
848 break;
849 case GLX_ACCUM_BLUE_SIZE:
850 parselist++;
851 {
852 GLint size = *parselist++;
853 accumBlueSize = MAX2( accumBlueSize, size );
854 }
855 break;
856 case GLX_ACCUM_ALPHA_SIZE:
857 parselist++;
858 {
859 GLint size = *parselist++;
860 accumAlphaSize = MAX2( accumAlphaSize, size );
861 }
862 break;
863
864 /*
865 * GLX_EXT_visual_info extension
866 */
867 case GLX_X_VISUAL_TYPE_EXT:
868 parselist++;
869 visual_type = *parselist++;
870 break;
871 case GLX_TRANSPARENT_TYPE_EXT:
872 parselist++;
873 parselist++;
874 break;
875 case GLX_TRANSPARENT_INDEX_VALUE_EXT:
876 parselist++;
877 parselist++;
878 break;
879 case GLX_TRANSPARENT_RED_VALUE_EXT:
880 case GLX_TRANSPARENT_GREEN_VALUE_EXT:
881 case GLX_TRANSPARENT_BLUE_VALUE_EXT:
882 case GLX_TRANSPARENT_ALPHA_VALUE_EXT:
883 /* ignore */
884 parselist++;
885 parselist++;
886 break;
887
888 /*
889 * GLX_EXT_visual_info extension
890 */
891 case GLX_VISUAL_CAVEAT_EXT:
892 parselist++;
893 caveat = *parselist++; /* ignored for now */
894 break;
895
896 /*
897 * GLX_ARB_multisample
898 */
899 case GLX_SAMPLE_BUFFERS_ARB:
900 case GLX_SAMPLES_ARB:
901 parselist++;
902 if (*parselist++ != 0) {
903 /* ms not supported */
904 return NULL;
905 }
906 break;
907
908 /*
909 * FBConfig attribs.
910 */
911 case GLX_RENDER_TYPE:
912 if (!fbConfig)
913 return NULL;
914 parselist++;
915 if (*parselist & GLX_RGBA_BIT) {
916 rgb_flag = GL_TRUE;
917 }
918 else if (*parselist & GLX_COLOR_INDEX_BIT) {
919 rgb_flag = GL_FALSE;
920 }
921 else if (*parselist == 0) {
922 rgb_flag = GL_TRUE;
923 }
924 parselist++;
925 break;
926 case GLX_DRAWABLE_TYPE:
927 if (!fbConfig)
928 return NULL;
929 parselist++;
930 if (*parselist & ~(GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT)) {
931 return NULL; /* bad bit */
932 }
933 parselist++;
934 break;
935 case GLX_FBCONFIG_ID:
936 case GLX_VISUAL_ID:
937 if (!fbConfig)
938 return NULL;
939 parselist++;
940 desiredVisualID = *parselist++;
941 break;
942 case GLX_X_RENDERABLE:
943 case GLX_MAX_PBUFFER_WIDTH:
944 case GLX_MAX_PBUFFER_HEIGHT:
945 case GLX_MAX_PBUFFER_PIXELS:
946 if (!fbConfig)
947 return NULL; /* invalid config option */
948 parselist += 2; /* ignore the parameter */
949 break;
950
951 #ifdef GLX_EXT_texture_from_pixmap
952 case GLX_BIND_TO_TEXTURE_RGB_EXT:
953 parselist++; /*skip*/
954 break;
955 case GLX_BIND_TO_TEXTURE_RGBA_EXT:
956 parselist++; /*skip*/
957 break;
958 case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
959 parselist++; /*skip*/
960 break;
961 case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
962 parselist++;
963 if (*parselist & ~(GLX_TEXTURE_1D_BIT_EXT |
964 GLX_TEXTURE_2D_BIT_EXT |
965 GLX_TEXTURE_RECTANGLE_BIT_EXT)) {
966 /* invalid bit */
967 return NULL;
968 }
969 break;
970 case GLX_Y_INVERTED_EXT:
971 parselist++; /*skip*/
972 break;
973 #endif
974
975 case None:
976 /* end of list */
977 break;
978
979 default:
980 /* undefined attribute */
981 _mesa_warning(NULL, "unexpected attrib 0x%x in choose_visual()",
982 *parselist);
983 return NULL;
984 }
985 }
986
987 (void) caveat;
988
989
990 /*
991 * Since we're only simulating the GLX extension this function will never
992 * find any real GL visuals. Instead, all we can do is try to find an RGB
993 * or CI visual of appropriate depth. Other requested attributes such as
994 * double buffering, depth buffer, etc. will be associated with the X
995 * visual and stored in the VisualTable[].
996 */
997 if (desiredVisualID != -1) {
998 /* try to get a specific visual, by visualID */
999 XVisualInfo temp;
1000 int n;
1001 temp.visualid = desiredVisualID;
1002 temp.screen = screen;
1003 vis = XGetVisualInfo(dpy, VisualIDMask | VisualScreenMask, &temp, &n);
1004 if (vis) {
1005 /* give the visual some useful GLX attributes */
1006 double_flag = GL_TRUE;
1007 rgb_flag = GL_TRUE;
1008 }
1009 }
1010 else if (level==0) {
1011 /* normal color planes */
1012 /* Get an RGB visual */
1013 int min_rgb = min_red + min_green + min_blue;
1014 if (min_rgb>1 && min_rgb<8) {
1015 /* a special case to be sure we can get a monochrome visual */
1016 min_rgb = 1;
1017 }
1018 vis = choose_x_visual( dpy, screen, min_rgb, visual_type );
1019 }
1020 else {
1021 _mesa_warning(NULL, "overlay not supported");
1022 return NULL;
1023 }
1024
1025 if (vis) {
1026 /* Note: we're not exactly obeying the glXChooseVisual rules here.
1027 * When GLX_DEPTH_SIZE = 1 is specified we're supposed to choose the
1028 * largest depth buffer size, which is 32bits/value. Instead, we
1029 * return 16 to maintain performance with earlier versions of Mesa.
1030 */
1031 if (stencil_size > 0)
1032 depth_size = 24; /* if Z and stencil, always use 24+8 format */
1033 else if (depth_size > 24)
1034 depth_size = 32;
1035 else if (depth_size > 16)
1036 depth_size = 24;
1037 else if (depth_size > 0) {
1038 depth_size = default_depth_bits();
1039 }
1040
1041 if (!alpha_flag) {
1042 alpha_flag = default_alpha_bits() > 0;
1043 }
1044
1045 /* we only support one size of stencil and accum buffers. */
1046 if (stencil_size > 0)
1047 stencil_size = 8;
1048
1049 if (accumRedSize > 0 ||
1050 accumGreenSize > 0 ||
1051 accumBlueSize > 0 ||
1052 accumAlphaSize > 0) {
1053
1054 accumRedSize =
1055 accumGreenSize =
1056 accumBlueSize = default_accum_bits();
1057
1058 accumAlphaSize = alpha_flag ? accumRedSize : 0;
1059 }
1060
1061 xmvis = save_glx_visual( dpy, vis, rgb_flag, alpha_flag, double_flag,
1062 stereo_flag, depth_size, stencil_size,
1063 accumRedSize, accumGreenSize,
1064 accumBlueSize, accumAlphaSize, level, numAux );
1065 }
1066
1067 return xmvis;
1068 }
1069
1070
1071 PUBLIC XVisualInfo *
1072 glXChooseVisual( Display *dpy, int screen, int *list )
1073 {
1074 XMesaVisual xmvis;
1075
1076 /* register ourselves as an extension on this display */
1077 register_with_display(dpy);
1078
1079 xmvis = choose_visual(dpy, screen, list, GL_FALSE);
1080 if (xmvis) {
1081 /* create a new vishandle - the cached one may be stale */
1082 xmvis->vishandle = malloc(sizeof(XVisualInfo));
1083 if (xmvis->vishandle) {
1084 memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo));
1085 }
1086 return xmvis->vishandle;
1087 }
1088 else
1089 return NULL;
1090 }
1091
1092
1093 /**
1094 * Helper function used by other glXCreateContext functions.
1095 */
1096 static GLXContext
1097 create_context(Display *dpy, XMesaVisual xmvis,
1098 XMesaContext shareCtx, Bool direct,
1099 unsigned major, unsigned minor,
1100 unsigned profileMask, unsigned contextFlags)
1101 {
1102 GLXContext glxCtx;
1103
1104 if (!dpy || !xmvis)
1105 return 0;
1106
1107 glxCtx = CALLOC_STRUCT(__GLXcontextRec);
1108 if (!glxCtx)
1109 return 0;
1110
1111 /* deallocate unused windows/buffers */
1112 #if 0
1113 XMesaGarbageCollect();
1114 #endif
1115
1116 glxCtx->xmesaContext = XMesaCreateContext(xmvis, shareCtx, major, minor,
1117 profileMask, contextFlags);
1118 if (!glxCtx->xmesaContext) {
1119 free(glxCtx);
1120 return NULL;
1121 }
1122
1123 glxCtx->isDirect = DEFAULT_DIRECT;
1124 glxCtx->currentDpy = dpy;
1125 glxCtx->xid = (XID) glxCtx; /* self pointer */
1126
1127 return glxCtx;
1128 }
1129
1130
1131 PUBLIC GLXContext
1132 glXCreateContext( Display *dpy, XVisualInfo *visinfo,
1133 GLXContext shareCtx, Bool direct )
1134 {
1135 XMesaVisual xmvis;
1136
1137 xmvis = find_glx_visual( dpy, visinfo );
1138 if (!xmvis) {
1139 /* This visual wasn't found with glXChooseVisual() */
1140 xmvis = create_glx_visual( dpy, visinfo );
1141 if (!xmvis) {
1142 /* unusable visual */
1143 return NULL;
1144 }
1145 }
1146
1147 return create_context(dpy, xmvis,
1148 shareCtx ? shareCtx->xmesaContext : NULL,
1149 direct,
1150 1, 0, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, 0x0);
1151 }
1152
1153
1154 /* XXX these may have to be removed due to thread-safety issues. */
1155 static GLXContext MakeCurrent_PrevContext = 0;
1156 static GLXDrawable MakeCurrent_PrevDrawable = 0;
1157 static GLXDrawable MakeCurrent_PrevReadable = 0;
1158 static XMesaBuffer MakeCurrent_PrevDrawBuffer = 0;
1159 static XMesaBuffer MakeCurrent_PrevReadBuffer = 0;
1160
1161
1162 /* GLX 1.3 and later */
1163 PUBLIC Bool
1164 glXMakeContextCurrent( Display *dpy, GLXDrawable draw,
1165 GLXDrawable read, GLXContext ctx )
1166 {
1167 GLXContext glxCtx = ctx;
1168 static boolean firsttime = 1, no_rast = 0;
1169
1170 if (firsttime) {
1171 no_rast = getenv("SP_NO_RAST") != NULL;
1172 firsttime = 0;
1173 }
1174
1175 if (ctx && draw && read) {
1176 XMesaBuffer drawBuffer, readBuffer;
1177 XMesaContext xmctx = glxCtx->xmesaContext;
1178
1179 /* Find the XMesaBuffer which corresponds to the GLXDrawable 'draw' */
1180 if (ctx == MakeCurrent_PrevContext
1181 && draw == MakeCurrent_PrevDrawable) {
1182 drawBuffer = MakeCurrent_PrevDrawBuffer;
1183 }
1184 else {
1185 drawBuffer = XMesaFindBuffer( dpy, draw );
1186 }
1187 if (!drawBuffer) {
1188 /* drawable must be a new window! */
1189 drawBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, draw );
1190 if (!drawBuffer) {
1191 /* Out of memory, or context/drawable depth mismatch */
1192 return False;
1193 }
1194 }
1195
1196 /* Find the XMesaBuffer which corresponds to the GLXDrawable 'read' */
1197 if (ctx == MakeCurrent_PrevContext
1198 && read == MakeCurrent_PrevReadable) {
1199 readBuffer = MakeCurrent_PrevReadBuffer;
1200 }
1201 else {
1202 readBuffer = XMesaFindBuffer( dpy, read );
1203 }
1204 if (!readBuffer) {
1205 /* drawable must be a new window! */
1206 readBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, read );
1207 if (!readBuffer) {
1208 /* Out of memory, or context/drawable depth mismatch */
1209 return False;
1210 }
1211 }
1212
1213 if (no_rast &&
1214 MakeCurrent_PrevContext == ctx &&
1215 MakeCurrent_PrevDrawable == draw &&
1216 MakeCurrent_PrevReadable == read &&
1217 MakeCurrent_PrevDrawBuffer == drawBuffer &&
1218 MakeCurrent_PrevReadBuffer == readBuffer)
1219 return True;
1220
1221 MakeCurrent_PrevContext = ctx;
1222 MakeCurrent_PrevDrawable = draw;
1223 MakeCurrent_PrevReadable = read;
1224 MakeCurrent_PrevDrawBuffer = drawBuffer;
1225 MakeCurrent_PrevReadBuffer = readBuffer;
1226
1227 /* Now make current! */
1228 if (XMesaMakeCurrent2(xmctx, drawBuffer, readBuffer)) {
1229 ctx->currentDpy = dpy;
1230 ctx->currentDrawable = draw;
1231 ctx->currentReadable = read;
1232 SetCurrentContext(ctx);
1233 return True;
1234 }
1235 else {
1236 return False;
1237 }
1238 }
1239 else if (!ctx && !draw && !read) {
1240 /* release current context w/out assigning new one. */
1241 XMesaMakeCurrent2( NULL, NULL, NULL );
1242 MakeCurrent_PrevContext = 0;
1243 MakeCurrent_PrevDrawable = 0;
1244 MakeCurrent_PrevReadable = 0;
1245 MakeCurrent_PrevDrawBuffer = 0;
1246 MakeCurrent_PrevReadBuffer = 0;
1247 SetCurrentContext(NULL);
1248 return True;
1249 }
1250 else {
1251 /* The args must either all be non-zero or all zero.
1252 * This is an error.
1253 */
1254 return False;
1255 }
1256 }
1257
1258
1259 PUBLIC Bool
1260 glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx )
1261 {
1262 return glXMakeContextCurrent( dpy, drawable, drawable, ctx );
1263 }
1264
1265
1266 PUBLIC GLXContext
1267 glXGetCurrentContext(void)
1268 {
1269 return GetCurrentContext();
1270 }
1271
1272
1273 PUBLIC Display *
1274 glXGetCurrentDisplay(void)
1275 {
1276 GLXContext glxCtx = glXGetCurrentContext();
1277
1278 return glxCtx ? glxCtx->currentDpy : NULL;
1279 }
1280
1281
1282 PUBLIC Display *
1283 glXGetCurrentDisplayEXT(void)
1284 {
1285 return glXGetCurrentDisplay();
1286 }
1287
1288
1289 PUBLIC GLXDrawable
1290 glXGetCurrentDrawable(void)
1291 {
1292 GLXContext gc = glXGetCurrentContext();
1293 return gc ? gc->currentDrawable : 0;
1294 }
1295
1296
1297 PUBLIC GLXDrawable
1298 glXGetCurrentReadDrawable(void)
1299 {
1300 GLXContext gc = glXGetCurrentContext();
1301 return gc ? gc->currentReadable : 0;
1302 }
1303
1304
1305 PUBLIC GLXDrawable
1306 glXGetCurrentReadDrawableSGI(void)
1307 {
1308 return glXGetCurrentReadDrawable();
1309 }
1310
1311
1312 PUBLIC GLXPixmap
1313 glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, Pixmap pixmap )
1314 {
1315 XMesaVisual v;
1316 XMesaBuffer b;
1317
1318 v = find_glx_visual( dpy, visinfo );
1319 if (!v) {
1320 v = create_glx_visual( dpy, visinfo );
1321 if (!v) {
1322 /* unusable visual */
1323 return 0;
1324 }
1325 }
1326
1327 b = XMesaCreatePixmapBuffer( v, pixmap, 0 );
1328 if (!b) {
1329 return 0;
1330 }
1331 return b->ws.drawable;
1332 }
1333
1334
1335 /*** GLX_MESA_pixmap_colormap ***/
1336
1337 PUBLIC GLXPixmap
1338 glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo,
1339 Pixmap pixmap, Colormap cmap )
1340 {
1341 XMesaVisual v;
1342 XMesaBuffer b;
1343
1344 v = find_glx_visual( dpy, visinfo );
1345 if (!v) {
1346 v = create_glx_visual( dpy, visinfo );
1347 if (!v) {
1348 /* unusable visual */
1349 return 0;
1350 }
1351 }
1352
1353 b = XMesaCreatePixmapBuffer( v, pixmap, cmap );
1354 if (!b) {
1355 return 0;
1356 }
1357 return b->ws.drawable;
1358 }
1359
1360
1361 PUBLIC void
1362 glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap )
1363 {
1364 XMesaBuffer b = XMesaFindBuffer(dpy, pixmap);
1365 if (b) {
1366 XMesaDestroyBuffer(b);
1367 }
1368 else if (getenv("MESA_DEBUG")) {
1369 _mesa_warning(NULL, "Mesa: glXDestroyGLXPixmap: invalid pixmap\n");
1370 }
1371 }
1372
1373
1374 PUBLIC void
1375 glXCopyContext( Display *dpy, GLXContext src, GLXContext dst,
1376 unsigned long mask )
1377 {
1378 XMesaContext xm_src = src->xmesaContext;
1379 XMesaContext xm_dst = dst->xmesaContext;
1380 (void) dpy;
1381 if (MakeCurrent_PrevContext == src) {
1382 glFlush();
1383 }
1384 XMesaCopyContext(xm_src, xm_dst, mask);
1385 }
1386
1387
1388 PUBLIC Bool
1389 glXQueryExtension( Display *dpy, int *errorBase, int *eventBase )
1390 {
1391 int op, ev, err;
1392 /* Mesa's GLX isn't really an X extension but we try to act like one. */
1393 if (!XQueryExtension(dpy, GLX_EXTENSION_NAME, &op, &ev, &err))
1394 ev = err = 0;
1395 if (errorBase)
1396 *errorBase = err;
1397 if (eventBase)
1398 *eventBase = ev;
1399 return True; /* we're faking GLX so always return success */
1400 }
1401
1402
1403 PUBLIC void
1404 glXDestroyContext( Display *dpy, GLXContext ctx )
1405 {
1406 if (ctx) {
1407 GLXContext glxCtx = ctx;
1408 (void) dpy;
1409 MakeCurrent_PrevContext = 0;
1410 MakeCurrent_PrevDrawable = 0;
1411 MakeCurrent_PrevReadable = 0;
1412 MakeCurrent_PrevDrawBuffer = 0;
1413 MakeCurrent_PrevReadBuffer = 0;
1414 XMesaDestroyContext( glxCtx->xmesaContext );
1415 XMesaGarbageCollect();
1416 free(glxCtx);
1417 }
1418 }
1419
1420
1421 PUBLIC Bool
1422 glXIsDirect( Display *dpy, GLXContext ctx )
1423 {
1424 return ctx ? ctx->isDirect : False;
1425 }
1426
1427
1428
1429 PUBLIC void
1430 glXSwapBuffers( Display *dpy, GLXDrawable drawable )
1431 {
1432 XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable );
1433 static boolean firsttime = 1, no_rast = 0;
1434
1435 if (firsttime) {
1436 no_rast = getenv("SP_NO_RAST") != NULL;
1437 firsttime = 0;
1438 }
1439
1440 if (no_rast)
1441 return;
1442
1443 if (buffer) {
1444 XMesaSwapBuffers(buffer);
1445 }
1446 else if (getenv("MESA_DEBUG")) {
1447 _mesa_warning(NULL, "glXSwapBuffers: invalid drawable 0x%x\n",
1448 (int) drawable);
1449 }
1450 }
1451
1452
1453
1454 /*** GLX_MESA_copy_sub_buffer ***/
1455
1456 PUBLIC void
1457 glXCopySubBufferMESA(Display *dpy, GLXDrawable drawable,
1458 int x, int y, int width, int height)
1459 {
1460 XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable );
1461 if (buffer) {
1462 XMesaCopySubBuffer(buffer, x, y, width, height);
1463 }
1464 else if (getenv("MESA_DEBUG")) {
1465 _mesa_warning(NULL, "Mesa: glXCopySubBufferMESA: invalid drawable\n");
1466 }
1467 }
1468
1469
1470 PUBLIC Bool
1471 glXQueryVersion( Display *dpy, int *maj, int *min )
1472 {
1473 (void) dpy;
1474 /* Return GLX version, not Mesa version */
1475 assert(CLIENT_MAJOR_VERSION == SERVER_MAJOR_VERSION);
1476 *maj = CLIENT_MAJOR_VERSION;
1477 *min = MIN2( CLIENT_MINOR_VERSION, SERVER_MINOR_VERSION );
1478 return True;
1479 }
1480
1481
1482 /*
1483 * Query the GLX attributes of the given XVisualInfo.
1484 */
1485 static int
1486 get_config( XMesaVisual xmvis, int attrib, int *value, GLboolean fbconfig )
1487 {
1488 assert(xmvis);
1489 switch(attrib) {
1490 case GLX_USE_GL:
1491 if (fbconfig)
1492 return GLX_BAD_ATTRIBUTE;
1493 *value = (int) True;
1494 return 0;
1495 case GLX_BUFFER_SIZE:
1496 *value = xmvis->visinfo->depth;
1497 return 0;
1498 case GLX_LEVEL:
1499 *value = xmvis->mesa_visual.level;
1500 return 0;
1501 case GLX_RGBA:
1502 if (fbconfig)
1503 return GLX_BAD_ATTRIBUTE;
1504 if (xmvis->mesa_visual.rgbMode) {
1505 *value = True;
1506 }
1507 else {
1508 *value = False;
1509 }
1510 return 0;
1511 case GLX_DOUBLEBUFFER:
1512 *value = (int) xmvis->mesa_visual.doubleBufferMode;
1513 return 0;
1514 case GLX_STEREO:
1515 *value = (int) xmvis->mesa_visual.stereoMode;
1516 return 0;
1517 case GLX_AUX_BUFFERS:
1518 *value = xmvis->mesa_visual.numAuxBuffers;
1519 return 0;
1520 case GLX_RED_SIZE:
1521 *value = xmvis->mesa_visual.redBits;
1522 return 0;
1523 case GLX_GREEN_SIZE:
1524 *value = xmvis->mesa_visual.greenBits;
1525 return 0;
1526 case GLX_BLUE_SIZE:
1527 *value = xmvis->mesa_visual.blueBits;
1528 return 0;
1529 case GLX_ALPHA_SIZE:
1530 *value = xmvis->mesa_visual.alphaBits;
1531 return 0;
1532 case GLX_DEPTH_SIZE:
1533 *value = xmvis->mesa_visual.depthBits;
1534 return 0;
1535 case GLX_STENCIL_SIZE:
1536 *value = xmvis->mesa_visual.stencilBits;
1537 return 0;
1538 case GLX_ACCUM_RED_SIZE:
1539 *value = xmvis->mesa_visual.accumRedBits;
1540 return 0;
1541 case GLX_ACCUM_GREEN_SIZE:
1542 *value = xmvis->mesa_visual.accumGreenBits;
1543 return 0;
1544 case GLX_ACCUM_BLUE_SIZE:
1545 *value = xmvis->mesa_visual.accumBlueBits;
1546 return 0;
1547 case GLX_ACCUM_ALPHA_SIZE:
1548 *value = xmvis->mesa_visual.accumAlphaBits;
1549 return 0;
1550
1551 /*
1552 * GLX_EXT_visual_info extension
1553 */
1554 case GLX_X_VISUAL_TYPE_EXT:
1555 switch (xmvis->visinfo->CLASS) {
1556 case StaticGray: *value = GLX_STATIC_GRAY_EXT; return 0;
1557 case GrayScale: *value = GLX_GRAY_SCALE_EXT; return 0;
1558 case StaticColor: *value = GLX_STATIC_GRAY_EXT; return 0;
1559 case PseudoColor: *value = GLX_PSEUDO_COLOR_EXT; return 0;
1560 case TrueColor: *value = GLX_TRUE_COLOR_EXT; return 0;
1561 case DirectColor: *value = GLX_DIRECT_COLOR_EXT; return 0;
1562 }
1563 return 0;
1564 case GLX_TRANSPARENT_TYPE_EXT:
1565 /* normal planes */
1566 *value = GLX_NONE_EXT;
1567 return 0;
1568 case GLX_TRANSPARENT_INDEX_VALUE_EXT:
1569 /* undefined */
1570 return 0;
1571 case GLX_TRANSPARENT_RED_VALUE_EXT:
1572 /* undefined */
1573 return 0;
1574 case GLX_TRANSPARENT_GREEN_VALUE_EXT:
1575 /* undefined */
1576 return 0;
1577 case GLX_TRANSPARENT_BLUE_VALUE_EXT:
1578 /* undefined */
1579 return 0;
1580 case GLX_TRANSPARENT_ALPHA_VALUE_EXT:
1581 /* undefined */
1582 return 0;
1583
1584 /*
1585 * GLX_EXT_visual_info extension
1586 */
1587 case GLX_VISUAL_CAVEAT_EXT:
1588 /* test for zero, just in case */
1589 if (xmvis->mesa_visual.visualRating > 0)
1590 *value = xmvis->mesa_visual.visualRating;
1591 else
1592 *value = GLX_NONE_EXT;
1593 return 0;
1594
1595 /*
1596 * GLX_ARB_multisample
1597 */
1598 case GLX_SAMPLE_BUFFERS_ARB:
1599 *value = 0;
1600 return 0;
1601 case GLX_SAMPLES_ARB:
1602 *value = 0;
1603 return 0;
1604
1605 /*
1606 * For FBConfigs:
1607 */
1608 case GLX_SCREEN_EXT:
1609 if (!fbconfig)
1610 return GLX_BAD_ATTRIBUTE;
1611 *value = xmvis->visinfo->screen;
1612 break;
1613 case GLX_DRAWABLE_TYPE: /*SGIX too */
1614 if (!fbconfig)
1615 return GLX_BAD_ATTRIBUTE;
1616 *value = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;
1617 break;
1618 case GLX_RENDER_TYPE_SGIX:
1619 if (!fbconfig)
1620 return GLX_BAD_ATTRIBUTE;
1621 if (xmvis->mesa_visual.rgbMode)
1622 *value = GLX_RGBA_BIT;
1623 else
1624 *value = GLX_COLOR_INDEX_BIT;
1625 break;
1626 case GLX_X_RENDERABLE_SGIX:
1627 if (!fbconfig)
1628 return GLX_BAD_ATTRIBUTE;
1629 *value = True; /* XXX really? */
1630 break;
1631 case GLX_FBCONFIG_ID_SGIX:
1632 if (!fbconfig)
1633 return GLX_BAD_ATTRIBUTE;
1634 *value = xmvis->visinfo->visualid;
1635 break;
1636 case GLX_MAX_PBUFFER_WIDTH:
1637 if (!fbconfig)
1638 return GLX_BAD_ATTRIBUTE;
1639 /* XXX or MAX_WIDTH? */
1640 *value = DisplayWidth(xmvis->display, xmvis->visinfo->screen);
1641 break;
1642 case GLX_MAX_PBUFFER_HEIGHT:
1643 if (!fbconfig)
1644 return GLX_BAD_ATTRIBUTE;
1645 *value = DisplayHeight(xmvis->display, xmvis->visinfo->screen);
1646 break;
1647 case GLX_MAX_PBUFFER_PIXELS:
1648 if (!fbconfig)
1649 return GLX_BAD_ATTRIBUTE;
1650 *value = DisplayWidth(xmvis->display, xmvis->visinfo->screen) *
1651 DisplayHeight(xmvis->display, xmvis->visinfo->screen);
1652 break;
1653 case GLX_VISUAL_ID:
1654 if (!fbconfig)
1655 return GLX_BAD_ATTRIBUTE;
1656 *value = xmvis->visinfo->visualid;
1657 break;
1658
1659 #ifdef GLX_EXT_texture_from_pixmap
1660 case GLX_BIND_TO_TEXTURE_RGB_EXT:
1661 *value = True; /*XXX*/
1662 break;
1663 case GLX_BIND_TO_TEXTURE_RGBA_EXT:
1664 /* XXX review */
1665 *value = xmvis->mesa_visual.alphaBits > 0 ? True : False;
1666 break;
1667 case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:
1668 *value = True; /*XXX*/
1669 break;
1670 case GLX_BIND_TO_TEXTURE_TARGETS_EXT:
1671 *value = (GLX_TEXTURE_1D_BIT_EXT |
1672 GLX_TEXTURE_2D_BIT_EXT |
1673 GLX_TEXTURE_RECTANGLE_BIT_EXT); /*XXX*/
1674 break;
1675 case GLX_Y_INVERTED_EXT:
1676 *value = True; /*XXX*/
1677 break;
1678 #endif
1679
1680 default:
1681 return GLX_BAD_ATTRIBUTE;
1682 }
1683 return Success;
1684 }
1685
1686
1687 PUBLIC int
1688 glXGetConfig( Display *dpy, XVisualInfo *visinfo,
1689 int attrib, int *value )
1690 {
1691 XMesaVisual xmvis;
1692 int k;
1693 if (!dpy || !visinfo)
1694 return GLX_BAD_ATTRIBUTE;
1695
1696 xmvis = find_glx_visual( dpy, visinfo );
1697 if (!xmvis) {
1698 /* this visual wasn't obtained with glXChooseVisual */
1699 xmvis = create_glx_visual( dpy, visinfo );
1700 if (!xmvis) {
1701 /* this visual can't be used for GL rendering */
1702 if (attrib==GLX_USE_GL) {
1703 *value = (int) False;
1704 return 0;
1705 }
1706 else {
1707 return GLX_BAD_VISUAL;
1708 }
1709 }
1710 }
1711
1712 k = get_config(xmvis, attrib, value, GL_FALSE);
1713 return k;
1714 }
1715
1716
1717 PUBLIC void
1718 glXWaitGL( void )
1719 {
1720 XMesaContext xmesa = XMesaGetCurrentContext();
1721 XMesaFlush( xmesa );
1722 }
1723
1724
1725
1726 PUBLIC void
1727 glXWaitX( void )
1728 {
1729 XMesaContext xmesa = XMesaGetCurrentContext();
1730 XMesaFlush( xmesa );
1731 }
1732
1733
1734 static const char *
1735 get_extensions( void )
1736 {
1737 return EXTENSIONS;
1738 }
1739
1740
1741
1742 /* GLX 1.1 and later */
1743 PUBLIC const char *
1744 glXQueryExtensionsString( Display *dpy, int screen )
1745 {
1746 (void) dpy;
1747 (void) screen;
1748 return get_extensions();
1749 }
1750
1751
1752
1753 /* GLX 1.1 and later */
1754 PUBLIC const char *
1755 glXQueryServerString( Display *dpy, int screen, int name )
1756 {
1757 static char version[1000];
1758 sprintf(version, "%d.%d %s",
1759 SERVER_MAJOR_VERSION, SERVER_MINOR_VERSION, xmesa_get_name());
1760
1761 (void) dpy;
1762 (void) screen;
1763
1764 switch (name) {
1765 case GLX_EXTENSIONS:
1766 return get_extensions();
1767 case GLX_VENDOR:
1768 return VENDOR;
1769 case GLX_VERSION:
1770 return version;
1771 default:
1772 return NULL;
1773 }
1774 }
1775
1776
1777
1778 /* GLX 1.1 and later */
1779 PUBLIC const char *
1780 glXGetClientString( Display *dpy, int name )
1781 {
1782 static char version[1000];
1783 sprintf(version, "%d.%d %s", CLIENT_MAJOR_VERSION,
1784 CLIENT_MINOR_VERSION, xmesa_get_name());
1785
1786 (void) dpy;
1787
1788 switch (name) {
1789 case GLX_EXTENSIONS:
1790 return get_extensions();
1791 case GLX_VENDOR:
1792 return VENDOR;
1793 case GLX_VERSION:
1794 return version;
1795 default:
1796 return NULL;
1797 }
1798 }
1799
1800
1801
1802 /*
1803 * GLX 1.3 and later
1804 */
1805
1806
1807 PUBLIC int
1808 glXGetFBConfigAttrib(Display *dpy, GLXFBConfig config,
1809 int attribute, int *value)
1810 {
1811 XMesaVisual v = (XMesaVisual) config;
1812 (void) dpy;
1813 (void) config;
1814
1815 if (!dpy || !config || !value)
1816 return -1;
1817
1818 return get_config(v, attribute, value, GL_TRUE);
1819 }
1820
1821
1822 PUBLIC GLXFBConfig *
1823 glXGetFBConfigs( Display *dpy, int screen, int *nelements )
1824 {
1825 XVisualInfo *visuals, visTemplate;
1826 const long visMask = VisualScreenMask;
1827 int i;
1828
1829 /* Get list of all X visuals */
1830 visTemplate.screen = screen;
1831 visuals = XGetVisualInfo(dpy, visMask, &visTemplate, nelements);
1832 if (*nelements > 0) {
1833 XMesaVisual *results = 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 = 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 = 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 }