summaryrefslogtreecommitdiffstats
path: root/src/mesa/drivers/x11/fakeglx.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/drivers/x11/fakeglx.c')
-rw-r--r--src/mesa/drivers/x11/fakeglx.c1516
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
+ *
+ * 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;
+}