variety of updates to better conform to real GLX
[mesa.git] / src / mesa / drivers / x11 / fakeglx.c
1 /* $Id: fakeglx.c,v 1.34 2000/06/08 22:50:28 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.3
6 *
7 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28 /*
29 * This is an emulation of the GLX API which allows Mesa/GLX-based programs
30 * to run on X servers which do not have the real GLX extension.
31 *
32 * Thanks to the contributors:
33 *
34 * Initial version: Philip Brown (philb@CSUA.Berkeley.EDU)
35 * Better glXGetConfig() support: Armin Liebchen (liebchen@asylum.cs.utah.edu)
36 * Further visual-handling refinements: Wolfram Gloger
37 * (wmglo@Dent.MED.Uni-Muenchen.DE).
38 *
39 * Notes:
40 * Don't be fooled, stereo isn't supported yet.
41 */
42
43
44
45 #include "glxheader.h"
46 #include "glxapi.h"
47 #include "GL/xmesa.h"
48 #include "context.h"
49 #include "config.h"
50 #include "macros.h"
51 #include "mmath.h"
52 #include "types.h"
53 #include "xfonts.h"
54 #include "xmesaP.h"
55
56
57 /* This indicates the client-side GLX API and GLX encoder version. */
58 #define CLIENT_MAJOR_VERSION 1
59 #define CLIENT_MINOR_VERSION 2
60
61 /* This indicates the server-side GLX decoder version.
62 * GLX 1.3 indicates OpenGL 1.2 support
63 */
64 #define SERVER_MAJOR_VERSION 1
65 #define SERVER_MINOR_VERSION 3
66
67 /* This is appended onto the glXGetClient/ServerString version strings. */
68 #define MESA_GLX_VERSION "Mesa 3.3"
69
70 /* Who implemented this GLX? */
71 #define VENDOR "Brian Paul"
72
73
74
75 /* Silence compiler warnings */
76 extern void Fake_glXDummyFunc( void );
77 void Fake_glXDummyFunc( void )
78 {
79 (void) kernel8;
80 (void) DitherValues;
81 (void) HPCR_DRGB;
82 (void) kernel1;
83 }
84
85
86
87 #define DONT_CARE -1
88
89
90
91 #define MAX_VISUALS 100
92 static XMesaVisual VisualTable[MAX_VISUALS];
93 static int NumVisuals = 0;
94
95
96
97 /*
98 * This struct and some code fragments borrowed
99 * from Mark Kilgard's GLUT library.
100 */
101 typedef struct _OverlayInfo {
102 /* Avoid 64-bit portability problems by being careful to use
103 longs due to the way XGetWindowProperty is specified. Note
104 that these parameters are passed as CARD32s over X
105 protocol. */
106 unsigned long overlay_visual;
107 long transparent_type;
108 long value;
109 long layer;
110 } OverlayInfo;
111
112
113
114 /* Macro to handle c_class vs class field name in XVisualInfo struct */
115 #if defined(__cplusplus) || defined(c_plusplus)
116 #define CLASS c_class
117 #else
118 #define CLASS class
119 #endif
120
121
122
123
124 /*
125 * Test if the given XVisualInfo is usable for Mesa rendering.
126 */
127 static GLboolean is_usable_visual( XVisualInfo *vinfo )
128 {
129 switch (vinfo->CLASS) {
130 case StaticGray:
131 case GrayScale:
132 /* Any StaticGray/GrayScale visual works in RGB or CI mode */
133 return GL_TRUE;
134 case StaticColor:
135 case PseudoColor:
136 /* Any StaticColor/PseudoColor visual of at least 4 bits */
137 if (vinfo->depth>=4) {
138 return GL_TRUE;
139 }
140 else {
141 return GL_FALSE;
142 }
143 case TrueColor:
144 case DirectColor:
145 /* Any depth of TrueColor or DirectColor works in RGB mode */
146 return GL_TRUE;
147 default:
148 /* This should never happen */
149 return GL_FALSE;
150 }
151 }
152
153
154
155 /*
156 * Return the level (overlay, normal, underlay) of a given XVisualInfo.
157 * Input: dpy - the X display
158 * vinfo - the XVisualInfo to test
159 * Return: level of the visual:
160 * 0 = normal planes
161 * >0 = overlay planes
162 * <0 = underlay planes
163 */
164 static int level_of_visual( Display *dpy, XVisualInfo *vinfo )
165 {
166 Atom overlayVisualsAtom;
167 OverlayInfo *overlay_info = NULL;
168 int numOverlaysPerScreen;
169 Status status;
170 Atom actualType;
171 int actualFormat;
172 unsigned long sizeData, bytesLeft;
173 int i;
174
175 /*
176 * The SERVER_OVERLAY_VISUALS property on the root window contains
177 * a list of overlay visuals. Get that list now.
178 */
179 overlayVisualsAtom = XInternAtom(dpy,"SERVER_OVERLAY_VISUALS", True);
180 if (overlayVisualsAtom == None) {
181 return 0;
182 }
183
184 status = XGetWindowProperty(dpy, RootWindow( dpy, vinfo->screen ),
185 overlayVisualsAtom, 0L, (long) 10000, False,
186 overlayVisualsAtom, &actualType, &actualFormat,
187 &sizeData, &bytesLeft,
188 (unsigned char **) &overlay_info );
189
190 if (status != Success || actualType != overlayVisualsAtom ||
191 actualFormat != 32 || sizeData < 4) {
192 /* something went wrong */
193 XFree((void *) overlay_info);
194 return 0;
195 }
196
197 /* search the overlay visual list for the visual ID of interest */
198 numOverlaysPerScreen = (int) (sizeData / 4);
199 for (i=0;i<numOverlaysPerScreen;i++) {
200 OverlayInfo *ov;
201 ov = overlay_info + i;
202 if (ov->overlay_visual==vinfo->visualid) {
203 /* found the visual */
204 if (/*ov->transparent_type==1 &&*/ ov->layer!=0) {
205 int level = ov->layer;
206 XFree((void *) overlay_info);
207 return level;
208 }
209 else {
210 XFree((void *) overlay_info);
211 return 0;
212 }
213 }
214 }
215
216 /* The visual ID was not found in the overlay list. */
217 XFree((void *) overlay_info);
218 return 0;
219 }
220
221
222
223
224 /*
225 * Given an XVisualInfo and RGB, Double, and Depth buffer flags, save the
226 * configuration in our list of GLX visuals.
227 */
228 static XMesaVisual
229 save_glx_visual( Display *dpy, XVisualInfo *vinfo,
230 GLboolean rgbFlag, GLboolean alphaFlag, GLboolean dbFlag,
231 GLboolean stereoFlag,
232 GLint depth_size, GLint stencil_size,
233 GLint accumRedSize, GLint accumGreenSize,
234 GLint accumBlueSize, GLint accumAlphaSize,
235 GLint level )
236 {
237 GLboolean ximageFlag = GL_TRUE;
238 XMesaVisual xmvis;
239 GLint i;
240 GLboolean comparePointers;
241
242 if (dbFlag) {
243 /* Check if the MESA_BACK_BUFFER env var is set */
244 char *backbuffer = getenv("MESA_BACK_BUFFER");
245 if (backbuffer) {
246 if (backbuffer[0]=='p' || backbuffer[0]=='P') {
247 ximageFlag = GL_FALSE;
248 }
249 else if (backbuffer[0]=='x' || backbuffer[0]=='X') {
250 ximageFlag = GL_TRUE;
251 }
252 else {
253 fprintf(stderr, "Mesa: invalid value for MESA_BACK_BUFFER ");
254 fprintf(stderr, "environment variable, using an XImage.\n");
255 }
256 }
257 }
258
259 /* Comparing IDs uses less memory but sometimes fails. */
260 /* XXX revisit this after 3.0 is finished. */
261 if (getenv("MESA_GLX_VISUAL_HACK"))
262 comparePointers = GL_TRUE;
263 else
264 comparePointers = GL_FALSE;
265
266 /* First check if a matching visual is already in the list */
267 for (i=0; i<NumVisuals; i++) {
268 XMesaVisual v = VisualTable[i];
269 if (v->display == dpy
270 && v->level == level
271 && v->ximage_flag == ximageFlag
272 && v->gl_visual->RGBAflag == rgbFlag
273 && v->gl_visual->DBflag == dbFlag
274 && v->gl_visual->StereoFlag == stereoFlag
275 && (v->gl_visual->AlphaBits > 0) == alphaFlag
276 && (v->gl_visual->DepthBits >= depth_size || depth_size == 0)
277 && (v->gl_visual->StencilBits >= stencil_size || stencil_size == 0)
278 && (v->gl_visual->AccumRedBits >= accumRedSize || accumRedSize == 0)
279 && (v->gl_visual->AccumGreenBits >= accumGreenSize || accumGreenSize == 0)
280 && (v->gl_visual->AccumBlueBits >= accumBlueSize || accumBlueSize == 0)
281 && (v->gl_visual->AccumAlphaBits >= accumAlphaSize || accumAlphaSize == 0)) {
282 /* now either compare XVisualInfo pointers or visual IDs */
283 if ((!comparePointers && v->visinfo->visualid == vinfo->visualid)
284 || (comparePointers && v->vishandle == vinfo)) {
285 return v;
286 }
287 }
288 }
289
290 /* Create a new visual and add it to the list. */
291
292 if (NumVisuals>=MAX_VISUALS) {
293 fprintf( stderr, "GLX Error: maximum number of visuals exceeded\n");
294 return NULL;
295 }
296
297 xmvis = XMesaCreateVisual( dpy, vinfo, rgbFlag, alphaFlag, dbFlag,
298 stereoFlag, ximageFlag,
299 depth_size, stencil_size,
300 accumRedSize, accumBlueSize,
301 accumBlueSize, accumAlphaSize, 0, level,
302 GLX_NONE_EXT );
303 if (xmvis) {
304 VisualTable[NumVisuals] = xmvis;
305 NumVisuals++;
306 }
307 return xmvis;
308 }
309
310
311
312 /*
313 * Create a GLX visual from a regular XVisualInfo.
314 * This is called when Fake GLX is given an XVisualInfo which wasn't
315 * returned by glXChooseVisual. Since this is the first time we're
316 * considering this visual we'll take a guess at reasonable values
317 * for depth buffer size, stencil size, accum size, etc.
318 * This is the best we can do with a client-side emulation of GLX.
319 */
320 static XMesaVisual
321 create_glx_visual( Display *dpy, XVisualInfo *visinfo )
322 {
323 int vislevel;
324
325 vislevel = level_of_visual( dpy, visinfo );
326 if (vislevel) {
327 /* Configure this visual as a CI, single-buffered overlay */
328 return save_glx_visual( dpy, visinfo,
329 GL_FALSE, /* rgb */
330 GL_FALSE, /* alpha */
331 GL_FALSE, /* double */
332 GL_FALSE, /* stereo */
333 0, /* depth bits */
334 0, /* stencil bits */
335 0,0,0,0, /* accum bits */
336 vislevel /* level */
337 );
338 }
339 else if (is_usable_visual( visinfo )) {
340 /* Configure this visual as RGB, double-buffered, depth-buffered. */
341 /* This is surely wrong for some people's needs but what else */
342 /* can be done? They should use glXChooseVisual(). */
343 return save_glx_visual( dpy, visinfo,
344 GL_TRUE, /* rgb */
345 GL_FALSE, /* alpha */
346 GL_TRUE, /* double */
347 GL_FALSE, /* stereo */
348 DEFAULT_SOFTWARE_DEPTH_BITS,
349 8 * sizeof(GLstencil),
350 8 * sizeof(GLaccum), /* r */
351 8 * sizeof(GLaccum), /* g */
352 8 * sizeof(GLaccum), /* b */
353 8 * sizeof(GLaccum), /* a */
354 0 /* level */
355 );
356 }
357 else {
358 fprintf(stderr,"Mesa: error in glXCreateContext: bad visual\n");
359 return NULL;
360 }
361 }
362
363
364
365 /*
366 * Find the GLX visual associated with an XVisualInfo.
367 */
368 static XMesaVisual
369 find_glx_visual( Display *dpy, XVisualInfo *vinfo )
370 {
371 int i;
372
373 /* First try to match pointers */
374 for (i=0;i<NumVisuals;i++) {
375 if (VisualTable[i]->display==dpy && VisualTable[i]->vishandle==vinfo) {
376 return VisualTable[i];
377 }
378 }
379 /* try to match visual id */
380 for (i=0;i<NumVisuals;i++) {
381 if (VisualTable[i]->display==dpy
382 && VisualTable[i]->visinfo->visualid == vinfo->visualid) {
383 return VisualTable[i];
384 }
385 }
386 return NULL;
387 }
388
389
390
391 /*
392 * Return the transparent pixel value for a GLX visual.
393 * Input: glxvis - the glx_visual
394 * Return: a pixel value or -1 if no transparent pixel
395 */
396 static int transparent_pixel( XMesaVisual glxvis )
397 {
398 Display *dpy = glxvis->display;
399 XVisualInfo *vinfo = glxvis->visinfo;
400 Atom overlayVisualsAtom;
401 OverlayInfo *overlay_info = NULL;
402 int numOverlaysPerScreen;
403 Status status;
404 Atom actualType;
405 int actualFormat;
406 unsigned long sizeData, bytesLeft;
407 int i;
408
409 /*
410 * The SERVER_OVERLAY_VISUALS property on the root window contains
411 * a list of overlay visuals. Get that list now.
412 */
413 overlayVisualsAtom = XInternAtom(dpy,"SERVER_OVERLAY_VISUALS", True);
414 if (overlayVisualsAtom == None) {
415 return -1;
416 }
417
418 status = XGetWindowProperty(dpy, RootWindow( dpy, vinfo->screen ),
419 overlayVisualsAtom, 0L, (long) 10000, False,
420 overlayVisualsAtom, &actualType, &actualFormat,
421 &sizeData, &bytesLeft,
422 (unsigned char **) &overlay_info );
423
424 if (status != Success || actualType != overlayVisualsAtom ||
425 actualFormat != 32 || sizeData < 4) {
426 /* something went wrong */
427 XFree((void *) overlay_info);
428 return -1;
429 }
430
431 /* search the overlay visual list for the visual ID of interest */
432 numOverlaysPerScreen = (int) (sizeData / 4);
433 for (i=0;i<numOverlaysPerScreen;i++) {
434 OverlayInfo *ov;
435 ov = overlay_info + i;
436 if (ov->overlay_visual==vinfo->visualid) {
437 /* found it! */
438 if (ov->transparent_type==0) {
439 /* type 0 indicates no transparency */
440 XFree((void *) overlay_info);
441 return -1;
442 }
443 else {
444 /* ov->value is the transparent pixel */
445 XFree((void *) overlay_info);
446 return ov->value;
447 }
448 }
449 }
450
451 /* The visual ID was not found in the overlay list. */
452 XFree((void *) overlay_info);
453 return -1;
454 }
455
456
457
458 /*
459 * Try to get an X visual which matches the given arguments.
460 */
461 static XVisualInfo *get_visual( Display *dpy, int scr,
462 unsigned int depth, int xclass )
463 {
464 XVisualInfo temp, *vis;
465 long mask;
466 int n;
467 unsigned int default_depth;
468 int default_class;
469
470 mask = VisualScreenMask | VisualDepthMask | VisualClassMask;
471 temp.screen = scr;
472 temp.depth = depth;
473 temp.CLASS = xclass;
474
475 default_depth = DefaultDepth(dpy,scr);
476 default_class = DefaultVisual(dpy,scr)->CLASS;
477
478 if (depth==default_depth && xclass==default_class) {
479 /* try to get root window's visual */
480 temp.visualid = DefaultVisual(dpy,scr)->visualid;
481 mask |= VisualIDMask;
482 }
483
484 vis = XGetVisualInfo( dpy, mask, &temp, &n );
485
486 /* In case bits/pixel > 24, make sure color channels are still <=8 bits.
487 * An SGI Infinite Reality system, for example, can have 30bpp pixels:
488 * 10 bits per color channel. Mesa's limited to a max of 8 bits/channel.
489 */
490 if (vis && depth > 24 && (xclass==TrueColor || xclass==DirectColor)) {
491 if (_mesa_bitcount((GLuint) vis->red_mask ) <= 8 &&
492 _mesa_bitcount((GLuint) vis->green_mask) <= 8 &&
493 _mesa_bitcount((GLuint) vis->blue_mask ) <= 8) {
494 return vis;
495 }
496 else {
497 XFree((void *) vis);
498 return NULL;
499 }
500 }
501
502 return vis;
503 }
504
505
506
507 /*
508 * Retrieve the value of the given environment variable and find
509 * the X visual which matches it.
510 * Input: dpy - the display
511 * screen - the screen number
512 * varname - the name of the environment variable
513 * Return: an XVisualInfo pointer to NULL if error.
514 */
515 static XVisualInfo *get_env_visual(Display *dpy, int scr, const char *varname)
516 {
517 char value[100], type[100];
518 int depth, xclass = -1;
519 XVisualInfo *vis;
520
521 if (!getenv( varname )) {
522 return NULL;
523 }
524
525 strncpy( value, getenv(varname), 100 );
526 value[99] = 0;
527
528 sscanf( value, "%s %d", type, &depth );
529
530 if (strcmp(type,"TrueColor")==0) xclass = TrueColor;
531 else if (strcmp(type,"DirectColor")==0) xclass = DirectColor;
532 else if (strcmp(type,"PseudoColor")==0) xclass = PseudoColor;
533 else if (strcmp(type,"StaticColor")==0) xclass = StaticColor;
534 else if (strcmp(type,"GrayScale")==0) xclass = GrayScale;
535 else if (strcmp(type,"StaticGray")==0) xclass = StaticGray;
536
537 if (xclass>-1 && depth>0) {
538 vis = get_visual( dpy, scr, depth, xclass );
539 if (vis) {
540 return vis;
541 }
542 }
543
544 fprintf( stderr, "Mesa: GLX unable to find visual class=%s, depth=%d.\n",
545 type, depth );
546 return NULL;
547 }
548
549
550
551 /*
552 * Select an X visual which satisfies the RGBA/CI flag and minimum depth.
553 * Input: dpy, screen - X display and screen number
554 * rgba - GL_TRUE = RGBA mode, GL_FALSE = CI mode
555 * min_depth - minimum visual depth
556 * preferred_class - preferred GLX visual class or DONT_CARE
557 * Return: pointer to an XVisualInfo or NULL.
558 */
559 static XVisualInfo *choose_x_visual( Display *dpy, int screen,
560 GLboolean rgba, int min_depth,
561 int preferred_class )
562 {
563 XVisualInfo *vis;
564 int xclass, visclass;
565 int depth;
566
567 if (rgba) {
568 Atom hp_cr_maps = XInternAtom(dpy, "_HP_RGB_SMOOTH_MAP_LIST", True);
569 /* First see if the MESA_RGB_VISUAL env var is defined */
570 vis = get_env_visual( dpy, screen, "MESA_RGB_VISUAL" );
571 if (vis) {
572 return vis;
573 }
574 /* Otherwise, search for a suitable visual */
575 if (preferred_class==DONT_CARE) {
576 for (xclass=0;xclass<6;xclass++) {
577 switch (xclass) {
578 case 0: visclass = TrueColor; break;
579 case 1: visclass = DirectColor; break;
580 case 2: visclass = PseudoColor; break;
581 case 3: visclass = StaticColor; break;
582 case 4: visclass = GrayScale; break;
583 case 5: visclass = StaticGray; break;
584 }
585 if (min_depth==0) {
586 /* start with shallowest */
587 for (depth=0;depth<=32;depth++) {
588 if (visclass==TrueColor && depth==8 && !hp_cr_maps) {
589 /* Special case: try to get 8-bit PseudoColor before */
590 /* 8-bit TrueColor */
591 vis = get_visual( dpy, screen, 8, PseudoColor );
592 if (vis) {
593 return vis;
594 }
595 }
596 vis = get_visual( dpy, screen, depth, visclass );
597 if (vis) {
598 return vis;
599 }
600 }
601 }
602 else {
603 /* start with deepest */
604 for (depth=32;depth>=min_depth;depth--) {
605 if (visclass==TrueColor && depth==8 && !hp_cr_maps) {
606 /* Special case: try to get 8-bit PseudoColor before */
607 /* 8-bit TrueColor */
608 vis = get_visual( dpy, screen, 8, PseudoColor );
609 if (vis) {
610 return vis;
611 }
612 }
613 vis = get_visual( dpy, screen, depth, visclass );
614 if (vis) {
615 return vis;
616 }
617 }
618 }
619 }
620 }
621 else {
622 /* search for a specific visual class */
623 switch (preferred_class) {
624 case GLX_TRUE_COLOR_EXT: visclass = TrueColor; break;
625 case GLX_DIRECT_COLOR_EXT: visclass = DirectColor; break;
626 case GLX_PSEUDO_COLOR_EXT: visclass = PseudoColor; break;
627 case GLX_STATIC_COLOR_EXT: visclass = StaticColor; break;
628 case GLX_GRAY_SCALE_EXT: visclass = GrayScale; break;
629 case GLX_STATIC_GRAY_EXT: visclass = StaticGray; break;
630 default: return NULL;
631 }
632 if (min_depth==0) {
633 /* start with shallowest */
634 for (depth=0;depth<=32;depth++) {
635 vis = get_visual( dpy, screen, depth, visclass );
636 if (vis) {
637 return vis;
638 }
639 }
640 }
641 else {
642 /* start with deepest */
643 for (depth=32;depth>=min_depth;depth--) {
644 vis = get_visual( dpy, screen, depth, visclass );
645 if (vis) {
646 return vis;
647 }
648 }
649 }
650 }
651 }
652 else {
653 /* First see if the MESA_CI_VISUAL env var is defined */
654 vis = get_env_visual( dpy, screen, "MESA_CI_VISUAL" );
655 if (vis) {
656 return vis;
657 }
658 /* Otherwise, search for a suitable visual, starting with shallowest */
659 if (preferred_class==DONT_CARE) {
660 for (xclass=0;xclass<4;xclass++) {
661 switch (xclass) {
662 case 0: visclass = PseudoColor; break;
663 case 1: visclass = StaticColor; break;
664 case 2: visclass = GrayScale; break;
665 case 3: visclass = StaticGray; break;
666 }
667 /* try 8-bit up through 16-bit */
668 for (depth=8;depth<=16;depth++) {
669 vis = get_visual( dpy, screen, depth, visclass );
670 if (vis) {
671 return vis;
672 }
673 }
674 /* try min_depth up to 8-bit */
675 for (depth=min_depth;depth<8;depth++) {
676 vis = get_visual( dpy, screen, depth, visclass );
677 if (vis) {
678 return vis;
679 }
680 }
681 }
682 }
683 else {
684 /* search for a specific visual class */
685 switch (preferred_class) {
686 case GLX_TRUE_COLOR_EXT: visclass = TrueColor; break;
687 case GLX_DIRECT_COLOR_EXT: visclass = DirectColor; break;
688 case GLX_PSEUDO_COLOR_EXT: visclass = PseudoColor; break;
689 case GLX_STATIC_COLOR_EXT: visclass = StaticColor; break;
690 case GLX_GRAY_SCALE_EXT: visclass = GrayScale; break;
691 case GLX_STATIC_GRAY_EXT: visclass = StaticGray; break;
692 default: return NULL;
693 }
694 /* try 8-bit up through 16-bit */
695 for (depth=8;depth<=16;depth++) {
696 vis = get_visual( dpy, screen, depth, visclass );
697 if (vis) {
698 return vis;
699 }
700 }
701 /* try min_depth up to 8-bit */
702 for (depth=min_depth;depth<8;depth++) {
703 vis = get_visual( dpy, screen, depth, visclass );
704 if (vis) {
705 return vis;
706 }
707 }
708 }
709 }
710
711 /* didn't find a visual */
712 return NULL;
713 }
714
715
716
717 /*
718 * Find the deepest X over/underlay visual of at least min_depth.
719 * Input: dpy, screen - X display and screen number
720 * level - the over/underlay level
721 * trans_type - transparent pixel type: GLX_NONE_EXT,
722 * GLX_TRANSPARENT_RGB_EXT, GLX_TRANSPARENT_INDEX_EXT,
723 * or DONT_CARE
724 * trans_value - transparent pixel value or DONT_CARE
725 * min_depth - minimum visual depth
726 * preferred_class - preferred GLX visual class or DONT_CARE
727 * Return: pointer to an XVisualInfo or NULL.
728 */
729 static XVisualInfo *choose_x_overlay_visual( Display *dpy, int scr,
730 GLboolean rgbFlag,
731 int level, int trans_type,
732 int trans_value,
733 int min_depth,
734 int preferred_class )
735 {
736 Atom overlayVisualsAtom;
737 OverlayInfo *overlay_info;
738 int numOverlaysPerScreen;
739 Status status;
740 Atom actualType;
741 int actualFormat;
742 unsigned long sizeData, bytesLeft;
743 int i;
744 XVisualInfo *deepvis;
745 int deepest;
746
747 /*DEBUG int tt, tv; */
748
749 switch (preferred_class) {
750 case GLX_TRUE_COLOR_EXT: preferred_class = TrueColor; break;
751 case GLX_DIRECT_COLOR_EXT: preferred_class = DirectColor; break;
752 case GLX_PSEUDO_COLOR_EXT: preferred_class = PseudoColor; break;
753 case GLX_STATIC_COLOR_EXT: preferred_class = StaticColor; break;
754 case GLX_GRAY_SCALE_EXT: preferred_class = GrayScale; break;
755 case GLX_STATIC_GRAY_EXT: preferred_class = StaticGray; break;
756 default: preferred_class = DONT_CARE;
757 }
758
759 /*
760 * The SERVER_OVERLAY_VISUALS property on the root window contains
761 * a list of overlay visuals. Get that list now.
762 */
763 overlayVisualsAtom = XInternAtom(dpy,"SERVER_OVERLAY_VISUALS", True);
764 if (overlayVisualsAtom == (Atom) None) {
765 return NULL;
766 }
767
768 status = XGetWindowProperty(dpy, RootWindow( dpy, scr ),
769 overlayVisualsAtom, 0L, (long) 10000, False,
770 overlayVisualsAtom, &actualType, &actualFormat,
771 &sizeData, &bytesLeft,
772 (unsigned char **) &overlay_info );
773
774 if (status != Success || actualType != overlayVisualsAtom ||
775 actualFormat != 32 || sizeData < 4) {
776 /* something went wrong */
777 return NULL;
778 }
779
780 /* Search for the deepest overlay which satisifies all criteria. */
781 deepest = min_depth;
782 deepvis = NULL;
783
784 numOverlaysPerScreen = (int) (sizeData / 4);
785 for (i=0;i<numOverlaysPerScreen;i++) {
786 XVisualInfo *vislist, vistemplate;
787 int count;
788 OverlayInfo *ov;
789 ov = overlay_info + i;
790
791 if (ov->layer!=level) {
792 /* failed overlay level criteria */
793 continue;
794 }
795 if (!(trans_type==DONT_CARE
796 || (trans_type==GLX_TRANSPARENT_INDEX_EXT
797 && ov->transparent_type>0)
798 || (trans_type==GLX_NONE_EXT && ov->transparent_type==0))) {
799 /* failed transparent pixel type criteria */
800 continue;
801 }
802 if (trans_value!=DONT_CARE && trans_value!=ov->value) {
803 /* failed transparent pixel value criteria */
804 continue;
805 }
806
807 /* get XVisualInfo and check the depth */
808 vistemplate.visualid = ov->overlay_visual;
809 vistemplate.screen = scr;
810 vislist = XGetVisualInfo( dpy, VisualIDMask | VisualScreenMask,
811 &vistemplate, &count );
812
813 if (count!=1) {
814 /* something went wrong */
815 continue;
816 }
817 if (preferred_class!=DONT_CARE && preferred_class!=vislist->CLASS) {
818 /* wrong visual class */
819 continue;
820 }
821
822 /* if RGB was requested, make sure we have True/DirectColor */
823 if (rgbFlag && vislist->CLASS != TrueColor
824 && vislist->CLASS != DirectColor)
825 continue;
826
827 /* if CI was requested, make sure we have a color indexed visual */
828 if (!rgbFlag
829 && (vislist->CLASS == TrueColor || vislist->CLASS == DirectColor))
830 continue;
831
832 if (deepvis==NULL || vislist->depth > deepest) {
833 /* YES! found a satisfactory visual */
834 if (deepvis) {
835 XFree( deepvis );
836 }
837 deepest = vislist->depth;
838 deepvis = vislist;
839 /* DEBUG tt = ov->transparent_type;*/
840 /* DEBUG tv = ov->value; */
841 }
842 }
843
844 /*DEBUG
845 if (deepvis) {
846 printf("chose 0x%x: layer=%d depth=%d trans_type=%d trans_value=%d\n",
847 deepvis->visualid, level, deepvis->depth, tt, tv );
848 }
849 */
850 return deepvis;
851 }
852
853
854
855 static XVisualInfo *
856 Fake_glXChooseVisual( Display *dpy, int screen, int *list )
857 {
858 int *parselist;
859 XVisualInfo *vis;
860 int min_ci = 0;
861 int min_red=0, min_green=0, min_blue=0;
862 GLboolean rgb_flag = GL_FALSE;
863 GLboolean alpha_flag = GL_FALSE;
864 GLboolean double_flag = GL_FALSE;
865 GLboolean stereo_flag = GL_FALSE;
866 GLint depth_size = 0;
867 GLint stencil_size = 0;
868 GLint accumRedSize = 0;
869 GLint accumGreenSize = 0;
870 GLint accumBlueSize = 0;
871 GLint accumAlphaSize = 0;
872 int level = 0;
873 int visual_type = DONT_CARE;
874 int trans_type = DONT_CARE;
875 int trans_value = DONT_CARE;
876 GLint caveat = DONT_CARE;
877
878 parselist = list;
879
880 while (*parselist) {
881
882 switch (*parselist) {
883 case GLX_USE_GL:
884 /* ignore */
885 parselist++;
886 break;
887 case GLX_BUFFER_SIZE:
888 parselist++;
889 min_ci = *parselist++;
890 break;
891 case GLX_LEVEL:
892 parselist++;
893 level = *parselist++;
894 break;
895 case GLX_RGBA:
896 rgb_flag = GL_TRUE;
897 parselist++;
898 break;
899 case GLX_DOUBLEBUFFER:
900 double_flag = GL_TRUE;
901 parselist++;
902 break;
903 case GLX_STEREO:
904 stereo_flag = GL_TRUE;
905 return NULL;
906 case GLX_AUX_BUFFERS:
907 /* ignore */
908 parselist++;
909 parselist++;
910 break;
911 case GLX_RED_SIZE:
912 parselist++;
913 min_red = *parselist++;
914 break;
915 case GLX_GREEN_SIZE:
916 parselist++;
917 min_green = *parselist++;
918 break;
919 case GLX_BLUE_SIZE:
920 parselist++;
921 min_blue = *parselist++;
922 break;
923 case GLX_ALPHA_SIZE:
924 parselist++;
925 {
926 GLint size = *parselist++;
927 alpha_flag = size>0 ? 1 : 0;
928 }
929 break;
930 case GLX_DEPTH_SIZE:
931 parselist++;
932 depth_size = *parselist++;
933 break;
934 case GLX_STENCIL_SIZE:
935 parselist++;
936 stencil_size = *parselist++;
937 break;
938 case GLX_ACCUM_RED_SIZE:
939 parselist++;
940 {
941 GLint size = *parselist++;
942 accumRedSize = MAX2( accumRedSize, size );
943 }
944 break;
945 case GLX_ACCUM_GREEN_SIZE:
946 parselist++;
947 {
948 GLint size = *parselist++;
949 accumGreenSize = MAX2( accumGreenSize, size );
950 }
951 break;
952 case GLX_ACCUM_BLUE_SIZE:
953 parselist++;
954 {
955 GLint size = *parselist++;
956 accumBlueSize = MAX2( accumBlueSize, size );
957 }
958 break;
959 case GLX_ACCUM_ALPHA_SIZE:
960 parselist++;
961 {
962 GLint size = *parselist++;
963 accumAlphaSize = MAX2( accumAlphaSize, size );
964 }
965 break;
966
967 /*
968 * GLX_EXT_visual_info extension
969 */
970 case GLX_X_VISUAL_TYPE_EXT:
971 parselist++;
972 visual_type = *parselist++;
973 break;
974 case GLX_TRANSPARENT_TYPE_EXT:
975 parselist++;
976 trans_type = *parselist++;
977 break;
978 case GLX_TRANSPARENT_INDEX_VALUE_EXT:
979 parselist++;
980 trans_value = *parselist++;
981 break;
982 case GLX_TRANSPARENT_RED_VALUE_EXT:
983 case GLX_TRANSPARENT_GREEN_VALUE_EXT:
984 case GLX_TRANSPARENT_BLUE_VALUE_EXT:
985 case GLX_TRANSPARENT_ALPHA_VALUE_EXT:
986 /* ignore */
987 parselist++;
988 parselist++;
989 break;
990
991 /*
992 * GLX_EXT_visual_info extension
993 */
994 case GLX_VISUAL_CAVEAT_EXT:
995 parselist++;
996 caveat = *parselist++; /* ignored for now */
997 break;
998
999 case None:
1000 break;
1001 default:
1002 /* undefined attribute */
1003 return NULL;
1004 }
1005 }
1006
1007 /*
1008 * Since we're only simulating the GLX extension this function will never
1009 * find any real GL visuals. Instead, all we can do is try to find an RGB
1010 * or CI visual of appropriate depth. Other requested attributes such as
1011 * double buffering, depth buffer, etc. will be associated with the X
1012 * visual and stored in the VisualTable[].
1013 */
1014 if (level==0) {
1015 /* normal color planes */
1016 if (rgb_flag) {
1017 /* Get an RGB visual */
1018 int min_rgb = min_red + min_green + min_blue;
1019 if (min_rgb>1 && min_rgb<8) {
1020 /* a special case to be sure we can get a monochrome visual */
1021 min_rgb = 1;
1022 }
1023 vis = choose_x_visual( dpy, screen, rgb_flag, min_rgb, visual_type );
1024 }
1025 else {
1026 /* Get a color index visual */
1027 vis = choose_x_visual( dpy, screen, rgb_flag, min_ci, visual_type );
1028 accumRedSize = accumGreenSize = accumBlueSize = accumAlphaSize = 0;
1029 }
1030 }
1031 else {
1032 /* over/underlay planes */
1033 if (rgb_flag) {
1034 /* rgba overlay */
1035 int min_rgb = min_red + min_green + min_blue;
1036 if (min_rgb>1 && min_rgb<8) {
1037 /* a special case to be sure we can get a monochrome visual */
1038 min_rgb = 1;
1039 }
1040 vis = choose_x_overlay_visual( dpy, screen, rgb_flag, level,
1041 trans_type, trans_value, min_rgb, visual_type );
1042 }
1043 else {
1044 /* color index overlay */
1045 vis = choose_x_overlay_visual( dpy, screen, rgb_flag, level,
1046 trans_type, trans_value, min_ci, visual_type );
1047 }
1048 }
1049
1050 if (vis) {
1051 /* Note: we're not exactly obeying the glXChooseVisual rules here.
1052 * When GLX_DEPTH_SIZE = 1 is specified we're supposed to choose the
1053 * largest depth buffer size, which is 32bits/value. However, we
1054 * return 16 to maintain performance with earlier versions of Mesa.
1055 */
1056 if (depth_size == 1)
1057 depth_size = DEFAULT_SOFTWARE_DEPTH_BITS;
1058 else if (depth_size > 24)
1059 depth_size = 31;
1060 else if (depth_size > 16)
1061 depth_size = 24;
1062 /* we only support one size of stencil and accum buffers. */
1063 if (stencil_size > 0)
1064 stencil_size = STENCIL_BITS;
1065 if (accumRedSize > 0)
1066 accumRedSize = ACCUM_BITS;
1067 if (accumGreenSize > 0)
1068 accumGreenSize = ACCUM_BITS;
1069 if (accumBlueSize > 0)
1070 accumBlueSize = ACCUM_BITS;
1071 if (accumAlphaSize > 0)
1072 accumAlphaSize = ACCUM_BITS;
1073 if (!save_glx_visual( dpy, vis, rgb_flag, alpha_flag, double_flag,
1074 stereo_flag, depth_size, stencil_size,
1075 accumRedSize, accumGreenSize,
1076 accumBlueSize, accumAlphaSize,
1077 level ))
1078 return NULL;
1079 }
1080
1081 return vis;
1082 }
1083
1084
1085
1086
1087 static GLXContext
1088 Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo,
1089 GLXContext share_list, Bool direct )
1090 {
1091 XMesaVisual glxvis;
1092 XMesaContext xmctx;
1093
1094 /* deallocate unused windows/buffers */
1095 XMesaGarbageCollect();
1096
1097 glxvis = find_glx_visual( dpy, visinfo );
1098 if (!glxvis) {
1099 /* This visual wasn't found with glXChooseVisual() */
1100 glxvis = create_glx_visual( dpy, visinfo );
1101 if (!glxvis) {
1102 /* unusable visual */
1103 return NULL;
1104 }
1105 }
1106
1107 xmctx = XMesaCreateContext( glxvis, (XMesaContext) share_list );
1108 if (xmctx) {
1109 /* set the direct/indirect flag */
1110 xmctx->direct = direct;
1111 }
1112 return (GLXContext) xmctx;
1113 }
1114
1115
1116 static GLXContext MakeCurrent_PrevContext = 0;
1117 static GLXDrawable MakeCurrent_PrevDrawable = 0;
1118 static GLXDrawable MakeCurrent_PrevReadable = 0;
1119 static XMesaBuffer MakeCurrent_PrevDrawBuffer = 0;
1120 static XMesaBuffer MakeCurrent_PrevReadBuffer = 0;
1121
1122 /* GLX 1.3 and later */
1123 static Bool
1124 Fake_glXMakeContextCurrent( Display *dpy, GLXDrawable draw,
1125 GLXDrawable read, GLXContext ctx )
1126 {
1127 if (ctx && draw && read) {
1128 XMesaBuffer drawBuffer, readBuffer;
1129 XMesaContext xmctx = (XMesaContext) ctx;
1130
1131 /* Find the XMesaBuffer which corresponds to the GLXDrawable 'draw' */
1132 if (ctx == MakeCurrent_PrevContext
1133 && draw == MakeCurrent_PrevDrawable) {
1134 drawBuffer = MakeCurrent_PrevDrawBuffer;
1135 }
1136 else {
1137 drawBuffer = XMesaFindBuffer( dpy, draw );
1138 }
1139 if (!drawBuffer) {
1140 /* drawable must be a new window! */
1141 drawBuffer = XMesaCreateWindowBuffer2( xmctx->xm_visual, draw, (XMesaContext) ctx );
1142 if (!drawBuffer) {
1143 /* Out of memory, or context/drawable depth mismatch */
1144 return False;
1145 }
1146 }
1147
1148 /* Find the XMesaBuffer which corresponds to the GLXDrawable 'read' */
1149 if (ctx == MakeCurrent_PrevContext
1150 && read == MakeCurrent_PrevReadable) {
1151 readBuffer = MakeCurrent_PrevReadBuffer;
1152 }
1153 else {
1154 readBuffer = XMesaFindBuffer( dpy, read );
1155 }
1156 if (!readBuffer) {
1157 /* drawable must be a new window! */
1158 readBuffer = XMesaCreateWindowBuffer2( xmctx->xm_visual, read, (XMesaContext) ctx );
1159 if (!readBuffer) {
1160 /* Out of memory, or context/drawable depth mismatch */
1161 return False;
1162 }
1163 }
1164
1165 MakeCurrent_PrevContext = ctx;
1166 MakeCurrent_PrevDrawable = draw;
1167 MakeCurrent_PrevReadable = read;
1168 MakeCurrent_PrevDrawBuffer = drawBuffer;
1169 MakeCurrent_PrevReadBuffer = readBuffer;
1170
1171 /* Now make current! */
1172 return (Bool) XMesaMakeCurrent2((XMesaContext) ctx, drawBuffer, readBuffer);
1173 }
1174 else if (!ctx && !draw && !read) {
1175 /* release current context w/out assigning new one. */
1176 XMesaMakeCurrent( NULL, NULL );
1177 MakeCurrent_PrevContext = 0;
1178 MakeCurrent_PrevDrawable = 0;
1179 MakeCurrent_PrevReadable = 0;
1180 MakeCurrent_PrevDrawBuffer = 0;
1181 MakeCurrent_PrevReadBuffer = 0;
1182 return True;
1183 }
1184 else {
1185 /* The args must either all be non-zero or all zero.
1186 * This is an error.
1187 */
1188 return False;
1189 }
1190 }
1191
1192
1193
1194 static Bool
1195 Fake_glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx )
1196 {
1197 return Fake_glXMakeContextCurrent( dpy, drawable, drawable, ctx );
1198 }
1199
1200
1201
1202 static GLXPixmap
1203 Fake_glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, Pixmap pixmap )
1204 {
1205 XMesaVisual v;
1206 XMesaBuffer b;
1207
1208 v = find_glx_visual( dpy, visinfo );
1209 if (!v) {
1210 v = create_glx_visual( dpy, visinfo );
1211 if (!v) {
1212 /* unusable visual */
1213 return 0;
1214 }
1215 }
1216
1217 b = XMesaCreatePixmapBuffer( v, pixmap, 0 );
1218 if (!b) {
1219 return 0;
1220 }
1221 return b->frontbuffer;
1222 }
1223
1224
1225 #ifdef GLX_MESA_pixmap_colormap
1226 static GLXPixmap
1227 Fake_glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo,
1228 Pixmap pixmap, Colormap cmap )
1229 {
1230 XMesaVisual v;
1231 XMesaBuffer b;
1232
1233 v = find_glx_visual( dpy, visinfo );
1234 if (!v) {
1235 v = create_glx_visual( dpy, visinfo );
1236 if (!v) {
1237 /* unusable visual */
1238 return 0;
1239 }
1240 }
1241
1242 b = XMesaCreatePixmapBuffer( v, pixmap, cmap );
1243 if (!b) {
1244 return 0;
1245 }
1246 return b->frontbuffer;
1247 }
1248 #endif
1249
1250
1251 static void
1252 Fake_glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap )
1253 {
1254 XMesaBuffer b = XMesaFindBuffer(dpy, pixmap);
1255 if (b) {
1256 XMesaDestroyBuffer(b);
1257 }
1258 else if (getenv("MESA_DEBUG")) {
1259 fprintf( stderr, "Mesa: glXDestroyGLXPixmap: invalid pixmap\n");
1260 }
1261 }
1262
1263
1264
1265 static void
1266 Fake_glXCopyContext( Display *dpy, GLXContext src, GLXContext dst,
1267 unsigned long mask )
1268 {
1269 XMesaContext xm_src = (XMesaContext) src;
1270 XMesaContext xm_dst = (XMesaContext) dst;
1271 (void) dpy;
1272 gl_copy_context( xm_src->gl_ctx, xm_dst->gl_ctx, (GLuint) mask );
1273 }
1274
1275
1276
1277 static Bool
1278 Fake_glXQueryExtension( Display *dpy, int *errorb, int *event )
1279 {
1280 /* Mesa's GLX isn't really an X extension but we try to act like one. */
1281 (void) dpy;
1282 (void) errorb;
1283 (void) event;
1284 return True;
1285 }
1286
1287
1288 extern void _kw_ungrab_all( Display *dpy );
1289 void _kw_ungrab_all( Display *dpy )
1290 {
1291 XUngrabPointer( dpy, CurrentTime );
1292 XUngrabKeyboard( dpy, CurrentTime );
1293 }
1294
1295
1296 static void
1297 Fake_glXDestroyContext( Display *dpy, GLXContext ctx )
1298 {
1299 (void) dpy;
1300 MakeCurrent_PrevContext = 0;
1301 MakeCurrent_PrevDrawable = 0;
1302 MakeCurrent_PrevReadable = 0;
1303 MakeCurrent_PrevDrawBuffer = 0;
1304 MakeCurrent_PrevReadBuffer = 0;
1305 XMesaDestroyContext( (XMesaContext) ctx );
1306 XMesaGarbageCollect();
1307 }
1308
1309
1310
1311 static Bool
1312 Fake_glXIsDirect( Display *dpy, GLXContext ctx )
1313 {
1314 (void) dpy;
1315 return ((XMesaContext) ctx)->direct;
1316 }
1317
1318
1319
1320 static void
1321 Fake_glXSwapBuffers( Display *dpy, GLXDrawable drawable )
1322 {
1323 XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable );
1324
1325 if (buffer) {
1326 XMesaSwapBuffers(buffer);
1327 }
1328 else if (getenv("MESA_DEBUG")) {
1329 fprintf(stderr, "Mesa Warning: glXSwapBuffers: invalid drawable\n");
1330 }
1331 }
1332
1333
1334
1335 #ifdef GLX_MESA_copy_sub_buffer
1336 static void
1337 Fake_glXCopySubBufferMESA( Display *dpy, GLXDrawable drawable,
1338 int x, int y, int width, int height )
1339 {
1340 XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable );
1341 if (buffer) {
1342 XMesaCopySubBuffer(buffer, x, y, width, height);
1343 }
1344 else if (getenv("MESA_DEBUG")) {
1345 fprintf(stderr, "Mesa Warning: glXCopySubBufferMESA: invalid drawable\n");
1346 }
1347 }
1348 #endif
1349
1350
1351
1352 static Bool
1353 Fake_glXQueryVersion( Display *dpy, int *maj, int *min )
1354 {
1355 (void) dpy;
1356 /* Return GLX version, not Mesa version */
1357 assert(CLIENT_MAJOR_VERSION == SERVER_MAJOR_VERSION);
1358 *maj = CLIENT_MAJOR_VERSION;
1359 *min = MIN2( CLIENT_MINOR_VERSION, SERVER_MINOR_VERSION );
1360 return True;
1361 }
1362
1363
1364
1365 /*
1366 * Query the GLX attributes of the given XVisualInfo.
1367 */
1368 static int
1369 Fake_glXGetConfig( Display *dpy, XVisualInfo *visinfo,
1370 int attrib, int *value )
1371 {
1372 XMesaVisual glxvis;
1373
1374 glxvis = find_glx_visual( dpy, visinfo );
1375 if (!glxvis) {
1376 /* this visual wasn't obtained with glXChooseVisual */
1377 glxvis = create_glx_visual( dpy, visinfo );
1378 if (!glxvis) {
1379 /* this visual can't be used for GL rendering */
1380 if (attrib==GLX_USE_GL) {
1381 *value = (int) False;
1382 return 0;
1383 }
1384 else {
1385 /*fprintf( stderr, "Mesa: Error in glXGetConfig: bad visual\n");*/
1386 return GLX_BAD_VISUAL;
1387 }
1388 }
1389 }
1390
1391 switch(attrib) {
1392 case GLX_USE_GL:
1393 *value = (int) True;
1394 return 0;
1395 case GLX_BUFFER_SIZE:
1396 *value = visinfo->depth;
1397 return 0;
1398 case GLX_LEVEL:
1399 *value = glxvis->level;
1400 return 0;
1401 case GLX_RGBA:
1402 if (glxvis->gl_visual->RGBAflag) {
1403 *value = True;
1404 }
1405 else {
1406 *value = False;
1407 }
1408 return 0;
1409 case GLX_DOUBLEBUFFER:
1410 *value = (int) glxvis->gl_visual->DBflag;
1411 return 0;
1412 case GLX_STEREO:
1413 *value = (int) glxvis->gl_visual->StereoFlag;
1414 return 0;
1415 case GLX_AUX_BUFFERS:
1416 *value = (int) False;
1417 return 0;
1418 case GLX_RED_SIZE:
1419 *value = glxvis->gl_visual->RedBits;
1420 return 0;
1421 case GLX_GREEN_SIZE:
1422 *value = glxvis->gl_visual->GreenBits;
1423 return 0;
1424 case GLX_BLUE_SIZE:
1425 *value = glxvis->gl_visual->BlueBits;
1426 return 0;
1427 case GLX_ALPHA_SIZE:
1428 *value = glxvis->gl_visual->AlphaBits;
1429 return 0;
1430 case GLX_DEPTH_SIZE:
1431 *value = glxvis->gl_visual->DepthBits;
1432 return 0;
1433 case GLX_STENCIL_SIZE:
1434 *value = glxvis->gl_visual->StencilBits;
1435 return 0;
1436 case GLX_ACCUM_RED_SIZE:
1437 *value = glxvis->gl_visual->AccumRedBits;
1438 return 0;
1439 case GLX_ACCUM_GREEN_SIZE:
1440 *value = glxvis->gl_visual->AccumGreenBits;
1441 return 0;
1442 case GLX_ACCUM_BLUE_SIZE:
1443 *value = glxvis->gl_visual->AccumBlueBits;
1444 return 0;
1445 case GLX_ACCUM_ALPHA_SIZE:
1446 *value = glxvis->gl_visual->AccumAlphaBits;
1447 return 0;
1448
1449 /*
1450 * GLX_EXT_visual_info extension
1451 */
1452 case GLX_X_VISUAL_TYPE_EXT:
1453 switch (glxvis->visinfo->CLASS) {
1454 case StaticGray: *value = GLX_STATIC_GRAY_EXT; return 0;
1455 case GrayScale: *value = GLX_GRAY_SCALE_EXT; return 0;
1456 case StaticColor: *value = GLX_STATIC_GRAY_EXT; return 0;
1457 case PseudoColor: *value = GLX_PSEUDO_COLOR_EXT; return 0;
1458 case TrueColor: *value = GLX_TRUE_COLOR_EXT; return 0;
1459 case DirectColor: *value = GLX_DIRECT_COLOR_EXT; return 0;
1460 }
1461 return 0;
1462 case GLX_TRANSPARENT_TYPE_EXT:
1463 if (glxvis->level==0) {
1464 /* normal planes */
1465 *value = GLX_NONE_EXT;
1466 }
1467 else if (glxvis->level>0) {
1468 /* overlay */
1469 if (glxvis->gl_visual->RGBAflag) {
1470 *value = GLX_TRANSPARENT_RGB_EXT;
1471 }
1472 else {
1473 *value = GLX_TRANSPARENT_INDEX_EXT;
1474 }
1475 }
1476 else if (glxvis->level<0) {
1477 /* underlay */
1478 *value = GLX_NONE_EXT;
1479 }
1480 return 0;
1481 case GLX_TRANSPARENT_INDEX_VALUE_EXT:
1482 {
1483 int pixel = transparent_pixel( glxvis );
1484 if (pixel>=0) {
1485 *value = pixel;
1486 }
1487 /* else undefined */
1488 }
1489 return 0;
1490 case GLX_TRANSPARENT_RED_VALUE_EXT:
1491 /* undefined */
1492 return 0;
1493 case GLX_TRANSPARENT_GREEN_VALUE_EXT:
1494 /* undefined */
1495 return 0;
1496 case GLX_TRANSPARENT_BLUE_VALUE_EXT:
1497 /* undefined */
1498 return 0;
1499 case GLX_TRANSPARENT_ALPHA_VALUE_EXT:
1500 /* undefined */
1501 return 0;
1502
1503 /*
1504 * GLX_EXT_visual_info extension
1505 */
1506 case GLX_VISUAL_CAVEAT_EXT:
1507 /* test for zero, just in case */
1508 if (glxvis->VisualCaveat > 0)
1509 *value = glxvis->VisualCaveat;
1510 else
1511 *value = GLX_NONE_EXT;
1512 return 0;
1513
1514 /*
1515 * Extensions
1516 */
1517 default:
1518 return GLX_BAD_ATTRIBUTE;
1519 }
1520 }
1521
1522
1523
1524 static void
1525 Fake_glXWaitGL( void )
1526 {
1527 XMesaContext xmesa = XMesaGetCurrentContext();
1528 XMesaFlush( xmesa );
1529 }
1530
1531
1532
1533 static void
1534 Fake_glXWaitX( void )
1535 {
1536 XMesaContext xmesa = XMesaGetCurrentContext();
1537 XMesaFlush( xmesa );
1538 }
1539
1540
1541 /*
1542 * Return the extensions string, which is 3Dfx-dependant.
1543 */
1544 static const char *get_extensions( void )
1545 {
1546 #ifdef FX
1547 const char *fx = getenv("MESA_GLX_FX");
1548 if (fx && fx[0] != 'd') {
1549 return "GLX_MESA_pixmap_colormap GLX_EXT_visual_info GLX_EXT_visual_rating GLX_MESA_release_buffers GLX_MESA_copy_sub_buffer GLX_SGI_video_sync GLX_MESA_set_3dfx_mode GLX_ARB_get_proc_address";
1550 }
1551 #endif
1552 return "GLX_MESA_pixmap_colormap GLX_EXT_visual_info GLX_EXT_visual_rating GLX_MESA_release_buffers GLX_MESA_copy_sub_buffer GLX_SGI_video_sync GLX_ARB_get_proc_address";
1553 }
1554
1555
1556
1557 /* GLX 1.1 and later */
1558 static const char *
1559 Fake_glXQueryExtensionsString( Display *dpy, int screen )
1560 {
1561 (void) dpy;
1562 (void) screen;
1563 return get_extensions();
1564 }
1565
1566
1567
1568 /* GLX 1.1 and later */
1569 static const char *
1570 Fake_glXQueryServerString( Display *dpy, int screen, int name )
1571 {
1572 static char version[1000];
1573 sprintf(version, "%d.%d %s", SERVER_MAJOR_VERSION, SERVER_MINOR_VERSION,
1574 MESA_GLX_VERSION);
1575
1576 (void) dpy;
1577 (void) screen;
1578
1579 switch (name) {
1580 case GLX_EXTENSIONS:
1581 return get_extensions();
1582 case GLX_VENDOR:
1583 return VENDOR;
1584 case GLX_VERSION:
1585 return version;
1586 default:
1587 return NULL;
1588 }
1589 }
1590
1591
1592
1593 /* GLX 1.1 and later */
1594 static const char *
1595 Fake_glXGetClientString( Display *dpy, int name )
1596 {
1597 static char version[1000];
1598 sprintf(version, "%d.%d %s", CLIENT_MAJOR_VERSION, CLIENT_MINOR_VERSION,
1599 MESA_GLX_VERSION);
1600
1601 (void) dpy;
1602
1603 switch (name) {
1604 case GLX_EXTENSIONS:
1605 return get_extensions();
1606 case GLX_VENDOR:
1607 return VENDOR;
1608 case GLX_VERSION:
1609 return version;
1610 default:
1611 return NULL;
1612 }
1613 }
1614
1615
1616
1617 /*
1618 * GLX 1.3 and later
1619 */
1620
1621 static GLXFBConfig *
1622 Fake_glXChooseFBConfig( Display *dpy, int screen,
1623 const int *attribList, int *nitems )
1624 {
1625 (void) dpy;
1626 (void) screen;
1627 (void) attribList;
1628 (void) nitems;
1629 return 0;
1630 }
1631
1632
1633 static int
1634 Fake_glXGetFBConfigAttrib( Display *dpy, GLXFBConfig config,
1635 int attribute, int *value )
1636 {
1637 (void) dpy;
1638 (void) config;
1639 (void) attribute;
1640 (void) value;
1641 return 0;
1642 }
1643
1644
1645 static GLXFBConfig *
1646 Fake_glXGetFBConfigs( Display *dpy, int screen, int *nelements )
1647 {
1648 (void) dpy;
1649 (void) screen;
1650 (void) nelements;
1651 return 0;
1652 }
1653
1654
1655 static XVisualInfo *
1656 Fake_glXGetVisualFromFBConfig( Display *dpy, GLXFBConfig config )
1657 {
1658 (void) dpy;
1659 (void) config;
1660 return 0;
1661 }
1662
1663
1664 static GLXWindow
1665 Fake_glXCreateWindow( Display *dpy, GLXFBConfig config, Window win,
1666 const int *attribList )
1667 {
1668 (void) dpy;
1669 (void) config;
1670 (void) win;
1671 (void) attribList;
1672 return 0;
1673 }
1674
1675
1676 static void
1677 Fake_glXDestroyWindow( Display *dpy, GLXWindow window )
1678 {
1679 (void) dpy;
1680 (void) window;
1681 return;
1682 }
1683
1684
1685 static GLXPixmap
1686 Fake_glXCreatePixmap( Display *dpy, GLXFBConfig config, Pixmap pixmap,
1687 const int *attribList )
1688 {
1689 (void) dpy;
1690 (void) config;
1691 (void) pixmap;
1692 (void) attribList;
1693 return 0;
1694 }
1695
1696
1697 static void
1698 Fake_glXDestroyPixmap( Display *dpy, GLXPixmap pixmap )
1699 {
1700 (void) dpy;
1701 (void) pixmap;
1702 return;
1703 }
1704
1705
1706 static GLXPbuffer
1707 Fake_glXCreatePbuffer( Display *dpy, GLXFBConfig config,
1708 const int *attribList )
1709 {
1710 (void) dpy;
1711 (void) config;
1712 (void) attribList;
1713 return 0;
1714 }
1715
1716
1717 static void
1718 Fake_glXDestroyPbuffer( Display *dpy, GLXPbuffer pbuf )
1719 {
1720 (void) dpy;
1721 (void) pbuf;
1722 }
1723
1724
1725 static void
1726 Fake_glXQueryDrawable( Display *dpy, GLXDrawable draw, int attribute,
1727 unsigned int *value )
1728 {
1729 (void) dpy;
1730 (void) draw;
1731 (void) attribute;
1732 (void) value;
1733 }
1734
1735
1736 static GLXContext
1737 Fake_glXCreateNewContext( Display *dpy, GLXFBConfig config,
1738 int renderType, GLXContext shareList, Bool direct )
1739 {
1740 (void) dpy;
1741 (void) config;
1742 (void) renderType;
1743 (void) shareList;
1744 (void) direct;
1745 return 0;
1746 }
1747
1748
1749 static int
1750 Fake_glXQueryContext( Display *dpy, GLXContext ctx, int attribute, int *value )
1751 {
1752 (void) dpy;
1753 (void) ctx;
1754 (void) attribute;
1755 (void) value;
1756 return 0;
1757 }
1758
1759
1760 static void
1761 Fake_glXSelectEvent( Display *dpy, GLXDrawable drawable, unsigned long mask )
1762 {
1763 (void) dpy;
1764 (void) drawable;
1765 (void) mask;
1766 }
1767
1768
1769 static void
1770 Fake_glXGetSelectedEvent( Display *dpy, GLXDrawable drawable,
1771 unsigned long *mask )
1772 {
1773 (void) dpy;
1774 (void) drawable;
1775 (void) mask;
1776 }
1777
1778
1779
1780 #ifdef GLX_MESA_release_buffers
1781 /*
1782 * Release the depth, stencil, accum buffers attached to a GLXDrawable
1783 * (a window or pixmap) prior to destroying the GLXDrawable.
1784 */
1785 static Bool
1786 Fake_glXReleaseBuffersMESA( Display *dpy, GLXDrawable d )
1787 {
1788 XMesaBuffer b = XMesaFindBuffer(dpy, d);
1789 if (b) {
1790 XMesaDestroyBuffer(b);
1791 return True;
1792 }
1793 return False;
1794 }
1795 #endif
1796
1797
1798
1799 #ifdef GLX_MESA_set_3dfx_mode
1800 static GLboolean
1801 Fake_glXSet3DfxModeMESA( GLint mode )
1802 {
1803 return XMesaSetFXmode( mode );
1804 }
1805 #endif
1806
1807
1808
1809 /*
1810 * GLX_SGI_video_sync
1811 */
1812
1813 #ifdef GLX_SGI_video_sync
1814
1815 static int
1816 Fake_glXGetVideoSyncSGI(unsigned int *count)
1817 {
1818 return 0;
1819 }
1820
1821
1822 static int
1823 Fake_glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count)
1824 {
1825 return 0;
1826 }
1827
1828 #endif
1829
1830
1831
1832 extern struct _glxapi_table *_mesa_GetGLXDispatchTable(void);
1833 struct _glxapi_table *_mesa_GetGLXDispatchTable(void)
1834 {
1835 static struct _glxapi_table glx;
1836
1837 /* be sure our dispatch table size <= libGL's table */
1838 {
1839 int size = sizeof(struct _glxapi_table) / sizeof(void *);
1840 (void) size;
1841 assert(_glxapi_get_dispatch_table_size() >= size);
1842 }
1843
1844 /* initialize the whole table to no-ops */
1845 _glxapi_set_no_op_table(&glx);
1846
1847 /* now initialize the table with the functions I implement */
1848 glx.ChooseVisual = Fake_glXChooseVisual;
1849 glx.CopyContext = Fake_glXCopyContext;
1850 glx.CreateContext = Fake_glXCreateContext;
1851 glx.CreateGLXPixmap = Fake_glXCreateGLXPixmap;
1852 glx.DestroyContext = Fake_glXDestroyContext;
1853 glx.DestroyGLXPixmap = Fake_glXDestroyGLXPixmap;
1854 glx.GetConfig = Fake_glXGetConfig;
1855 /*glx.GetCurrentContext = Fake_glXGetCurrentContext;*/
1856 /*glx.GetCurrentDrawable = Fake_glXGetCurrentDrawable;*/
1857 glx.IsDirect = Fake_glXIsDirect;
1858 glx.MakeCurrent = Fake_glXMakeCurrent;
1859 glx.QueryExtension = Fake_glXQueryExtension;
1860 glx.QueryVersion = Fake_glXQueryVersion;
1861 glx.SwapBuffers = Fake_glXSwapBuffers;
1862 glx.UseXFont = Fake_glXUseXFont;
1863 glx.WaitGL = Fake_glXWaitGL;
1864 glx.WaitX = Fake_glXWaitX;
1865
1866 #ifdef GLX_VERSION_1_1
1867 glx.GetClientString = Fake_glXGetClientString;
1868 glx.QueryExtensionsString = Fake_glXQueryExtensionsString;
1869 glx.QueryServerString = Fake_glXQueryServerString;
1870 #endif
1871
1872 #ifdef GLX_VERSION_1_2
1873 /*glx.GetCurrentDisplay = Fake_glXGetCurrentDisplay;*/
1874 #endif
1875
1876 #ifdef GLX_VERSION_1_3
1877 glx.ChooseFBConfig = Fake_glXChooseFBConfig;
1878 glx.CreateNewContext = Fake_glXCreateNewContext;
1879 glx.CreatePbuffer = Fake_glXCreatePbuffer;
1880 glx.CreatePixmap = Fake_glXCreatePixmap;
1881 glx.CreateWindow = Fake_glXCreateWindow;
1882 glx.DestroyPbuffer = Fake_glXDestroyPbuffer;
1883 glx.DestroyPixmap = Fake_glXDestroyPixmap;
1884 glx.DestroyWindow = Fake_glXDestroyWindow;
1885 /*glx.GetCurrentReadDrawable = Fake_glXGetCurrentReadDrawable;*/
1886 glx.GetFBConfigAttrib = Fake_glXGetFBConfigAttrib;
1887 glx.GetFBConfigs = Fake_glXGetFBConfigs;
1888 glx.GetSelectedEvent = Fake_glXGetSelectedEvent;
1889 glx.GetVisualFromFBConfig = Fake_glXGetVisualFromFBConfig;
1890 glx.MakeContextCurrent = Fake_glXMakeContextCurrent;
1891 glx.QueryContext = Fake_glXQueryContext;
1892 glx.QueryDrawable = Fake_glXQueryDrawable;
1893 glx.SelectEvent = Fake_glXSelectEvent;
1894 #endif
1895
1896 #ifdef GLX_SGI_video_sync
1897 glx.GetVideoSyncSGI = Fake_glXGetVideoSyncSGI;
1898 glx.WaitVideoSyncSGI = Fake_glXWaitVideoSyncSGI;
1899 #endif
1900
1901 #ifdef GLX_MESA_copy_sub_buffer
1902 glx.CopySubBufferMESA = Fake_glXCopySubBufferMESA;
1903 #endif
1904
1905 #ifdef GLX_MESA_release_buffers
1906 glx.ReleaseBuffersMESA = Fake_glXReleaseBuffersMESA;
1907 #endif
1908
1909 #ifdef GLX_MESA_pixmap_colormap
1910 glx.CreateGLXPixmapMESA = Fake_glXCreateGLXPixmapMESA;
1911 #endif
1912
1913 #ifdef GLX_MESA_set_3dfx_mode
1914 glx.Set3DfxModeMESA = Fake_glXSet3DfxModeMESA;
1915 #endif
1916
1917 return &glx;
1918 }