1 /* $Id: fakeglx.c,v 1.15 1999/11/22 21:52:23 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999 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.
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
35 * Thanks to the contributors:
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).
43 * Don't be fooled, stereo isn't supported yet.
48 #include "glxheader.h"
59 /* Silence compiler warnings */
60 void Fake_glXDummyFunc( void )
74 #define MAX_VISUALS 100
75 static XMesaVisual VisualTable
[MAX_VISUALS
];
76 static int NumVisuals
= 0;
81 * This struct and some code fragments borrowed
82 * from Mark Kilgard's GLUT library.
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
89 unsigned long overlay_visual
;
90 long transparent_type
;
97 /* Macro to handle c_class vs class field name in XVisualInfo struct */
98 #if defined(__cplusplus) || defined(c_plusplus)
108 * Test if the given XVisualInfo is usable for Mesa rendering.
110 static GLboolean
is_usable_visual( XVisualInfo
*vinfo
)
112 switch (vinfo
->CLASS
) {
115 /* Any StaticGray/GrayScale visual works in RGB or CI mode */
119 /* Any StaticColor/PseudoColor visual of at least 4 bits */
120 if (vinfo
->depth
>=4) {
128 /* Any depth of TrueColor or DirectColor works in RGB mode */
131 /* This should never happen */
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:
144 * >0 = overlay planes
145 * <0 = underlay planes
147 static int level_of_visual( Display
*dpy
, XVisualInfo
*vinfo
)
149 Atom overlayVisualsAtom
;
150 OverlayInfo
*overlay_info
= NULL
;
151 int numOverlaysPerScreen
;
155 unsigned long sizeData
, bytesLeft
;
159 * The SERVER_OVERLAY_VISUALS property on the root window contains
160 * a list of overlay visuals. Get that list now.
162 overlayVisualsAtom
= XInternAtom(dpy
,"SERVER_OVERLAY_VISUALS", True
);
163 if (overlayVisualsAtom
== None
) {
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
);
173 if (status
!= Success
|| actualType
!= overlayVisualsAtom
||
174 actualFormat
!= 32 || sizeData
< 4) {
175 /* something went wrong */
176 XFree((void *) overlay_info
);
180 /* search the overlay visual list for the visual ID of interest */
181 numOverlaysPerScreen
= (int) (sizeData
/ 4);
182 for (i
=0;i
<numOverlaysPerScreen
;i
++) {
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
);
193 XFree((void *) overlay_info
);
199 /* The visual ID was not found in the overlay list. */
200 XFree((void *) overlay_info
);
208 * Given an XVisualInfo and RGB, Double, and Depth buffer flags, save the
209 * configuration in our list of GLX visuals.
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
)
218 GLboolean ximageFlag
= GL_TRUE
;
221 GLboolean comparePointers
;
224 /* Check if the MESA_BACK_BUFFER env var is set */
225 char *backbuffer
= getenv("MESA_BACK_BUFFER");
227 if (backbuffer
[0]=='p' || backbuffer
[0]=='P') {
228 ximageFlag
= GL_FALSE
;
230 else if (backbuffer
[0]=='x' || backbuffer
[0]=='X') {
231 ximageFlag
= GL_TRUE
;
234 fprintf(stderr
, "Mesa: invalid value for MESA_BACK_BUFFER ");
235 fprintf(stderr
, "environment variable, using an XImage.\n");
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
;
245 comparePointers
= GL_FALSE
;
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
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
)) {
268 /* Create a new visual and add it to the list. */
270 if (NumVisuals
>=MAX_VISUALS
) {
271 fprintf( stderr
, "GLX Error: maximum number of visuals exceeded\n");
275 xmvis
= XMesaCreateVisual( dpy
, vinfo
, rgbFlag
, alphaFlag
, dbFlag
,
276 stereoFlag
, ximageFlag
,
277 depth_size
, stencil_size
, accum_size
, level
);
279 VisualTable
[NumVisuals
] = xmvis
;
288 * Create a GLX visual from a regular XVisualInfo.
291 create_glx_visual( Display
*dpy
, XVisualInfo
*visinfo
)
295 vislevel
= level_of_visual( dpy
, visinfo
);
297 /* Configure this visual as a CI, single-buffered overlay */
298 return save_glx_visual( dpy
, visinfo
,
300 GL_FALSE
, /* alpha */
301 GL_FALSE
, /* double */
302 GL_FALSE
, /* stereo */
304 0, /* stencil bits */
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
,
315 GL_FALSE
, /* alpha */
316 GL_TRUE
, /* double */
317 GL_FALSE
, /* stereo */
325 fprintf(stderr
,"Mesa: error in glXCreateContext: bad visual\n");
333 * Find the GLX visual associated with an XVisualInfo.
336 find_glx_visual( Display
*dpy
, XVisualInfo
*vinfo
)
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
];
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
];
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
363 static int transparent_pixel( XMesaVisual glxvis
)
365 Display
*dpy
= glxvis
->display
;
366 XVisualInfo
*vinfo
= glxvis
->visinfo
;
367 Atom overlayVisualsAtom
;
368 OverlayInfo
*overlay_info
= NULL
;
369 int numOverlaysPerScreen
;
373 unsigned long sizeData
, bytesLeft
;
377 * The SERVER_OVERLAY_VISUALS property on the root window contains
378 * a list of overlay visuals. Get that list now.
380 overlayVisualsAtom
= XInternAtom(dpy
,"SERVER_OVERLAY_VISUALS", True
);
381 if (overlayVisualsAtom
== None
) {
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
);
391 if (status
!= Success
|| actualType
!= overlayVisualsAtom
||
392 actualFormat
!= 32 || sizeData
< 4) {
393 /* something went wrong */
394 XFree((void *) overlay_info
);
398 /* search the overlay visual list for the visual ID of interest */
399 numOverlaysPerScreen
= (int) (sizeData
/ 4);
400 for (i
=0;i
<numOverlaysPerScreen
;i
++) {
402 ov
= overlay_info
+ i
;
403 if (ov
->overlay_visual
==vinfo
->visualid
) {
405 if (ov
->transparent_type
==0) {
406 /* type 0 indicates no transparency */
407 XFree((void *) overlay_info
);
411 /* ov->value is the transparent pixel */
412 XFree((void *) overlay_info
);
418 /* The visual ID was not found in the overlay list. */
419 XFree((void *) overlay_info
);
426 * Return number of bits set in n.
428 static int bitcount( unsigned long n
)
431 for (bits
=0; n
>0; n
=n
>>1) {
441 * Try to get an X visual which matches the given arguments.
443 static XVisualInfo
*get_visual( Display
*dpy
, int scr
,
444 unsigned int depth
, int xclass
)
446 XVisualInfo temp
, *vis
;
449 unsigned int default_depth
;
452 mask
= VisualScreenMask
| VisualDepthMask
| VisualClassMask
;
457 default_depth
= DefaultDepth(dpy
,scr
);
458 default_class
= DefaultVisual(dpy
,scr
)->CLASS
;
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
;
466 vis
= XGetVisualInfo( dpy
, mask
, &temp
, &n
);
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.
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) {
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.
497 static XVisualInfo
*get_env_visual(Display
*dpy
, int scr
, const char *varname
)
499 char value
[100], type
[100];
500 int depth
, xclass
= -1;
503 if (!getenv( varname
)) {
507 strncpy( value
, getenv(varname
), 100 );
510 sscanf( value
, "%s %d", type
, &depth
);
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
;
519 if (xclass
>-1 && depth
>0) {
520 vis
= get_visual( dpy
, scr
, depth
, xclass
);
526 fprintf( stderr
, "Mesa: GLX unable to find visual class=%s, depth=%d.\n",
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.
541 static XVisualInfo
*choose_x_visual( Display
*dpy
, int screen
,
542 GLboolean rgba
, int min_depth
,
543 int preferred_class
)
546 int xclass
, visclass
;
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" );
556 /* Otherwise, search for a suitable visual */
557 if (preferred_class
==DONT_CARE
) {
558 for (xclass
=0;xclass
<6;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;
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
);
578 vis
= get_visual( dpy
, screen
, depth
, visclass
);
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
);
595 vis
= get_visual( dpy
, screen
, depth
, visclass
);
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
;
615 /* start with shallowest */
616 for (depth
=0;depth
<=32;depth
++) {
617 vis
= get_visual( dpy
, screen
, depth
, visclass
);
624 /* start with deepest */
625 for (depth
=32;depth
>=min_depth
;depth
--) {
626 vis
= get_visual( dpy
, screen
, depth
, visclass
);
635 /* First see if the MESA_CI_VISUAL env var is defined */
636 vis
= get_env_visual( dpy
, screen
, "MESA_CI_VISUAL" );
640 /* Otherwise, search for a suitable visual, starting with shallowest */
641 if (preferred_class
==DONT_CARE
) {
642 for (xclass
=0;xclass
<4;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;
649 /* try 8-bit up through 16-bit */
650 for (depth
=8;depth
<=16;depth
++) {
651 vis
= get_visual( dpy
, screen
, depth
, visclass
);
656 /* try min_depth up to 8-bit */
657 for (depth
=min_depth
;depth
<8;depth
++) {
658 vis
= get_visual( dpy
, screen
, depth
, visclass
);
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
;
676 /* try 8-bit up through 16-bit */
677 for (depth
=8;depth
<=16;depth
++) {
678 vis
= get_visual( dpy
, screen
, depth
, visclass
);
683 /* try min_depth up to 8-bit */
684 for (depth
=min_depth
;depth
<8;depth
++) {
685 vis
= get_visual( dpy
, screen
, depth
, visclass
);
693 /* didn't find a visual */
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,
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.
711 static XVisualInfo
*choose_x_overlay_visual( Display
*dpy
, int scr
,
713 int level
, int trans_type
,
716 int preferred_class
)
718 Atom overlayVisualsAtom
;
719 OverlayInfo
*overlay_info
;
720 int numOverlaysPerScreen
;
724 unsigned long sizeData
, bytesLeft
;
726 XVisualInfo
*deepvis
;
729 /*DEBUG int tt, tv; */
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
;
742 * The SERVER_OVERLAY_VISUALS property on the root window contains
743 * a list of overlay visuals. Get that list now.
745 overlayVisualsAtom
= XInternAtom(dpy
,"SERVER_OVERLAY_VISUALS", True
);
746 if (overlayVisualsAtom
== (Atom
) None
) {
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
);
756 if (status
!= Success
|| actualType
!= overlayVisualsAtom
||
757 actualFormat
!= 32 || sizeData
< 4) {
758 /* something went wrong */
762 /* Search for the deepest overlay which satisifies all criteria. */
766 numOverlaysPerScreen
= (int) (sizeData
/ 4);
767 for (i
=0;i
<numOverlaysPerScreen
;i
++) {
768 XVisualInfo
*vislist
, vistemplate
;
771 ov
= overlay_info
+ i
;
773 if (ov
->layer
!=level
) {
774 /* failed overlay level criteria */
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 */
784 if (trans_value
!=DONT_CARE
&& trans_value
!=ov
->value
) {
785 /* failed transparent pixel value criteria */
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
);
796 /* something went wrong */
799 if (preferred_class
!=DONT_CARE
&& preferred_class
!=vislist
->CLASS
) {
800 /* wrong visual class */
804 /* if RGB was requested, make sure we have True/DirectColor */
805 if (rgbFlag
&& vislist
->CLASS
!= TrueColor
806 && vislist
->CLASS
!= DirectColor
)
809 /* if CI was requested, make sure we have a color indexed visual */
811 && (vislist
->CLASS
== TrueColor
|| vislist
->CLASS
== DirectColor
))
814 if (deepvis
==NULL
|| vislist
->depth
> deepest
) {
815 /* YES! found a satisfactory visual */
819 deepest
= vislist
->depth
;
821 /* DEBUG tt = ov->transparent_type;*/
822 /* DEBUG tv = ov->value; */
828 printf("chose 0x%x: layer=%d depth=%d trans_type=%d trans_value=%d\n",
829 deepvis->visualid, level, deepvis->depth, tt, tv );
837 XVisualInfo
*Fake_glXChooseVisual( Display
*dpy
, int screen
, int *list
)
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;
851 int visual_type
= DONT_CARE
;
852 int trans_type
= DONT_CARE
;
853 int trans_value
= DONT_CARE
;
859 switch (*parselist
) {
864 case GLX_BUFFER_SIZE
:
866 min_ci
= *parselist
++;
870 level
= *parselist
++;
876 case GLX_DOUBLEBUFFER
:
877 double_flag
= GL_TRUE
;
881 stereo_flag
= GL_TRUE
;
883 case GLX_AUX_BUFFERS
:
890 min_red
= *parselist
++;
894 min_green
= *parselist
++;
898 min_blue
= *parselist
++;
903 GLint size
= *parselist
++;
904 alpha_flag
= size
>0 ? 1 : 0;
909 depth_size
= *parselist
++;
911 case GLX_STENCIL_SIZE
:
913 stencil_size
= *parselist
++;
915 case GLX_ACCUM_RED_SIZE
:
916 case GLX_ACCUM_GREEN_SIZE
:
917 case GLX_ACCUM_BLUE_SIZE
:
918 case GLX_ACCUM_ALPHA_SIZE
:
921 GLint size
= *parselist
++;
922 accum_size
= MAX2( accum_size
, size
);
927 * GLX_EXT_visual_info extension
929 case GLX_X_VISUAL_TYPE_EXT
:
931 visual_type
= *parselist
++;
933 case GLX_TRANSPARENT_TYPE_EXT
:
935 trans_type
= *parselist
++;
937 case GLX_TRANSPARENT_INDEX_VALUE_EXT
:
939 trans_value
= *parselist
++;
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
:
953 /* undefined attribute */
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[].
966 /* normal color planes */
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 */
974 vis
= choose_x_visual( dpy
, screen
, rgb_flag
, min_rgb
, visual_type
);
977 /* Get a color index visual */
978 vis
= choose_x_visual( dpy
, screen
, rgb_flag
, min_ci
, visual_type
);
983 /* over/underlay planes */
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 */
991 vis
= choose_x_overlay_visual( dpy
, screen
, rgb_flag
, level
,
992 trans_type
, trans_value
, min_rgb
, visual_type
);
995 /* color index overlay */
996 vis
= choose_x_overlay_visual( dpy
, screen
, rgb_flag
, level
,
997 trans_type
, trans_value
, min_ci
, visual_type
);
1002 if (!save_glx_visual( dpy
, vis
, rgb_flag
, alpha_flag
, double_flag
,
1004 depth_size
, stencil_size
, accum_size
, level
))
1014 GLXContext
Fake_glXCreateContext( Display
*dpy
, XVisualInfo
*visinfo
,
1015 GLXContext share_list
, Bool direct
)
1020 /* deallocate unused windows/buffers */
1021 XMesaGarbageCollect();
1023 glxvis
= find_glx_visual( dpy
, visinfo
);
1025 /* This visual wasn't found with glXChooseVisual() */
1026 glxvis
= create_glx_visual( dpy
, visinfo
);
1028 /* unusable visual */
1033 xmctx
= XMesaCreateContext( glxvis
, (XMesaContext
) share_list
);
1035 /* set the direct/indirect flag */
1036 xmctx
->direct
= direct
;
1038 return (GLXContext
) xmctx
;
1042 static GLXDrawable MakeCurrent_PrevDrawable
= 0;
1043 static GLXContext MakeCurrent_PrevContext
= 0;
1044 static XMesaBuffer MakeCurrent_PrevBuffer
= 0;
1046 Bool
Fake_glXMakeCurrent( Display
*dpy
, GLXDrawable drawable
, GLXContext ctx
)
1048 if (ctx
&& drawable
) {
1050 XMesaContext xmctx
= (XMesaContext
) ctx
;
1052 if (drawable
==MakeCurrent_PrevDrawable
&& ctx
==MakeCurrent_PrevContext
) {
1053 buffer
= MakeCurrent_PrevBuffer
;
1056 buffer
= XMesaFindBuffer( dpy
, drawable
);
1059 /* drawable must be a new window! */
1060 buffer
= XMesaCreateWindowBuffer2( xmctx
->xm_visual
, drawable
, ctx
);
1062 /* Out of memory, or context/drawable depth mismatch */
1066 MakeCurrent_PrevContext
= ctx
;
1067 MakeCurrent_PrevDrawable
= drawable
;
1068 MakeCurrent_PrevBuffer
= buffer
;
1070 /* Now make current! */
1071 return (Bool
) XMesaMakeCurrent( (XMesaContext
) ctx
, buffer
);
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;
1082 /* ctx XOR drawable is NULL, this is an error */
1089 GLXPixmap
Fake_glXCreateGLXPixmap( Display
*dpy
, XVisualInfo
*visinfo
,
1095 v
= find_glx_visual( dpy
, visinfo
);
1097 v
= create_glx_visual( dpy
, visinfo
);
1099 /* unusable visual */
1104 b
= XMesaCreatePixmapBuffer( v
, pixmap
, 0 );
1108 return b
->frontbuffer
;
1112 #ifdef GLX_MESA_pixmap_colormap
1114 GLXPixmap
Fake_glXCreateGLXPixmapMESA( Display
*dpy
, XVisualInfo
*visinfo
,
1115 Pixmap pixmap
, Colormap cmap
)
1120 v
= find_glx_visual( dpy
, visinfo
);
1122 v
= create_glx_visual( dpy
, visinfo
);
1124 /* unusable visual */
1129 b
= XMesaCreatePixmapBuffer( v
, pixmap
, cmap
);
1133 return b
->frontbuffer
;
1139 void Fake_glXDestroyGLXPixmap( Display
*dpy
, GLXPixmap pixmap
)
1141 XMesaBuffer b
= XMesaFindBuffer(dpy
, pixmap
);
1143 XMesaDestroyBuffer(b
);
1145 else if (getenv("MESA_DEBUG")) {
1146 fprintf( stderr
, "Mesa: glXDestroyGLXPixmap: invalid pixmap\n");
1151 void Fake_glXCopyContext( Display
*dpy
, GLXContext src
, GLXContext dst
,
1154 XMesaContext xm_src
= (XMesaContext
) src
;
1155 XMesaContext xm_dst
= (XMesaContext
) dst
;
1157 gl_copy_context( xm_src
->gl_ctx
, xm_dst
->gl_ctx
, mask
);
1162 Bool
Fake_glXQueryExtension( Display
*dpy
, int *errorb
, int *event
)
1164 /* Mesa's GLX isn't really an X extension but we try to act like one. */
1172 void _kw_ungrab_all( Display
*dpy
)
1174 XUngrabPointer( dpy
, CurrentTime
);
1175 XUngrabKeyboard( dpy
, CurrentTime
);
1179 void Fake_glXDestroyContext( Display
*dpy
, GLXContext ctx
)
1182 MakeCurrent_PrevContext
= 0;
1183 MakeCurrent_PrevDrawable
= 0;
1184 MakeCurrent_PrevBuffer
= 0;
1185 XMesaDestroyContext( (XMesaContext
) ctx
);
1186 XMesaGarbageCollect();
1191 Bool
Fake_glXIsDirect( Display
*dpy
, GLXContext ctx
)
1194 return ((XMesaContext
) ctx
)->direct
;
1199 void Fake_glXSwapBuffers( Display
*dpy
, GLXDrawable drawable
)
1201 XMesaBuffer buffer
= XMesaFindBuffer( dpy
, drawable
);
1204 XMesaSwapBuffers(buffer
);
1206 else if (getenv("MESA_DEBUG")) {
1207 fprintf(stderr
, "Mesa Warning: glXSwapBuffers: invalid drawable\n");
1212 void Fake_glXCopySubBufferMESA( Display
*dpy
, GLXDrawable drawable
,
1213 int x
, int y
, int width
, int height
)
1215 XMesaBuffer buffer
= XMesaFindBuffer( dpy
, drawable
);
1217 XMesaCopySubBuffer(buffer
, x
, y
, width
, height
);
1219 else if (getenv("MESA_DEBUG")) {
1220 fprintf(stderr
, "Mesa Warning: glXCopySubBufferMESA: invalid drawable\n");
1226 Bool
Fake_glXQueryVersion( Display
*dpy
, int *maj
, int *min
)
1229 /* Return GLX version, not Mesa version */
1238 * Query the GLX attributes of the given XVisualInfo.
1240 int Fake_glXGetConfig( Display
*dpy
, XVisualInfo
*visinfo
,
1241 int attrib
, int *value
)
1245 glxvis
= find_glx_visual( dpy
, visinfo
);
1247 /* this visual wasn't obtained with glXChooseVisual */
1248 glxvis
= create_glx_visual( dpy
, visinfo
);
1250 /* this visual can't be used for GL rendering */
1251 if (attrib
==GLX_USE_GL
) {
1252 *value
= (int) False
;
1256 /*fprintf( stderr, "Mesa: Error in glXGetConfig: bad visual\n");*/
1257 return GLX_BAD_VISUAL
;
1264 *value
= (int) True
;
1266 case GLX_BUFFER_SIZE
:
1267 *value
= visinfo
->depth
;
1270 *value
= glxvis
->level
;
1273 if (glxvis
->gl_visual
->RGBAflag
) {
1280 case GLX_DOUBLEBUFFER
:
1281 *value
= (int) glxvis
->gl_visual
->DBflag
;
1284 *value
= (int) glxvis
->gl_visual
->StereoFlag
;
1286 case GLX_AUX_BUFFERS
:
1287 *value
= (int) False
;
1290 *value
= glxvis
->gl_visual
->RedBits
;
1292 case GLX_GREEN_SIZE
:
1293 *value
= glxvis
->gl_visual
->GreenBits
;
1296 *value
= glxvis
->gl_visual
->BlueBits
;
1298 case GLX_ALPHA_SIZE
:
1299 *value
= glxvis
->gl_visual
->AlphaBits
;
1301 case GLX_DEPTH_SIZE
:
1302 *value
= glxvis
->gl_visual
->DepthBits
;
1304 case GLX_STENCIL_SIZE
:
1305 *value
= glxvis
->gl_visual
->StencilBits
;
1307 case GLX_ACCUM_RED_SIZE
:
1308 case GLX_ACCUM_GREEN_SIZE
:
1309 case GLX_ACCUM_BLUE_SIZE
:
1310 *value
= glxvis
->gl_visual
->AccumBits
;
1312 case GLX_ACCUM_ALPHA_SIZE
:
1313 if (glxvis
->gl_visual
->AlphaBits
> 0)
1314 *value
= glxvis
->gl_visual
->AccumBits
;
1320 * GLX_EXT_visual_info extension
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;
1332 case GLX_TRANSPARENT_TYPE_EXT
:
1333 if (glxvis
->level
==0) {
1335 *value
= GLX_NONE_EXT
;
1337 else if (glxvis
->level
>0) {
1339 if (glxvis
->gl_visual
->RGBAflag
) {
1340 *value
= GLX_TRANSPARENT_RGB_EXT
;
1343 *value
= GLX_TRANSPARENT_INDEX_EXT
;
1346 else if (glxvis
->level
<0) {
1348 *value
= GLX_NONE_EXT
;
1351 case GLX_TRANSPARENT_INDEX_VALUE_EXT
:
1353 int pixel
= transparent_pixel( glxvis
);
1357 /* else undefined */
1360 case GLX_TRANSPARENT_RED_VALUE_EXT
:
1363 case GLX_TRANSPARENT_GREEN_VALUE_EXT
:
1366 case GLX_TRANSPARENT_BLUE_VALUE_EXT
:
1369 case GLX_TRANSPARENT_ALPHA_VALUE_EXT
:
1377 return GLX_BAD_ATTRIBUTE
;
1383 GLXContext
Fake_glXGetCurrentContext( void )
1385 return (GLXContext
) XMesaGetCurrentContext();
1390 GLXDrawable
Fake_glXGetCurrentDrawable( void )
1392 XMesaBuffer b
= XMesaGetCurrentBuffer();
1394 return b
->frontbuffer
;
1402 void Fake_glXWaitGL( void )
1404 XMesaContext xmesa
= XMesaGetCurrentContext();
1405 XMesaFlush( xmesa
);
1410 void Fake_glXWaitX( void )
1412 XMesaContext xmesa
= XMesaGetCurrentContext();
1413 XMesaFlush( xmesa
);
1418 * Return the extensions string, which is 3Dfx-dependant.
1420 static const char *get_extensions( void )
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";
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";
1433 /* GLX 1.1 and later */
1434 const char *Fake_glXQueryExtensionsString( Display
*dpy
, int screen
)
1438 return get_extensions();
1443 /* GLX 1.1 and later */
1444 const char *Fake_glXQueryServerString( Display
*dpy
, int screen
, int name
)
1446 static char *vendor
= "Brian Paul";
1447 static char *version
= "1.1 Mesa 3.1";
1453 case GLX_EXTENSIONS
:
1454 return get_extensions();
1466 /* GLX 1.1 and later */
1467 const char *Fake_glXGetClientString( Display
*dpy
, int name
)
1469 static char *vendor
= "Brian Paul";
1470 static char *version
= "1.1 Mesa 3.1";
1475 case GLX_EXTENSIONS
:
1476 return get_extensions();
1488 /* GLX 1.2 and later */
1489 Display
*Fake_glXGetCurrentDisplay( void )
1491 XMesaContext xmesa
= XMesaGetCurrentContext();
1492 if (xmesa
&& xmesa
->xm_visual
)
1493 return xmesa
->xm_visual
->display
;
1501 * Release the depth, stencil, accum buffers attached to a GLXDrawable
1502 * (a window or pixmap) prior to destroying the GLXDrawable.
1504 Bool
Fake_glXReleaseBuffersMESA( Display
*dpy
, GLXDrawable d
)
1506 XMesaBuffer b
= XMesaFindBuffer(dpy
, d
);
1508 XMesaDestroyBuffer(b
);
1516 * GLX_MESA_set_3dfx_mode
1518 GLboolean
Fake_glXSet3DfxModeMESA( GLint mode
)
1520 return XMesaSetFXmode( mode
);
1526 /*GLfunction Fake_glXGetProcAddress( const GLubyte *procName )*/
1527 void (*Fake_glXGetProcAddress( const GLubyte
*procName
))()
1529 typedef void (*GLfunction
)();
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 */
1545 /* First, look for core library functions */
1546 GLfunction f
= (GLfunction
) gl_get_proc_address(procName
);
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
;