1 /* $Id: fakeglx.c,v 1.12 1999/10/27 09:50:10 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.
56 #include <X11/Xutil.h>
68 /* Silence compiler warnings */
69 void Fake_glXDummyFunc( void )
83 #define MAX_VISUALS 100
84 static XMesaVisual VisualTable
[MAX_VISUALS
];
85 static int NumVisuals
= 0;
90 * This struct and some code fragments borrowed
91 * from Mark Kilgard's GLUT library.
93 typedef struct _OverlayInfo
{
94 /* Avoid 64-bit portability problems by being careful to use
95 longs due to the way XGetWindowProperty is specified. Note
96 that these parameters are passed as CARD32s over X
98 unsigned long overlay_visual
;
99 long transparent_type
;
106 /* Macro to handle c_class vs class field name in XVisualInfo struct */
107 #if defined(__cplusplus) || defined(c_plusplus)
108 #define CLASS c_class
117 * Test if the given XVisualInfo is usable for Mesa rendering.
119 static GLboolean
is_usable_visual( XVisualInfo
*vinfo
)
121 switch (vinfo
->CLASS
) {
124 /* Any StaticGray/GrayScale visual works in RGB or CI mode */
128 /* Any StaticColor/PseudoColor visual of at least 4 bits */
129 if (vinfo
->depth
>=4) {
137 /* Any depth of TrueColor or DirectColor works in RGB mode */
140 /* This should never happen */
148 * Return the level (overlay, normal, underlay) of a given XVisualInfo.
149 * Input: dpy - the X display
150 * vinfo - the XVisualInfo to test
151 * Return: level of the visual:
153 * >0 = overlay planes
154 * <0 = underlay planes
156 static int level_of_visual( Display
*dpy
, XVisualInfo
*vinfo
)
158 Atom overlayVisualsAtom
;
159 OverlayInfo
*overlay_info
= NULL
;
160 int numOverlaysPerScreen
;
164 unsigned long sizeData
, bytesLeft
;
168 * The SERVER_OVERLAY_VISUALS property on the root window contains
169 * a list of overlay visuals. Get that list now.
171 overlayVisualsAtom
= XInternAtom(dpy
,"SERVER_OVERLAY_VISUALS", True
);
172 if (overlayVisualsAtom
== None
) {
176 status
= XGetWindowProperty(dpy
, RootWindow( dpy
, vinfo
->screen
),
177 overlayVisualsAtom
, 0L, (long) 10000, False
,
178 overlayVisualsAtom
, &actualType
, &actualFormat
,
179 &sizeData
, &bytesLeft
,
180 (unsigned char **) &overlay_info
);
182 if (status
!= Success
|| actualType
!= overlayVisualsAtom
||
183 actualFormat
!= 32 || sizeData
< 4) {
184 /* something went wrong */
185 XFree((void *) overlay_info
);
189 /* search the overlay visual list for the visual ID of interest */
190 numOverlaysPerScreen
= (int) (sizeData
/ 4);
191 for (i
=0;i
<numOverlaysPerScreen
;i
++) {
193 ov
= overlay_info
+ i
;
194 if (ov
->overlay_visual
==vinfo
->visualid
) {
195 /* found the visual */
196 if (/*ov->transparent_type==1 &&*/ ov
->layer
!=0) {
197 int level
= ov
->layer
;
198 XFree((void *) overlay_info
);
202 XFree((void *) overlay_info
);
208 /* The visual ID was not found in the overlay list. */
209 XFree((void *) overlay_info
);
217 * Given an XVisualInfo and RGB, Double, and Depth buffer flags, save the
218 * configuration in our list of GLX visuals.
221 save_glx_visual( Display
*dpy
, XVisualInfo
*vinfo
,
222 GLboolean rgbFlag
, GLboolean alphaFlag
, GLboolean dbFlag
,
223 GLboolean stereoFlag
,
224 GLint depth_size
, GLint stencil_size
,
225 GLint accum_size
, GLint level
)
227 GLboolean ximageFlag
= GL_TRUE
;
230 GLboolean comparePointers
;
233 /* Check if the MESA_BACK_BUFFER env var is set */
234 char *backbuffer
= getenv("MESA_BACK_BUFFER");
236 if (backbuffer
[0]=='p' || backbuffer
[0]=='P') {
237 ximageFlag
= GL_FALSE
;
239 else if (backbuffer
[0]=='x' || backbuffer
[0]=='X') {
240 ximageFlag
= GL_TRUE
;
243 fprintf(stderr
, "Mesa: invalid value for MESA_BACK_BUFFER ");
244 fprintf(stderr
, "environment variable, using an XImage.\n");
249 /* Comparing IDs uses less memory but sometimes fails. */
250 /* XXX revisit this after 3.0 is finished. */
251 if (getenv("MESA_GLX_VISUAL_HACK"))
252 comparePointers
= GL_TRUE
;
254 comparePointers
= GL_FALSE
;
256 /* First check if a matching visual is already in the list */
257 for (i
=0; i
<NumVisuals
; i
++) {
258 XMesaVisual v
= VisualTable
[i
];
259 if (v
->display
== dpy
261 && v
->ximage_flag
== ximageFlag
262 && v
->gl_visual
->RGBAflag
== rgbFlag
263 && v
->gl_visual
->DBflag
== dbFlag
264 && v
->gl_visual
->StereoFlag
== stereoFlag
265 && (v
->gl_visual
->AlphaBits
> 0) == alphaFlag
266 && (v
->gl_visual
->DepthBits
>= depth_size
|| depth_size
== 0)
267 && (v
->gl_visual
->StencilBits
>= stencil_size
|| stencil_size
== 0)
268 && (v
->gl_visual
->AccumBits
>= accum_size
|| accum_size
== 0)) {
269 /* now either compare XVisualInfo pointers or visual IDs */
270 if ((!comparePointers
&& v
->vishandle
->visualid
== vinfo
->visualid
)
271 || (comparePointers
&& v
->vishandle
== vinfo
)) {
277 /* Create a new visual and add it to the list. */
279 if (NumVisuals
>=MAX_VISUALS
) {
280 fprintf( stderr
, "GLX Error: maximum number of visuals exceeded\n");
284 xmvis
= XMesaCreateVisual( dpy
, vinfo
, rgbFlag
, alphaFlag
, dbFlag
,
285 stereoFlag
, ximageFlag
,
286 depth_size
, stencil_size
, accum_size
, level
);
288 VisualTable
[NumVisuals
] = xmvis
;
297 * Create a GLX visual from a regular XVisualInfo.
300 create_glx_visual( Display
*dpy
, XVisualInfo
*visinfo
)
304 vislevel
= level_of_visual( dpy
, visinfo
);
306 /* Configure this visual as a CI, single-buffered overlay */
307 return save_glx_visual( dpy
, visinfo
,
309 GL_FALSE
, /* alpha */
310 GL_FALSE
, /* double */
311 GL_FALSE
, /* stereo */
313 0, /* stencil bits */
318 else if (is_usable_visual( visinfo
)) {
319 /* Configure this visual as RGB, double-buffered, depth-buffered. */
320 /* This is surely wrong for some people's needs but what else */
321 /* can be done? They should use glXChooseVisual(). */
322 return save_glx_visual( dpy
, visinfo
,
324 GL_FALSE
, /* alpha */
325 GL_TRUE
, /* double */
326 GL_FALSE
, /* stereo */
334 fprintf(stderr
,"Mesa: error in glXCreateContext: bad visual\n");
342 * Find the GLX visual associated with an XVisualInfo.
345 find_glx_visual( Display
*dpy
, XVisualInfo
*vinfo
)
349 /* First try to match pointers */
350 for (i
=0;i
<NumVisuals
;i
++) {
351 if (VisualTable
[i
]->display
==dpy
&& VisualTable
[i
]->vishandle
==vinfo
) {
352 return VisualTable
[i
];
355 /* try to match visual id */
356 for (i
=0;i
<NumVisuals
;i
++) {
357 if (VisualTable
[i
]->display
==dpy
358 && VisualTable
[i
]->visinfo
->visualid
== vinfo
->visualid
) {
359 return VisualTable
[i
];
368 * Return the transparent pixel value for a GLX visual.
369 * Input: glxvis - the glx_visual
370 * Return: a pixel value or -1 if no transparent pixel
372 static int transparent_pixel( XMesaVisual glxvis
)
374 Display
*dpy
= glxvis
->display
;
375 XVisualInfo
*vinfo
= glxvis
->visinfo
;
376 Atom overlayVisualsAtom
;
377 OverlayInfo
*overlay_info
= NULL
;
378 int numOverlaysPerScreen
;
382 unsigned long sizeData
, bytesLeft
;
386 * The SERVER_OVERLAY_VISUALS property on the root window contains
387 * a list of overlay visuals. Get that list now.
389 overlayVisualsAtom
= XInternAtom(dpy
,"SERVER_OVERLAY_VISUALS", True
);
390 if (overlayVisualsAtom
== None
) {
394 status
= XGetWindowProperty(dpy
, RootWindow( dpy
, vinfo
->screen
),
395 overlayVisualsAtom
, 0L, (long) 10000, False
,
396 overlayVisualsAtom
, &actualType
, &actualFormat
,
397 &sizeData
, &bytesLeft
,
398 (unsigned char **) &overlay_info
);
400 if (status
!= Success
|| actualType
!= overlayVisualsAtom
||
401 actualFormat
!= 32 || sizeData
< 4) {
402 /* something went wrong */
403 XFree((void *) overlay_info
);
407 /* search the overlay visual list for the visual ID of interest */
408 numOverlaysPerScreen
= (int) (sizeData
/ 4);
409 for (i
=0;i
<numOverlaysPerScreen
;i
++) {
411 ov
= overlay_info
+ i
;
412 if (ov
->overlay_visual
==vinfo
->visualid
) {
414 if (ov
->transparent_type
==0) {
415 /* type 0 indicates no transparency */
416 XFree((void *) overlay_info
);
420 /* ov->value is the transparent pixel */
421 XFree((void *) overlay_info
);
427 /* The visual ID was not found in the overlay list. */
428 XFree((void *) overlay_info
);
435 * Return number of bits set in n.
437 static int bitcount( unsigned long n
)
440 for (bits
=0; n
>0; n
=n
>>1) {
450 * Try to get an X visual which matches the given arguments.
452 static XVisualInfo
*get_visual( Display
*dpy
, int scr
,
453 unsigned int depth
, int xclass
)
455 XVisualInfo temp
, *vis
;
458 unsigned int default_depth
;
461 mask
= VisualScreenMask
| VisualDepthMask
| VisualClassMask
;
466 default_depth
= DefaultDepth(dpy
,scr
);
467 default_class
= DefaultVisual(dpy
,scr
)->CLASS
;
469 if (depth
==default_depth
&& xclass
==default_class
) {
470 /* try to get root window's visual */
471 temp
.visualid
= DefaultVisual(dpy
,scr
)->visualid
;
472 mask
|= VisualIDMask
;
475 vis
= XGetVisualInfo( dpy
, mask
, &temp
, &n
);
477 /* In case bits/pixel > 24, make sure color channels are still <=8 bits.
478 * An SGI Infinite Reality system, for example, can have 30bpp pixels:
479 * 10 bits per color channel. Mesa's limited to a max of 8 bits/channel.
481 if (vis
&& depth
> 24 && (xclass
==TrueColor
|| xclass
==DirectColor
)) {
482 if (bitcount(vis
->red_mask
) <= 8
483 && bitcount(vis
->green_mask
) <= 8
484 && bitcount(vis
->blue_mask
) <= 8) {
499 * Retrieve the value of the given environment variable and find
500 * the X visual which matches it.
501 * Input: dpy - the display
502 * screen - the screen number
503 * varname - the name of the environment variable
504 * Return: an XVisualInfo pointer to NULL if error.
506 static XVisualInfo
*get_env_visual(Display
*dpy
, int scr
, const char *varname
)
508 char value
[100], type
[100];
509 int depth
, xclass
= -1;
512 if (!getenv( varname
)) {
516 strncpy( value
, getenv(varname
), 100 );
519 sscanf( value
, "%s %d", type
, &depth
);
521 if (strcmp(type
,"TrueColor")==0) xclass
= TrueColor
;
522 else if (strcmp(type
,"DirectColor")==0) xclass
= DirectColor
;
523 else if (strcmp(type
,"PseudoColor")==0) xclass
= PseudoColor
;
524 else if (strcmp(type
,"StaticColor")==0) xclass
= StaticColor
;
525 else if (strcmp(type
,"GrayScale")==0) xclass
= GrayScale
;
526 else if (strcmp(type
,"StaticGray")==0) xclass
= StaticGray
;
528 if (xclass
>-1 && depth
>0) {
529 vis
= get_visual( dpy
, scr
, depth
, xclass
);
535 fprintf( stderr
, "Mesa: GLX unable to find visual class=%s, depth=%d.\n",
543 * Select an X visual which satisfies the RGBA/CI flag and minimum depth.
544 * Input: dpy, screen - X display and screen number
545 * rgba - GL_TRUE = RGBA mode, GL_FALSE = CI mode
546 * min_depth - minimum visual depth
547 * preferred_class - preferred GLX visual class or DONT_CARE
548 * Return: pointer to an XVisualInfo or NULL.
550 static XVisualInfo
*choose_x_visual( Display
*dpy
, int screen
,
551 GLboolean rgba
, int min_depth
,
552 int preferred_class
)
555 int xclass
, visclass
;
559 Atom hp_cr_maps
= XInternAtom(dpy
, "_HP_RGB_SMOOTH_MAP_LIST", True
);
560 /* First see if the MESA_RGB_VISUAL env var is defined */
561 vis
= get_env_visual( dpy
, screen
, "MESA_RGB_VISUAL" );
565 /* Otherwise, search for a suitable visual */
566 if (preferred_class
==DONT_CARE
) {
567 for (xclass
=0;xclass
<6;xclass
++) {
569 case 0: visclass
= TrueColor
; break;
570 case 1: visclass
= DirectColor
; break;
571 case 2: visclass
= PseudoColor
; break;
572 case 3: visclass
= StaticColor
; break;
573 case 4: visclass
= GrayScale
; break;
574 case 5: visclass
= StaticGray
; break;
577 /* start with shallowest */
578 for (depth
=0;depth
<=32;depth
++) {
579 if (visclass
==TrueColor
&& depth
==8 && !hp_cr_maps
) {
580 /* Special case: try to get 8-bit PseudoColor before */
581 /* 8-bit TrueColor */
582 vis
= get_visual( dpy
, screen
, 8, PseudoColor
);
587 vis
= get_visual( dpy
, screen
, depth
, visclass
);
594 /* start with deepest */
595 for (depth
=32;depth
>=min_depth
;depth
--) {
596 if (visclass
==TrueColor
&& depth
==8 && !hp_cr_maps
) {
597 /* Special case: try to get 8-bit PseudoColor before */
598 /* 8-bit TrueColor */
599 vis
= get_visual( dpy
, screen
, 8, PseudoColor
);
604 vis
= get_visual( dpy
, screen
, depth
, visclass
);
613 /* search for a specific visual class */
614 switch (preferred_class
) {
615 case GLX_TRUE_COLOR_EXT
: visclass
= TrueColor
; break;
616 case GLX_DIRECT_COLOR_EXT
: visclass
= DirectColor
; break;
617 case GLX_PSEUDO_COLOR_EXT
: visclass
= PseudoColor
; break;
618 case GLX_STATIC_COLOR_EXT
: visclass
= StaticColor
; break;
619 case GLX_GRAY_SCALE_EXT
: visclass
= GrayScale
; break;
620 case GLX_STATIC_GRAY_EXT
: visclass
= StaticGray
; break;
621 default: return NULL
;
624 /* start with shallowest */
625 for (depth
=0;depth
<=32;depth
++) {
626 vis
= get_visual( dpy
, screen
, depth
, visclass
);
633 /* start with deepest */
634 for (depth
=32;depth
>=min_depth
;depth
--) {
635 vis
= get_visual( dpy
, screen
, depth
, visclass
);
644 /* First see if the MESA_CI_VISUAL env var is defined */
645 vis
= get_env_visual( dpy
, screen
, "MESA_CI_VISUAL" );
649 /* Otherwise, search for a suitable visual, starting with shallowest */
650 if (preferred_class
==DONT_CARE
) {
651 for (xclass
=0;xclass
<4;xclass
++) {
653 case 0: visclass
= PseudoColor
; break;
654 case 1: visclass
= StaticColor
; break;
655 case 2: visclass
= GrayScale
; break;
656 case 3: visclass
= StaticGray
; break;
658 /* try 8-bit up through 16-bit */
659 for (depth
=8;depth
<=16;depth
++) {
660 vis
= get_visual( dpy
, screen
, depth
, visclass
);
665 /* try min_depth up to 8-bit */
666 for (depth
=min_depth
;depth
<8;depth
++) {
667 vis
= get_visual( dpy
, screen
, depth
, visclass
);
675 /* search for a specific visual class */
676 switch (preferred_class
) {
677 case GLX_TRUE_COLOR_EXT
: visclass
= TrueColor
; break;
678 case GLX_DIRECT_COLOR_EXT
: visclass
= DirectColor
; break;
679 case GLX_PSEUDO_COLOR_EXT
: visclass
= PseudoColor
; break;
680 case GLX_STATIC_COLOR_EXT
: visclass
= StaticColor
; break;
681 case GLX_GRAY_SCALE_EXT
: visclass
= GrayScale
; break;
682 case GLX_STATIC_GRAY_EXT
: visclass
= StaticGray
; break;
683 default: return NULL
;
685 /* try 8-bit up through 16-bit */
686 for (depth
=8;depth
<=16;depth
++) {
687 vis
= get_visual( dpy
, screen
, depth
, visclass
);
692 /* try min_depth up to 8-bit */
693 for (depth
=min_depth
;depth
<8;depth
++) {
694 vis
= get_visual( dpy
, screen
, depth
, visclass
);
702 /* didn't find a visual */
709 * Find the deepest X over/underlay visual of at least min_depth.
710 * Input: dpy, screen - X display and screen number
711 * level - the over/underlay level
712 * trans_type - transparent pixel type: GLX_NONE_EXT,
713 * GLX_TRANSPARENT_RGB_EXT, GLX_TRANSPARENT_INDEX_EXT,
715 * trans_value - transparent pixel value or DONT_CARE
716 * min_depth - minimum visual depth
717 * preferred_class - preferred GLX visual class or DONT_CARE
718 * Return: pointer to an XVisualInfo or NULL.
720 static XVisualInfo
*choose_x_overlay_visual( Display
*dpy
, int scr
,
722 int level
, int trans_type
,
725 int preferred_class
)
727 Atom overlayVisualsAtom
;
728 OverlayInfo
*overlay_info
;
729 int numOverlaysPerScreen
;
733 unsigned long sizeData
, bytesLeft
;
735 XVisualInfo
*deepvis
;
738 /*DEBUG int tt, tv; */
740 switch (preferred_class
) {
741 case GLX_TRUE_COLOR_EXT
: preferred_class
= TrueColor
; break;
742 case GLX_DIRECT_COLOR_EXT
: preferred_class
= DirectColor
; break;
743 case GLX_PSEUDO_COLOR_EXT
: preferred_class
= PseudoColor
; break;
744 case GLX_STATIC_COLOR_EXT
: preferred_class
= StaticColor
; break;
745 case GLX_GRAY_SCALE_EXT
: preferred_class
= GrayScale
; break;
746 case GLX_STATIC_GRAY_EXT
: preferred_class
= StaticGray
; break;
747 default: preferred_class
= DONT_CARE
;
751 * The SERVER_OVERLAY_VISUALS property on the root window contains
752 * a list of overlay visuals. Get that list now.
754 overlayVisualsAtom
= XInternAtom(dpy
,"SERVER_OVERLAY_VISUALS", True
);
755 if (overlayVisualsAtom
== (Atom
) None
) {
759 status
= XGetWindowProperty(dpy
, RootWindow( dpy
, scr
),
760 overlayVisualsAtom
, 0L, (long) 10000, False
,
761 overlayVisualsAtom
, &actualType
, &actualFormat
,
762 &sizeData
, &bytesLeft
,
763 (unsigned char **) &overlay_info
);
765 if (status
!= Success
|| actualType
!= overlayVisualsAtom
||
766 actualFormat
!= 32 || sizeData
< 4) {
767 /* something went wrong */
771 /* Search for the deepest overlay which satisifies all criteria. */
775 numOverlaysPerScreen
= (int) (sizeData
/ 4);
776 for (i
=0;i
<numOverlaysPerScreen
;i
++) {
777 XVisualInfo
*vislist
, vistemplate
;
780 ov
= overlay_info
+ i
;
782 if (ov
->layer
!=level
) {
783 /* failed overlay level criteria */
786 if (!(trans_type
==DONT_CARE
787 || (trans_type
==GLX_TRANSPARENT_INDEX_EXT
788 && ov
->transparent_type
>0)
789 || (trans_type
==GLX_NONE_EXT
&& ov
->transparent_type
==0))) {
790 /* failed transparent pixel type criteria */
793 if (trans_value
!=DONT_CARE
&& trans_value
!=ov
->value
) {
794 /* failed transparent pixel value criteria */
798 /* get XVisualInfo and check the depth */
799 vistemplate
.visualid
= ov
->overlay_visual
;
800 vistemplate
.screen
= scr
;
801 vislist
= XGetVisualInfo( dpy
, VisualIDMask
| VisualScreenMask
,
802 &vistemplate
, &count
);
805 /* something went wrong */
808 if (preferred_class
!=DONT_CARE
&& preferred_class
!=vislist
->CLASS
) {
809 /* wrong visual class */
813 /* if RGB was requested, make sure we have True/DirectColor */
814 if (rgbFlag
&& vislist
->CLASS
!= TrueColor
815 && vislist
->CLASS
!= DirectColor
)
818 /* if CI was requested, make sure we have a color indexed visual */
820 && (vislist
->CLASS
== TrueColor
|| vislist
->CLASS
== DirectColor
))
823 if (deepvis
==NULL
|| vislist
->depth
> deepest
) {
824 /* YES! found a satisfactory visual */
828 deepest
= vislist
->depth
;
830 /* DEBUG tt = ov->transparent_type;*/
831 /* DEBUG tv = ov->value; */
837 printf("chose 0x%x: layer=%d depth=%d trans_type=%d trans_value=%d\n",
838 deepvis->visualid, level, deepvis->depth, tt, tv );
846 XVisualInfo
*Fake_glXChooseVisual( Display
*dpy
, int screen
, int *list
)
851 int min_red
=0, min_green
=0, min_blue
=0;
852 GLboolean rgb_flag
= GL_FALSE
;
853 GLboolean alpha_flag
= GL_FALSE
;
854 GLboolean double_flag
= GL_FALSE
;
855 GLboolean stereo_flag
= GL_FALSE
;
856 GLint depth_size
= 0;
857 GLint stencil_size
= 0;
858 GLint accum_size
= 0;
860 int visual_type
= DONT_CARE
;
861 int trans_type
= DONT_CARE
;
862 int trans_value
= DONT_CARE
;
868 switch (*parselist
) {
873 case GLX_BUFFER_SIZE
:
875 min_ci
= *parselist
++;
879 level
= *parselist
++;
885 case GLX_DOUBLEBUFFER
:
886 double_flag
= GL_TRUE
;
890 stereo_flag
= GL_TRUE
;
892 case GLX_AUX_BUFFERS
:
899 min_red
= *parselist
++;
903 min_green
= *parselist
++;
907 min_blue
= *parselist
++;
912 GLint size
= *parselist
++;
913 alpha_flag
= size
>0 ? 1 : 0;
918 depth_size
= *parselist
++;
920 case GLX_STENCIL_SIZE
:
922 stencil_size
= *parselist
++;
924 case GLX_ACCUM_RED_SIZE
:
925 case GLX_ACCUM_GREEN_SIZE
:
926 case GLX_ACCUM_BLUE_SIZE
:
927 case GLX_ACCUM_ALPHA_SIZE
:
930 GLint size
= *parselist
++;
931 accum_size
= MAX2( accum_size
, size
);
936 * GLX_EXT_visual_info extension
938 case GLX_X_VISUAL_TYPE_EXT
:
940 visual_type
= *parselist
++;
942 case GLX_TRANSPARENT_TYPE_EXT
:
944 trans_type
= *parselist
++;
946 case GLX_TRANSPARENT_INDEX_VALUE_EXT
:
948 trans_value
= *parselist
++;
950 case GLX_TRANSPARENT_RED_VALUE_EXT
:
951 case GLX_TRANSPARENT_GREEN_VALUE_EXT
:
952 case GLX_TRANSPARENT_BLUE_VALUE_EXT
:
953 case GLX_TRANSPARENT_ALPHA_VALUE_EXT
:
962 /* undefined attribute */
968 * Since we're only simulating the GLX extension this function will never
969 * find any real GL visuals. Instead, all we can do is try to find an RGB
970 * or CI visual of appropriate depth. Other requested attributes such as
971 * double buffering, depth buffer, etc. will be associated with the X
972 * visual and stored in the VisualTable[].
975 /* normal color planes */
977 /* Get an RGB visual */
978 int min_rgb
= min_red
+ min_green
+ min_blue
;
979 if (min_rgb
>1 && min_rgb
<8) {
980 /* a special case to be sure we can get a monochrome visual */
983 vis
= choose_x_visual( dpy
, screen
, rgb_flag
, min_rgb
, visual_type
);
986 /* Get a color index visual */
987 vis
= choose_x_visual( dpy
, screen
, rgb_flag
, min_ci
, visual_type
);
992 /* over/underlay planes */
995 int min_rgb
= min_red
+ min_green
+ min_blue
;
996 if (min_rgb
>1 && min_rgb
<8) {
997 /* a special case to be sure we can get a monochrome visual */
1000 vis
= choose_x_overlay_visual( dpy
, screen
, rgb_flag
, level
,
1001 trans_type
, trans_value
, min_rgb
, visual_type
);
1004 /* color index overlay */
1005 vis
= choose_x_overlay_visual( dpy
, screen
, rgb_flag
, level
,
1006 trans_type
, trans_value
, min_ci
, visual_type
);
1011 if (!save_glx_visual( dpy
, vis
, rgb_flag
, alpha_flag
, double_flag
,
1013 depth_size
, stencil_size
, accum_size
, level
))
1023 GLXContext
Fake_glXCreateContext( Display
*dpy
, XVisualInfo
*visinfo
,
1024 GLXContext share_list
, Bool direct
)
1029 /* deallocate unused windows/buffers */
1030 XMesaGarbageCollect();
1032 glxvis
= find_glx_visual( dpy
, visinfo
);
1034 /* This visual wasn't found with glXChooseVisual() */
1035 glxvis
= create_glx_visual( dpy
, visinfo
);
1037 /* unusable visual */
1042 xmctx
= XMesaCreateContext( glxvis
, (XMesaContext
) share_list
);
1044 /* set the direct/indirect flag */
1045 xmctx
->direct
= direct
;
1047 return (GLXContext
) xmctx
;
1051 static GLXDrawable MakeCurrent_PrevDrawable
= 0;
1052 static GLXContext MakeCurrent_PrevContext
= 0;
1053 static XMesaBuffer MakeCurrent_PrevBuffer
= 0;
1055 Bool
Fake_glXMakeCurrent( Display
*dpy
, GLXDrawable drawable
, GLXContext ctx
)
1057 if (ctx
&& drawable
) {
1060 if (drawable
==MakeCurrent_PrevDrawable
&& ctx
==MakeCurrent_PrevContext
) {
1061 buffer
= MakeCurrent_PrevBuffer
;
1064 buffer
= XMesaFindBuffer( dpy
, drawable
);
1067 /* drawable must be a new window! */
1068 buffer
= XMesaCreateWindowBuffer2( ctx
->xm_visual
, drawable
, ctx
);
1070 /* Out of memory, or context/drawable depth mismatch */
1074 MakeCurrent_PrevContext
= ctx
;
1075 MakeCurrent_PrevDrawable
= drawable
;
1076 MakeCurrent_PrevBuffer
= buffer
;
1078 /* Now make current! */
1079 return (Bool
) XMesaMakeCurrent( (XMesaContext
) ctx
, buffer
);
1081 else if (!ctx
&& !drawable
) {
1082 /* release current context w/out assigning new one. */
1083 XMesaMakeCurrent( NULL
, NULL
);
1084 MakeCurrent_PrevContext
= 0;
1085 MakeCurrent_PrevDrawable
= 0;
1086 MakeCurrent_PrevBuffer
= 0;
1090 /* ctx XOR drawable is NULL, this is an error */
1097 GLXPixmap
Fake_glXCreateGLXPixmap( Display
*dpy
, XVisualInfo
*visinfo
,
1103 v
= find_glx_visual( dpy
, visinfo
);
1105 v
= create_glx_visual( dpy
, visinfo
);
1107 /* unusable visual */
1112 b
= XMesaCreatePixmapBuffer( v
, pixmap
, 0 );
1116 return b
->frontbuffer
;
1120 #ifdef GLX_MESA_pixmap_colormap
1122 GLXPixmap
Fake_glXCreateGLXPixmapMESA( Display
*dpy
, XVisualInfo
*visinfo
,
1123 Pixmap pixmap
, Colormap cmap
)
1128 v
= find_glx_visual( dpy
, visinfo
);
1130 v
= create_glx_visual( dpy
, visinfo
);
1132 /* unusable visual */
1137 b
= XMesaCreatePixmapBuffer( v
, pixmap
, cmap
);
1141 return b
->frontbuffer
;
1147 void Fake_glXDestroyGLXPixmap( Display
*dpy
, GLXPixmap pixmap
)
1149 XMesaBuffer b
= XMesaFindBuffer(dpy
, pixmap
);
1151 XMesaDestroyBuffer(b
);
1153 else if (getenv("MESA_DEBUG")) {
1154 fprintf( stderr
, "Mesa: glXDestroyGLXPixmap: invalid pixmap\n");
1159 void Fake_glXCopyContext( Display
*dpy
, GLXContext src
, GLXContext dst
,
1162 XMesaContext xm_src
= (XMesaContext
) src
;
1163 XMesaContext xm_dst
= (XMesaContext
) dst
;
1165 gl_copy_context( xm_src
->gl_ctx
, xm_dst
->gl_ctx
, mask
);
1170 Bool
Fake_glXQueryExtension( Display
*dpy
, int *errorb
, int *event
)
1172 /* Mesa's GLX isn't really an X extension but we try to act like one. */
1180 void _kw_ungrab_all( Display
*dpy
)
1182 XUngrabPointer( dpy
, CurrentTime
);
1183 XUngrabKeyboard( dpy
, CurrentTime
);
1187 void Fake_glXDestroyContext( Display
*dpy
, GLXContext ctx
)
1190 MakeCurrent_PrevContext
= 0;
1191 MakeCurrent_PrevDrawable
= 0;
1192 MakeCurrent_PrevBuffer
= 0;
1193 XMesaDestroyContext( (XMesaContext
) ctx
);
1194 XMesaGarbageCollect();
1199 Bool
Fake_glXIsDirect( Display
*dpy
, GLXContext ctx
)
1202 return ((XMesaContext
) ctx
)->direct
;
1207 void Fake_glXSwapBuffers( Display
*dpy
, GLXDrawable drawable
)
1209 XMesaBuffer buffer
= XMesaFindBuffer( dpy
, drawable
);
1212 XMesaSwapBuffers(buffer
);
1214 else if (getenv("MESA_DEBUG")) {
1215 fprintf(stderr
, "Mesa Warning: glXSwapBuffers: invalid drawable\n");
1220 void Fake_glXCopySubBufferMESA( Display
*dpy
, GLXDrawable drawable
,
1221 int x
, int y
, int width
, int height
)
1223 XMesaBuffer buffer
= XMesaFindBuffer( dpy
, drawable
);
1225 XMesaCopySubBuffer(buffer
, x
, y
, width
, height
);
1227 else if (getenv("MESA_DEBUG")) {
1228 fprintf(stderr
, "Mesa Warning: glXCopySubBufferMESA: invalid drawable\n");
1234 Bool
Fake_glXQueryVersion( Display
*dpy
, int *maj
, int *min
)
1237 /* Return GLX version, not Mesa version */
1246 * Query the GLX attributes of the given XVisualInfo.
1248 int Fake_glXGetConfig( Display
*dpy
, XVisualInfo
*visinfo
,
1249 int attrib
, int *value
)
1253 glxvis
= find_glx_visual( dpy
, visinfo
);
1255 /* this visual wasn't obtained with glXChooseVisual */
1256 glxvis
= create_glx_visual( dpy
, visinfo
);
1258 /* this visual can't be used for GL rendering */
1259 if (attrib
==GLX_USE_GL
) {
1260 *value
= (int) False
;
1264 /*fprintf( stderr, "Mesa: Error in glXGetConfig: bad visual\n");*/
1265 return GLX_BAD_VISUAL
;
1272 *value
= (int) True
;
1274 case GLX_BUFFER_SIZE
:
1275 *value
= visinfo
->depth
;
1278 *value
= glxvis
->level
;
1281 if (glxvis
->gl_visual
->RGBAflag
) {
1288 case GLX_DOUBLEBUFFER
:
1289 *value
= (int) glxvis
->gl_visual
->DBflag
;
1292 *value
= (int) glxvis
->gl_visual
->StereoFlag
;
1294 case GLX_AUX_BUFFERS
:
1295 *value
= (int) False
;
1298 *value
= glxvis
->gl_visual
->RedBits
;
1300 case GLX_GREEN_SIZE
:
1301 *value
= glxvis
->gl_visual
->GreenBits
;
1304 *value
= glxvis
->gl_visual
->BlueBits
;
1306 case GLX_ALPHA_SIZE
:
1307 *value
= glxvis
->gl_visual
->AlphaBits
;
1309 case GLX_DEPTH_SIZE
:
1310 *value
= glxvis
->gl_visual
->DepthBits
;
1312 case GLX_STENCIL_SIZE
:
1313 *value
= glxvis
->gl_visual
->StencilBits
;
1315 case GLX_ACCUM_RED_SIZE
:
1316 case GLX_ACCUM_GREEN_SIZE
:
1317 case GLX_ACCUM_BLUE_SIZE
:
1318 *value
= glxvis
->gl_visual
->AccumBits
;
1320 case GLX_ACCUM_ALPHA_SIZE
:
1321 if (glxvis
->gl_visual
->AlphaBits
> 0)
1322 *value
= glxvis
->gl_visual
->AccumBits
;
1328 * GLX_EXT_visual_info extension
1330 case GLX_X_VISUAL_TYPE_EXT
:
1331 switch (glxvis
->visinfo
->CLASS
) {
1332 case StaticGray
: *value
= GLX_STATIC_GRAY_EXT
; return 0;
1333 case GrayScale
: *value
= GLX_GRAY_SCALE_EXT
; return 0;
1334 case StaticColor
: *value
= GLX_STATIC_GRAY_EXT
; return 0;
1335 case PseudoColor
: *value
= GLX_PSEUDO_COLOR_EXT
; return 0;
1336 case TrueColor
: *value
= GLX_TRUE_COLOR_EXT
; return 0;
1337 case DirectColor
: *value
= GLX_DIRECT_COLOR_EXT
; return 0;
1340 case GLX_TRANSPARENT_TYPE_EXT
:
1341 if (glxvis
->level
==0) {
1343 *value
= GLX_NONE_EXT
;
1345 else if (glxvis
->level
>0) {
1347 if (glxvis
->gl_visual
->RGBAflag
) {
1348 *value
= GLX_TRANSPARENT_RGB_EXT
;
1351 *value
= GLX_TRANSPARENT_INDEX_EXT
;
1354 else if (glxvis
->level
<0) {
1356 *value
= GLX_NONE_EXT
;
1359 case GLX_TRANSPARENT_INDEX_VALUE_EXT
:
1361 int pixel
= transparent_pixel( glxvis
);
1365 /* else undefined */
1368 case GLX_TRANSPARENT_RED_VALUE_EXT
:
1371 case GLX_TRANSPARENT_GREEN_VALUE_EXT
:
1374 case GLX_TRANSPARENT_BLUE_VALUE_EXT
:
1377 case GLX_TRANSPARENT_ALPHA_VALUE_EXT
:
1385 return GLX_BAD_ATTRIBUTE
;
1391 GLXContext
Fake_glXGetCurrentContext( void )
1393 return (GLXContext
) XMesaGetCurrentContext();
1398 GLXDrawable
Fake_glXGetCurrentDrawable( void )
1400 XMesaBuffer b
= XMesaGetCurrentBuffer();
1402 return b
->frontbuffer
;
1410 void Fake_glXWaitGL( void )
1412 XMesaContext xmesa
= XMesaGetCurrentContext();
1413 XMesaFlush( xmesa
);
1418 void Fake_glXWaitX( void )
1420 XMesaContext xmesa
= XMesaGetCurrentContext();
1421 XMesaFlush( xmesa
);
1426 * Return the extensions string, which is 3Dfx-dependant.
1428 static const char *get_extensions( void )
1431 const char *fx
= getenv("MESA_GLX_FX");
1432 if (fx
&& fx
[0] != 'd') {
1433 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";
1436 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";
1441 /* GLX 1.1 and later */
1442 const char *Fake_glXQueryExtensionsString( Display
*dpy
, int screen
)
1446 return get_extensions();
1451 /* GLX 1.1 and later */
1452 const char *Fake_glXQueryServerString( Display
*dpy
, int screen
, int name
)
1454 static char *vendor
= "Brian Paul";
1455 static char *version
= "1.1 Mesa 3.1";
1461 case GLX_EXTENSIONS
:
1462 return get_extensions();
1474 /* GLX 1.1 and later */
1475 const char *Fake_glXGetClientString( Display
*dpy
, int name
)
1477 static char *vendor
= "Brian Paul";
1478 static char *version
= "1.1 Mesa 3.1";
1483 case GLX_EXTENSIONS
:
1484 return get_extensions();
1497 * Release the depth, stencil, accum buffers attached to a GLXDrawable
1498 * (a window or pixmap) prior to destroying the GLXDrawable.
1500 Bool
Fake_glXReleaseBuffersMESA( Display
*dpy
, GLXDrawable d
)
1502 XMesaBuffer b
= XMesaFindBuffer(dpy
, d
);
1504 XMesaDestroyBuffer(b
);
1512 * GLX_MESA_set_3dfx_mode
1514 GLboolean
Fake_glXSet3DfxModeMESA( GLint mode
)
1516 return XMesaSetFXmode( mode
);
1522 /*GLfunction Fake_glXGetProcAddress( const GLubyte *procName )*/
1523 void (*Fake_glXGetProcAddress( const GLubyte
*procName
))()
1525 typedef void (*GLfunction
)();
1530 static struct proc procTable
[] = {
1531 { "glXGetProcAddressEXT", (GLfunction
) glXGetProcAddressEXT
},
1532 { "glXCreateGLXPixmapMESA", (GLfunction
) glXCreateGLXPixmapMESA
},
1533 { "glXReleaseBuffersMESA", (GLfunction
) glXReleaseBuffersMESA
},
1534 { "glXCopySubBufferMESA", (GLfunction
) glXCopySubBufferMESA
},
1535 { "glXSet3DfxModeMESA", (GLfunction
) glXSet3DfxModeMESA
},
1536 /* NOTE: GLX_SGI_video_sync not implemented in Mesa */
1537 { NULL
, NULL
} /* end of list token */
1541 /* First, look for core library functions */
1542 GLfunction f
= (GLfunction
) gl_get_proc_address(procName
);
1546 /* Second, look for GLX funtion */
1547 for (i
= 0; procTable
[i
].address
; i
++) {
1548 if (strcmp((const char *) procName
, procTable
[i
].name
) == 0)
1549 return (GLfunction
) procTable
[i
].address
;