1 /* $Id: fakeglx.c,v 1.3 1999/09/11 11:35:11 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>
72 #define MAX_VISUALS 100
73 static XMesaVisual VisualTable
[MAX_VISUALS
];
74 static int NumVisuals
= 0;
79 * This struct and some code fragments borrowed
80 * from Mark Kilgard's GLUT library.
82 typedef struct _OverlayInfo
{
83 /* Avoid 64-bit portability problems by being careful to use
84 longs due to the way XGetWindowProperty is specified. Note
85 that these parameters are passed as CARD32s over X
87 unsigned long overlay_visual
;
88 long transparent_type
;
95 /* Macro to handle c_class vs class field name in XVisualInfo struct */
96 #if defined(__cplusplus) || defined(c_plusplus)
106 * Test if the given XVisualInfo is usable for Mesa rendering.
108 static GLboolean
is_usable_visual( XVisualInfo
*vinfo
)
110 switch (vinfo
->CLASS
) {
113 /* Any StaticGray/GrayScale visual works in RGB or CI mode */
117 /* Any StaticColor/PseudoColor visual of at least 4 bits */
118 if (vinfo
->depth
>=4) {
126 /* Any depth of TrueColor or DirectColor works in RGB mode */
129 /* This should never happen */
137 * Return the level (overlay, normal, underlay) of a given XVisualInfo.
138 * Input: dpy - the X display
139 * vinfo - the XVisualInfo to test
140 * Return: level of the visual:
142 * >0 = overlay planes
143 * <0 = underlay planes
145 static int level_of_visual( Display
*dpy
, XVisualInfo
*vinfo
)
147 Atom overlayVisualsAtom
;
148 OverlayInfo
*overlay_info
= NULL
;
149 int numOverlaysPerScreen
;
153 unsigned long sizeData
, bytesLeft
;
157 * The SERVER_OVERLAY_VISUALS property on the root window contains
158 * a list of overlay visuals. Get that list now.
160 overlayVisualsAtom
= XInternAtom(dpy
,"SERVER_OVERLAY_VISUALS", True
);
161 if (overlayVisualsAtom
== None
) {
165 status
= XGetWindowProperty(dpy
, RootWindow( dpy
, vinfo
->screen
),
166 overlayVisualsAtom
, 0L, (long) 10000, False
,
167 overlayVisualsAtom
, &actualType
, &actualFormat
,
168 &sizeData
, &bytesLeft
,
169 (unsigned char **) &overlay_info
);
171 if (status
!= Success
|| actualType
!= overlayVisualsAtom
||
172 actualFormat
!= 32 || sizeData
< 4) {
173 /* something went wrong */
174 XFree((void *) overlay_info
);
178 /* search the overlay visual list for the visual ID of interest */
179 numOverlaysPerScreen
= (int) (sizeData
/ 4);
180 for (i
=0;i
<numOverlaysPerScreen
;i
++) {
182 ov
= overlay_info
+ i
;
183 if (ov
->overlay_visual
==vinfo
->visualid
) {
184 /* found the visual */
185 if (/*ov->transparent_type==1 &&*/ ov
->layer
!=0) {
186 int level
= ov
->layer
;
187 XFree((void *) overlay_info
);
191 XFree((void *) overlay_info
);
197 /* The visual ID was not found in the overlay list. */
198 XFree((void *) overlay_info
);
206 * Given an XVisualInfo and RGB, Double, and Depth buffer flags, save the
207 * configuration in our list of GLX visuals.
210 save_glx_visual( Display
*dpy
, XVisualInfo
*vinfo
,
211 GLboolean rgbFlag
, GLboolean alphaFlag
, GLboolean dbFlag
,
212 GLboolean stereoFlag
,
213 GLint depth_size
, GLint stencil_size
,
214 GLint accum_size
, GLint level
)
216 GLboolean ximageFlag
= GL_TRUE
;
219 GLboolean comparePointers
;
222 /* Check if the MESA_BACK_BUFFER env var is set */
223 char *backbuffer
= getenv("MESA_BACK_BUFFER");
225 if (backbuffer
[0]=='p' || backbuffer
[0]=='P') {
226 ximageFlag
= GL_FALSE
;
228 else if (backbuffer
[0]=='x' || backbuffer
[0]=='X') {
229 ximageFlag
= GL_TRUE
;
232 fprintf(stderr
, "Mesa: invalid value for MESA_BACK_BUFFER ");
233 fprintf(stderr
, "environment variable, using an XImage.\n");
238 /* Comparing IDs uses less memory but sometimes fails. */
239 /* XXX revisit this after 3.0 is finished. */
240 if (getenv("MESA_GLX_VISUAL_HACK"))
241 comparePointers
= GL_TRUE
;
243 comparePointers
= GL_FALSE
;
245 /* First check if a matching visual is already in the list */
246 for (i
=0; i
<NumVisuals
; i
++) {
247 XMesaVisual v
= VisualTable
[i
];
248 if (v
->display
== dpy
250 && v
->ximage_flag
== ximageFlag
251 && v
->gl_visual
->RGBAflag
== rgbFlag
252 && v
->gl_visual
->DBflag
== dbFlag
253 && v
->gl_visual
->StereoFlag
== stereoFlag
254 && (v
->gl_visual
->AlphaBits
> 0) == alphaFlag
255 && (v
->gl_visual
->DepthBits
>= depth_size
|| depth_size
== 0)
256 && (v
->gl_visual
->StencilBits
>= stencil_size
|| stencil_size
== 0)
257 && (v
->gl_visual
->AccumBits
>= accum_size
|| accum_size
== 0)) {
258 /* now either compare XVisualInfo pointers or visual IDs */
259 if ((!comparePointers
&& v
->vishandle
->visualid
== vinfo
->visualid
)
260 || (comparePointers
&& v
->vishandle
== vinfo
)) {
266 /* Create a new visual and add it to the list. */
268 if (NumVisuals
>=MAX_VISUALS
) {
269 fprintf( stderr
, "GLX Error: maximum number of visuals exceeded\n");
273 xmvis
= XMesaCreateVisual( dpy
, vinfo
, rgbFlag
, alphaFlag
, dbFlag
,
274 stereoFlag
, ximageFlag
,
275 depth_size
, stencil_size
, accum_size
, level
);
277 VisualTable
[NumVisuals
] = xmvis
;
286 * Create a GLX visual from a regular XVisualInfo.
289 create_glx_visual( Display
*dpy
, XVisualInfo
*visinfo
)
293 vislevel
= level_of_visual( dpy
, visinfo
);
295 /* Configure this visual as a CI, single-buffered overlay */
296 return save_glx_visual( dpy
, visinfo
,
298 GL_FALSE
, /* alpha */
299 GL_FALSE
, /* double */
300 GL_FALSE
, /* stereo */
302 0, /* stencil bits */
307 else if (is_usable_visual( visinfo
)) {
308 /* Configure this visual as RGB, double-buffered, depth-buffered. */
309 /* This is surely wrong for some people's needs but what else */
310 /* can be done? They should use glXChooseVisual(). */
311 return save_glx_visual( dpy
, visinfo
,
313 GL_FALSE
, /* alpha */
314 GL_TRUE
, /* double */
315 GL_FALSE
, /* stereo */
323 fprintf(stderr
,"Mesa: error in glXCreateContext: bad visual\n");
331 * Find the GLX visual associated with an XVisualInfo.
334 find_glx_visual( Display
*dpy
, XVisualInfo
*vinfo
)
338 /* First try to match pointers */
339 for (i
=0;i
<NumVisuals
;i
++) {
340 if (VisualTable
[i
]->display
==dpy
&& VisualTable
[i
]->vishandle
==vinfo
) {
341 return VisualTable
[i
];
344 /* try to match visual id */
345 for (i
=0;i
<NumVisuals
;i
++) {
346 if (VisualTable
[i
]->display
==dpy
347 && VisualTable
[i
]->visinfo
->visualid
== vinfo
->visualid
) {
348 return VisualTable
[i
];
357 * Return the transparent pixel value for a GLX visual.
358 * Input: glxvis - the glx_visual
359 * Return: a pixel value or -1 if no transparent pixel
361 static int transparent_pixel( XMesaVisual glxvis
)
363 Display
*dpy
= glxvis
->display
;
364 XVisualInfo
*vinfo
= glxvis
->visinfo
;
365 Atom overlayVisualsAtom
;
366 OverlayInfo
*overlay_info
= NULL
;
367 int numOverlaysPerScreen
;
371 unsigned long sizeData
, bytesLeft
;
375 * The SERVER_OVERLAY_VISUALS property on the root window contains
376 * a list of overlay visuals. Get that list now.
378 overlayVisualsAtom
= XInternAtom(dpy
,"SERVER_OVERLAY_VISUALS", True
);
379 if (overlayVisualsAtom
== None
) {
383 status
= XGetWindowProperty(dpy
, RootWindow( dpy
, vinfo
->screen
),
384 overlayVisualsAtom
, 0L, (long) 10000, False
,
385 overlayVisualsAtom
, &actualType
, &actualFormat
,
386 &sizeData
, &bytesLeft
,
387 (unsigned char **) &overlay_info
);
389 if (status
!= Success
|| actualType
!= overlayVisualsAtom
||
390 actualFormat
!= 32 || sizeData
< 4) {
391 /* something went wrong */
392 XFree((void *) overlay_info
);
396 /* search the overlay visual list for the visual ID of interest */
397 numOverlaysPerScreen
= (int) (sizeData
/ 4);
398 for (i
=0;i
<numOverlaysPerScreen
;i
++) {
400 ov
= overlay_info
+ i
;
401 if (ov
->overlay_visual
==vinfo
->visualid
) {
403 if (ov
->transparent_type
==0) {
404 /* type 0 indicates no transparency */
405 XFree((void *) overlay_info
);
409 /* ov->value is the transparent pixel */
410 XFree((void *) overlay_info
);
416 /* The visual ID was not found in the overlay list. */
417 XFree((void *) overlay_info
);
424 * Return number of bits set in n.
426 static int bitcount( unsigned long n
)
429 for (bits
=0; n
>0; n
=n
>>1) {
439 * Try to get an X visual which matches the given arguments.
441 static XVisualInfo
*get_visual( Display
*dpy
, int scr
,
442 unsigned int depth
, int xclass
)
444 XVisualInfo temp
, *vis
;
447 unsigned int default_depth
;
450 mask
= VisualScreenMask
| VisualDepthMask
| VisualClassMask
;
455 default_depth
= DefaultDepth(dpy
,scr
);
456 default_class
= DefaultVisual(dpy
,scr
)->CLASS
;
458 if (depth
==default_depth
&& xclass
==default_class
) {
459 /* try to get root window's visual */
460 temp
.visualid
= DefaultVisual(dpy
,scr
)->visualid
;
461 mask
|= VisualIDMask
;
464 vis
= XGetVisualInfo( dpy
, mask
, &temp
, &n
);
466 /* In case bits/pixel > 24, make sure color channels are still <=8 bits.
467 * An SGI Infinite Reality system, for example, can have 30bpp pixels:
468 * 10 bits per color channel. Mesa's limited to a max of 8 bits/channel.
470 if (vis
&& depth
> 24 && (xclass
==TrueColor
|| xclass
==DirectColor
)) {
471 if (bitcount(vis
->red_mask
) <= 8
472 && bitcount(vis
->green_mask
) <= 8
473 && bitcount(vis
->blue_mask
) <= 8) {
488 * Retrieve the value of the given environment variable and find
489 * the X visual which matches it.
490 * Input: dpy - the display
491 * screen - the screen number
492 * varname - the name of the environment variable
493 * Return: an XVisualInfo pointer to NULL if error.
495 static XVisualInfo
*get_env_visual(Display
*dpy
, int scr
, const char *varname
)
497 char value
[100], type
[100];
498 int depth
, xclass
= -1;
501 if (!getenv( varname
)) {
505 strncpy( value
, getenv(varname
), 100 );
508 sscanf( value
, "%s %d", type
, &depth
);
510 if (strcmp(type
,"TrueColor")==0) xclass
= TrueColor
;
511 else if (strcmp(type
,"DirectColor")==0) xclass
= DirectColor
;
512 else if (strcmp(type
,"PseudoColor")==0) xclass
= PseudoColor
;
513 else if (strcmp(type
,"StaticColor")==0) xclass
= StaticColor
;
514 else if (strcmp(type
,"GrayScale")==0) xclass
= GrayScale
;
515 else if (strcmp(type
,"StaticGray")==0) xclass
= StaticGray
;
517 if (xclass
>-1 && depth
>0) {
518 vis
= get_visual( dpy
, scr
, depth
, xclass
);
524 fprintf( stderr
, "Mesa: GLX unable to find visual class=%s, depth=%d.\n",
532 * Select an X visual which satisfies the RGBA/CI flag and minimum depth.
533 * Input: dpy, screen - X display and screen number
534 * rgba - GL_TRUE = RGBA mode, GL_FALSE = CI mode
535 * min_depth - minimum visual depth
536 * preferred_class - preferred GLX visual class or DONT_CARE
537 * Return: pointer to an XVisualInfo or NULL.
539 static XVisualInfo
*choose_x_visual( Display
*dpy
, int screen
,
540 GLboolean rgba
, int min_depth
,
541 int preferred_class
)
544 int xclass
, visclass
;
548 Atom hp_cr_maps
= XInternAtom(dpy
, "_HP_RGB_SMOOTH_MAP_LIST", True
);
549 /* First see if the MESA_RGB_VISUAL env var is defined */
550 vis
= get_env_visual( dpy
, screen
, "MESA_RGB_VISUAL" );
554 /* Otherwise, search for a suitable visual */
555 if (preferred_class
==DONT_CARE
) {
556 for (xclass
=0;xclass
<6;xclass
++) {
558 case 0: visclass
= TrueColor
; break;
559 case 1: visclass
= DirectColor
; break;
560 case 2: visclass
= PseudoColor
; break;
561 case 3: visclass
= StaticColor
; break;
562 case 4: visclass
= GrayScale
; break;
563 case 5: visclass
= StaticGray
; break;
566 /* start with shallowest */
567 for (depth
=0;depth
<=32;depth
++) {
568 if (visclass
==TrueColor
&& depth
==8 && !hp_cr_maps
) {
569 /* Special case: try to get 8-bit PseudoColor before */
570 /* 8-bit TrueColor */
571 vis
= get_visual( dpy
, screen
, 8, PseudoColor
);
576 vis
= get_visual( dpy
, screen
, depth
, visclass
);
583 /* start with deepest */
584 for (depth
=32;depth
>=min_depth
;depth
--) {
585 if (visclass
==TrueColor
&& depth
==8 && !hp_cr_maps
) {
586 /* Special case: try to get 8-bit PseudoColor before */
587 /* 8-bit TrueColor */
588 vis
= get_visual( dpy
, screen
, 8, PseudoColor
);
593 vis
= get_visual( dpy
, screen
, depth
, visclass
);
602 /* search for a specific visual class */
603 switch (preferred_class
) {
604 case GLX_TRUE_COLOR_EXT
: visclass
= TrueColor
; break;
605 case GLX_DIRECT_COLOR_EXT
: visclass
= DirectColor
; break;
606 case GLX_PSEUDO_COLOR_EXT
: visclass
= PseudoColor
; break;
607 case GLX_STATIC_COLOR_EXT
: visclass
= StaticColor
; break;
608 case GLX_GRAY_SCALE_EXT
: visclass
= GrayScale
; break;
609 case GLX_STATIC_GRAY_EXT
: visclass
= StaticGray
; break;
610 default: return NULL
;
613 /* start with shallowest */
614 for (depth
=0;depth
<=32;depth
++) {
615 vis
= get_visual( dpy
, screen
, depth
, visclass
);
622 /* start with deepest */
623 for (depth
=32;depth
>=min_depth
;depth
--) {
624 vis
= get_visual( dpy
, screen
, depth
, visclass
);
633 /* First see if the MESA_CI_VISUAL env var is defined */
634 vis
= get_env_visual( dpy
, screen
, "MESA_CI_VISUAL" );
638 /* Otherwise, search for a suitable visual, starting with shallowest */
639 if (preferred_class
==DONT_CARE
) {
640 for (xclass
=0;xclass
<4;xclass
++) {
642 case 0: visclass
= PseudoColor
; break;
643 case 1: visclass
= StaticColor
; break;
644 case 2: visclass
= GrayScale
; break;
645 case 3: visclass
= StaticGray
; break;
647 /* try 8-bit up through 16-bit */
648 for (depth
=8;depth
<=16;depth
++) {
649 vis
= get_visual( dpy
, screen
, depth
, visclass
);
654 /* try min_depth up to 8-bit */
655 for (depth
=min_depth
;depth
<8;depth
++) {
656 vis
= get_visual( dpy
, screen
, depth
, visclass
);
664 /* search for a specific visual class */
665 switch (preferred_class
) {
666 case GLX_TRUE_COLOR_EXT
: visclass
= TrueColor
; break;
667 case GLX_DIRECT_COLOR_EXT
: visclass
= DirectColor
; break;
668 case GLX_PSEUDO_COLOR_EXT
: visclass
= PseudoColor
; break;
669 case GLX_STATIC_COLOR_EXT
: visclass
= StaticColor
; break;
670 case GLX_GRAY_SCALE_EXT
: visclass
= GrayScale
; break;
671 case GLX_STATIC_GRAY_EXT
: visclass
= StaticGray
; break;
672 default: return NULL
;
674 /* try 8-bit up through 16-bit */
675 for (depth
=8;depth
<=16;depth
++) {
676 vis
= get_visual( dpy
, screen
, depth
, visclass
);
681 /* try min_depth up to 8-bit */
682 for (depth
=min_depth
;depth
<8;depth
++) {
683 vis
= get_visual( dpy
, screen
, depth
, visclass
);
691 /* didn't find a visual */
698 * Find the deepest X over/underlay visual of at least min_depth.
699 * Input: dpy, screen - X display and screen number
700 * level - the over/underlay level
701 * trans_type - transparent pixel type: GLX_NONE_EXT,
702 * GLX_TRANSPARENT_RGB_EXT, GLX_TRANSPARENT_INDEX_EXT,
704 * trans_value - transparent pixel value or DONT_CARE
705 * min_depth - minimum visual depth
706 * preferred_class - preferred GLX visual class or DONT_CARE
707 * Return: pointer to an XVisualInfo or NULL.
709 static XVisualInfo
*choose_x_overlay_visual( Display
*dpy
, int scr
,
710 int level
, int trans_type
,
713 int preferred_class
)
715 Atom overlayVisualsAtom
;
716 OverlayInfo
*overlay_info
;
717 int numOverlaysPerScreen
;
721 unsigned long sizeData
, bytesLeft
;
723 XVisualInfo
*deepvis
;
726 /*DEBUG int tt, tv; */
728 switch (preferred_class
) {
729 case GLX_TRUE_COLOR_EXT
: preferred_class
= TrueColor
; break;
730 case GLX_DIRECT_COLOR_EXT
: preferred_class
= DirectColor
; break;
731 case GLX_PSEUDO_COLOR_EXT
: preferred_class
= PseudoColor
; break;
732 case GLX_STATIC_COLOR_EXT
: preferred_class
= StaticColor
; break;
733 case GLX_GRAY_SCALE_EXT
: preferred_class
= GrayScale
; break;
734 case GLX_STATIC_GRAY_EXT
: preferred_class
= StaticGray
; break;
735 default: preferred_class
= DONT_CARE
;
739 * The SERVER_OVERLAY_VISUALS property on the root window contains
740 * a list of overlay visuals. Get that list now.
742 overlayVisualsAtom
= XInternAtom(dpy
,"SERVER_OVERLAY_VISUALS", True
);
743 if (overlayVisualsAtom
== (Atom
) None
) {
747 status
= XGetWindowProperty(dpy
, RootWindow( dpy
, scr
),
748 overlayVisualsAtom
, 0L, (long) 10000, False
,
749 overlayVisualsAtom
, &actualType
, &actualFormat
,
750 &sizeData
, &bytesLeft
,
751 (unsigned char **) &overlay_info
);
753 if (status
!= Success
|| actualType
!= overlayVisualsAtom
||
754 actualFormat
!= 32 || sizeData
< 4) {
755 /* something went wrong */
759 /* Search for the deepest overlay which satisifies all criteria. */
763 numOverlaysPerScreen
= (int) (sizeData
/ 4);
764 for (i
=0;i
<numOverlaysPerScreen
;i
++) {
765 XVisualInfo
*vislist
, vistemplate
;
768 ov
= overlay_info
+ i
;
770 if (ov
->layer
!=level
) {
771 /* failed overlay level criteria */
774 if (!(trans_type
==DONT_CARE
775 || (trans_type
==GLX_TRANSPARENT_INDEX_EXT
776 && ov
->transparent_type
>0)
777 || (trans_type
==GLX_NONE_EXT
&& ov
->transparent_type
==0))) {
778 /* failed transparent pixel type criteria */
781 if (trans_value
!=DONT_CARE
&& trans_value
!=ov
->value
) {
782 /* failed transparent pixel value criteria */
786 /* get XVisualInfo and check the depth */
787 vistemplate
.visualid
= ov
->overlay_visual
;
788 vistemplate
.screen
= scr
;
789 vislist
= XGetVisualInfo( dpy
, VisualIDMask
| VisualScreenMask
,
790 &vistemplate
, &count
);
793 /* something went wrong */
796 if (preferred_class
!=DONT_CARE
&& preferred_class
!=vislist
->CLASS
) {
797 /* wrong visual class */
801 if (deepvis
==NULL
|| vislist
->depth
> deepest
) {
802 /* YES! found a satisfactory visual */
806 deepest
= vislist
->depth
;
808 /* DEBUG tt = ov->transparent_type;*/
809 /* DEBUG tv = ov->value; */
815 printf("chose 0x%x: layer=%d depth=%d trans_type=%d trans_value=%d\n",
816 deepvis->visualid, level, deepvis->depth, tt, tv );
824 XVisualInfo
*Fake_glXChooseVisual( Display
*dpy
, int screen
, int *list
)
829 int min_red
=0, min_green
=0, min_blue
=0;
830 GLboolean rgb_flag
= GL_FALSE
;
831 GLboolean alpha_flag
= GL_FALSE
;
832 GLboolean double_flag
= GL_FALSE
;
833 GLboolean stereo_flag
= GL_FALSE
;
834 GLint depth_size
= 0;
835 GLint stencil_size
= 0;
836 GLint accum_size
= 0;
838 int visual_type
= DONT_CARE
;
839 int trans_type
= DONT_CARE
;
840 int trans_value
= DONT_CARE
;
846 switch (*parselist
) {
851 case GLX_BUFFER_SIZE
:
853 min_ci
= *parselist
++;
857 level
= *parselist
++;
863 case GLX_DOUBLEBUFFER
:
864 double_flag
= GL_TRUE
;
868 stereo_flag
= GL_TRUE
;
870 case GLX_AUX_BUFFERS
:
877 min_red
= *parselist
++;
881 min_green
= *parselist
++;
885 min_blue
= *parselist
++;
890 GLint size
= *parselist
++;
891 alpha_flag
= size
>0 ? 1 : 0;
896 depth_size
= *parselist
++;
898 case GLX_STENCIL_SIZE
:
900 stencil_size
= *parselist
++;
902 case GLX_ACCUM_RED_SIZE
:
903 case GLX_ACCUM_GREEN_SIZE
:
904 case GLX_ACCUM_BLUE_SIZE
:
905 case GLX_ACCUM_ALPHA_SIZE
:
908 GLint size
= *parselist
++;
909 accum_size
= MAX2( accum_size
, size
);
914 * GLX_EXT_visual_info extension
916 case GLX_X_VISUAL_TYPE_EXT
:
918 visual_type
= *parselist
++;
920 case GLX_TRANSPARENT_TYPE_EXT
:
922 trans_type
= *parselist
++;
924 case GLX_TRANSPARENT_INDEX_VALUE_EXT
:
926 trans_value
= *parselist
++;
928 case GLX_TRANSPARENT_RED_VALUE_EXT
:
929 case GLX_TRANSPARENT_GREEN_VALUE_EXT
:
930 case GLX_TRANSPARENT_BLUE_VALUE_EXT
:
931 case GLX_TRANSPARENT_ALPHA_VALUE_EXT
:
940 /* undefined attribute */
946 * Since we're only simulating the GLX extension this function will never
947 * find any real GL visuals. Instead, all we can do is try to find an RGB
948 * or CI visual of appropriate depth. Other requested attributes such as
949 * double buffering, depth buffer, etc. will be associated with the X
950 * visual and stored in the VisualTable[].
953 /* normal color planes */
955 /* Get an RGB visual */
956 int min_rgb
= min_red
+ min_green
+ min_blue
;
957 if (min_rgb
>1 && min_rgb
<8) {
958 /* a special case to be sure we can get a monochrome visual */
961 vis
= choose_x_visual( dpy
, screen
, rgb_flag
, min_rgb
, visual_type
);
964 /* Get a color index visual */
965 vis
= choose_x_visual( dpy
, screen
, rgb_flag
, min_ci
, visual_type
);
970 /* over/underlay planes */
971 vis
= choose_x_overlay_visual( dpy
, screen
, level
, trans_type
,
972 trans_value
, min_ci
, visual_type
);
976 if (!save_glx_visual( dpy
, vis
, rgb_flag
, alpha_flag
, double_flag
,
978 depth_size
, stencil_size
, accum_size
, level
))
988 GLXContext
Fake_glXCreateContext( Display
*dpy
, XVisualInfo
*visinfo
,
989 GLXContext share_list
, Bool direct
)
994 /* deallocate unused windows/buffers */
995 XMesaGarbageCollect();
997 glxvis
= find_glx_visual( dpy
, visinfo
);
999 /* This visual wasn't found with glXChooseVisual() */
1000 glxvis
= create_glx_visual( dpy
, visinfo
);
1002 /* unusable visual */
1007 xmctx
= XMesaCreateContext( glxvis
, (XMesaContext
) share_list
);
1009 /* set the direct/indirect flag */
1010 xmctx
->direct
= direct
;
1012 return (GLXContext
) xmctx
;
1016 static GLXDrawable MakeCurrent_PrevDrawable
= 0;
1017 static GLXContext MakeCurrent_PrevContext
= 0;
1018 static XMesaBuffer MakeCurrent_PrevBuffer
= 0;
1020 Bool
Fake_glXMakeCurrent( Display
*dpy
, GLXDrawable drawable
, GLXContext ctx
)
1022 if (ctx
&& drawable
) {
1025 if (drawable
==MakeCurrent_PrevDrawable
&& ctx
==MakeCurrent_PrevContext
) {
1026 buffer
= MakeCurrent_PrevBuffer
;
1029 buffer
= XMesaFindBuffer( dpy
, drawable
);
1032 /* drawable must be a new window! */
1033 buffer
= XMesaCreateWindowBuffer2( ctx
->xm_visual
, drawable
, ctx
);
1035 /* Out of memory, or context/drawable depth mismatch */
1039 MakeCurrent_PrevContext
= ctx
;
1040 MakeCurrent_PrevDrawable
= drawable
;
1041 MakeCurrent_PrevBuffer
= buffer
;
1043 /* Now make current! */
1044 return (Bool
) XMesaMakeCurrent( (XMesaContext
) ctx
, buffer
);
1046 else if (!ctx
&& !drawable
) {
1047 /* release current context w/out assigning new one. */
1048 XMesaMakeCurrent( NULL
, NULL
);
1049 MakeCurrent_PrevContext
= 0;
1050 MakeCurrent_PrevDrawable
= 0;
1051 MakeCurrent_PrevBuffer
= 0;
1055 /* ctx XOR drawable is NULL, this is an error */
1062 GLXPixmap
Fake_glXCreateGLXPixmap( Display
*dpy
, XVisualInfo
*visinfo
,
1068 v
= find_glx_visual( dpy
, visinfo
);
1070 v
= create_glx_visual( dpy
, visinfo
);
1072 /* unusable visual */
1077 b
= XMesaCreatePixmapBuffer( v
, pixmap
, 0 );
1081 return b
->frontbuffer
;
1085 #ifdef GLX_MESA_pixmap_colormap
1087 GLXPixmap
Fake_glXCreateGLXPixmapMESA( Display
*dpy
, XVisualInfo
*visinfo
,
1088 Pixmap pixmap
, Colormap cmap
)
1093 v
= find_glx_visual( dpy
, visinfo
);
1095 v
= create_glx_visual( dpy
, visinfo
);
1097 /* unusable visual */
1102 b
= XMesaCreatePixmapBuffer( v
, pixmap
, cmap
);
1106 return b
->frontbuffer
;
1112 void Fake_glXDestroyGLXPixmap( Display
*dpy
, GLXPixmap pixmap
)
1114 XMesaBuffer b
= XMesaFindBuffer(dpy
, pixmap
);
1116 XMesaDestroyBuffer(b
);
1118 else if (getenv("MESA_DEBUG")) {
1119 fprintf( stderr
, "Mesa: glXDestroyGLXPixmap: invalid pixmap\n");
1124 void Fake_glXCopyContext( Display
*dpy
, GLXContext src
, GLXContext dst
,
1127 XMesaContext xm_src
= (XMesaContext
) src
;
1128 XMesaContext xm_dst
= (XMesaContext
) dst
;
1130 gl_copy_context( xm_src
->gl_ctx
, xm_dst
->gl_ctx
, mask
);
1135 Bool
Fake_glXQueryExtension( Display
*dpy
, int *errorb
, int *event
)
1137 /* Mesa's GLX isn't really an X extension but we try to act like one. */
1145 void _kw_ungrab_all( Display
*dpy
)
1147 XUngrabPointer( dpy
, CurrentTime
);
1148 XUngrabKeyboard( dpy
, CurrentTime
);
1152 void Fake_glXDestroyContext( Display
*dpy
, GLXContext ctx
)
1155 MakeCurrent_PrevContext
= 0;
1156 MakeCurrent_PrevDrawable
= 0;
1157 MakeCurrent_PrevBuffer
= 0;
1158 XMesaDestroyContext( (XMesaContext
) ctx
);
1159 XMesaGarbageCollect();
1164 Bool
Fake_glXIsDirect( Display
*dpy
, GLXContext ctx
)
1167 return ((XMesaContext
) ctx
)->direct
;
1172 void Fake_glXSwapBuffers( Display
*dpy
, GLXDrawable drawable
)
1174 XMesaBuffer buffer
= XMesaFindBuffer( dpy
, drawable
);
1177 XMesaSwapBuffers(buffer
);
1179 else if (getenv("MESA_DEBUG")) {
1180 fprintf(stderr
, "Mesa Warning: glXSwapBuffers: invalid drawable\n");
1185 void Fake_glXCopySubBufferMESA( Display
*dpy
, GLXDrawable drawable
,
1186 int x
, int y
, int width
, int height
)
1188 XMesaBuffer buffer
= XMesaFindBuffer( dpy
, drawable
);
1190 XMesaCopySubBuffer(buffer
, x
, y
, width
, height
);
1192 else if (getenv("MESA_DEBUG")) {
1193 fprintf(stderr
, "Mesa Warning: glXCopySubBufferMESA: invalid drawable\n");
1199 Bool
Fake_glXQueryVersion( Display
*dpy
, int *maj
, int *min
)
1202 /* Return GLX version, not Mesa version */
1211 * Query the GLX attributes of the given XVisualInfo.
1213 int Fake_glXGetConfig( Display
*dpy
, XVisualInfo
*visinfo
,
1214 int attrib
, int *value
)
1218 glxvis
= find_glx_visual( dpy
, visinfo
);
1220 /* this visual wasn't obtained with glXChooseVisual */
1221 glxvis
= create_glx_visual( dpy
, visinfo
);
1223 /* this visual can't be used for GL rendering */
1224 if (attrib
==GLX_USE_GL
) {
1225 *value
= (int) False
;
1229 /*fprintf( stderr, "Mesa: Error in glXGetConfig: bad visual\n");*/
1230 return GLX_BAD_VISUAL
;
1237 *value
= (int) True
;
1239 case GLX_BUFFER_SIZE
:
1240 *value
= visinfo
->depth
;
1243 *value
= glxvis
->level
;
1246 if (glxvis
->gl_visual
->RGBAflag
) {
1253 case GLX_DOUBLEBUFFER
:
1254 *value
= (int) glxvis
->gl_visual
->DBflag
;
1257 *value
= (int) glxvis
->gl_visual
->StereoFlag
;
1259 case GLX_AUX_BUFFERS
:
1260 *value
= (int) False
;
1263 *value
= glxvis
->gl_visual
->RedBits
;
1265 case GLX_GREEN_SIZE
:
1266 *value
= glxvis
->gl_visual
->GreenBits
;
1269 *value
= glxvis
->gl_visual
->BlueBits
;
1271 case GLX_ALPHA_SIZE
:
1272 *value
= glxvis
->gl_visual
->AlphaBits
;
1274 case GLX_DEPTH_SIZE
:
1275 *value
= glxvis
->gl_visual
->DepthBits
;
1277 case GLX_STENCIL_SIZE
:
1278 *value
= glxvis
->gl_visual
->StencilBits
;
1280 case GLX_ACCUM_RED_SIZE
:
1281 case GLX_ACCUM_GREEN_SIZE
:
1282 case GLX_ACCUM_BLUE_SIZE
:
1283 *value
= glxvis
->gl_visual
->AccumBits
;
1285 case GLX_ACCUM_ALPHA_SIZE
:
1286 if (glxvis
->gl_visual
->AlphaBits
> 0)
1287 *value
= glxvis
->gl_visual
->AccumBits
;
1293 * GLX_EXT_visual_info extension
1295 case GLX_X_VISUAL_TYPE_EXT
:
1296 switch (glxvis
->visinfo
->CLASS
) {
1297 case StaticGray
: *value
= GLX_STATIC_GRAY_EXT
; return 0;
1298 case GrayScale
: *value
= GLX_GRAY_SCALE_EXT
; return 0;
1299 case StaticColor
: *value
= GLX_STATIC_GRAY_EXT
; return 0;
1300 case PseudoColor
: *value
= GLX_PSEUDO_COLOR_EXT
; return 0;
1301 case TrueColor
: *value
= GLX_TRUE_COLOR_EXT
; return 0;
1302 case DirectColor
: *value
= GLX_DIRECT_COLOR_EXT
; return 0;
1305 case GLX_TRANSPARENT_TYPE_EXT
:
1306 if (glxvis
->level
==0) {
1308 *value
= GLX_NONE_EXT
;
1310 else if (glxvis
->level
>0) {
1312 if (glxvis
->gl_visual
->RGBAflag
) {
1313 *value
= GLX_TRANSPARENT_RGB_EXT
;
1316 *value
= GLX_TRANSPARENT_INDEX_EXT
;
1319 else if (glxvis
->level
<0) {
1321 *value
= GLX_NONE_EXT
;
1324 case GLX_TRANSPARENT_INDEX_VALUE_EXT
:
1326 int pixel
= transparent_pixel( glxvis
);
1330 /* else undefined */
1333 case GLX_TRANSPARENT_RED_VALUE_EXT
:
1336 case GLX_TRANSPARENT_GREEN_VALUE_EXT
:
1339 case GLX_TRANSPARENT_BLUE_VALUE_EXT
:
1342 case GLX_TRANSPARENT_ALPHA_VALUE_EXT
:
1350 return GLX_BAD_ATTRIBUTE
;
1356 GLXContext
Fake_glXGetCurrentContext( void )
1358 return (GLXContext
) XMesaGetCurrentContext();
1363 GLXDrawable
Fake_glXGetCurrentDrawable( void )
1365 XMesaBuffer b
= XMesaGetCurrentBuffer();
1367 return b
->frontbuffer
;
1375 void Fake_glXWaitGL( void )
1377 XMesaContext xmesa
= XMesaGetCurrentContext();
1378 XMesaFlush( xmesa
);
1383 void Fake_glXWaitX( void )
1385 XMesaContext xmesa
= XMesaGetCurrentContext();
1386 XMesaFlush( xmesa
);
1391 #define EXTENSIONS "GLX_MESA_pixmap_colormap GLX_EXT_visual_info GLX_MESA_release_buffers GLX_MESA_copy_sub_buffer GLX_SGI_video_sync"
1394 /* GLX 1.1 and later */
1395 const char *Fake_glXQueryExtensionsString( Display
*dpy
, int screen
)
1397 static char *extensions
= EXTENSIONS
;
1405 /* GLX 1.1 and later */
1406 const char *Fake_glXQueryServerString( Display
*dpy
, int screen
, int name
)
1408 static char *extensions
= EXTENSIONS
;
1409 static char *vendor
= "Brian Paul";
1410 static char *version
= "1.1 Mesa 3.0";
1416 case GLX_EXTENSIONS
:
1429 /* GLX 1.1 and later */
1430 const char *Fake_glXGetClientString( Display
*dpy
, int name
)
1432 static char *extensions
= EXTENSIONS
;
1433 static char *vendor
= "Brian Paul";
1434 static char *version
= "1.1 Mesa 3.0";
1439 case GLX_EXTENSIONS
:
1453 * Release the depth, stencil, accum buffers attached to a GLXDrawable
1454 * (a window or pixmap) prior to destroying the GLXDrawable.
1456 Bool
Fake_glXReleaseBuffersMESA( Display
*dpy
, GLXDrawable d
)
1458 XMesaBuffer b
= XMesaFindBuffer(dpy
, d
);
1460 XMesaDestroyBuffer(b
);
1467 /* Silence compiler warnings */
1468 void Fake_glXDummyFunc( void )
1471 (void) DitherValues
;
1477 GLfunction
Fake_glXGetProcAddress( const GLubyte
*procName
)
1483 static struct proc procTable
[] = {
1484 { "glXGetProcAddressEXT", glXGetProcAddressEXT
}, /* myself! */
1485 { "glXReleaseBuffersMESA", glXReleaseBuffersMESA
},
1486 { "glXReleaseBuffersMESA", glXReleaseBuffersMESA
},
1487 { "glXCopySubBufferMESA", glXCopySubBufferMESA
},
1488 /* NOTE: GLX_SGI_video_sync not implemented in Mesa */
1489 { NULL
, NULL
} /* end of list token */
1493 /* First, look for core library functions */
1494 for (i
= 0; procTable
[i
].address
; i
++) {
1495 if (strcmp((const char *) procName
, procTable
[i
].name
) == 0)
1496 return (GLfunction
) procTable
[i
].address
;