diff options
Diffstat (limited to 'src/mesa/drivers/x11/fakeglx.c')
-rw-r--r-- | src/mesa/drivers/x11/fakeglx.c | 1516 |
1 files changed, 1516 insertions, 0 deletions
diff --git a/src/mesa/drivers/x11/fakeglx.c b/src/mesa/drivers/x11/fakeglx.c new file mode 100644 index 00000000000..12567fe19c5 --- /dev/null +++ b/src/mesa/drivers/x11/fakeglx.c @@ -0,0 +1,1516 @@ +/* $Id: fakeglx.c,v 1.1 1999/08/19 00:55:42 jtg Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.1 + * + * Copyright (C) 1999 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + + + +/* + * A pseudo-GLX implementation to allow OpenGL/GLX programs to work with Mesa. + * The Fake_glX*() functions implemented here are called from glxapi.c + * + * Thanks to the contributors: + * + * Initial version: Philip Brown ([email protected]) + * Better glXGetConfig() support: Armin Liebchen ([email protected]) + * Further visual-handling refinements: Wolfram Gloger + * ([email protected]). + * + * Notes: + * Don't be fooled, stereo isn't supported yet. + */ + + + +#ifdef HAVE_CONFIG_H +#include "conf.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include "GL/gl.h" +#include "GL/xmesa.h" +#include "context.h" +#include "config.h" +#include "fakeglx.h" +#include "macros.h" +#include "types.h" +#include "xmesaP.h" + + + +#define DONT_CARE -1 + + + +#define MAX_VISUALS 100 +static XMesaVisual VisualTable[MAX_VISUALS]; +static int NumVisuals = 0; + + + +/* + * This struct and some code fragments borrowed + * from Mark Kilgard's GLUT library. + */ +typedef struct _OverlayInfo { + /* Avoid 64-bit portability problems by being careful to use + longs due to the way XGetWindowProperty is specified. Note + that these parameters are passed as CARD32s over X + protocol. */ + unsigned long overlay_visual; + long transparent_type; + long value; + long layer; +} OverlayInfo; + + + +/* Macro to handle c_class vs class field name in XVisualInfo struct */ +#if defined(__cplusplus) || defined(c_plusplus) +#define CLASS c_class +#else +#define CLASS class +#endif + + + + +/* + * Test if the given XVisualInfo is usable for Mesa rendering. + */ +static GLboolean is_usable_visual( XVisualInfo *vinfo ) +{ + switch (vinfo->CLASS) { + case StaticGray: + case GrayScale: + /* Any StaticGray/GrayScale visual works in RGB or CI mode */ + return GL_TRUE; + case StaticColor: + case PseudoColor: + /* Any StaticColor/PseudoColor visual of at least 4 bits */ + if (vinfo->depth>=4) { + return GL_TRUE; + } + else { + return GL_FALSE; + } + case TrueColor: + case DirectColor: + /* Any depth of TrueColor or DirectColor works in RGB mode */ + return GL_TRUE; + default: + /* This should never happen */ + return GL_FALSE; + } +} + + + +/* + * Return the level (overlay, normal, underlay) of a given XVisualInfo. + * Input: dpy - the X display + * vinfo - the XVisualInfo to test + * Return: level of the visual: + * 0 = normal planes + * >0 = overlay planes + * <0 = underlay planes + */ +static int level_of_visual( Display *dpy, XVisualInfo *vinfo ) +{ + Atom overlayVisualsAtom; + OverlayInfo *overlay_info = NULL; + int numOverlaysPerScreen; + Status status; + Atom actualType; + int actualFormat; + unsigned long sizeData, bytesLeft; + int i; + + /* + * The SERVER_OVERLAY_VISUALS property on the root window contains + * a list of overlay visuals. Get that list now. + */ + overlayVisualsAtom = XInternAtom(dpy,"SERVER_OVERLAY_VISUALS", True); + if (overlayVisualsAtom == None) { + return 0; + } + + status = XGetWindowProperty(dpy, RootWindow( dpy, vinfo->screen ), + overlayVisualsAtom, 0L, (long) 10000, False, + overlayVisualsAtom, &actualType, &actualFormat, + &sizeData, &bytesLeft, + (unsigned char **) &overlay_info ); + + if (status != Success || actualType != overlayVisualsAtom || + actualFormat != 32 || sizeData < 4) { + /* something went wrong */ + XFree((void *) overlay_info); + return 0; + } + + /* search the overlay visual list for the visual ID of interest */ + numOverlaysPerScreen = (int) (sizeData / 4); + for (i=0;i<numOverlaysPerScreen;i++) { + OverlayInfo *ov; + ov = overlay_info + i; + if (ov->overlay_visual==vinfo->visualid) { + /* found the visual */ + if (/*ov->transparent_type==1 &&*/ ov->layer!=0) { + int level = ov->layer; + XFree((void *) overlay_info); + return level; + } + else { + XFree((void *) overlay_info); + return 0; + } + } + } + + /* The visual ID was not found in the overlay list. */ + XFree((void *) overlay_info); + return 0; +} + + + + +/* + * Given an XVisualInfo and RGB, Double, and Depth buffer flags, save the + * configuration in our list of GLX visuals. + */ +static XMesaVisual +save_glx_visual( Display *dpy, XVisualInfo *vinfo, + GLboolean rgbFlag, GLboolean alphaFlag, GLboolean dbFlag, + GLboolean stereoFlag, + GLint depth_size, GLint stencil_size, + GLint accum_size, GLint level ) +{ + GLboolean ximageFlag = GL_TRUE; + XMesaVisual xmvis; + GLint i; + GLboolean comparePointers; + + if (dbFlag) { + /* Check if the MESA_BACK_BUFFER env var is set */ + char *backbuffer = getenv("MESA_BACK_BUFFER"); + if (backbuffer) { + if (backbuffer[0]=='p' || backbuffer[0]=='P') { + ximageFlag = GL_FALSE; + } + else if (backbuffer[0]=='x' || backbuffer[0]=='X') { + ximageFlag = GL_TRUE; + } + else { + fprintf(stderr, "Mesa: invalid value for MESA_BACK_BUFFER "); + fprintf(stderr, "environment variable, using an XImage.\n"); + } + } + } + + /* Comparing IDs uses less memory but sometimes fails. */ + /* XXX revisit this after 3.0 is finished. */ + if (getenv("MESA_GLX_VISUAL_HACK")) + comparePointers = GL_TRUE; + else + comparePointers = GL_FALSE; + + /* First check if a matching visual is already in the list */ + for (i=0; i<NumVisuals; i++) { + XMesaVisual v = VisualTable[i]; + if (v->display == dpy + && v->level == level + && v->ximage_flag == ximageFlag + && v->gl_visual->RGBAflag == rgbFlag + && v->gl_visual->DBflag == dbFlag + && v->gl_visual->StereoFlag == stereoFlag + && (v->gl_visual->AlphaBits > 0) == alphaFlag + && (v->gl_visual->DepthBits >= depth_size || depth_size == 0) + && (v->gl_visual->StencilBits >= stencil_size || stencil_size == 0) + && (v->gl_visual->AccumBits >= accum_size || accum_size == 0)) { + /* now either compare XVisualInfo pointers or visual IDs */ + if ((!comparePointers && v->vishandle->visualid == vinfo->visualid) + || (comparePointers && v->vishandle == vinfo)) { + return v; + } + } + } + + /* Create a new visual and add it to the list. */ + + if (NumVisuals>=MAX_VISUALS) { + fprintf( stderr, "GLX Error: maximum number of visuals exceeded\n"); + return NULL; + } + + xmvis = XMesaCreateVisual( dpy, vinfo, rgbFlag, alphaFlag, dbFlag, + stereoFlag, ximageFlag, + depth_size, stencil_size, accum_size, level ); + if (xmvis) { + VisualTable[NumVisuals] = xmvis; + NumVisuals++; + } + return xmvis; +} + + + +/* + * Create a GLX visual from a regular XVisualInfo. + */ +static XMesaVisual +create_glx_visual( Display *dpy, XVisualInfo *visinfo ) +{ + int vislevel; + + vislevel = level_of_visual( dpy, visinfo ); + if (vislevel) { + /* Configure this visual as a CI, single-buffered overlay */ + return save_glx_visual( dpy, visinfo, + GL_FALSE, /* rgb */ + GL_FALSE, /* alpha */ + GL_FALSE, /* double */ + GL_FALSE, /* stereo */ + 0, /* depth bits */ + 0, /* stencil bits */ + 0, /* accum bits */ + vislevel /* level */ + ); + } + else if (is_usable_visual( visinfo )) { + /* Configure this visual as RGB, double-buffered, depth-buffered. */ + /* This is surely wrong for some people's needs but what else */ + /* can be done? They should use glXChooseVisual(). */ + return save_glx_visual( dpy, visinfo, + GL_TRUE, /* rgb */ + GL_FALSE, /* alpha */ + GL_TRUE, /* double */ + GL_FALSE, /* stereo */ + 8*sizeof(GLdepth), + 8*sizeof(GLstencil), + 8*sizeof(GLaccum), + 0 /* level */ + ); + } + else { + fprintf(stderr,"Mesa: error in glXCreateContext: bad visual\n"); + return NULL; + } +} + + + +/* + * Find the GLX visual associated with an XVisualInfo. + */ +static XMesaVisual +find_glx_visual( Display *dpy, XVisualInfo *vinfo ) +{ + int i; + + /* First try to match pointers */ + for (i=0;i<NumVisuals;i++) { + if (VisualTable[i]->display==dpy && VisualTable[i]->vishandle==vinfo) { + return VisualTable[i]; + } + } + /* try to match visual id */ + for (i=0;i<NumVisuals;i++) { + if (VisualTable[i]->display==dpy + && VisualTable[i]->visinfo->visualid == vinfo->visualid) { + return VisualTable[i]; + } + } + return NULL; +} + + + +/* + * Return the transparent pixel value for a GLX visual. + * Input: glxvis - the glx_visual + * Return: a pixel value or -1 if no transparent pixel + */ +static int transparent_pixel( XMesaVisual glxvis ) +{ + Display *dpy = glxvis->display; + XVisualInfo *vinfo = glxvis->visinfo; + Atom overlayVisualsAtom; + OverlayInfo *overlay_info = NULL; + int numOverlaysPerScreen; + Status status; + Atom actualType; + int actualFormat; + unsigned long sizeData, bytesLeft; + int i; + + /* + * The SERVER_OVERLAY_VISUALS property on the root window contains + * a list of overlay visuals. Get that list now. + */ + overlayVisualsAtom = XInternAtom(dpy,"SERVER_OVERLAY_VISUALS", True); + if (overlayVisualsAtom == None) { + return -1; + } + + status = XGetWindowProperty(dpy, RootWindow( dpy, vinfo->screen ), + overlayVisualsAtom, 0L, (long) 10000, False, + overlayVisualsAtom, &actualType, &actualFormat, + &sizeData, &bytesLeft, + (unsigned char **) &overlay_info ); + + if (status != Success || actualType != overlayVisualsAtom || + actualFormat != 32 || sizeData < 4) { + /* something went wrong */ + XFree((void *) overlay_info); + return -1; + } + + /* search the overlay visual list for the visual ID of interest */ + numOverlaysPerScreen = (int) (sizeData / 4); + for (i=0;i<numOverlaysPerScreen;i++) { + OverlayInfo *ov; + ov = overlay_info + i; + if (ov->overlay_visual==vinfo->visualid) { + /* found it! */ + if (ov->transparent_type==0) { + /* type 0 indicates no transparency */ + XFree((void *) overlay_info); + return -1; + } + else { + /* ov->value is the transparent pixel */ + XFree((void *) overlay_info); + return ov->value; + } + } + } + + /* The visual ID was not found in the overlay list. */ + XFree((void *) overlay_info); + return -1; +} + + + +/* + * Return number of bits set in n. + */ +static int bitcount( unsigned long n ) +{ + int bits; + for (bits=0; n>0; n=n>>1) { + if (n&1) { + bits++; + } + } + return bits; +} + + +/* + * Try to get an X visual which matches the given arguments. + */ +static XVisualInfo *get_visual( Display *dpy, int scr, + unsigned int depth, int xclass ) +{ + XVisualInfo temp, *vis; + long mask; + int n; + unsigned int default_depth; + int default_class; + + mask = VisualScreenMask | VisualDepthMask | VisualClassMask; + temp.screen = scr; + temp.depth = depth; + temp.CLASS = xclass; + + default_depth = DefaultDepth(dpy,scr); + default_class = DefaultVisual(dpy,scr)->CLASS; + + if (depth==default_depth && xclass==default_class) { + /* try to get root window's visual */ + temp.visualid = DefaultVisual(dpy,scr)->visualid; + mask |= VisualIDMask; + } + + vis = XGetVisualInfo( dpy, mask, &temp, &n ); + + /* In case bits/pixel > 24, make sure color channels are still <=8 bits. + * An SGI Infinite Reality system, for example, can have 30bpp pixels: + * 10 bits per color channel. Mesa's limited to a max of 8 bits/channel. + */ + if (vis && depth > 24 && (xclass==TrueColor || xclass==DirectColor)) { + if (bitcount(vis->red_mask) <= 8 + && bitcount(vis->green_mask) <= 8 + && bitcount(vis->blue_mask) <= 8) { + return vis; + } + else { + XFree((void *) vis); + return NULL; + } + } + + return vis; +} + + + +/* + * Retrieve the value of the given environment variable and find + * the X visual which matches it. + * Input: dpy - the display + * screen - the screen number + * varname - the name of the environment variable + * Return: an XVisualInfo pointer to NULL if error. + */ +static XVisualInfo *get_env_visual(Display *dpy, int scr, const char *varname) +{ + char value[100], type[100]; + int depth, xclass = -1; + XVisualInfo *vis; + + if (!getenv( varname )) { + return NULL; + } + + strncpy( value, getenv(varname), 100 ); + value[99] = 0; + + sscanf( value, "%s %d", type, &depth ); + + if (strcmp(type,"TrueColor")==0) xclass = TrueColor; + else if (strcmp(type,"DirectColor")==0) xclass = DirectColor; + else if (strcmp(type,"PseudoColor")==0) xclass = PseudoColor; + else if (strcmp(type,"StaticColor")==0) xclass = StaticColor; + else if (strcmp(type,"GrayScale")==0) xclass = GrayScale; + else if (strcmp(type,"StaticGray")==0) xclass = StaticGray; + + if (xclass>-1 && depth>0) { + vis = get_visual( dpy, scr, depth, xclass ); + if (vis) { + return vis; + } + } + + fprintf( stderr, "Mesa: GLX unable to find visual class=%s, depth=%d.\n", + type, depth ); + return NULL; +} + + + +/* + * Select an X visual which satisfies the RGBA/CI flag and minimum depth. + * Input: dpy, screen - X display and screen number + * rgba - GL_TRUE = RGBA mode, GL_FALSE = CI mode + * min_depth - minimum visual depth + * preferred_class - preferred GLX visual class or DONT_CARE + * Return: pointer to an XVisualInfo or NULL. + */ +static XVisualInfo *choose_x_visual( Display *dpy, int screen, + GLboolean rgba, int min_depth, + int preferred_class ) +{ + XVisualInfo *vis; + int xclass, visclass; + int depth; + + if (rgba) { + Atom hp_cr_maps = XInternAtom(dpy, "_HP_RGB_SMOOTH_MAP_LIST", True); + /* First see if the MESA_RGB_VISUAL env var is defined */ + vis = get_env_visual( dpy, screen, "MESA_RGB_VISUAL" ); + if (vis) { + return vis; + } + /* Otherwise, search for a suitable visual */ + if (preferred_class==DONT_CARE) { + for (xclass=0;xclass<6;xclass++) { + switch (xclass) { + case 0: visclass = TrueColor; break; + case 1: visclass = DirectColor; break; + case 2: visclass = PseudoColor; break; + case 3: visclass = StaticColor; break; + case 4: visclass = GrayScale; break; + case 5: visclass = StaticGray; break; + } + if (min_depth==0) { + /* start with shallowest */ + for (depth=0;depth<=32;depth++) { + if (visclass==TrueColor && depth==8 && !hp_cr_maps) { + /* Special case: try to get 8-bit PseudoColor before */ + /* 8-bit TrueColor */ + vis = get_visual( dpy, screen, 8, PseudoColor ); + if (vis) { + return vis; + } + } + vis = get_visual( dpy, screen, depth, visclass ); + if (vis) { + return vis; + } + } + } + else { + /* start with deepest */ + for (depth=32;depth>=min_depth;depth--) { + if (visclass==TrueColor && depth==8 && !hp_cr_maps) { + /* Special case: try to get 8-bit PseudoColor before */ + /* 8-bit TrueColor */ + vis = get_visual( dpy, screen, 8, PseudoColor ); + if (vis) { + return vis; + } + } + vis = get_visual( dpy, screen, depth, visclass ); + if (vis) { + return vis; + } + } + } + } + } + else { + /* search for a specific visual class */ + switch (preferred_class) { + case GLX_TRUE_COLOR_EXT: visclass = TrueColor; break; + case GLX_DIRECT_COLOR_EXT: visclass = DirectColor; break; + case GLX_PSEUDO_COLOR_EXT: visclass = PseudoColor; break; + case GLX_STATIC_COLOR_EXT: visclass = StaticColor; break; + case GLX_GRAY_SCALE_EXT: visclass = GrayScale; break; + case GLX_STATIC_GRAY_EXT: visclass = StaticGray; break; + default: return NULL; + } + if (min_depth==0) { + /* start with shallowest */ + for (depth=0;depth<=32;depth++) { + vis = get_visual( dpy, screen, depth, visclass ); + if (vis) { + return vis; + } + } + } + else { + /* start with deepest */ + for (depth=32;depth>=min_depth;depth--) { + vis = get_visual( dpy, screen, depth, visclass ); + if (vis) { + return vis; + } + } + } + } + } + else { + /* First see if the MESA_CI_VISUAL env var is defined */ + vis = get_env_visual( dpy, screen, "MESA_CI_VISUAL" ); + if (vis) { + return vis; + } + /* Otherwise, search for a suitable visual, starting with shallowest */ + if (preferred_class==DONT_CARE) { + for (xclass=0;xclass<4;xclass++) { + switch (xclass) { + case 0: visclass = PseudoColor; break; + case 1: visclass = StaticColor; break; + case 2: visclass = GrayScale; break; + case 3: visclass = StaticGray; break; + } + /* try 8-bit up through 16-bit */ + for (depth=8;depth<=16;depth++) { + vis = get_visual( dpy, screen, depth, visclass ); + if (vis) { + return vis; + } + } + /* try min_depth up to 8-bit */ + for (depth=min_depth;depth<8;depth++) { + vis = get_visual( dpy, screen, depth, visclass ); + if (vis) { + return vis; + } + } + } + } + else { + /* search for a specific visual class */ + switch (preferred_class) { + case GLX_TRUE_COLOR_EXT: visclass = TrueColor; break; + case GLX_DIRECT_COLOR_EXT: visclass = DirectColor; break; + case GLX_PSEUDO_COLOR_EXT: visclass = PseudoColor; break; + case GLX_STATIC_COLOR_EXT: visclass = StaticColor; break; + case GLX_GRAY_SCALE_EXT: visclass = GrayScale; break; + case GLX_STATIC_GRAY_EXT: visclass = StaticGray; break; + default: return NULL; + } + /* try 8-bit up through 16-bit */ + for (depth=8;depth<=16;depth++) { + vis = get_visual( dpy, screen, depth, visclass ); + if (vis) { + return vis; + } + } + /* try min_depth up to 8-bit */ + for (depth=min_depth;depth<8;depth++) { + vis = get_visual( dpy, screen, depth, visclass ); + if (vis) { + return vis; + } + } + } + } + + /* didn't find a visual */ + return NULL; +} + + + +/* + * Find the deepest X over/underlay visual of at least min_depth. + * Input: dpy, screen - X display and screen number + * level - the over/underlay level + * trans_type - transparent pixel type: GLX_NONE_EXT, + * GLX_TRANSPARENT_RGB_EXT, GLX_TRANSPARENT_INDEX_EXT, + * or DONT_CARE + * trans_value - transparent pixel value or DONT_CARE + * min_depth - minimum visual depth + * preferred_class - preferred GLX visual class or DONT_CARE + * Return: pointer to an XVisualInfo or NULL. + */ +static XVisualInfo *choose_x_overlay_visual( Display *dpy, int scr, + int level, int trans_type, + int trans_value, + int min_depth, + int preferred_class ) +{ + Atom overlayVisualsAtom; + OverlayInfo *overlay_info; + int numOverlaysPerScreen; + Status status; + Atom actualType; + int actualFormat; + unsigned long sizeData, bytesLeft; + int i; + XVisualInfo *deepvis; + int deepest; + + /*DEBUG int tt, tv; */ + + switch (preferred_class) { + case GLX_TRUE_COLOR_EXT: preferred_class = TrueColor; break; + case GLX_DIRECT_COLOR_EXT: preferred_class = DirectColor; break; + case GLX_PSEUDO_COLOR_EXT: preferred_class = PseudoColor; break; + case GLX_STATIC_COLOR_EXT: preferred_class = StaticColor; break; + case GLX_GRAY_SCALE_EXT: preferred_class = GrayScale; break; + case GLX_STATIC_GRAY_EXT: preferred_class = StaticGray; break; + default: preferred_class = DONT_CARE; + } + + /* + * The SERVER_OVERLAY_VISUALS property on the root window contains + * a list of overlay visuals. Get that list now. + */ + overlayVisualsAtom = XInternAtom(dpy,"SERVER_OVERLAY_VISUALS", True); + if (overlayVisualsAtom == (Atom) None) { + return NULL; + } + + status = XGetWindowProperty(dpy, RootWindow( dpy, scr ), + overlayVisualsAtom, 0L, (long) 10000, False, + overlayVisualsAtom, &actualType, &actualFormat, + &sizeData, &bytesLeft, + (unsigned char **) &overlay_info ); + + if (status != Success || actualType != overlayVisualsAtom || + actualFormat != 32 || sizeData < 4) { + /* something went wrong */ + return NULL; + } + + /* Search for the deepest overlay which satisifies all criteria. */ + deepest = min_depth; + deepvis = NULL; + + numOverlaysPerScreen = (int) (sizeData / 4); + for (i=0;i<numOverlaysPerScreen;i++) { + XVisualInfo *vislist, vistemplate; + int count; + OverlayInfo *ov; + ov = overlay_info + i; + + if (ov->layer!=level) { + /* failed overlay level criteria */ + continue; + } + if (!(trans_type==DONT_CARE + || (trans_type==GLX_TRANSPARENT_INDEX_EXT + && ov->transparent_type>0) + || (trans_type==GLX_NONE_EXT && ov->transparent_type==0))) { + /* failed transparent pixel type criteria */ + continue; + } + if (trans_value!=DONT_CARE && trans_value!=ov->value) { + /* failed transparent pixel value criteria */ + continue; + } + + /* get XVisualInfo and check the depth */ + vistemplate.visualid = ov->overlay_visual; + vistemplate.screen = scr; + vislist = XGetVisualInfo( dpy, VisualIDMask | VisualScreenMask, + &vistemplate, &count ); + + if (count!=1) { + /* something went wrong */ + continue; + } + if (preferred_class!=DONT_CARE && preferred_class!=vislist->CLASS) { + /* wrong visual class */ + continue; + } + + if (deepvis==NULL || vislist->depth > deepest) { + /* YES! found a satisfactory visual */ + if (deepvis) { + free( deepvis ); + } + deepest = vislist->depth; + deepvis = vislist; + /* DEBUG tt = ov->transparent_type;*/ + /* DEBUG tv = ov->value; */ + } + } + +/*DEBUG + if (deepvis) { + printf("chose 0x%x: layer=%d depth=%d trans_type=%d trans_value=%d\n", + deepvis->visualid, level, deepvis->depth, tt, tv ); + } +*/ + return deepvis; +} + + + +XVisualInfo *Fake_glXChooseVisual( Display *dpy, int screen, int *list ) +{ + int *parselist; + XVisualInfo *vis; + int min_ci = 0; + int min_red=0, min_green=0, min_blue=0; + GLboolean rgb_flag = GL_FALSE; + GLboolean alpha_flag = GL_FALSE; + GLboolean double_flag = GL_FALSE; + GLboolean stereo_flag = GL_FALSE; + GLint depth_size = 0; + GLint stencil_size = 0; + GLint accum_size = 0; + int level = 0; + int visual_type = DONT_CARE; + int trans_type = DONT_CARE; + int trans_value = DONT_CARE; + + parselist = list; + + while (*parselist) { + + switch (*parselist) { + case GLX_USE_GL: + /* ignore */ + parselist++; + break; + case GLX_BUFFER_SIZE: + parselist++; + min_ci = *parselist++; + break; + case GLX_LEVEL: + parselist++; + level = *parselist++; + break; + case GLX_RGBA: + rgb_flag = GL_TRUE; + parselist++; + break; + case GLX_DOUBLEBUFFER: + double_flag = GL_TRUE; + parselist++; + break; + case GLX_STEREO: + stereo_flag = GL_TRUE; + return NULL; + case GLX_AUX_BUFFERS: + /* ignore */ + parselist++; + parselist++; + break; + case GLX_RED_SIZE: + parselist++; + min_red = *parselist++; + break; + case GLX_GREEN_SIZE: + parselist++; + min_green = *parselist++; + break; + case GLX_BLUE_SIZE: + parselist++; + min_blue = *parselist++; + break; + case GLX_ALPHA_SIZE: + parselist++; + { + GLint size = *parselist++; + alpha_flag = size>0 ? 1 : 0; + } + break; + case GLX_DEPTH_SIZE: + parselist++; + depth_size = *parselist++; + break; + case GLX_STENCIL_SIZE: + parselist++; + stencil_size = *parselist++; + break; + case GLX_ACCUM_RED_SIZE: + case GLX_ACCUM_GREEN_SIZE: + case GLX_ACCUM_BLUE_SIZE: + case GLX_ACCUM_ALPHA_SIZE: + parselist++; + { + GLint size = *parselist++; + accum_size = MAX2( accum_size, size ); + } + break; + + /* + * GLX_EXT_visual_info extension + */ + case GLX_X_VISUAL_TYPE_EXT: + parselist++; + visual_type = *parselist++; + break; + case GLX_TRANSPARENT_TYPE_EXT: + parselist++; + trans_type = *parselist++; + break; + case GLX_TRANSPARENT_INDEX_VALUE_EXT: + parselist++; + trans_value = *parselist++; + break; + case GLX_TRANSPARENT_RED_VALUE_EXT: + case GLX_TRANSPARENT_GREEN_VALUE_EXT: + case GLX_TRANSPARENT_BLUE_VALUE_EXT: + case GLX_TRANSPARENT_ALPHA_VALUE_EXT: + /* ignore */ + parselist++; + parselist++; + break; + + case None: + break; + default: + /* undefined attribute */ + return NULL; + } + } + + /* + * Since we're only simulating the GLX extension this function will never + * find any real GL visuals. Instead, all we can do is try to find an RGB + * or CI visual of appropriate depth. Other requested attributes such as + * double buffering, depth buffer, etc. will be associated with the X + * visual and stored in the VisualTable[]. + */ + if (level==0) { + /* normal color planes */ + if (rgb_flag) { + /* Get an RGB visual */ + int min_rgb = min_red + min_green + min_blue; + if (min_rgb>1 && min_rgb<8) { + /* a special case to be sure we can get a monochrome visual */ + min_rgb = 1; + } + vis = choose_x_visual( dpy, screen, rgb_flag, min_rgb, visual_type ); + } + else { + /* Get a color index visual */ + vis = choose_x_visual( dpy, screen, rgb_flag, min_ci, visual_type ); + accum_size = 0; + } + } + else { + /* over/underlay planes */ + vis = choose_x_overlay_visual( dpy, screen, level, trans_type, + trans_value, min_ci, visual_type ); + } + + if (vis) { + if (!save_glx_visual( dpy, vis, rgb_flag, alpha_flag, double_flag, + stereo_flag, + depth_size, stencil_size, accum_size, level )) + return NULL; + } + + return vis; +} + + + + +GLXContext Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo, + GLXContext share_list, Bool direct ) +{ + XMesaVisual glxvis; + XMesaContext xmctx; + + /* deallocate unused windows/buffers */ + XMesaGarbageCollect(); + + glxvis = find_glx_visual( dpy, visinfo ); + if (!glxvis) { + /* This visual wasn't found with glXChooseVisual() */ + glxvis = create_glx_visual( dpy, visinfo ); + if (!glxvis) { + /* unusable visual */ + return NULL; + } + } + + xmctx = XMesaCreateContext( glxvis, (XMesaContext) share_list ); + if (xmctx) { + /* set the direct/indirect flag */ + xmctx->direct = direct; + } + return (GLXContext) xmctx; +} + + +static GLXDrawable MakeCurrent_PrevDrawable = 0; +static GLXContext MakeCurrent_PrevContext = 0; +static XMesaBuffer MakeCurrent_PrevBuffer = 0; + +Bool Fake_glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx ) +{ + if (ctx && drawable) { + XMesaBuffer buffer; + + if (drawable==MakeCurrent_PrevDrawable && ctx==MakeCurrent_PrevContext) { + buffer = MakeCurrent_PrevBuffer; + } + else { + buffer = XMesaFindBuffer( dpy, drawable ); + } + if (!buffer) { + /* drawable must be a new window! */ + buffer = XMesaCreateWindowBuffer2( ctx->xm_visual, drawable, ctx ); + if (!buffer) { + /* Out of memory, or context/drawable depth mismatch */ + return False; + } + } + MakeCurrent_PrevContext = ctx; + MakeCurrent_PrevDrawable = drawable; + MakeCurrent_PrevBuffer = buffer; + + /* Now make current! */ + return (Bool) XMesaMakeCurrent( (XMesaContext) ctx, buffer ); + } + else if (!ctx && !drawable) { + /* release current context w/out assigning new one. */ + XMesaMakeCurrent( NULL, NULL ); + MakeCurrent_PrevContext = 0; + MakeCurrent_PrevDrawable = 0; + MakeCurrent_PrevBuffer = 0; + return True; + } + else { + /* ctx XOR drawable is NULL, this is an error */ + return False; + } +} + + + +GLXPixmap Fake_glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, + Pixmap pixmap ) +{ + XMesaVisual v; + XMesaBuffer b; + + v = find_glx_visual( dpy, visinfo ); + if (!v) { + v = create_glx_visual( dpy, visinfo ); + if (!v) { + /* unusable visual */ + return 0; + } + } + + b = XMesaCreatePixmapBuffer( v, pixmap, 0 ); + if (!b) { + return 0; + } + return b->frontbuffer; +} + + +#ifdef GLX_MESA_pixmap_colormap + +GLXPixmap Fake_glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo, + Pixmap pixmap, Colormap cmap ) +{ + XMesaVisual v; + XMesaBuffer b; + + v = find_glx_visual( dpy, visinfo ); + if (!v) { + v = create_glx_visual( dpy, visinfo ); + if (!v) { + /* unusable visual */ + return 0; + } + } + + b = XMesaCreatePixmapBuffer( v, pixmap, cmap ); + if (!b) { + return 0; + } + return b->frontbuffer; +} + +#endif + + +void Fake_glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap ) +{ + XMesaBuffer b = XMesaFindBuffer(dpy, pixmap); + if (b) { + XMesaDestroyBuffer(b); + } + else if (getenv("MESA_DEBUG")) { + fprintf( stderr, "Mesa: glXDestroyGLXPixmap: invalid pixmap\n"); + } +} + + +void Fake_glXCopyContext( Display *dpy, GLXContext src, GLXContext dst, + GLuint mask ) +{ + XMesaContext xm_src = (XMesaContext) src; + XMesaContext xm_dst = (XMesaContext) dst; + (void) dpy; + gl_copy_context( xm_src->gl_ctx, xm_dst->gl_ctx, mask ); +} + + + +Bool Fake_glXQueryExtension( Display *dpy, int *errorb, int *event ) +{ + /* Mesa's GLX isn't really an X extension but we try to act like one. */ + (void) dpy; + (void) errorb; + (void) event; + return True; +} + + +void _kw_ungrab_all( Display *dpy ) +{ + XUngrabPointer( dpy, CurrentTime ); + XUngrabKeyboard( dpy, CurrentTime ); +} + + +void Fake_glXDestroyContext( Display *dpy, GLXContext ctx ) +{ + (void) dpy; + MakeCurrent_PrevContext = 0; + MakeCurrent_PrevDrawable = 0; + MakeCurrent_PrevBuffer = 0; + XMesaDestroyContext( (XMesaContext) ctx ); + XMesaGarbageCollect(); +} + + + +Bool Fake_glXIsDirect( Display *dpy, GLXContext ctx ) +{ + (void) dpy; + return ((XMesaContext) ctx)->direct; +} + + + +void Fake_glXSwapBuffers( Display *dpy, GLXDrawable drawable ) +{ + XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable ); + static GLXDrawable last = 0; + static Window window = 0; + if (drawable != last && 0) { + XSetWindowAttributes cwa; + + _kw_ungrab_all( dpy ); + cwa.override_redirect = 0; + XChangeWindowAttributes( dpy, drawable, CWOverrideRedirect, + &cwa ); +/* printf("KW: Ungrab display %s\n", DisplayString(dpy)); */ + + +/* last = drawable; */ + + + if (!window) { + XSetWindowAttributes cwa; + + if ((window = XCreateSimpleWindow( dpy, + RootWindow( dpy, 0 ), + 10,10,100,100, 0, + WhitePixel( dpy, 0 ), + BlackPixel( dpy, 0 ))) == 0) + { + printf("Failed to open radar window\n"); + abort(); + } + + cwa.event_mask = (PointerMotionMask | + ButtonPressMask | + ButtonReleaseMask | + KeyPressMask | + KeyReleaseMask | + ExposureMask ); + + XChangeWindowAttributes( dpy, window, + CWEventMask, + &cwa ); + + XMapWindow( dpy, window ); + XFlush( dpy ); + } + } + if (buffer) { + XMesaSwapBuffers(buffer); + } + else if (getenv("MESA_DEBUG")) { + fprintf(stderr, "Mesa Warning: glXSwapBuffers: invalid drawable\n"); + } +} + + +void Fake_glXCopySubBufferMESA( Display *dpy, GLXDrawable drawable, + int x, int y, int width, int height ) +{ + XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable ); + if (buffer) { + XMesaCopySubBuffer(buffer, x, y, width, height); + } + else if (getenv("MESA_DEBUG")) { + fprintf(stderr, "Mesa Warning: glXCopySubBufferMESA: invalid drawable\n"); + } +} + + + +Bool Fake_glXQueryVersion( Display *dpy, int *maj, int *min ) +{ + (void) dpy; + /* Return GLX version, not Mesa version */ + *maj = 1; + *min = 1; + return True; +} + + + +/* + * Query the GLX attributes of the given XVisualInfo. + */ +int Fake_glXGetConfig( Display *dpy, XVisualInfo *visinfo, + int attrib, int *value ) +{ + XMesaVisual glxvis; + + glxvis = find_glx_visual( dpy, visinfo ); + if (!glxvis) { + /* this visual wasn't obtained with glXChooseVisual */ + glxvis = create_glx_visual( dpy, visinfo ); + if (!glxvis) { + /* this visual can't be used for GL rendering */ + if (attrib==GLX_USE_GL) { + *value = (int) False; + return 0; + } + else { + /*fprintf( stderr, "Mesa: Error in glXGetConfig: bad visual\n");*/ + return GLX_BAD_VISUAL; + } + } + } + + switch(attrib) { + case GLX_USE_GL: + *value = (int) True; + return 0; + case GLX_BUFFER_SIZE: + *value = visinfo->depth; + return 0; + case GLX_LEVEL: + *value = glxvis->level; + return 0; + case GLX_RGBA: + if (glxvis->gl_visual->RGBAflag) { + *value = True; + } + else { + *value = False; + } + return 0; + case GLX_DOUBLEBUFFER: + *value = (int) glxvis->gl_visual->DBflag; + return 0; + case GLX_STEREO: + *value = (int) glxvis->gl_visual->StereoFlag; + return 0; + case GLX_AUX_BUFFERS: + *value = (int) False; + return 0; + case GLX_RED_SIZE: + *value = glxvis->gl_visual->RedBits; + return 0; + case GLX_GREEN_SIZE: + *value = glxvis->gl_visual->GreenBits; + return 0; + case GLX_BLUE_SIZE: + *value = glxvis->gl_visual->BlueBits; + return 0; + case GLX_ALPHA_SIZE: + *value = glxvis->gl_visual->AlphaBits; + return 0; + case GLX_DEPTH_SIZE: + *value = glxvis->gl_visual->DepthBits; + return 0; + case GLX_STENCIL_SIZE: + *value = glxvis->gl_visual->StencilBits; + return 0; + case GLX_ACCUM_RED_SIZE: + case GLX_ACCUM_GREEN_SIZE: + case GLX_ACCUM_BLUE_SIZE: + *value = glxvis->gl_visual->AccumBits; + return 0; + case GLX_ACCUM_ALPHA_SIZE: + if (glxvis->gl_visual->AlphaBits > 0) + *value = glxvis->gl_visual->AccumBits; + else + *value = 0; + return 0; + + /* + * GLX_EXT_visual_info extension + */ + case GLX_X_VISUAL_TYPE_EXT: + switch (glxvis->visinfo->CLASS) { + case StaticGray: *value = GLX_STATIC_GRAY_EXT; return 0; + case GrayScale: *value = GLX_GRAY_SCALE_EXT; return 0; + case StaticColor: *value = GLX_STATIC_GRAY_EXT; return 0; + case PseudoColor: *value = GLX_PSEUDO_COLOR_EXT; return 0; + case TrueColor: *value = GLX_TRUE_COLOR_EXT; return 0; + case DirectColor: *value = GLX_DIRECT_COLOR_EXT; return 0; + } + return 0; + case GLX_TRANSPARENT_TYPE_EXT: + if (glxvis->level==0) { + /* normal planes */ + *value = GLX_NONE_EXT; + } + else if (glxvis->level>0) { + /* overlay */ + if (glxvis->gl_visual->RGBAflag) { + *value = GLX_TRANSPARENT_RGB_EXT; + } + else { + *value = GLX_TRANSPARENT_INDEX_EXT; + } + } + else if (glxvis->level<0) { + /* underlay */ + *value = GLX_NONE_EXT; + } + return 0; + case GLX_TRANSPARENT_INDEX_VALUE_EXT: + { + int pixel = transparent_pixel( glxvis ); + if (pixel>=0) { + *value = pixel; + } + /* else undefined */ + } + return 0; + case GLX_TRANSPARENT_RED_VALUE_EXT: + /* undefined */ + return 0; + case GLX_TRANSPARENT_GREEN_VALUE_EXT: + /* undefined */ + return 0; + case GLX_TRANSPARENT_BLUE_VALUE_EXT: + /* undefined */ + return 0; + case GLX_TRANSPARENT_ALPHA_VALUE_EXT: + /* undefined */ + return 0; + + /* + * Extensions + */ + default: + return GLX_BAD_ATTRIBUTE; + } +} + + + +GLXContext Fake_glXGetCurrentContext( void ) +{ + return (GLXContext) XMesaGetCurrentContext(); +} + + + +GLXDrawable Fake_glXGetCurrentDrawable( void ) +{ + XMesaBuffer b = XMesaGetCurrentBuffer(); + if (b) { + return b->frontbuffer; + } + else { + return 0; + } +} + + +void Fake_glXWaitGL( void ) +{ + XMesaContext xmesa = XMesaGetCurrentContext(); + XMesaFlush( xmesa ); +} + + + +void Fake_glXWaitX( void ) +{ + XMesaContext xmesa = XMesaGetCurrentContext(); + XMesaFlush( xmesa ); +} + + + +#define EXTENSIONS "GLX_MESA_pixmap_colormap GLX_EXT_visual_info GLX_MESA_release_buffers GLX_MESA_copy_sub_buffer GLX_SGI_video_sync" + + +/* GLX 1.1 and later */ +const char *Fake_glXQueryExtensionsString( Display *dpy, int screen ) +{ + static char *extensions = EXTENSIONS; + (void) dpy; + (void) screen; + return extensions; +} + + + +/* GLX 1.1 and later */ +const char *Fake_glXQueryServerString( Display *dpy, int screen, int name ) +{ + static char *extensions = EXTENSIONS; + static char *vendor = "Brian Paul"; + static char *version = "1.1 Mesa 3.0"; + + (void) dpy; + (void) screen; + + switch (name) { + case GLX_EXTENSIONS: + return extensions; + case GLX_VENDOR: + return vendor; + case GLX_VERSION: + return version; + default: + return NULL; + } +} + + + +/* GLX 1.1 and later */ +const char *Fake_glXGetClientString( Display *dpy, int name ) +{ + static char *extensions = EXTENSIONS; + static char *vendor = "Brian Paul"; + static char *version = "1.1 Mesa 3.0"; + + (void) dpy; + + switch (name) { + case GLX_EXTENSIONS: + return extensions; + case GLX_VENDOR: + return vendor; + case GLX_VERSION: + return version; + default: + return NULL; + } +} + + + +/* + * Release the depth, stencil, accum buffers attached to a GLXDrawable + * (a window or pixmap) prior to destroying the GLXDrawable. + */ +Bool Fake_glXReleaseBuffersMESA( Display *dpy, GLXDrawable d ) +{ + XMesaBuffer b = XMesaFindBuffer(dpy, d); + if (b) { + XMesaDestroyBuffer(b); + return True; + } + return False; +} + + +/* Silence compiler warnings */ +void Fake_glXDummyFunc( void ) +{ + (void) kernel8; + (void) DitherValues; + (void) HPCR_DRGB; + (void) kernel1; +} |