1 /* $Id: fakeglx.c,v 1.8 1999/09/16 16:44:37 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
,
721 int level
, int trans_type
,
724 int preferred_class
)
726 Atom overlayVisualsAtom
;
727 OverlayInfo
*overlay_info
;
728 int numOverlaysPerScreen
;
732 unsigned long sizeData
, bytesLeft
;
734 XVisualInfo
*deepvis
;
737 /*DEBUG int tt, tv; */
739 switch (preferred_class
) {
740 case GLX_TRUE_COLOR_EXT
: preferred_class
= TrueColor
; break;
741 case GLX_DIRECT_COLOR_EXT
: preferred_class
= DirectColor
; break;
742 case GLX_PSEUDO_COLOR_EXT
: preferred_class
= PseudoColor
; break;
743 case GLX_STATIC_COLOR_EXT
: preferred_class
= StaticColor
; break;
744 case GLX_GRAY_SCALE_EXT
: preferred_class
= GrayScale
; break;
745 case GLX_STATIC_GRAY_EXT
: preferred_class
= StaticGray
; break;
746 default: preferred_class
= DONT_CARE
;
750 * The SERVER_OVERLAY_VISUALS property on the root window contains
751 * a list of overlay visuals. Get that list now.
753 overlayVisualsAtom
= XInternAtom(dpy
,"SERVER_OVERLAY_VISUALS", True
);
754 if (overlayVisualsAtom
== (Atom
) None
) {
758 status
= XGetWindowProperty(dpy
, RootWindow( dpy
, scr
),
759 overlayVisualsAtom
, 0L, (long) 10000, False
,
760 overlayVisualsAtom
, &actualType
, &actualFormat
,
761 &sizeData
, &bytesLeft
,
762 (unsigned char **) &overlay_info
);
764 if (status
!= Success
|| actualType
!= overlayVisualsAtom
||
765 actualFormat
!= 32 || sizeData
< 4) {
766 /* something went wrong */
770 /* Search for the deepest overlay which satisifies all criteria. */
774 numOverlaysPerScreen
= (int) (sizeData
/ 4);
775 for (i
=0;i
<numOverlaysPerScreen
;i
++) {
776 XVisualInfo
*vislist
, vistemplate
;
779 ov
= overlay_info
+ i
;
781 if (ov
->layer
!=level
) {
782 /* failed overlay level criteria */
785 if (!(trans_type
==DONT_CARE
786 || (trans_type
==GLX_TRANSPARENT_INDEX_EXT
787 && ov
->transparent_type
>0)
788 || (trans_type
==GLX_NONE_EXT
&& ov
->transparent_type
==0))) {
789 /* failed transparent pixel type criteria */
792 if (trans_value
!=DONT_CARE
&& trans_value
!=ov
->value
) {
793 /* failed transparent pixel value criteria */
797 /* get XVisualInfo and check the depth */
798 vistemplate
.visualid
= ov
->overlay_visual
;
799 vistemplate
.screen
= scr
;
800 vislist
= XGetVisualInfo( dpy
, VisualIDMask
| VisualScreenMask
,
801 &vistemplate
, &count
);
804 /* something went wrong */
807 if (preferred_class
!=DONT_CARE
&& preferred_class
!=vislist
->CLASS
) {
808 /* wrong visual class */
812 if (deepvis
==NULL
|| vislist
->depth
> deepest
) {
813 /* YES! found a satisfactory visual */
817 deepest
= vislist
->depth
;
819 /* DEBUG tt = ov->transparent_type;*/
820 /* DEBUG tv = ov->value; */
826 printf("chose 0x%x: layer=%d depth=%d trans_type=%d trans_value=%d\n",
827 deepvis->visualid, level, deepvis->depth, tt, tv );
835 XVisualInfo
*Fake_glXChooseVisual( Display
*dpy
, int screen
, int *list
)
840 int min_red
=0, min_green
=0, min_blue
=0;
841 GLboolean rgb_flag
= GL_FALSE
;
842 GLboolean alpha_flag
= GL_FALSE
;
843 GLboolean double_flag
= GL_FALSE
;
844 GLboolean stereo_flag
= GL_FALSE
;
845 GLint depth_size
= 0;
846 GLint stencil_size
= 0;
847 GLint accum_size
= 0;
849 int visual_type
= DONT_CARE
;
850 int trans_type
= DONT_CARE
;
851 int trans_value
= DONT_CARE
;
857 switch (*parselist
) {
862 case GLX_BUFFER_SIZE
:
864 min_ci
= *parselist
++;
868 level
= *parselist
++;
874 case GLX_DOUBLEBUFFER
:
875 double_flag
= GL_TRUE
;
879 stereo_flag
= GL_TRUE
;
881 case GLX_AUX_BUFFERS
:
888 min_red
= *parselist
++;
892 min_green
= *parselist
++;
896 min_blue
= *parselist
++;
901 GLint size
= *parselist
++;
902 alpha_flag
= size
>0 ? 1 : 0;
907 depth_size
= *parselist
++;
909 case GLX_STENCIL_SIZE
:
911 stencil_size
= *parselist
++;
913 case GLX_ACCUM_RED_SIZE
:
914 case GLX_ACCUM_GREEN_SIZE
:
915 case GLX_ACCUM_BLUE_SIZE
:
916 case GLX_ACCUM_ALPHA_SIZE
:
919 GLint size
= *parselist
++;
920 accum_size
= MAX2( accum_size
, size
);
925 * GLX_EXT_visual_info extension
927 case GLX_X_VISUAL_TYPE_EXT
:
929 visual_type
= *parselist
++;
931 case GLX_TRANSPARENT_TYPE_EXT
:
933 trans_type
= *parselist
++;
935 case GLX_TRANSPARENT_INDEX_VALUE_EXT
:
937 trans_value
= *parselist
++;
939 case GLX_TRANSPARENT_RED_VALUE_EXT
:
940 case GLX_TRANSPARENT_GREEN_VALUE_EXT
:
941 case GLX_TRANSPARENT_BLUE_VALUE_EXT
:
942 case GLX_TRANSPARENT_ALPHA_VALUE_EXT
:
951 /* undefined attribute */
957 * Since we're only simulating the GLX extension this function will never
958 * find any real GL visuals. Instead, all we can do is try to find an RGB
959 * or CI visual of appropriate depth. Other requested attributes such as
960 * double buffering, depth buffer, etc. will be associated with the X
961 * visual and stored in the VisualTable[].
964 /* normal color planes */
966 /* Get an RGB visual */
967 int min_rgb
= min_red
+ min_green
+ min_blue
;
968 if (min_rgb
>1 && min_rgb
<8) {
969 /* a special case to be sure we can get a monochrome visual */
972 vis
= choose_x_visual( dpy
, screen
, rgb_flag
, min_rgb
, visual_type
);
975 /* Get a color index visual */
976 vis
= choose_x_visual( dpy
, screen
, rgb_flag
, min_ci
, visual_type
);
981 /* over/underlay planes */
982 vis
= choose_x_overlay_visual( dpy
, screen
, level
, trans_type
,
983 trans_value
, min_ci
, visual_type
);
987 if (!save_glx_visual( dpy
, vis
, rgb_flag
, alpha_flag
, double_flag
,
989 depth_size
, stencil_size
, accum_size
, level
))
999 GLXContext
Fake_glXCreateContext( Display
*dpy
, XVisualInfo
*visinfo
,
1000 GLXContext share_list
, Bool direct
)
1005 /* deallocate unused windows/buffers */
1006 XMesaGarbageCollect();
1008 glxvis
= find_glx_visual( dpy
, visinfo
);
1010 /* This visual wasn't found with glXChooseVisual() */
1011 glxvis
= create_glx_visual( dpy
, visinfo
);
1013 /* unusable visual */
1018 xmctx
= XMesaCreateContext( glxvis
, (XMesaContext
) share_list
);
1020 /* set the direct/indirect flag */
1021 xmctx
->direct
= direct
;
1023 return (GLXContext
) xmctx
;
1027 static GLXDrawable MakeCurrent_PrevDrawable
= 0;
1028 static GLXContext MakeCurrent_PrevContext
= 0;
1029 static XMesaBuffer MakeCurrent_PrevBuffer
= 0;
1031 Bool
Fake_glXMakeCurrent( Display
*dpy
, GLXDrawable drawable
, GLXContext ctx
)
1033 if (ctx
&& drawable
) {
1036 if (drawable
==MakeCurrent_PrevDrawable
&& ctx
==MakeCurrent_PrevContext
) {
1037 buffer
= MakeCurrent_PrevBuffer
;
1040 buffer
= XMesaFindBuffer( dpy
, drawable
);
1043 /* drawable must be a new window! */
1044 buffer
= XMesaCreateWindowBuffer2( ctx
->xm_visual
, drawable
, ctx
);
1046 /* Out of memory, or context/drawable depth mismatch */
1050 MakeCurrent_PrevContext
= ctx
;
1051 MakeCurrent_PrevDrawable
= drawable
;
1052 MakeCurrent_PrevBuffer
= buffer
;
1054 /* Now make current! */
1055 return (Bool
) XMesaMakeCurrent( (XMesaContext
) ctx
, buffer
);
1057 else if (!ctx
&& !drawable
) {
1058 /* release current context w/out assigning new one. */
1059 XMesaMakeCurrent( NULL
, NULL
);
1060 MakeCurrent_PrevContext
= 0;
1061 MakeCurrent_PrevDrawable
= 0;
1062 MakeCurrent_PrevBuffer
= 0;
1066 /* ctx XOR drawable is NULL, this is an error */
1073 GLXPixmap
Fake_glXCreateGLXPixmap( Display
*dpy
, XVisualInfo
*visinfo
,
1079 v
= find_glx_visual( dpy
, visinfo
);
1081 v
= create_glx_visual( dpy
, visinfo
);
1083 /* unusable visual */
1088 b
= XMesaCreatePixmapBuffer( v
, pixmap
, 0 );
1092 return b
->frontbuffer
;
1096 #ifdef GLX_MESA_pixmap_colormap
1098 GLXPixmap
Fake_glXCreateGLXPixmapMESA( Display
*dpy
, XVisualInfo
*visinfo
,
1099 Pixmap pixmap
, Colormap cmap
)
1104 v
= find_glx_visual( dpy
, visinfo
);
1106 v
= create_glx_visual( dpy
, visinfo
);
1108 /* unusable visual */
1113 b
= XMesaCreatePixmapBuffer( v
, pixmap
, cmap
);
1117 return b
->frontbuffer
;
1123 void Fake_glXDestroyGLXPixmap( Display
*dpy
, GLXPixmap pixmap
)
1125 XMesaBuffer b
= XMesaFindBuffer(dpy
, pixmap
);
1127 XMesaDestroyBuffer(b
);
1129 else if (getenv("MESA_DEBUG")) {
1130 fprintf( stderr
, "Mesa: glXDestroyGLXPixmap: invalid pixmap\n");
1135 void Fake_glXCopyContext( Display
*dpy
, GLXContext src
, GLXContext dst
,
1138 XMesaContext xm_src
= (XMesaContext
) src
;
1139 XMesaContext xm_dst
= (XMesaContext
) dst
;
1141 gl_copy_context( xm_src
->gl_ctx
, xm_dst
->gl_ctx
, mask
);
1146 Bool
Fake_glXQueryExtension( Display
*dpy
, int *errorb
, int *event
)
1148 /* Mesa's GLX isn't really an X extension but we try to act like one. */
1156 void _kw_ungrab_all( Display
*dpy
)
1158 XUngrabPointer( dpy
, CurrentTime
);
1159 XUngrabKeyboard( dpy
, CurrentTime
);
1163 void Fake_glXDestroyContext( Display
*dpy
, GLXContext ctx
)
1166 MakeCurrent_PrevContext
= 0;
1167 MakeCurrent_PrevDrawable
= 0;
1168 MakeCurrent_PrevBuffer
= 0;
1169 XMesaDestroyContext( (XMesaContext
) ctx
);
1170 XMesaGarbageCollect();
1175 Bool
Fake_glXIsDirect( Display
*dpy
, GLXContext ctx
)
1178 return ((XMesaContext
) ctx
)->direct
;
1183 void Fake_glXSwapBuffers( Display
*dpy
, GLXDrawable drawable
)
1185 XMesaBuffer buffer
= XMesaFindBuffer( dpy
, drawable
);
1188 XMesaSwapBuffers(buffer
);
1190 else if (getenv("MESA_DEBUG")) {
1191 fprintf(stderr
, "Mesa Warning: glXSwapBuffers: invalid drawable\n");
1196 void Fake_glXCopySubBufferMESA( Display
*dpy
, GLXDrawable drawable
,
1197 int x
, int y
, int width
, int height
)
1199 XMesaBuffer buffer
= XMesaFindBuffer( dpy
, drawable
);
1201 XMesaCopySubBuffer(buffer
, x
, y
, width
, height
);
1203 else if (getenv("MESA_DEBUG")) {
1204 fprintf(stderr
, "Mesa Warning: glXCopySubBufferMESA: invalid drawable\n");
1210 Bool
Fake_glXQueryVersion( Display
*dpy
, int *maj
, int *min
)
1213 /* Return GLX version, not Mesa version */
1222 * Query the GLX attributes of the given XVisualInfo.
1224 int Fake_glXGetConfig( Display
*dpy
, XVisualInfo
*visinfo
,
1225 int attrib
, int *value
)
1229 glxvis
= find_glx_visual( dpy
, visinfo
);
1231 /* this visual wasn't obtained with glXChooseVisual */
1232 glxvis
= create_glx_visual( dpy
, visinfo
);
1234 /* this visual can't be used for GL rendering */
1235 if (attrib
==GLX_USE_GL
) {
1236 *value
= (int) False
;
1240 /*fprintf( stderr, "Mesa: Error in glXGetConfig: bad visual\n");*/
1241 return GLX_BAD_VISUAL
;
1248 *value
= (int) True
;
1250 case GLX_BUFFER_SIZE
:
1251 *value
= visinfo
->depth
;
1254 *value
= glxvis
->level
;
1257 if (glxvis
->gl_visual
->RGBAflag
) {
1264 case GLX_DOUBLEBUFFER
:
1265 *value
= (int) glxvis
->gl_visual
->DBflag
;
1268 *value
= (int) glxvis
->gl_visual
->StereoFlag
;
1270 case GLX_AUX_BUFFERS
:
1271 *value
= (int) False
;
1274 *value
= glxvis
->gl_visual
->RedBits
;
1276 case GLX_GREEN_SIZE
:
1277 *value
= glxvis
->gl_visual
->GreenBits
;
1280 *value
= glxvis
->gl_visual
->BlueBits
;
1282 case GLX_ALPHA_SIZE
:
1283 *value
= glxvis
->gl_visual
->AlphaBits
;
1285 case GLX_DEPTH_SIZE
:
1286 *value
= glxvis
->gl_visual
->DepthBits
;
1288 case GLX_STENCIL_SIZE
:
1289 *value
= glxvis
->gl_visual
->StencilBits
;
1291 case GLX_ACCUM_RED_SIZE
:
1292 case GLX_ACCUM_GREEN_SIZE
:
1293 case GLX_ACCUM_BLUE_SIZE
:
1294 *value
= glxvis
->gl_visual
->AccumBits
;
1296 case GLX_ACCUM_ALPHA_SIZE
:
1297 if (glxvis
->gl_visual
->AlphaBits
> 0)
1298 *value
= glxvis
->gl_visual
->AccumBits
;
1304 * GLX_EXT_visual_info extension
1306 case GLX_X_VISUAL_TYPE_EXT
:
1307 switch (glxvis
->visinfo
->CLASS
) {
1308 case StaticGray
: *value
= GLX_STATIC_GRAY_EXT
; return 0;
1309 case GrayScale
: *value
= GLX_GRAY_SCALE_EXT
; return 0;
1310 case StaticColor
: *value
= GLX_STATIC_GRAY_EXT
; return 0;
1311 case PseudoColor
: *value
= GLX_PSEUDO_COLOR_EXT
; return 0;
1312 case TrueColor
: *value
= GLX_TRUE_COLOR_EXT
; return 0;
1313 case DirectColor
: *value
= GLX_DIRECT_COLOR_EXT
; return 0;
1316 case GLX_TRANSPARENT_TYPE_EXT
:
1317 if (glxvis
->level
==0) {
1319 *value
= GLX_NONE_EXT
;
1321 else if (glxvis
->level
>0) {
1323 if (glxvis
->gl_visual
->RGBAflag
) {
1324 *value
= GLX_TRANSPARENT_RGB_EXT
;
1327 *value
= GLX_TRANSPARENT_INDEX_EXT
;
1330 else if (glxvis
->level
<0) {
1332 *value
= GLX_NONE_EXT
;
1335 case GLX_TRANSPARENT_INDEX_VALUE_EXT
:
1337 int pixel
= transparent_pixel( glxvis
);
1341 /* else undefined */
1344 case GLX_TRANSPARENT_RED_VALUE_EXT
:
1347 case GLX_TRANSPARENT_GREEN_VALUE_EXT
:
1350 case GLX_TRANSPARENT_BLUE_VALUE_EXT
:
1353 case GLX_TRANSPARENT_ALPHA_VALUE_EXT
:
1361 return GLX_BAD_ATTRIBUTE
;
1367 GLXContext
Fake_glXGetCurrentContext( void )
1369 return (GLXContext
) XMesaGetCurrentContext();
1374 GLXDrawable
Fake_glXGetCurrentDrawable( void )
1376 XMesaBuffer b
= XMesaGetCurrentBuffer();
1378 return b
->frontbuffer
;
1386 void Fake_glXWaitGL( void )
1388 XMesaContext xmesa
= XMesaGetCurrentContext();
1389 XMesaFlush( xmesa
);
1394 void Fake_glXWaitX( void )
1396 XMesaContext xmesa
= XMesaGetCurrentContext();
1397 XMesaFlush( xmesa
);
1402 * Return the extensions string, which is 3Dfx-dependant.
1404 static const char *get_extensions( void )
1407 const char *fx
= getenv("MESA_GLX_FX");
1408 if (fx
&& fx
[0] != 'd') {
1409 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";
1412 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";
1417 /* GLX 1.1 and later */
1418 const char *Fake_glXQueryExtensionsString( Display
*dpy
, int screen
)
1422 return get_extensions();
1427 /* GLX 1.1 and later */
1428 const char *Fake_glXQueryServerString( Display
*dpy
, int screen
, int name
)
1430 static char *vendor
= "Brian Paul";
1431 static char *version
= "1.1 Mesa 3.1";
1437 case GLX_EXTENSIONS
:
1438 return get_extensions();
1450 /* GLX 1.1 and later */
1451 const char *Fake_glXGetClientString( Display
*dpy
, int name
)
1453 static char *vendor
= "Brian Paul";
1454 static char *version
= "1.1 Mesa 3.1";
1459 case GLX_EXTENSIONS
:
1460 return get_extensions();
1473 * Release the depth, stencil, accum buffers attached to a GLXDrawable
1474 * (a window or pixmap) prior to destroying the GLXDrawable.
1476 Bool
Fake_glXReleaseBuffersMESA( Display
*dpy
, GLXDrawable d
)
1478 XMesaBuffer b
= XMesaFindBuffer(dpy
, d
);
1480 XMesaDestroyBuffer(b
);
1488 * GLX_MESA_set_3dfx_mode
1490 GLboolean
Fake_glXSet3DfxModeMESA( GLint mode
)
1492 return XMesaSetFXmode( mode
);
1497 /*GLfunction Fake_glXGetProcAddress( const GLubyte *procName )*/
1498 void (*Fake_glXGetProcAddress( const GLubyte
*procName
))()
1500 typedef void (*GLfunction
)();
1505 static struct proc procTable
[] = {
1506 { "glXGetProcAddressEXT", (GLfunction
) glXGetProcAddressEXT
},
1507 { "glXCreateGLXPixmapMESA", (GLfunction
) glXCreateGLXPixmapMESA
},
1508 { "glXReleaseBuffersMESA", (GLfunction
) glXReleaseBuffersMESA
},
1509 { "glXCopySubBufferMESA", (GLfunction
) glXCopySubBufferMESA
},
1510 { "glXSet3DfxModeMESA", (GLfunction
) glXSet3DfxModeMESA
},
1511 /* NOTE: GLX_SGI_video_sync not implemented in Mesa */
1512 { NULL
, NULL
} /* end of list token */
1516 /* First, look for core library functions */
1517 for (i
= 0; procTable
[i
].address
; i
++) {
1518 if (strcmp((const char *) procName
, procTable
[i
].name
) == 0)
1519 return (GLfunction
) procTable
[i
].address
;