5b231875651a251e9dbec2c62a6ab8c5e1590d7e
[mesa.git] / src / mesa / drivers / x11 / fakeglx.c
1 /* $Id: fakeglx.c,v 1.33 2000/04/19 01:44:01 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, 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, 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
1227 static GLXPixmap
1228 Fake_glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo,
1229 Pixmap pixmap, Colormap cmap )
1230 {
1231 XMesaVisual v;
1232 XMesaBuffer b;
1233
1234 v = find_glx_visual( dpy, visinfo );
1235 if (!v) {
1236 v = create_glx_visual( dpy, visinfo );
1237 if (!v) {
1238 /* unusable visual */
1239 return 0;
1240 }
1241 }
1242
1243 b = XMesaCreatePixmapBuffer( v, pixmap, cmap );
1244 if (!b) {
1245 return 0;
1246 }
1247 return b->frontbuffer;
1248 }
1249
1250 #endif
1251
1252
1253 static void
1254 Fake_glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap )
1255 {
1256 XMesaBuffer b = XMesaFindBuffer(dpy, pixmap);
1257 if (b) {
1258 XMesaDestroyBuffer(b);
1259 }
1260 else if (getenv("MESA_DEBUG")) {
1261 fprintf( stderr, "Mesa: glXDestroyGLXPixmap: invalid pixmap\n");
1262 }
1263 }
1264
1265
1266 static void
1267 Fake_glXCopyContext( Display *dpy, GLXContext src, GLXContext dst,
1268 unsigned long mask )
1269 {
1270 XMesaContext xm_src = (XMesaContext) src;
1271 XMesaContext xm_dst = (XMesaContext) dst;
1272 (void) dpy;
1273 gl_copy_context( xm_src->gl_ctx, xm_dst->gl_ctx, (GLuint) mask );
1274 }
1275
1276
1277
1278 static Bool
1279 Fake_glXQueryExtension( Display *dpy, int *errorb, int *event )
1280 {
1281 /* Mesa's GLX isn't really an X extension but we try to act like one. */
1282 (void) dpy;
1283 (void) errorb;
1284 (void) event;
1285 return True;
1286 }
1287
1288
1289 extern void _kw_ungrab_all( Display *dpy );
1290 void _kw_ungrab_all( Display *dpy )
1291 {
1292 XUngrabPointer( dpy, CurrentTime );
1293 XUngrabKeyboard( dpy, CurrentTime );
1294 }
1295
1296
1297 static void
1298 Fake_glXDestroyContext( Display *dpy, GLXContext ctx )
1299 {
1300 (void) dpy;
1301 MakeCurrent_PrevContext = 0;
1302 MakeCurrent_PrevDrawable = 0;
1303 MakeCurrent_PrevReadable = 0;
1304 MakeCurrent_PrevDrawBuffer = 0;
1305 MakeCurrent_PrevReadBuffer = 0;
1306 XMesaDestroyContext( (XMesaContext) ctx );
1307 XMesaGarbageCollect();
1308 }
1309
1310
1311
1312 static Bool
1313 Fake_glXIsDirect( Display *dpy, GLXContext ctx )
1314 {
1315 (void) dpy;
1316 return ((XMesaContext) ctx)->direct;
1317 }
1318
1319
1320
1321 static void
1322 Fake_glXSwapBuffers( Display *dpy, GLXDrawable drawable )
1323 {
1324 XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable );
1325
1326 if (buffer) {
1327 XMesaSwapBuffers(buffer);
1328 }
1329 else if (getenv("MESA_DEBUG")) {
1330 fprintf(stderr, "Mesa Warning: glXSwapBuffers: invalid drawable\n");
1331 }
1332 }
1333
1334
1335 static void
1336 Fake_glXCopySubBufferMESA( Display *dpy, GLXDrawable drawable,
1337 int x, int y, int width, int height )
1338 {
1339 XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable );
1340 if (buffer) {
1341 XMesaCopySubBuffer(buffer, x, y, width, height);
1342 }
1343 else if (getenv("MESA_DEBUG")) {
1344 fprintf(stderr, "Mesa Warning: glXCopySubBufferMESA: invalid drawable\n");
1345 }
1346 }
1347
1348
1349
1350 static Bool
1351 Fake_glXQueryVersion( Display *dpy, int *maj, int *min )
1352 {
1353 (void) dpy;
1354 /* Return GLX version, not Mesa version */
1355 assert(CLIENT_MAJOR_VERSION == SERVER_MAJOR_VERSION);
1356 *maj = CLIENT_MAJOR_VERSION;
1357 *min = MIN2( CLIENT_MINOR_VERSION, SERVER_MINOR_VERSION );
1358 return True;
1359 }
1360
1361
1362
1363 /*
1364 * Query the GLX attributes of the given XVisualInfo.
1365 */
1366 static int
1367 Fake_glXGetConfig( Display *dpy, XVisualInfo *visinfo,
1368 int attrib, int *value )
1369 {
1370 XMesaVisual glxvis;
1371
1372 glxvis = find_glx_visual( dpy, visinfo );
1373 if (!glxvis) {
1374 /* this visual wasn't obtained with glXChooseVisual */
1375 glxvis = create_glx_visual( dpy, visinfo );
1376 if (!glxvis) {
1377 /* this visual can't be used for GL rendering */
1378 if (attrib==GLX_USE_GL) {
1379 *value = (int) False;
1380 return 0;
1381 }
1382 else {
1383 /*fprintf( stderr, "Mesa: Error in glXGetConfig: bad visual\n");*/
1384 return GLX_BAD_VISUAL;
1385 }
1386 }
1387 }
1388
1389 switch(attrib) {
1390 case GLX_USE_GL:
1391 *value = (int) True;
1392 return 0;
1393 case GLX_BUFFER_SIZE:
1394 *value = visinfo->depth;
1395 return 0;
1396 case GLX_LEVEL:
1397 *value = glxvis->level;
1398 return 0;
1399 case GLX_RGBA:
1400 if (glxvis->gl_visual->RGBAflag) {
1401 *value = True;
1402 }
1403 else {
1404 *value = False;
1405 }
1406 return 0;
1407 case GLX_DOUBLEBUFFER:
1408 *value = (int) glxvis->gl_visual->DBflag;
1409 return 0;
1410 case GLX_STEREO:
1411 *value = (int) glxvis->gl_visual->StereoFlag;
1412 return 0;
1413 case GLX_AUX_BUFFERS:
1414 *value = (int) False;
1415 return 0;
1416 case GLX_RED_SIZE:
1417 *value = glxvis->gl_visual->RedBits;
1418 return 0;
1419 case GLX_GREEN_SIZE:
1420 *value = glxvis->gl_visual->GreenBits;
1421 return 0;
1422 case GLX_BLUE_SIZE:
1423 *value = glxvis->gl_visual->BlueBits;
1424 return 0;
1425 case GLX_ALPHA_SIZE:
1426 *value = glxvis->gl_visual->AlphaBits;
1427 return 0;
1428 case GLX_DEPTH_SIZE:
1429 *value = glxvis->gl_visual->DepthBits;
1430 return 0;
1431 case GLX_STENCIL_SIZE:
1432 *value = glxvis->gl_visual->StencilBits;
1433 return 0;
1434 case GLX_ACCUM_RED_SIZE:
1435 *value = glxvis->gl_visual->AccumRedBits;
1436 return 0;
1437 case GLX_ACCUM_GREEN_SIZE:
1438 *value = glxvis->gl_visual->AccumGreenBits;
1439 return 0;
1440 case GLX_ACCUM_BLUE_SIZE:
1441 *value = glxvis->gl_visual->AccumBlueBits;
1442 return 0;
1443 case GLX_ACCUM_ALPHA_SIZE:
1444 *value = glxvis->gl_visual->AccumAlphaBits;
1445 return 0;
1446
1447 /*
1448 * GLX_EXT_visual_info extension
1449 */
1450 case GLX_X_VISUAL_TYPE_EXT:
1451 switch (glxvis->visinfo->CLASS) {
1452 case StaticGray: *value = GLX_STATIC_GRAY_EXT; return 0;
1453 case GrayScale: *value = GLX_GRAY_SCALE_EXT; return 0;
1454 case StaticColor: *value = GLX_STATIC_GRAY_EXT; return 0;
1455 case PseudoColor: *value = GLX_PSEUDO_COLOR_EXT; return 0;
1456 case TrueColor: *value = GLX_TRUE_COLOR_EXT; return 0;
1457 case DirectColor: *value = GLX_DIRECT_COLOR_EXT; return 0;
1458 }
1459 return 0;
1460 case GLX_TRANSPARENT_TYPE_EXT:
1461 if (glxvis->level==0) {
1462 /* normal planes */
1463 *value = GLX_NONE_EXT;
1464 }
1465 else if (glxvis->level>0) {
1466 /* overlay */
1467 if (glxvis->gl_visual->RGBAflag) {
1468 *value = GLX_TRANSPARENT_RGB_EXT;
1469 }
1470 else {
1471 *value = GLX_TRANSPARENT_INDEX_EXT;
1472 }
1473 }
1474 else if (glxvis->level<0) {
1475 /* underlay */
1476 *value = GLX_NONE_EXT;
1477 }
1478 return 0;
1479 case GLX_TRANSPARENT_INDEX_VALUE_EXT:
1480 {
1481 int pixel = transparent_pixel( glxvis );
1482 if (pixel>=0) {
1483 *value = pixel;
1484 }
1485 /* else undefined */
1486 }
1487 return 0;
1488 case GLX_TRANSPARENT_RED_VALUE_EXT:
1489 /* undefined */
1490 return 0;
1491 case GLX_TRANSPARENT_GREEN_VALUE_EXT:
1492 /* undefined */
1493 return 0;
1494 case GLX_TRANSPARENT_BLUE_VALUE_EXT:
1495 /* undefined */
1496 return 0;
1497 case GLX_TRANSPARENT_ALPHA_VALUE_EXT:
1498 /* undefined */
1499 return 0;
1500
1501 /*
1502 * GLX_EXT_visual_info extension
1503 */
1504 case GLX_VISUAL_CAVEAT_EXT:
1505 /* test for zero, just in case */
1506 if (glxvis->VisualCaveat > 0)
1507 *value = glxvis->VisualCaveat;
1508 else
1509 *value = GLX_NONE_EXT;
1510 return 0;
1511
1512 /*
1513 * Extensions
1514 */
1515 default:
1516 return GLX_BAD_ATTRIBUTE;
1517 }
1518 }
1519
1520
1521
1522 static void
1523 Fake_glXWaitGL( void )
1524 {
1525 XMesaContext xmesa = XMesaGetCurrentContext();
1526 XMesaFlush( xmesa );
1527 }
1528
1529
1530
1531 static void
1532 Fake_glXWaitX( void )
1533 {
1534 XMesaContext xmesa = XMesaGetCurrentContext();
1535 XMesaFlush( xmesa );
1536 }
1537
1538
1539 /*
1540 * Return the extensions string, which is 3Dfx-dependant.
1541 */
1542 static const char *get_extensions( void )
1543 {
1544 #ifdef FX
1545 const char *fx = getenv("MESA_GLX_FX");
1546 if (fx && fx[0] != 'd') {
1547 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";
1548 }
1549 #endif
1550 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";
1551 }
1552
1553
1554
1555 /* GLX 1.1 and later */
1556 static const char *
1557 Fake_glXQueryExtensionsString( Display *dpy, int screen )
1558 {
1559 (void) dpy;
1560 (void) screen;
1561 return get_extensions();
1562 }
1563
1564
1565
1566 /* GLX 1.1 and later */
1567 static const char *
1568 Fake_glXQueryServerString( Display *dpy, int screen, int name )
1569 {
1570 static char version[1000];
1571 sprintf(version, "%d.%d %s", SERVER_MAJOR_VERSION, SERVER_MINOR_VERSION,
1572 MESA_GLX_VERSION);
1573
1574 (void) dpy;
1575 (void) screen;
1576
1577 switch (name) {
1578 case GLX_EXTENSIONS:
1579 return get_extensions();
1580 case GLX_VENDOR:
1581 return VENDOR;
1582 case GLX_VERSION:
1583 return version;
1584 default:
1585 return NULL;
1586 }
1587 }
1588
1589
1590
1591 /* GLX 1.1 and later */
1592 static const char *
1593 Fake_glXGetClientString( Display *dpy, int name )
1594 {
1595 static char version[1000];
1596 sprintf(version, "%d.%d %s", CLIENT_MAJOR_VERSION, CLIENT_MINOR_VERSION,
1597 MESA_GLX_VERSION);
1598
1599 (void) dpy;
1600
1601 switch (name) {
1602 case GLX_EXTENSIONS:
1603 return get_extensions();
1604 case GLX_VENDOR:
1605 return VENDOR;
1606 case GLX_VERSION:
1607 return version;
1608 default:
1609 return NULL;
1610 }
1611 }
1612
1613
1614
1615 /*
1616 * GLX 1.3 and later
1617 */
1618
1619 static GLXFBConfig *
1620 Fake_glXChooseFBConfig( Display *dpy, int screen,
1621 const int *attribList, int *nitems )
1622 {
1623 (void) dpy;
1624 (void) screen;
1625 (void) attribList;
1626 (void) nitems;
1627 return 0;
1628 }
1629
1630
1631 static int
1632 Fake_glXGetFBConfigAttrib( Display *dpy, GLXFBConfig config,
1633 int attribute, int *value )
1634 {
1635 (void) dpy;
1636 (void) config;
1637 (void) attribute;
1638 (void) value;
1639 return 0;
1640 }
1641
1642
1643 static GLXFBConfig *
1644 Fake_glXGetFBConfigs( Display *dpy, int screen, int *nelements )
1645 {
1646 (void) dpy;
1647 (void) screen;
1648 (void) nelements;
1649 return 0;
1650 }
1651
1652
1653 static XVisualInfo *
1654 Fake_glXGetVisualFromFBConfig( Display *dpy, GLXFBConfig config )
1655 {
1656 (void) dpy;
1657 (void) config;
1658 return 0;
1659 }
1660
1661
1662 static GLXWindow
1663 Fake_glXCreateWindow( Display *dpy, GLXFBConfig config, Window win,
1664 const int *attribList )
1665 {
1666 (void) dpy;
1667 (void) config;
1668 (void) win;
1669 (void) attribList;
1670 return 0;
1671 }
1672
1673
1674 static void
1675 Fake_glXDestroyWindow( Display *dpy, GLXWindow window )
1676 {
1677 (void) dpy;
1678 (void) window;
1679 return;
1680 }
1681
1682
1683 static GLXPixmap
1684 Fake_glXCreatePixmap( Display *dpy, GLXFBConfig config, Pixmap pixmap,
1685 const int *attribList )
1686 {
1687 (void) dpy;
1688 (void) config;
1689 (void) pixmap;
1690 (void) attribList;
1691 return 0;
1692 }
1693
1694
1695 static void
1696 Fake_glXDestroyPixmap( Display *dpy, GLXPixmap pixmap )
1697 {
1698 (void) dpy;
1699 (void) pixmap;
1700 return;
1701 }
1702
1703
1704 static GLXPbuffer
1705 Fake_glXCreatePbuffer( Display *dpy, GLXFBConfig config,
1706 const int *attribList )
1707 {
1708 (void) dpy;
1709 (void) config;
1710 (void) attribList;
1711 return 0;
1712 }
1713
1714
1715 static void
1716 Fake_glXDestroyPbuffer( Display *dpy, GLXPbuffer pbuf )
1717 {
1718 (void) dpy;
1719 (void) pbuf;
1720 }
1721
1722
1723 static void
1724 Fake_glXQueryDrawable( Display *dpy, GLXDrawable draw, int attribute,
1725 unsigned int *value )
1726 {
1727 (void) dpy;
1728 (void) draw;
1729 (void) attribute;
1730 (void) value;
1731 }
1732
1733
1734 static GLXContext
1735 Fake_glXCreateNewContext( Display *dpy, GLXFBConfig config,
1736 int renderType, GLXContext shareList, Bool direct )
1737 {
1738 (void) dpy;
1739 (void) config;
1740 (void) renderType;
1741 (void) shareList;
1742 (void) direct;
1743 return 0;
1744 }
1745
1746
1747 static int
1748 Fake_glXQueryContext( Display *dpy, GLXContext ctx, int attribute, int *value )
1749 {
1750 (void) dpy;
1751 (void) ctx;
1752 (void) attribute;
1753 (void) value;
1754 return 0;
1755 }
1756
1757
1758 static void
1759 Fake_glXSelectEvent( Display *dpy, GLXDrawable drawable, unsigned long mask )
1760 {
1761 (void) dpy;
1762 (void) drawable;
1763 (void) mask;
1764 }
1765
1766
1767 static void
1768 Fake_glXGetSelectedEvent( Display *dpy, GLXDrawable drawable,
1769 unsigned long *mask )
1770 {
1771 (void) dpy;
1772 (void) drawable;
1773 (void) mask;
1774 }
1775
1776
1777
1778 /*
1779 * Release the depth, stencil, accum buffers attached to a GLXDrawable
1780 * (a window or pixmap) prior to destroying the GLXDrawable.
1781 */
1782 static Bool
1783 Fake_glXReleaseBuffersMESA( Display *dpy, GLXDrawable d )
1784 {
1785 XMesaBuffer b = XMesaFindBuffer(dpy, d);
1786 if (b) {
1787 XMesaDestroyBuffer(b);
1788 return True;
1789 }
1790 return False;
1791 }
1792
1793
1794 /*
1795 * GLX_MESA_set_3dfx_mode
1796 */
1797 static GLboolean
1798 Fake_glXSet3DfxModeMESA( GLint mode )
1799 {
1800 return XMesaSetFXmode( mode );
1801 }
1802
1803
1804 /*
1805 * GLX_SGI_video_sync
1806 */
1807
1808 #ifdef GLX_SGI_video_sync
1809
1810 static int
1811 Fake_glXGetVideoSyncSGI(unsigned int *count)
1812 {
1813 return 0;
1814 }
1815
1816
1817 static int
1818 Fake_glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count)
1819 {
1820 return 0;
1821 }
1822
1823 #endif
1824
1825
1826
1827 extern struct _glxapi_table *_mesa_GetGLXDispatchTable(void);
1828 struct _glxapi_table *_mesa_GetGLXDispatchTable(void)
1829 {
1830 static struct _glxapi_table glx;
1831
1832 /* be sure our dispatch table size <= libGL's table */
1833 {
1834 int size = sizeof(struct _glxapi_table) / sizeof(void *);
1835 (void) size;
1836 assert(_glxapi_get_dispatch_table_size() >= size);
1837 }
1838
1839 /* initialize the whole table to no-ops */
1840 _glxapi_set_no_op_table(&glx);
1841
1842 /* now initialize the table with the functions I implement */
1843 glx.ChooseVisual = Fake_glXChooseVisual;
1844 glx.CopyContext = Fake_glXCopyContext;
1845 glx.CreateContext = Fake_glXCreateContext;
1846 glx.CreateGLXPixmap = Fake_glXCreateGLXPixmap;
1847 glx.DestroyContext = Fake_glXDestroyContext;
1848 glx.DestroyGLXPixmap = Fake_glXDestroyGLXPixmap;
1849 glx.GetConfig = Fake_glXGetConfig;
1850 /*glx.GetCurrentContext = Fake_glXGetCurrentContext;*/
1851 /*glx.GetCurrentDrawable = Fake_glXGetCurrentDrawable;*/
1852 glx.IsDirect = Fake_glXIsDirect;
1853 glx.MakeCurrent = Fake_glXMakeCurrent;
1854 glx.QueryExtension = Fake_glXQueryExtension;
1855 glx.QueryVersion = Fake_glXQueryVersion;
1856 glx.SwapBuffers = Fake_glXSwapBuffers;
1857 glx.UseXFont = Fake_glXUseXFont;
1858 glx.WaitGL = Fake_glXWaitGL;
1859 glx.WaitX = Fake_glXWaitX;
1860
1861 #ifdef _GLXAPI_VERSION_1_1
1862 glx.GetClientString = Fake_glXGetClientString;
1863 glx.QueryExtensionsString = Fake_glXQueryExtensionsString;
1864 glx.QueryServerString = Fake_glXQueryServerString;
1865 #endif
1866
1867 #ifdef _GLXAPI_VERSION_1_2
1868 /*glx.GetCurrentDisplay = Fake_glXGetCurrentDisplay;*/
1869 #endif
1870
1871 #ifdef _GLXAPI_VERSION_1_3
1872 glx.ChooseFBConfig = Fake_glXChooseFBConfig;
1873 glx.CreateNewContext = Fake_glXCreateNewContext;
1874 glx.CreatePbuffer = Fake_glXCreatePbuffer;
1875 glx.CreatePixmap = Fake_glXCreatePixmap;
1876 glx.CreateWindow = Fake_glXCreateWindow;
1877 glx.DestroyPbuffer = Fake_glXDestroyPbuffer;
1878 glx.DestroyPixmap = Fake_glXDestroyPixmap;
1879 glx.DestroyWindow = Fake_glXDestroyWindow;
1880 /*glx.GetCurrentReadDrawable = Fake_glXGetCurrentReadDrawable;*/
1881 glx.GetFBConfigAttrib = Fake_glXGetFBConfigAttrib;
1882 glx.GetFBConfigs = Fake_glXGetFBConfigs;
1883 glx.GetSelectedEvent = Fake_glXGetSelectedEvent;
1884 glx.GetVisualFromFBConfig = Fake_glXGetVisualFromFBConfig;
1885 glx.MakeContextCurrent = Fake_glXMakeContextCurrent;
1886 glx.QueryContext = Fake_glXQueryContext;
1887 glx.QueryDrawable = Fake_glXQueryDrawable;
1888 glx.SelectEvent = Fake_glXSelectEvent;
1889 #endif
1890
1891 #ifdef _GLXAPI_SGI_video_sync
1892 glx.GetVideoSyncSGI = Fake_glXGetVideoSyncSGI;
1893 glx.WaitVideoSyncSGI = Fake_glXWaitVideoSyncSGI;
1894 #endif
1895
1896 #ifdef _GLXAPI_MESA_copy_sub_buffer
1897 glx.CopySubBufferMESA = Fake_glXCopySubBufferMESA;
1898 #endif
1899
1900 #ifdef _GLXAPI_MESA_release_buffers
1901 glx.ReleaseBuffersMESA = Fake_glXReleaseBuffersMESA;
1902 #endif
1903
1904 #ifdef _GLXAPI_MESA_pixmap_colormap
1905 glx.CreateGLXPixmapMESA = Fake_glXCreateGLXPixmapMESA;
1906 #endif
1907
1908 #ifdef _GLXAPI_MESA_set_3dfx_mode
1909 glx.Set3DfxModeMESA = Fake_glXSet3DfxModeMESA;
1910 #endif
1911
1912 return &glx;
1913 }