1 /* $Id: fakeglx.c,v 1.22 2000/02/23 23:09:12 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
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:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
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.
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.
32 * Thanks to the contributors:
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).
40 * Don't be fooled, stereo isn't supported yet.
45 #include "glxheader.h"
55 /* This indicates the client-side GLX API and GLX encoder version. */
56 #define CLIENT_MAJOR_VERSION 1
57 #define CLIENT_MINOR_VERSION 2
59 /* This indicates the server-side GLX decoder version.
60 * GLX 1.3 indicates OpenGL 1.2 support
62 #define SERVER_MAJOR_VERSION 1
63 #define SERVER_MINOR_VERSION 3
65 /* This is appended onto the glXGetClient/ServerString version strings. */
66 #define MESA_GLX_VERSION "Mesa 3.3"
68 /* Who implemented this GLX? */
69 #define VENDOR "Brian Paul"
73 /* Silence compiler warnings */
74 void Fake_glXDummyFunc( void )
88 #define MAX_VISUALS 100
89 static XMesaVisual VisualTable
[MAX_VISUALS
];
90 static int NumVisuals
= 0;
95 * This struct and some code fragments borrowed
96 * from Mark Kilgard's GLUT library.
98 typedef struct _OverlayInfo
{
99 /* Avoid 64-bit portability problems by being careful to use
100 longs due to the way XGetWindowProperty is specified. Note
101 that these parameters are passed as CARD32s over X
103 unsigned long overlay_visual
;
104 long transparent_type
;
111 /* Macro to handle c_class vs class field name in XVisualInfo struct */
112 #if defined(__cplusplus) || defined(c_plusplus)
113 #define CLASS c_class
122 * Test if the given XVisualInfo is usable for Mesa rendering.
124 static GLboolean
is_usable_visual( XVisualInfo
*vinfo
)
126 switch (vinfo
->CLASS
) {
129 /* Any StaticGray/GrayScale visual works in RGB or CI mode */
133 /* Any StaticColor/PseudoColor visual of at least 4 bits */
134 if (vinfo
->depth
>=4) {
142 /* Any depth of TrueColor or DirectColor works in RGB mode */
145 /* This should never happen */
153 * Return the level (overlay, normal, underlay) of a given XVisualInfo.
154 * Input: dpy - the X display
155 * vinfo - the XVisualInfo to test
156 * Return: level of the visual:
158 * >0 = overlay planes
159 * <0 = underlay planes
161 static int level_of_visual( Display
*dpy
, XVisualInfo
*vinfo
)
163 Atom overlayVisualsAtom
;
164 OverlayInfo
*overlay_info
= NULL
;
165 int numOverlaysPerScreen
;
169 unsigned long sizeData
, bytesLeft
;
173 * The SERVER_OVERLAY_VISUALS property on the root window contains
174 * a list of overlay visuals. Get that list now.
176 overlayVisualsAtom
= XInternAtom(dpy
,"SERVER_OVERLAY_VISUALS", True
);
177 if (overlayVisualsAtom
== None
) {
181 status
= XGetWindowProperty(dpy
, RootWindow( dpy
, vinfo
->screen
),
182 overlayVisualsAtom
, 0L, (long) 10000, False
,
183 overlayVisualsAtom
, &actualType
, &actualFormat
,
184 &sizeData
, &bytesLeft
,
185 (unsigned char **) &overlay_info
);
187 if (status
!= Success
|| actualType
!= overlayVisualsAtom
||
188 actualFormat
!= 32 || sizeData
< 4) {
189 /* something went wrong */
190 XFree((void *) overlay_info
);
194 /* search the overlay visual list for the visual ID of interest */
195 numOverlaysPerScreen
= (int) (sizeData
/ 4);
196 for (i
=0;i
<numOverlaysPerScreen
;i
++) {
198 ov
= overlay_info
+ i
;
199 if (ov
->overlay_visual
==vinfo
->visualid
) {
200 /* found the visual */
201 if (/*ov->transparent_type==1 &&*/ ov
->layer
!=0) {
202 int level
= ov
->layer
;
203 XFree((void *) overlay_info
);
207 XFree((void *) overlay_info
);
213 /* The visual ID was not found in the overlay list. */
214 XFree((void *) overlay_info
);
222 * Given an XVisualInfo and RGB, Double, and Depth buffer flags, save the
223 * configuration in our list of GLX visuals.
226 save_glx_visual( Display
*dpy
, XVisualInfo
*vinfo
,
227 GLboolean rgbFlag
, GLboolean alphaFlag
, GLboolean dbFlag
,
228 GLboolean stereoFlag
,
229 GLint depth_size
, GLint stencil_size
,
230 GLint accum_size
, GLint level
)
232 GLboolean ximageFlag
= GL_TRUE
;
235 GLboolean comparePointers
;
238 /* Check if the MESA_BACK_BUFFER env var is set */
239 char *backbuffer
= getenv("MESA_BACK_BUFFER");
241 if (backbuffer
[0]=='p' || backbuffer
[0]=='P') {
242 ximageFlag
= GL_FALSE
;
244 else if (backbuffer
[0]=='x' || backbuffer
[0]=='X') {
245 ximageFlag
= GL_TRUE
;
248 fprintf(stderr
, "Mesa: invalid value for MESA_BACK_BUFFER ");
249 fprintf(stderr
, "environment variable, using an XImage.\n");
254 /* Comparing IDs uses less memory but sometimes fails. */
255 /* XXX revisit this after 3.0 is finished. */
256 if (getenv("MESA_GLX_VISUAL_HACK"))
257 comparePointers
= GL_TRUE
;
259 comparePointers
= GL_FALSE
;
261 /* First check if a matching visual is already in the list */
262 for (i
=0; i
<NumVisuals
; i
++) {
263 XMesaVisual v
= VisualTable
[i
];
264 if (v
->display
== dpy
266 && v
->ximage_flag
== ximageFlag
267 && v
->gl_visual
->RGBAflag
== rgbFlag
268 && v
->gl_visual
->DBflag
== dbFlag
269 && v
->gl_visual
->StereoFlag
== stereoFlag
270 && (v
->gl_visual
->AlphaBits
> 0) == alphaFlag
271 && (v
->gl_visual
->DepthBits
>= depth_size
|| depth_size
== 0)
272 && (v
->gl_visual
->StencilBits
>= stencil_size
|| stencil_size
== 0)
273 && (v
->gl_visual
->AccumBits
>= accum_size
|| accum_size
== 0)) {
274 /* now either compare XVisualInfo pointers or visual IDs */
275 if ((!comparePointers
&& v
->visinfo
->visualid
== vinfo
->visualid
)
276 || (comparePointers
&& v
->vishandle
== vinfo
)) {
282 /* Create a new visual and add it to the list. */
284 if (NumVisuals
>=MAX_VISUALS
) {
285 fprintf( stderr
, "GLX Error: maximum number of visuals exceeded\n");
289 xmvis
= XMesaCreateVisual( dpy
, vinfo
, rgbFlag
, alphaFlag
, dbFlag
,
290 stereoFlag
, ximageFlag
,
291 depth_size
, stencil_size
, accum_size
, level
);
293 VisualTable
[NumVisuals
] = xmvis
;
302 * Create a GLX visual from a regular XVisualInfo.
305 create_glx_visual( Display
*dpy
, XVisualInfo
*visinfo
)
309 vislevel
= level_of_visual( dpy
, visinfo
);
311 /* Configure this visual as a CI, single-buffered overlay */
312 return save_glx_visual( dpy
, visinfo
,
314 GL_FALSE
, /* alpha */
315 GL_FALSE
, /* double */
316 GL_FALSE
, /* stereo */
318 0, /* stencil bits */
323 else if (is_usable_visual( visinfo
)) {
324 /* Configure this visual as RGB, double-buffered, depth-buffered. */
325 /* This is surely wrong for some people's needs but what else */
326 /* can be done? They should use glXChooseVisual(). */
327 return save_glx_visual( dpy
, visinfo
,
329 GL_FALSE
, /* alpha */
330 GL_TRUE
, /* double */
331 GL_FALSE
, /* stereo */
339 fprintf(stderr
,"Mesa: error in glXCreateContext: bad visual\n");
347 * Find the GLX visual associated with an XVisualInfo.
350 find_glx_visual( Display
*dpy
, XVisualInfo
*vinfo
)
354 /* First try to match pointers */
355 for (i
=0;i
<NumVisuals
;i
++) {
356 if (VisualTable
[i
]->display
==dpy
&& VisualTable
[i
]->vishandle
==vinfo
) {
357 return VisualTable
[i
];
360 /* try to match visual id */
361 for (i
=0;i
<NumVisuals
;i
++) {
362 if (VisualTable
[i
]->display
==dpy
363 && VisualTable
[i
]->visinfo
->visualid
== vinfo
->visualid
) {
364 return VisualTable
[i
];
373 * Return the transparent pixel value for a GLX visual.
374 * Input: glxvis - the glx_visual
375 * Return: a pixel value or -1 if no transparent pixel
377 static int transparent_pixel( XMesaVisual glxvis
)
379 Display
*dpy
= glxvis
->display
;
380 XVisualInfo
*vinfo
= glxvis
->visinfo
;
381 Atom overlayVisualsAtom
;
382 OverlayInfo
*overlay_info
= NULL
;
383 int numOverlaysPerScreen
;
387 unsigned long sizeData
, bytesLeft
;
391 * The SERVER_OVERLAY_VISUALS property on the root window contains
392 * a list of overlay visuals. Get that list now.
394 overlayVisualsAtom
= XInternAtom(dpy
,"SERVER_OVERLAY_VISUALS", True
);
395 if (overlayVisualsAtom
== None
) {
399 status
= XGetWindowProperty(dpy
, RootWindow( dpy
, vinfo
->screen
),
400 overlayVisualsAtom
, 0L, (long) 10000, False
,
401 overlayVisualsAtom
, &actualType
, &actualFormat
,
402 &sizeData
, &bytesLeft
,
403 (unsigned char **) &overlay_info
);
405 if (status
!= Success
|| actualType
!= overlayVisualsAtom
||
406 actualFormat
!= 32 || sizeData
< 4) {
407 /* something went wrong */
408 XFree((void *) overlay_info
);
412 /* search the overlay visual list for the visual ID of interest */
413 numOverlaysPerScreen
= (int) (sizeData
/ 4);
414 for (i
=0;i
<numOverlaysPerScreen
;i
++) {
416 ov
= overlay_info
+ i
;
417 if (ov
->overlay_visual
==vinfo
->visualid
) {
419 if (ov
->transparent_type
==0) {
420 /* type 0 indicates no transparency */
421 XFree((void *) overlay_info
);
425 /* ov->value is the transparent pixel */
426 XFree((void *) overlay_info
);
432 /* The visual ID was not found in the overlay list. */
433 XFree((void *) overlay_info
);
440 * Return number of bits set in n.
442 static int bitcount( unsigned long n
)
445 for (bits
=0; n
>0; n
=n
>>1) {
455 * Try to get an X visual which matches the given arguments.
457 static XVisualInfo
*get_visual( Display
*dpy
, int scr
,
458 unsigned int depth
, int xclass
)
460 XVisualInfo temp
, *vis
;
463 unsigned int default_depth
;
466 mask
= VisualScreenMask
| VisualDepthMask
| VisualClassMask
;
471 default_depth
= DefaultDepth(dpy
,scr
);
472 default_class
= DefaultVisual(dpy
,scr
)->CLASS
;
474 if (depth
==default_depth
&& xclass
==default_class
) {
475 /* try to get root window's visual */
476 temp
.visualid
= DefaultVisual(dpy
,scr
)->visualid
;
477 mask
|= VisualIDMask
;
480 vis
= XGetVisualInfo( dpy
, mask
, &temp
, &n
);
482 /* In case bits/pixel > 24, make sure color channels are still <=8 bits.
483 * An SGI Infinite Reality system, for example, can have 30bpp pixels:
484 * 10 bits per color channel. Mesa's limited to a max of 8 bits/channel.
486 if (vis
&& depth
> 24 && (xclass
==TrueColor
|| xclass
==DirectColor
)) {
487 if (bitcount(vis
->red_mask
) <= 8
488 && bitcount(vis
->green_mask
) <= 8
489 && bitcount(vis
->blue_mask
) <= 8) {
504 * Retrieve the value of the given environment variable and find
505 * the X visual which matches it.
506 * Input: dpy - the display
507 * screen - the screen number
508 * varname - the name of the environment variable
509 * Return: an XVisualInfo pointer to NULL if error.
511 static XVisualInfo
*get_env_visual(Display
*dpy
, int scr
, const char *varname
)
513 char value
[100], type
[100];
514 int depth
, xclass
= -1;
517 if (!getenv( varname
)) {
521 strncpy( value
, getenv(varname
), 100 );
524 sscanf( value
, "%s %d", type
, &depth
);
526 if (strcmp(type
,"TrueColor")==0) xclass
= TrueColor
;
527 else if (strcmp(type
,"DirectColor")==0) xclass
= DirectColor
;
528 else if (strcmp(type
,"PseudoColor")==0) xclass
= PseudoColor
;
529 else if (strcmp(type
,"StaticColor")==0) xclass
= StaticColor
;
530 else if (strcmp(type
,"GrayScale")==0) xclass
= GrayScale
;
531 else if (strcmp(type
,"StaticGray")==0) xclass
= StaticGray
;
533 if (xclass
>-1 && depth
>0) {
534 vis
= get_visual( dpy
, scr
, depth
, xclass
);
540 fprintf( stderr
, "Mesa: GLX unable to find visual class=%s, depth=%d.\n",
548 * Select an X visual which satisfies the RGBA/CI flag and minimum depth.
549 * Input: dpy, screen - X display and screen number
550 * rgba - GL_TRUE = RGBA mode, GL_FALSE = CI mode
551 * min_depth - minimum visual depth
552 * preferred_class - preferred GLX visual class or DONT_CARE
553 * Return: pointer to an XVisualInfo or NULL.
555 static XVisualInfo
*choose_x_visual( Display
*dpy
, int screen
,
556 GLboolean rgba
, int min_depth
,
557 int preferred_class
)
560 int xclass
, visclass
;
564 Atom hp_cr_maps
= XInternAtom(dpy
, "_HP_RGB_SMOOTH_MAP_LIST", True
);
565 /* First see if the MESA_RGB_VISUAL env var is defined */
566 vis
= get_env_visual( dpy
, screen
, "MESA_RGB_VISUAL" );
570 /* Otherwise, search for a suitable visual */
571 if (preferred_class
==DONT_CARE
) {
572 for (xclass
=0;xclass
<6;xclass
++) {
574 case 0: visclass
= TrueColor
; break;
575 case 1: visclass
= DirectColor
; break;
576 case 2: visclass
= PseudoColor
; break;
577 case 3: visclass
= StaticColor
; break;
578 case 4: visclass
= GrayScale
; break;
579 case 5: visclass
= StaticGray
; break;
582 /* start with shallowest */
583 for (depth
=0;depth
<=32;depth
++) {
584 if (visclass
==TrueColor
&& depth
==8 && !hp_cr_maps
) {
585 /* Special case: try to get 8-bit PseudoColor before */
586 /* 8-bit TrueColor */
587 vis
= get_visual( dpy
, screen
, 8, PseudoColor
);
592 vis
= get_visual( dpy
, screen
, depth
, visclass
);
599 /* start with deepest */
600 for (depth
=32;depth
>=min_depth
;depth
--) {
601 if (visclass
==TrueColor
&& depth
==8 && !hp_cr_maps
) {
602 /* Special case: try to get 8-bit PseudoColor before */
603 /* 8-bit TrueColor */
604 vis
= get_visual( dpy
, screen
, 8, PseudoColor
);
609 vis
= get_visual( dpy
, screen
, depth
, visclass
);
618 /* search for a specific visual class */
619 switch (preferred_class
) {
620 case GLX_TRUE_COLOR_EXT
: visclass
= TrueColor
; break;
621 case GLX_DIRECT_COLOR_EXT
: visclass
= DirectColor
; break;
622 case GLX_PSEUDO_COLOR_EXT
: visclass
= PseudoColor
; break;
623 case GLX_STATIC_COLOR_EXT
: visclass
= StaticColor
; break;
624 case GLX_GRAY_SCALE_EXT
: visclass
= GrayScale
; break;
625 case GLX_STATIC_GRAY_EXT
: visclass
= StaticGray
; break;
626 default: return NULL
;
629 /* start with shallowest */
630 for (depth
=0;depth
<=32;depth
++) {
631 vis
= get_visual( dpy
, screen
, depth
, visclass
);
638 /* start with deepest */
639 for (depth
=32;depth
>=min_depth
;depth
--) {
640 vis
= get_visual( dpy
, screen
, depth
, visclass
);
649 /* First see if the MESA_CI_VISUAL env var is defined */
650 vis
= get_env_visual( dpy
, screen
, "MESA_CI_VISUAL" );
654 /* Otherwise, search for a suitable visual, starting with shallowest */
655 if (preferred_class
==DONT_CARE
) {
656 for (xclass
=0;xclass
<4;xclass
++) {
658 case 0: visclass
= PseudoColor
; break;
659 case 1: visclass
= StaticColor
; break;
660 case 2: visclass
= GrayScale
; break;
661 case 3: visclass
= StaticGray
; break;
663 /* try 8-bit up through 16-bit */
664 for (depth
=8;depth
<=16;depth
++) {
665 vis
= get_visual( dpy
, screen
, depth
, visclass
);
670 /* try min_depth up to 8-bit */
671 for (depth
=min_depth
;depth
<8;depth
++) {
672 vis
= get_visual( dpy
, screen
, depth
, visclass
);
680 /* search for a specific visual class */
681 switch (preferred_class
) {
682 case GLX_TRUE_COLOR_EXT
: visclass
= TrueColor
; break;
683 case GLX_DIRECT_COLOR_EXT
: visclass
= DirectColor
; break;
684 case GLX_PSEUDO_COLOR_EXT
: visclass
= PseudoColor
; break;
685 case GLX_STATIC_COLOR_EXT
: visclass
= StaticColor
; break;
686 case GLX_GRAY_SCALE_EXT
: visclass
= GrayScale
; break;
687 case GLX_STATIC_GRAY_EXT
: visclass
= StaticGray
; break;
688 default: return NULL
;
690 /* try 8-bit up through 16-bit */
691 for (depth
=8;depth
<=16;depth
++) {
692 vis
= get_visual( dpy
, screen
, depth
, visclass
);
697 /* try min_depth up to 8-bit */
698 for (depth
=min_depth
;depth
<8;depth
++) {
699 vis
= get_visual( dpy
, screen
, depth
, visclass
);
707 /* didn't find a visual */
714 * Find the deepest X over/underlay visual of at least min_depth.
715 * Input: dpy, screen - X display and screen number
716 * level - the over/underlay level
717 * trans_type - transparent pixel type: GLX_NONE_EXT,
718 * GLX_TRANSPARENT_RGB_EXT, GLX_TRANSPARENT_INDEX_EXT,
720 * trans_value - transparent pixel value or DONT_CARE
721 * min_depth - minimum visual depth
722 * preferred_class - preferred GLX visual class or DONT_CARE
723 * Return: pointer to an XVisualInfo or NULL.
725 static XVisualInfo
*choose_x_overlay_visual( Display
*dpy
, int scr
,
727 int level
, int trans_type
,
730 int preferred_class
)
732 Atom overlayVisualsAtom
;
733 OverlayInfo
*overlay_info
;
734 int numOverlaysPerScreen
;
738 unsigned long sizeData
, bytesLeft
;
740 XVisualInfo
*deepvis
;
743 /*DEBUG int tt, tv; */
745 switch (preferred_class
) {
746 case GLX_TRUE_COLOR_EXT
: preferred_class
= TrueColor
; break;
747 case GLX_DIRECT_COLOR_EXT
: preferred_class
= DirectColor
; break;
748 case GLX_PSEUDO_COLOR_EXT
: preferred_class
= PseudoColor
; break;
749 case GLX_STATIC_COLOR_EXT
: preferred_class
= StaticColor
; break;
750 case GLX_GRAY_SCALE_EXT
: preferred_class
= GrayScale
; break;
751 case GLX_STATIC_GRAY_EXT
: preferred_class
= StaticGray
; break;
752 default: preferred_class
= DONT_CARE
;
756 * The SERVER_OVERLAY_VISUALS property on the root window contains
757 * a list of overlay visuals. Get that list now.
759 overlayVisualsAtom
= XInternAtom(dpy
,"SERVER_OVERLAY_VISUALS", True
);
760 if (overlayVisualsAtom
== (Atom
) None
) {
764 status
= XGetWindowProperty(dpy
, RootWindow( dpy
, scr
),
765 overlayVisualsAtom
, 0L, (long) 10000, False
,
766 overlayVisualsAtom
, &actualType
, &actualFormat
,
767 &sizeData
, &bytesLeft
,
768 (unsigned char **) &overlay_info
);
770 if (status
!= Success
|| actualType
!= overlayVisualsAtom
||
771 actualFormat
!= 32 || sizeData
< 4) {
772 /* something went wrong */
776 /* Search for the deepest overlay which satisifies all criteria. */
780 numOverlaysPerScreen
= (int) (sizeData
/ 4);
781 for (i
=0;i
<numOverlaysPerScreen
;i
++) {
782 XVisualInfo
*vislist
, vistemplate
;
785 ov
= overlay_info
+ i
;
787 if (ov
->layer
!=level
) {
788 /* failed overlay level criteria */
791 if (!(trans_type
==DONT_CARE
792 || (trans_type
==GLX_TRANSPARENT_INDEX_EXT
793 && ov
->transparent_type
>0)
794 || (trans_type
==GLX_NONE_EXT
&& ov
->transparent_type
==0))) {
795 /* failed transparent pixel type criteria */
798 if (trans_value
!=DONT_CARE
&& trans_value
!=ov
->value
) {
799 /* failed transparent pixel value criteria */
803 /* get XVisualInfo and check the depth */
804 vistemplate
.visualid
= ov
->overlay_visual
;
805 vistemplate
.screen
= scr
;
806 vislist
= XGetVisualInfo( dpy
, VisualIDMask
| VisualScreenMask
,
807 &vistemplate
, &count
);
810 /* something went wrong */
813 if (preferred_class
!=DONT_CARE
&& preferred_class
!=vislist
->CLASS
) {
814 /* wrong visual class */
818 /* if RGB was requested, make sure we have True/DirectColor */
819 if (rgbFlag
&& vislist
->CLASS
!= TrueColor
820 && vislist
->CLASS
!= DirectColor
)
823 /* if CI was requested, make sure we have a color indexed visual */
825 && (vislist
->CLASS
== TrueColor
|| vislist
->CLASS
== DirectColor
))
828 if (deepvis
==NULL
|| vislist
->depth
> deepest
) {
829 /* YES! found a satisfactory visual */
833 deepest
= vislist
->depth
;
835 /* DEBUG tt = ov->transparent_type;*/
836 /* DEBUG tv = ov->value; */
842 printf("chose 0x%x: layer=%d depth=%d trans_type=%d trans_value=%d\n",
843 deepvis->visualid, level, deepvis->depth, tt, tv );
852 Fake_glXChooseVisual( Display
*dpy
, int screen
, int *list
)
857 int min_red
=0, min_green
=0, min_blue
=0;
858 GLboolean rgb_flag
= GL_FALSE
;
859 GLboolean alpha_flag
= GL_FALSE
;
860 GLboolean double_flag
= GL_FALSE
;
861 GLboolean stereo_flag
= GL_FALSE
;
862 GLint depth_size
= 0;
863 GLint stencil_size
= 0;
864 GLint accum_size
= 0;
866 int visual_type
= DONT_CARE
;
867 int trans_type
= DONT_CARE
;
868 int trans_value
= DONT_CARE
;
874 switch (*parselist
) {
879 case GLX_BUFFER_SIZE
:
881 min_ci
= *parselist
++;
885 level
= *parselist
++;
891 case GLX_DOUBLEBUFFER
:
892 double_flag
= GL_TRUE
;
896 stereo_flag
= GL_TRUE
;
898 case GLX_AUX_BUFFERS
:
905 min_red
= *parselist
++;
909 min_green
= *parselist
++;
913 min_blue
= *parselist
++;
918 GLint size
= *parselist
++;
919 alpha_flag
= size
>0 ? 1 : 0;
924 depth_size
= *parselist
++;
926 case GLX_STENCIL_SIZE
:
928 stencil_size
= *parselist
++;
930 case GLX_ACCUM_RED_SIZE
:
931 case GLX_ACCUM_GREEN_SIZE
:
932 case GLX_ACCUM_BLUE_SIZE
:
933 case GLX_ACCUM_ALPHA_SIZE
:
936 GLint size
= *parselist
++;
937 accum_size
= MAX2( accum_size
, size
);
942 * GLX_EXT_visual_info extension
944 case GLX_X_VISUAL_TYPE_EXT
:
946 visual_type
= *parselist
++;
948 case GLX_TRANSPARENT_TYPE_EXT
:
950 trans_type
= *parselist
++;
952 case GLX_TRANSPARENT_INDEX_VALUE_EXT
:
954 trans_value
= *parselist
++;
956 case GLX_TRANSPARENT_RED_VALUE_EXT
:
957 case GLX_TRANSPARENT_GREEN_VALUE_EXT
:
958 case GLX_TRANSPARENT_BLUE_VALUE_EXT
:
959 case GLX_TRANSPARENT_ALPHA_VALUE_EXT
:
968 /* undefined attribute */
974 * Since we're only simulating the GLX extension this function will never
975 * find any real GL visuals. Instead, all we can do is try to find an RGB
976 * or CI visual of appropriate depth. Other requested attributes such as
977 * double buffering, depth buffer, etc. will be associated with the X
978 * visual and stored in the VisualTable[].
981 /* normal color planes */
983 /* Get an RGB visual */
984 int min_rgb
= min_red
+ min_green
+ min_blue
;
985 if (min_rgb
>1 && min_rgb
<8) {
986 /* a special case to be sure we can get a monochrome visual */
989 vis
= choose_x_visual( dpy
, screen
, rgb_flag
, min_rgb
, visual_type
);
992 /* Get a color index visual */
993 vis
= choose_x_visual( dpy
, screen
, rgb_flag
, min_ci
, visual_type
);
998 /* over/underlay planes */
1001 int min_rgb
= min_red
+ min_green
+ min_blue
;
1002 if (min_rgb
>1 && min_rgb
<8) {
1003 /* a special case to be sure we can get a monochrome visual */
1006 vis
= choose_x_overlay_visual( dpy
, screen
, rgb_flag
, level
,
1007 trans_type
, trans_value
, min_rgb
, visual_type
);
1010 /* color index overlay */
1011 vis
= choose_x_overlay_visual( dpy
, screen
, rgb_flag
, level
,
1012 trans_type
, trans_value
, min_ci
, visual_type
);
1017 if (!save_glx_visual( dpy
, vis
, rgb_flag
, alpha_flag
, double_flag
,
1019 depth_size
, stencil_size
, accum_size
, level
))
1030 Fake_glXCreateContext( Display
*dpy
, XVisualInfo
*visinfo
,
1031 GLXContext share_list
, Bool direct
)
1036 /* deallocate unused windows/buffers */
1037 XMesaGarbageCollect();
1039 glxvis
= find_glx_visual( dpy
, visinfo
);
1041 /* This visual wasn't found with glXChooseVisual() */
1042 glxvis
= create_glx_visual( dpy
, visinfo
);
1044 /* unusable visual */
1049 xmctx
= XMesaCreateContext( glxvis
, (XMesaContext
) share_list
);
1051 /* set the direct/indirect flag */
1052 xmctx
->direct
= direct
;
1054 return (GLXContext
) xmctx
;
1058 static GLXContext MakeCurrent_PrevContext
= 0;
1059 static GLXDrawable MakeCurrent_PrevDrawable
= 0;
1060 static GLXDrawable MakeCurrent_PrevReadable
= 0;
1061 static XMesaBuffer MakeCurrent_PrevDrawBuffer
= 0;
1062 static XMesaBuffer MakeCurrent_PrevReadBuffer
= 0;
1064 /* GLX 1.3 and later */
1066 Fake_glXMakeContextCurrent( Display
*dpy
, GLXDrawable draw
,
1067 GLXDrawable read
, GLXContext ctx
)
1069 if (ctx
&& draw
&& read
) {
1070 XMesaBuffer drawBuffer
, readBuffer
;
1071 XMesaContext xmctx
= (XMesaContext
) ctx
;
1073 /* Find the XMesaBuffer which corresponds to the GLXDrawable 'draw' */
1074 if (ctx
== MakeCurrent_PrevContext
1075 && draw
== MakeCurrent_PrevDrawable
) {
1076 drawBuffer
= MakeCurrent_PrevDrawBuffer
;
1079 drawBuffer
= XMesaFindBuffer( dpy
, draw
);
1082 /* drawable must be a new window! */
1083 drawBuffer
= XMesaCreateWindowBuffer2( xmctx
->xm_visual
, draw
, ctx
);
1085 /* Out of memory, or context/drawable depth mismatch */
1090 /* Find the XMesaBuffer which corresponds to the GLXDrawable 'read' */
1091 if (ctx
== MakeCurrent_PrevContext
1092 && read
== MakeCurrent_PrevReadable
) {
1093 readBuffer
= MakeCurrent_PrevReadBuffer
;
1096 readBuffer
= XMesaFindBuffer( dpy
, read
);
1099 /* drawable must be a new window! */
1100 readBuffer
= XMesaCreateWindowBuffer2( xmctx
->xm_visual
, read
, ctx
);
1102 /* Out of memory, or context/drawable depth mismatch */
1107 MakeCurrent_PrevContext
= ctx
;
1108 MakeCurrent_PrevDrawable
= draw
;
1109 MakeCurrent_PrevReadable
= read
;
1110 MakeCurrent_PrevDrawBuffer
= drawBuffer
;
1111 MakeCurrent_PrevReadBuffer
= readBuffer
;
1113 /* Now make current! */
1114 return (Bool
) XMesaMakeCurrent2((XMesaContext
) ctx
, drawBuffer
, readBuffer
);
1116 else if (!ctx
&& !draw
&& !read
) {
1117 /* release current context w/out assigning new one. */
1118 XMesaMakeCurrent( NULL
, NULL
);
1119 MakeCurrent_PrevContext
= 0;
1120 MakeCurrent_PrevDrawable
= 0;
1121 MakeCurrent_PrevReadable
= 0;
1122 MakeCurrent_PrevDrawBuffer
= 0;
1123 MakeCurrent_PrevReadBuffer
= 0;
1127 /* The args must either all be non-zero or all zero.
1137 Fake_glXMakeCurrent( Display
*dpy
, GLXDrawable drawable
, GLXContext ctx
)
1139 return Fake_glXMakeContextCurrent( dpy
, drawable
, drawable
, ctx
);
1145 Fake_glXCreateGLXPixmap( Display
*dpy
, XVisualInfo
*visinfo
, Pixmap pixmap
)
1150 v
= find_glx_visual( dpy
, visinfo
);
1152 v
= create_glx_visual( dpy
, visinfo
);
1154 /* unusable visual */
1159 b
= XMesaCreatePixmapBuffer( v
, pixmap
, 0 );
1163 return b
->frontbuffer
;
1167 #ifdef GLX_MESA_pixmap_colormap
1170 Fake_glXCreateGLXPixmapMESA( Display
*dpy
, XVisualInfo
*visinfo
,
1171 Pixmap pixmap
, Colormap cmap
)
1176 v
= find_glx_visual( dpy
, visinfo
);
1178 v
= create_glx_visual( dpy
, visinfo
);
1180 /* unusable visual */
1185 b
= XMesaCreatePixmapBuffer( v
, pixmap
, cmap
);
1189 return b
->frontbuffer
;
1196 Fake_glXDestroyGLXPixmap( Display
*dpy
, GLXPixmap pixmap
)
1198 XMesaBuffer b
= XMesaFindBuffer(dpy
, pixmap
);
1200 XMesaDestroyBuffer(b
);
1202 else if (getenv("MESA_DEBUG")) {
1203 fprintf( stderr
, "Mesa: glXDestroyGLXPixmap: invalid pixmap\n");
1209 Fake_glXCopyContext( Display
*dpy
, GLXContext src
, GLXContext dst
,
1210 unsigned long mask
)
1212 XMesaContext xm_src
= (XMesaContext
) src
;
1213 XMesaContext xm_dst
= (XMesaContext
) dst
;
1215 gl_copy_context( xm_src
->gl_ctx
, xm_dst
->gl_ctx
, (GLuint
) mask
);
1221 Fake_glXQueryExtension( Display
*dpy
, int *errorb
, int *event
)
1223 /* Mesa's GLX isn't really an X extension but we try to act like one. */
1231 void _kw_ungrab_all( Display
*dpy
)
1233 XUngrabPointer( dpy
, CurrentTime
);
1234 XUngrabKeyboard( dpy
, CurrentTime
);
1239 Fake_glXDestroyContext( Display
*dpy
, GLXContext ctx
)
1242 MakeCurrent_PrevContext
= 0;
1243 MakeCurrent_PrevDrawable
= 0;
1244 MakeCurrent_PrevReadable
= 0;
1245 MakeCurrent_PrevDrawBuffer
= 0;
1246 MakeCurrent_PrevReadBuffer
= 0;
1247 XMesaDestroyContext( (XMesaContext
) ctx
);
1248 XMesaGarbageCollect();
1254 Fake_glXIsDirect( Display
*dpy
, GLXContext ctx
)
1257 return ((XMesaContext
) ctx
)->direct
;
1263 Fake_glXSwapBuffers( Display
*dpy
, GLXDrawable drawable
)
1265 XMesaBuffer buffer
= XMesaFindBuffer( dpy
, drawable
);
1268 XMesaSwapBuffers(buffer
);
1270 else if (getenv("MESA_DEBUG")) {
1271 fprintf(stderr
, "Mesa Warning: glXSwapBuffers: invalid drawable\n");
1277 Fake_glXCopySubBufferMESA( Display
*dpy
, GLXDrawable drawable
,
1278 int x
, int y
, int width
, int height
)
1280 XMesaBuffer buffer
= XMesaFindBuffer( dpy
, drawable
);
1282 XMesaCopySubBuffer(buffer
, x
, y
, width
, height
);
1284 else if (getenv("MESA_DEBUG")) {
1285 fprintf(stderr
, "Mesa Warning: glXCopySubBufferMESA: invalid drawable\n");
1292 Fake_glXQueryVersion( Display
*dpy
, int *maj
, int *min
)
1295 /* Return GLX version, not Mesa version */
1296 assert(CLIENT_MAJOR_VERSION
== SERVER_MAJOR_VERSION
);
1297 *maj
= CLIENT_MAJOR_VERSION
;
1298 *min
= MIN2( CLIENT_MINOR_VERSION
, SERVER_MINOR_VERSION
);
1305 * Query the GLX attributes of the given XVisualInfo.
1308 Fake_glXGetConfig( Display
*dpy
, XVisualInfo
*visinfo
,
1309 int attrib
, int *value
)
1313 glxvis
= find_glx_visual( dpy
, visinfo
);
1315 /* this visual wasn't obtained with glXChooseVisual */
1316 glxvis
= create_glx_visual( dpy
, visinfo
);
1318 /* this visual can't be used for GL rendering */
1319 if (attrib
==GLX_USE_GL
) {
1320 *value
= (int) False
;
1324 /*fprintf( stderr, "Mesa: Error in glXGetConfig: bad visual\n");*/
1325 return GLX_BAD_VISUAL
;
1332 *value
= (int) True
;
1334 case GLX_BUFFER_SIZE
:
1335 *value
= visinfo
->depth
;
1338 *value
= glxvis
->level
;
1341 if (glxvis
->gl_visual
->RGBAflag
) {
1348 case GLX_DOUBLEBUFFER
:
1349 *value
= (int) glxvis
->gl_visual
->DBflag
;
1352 *value
= (int) glxvis
->gl_visual
->StereoFlag
;
1354 case GLX_AUX_BUFFERS
:
1355 *value
= (int) False
;
1358 *value
= glxvis
->gl_visual
->RedBits
;
1360 case GLX_GREEN_SIZE
:
1361 *value
= glxvis
->gl_visual
->GreenBits
;
1364 *value
= glxvis
->gl_visual
->BlueBits
;
1366 case GLX_ALPHA_SIZE
:
1367 *value
= glxvis
->gl_visual
->AlphaBits
;
1369 case GLX_DEPTH_SIZE
:
1370 *value
= glxvis
->gl_visual
->DepthBits
;
1372 case GLX_STENCIL_SIZE
:
1373 *value
= glxvis
->gl_visual
->StencilBits
;
1375 case GLX_ACCUM_RED_SIZE
:
1376 case GLX_ACCUM_GREEN_SIZE
:
1377 case GLX_ACCUM_BLUE_SIZE
:
1378 *value
= glxvis
->gl_visual
->AccumBits
;
1380 case GLX_ACCUM_ALPHA_SIZE
:
1381 if (glxvis
->gl_visual
->AlphaBits
> 0)
1382 *value
= glxvis
->gl_visual
->AccumBits
;
1388 * GLX_EXT_visual_info extension
1390 case GLX_X_VISUAL_TYPE_EXT
:
1391 switch (glxvis
->visinfo
->CLASS
) {
1392 case StaticGray
: *value
= GLX_STATIC_GRAY_EXT
; return 0;
1393 case GrayScale
: *value
= GLX_GRAY_SCALE_EXT
; return 0;
1394 case StaticColor
: *value
= GLX_STATIC_GRAY_EXT
; return 0;
1395 case PseudoColor
: *value
= GLX_PSEUDO_COLOR_EXT
; return 0;
1396 case TrueColor
: *value
= GLX_TRUE_COLOR_EXT
; return 0;
1397 case DirectColor
: *value
= GLX_DIRECT_COLOR_EXT
; return 0;
1400 case GLX_TRANSPARENT_TYPE_EXT
:
1401 if (glxvis
->level
==0) {
1403 *value
= GLX_NONE_EXT
;
1405 else if (glxvis
->level
>0) {
1407 if (glxvis
->gl_visual
->RGBAflag
) {
1408 *value
= GLX_TRANSPARENT_RGB_EXT
;
1411 *value
= GLX_TRANSPARENT_INDEX_EXT
;
1414 else if (glxvis
->level
<0) {
1416 *value
= GLX_NONE_EXT
;
1419 case GLX_TRANSPARENT_INDEX_VALUE_EXT
:
1421 int pixel
= transparent_pixel( glxvis
);
1425 /* else undefined */
1428 case GLX_TRANSPARENT_RED_VALUE_EXT
:
1431 case GLX_TRANSPARENT_GREEN_VALUE_EXT
:
1434 case GLX_TRANSPARENT_BLUE_VALUE_EXT
:
1437 case GLX_TRANSPARENT_ALPHA_VALUE_EXT
:
1445 return GLX_BAD_ATTRIBUTE
;
1452 Fake_glXWaitGL( void )
1454 XMesaContext xmesa
= XMesaGetCurrentContext();
1455 XMesaFlush( xmesa
);
1461 Fake_glXWaitX( void )
1463 XMesaContext xmesa
= XMesaGetCurrentContext();
1464 XMesaFlush( xmesa
);
1469 * Return the extensions string, which is 3Dfx-dependant.
1471 static const char *get_extensions( void )
1474 const char *fx
= getenv("MESA_GLX_FX");
1475 if (fx
&& fx
[0] != 'd') {
1476 return "GLX_MESA_pixmap_colormap GLX_EXT_visual_info GLX_MESA_release_buffers GLX_MESA_copy_sub_buffer GLX_SGI_video_sync GLX_MESA_set_3dfx_mode GLX_ARB_get_proc_address";
1479 return "GLX_MESA_pixmap_colormap GLX_EXT_visual_info GLX_MESA_release_buffers GLX_MESA_copy_sub_buffer GLX_SGI_video_sync GLX_ARB_get_proc_address";
1484 /* GLX 1.1 and later */
1486 Fake_glXQueryExtensionsString( Display
*dpy
, int screen
)
1490 return get_extensions();
1495 /* GLX 1.1 and later */
1497 Fake_glXQueryServerString( Display
*dpy
, int screen
, int name
)
1499 static char version
[1000];
1500 sprintf(version
, "%d.%d %s", SERVER_MAJOR_VERSION
, SERVER_MINOR_VERSION
,
1507 case GLX_EXTENSIONS
:
1508 return get_extensions();
1520 /* GLX 1.1 and later */
1522 Fake_glXGetClientString( Display
*dpy
, int name
)
1524 static char version
[1000];
1525 sprintf(version
, "%d.%d %s", CLIENT_MAJOR_VERSION
, CLIENT_MINOR_VERSION
,
1531 case GLX_EXTENSIONS
:
1532 return get_extensions();
1549 Fake_glXChooseFBConfig( Display
*dpy
, int screen
,
1550 const int *attribList
, int *nitems
)
1561 Fake_glXGetFBConfigAttrib( Display
*dpy
, GLXFBConfig config
,
1562 int attribute
, int *value
)
1572 static XVisualInfo
*
1573 Fake_glXGetVisualFromFBConfig( Display
*dpy
, GLXFBConfig config
)
1582 Fake_glXCreateWindow( Display
*dpy
, GLXFBConfig config
, Window win
,
1583 const int *attribList
)
1594 Fake_glXDestroyWindow( Display
*dpy
, GLXWindow window
)
1603 Fake_glXCreatePixmap( Display
*dpy
, GLXFBConfig config
, Pixmap pixmap
,
1604 const int *attribList
)
1615 Fake_glXDestroyPixmap( Display
*dpy
, GLXPixmap pixmap
)
1624 Fake_glXCreatePbuffer( Display
*dpy
, GLXFBConfig config
,
1625 const int *attribList
)
1635 Fake_glXDestroyPbuffer( Display
*dpy
, GLXPbuffer pbuf
)
1643 Fake_glXQueryDrawable( Display
*dpy
, GLXDrawable draw
, int attribute
,
1644 unsigned int *value
)
1654 Fake_glXCreateNewContext( Display
*dpy
, GLXFBConfig config
,
1655 int renderType
, GLXContext shareList
, Bool direct
)
1667 Fake_glXQueryContext( Display
*dpy
, GLXContext ctx
, int attribute
, int *value
)
1678 Fake_glXSelectEvent( Display
*dpy
, GLXDrawable drawable
, unsigned long mask
)
1687 Fake_glXGetSelectedEvent( Display
*dpy
, GLXDrawable drawable
,
1688 unsigned long *mask
)
1698 * Release the depth, stencil, accum buffers attached to a GLXDrawable
1699 * (a window or pixmap) prior to destroying the GLXDrawable.
1702 Fake_glXReleaseBuffersMESA( Display
*dpy
, GLXDrawable d
)
1704 XMesaBuffer b
= XMesaFindBuffer(dpy
, d
);
1706 XMesaDestroyBuffer(b
);
1714 * GLX_MESA_set_3dfx_mode
1717 Fake_glXSet3DfxModeMESA( GLint mode
)
1719 return XMesaSetFXmode( mode
);
1724 * GLX_SGI_video_sync
1727 #ifdef GLX_SGI_video_sync
1730 Fake_glXGetVideoSyncSGI(unsigned int *count
)
1737 Fake_glXWaitVideoSyncSGI(int divisor
, int remainder
, unsigned int *count
)
1746 extern void Fake_glXUseXFont( Font font
, int first
, int count
, int listbase
);
1749 struct _glxapi_table
*_mesa_GetGLXDispatchTable(void)
1751 static struct _glxapi_table glx
;
1753 /* be sure our dispatch table size <= libGL's table */
1755 int size
= sizeof(struct _glxapi_table
) / sizeof(void *);
1757 assert(_glxapi_get_dispatch_table_size() >= size
);
1760 /* initialize the whole table to no-ops */
1761 _glxapi_set_no_op_table(&glx
);
1763 /* now initialize the table with the functions I implement */
1764 glx
.ChooseVisual
= Fake_glXChooseVisual
;
1765 glx
.CopyContext
= Fake_glXCopyContext
;
1766 glx
.CreateContext
= Fake_glXCreateContext
;
1767 glx
.CreateGLXPixmap
= Fake_glXCreateGLXPixmap
;
1768 glx
.DestroyContext
= Fake_glXDestroyContext
;
1769 glx
.DestroyGLXPixmap
= Fake_glXDestroyGLXPixmap
;
1770 glx
.GetConfig
= Fake_glXGetConfig
;
1771 /*glx.GetCurrentContext = Fake_glXGetCurrentContext;*/
1772 /*glx.GetCurrentDrawable = Fake_glXGetCurrentDrawable;*/
1773 glx
.IsDirect
= Fake_glXIsDirect
;
1774 glx
.MakeCurrent
= Fake_glXMakeCurrent
;
1775 glx
.QueryExtension
= Fake_glXQueryExtension
;
1776 glx
.QueryVersion
= Fake_glXQueryVersion
;
1777 glx
.SwapBuffers
= Fake_glXSwapBuffers
;
1778 glx
.UseXFont
= Fake_glXUseXFont
;
1779 glx
.WaitGL
= Fake_glXWaitGL
;
1780 glx
.WaitX
= Fake_glXWaitX
;
1782 #ifdef _GLXAPI_VERSION_1_1
1783 glx
.GetClientString
= Fake_glXGetClientString
;
1784 glx
.QueryExtensionsString
= Fake_glXQueryExtensionsString
;
1785 glx
.QueryServerString
= Fake_glXQueryServerString
;
1788 #ifdef _GLXAPI_VERSION_1_2
1789 /*glx.GetCurrentDisplay = Fake_glXGetCurrentDisplay;*/
1792 #ifdef _GLXAPI_VERSION_1_3
1793 glx
.ChooseFBConfig
= Fake_glXChooseFBConfig
;
1794 glx
.CreateNewContext
= Fake_glXCreateNewContext
;
1795 glx
.CreatePbuffer
= Fake_glXCreatePbuffer
;
1796 glx
.CreatePixmap
= Fake_glXCreatePixmap
;
1797 glx
.CreateWindow
= Fake_glXCreateWindow
;
1798 glx
.DestroyPbuffer
= Fake_glXDestroyPbuffer
;
1799 glx
.DestroyPixmap
= Fake_glXDestroyPixmap
;
1800 glx
.DestroyWindow
= Fake_glXDestroyWindow
;
1801 /*glx.GetCurrentReadDrawable = Fake_glXGetCurrentReadDrawable;*/
1802 glx
.GetFBConfigAttrib
= Fake_glXGetFBConfigAttrib
;
1803 glx
.GetSelectedEvent
= Fake_glXGetSelectedEvent
;
1804 glx
.GetVisualFromFBConfig
= Fake_glXGetVisualFromFBConfig
;
1805 glx
.MakeContextCurrent
= Fake_glXMakeContextCurrent
;
1806 glx
.QueryContext
= Fake_glXQueryContext
;
1807 glx
.QueryDrawable
= Fake_glXQueryDrawable
;
1808 glx
.SelectEvent
= Fake_glXSelectEvent
;
1811 #ifdef _GLXAPI_SGI_video_sync
1812 glx
.GetVideoSyncSGI
= Fake_glXGetVideoSyncSGI
;
1813 glx
.WaitVideoSyncSGI
= Fake_glXWaitVideoSyncSGI
;
1816 #ifdef _GLXAPI_MESA_copy_sub_buffer
1817 glx
.CopySubBufferMESA
= Fake_glXCopySubBufferMESA
;
1820 #ifdef _GLXAPI_MESA_release_buffers
1821 glx
.ReleaseBuffersMESA
= Fake_glXReleaseBuffersMESA
;
1824 #ifdef _GLXAPI_MESA_pixmap_colormap
1825 glx
.CreateGLXPixmapMESA
= Fake_glXCreateGLXPixmapMESA
;
1828 #ifdef _GLXAPI_MESA_set_3dfx_mode
1829 glx
.Set3DfxModeMESA
= Fake_glXSet3DfxModeMESA
;