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