added glXGetCurrentDisplay() for GLX 1.2
[mesa.git] / src / mesa / drivers / x11 / fakeglx.c
1 /* $Id: fakeglx.c,v 1.15 1999/11/22 21:52:23 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.3
6 *
7 * Copyright (C) 1999 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
30
31 /*
32 * A pseudo-GLX implementation to allow OpenGL/GLX programs to work with Mesa.
33 * The Fake_glX*() functions implemented here are called from glxapi.c
34 *
35 * Thanks to the contributors:
36 *
37 * Initial version: Philip Brown (philb@CSUA.Berkeley.EDU)
38 * Better glXGetConfig() support: Armin Liebchen (liebchen@asylum.cs.utah.edu)
39 * Further visual-handling refinements: Wolfram Gloger
40 * (wmglo@Dent.MED.Uni-Muenchen.DE).
41 *
42 * Notes:
43 * Don't be fooled, stereo isn't supported yet.
44 */
45
46
47
48 #include "glxheader.h"
49 #include "GL/xmesa.h"
50 #include "context.h"
51 #include "config.h"
52 #include "fakeglx.h"
53 #include "macros.h"
54 #include "types.h"
55 #include "xmesaP.h"
56
57
58
59 /* Silence compiler warnings */
60 void Fake_glXDummyFunc( void )
61 {
62 (void) kernel8;
63 (void) DitherValues;
64 (void) HPCR_DRGB;
65 (void) kernel1;
66 }
67
68
69
70 #define DONT_CARE -1
71
72
73
74 #define MAX_VISUALS 100
75 static XMesaVisual VisualTable[MAX_VISUALS];
76 static int NumVisuals = 0;
77
78
79
80 /*
81 * This struct and some code fragments borrowed
82 * from Mark Kilgard's GLUT library.
83 */
84 typedef struct _OverlayInfo {
85 /* Avoid 64-bit portability problems by being careful to use
86 longs due to the way XGetWindowProperty is specified. Note
87 that these parameters are passed as CARD32s over X
88 protocol. */
89 unsigned long overlay_visual;
90 long transparent_type;
91 long value;
92 long layer;
93 } OverlayInfo;
94
95
96
97 /* Macro to handle c_class vs class field name in XVisualInfo struct */
98 #if defined(__cplusplus) || defined(c_plusplus)
99 #define CLASS c_class
100 #else
101 #define CLASS class
102 #endif
103
104
105
106
107 /*
108 * Test if the given XVisualInfo is usable for Mesa rendering.
109 */
110 static GLboolean is_usable_visual( XVisualInfo *vinfo )
111 {
112 switch (vinfo->CLASS) {
113 case StaticGray:
114 case GrayScale:
115 /* Any StaticGray/GrayScale visual works in RGB or CI mode */
116 return GL_TRUE;
117 case StaticColor:
118 case PseudoColor:
119 /* Any StaticColor/PseudoColor visual of at least 4 bits */
120 if (vinfo->depth>=4) {
121 return GL_TRUE;
122 }
123 else {
124 return GL_FALSE;
125 }
126 case TrueColor:
127 case DirectColor:
128 /* Any depth of TrueColor or DirectColor works in RGB mode */
129 return GL_TRUE;
130 default:
131 /* This should never happen */
132 return GL_FALSE;
133 }
134 }
135
136
137
138 /*
139 * Return the level (overlay, normal, underlay) of a given XVisualInfo.
140 * Input: dpy - the X display
141 * vinfo - the XVisualInfo to test
142 * Return: level of the visual:
143 * 0 = normal planes
144 * >0 = overlay planes
145 * <0 = underlay planes
146 */
147 static int level_of_visual( Display *dpy, XVisualInfo *vinfo )
148 {
149 Atom overlayVisualsAtom;
150 OverlayInfo *overlay_info = NULL;
151 int numOverlaysPerScreen;
152 Status status;
153 Atom actualType;
154 int actualFormat;
155 unsigned long sizeData, bytesLeft;
156 int i;
157
158 /*
159 * The SERVER_OVERLAY_VISUALS property on the root window contains
160 * a list of overlay visuals. Get that list now.
161 */
162 overlayVisualsAtom = XInternAtom(dpy,"SERVER_OVERLAY_VISUALS", True);
163 if (overlayVisualsAtom == None) {
164 return 0;
165 }
166
167 status = XGetWindowProperty(dpy, RootWindow( dpy, vinfo->screen ),
168 overlayVisualsAtom, 0L, (long) 10000, False,
169 overlayVisualsAtom, &actualType, &actualFormat,
170 &sizeData, &bytesLeft,
171 (unsigned char **) &overlay_info );
172
173 if (status != Success || actualType != overlayVisualsAtom ||
174 actualFormat != 32 || sizeData < 4) {
175 /* something went wrong */
176 XFree((void *) overlay_info);
177 return 0;
178 }
179
180 /* search the overlay visual list for the visual ID of interest */
181 numOverlaysPerScreen = (int) (sizeData / 4);
182 for (i=0;i<numOverlaysPerScreen;i++) {
183 OverlayInfo *ov;
184 ov = overlay_info + i;
185 if (ov->overlay_visual==vinfo->visualid) {
186 /* found the visual */
187 if (/*ov->transparent_type==1 &&*/ ov->layer!=0) {
188 int level = ov->layer;
189 XFree((void *) overlay_info);
190 return level;
191 }
192 else {
193 XFree((void *) overlay_info);
194 return 0;
195 }
196 }
197 }
198
199 /* The visual ID was not found in the overlay list. */
200 XFree((void *) overlay_info);
201 return 0;
202 }
203
204
205
206
207 /*
208 * Given an XVisualInfo and RGB, Double, and Depth buffer flags, save the
209 * configuration in our list of GLX visuals.
210 */
211 static XMesaVisual
212 save_glx_visual( Display *dpy, XVisualInfo *vinfo,
213 GLboolean rgbFlag, GLboolean alphaFlag, GLboolean dbFlag,
214 GLboolean stereoFlag,
215 GLint depth_size, GLint stencil_size,
216 GLint accum_size, GLint level )
217 {
218 GLboolean ximageFlag = GL_TRUE;
219 XMesaVisual xmvis;
220 GLint i;
221 GLboolean comparePointers;
222
223 if (dbFlag) {
224 /* Check if the MESA_BACK_BUFFER env var is set */
225 char *backbuffer = getenv("MESA_BACK_BUFFER");
226 if (backbuffer) {
227 if (backbuffer[0]=='p' || backbuffer[0]=='P') {
228 ximageFlag = GL_FALSE;
229 }
230 else if (backbuffer[0]=='x' || backbuffer[0]=='X') {
231 ximageFlag = GL_TRUE;
232 }
233 else {
234 fprintf(stderr, "Mesa: invalid value for MESA_BACK_BUFFER ");
235 fprintf(stderr, "environment variable, using an XImage.\n");
236 }
237 }
238 }
239
240 /* Comparing IDs uses less memory but sometimes fails. */
241 /* XXX revisit this after 3.0 is finished. */
242 if (getenv("MESA_GLX_VISUAL_HACK"))
243 comparePointers = GL_TRUE;
244 else
245 comparePointers = GL_FALSE;
246
247 /* First check if a matching visual is already in the list */
248 for (i=0; i<NumVisuals; i++) {
249 XMesaVisual v = VisualTable[i];
250 if (v->display == dpy
251 && v->level == level
252 && v->ximage_flag == ximageFlag
253 && v->gl_visual->RGBAflag == rgbFlag
254 && v->gl_visual->DBflag == dbFlag
255 && v->gl_visual->StereoFlag == stereoFlag
256 && (v->gl_visual->AlphaBits > 0) == alphaFlag
257 && (v->gl_visual->DepthBits >= depth_size || depth_size == 0)
258 && (v->gl_visual->StencilBits >= stencil_size || stencil_size == 0)
259 && (v->gl_visual->AccumBits >= accum_size || accum_size == 0)) {
260 /* now either compare XVisualInfo pointers or visual IDs */
261 if ((!comparePointers && v->visinfo->visualid == vinfo->visualid)
262 || (comparePointers && v->vishandle == vinfo)) {
263 return v;
264 }
265 }
266 }
267
268 /* Create a new visual and add it to the list. */
269
270 if (NumVisuals>=MAX_VISUALS) {
271 fprintf( stderr, "GLX Error: maximum number of visuals exceeded\n");
272 return NULL;
273 }
274
275 xmvis = XMesaCreateVisual( dpy, vinfo, rgbFlag, alphaFlag, dbFlag,
276 stereoFlag, ximageFlag,
277 depth_size, stencil_size, accum_size, level );
278 if (xmvis) {
279 VisualTable[NumVisuals] = xmvis;
280 NumVisuals++;
281 }
282 return xmvis;
283 }
284
285
286
287 /*
288 * Create a GLX visual from a regular XVisualInfo.
289 */
290 static XMesaVisual
291 create_glx_visual( Display *dpy, XVisualInfo *visinfo )
292 {
293 int vislevel;
294
295 vislevel = level_of_visual( dpy, visinfo );
296 if (vislevel) {
297 /* Configure this visual as a CI, single-buffered overlay */
298 return save_glx_visual( dpy, visinfo,
299 GL_FALSE, /* rgb */
300 GL_FALSE, /* alpha */
301 GL_FALSE, /* double */
302 GL_FALSE, /* stereo */
303 0, /* depth bits */
304 0, /* stencil bits */
305 0, /* accum bits */
306 vislevel /* level */
307 );
308 }
309 else if (is_usable_visual( visinfo )) {
310 /* Configure this visual as RGB, double-buffered, depth-buffered. */
311 /* This is surely wrong for some people's needs but what else */
312 /* can be done? They should use glXChooseVisual(). */
313 return save_glx_visual( dpy, visinfo,
314 GL_TRUE, /* rgb */
315 GL_FALSE, /* alpha */
316 GL_TRUE, /* double */
317 GL_FALSE, /* stereo */
318 8*sizeof(GLdepth),
319 8*sizeof(GLstencil),
320 8*sizeof(GLaccum),
321 0 /* level */
322 );
323 }
324 else {
325 fprintf(stderr,"Mesa: error in glXCreateContext: bad visual\n");
326 return NULL;
327 }
328 }
329
330
331
332 /*
333 * Find the GLX visual associated with an XVisualInfo.
334 */
335 static XMesaVisual
336 find_glx_visual( Display *dpy, XVisualInfo *vinfo )
337 {
338 int i;
339
340 /* First try to match pointers */
341 for (i=0;i<NumVisuals;i++) {
342 if (VisualTable[i]->display==dpy && VisualTable[i]->vishandle==vinfo) {
343 return VisualTable[i];
344 }
345 }
346 /* try to match visual id */
347 for (i=0;i<NumVisuals;i++) {
348 if (VisualTable[i]->display==dpy
349 && VisualTable[i]->visinfo->visualid == vinfo->visualid) {
350 return VisualTable[i];
351 }
352 }
353 return NULL;
354 }
355
356
357
358 /*
359 * Return the transparent pixel value for a GLX visual.
360 * Input: glxvis - the glx_visual
361 * Return: a pixel value or -1 if no transparent pixel
362 */
363 static int transparent_pixel( XMesaVisual glxvis )
364 {
365 Display *dpy = glxvis->display;
366 XVisualInfo *vinfo = glxvis->visinfo;
367 Atom overlayVisualsAtom;
368 OverlayInfo *overlay_info = NULL;
369 int numOverlaysPerScreen;
370 Status status;
371 Atom actualType;
372 int actualFormat;
373 unsigned long sizeData, bytesLeft;
374 int i;
375
376 /*
377 * The SERVER_OVERLAY_VISUALS property on the root window contains
378 * a list of overlay visuals. Get that list now.
379 */
380 overlayVisualsAtom = XInternAtom(dpy,"SERVER_OVERLAY_VISUALS", True);
381 if (overlayVisualsAtom == None) {
382 return -1;
383 }
384
385 status = XGetWindowProperty(dpy, RootWindow( dpy, vinfo->screen ),
386 overlayVisualsAtom, 0L, (long) 10000, False,
387 overlayVisualsAtom, &actualType, &actualFormat,
388 &sizeData, &bytesLeft,
389 (unsigned char **) &overlay_info );
390
391 if (status != Success || actualType != overlayVisualsAtom ||
392 actualFormat != 32 || sizeData < 4) {
393 /* something went wrong */
394 XFree((void *) overlay_info);
395 return -1;
396 }
397
398 /* search the overlay visual list for the visual ID of interest */
399 numOverlaysPerScreen = (int) (sizeData / 4);
400 for (i=0;i<numOverlaysPerScreen;i++) {
401 OverlayInfo *ov;
402 ov = overlay_info + i;
403 if (ov->overlay_visual==vinfo->visualid) {
404 /* found it! */
405 if (ov->transparent_type==0) {
406 /* type 0 indicates no transparency */
407 XFree((void *) overlay_info);
408 return -1;
409 }
410 else {
411 /* ov->value is the transparent pixel */
412 XFree((void *) overlay_info);
413 return ov->value;
414 }
415 }
416 }
417
418 /* The visual ID was not found in the overlay list. */
419 XFree((void *) overlay_info);
420 return -1;
421 }
422
423
424
425 /*
426 * Return number of bits set in n.
427 */
428 static int bitcount( unsigned long n )
429 {
430 int bits;
431 for (bits=0; n>0; n=n>>1) {
432 if (n&1) {
433 bits++;
434 }
435 }
436 return bits;
437 }
438
439
440 /*
441 * Try to get an X visual which matches the given arguments.
442 */
443 static XVisualInfo *get_visual( Display *dpy, int scr,
444 unsigned int depth, int xclass )
445 {
446 XVisualInfo temp, *vis;
447 long mask;
448 int n;
449 unsigned int default_depth;
450 int default_class;
451
452 mask = VisualScreenMask | VisualDepthMask | VisualClassMask;
453 temp.screen = scr;
454 temp.depth = depth;
455 temp.CLASS = xclass;
456
457 default_depth = DefaultDepth(dpy,scr);
458 default_class = DefaultVisual(dpy,scr)->CLASS;
459
460 if (depth==default_depth && xclass==default_class) {
461 /* try to get root window's visual */
462 temp.visualid = DefaultVisual(dpy,scr)->visualid;
463 mask |= VisualIDMask;
464 }
465
466 vis = XGetVisualInfo( dpy, mask, &temp, &n );
467
468 /* In case bits/pixel > 24, make sure color channels are still <=8 bits.
469 * An SGI Infinite Reality system, for example, can have 30bpp pixels:
470 * 10 bits per color channel. Mesa's limited to a max of 8 bits/channel.
471 */
472 if (vis && depth > 24 && (xclass==TrueColor || xclass==DirectColor)) {
473 if (bitcount(vis->red_mask) <= 8
474 && bitcount(vis->green_mask) <= 8
475 && bitcount(vis->blue_mask) <= 8) {
476 return vis;
477 }
478 else {
479 XFree((void *) vis);
480 return NULL;
481 }
482 }
483
484 return vis;
485 }
486
487
488
489 /*
490 * Retrieve the value of the given environment variable and find
491 * the X visual which matches it.
492 * Input: dpy - the display
493 * screen - the screen number
494 * varname - the name of the environment variable
495 * Return: an XVisualInfo pointer to NULL if error.
496 */
497 static XVisualInfo *get_env_visual(Display *dpy, int scr, const char *varname)
498 {
499 char value[100], type[100];
500 int depth, xclass = -1;
501 XVisualInfo *vis;
502
503 if (!getenv( varname )) {
504 return NULL;
505 }
506
507 strncpy( value, getenv(varname), 100 );
508 value[99] = 0;
509
510 sscanf( value, "%s %d", type, &depth );
511
512 if (strcmp(type,"TrueColor")==0) xclass = TrueColor;
513 else if (strcmp(type,"DirectColor")==0) xclass = DirectColor;
514 else if (strcmp(type,"PseudoColor")==0) xclass = PseudoColor;
515 else if (strcmp(type,"StaticColor")==0) xclass = StaticColor;
516 else if (strcmp(type,"GrayScale")==0) xclass = GrayScale;
517 else if (strcmp(type,"StaticGray")==0) xclass = StaticGray;
518
519 if (xclass>-1 && depth>0) {
520 vis = get_visual( dpy, scr, depth, xclass );
521 if (vis) {
522 return vis;
523 }
524 }
525
526 fprintf( stderr, "Mesa: GLX unable to find visual class=%s, depth=%d.\n",
527 type, depth );
528 return NULL;
529 }
530
531
532
533 /*
534 * Select an X visual which satisfies the RGBA/CI flag and minimum depth.
535 * Input: dpy, screen - X display and screen number
536 * rgba - GL_TRUE = RGBA mode, GL_FALSE = CI mode
537 * min_depth - minimum visual depth
538 * preferred_class - preferred GLX visual class or DONT_CARE
539 * Return: pointer to an XVisualInfo or NULL.
540 */
541 static XVisualInfo *choose_x_visual( Display *dpy, int screen,
542 GLboolean rgba, int min_depth,
543 int preferred_class )
544 {
545 XVisualInfo *vis;
546 int xclass, visclass;
547 int depth;
548
549 if (rgba) {
550 Atom hp_cr_maps = XInternAtom(dpy, "_HP_RGB_SMOOTH_MAP_LIST", True);
551 /* First see if the MESA_RGB_VISUAL env var is defined */
552 vis = get_env_visual( dpy, screen, "MESA_RGB_VISUAL" );
553 if (vis) {
554 return vis;
555 }
556 /* Otherwise, search for a suitable visual */
557 if (preferred_class==DONT_CARE) {
558 for (xclass=0;xclass<6;xclass++) {
559 switch (xclass) {
560 case 0: visclass = TrueColor; break;
561 case 1: visclass = DirectColor; break;
562 case 2: visclass = PseudoColor; break;
563 case 3: visclass = StaticColor; break;
564 case 4: visclass = GrayScale; break;
565 case 5: visclass = StaticGray; break;
566 }
567 if (min_depth==0) {
568 /* start with shallowest */
569 for (depth=0;depth<=32;depth++) {
570 if (visclass==TrueColor && depth==8 && !hp_cr_maps) {
571 /* Special case: try to get 8-bit PseudoColor before */
572 /* 8-bit TrueColor */
573 vis = get_visual( dpy, screen, 8, PseudoColor );
574 if (vis) {
575 return vis;
576 }
577 }
578 vis = get_visual( dpy, screen, depth, visclass );
579 if (vis) {
580 return vis;
581 }
582 }
583 }
584 else {
585 /* start with deepest */
586 for (depth=32;depth>=min_depth;depth--) {
587 if (visclass==TrueColor && depth==8 && !hp_cr_maps) {
588 /* Special case: try to get 8-bit PseudoColor before */
589 /* 8-bit TrueColor */
590 vis = get_visual( dpy, screen, 8, PseudoColor );
591 if (vis) {
592 return vis;
593 }
594 }
595 vis = get_visual( dpy, screen, depth, visclass );
596 if (vis) {
597 return vis;
598 }
599 }
600 }
601 }
602 }
603 else {
604 /* search for a specific visual class */
605 switch (preferred_class) {
606 case GLX_TRUE_COLOR_EXT: visclass = TrueColor; break;
607 case GLX_DIRECT_COLOR_EXT: visclass = DirectColor; break;
608 case GLX_PSEUDO_COLOR_EXT: visclass = PseudoColor; break;
609 case GLX_STATIC_COLOR_EXT: visclass = StaticColor; break;
610 case GLX_GRAY_SCALE_EXT: visclass = GrayScale; break;
611 case GLX_STATIC_GRAY_EXT: visclass = StaticGray; break;
612 default: return NULL;
613 }
614 if (min_depth==0) {
615 /* start with shallowest */
616 for (depth=0;depth<=32;depth++) {
617 vis = get_visual( dpy, screen, depth, visclass );
618 if (vis) {
619 return vis;
620 }
621 }
622 }
623 else {
624 /* start with deepest */
625 for (depth=32;depth>=min_depth;depth--) {
626 vis = get_visual( dpy, screen, depth, visclass );
627 if (vis) {
628 return vis;
629 }
630 }
631 }
632 }
633 }
634 else {
635 /* First see if the MESA_CI_VISUAL env var is defined */
636 vis = get_env_visual( dpy, screen, "MESA_CI_VISUAL" );
637 if (vis) {
638 return vis;
639 }
640 /* Otherwise, search for a suitable visual, starting with shallowest */
641 if (preferred_class==DONT_CARE) {
642 for (xclass=0;xclass<4;xclass++) {
643 switch (xclass) {
644 case 0: visclass = PseudoColor; break;
645 case 1: visclass = StaticColor; break;
646 case 2: visclass = GrayScale; break;
647 case 3: visclass = StaticGray; break;
648 }
649 /* try 8-bit up through 16-bit */
650 for (depth=8;depth<=16;depth++) {
651 vis = get_visual( dpy, screen, depth, visclass );
652 if (vis) {
653 return vis;
654 }
655 }
656 /* try min_depth up to 8-bit */
657 for (depth=min_depth;depth<8;depth++) {
658 vis = get_visual( dpy, screen, depth, visclass );
659 if (vis) {
660 return vis;
661 }
662 }
663 }
664 }
665 else {
666 /* search for a specific visual class */
667 switch (preferred_class) {
668 case GLX_TRUE_COLOR_EXT: visclass = TrueColor; break;
669 case GLX_DIRECT_COLOR_EXT: visclass = DirectColor; break;
670 case GLX_PSEUDO_COLOR_EXT: visclass = PseudoColor; break;
671 case GLX_STATIC_COLOR_EXT: visclass = StaticColor; break;
672 case GLX_GRAY_SCALE_EXT: visclass = GrayScale; break;
673 case GLX_STATIC_GRAY_EXT: visclass = StaticGray; break;
674 default: return NULL;
675 }
676 /* try 8-bit up through 16-bit */
677 for (depth=8;depth<=16;depth++) {
678 vis = get_visual( dpy, screen, depth, visclass );
679 if (vis) {
680 return vis;
681 }
682 }
683 /* try min_depth up to 8-bit */
684 for (depth=min_depth;depth<8;depth++) {
685 vis = get_visual( dpy, screen, depth, visclass );
686 if (vis) {
687 return vis;
688 }
689 }
690 }
691 }
692
693 /* didn't find a visual */
694 return NULL;
695 }
696
697
698
699 /*
700 * Find the deepest X over/underlay visual of at least min_depth.
701 * Input: dpy, screen - X display and screen number
702 * level - the over/underlay level
703 * trans_type - transparent pixel type: GLX_NONE_EXT,
704 * GLX_TRANSPARENT_RGB_EXT, GLX_TRANSPARENT_INDEX_EXT,
705 * or DONT_CARE
706 * trans_value - transparent pixel value or DONT_CARE
707 * min_depth - minimum visual depth
708 * preferred_class - preferred GLX visual class or DONT_CARE
709 * Return: pointer to an XVisualInfo or NULL.
710 */
711 static XVisualInfo *choose_x_overlay_visual( Display *dpy, int scr,
712 GLboolean rgbFlag,
713 int level, int trans_type,
714 int trans_value,
715 int min_depth,
716 int preferred_class )
717 {
718 Atom overlayVisualsAtom;
719 OverlayInfo *overlay_info;
720 int numOverlaysPerScreen;
721 Status status;
722 Atom actualType;
723 int actualFormat;
724 unsigned long sizeData, bytesLeft;
725 int i;
726 XVisualInfo *deepvis;
727 int deepest;
728
729 /*DEBUG int tt, tv; */
730
731 switch (preferred_class) {
732 case GLX_TRUE_COLOR_EXT: preferred_class = TrueColor; break;
733 case GLX_DIRECT_COLOR_EXT: preferred_class = DirectColor; break;
734 case GLX_PSEUDO_COLOR_EXT: preferred_class = PseudoColor; break;
735 case GLX_STATIC_COLOR_EXT: preferred_class = StaticColor; break;
736 case GLX_GRAY_SCALE_EXT: preferred_class = GrayScale; break;
737 case GLX_STATIC_GRAY_EXT: preferred_class = StaticGray; break;
738 default: preferred_class = DONT_CARE;
739 }
740
741 /*
742 * The SERVER_OVERLAY_VISUALS property on the root window contains
743 * a list of overlay visuals. Get that list now.
744 */
745 overlayVisualsAtom = XInternAtom(dpy,"SERVER_OVERLAY_VISUALS", True);
746 if (overlayVisualsAtom == (Atom) None) {
747 return NULL;
748 }
749
750 status = XGetWindowProperty(dpy, RootWindow( dpy, scr ),
751 overlayVisualsAtom, 0L, (long) 10000, False,
752 overlayVisualsAtom, &actualType, &actualFormat,
753 &sizeData, &bytesLeft,
754 (unsigned char **) &overlay_info );
755
756 if (status != Success || actualType != overlayVisualsAtom ||
757 actualFormat != 32 || sizeData < 4) {
758 /* something went wrong */
759 return NULL;
760 }
761
762 /* Search for the deepest overlay which satisifies all criteria. */
763 deepest = min_depth;
764 deepvis = NULL;
765
766 numOverlaysPerScreen = (int) (sizeData / 4);
767 for (i=0;i<numOverlaysPerScreen;i++) {
768 XVisualInfo *vislist, vistemplate;
769 int count;
770 OverlayInfo *ov;
771 ov = overlay_info + i;
772
773 if (ov->layer!=level) {
774 /* failed overlay level criteria */
775 continue;
776 }
777 if (!(trans_type==DONT_CARE
778 || (trans_type==GLX_TRANSPARENT_INDEX_EXT
779 && ov->transparent_type>0)
780 || (trans_type==GLX_NONE_EXT && ov->transparent_type==0))) {
781 /* failed transparent pixel type criteria */
782 continue;
783 }
784 if (trans_value!=DONT_CARE && trans_value!=ov->value) {
785 /* failed transparent pixel value criteria */
786 continue;
787 }
788
789 /* get XVisualInfo and check the depth */
790 vistemplate.visualid = ov->overlay_visual;
791 vistemplate.screen = scr;
792 vislist = XGetVisualInfo( dpy, VisualIDMask | VisualScreenMask,
793 &vistemplate, &count );
794
795 if (count!=1) {
796 /* something went wrong */
797 continue;
798 }
799 if (preferred_class!=DONT_CARE && preferred_class!=vislist->CLASS) {
800 /* wrong visual class */
801 continue;
802 }
803
804 /* if RGB was requested, make sure we have True/DirectColor */
805 if (rgbFlag && vislist->CLASS != TrueColor
806 && vislist->CLASS != DirectColor)
807 continue;
808
809 /* if CI was requested, make sure we have a color indexed visual */
810 if (!rgbFlag
811 && (vislist->CLASS == TrueColor || vislist->CLASS == DirectColor))
812 continue;
813
814 if (deepvis==NULL || vislist->depth > deepest) {
815 /* YES! found a satisfactory visual */
816 if (deepvis) {
817 XFree( deepvis );
818 }
819 deepest = vislist->depth;
820 deepvis = vislist;
821 /* DEBUG tt = ov->transparent_type;*/
822 /* DEBUG tv = ov->value; */
823 }
824 }
825
826 /*DEBUG
827 if (deepvis) {
828 printf("chose 0x%x: layer=%d depth=%d trans_type=%d trans_value=%d\n",
829 deepvis->visualid, level, deepvis->depth, tt, tv );
830 }
831 */
832 return deepvis;
833 }
834
835
836
837 XVisualInfo *Fake_glXChooseVisual( Display *dpy, int screen, int *list )
838 {
839 int *parselist;
840 XVisualInfo *vis;
841 int min_ci = 0;
842 int min_red=0, min_green=0, min_blue=0;
843 GLboolean rgb_flag = GL_FALSE;
844 GLboolean alpha_flag = GL_FALSE;
845 GLboolean double_flag = GL_FALSE;
846 GLboolean stereo_flag = GL_FALSE;
847 GLint depth_size = 0;
848 GLint stencil_size = 0;
849 GLint accum_size = 0;
850 int level = 0;
851 int visual_type = DONT_CARE;
852 int trans_type = DONT_CARE;
853 int trans_value = DONT_CARE;
854
855 parselist = list;
856
857 while (*parselist) {
858
859 switch (*parselist) {
860 case GLX_USE_GL:
861 /* ignore */
862 parselist++;
863 break;
864 case GLX_BUFFER_SIZE:
865 parselist++;
866 min_ci = *parselist++;
867 break;
868 case GLX_LEVEL:
869 parselist++;
870 level = *parselist++;
871 break;
872 case GLX_RGBA:
873 rgb_flag = GL_TRUE;
874 parselist++;
875 break;
876 case GLX_DOUBLEBUFFER:
877 double_flag = GL_TRUE;
878 parselist++;
879 break;
880 case GLX_STEREO:
881 stereo_flag = GL_TRUE;
882 return NULL;
883 case GLX_AUX_BUFFERS:
884 /* ignore */
885 parselist++;
886 parselist++;
887 break;
888 case GLX_RED_SIZE:
889 parselist++;
890 min_red = *parselist++;
891 break;
892 case GLX_GREEN_SIZE:
893 parselist++;
894 min_green = *parselist++;
895 break;
896 case GLX_BLUE_SIZE:
897 parselist++;
898 min_blue = *parselist++;
899 break;
900 case GLX_ALPHA_SIZE:
901 parselist++;
902 {
903 GLint size = *parselist++;
904 alpha_flag = size>0 ? 1 : 0;
905 }
906 break;
907 case GLX_DEPTH_SIZE:
908 parselist++;
909 depth_size = *parselist++;
910 break;
911 case GLX_STENCIL_SIZE:
912 parselist++;
913 stencil_size = *parselist++;
914 break;
915 case GLX_ACCUM_RED_SIZE:
916 case GLX_ACCUM_GREEN_SIZE:
917 case GLX_ACCUM_BLUE_SIZE:
918 case GLX_ACCUM_ALPHA_SIZE:
919 parselist++;
920 {
921 GLint size = *parselist++;
922 accum_size = MAX2( accum_size, size );
923 }
924 break;
925
926 /*
927 * GLX_EXT_visual_info extension
928 */
929 case GLX_X_VISUAL_TYPE_EXT:
930 parselist++;
931 visual_type = *parselist++;
932 break;
933 case GLX_TRANSPARENT_TYPE_EXT:
934 parselist++;
935 trans_type = *parselist++;
936 break;
937 case GLX_TRANSPARENT_INDEX_VALUE_EXT:
938 parselist++;
939 trans_value = *parselist++;
940 break;
941 case GLX_TRANSPARENT_RED_VALUE_EXT:
942 case GLX_TRANSPARENT_GREEN_VALUE_EXT:
943 case GLX_TRANSPARENT_BLUE_VALUE_EXT:
944 case GLX_TRANSPARENT_ALPHA_VALUE_EXT:
945 /* ignore */
946 parselist++;
947 parselist++;
948 break;
949
950 case None:
951 break;
952 default:
953 /* undefined attribute */
954 return NULL;
955 }
956 }
957
958 /*
959 * Since we're only simulating the GLX extension this function will never
960 * find any real GL visuals. Instead, all we can do is try to find an RGB
961 * or CI visual of appropriate depth. Other requested attributes such as
962 * double buffering, depth buffer, etc. will be associated with the X
963 * visual and stored in the VisualTable[].
964 */
965 if (level==0) {
966 /* normal color planes */
967 if (rgb_flag) {
968 /* Get an RGB visual */
969 int min_rgb = min_red + min_green + min_blue;
970 if (min_rgb>1 && min_rgb<8) {
971 /* a special case to be sure we can get a monochrome visual */
972 min_rgb = 1;
973 }
974 vis = choose_x_visual( dpy, screen, rgb_flag, min_rgb, visual_type );
975 }
976 else {
977 /* Get a color index visual */
978 vis = choose_x_visual( dpy, screen, rgb_flag, min_ci, visual_type );
979 accum_size = 0;
980 }
981 }
982 else {
983 /* over/underlay planes */
984 if (rgb_flag) {
985 /* rgba overlay */
986 int min_rgb = min_red + min_green + min_blue;
987 if (min_rgb>1 && min_rgb<8) {
988 /* a special case to be sure we can get a monochrome visual */
989 min_rgb = 1;
990 }
991 vis = choose_x_overlay_visual( dpy, screen, rgb_flag, level,
992 trans_type, trans_value, min_rgb, visual_type );
993 }
994 else {
995 /* color index overlay */
996 vis = choose_x_overlay_visual( dpy, screen, rgb_flag, level,
997 trans_type, trans_value, min_ci, visual_type );
998 }
999 }
1000
1001 if (vis) {
1002 if (!save_glx_visual( dpy, vis, rgb_flag, alpha_flag, double_flag,
1003 stereo_flag,
1004 depth_size, stencil_size, accum_size, level ))
1005 return NULL;
1006 }
1007
1008 return vis;
1009 }
1010
1011
1012
1013
1014 GLXContext Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo,
1015 GLXContext share_list, Bool direct )
1016 {
1017 XMesaVisual glxvis;
1018 XMesaContext xmctx;
1019
1020 /* deallocate unused windows/buffers */
1021 XMesaGarbageCollect();
1022
1023 glxvis = find_glx_visual( dpy, visinfo );
1024 if (!glxvis) {
1025 /* This visual wasn't found with glXChooseVisual() */
1026 glxvis = create_glx_visual( dpy, visinfo );
1027 if (!glxvis) {
1028 /* unusable visual */
1029 return NULL;
1030 }
1031 }
1032
1033 xmctx = XMesaCreateContext( glxvis, (XMesaContext) share_list );
1034 if (xmctx) {
1035 /* set the direct/indirect flag */
1036 xmctx->direct = direct;
1037 }
1038 return (GLXContext) xmctx;
1039 }
1040
1041
1042 static GLXDrawable MakeCurrent_PrevDrawable = 0;
1043 static GLXContext MakeCurrent_PrevContext = 0;
1044 static XMesaBuffer MakeCurrent_PrevBuffer = 0;
1045
1046 Bool Fake_glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx )
1047 {
1048 if (ctx && drawable) {
1049 XMesaBuffer buffer;
1050 XMesaContext xmctx = (XMesaContext) ctx;
1051
1052 if (drawable==MakeCurrent_PrevDrawable && ctx==MakeCurrent_PrevContext) {
1053 buffer = MakeCurrent_PrevBuffer;
1054 }
1055 else {
1056 buffer = XMesaFindBuffer( dpy, drawable );
1057 }
1058 if (!buffer) {
1059 /* drawable must be a new window! */
1060 buffer = XMesaCreateWindowBuffer2( xmctx->xm_visual, drawable, ctx );
1061 if (!buffer) {
1062 /* Out of memory, or context/drawable depth mismatch */
1063 return False;
1064 }
1065 }
1066 MakeCurrent_PrevContext = ctx;
1067 MakeCurrent_PrevDrawable = drawable;
1068 MakeCurrent_PrevBuffer = buffer;
1069
1070 /* Now make current! */
1071 return (Bool) XMesaMakeCurrent( (XMesaContext) ctx, buffer );
1072 }
1073 else if (!ctx && !drawable) {
1074 /* release current context w/out assigning new one. */
1075 XMesaMakeCurrent( NULL, NULL );
1076 MakeCurrent_PrevContext = 0;
1077 MakeCurrent_PrevDrawable = 0;
1078 MakeCurrent_PrevBuffer = 0;
1079 return True;
1080 }
1081 else {
1082 /* ctx XOR drawable is NULL, this is an error */
1083 return False;
1084 }
1085 }
1086
1087
1088
1089 GLXPixmap Fake_glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo,
1090 Pixmap pixmap )
1091 {
1092 XMesaVisual v;
1093 XMesaBuffer b;
1094
1095 v = find_glx_visual( dpy, visinfo );
1096 if (!v) {
1097 v = create_glx_visual( dpy, visinfo );
1098 if (!v) {
1099 /* unusable visual */
1100 return 0;
1101 }
1102 }
1103
1104 b = XMesaCreatePixmapBuffer( v, pixmap, 0 );
1105 if (!b) {
1106 return 0;
1107 }
1108 return b->frontbuffer;
1109 }
1110
1111
1112 #ifdef GLX_MESA_pixmap_colormap
1113
1114 GLXPixmap Fake_glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo,
1115 Pixmap pixmap, Colormap cmap )
1116 {
1117 XMesaVisual v;
1118 XMesaBuffer b;
1119
1120 v = find_glx_visual( dpy, visinfo );
1121 if (!v) {
1122 v = create_glx_visual( dpy, visinfo );
1123 if (!v) {
1124 /* unusable visual */
1125 return 0;
1126 }
1127 }
1128
1129 b = XMesaCreatePixmapBuffer( v, pixmap, cmap );
1130 if (!b) {
1131 return 0;
1132 }
1133 return b->frontbuffer;
1134 }
1135
1136 #endif
1137
1138
1139 void Fake_glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap )
1140 {
1141 XMesaBuffer b = XMesaFindBuffer(dpy, pixmap);
1142 if (b) {
1143 XMesaDestroyBuffer(b);
1144 }
1145 else if (getenv("MESA_DEBUG")) {
1146 fprintf( stderr, "Mesa: glXDestroyGLXPixmap: invalid pixmap\n");
1147 }
1148 }
1149
1150
1151 void Fake_glXCopyContext( Display *dpy, GLXContext src, GLXContext dst,
1152 GLuint mask )
1153 {
1154 XMesaContext xm_src = (XMesaContext) src;
1155 XMesaContext xm_dst = (XMesaContext) dst;
1156 (void) dpy;
1157 gl_copy_context( xm_src->gl_ctx, xm_dst->gl_ctx, mask );
1158 }
1159
1160
1161
1162 Bool Fake_glXQueryExtension( Display *dpy, int *errorb, int *event )
1163 {
1164 /* Mesa's GLX isn't really an X extension but we try to act like one. */
1165 (void) dpy;
1166 (void) errorb;
1167 (void) event;
1168 return True;
1169 }
1170
1171
1172 void _kw_ungrab_all( Display *dpy )
1173 {
1174 XUngrabPointer( dpy, CurrentTime );
1175 XUngrabKeyboard( dpy, CurrentTime );
1176 }
1177
1178
1179 void Fake_glXDestroyContext( Display *dpy, GLXContext ctx )
1180 {
1181 (void) dpy;
1182 MakeCurrent_PrevContext = 0;
1183 MakeCurrent_PrevDrawable = 0;
1184 MakeCurrent_PrevBuffer = 0;
1185 XMesaDestroyContext( (XMesaContext) ctx );
1186 XMesaGarbageCollect();
1187 }
1188
1189
1190
1191 Bool Fake_glXIsDirect( Display *dpy, GLXContext ctx )
1192 {
1193 (void) dpy;
1194 return ((XMesaContext) ctx)->direct;
1195 }
1196
1197
1198
1199 void Fake_glXSwapBuffers( Display *dpy, GLXDrawable drawable )
1200 {
1201 XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable );
1202
1203 if (buffer) {
1204 XMesaSwapBuffers(buffer);
1205 }
1206 else if (getenv("MESA_DEBUG")) {
1207 fprintf(stderr, "Mesa Warning: glXSwapBuffers: invalid drawable\n");
1208 }
1209 }
1210
1211
1212 void Fake_glXCopySubBufferMESA( Display *dpy, GLXDrawable drawable,
1213 int x, int y, int width, int height )
1214 {
1215 XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable );
1216 if (buffer) {
1217 XMesaCopySubBuffer(buffer, x, y, width, height);
1218 }
1219 else if (getenv("MESA_DEBUG")) {
1220 fprintf(stderr, "Mesa Warning: glXCopySubBufferMESA: invalid drawable\n");
1221 }
1222 }
1223
1224
1225
1226 Bool Fake_glXQueryVersion( Display *dpy, int *maj, int *min )
1227 {
1228 (void) dpy;
1229 /* Return GLX version, not Mesa version */
1230 *maj = 1;
1231 *min = 1;
1232 return True;
1233 }
1234
1235
1236
1237 /*
1238 * Query the GLX attributes of the given XVisualInfo.
1239 */
1240 int Fake_glXGetConfig( Display *dpy, XVisualInfo *visinfo,
1241 int attrib, int *value )
1242 {
1243 XMesaVisual glxvis;
1244
1245 glxvis = find_glx_visual( dpy, visinfo );
1246 if (!glxvis) {
1247 /* this visual wasn't obtained with glXChooseVisual */
1248 glxvis = create_glx_visual( dpy, visinfo );
1249 if (!glxvis) {
1250 /* this visual can't be used for GL rendering */
1251 if (attrib==GLX_USE_GL) {
1252 *value = (int) False;
1253 return 0;
1254 }
1255 else {
1256 /*fprintf( stderr, "Mesa: Error in glXGetConfig: bad visual\n");*/
1257 return GLX_BAD_VISUAL;
1258 }
1259 }
1260 }
1261
1262 switch(attrib) {
1263 case GLX_USE_GL:
1264 *value = (int) True;
1265 return 0;
1266 case GLX_BUFFER_SIZE:
1267 *value = visinfo->depth;
1268 return 0;
1269 case GLX_LEVEL:
1270 *value = glxvis->level;
1271 return 0;
1272 case GLX_RGBA:
1273 if (glxvis->gl_visual->RGBAflag) {
1274 *value = True;
1275 }
1276 else {
1277 *value = False;
1278 }
1279 return 0;
1280 case GLX_DOUBLEBUFFER:
1281 *value = (int) glxvis->gl_visual->DBflag;
1282 return 0;
1283 case GLX_STEREO:
1284 *value = (int) glxvis->gl_visual->StereoFlag;
1285 return 0;
1286 case GLX_AUX_BUFFERS:
1287 *value = (int) False;
1288 return 0;
1289 case GLX_RED_SIZE:
1290 *value = glxvis->gl_visual->RedBits;
1291 return 0;
1292 case GLX_GREEN_SIZE:
1293 *value = glxvis->gl_visual->GreenBits;
1294 return 0;
1295 case GLX_BLUE_SIZE:
1296 *value = glxvis->gl_visual->BlueBits;
1297 return 0;
1298 case GLX_ALPHA_SIZE:
1299 *value = glxvis->gl_visual->AlphaBits;
1300 return 0;
1301 case GLX_DEPTH_SIZE:
1302 *value = glxvis->gl_visual->DepthBits;
1303 return 0;
1304 case GLX_STENCIL_SIZE:
1305 *value = glxvis->gl_visual->StencilBits;
1306 return 0;
1307 case GLX_ACCUM_RED_SIZE:
1308 case GLX_ACCUM_GREEN_SIZE:
1309 case GLX_ACCUM_BLUE_SIZE:
1310 *value = glxvis->gl_visual->AccumBits;
1311 return 0;
1312 case GLX_ACCUM_ALPHA_SIZE:
1313 if (glxvis->gl_visual->AlphaBits > 0)
1314 *value = glxvis->gl_visual->AccumBits;
1315 else
1316 *value = 0;
1317 return 0;
1318
1319 /*
1320 * GLX_EXT_visual_info extension
1321 */
1322 case GLX_X_VISUAL_TYPE_EXT:
1323 switch (glxvis->visinfo->CLASS) {
1324 case StaticGray: *value = GLX_STATIC_GRAY_EXT; return 0;
1325 case GrayScale: *value = GLX_GRAY_SCALE_EXT; return 0;
1326 case StaticColor: *value = GLX_STATIC_GRAY_EXT; return 0;
1327 case PseudoColor: *value = GLX_PSEUDO_COLOR_EXT; return 0;
1328 case TrueColor: *value = GLX_TRUE_COLOR_EXT; return 0;
1329 case DirectColor: *value = GLX_DIRECT_COLOR_EXT; return 0;
1330 }
1331 return 0;
1332 case GLX_TRANSPARENT_TYPE_EXT:
1333 if (glxvis->level==0) {
1334 /* normal planes */
1335 *value = GLX_NONE_EXT;
1336 }
1337 else if (glxvis->level>0) {
1338 /* overlay */
1339 if (glxvis->gl_visual->RGBAflag) {
1340 *value = GLX_TRANSPARENT_RGB_EXT;
1341 }
1342 else {
1343 *value = GLX_TRANSPARENT_INDEX_EXT;
1344 }
1345 }
1346 else if (glxvis->level<0) {
1347 /* underlay */
1348 *value = GLX_NONE_EXT;
1349 }
1350 return 0;
1351 case GLX_TRANSPARENT_INDEX_VALUE_EXT:
1352 {
1353 int pixel = transparent_pixel( glxvis );
1354 if (pixel>=0) {
1355 *value = pixel;
1356 }
1357 /* else undefined */
1358 }
1359 return 0;
1360 case GLX_TRANSPARENT_RED_VALUE_EXT:
1361 /* undefined */
1362 return 0;
1363 case GLX_TRANSPARENT_GREEN_VALUE_EXT:
1364 /* undefined */
1365 return 0;
1366 case GLX_TRANSPARENT_BLUE_VALUE_EXT:
1367 /* undefined */
1368 return 0;
1369 case GLX_TRANSPARENT_ALPHA_VALUE_EXT:
1370 /* undefined */
1371 return 0;
1372
1373 /*
1374 * Extensions
1375 */
1376 default:
1377 return GLX_BAD_ATTRIBUTE;
1378 }
1379 }
1380
1381
1382
1383 GLXContext Fake_glXGetCurrentContext( void )
1384 {
1385 return (GLXContext) XMesaGetCurrentContext();
1386 }
1387
1388
1389
1390 GLXDrawable Fake_glXGetCurrentDrawable( void )
1391 {
1392 XMesaBuffer b = XMesaGetCurrentBuffer();
1393 if (b) {
1394 return b->frontbuffer;
1395 }
1396 else {
1397 return 0;
1398 }
1399 }
1400
1401
1402 void Fake_glXWaitGL( void )
1403 {
1404 XMesaContext xmesa = XMesaGetCurrentContext();
1405 XMesaFlush( xmesa );
1406 }
1407
1408
1409
1410 void Fake_glXWaitX( void )
1411 {
1412 XMesaContext xmesa = XMesaGetCurrentContext();
1413 XMesaFlush( xmesa );
1414 }
1415
1416
1417 /*
1418 * Return the extensions string, which is 3Dfx-dependant.
1419 */
1420 static const char *get_extensions( void )
1421 {
1422 #ifdef FX
1423 const char *fx = getenv("MESA_GLX_FX");
1424 if (fx && fx[0] != 'd') {
1425 return "GLX_MESA_pixmap_colormap GLX_EXT_visual_info GLX_MESA_release_buffers GLX_MESA_copy_sub_buffer GLX_SGI_video_sync GLX_EXT_get_proc_address GLX_MESA_set_3dfx_mode";
1426 }
1427 #endif
1428 return "GLX_MESA_pixmap_colormap GLX_EXT_visual_info GLX_MESA_release_buffers GLX_MESA_copy_sub_buffer GLX_SGI_video_sync GL_EXT_get_proc_address";
1429 }
1430
1431
1432
1433 /* GLX 1.1 and later */
1434 const char *Fake_glXQueryExtensionsString( Display *dpy, int screen )
1435 {
1436 (void) dpy;
1437 (void) screen;
1438 return get_extensions();
1439 }
1440
1441
1442
1443 /* GLX 1.1 and later */
1444 const char *Fake_glXQueryServerString( Display *dpy, int screen, int name )
1445 {
1446 static char *vendor = "Brian Paul";
1447 static char *version = "1.1 Mesa 3.1";
1448
1449 (void) dpy;
1450 (void) screen;
1451
1452 switch (name) {
1453 case GLX_EXTENSIONS:
1454 return get_extensions();
1455 case GLX_VENDOR:
1456 return vendor;
1457 case GLX_VERSION:
1458 return version;
1459 default:
1460 return NULL;
1461 }
1462 }
1463
1464
1465
1466 /* GLX 1.1 and later */
1467 const char *Fake_glXGetClientString( Display *dpy, int name )
1468 {
1469 static char *vendor = "Brian Paul";
1470 static char *version = "1.1 Mesa 3.1";
1471
1472 (void) dpy;
1473
1474 switch (name) {
1475 case GLX_EXTENSIONS:
1476 return get_extensions();
1477 case GLX_VENDOR:
1478 return vendor;
1479 case GLX_VERSION:
1480 return version;
1481 default:
1482 return NULL;
1483 }
1484 }
1485
1486
1487
1488 /* GLX 1.2 and later */
1489 Display *Fake_glXGetCurrentDisplay( void )
1490 {
1491 XMesaContext xmesa = XMesaGetCurrentContext();
1492 if (xmesa && xmesa->xm_visual)
1493 return xmesa->xm_visual->display;
1494 else
1495 return NULL;
1496 }
1497
1498
1499
1500 /*
1501 * Release the depth, stencil, accum buffers attached to a GLXDrawable
1502 * (a window or pixmap) prior to destroying the GLXDrawable.
1503 */
1504 Bool Fake_glXReleaseBuffersMESA( Display *dpy, GLXDrawable d )
1505 {
1506 XMesaBuffer b = XMesaFindBuffer(dpy, d);
1507 if (b) {
1508 XMesaDestroyBuffer(b);
1509 return True;
1510 }
1511 return False;
1512 }
1513
1514
1515 /*
1516 * GLX_MESA_set_3dfx_mode
1517 */
1518 GLboolean Fake_glXSet3DfxModeMESA( GLint mode )
1519 {
1520 return XMesaSetFXmode( mode );
1521 }
1522
1523
1524
1525 #if 0
1526 /*GLfunction Fake_glXGetProcAddress( const GLubyte *procName )*/
1527 void (*Fake_glXGetProcAddress( const GLubyte *procName ))()
1528 {
1529 typedef void (*GLfunction)();
1530 struct proc {
1531 const char *name;
1532 GLfunction address;
1533 };
1534 static struct proc procTable[] = {
1535 { "glXGetProcAddressEXT", (GLfunction) glXGetProcAddressEXT },
1536 { "glXCreateGLXPixmapMESA", (GLfunction) glXCreateGLXPixmapMESA },
1537 { "glXReleaseBuffersMESA", (GLfunction) glXReleaseBuffersMESA },
1538 { "glXCopySubBufferMESA", (GLfunction) glXCopySubBufferMESA },
1539 { "glXSet3DfxModeMESA", (GLfunction) glXSet3DfxModeMESA },
1540 /* NOTE: GLX_SGI_video_sync not implemented in Mesa */
1541 { NULL, NULL } /* end of list token */
1542 };
1543 GLuint i;
1544
1545 /* First, look for core library functions */
1546 GLfunction f = (GLfunction) gl_get_proc_address(procName);
1547 if (f)
1548 return f;
1549
1550 /* Second, look for GLX funtion */
1551 for (i = 0; procTable[i].address; i++) {
1552 if (strcmp((const char *) procName, procTable[i].name) == 0)
1553 return (GLfunction) procTable[i].address;
1554 }
1555
1556 return NULL;
1557 }
1558 #endif