X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fx11%2Ffakeglx.c;h=1587df66bcd48f1ce8e8db76427d1cc30826326b;hb=a8ec5dac3c8c564b1c405798f7703e0d8e650f2d;hp=d3a36ec8f43337216071dbac788846e4460fdf7e;hpb=01915e90e6912f06d43d443a09157f7bbc96ddc5;p=mesa.git diff --git a/src/mesa/drivers/x11/fakeglx.c b/src/mesa/drivers/x11/fakeglx.c index d3a36ec8f43..1587df66bcd 100644 --- a/src/mesa/drivers/x11/fakeglx.c +++ b/src/mesa/drivers/x11/fakeglx.c @@ -1,10 +1,8 @@ -/* $Id: fakeglx.c,v 1.47 2001/03/08 15:23:46 brianp Exp $ */ - /* * Mesa 3-D graphics library - * Version: 3.5 + * Version: 7.1 * - * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * Copyright (C) 1999-2007 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"), @@ -48,52 +46,73 @@ #include "context.h" #include "config.h" #include "macros.h" -#include "mmath.h" +#include "imports.h" #include "mtypes.h" +#include "version.h" #include "xfonts.h" #include "xmesaP.h" +#ifdef __VMS +#define _mesa_sprintf sprintf +#endif /* This indicates the client-side GLX API and GLX encoder version. */ #define CLIENT_MAJOR_VERSION 1 -#define CLIENT_MINOR_VERSION 2 +#define CLIENT_MINOR_VERSION 4 /* but don't have 1.3's pbuffers, etc yet */ /* This indicates the server-side GLX decoder version. - * GLX 1.3 indicates OpenGL 1.2 support + * GLX 1.4 indicates OpenGL 1.3 support */ #define SERVER_MAJOR_VERSION 1 -#define SERVER_MINOR_VERSION 3 +#define SERVER_MINOR_VERSION 4 /* This is appended onto the glXGetClient/ServerString version strings. */ -#define MESA_GLX_VERSION "Mesa 3.5" +#define MESA_GLX_VERSION "Mesa " MESA_VERSION_STRING /* Who implemented this GLX? */ #define VENDOR "Brian Paul" +#define EXTENSIONS \ + "GLX_MESA_set_3dfx_mode " \ + "GLX_MESA_copy_sub_buffer " \ + "GLX_MESA_pixmap_colormap " \ + "GLX_MESA_release_buffers " \ + "GLX_ARB_get_proc_address " \ + "GLX_EXT_texture_from_pixmap " \ + "GLX_EXT_visual_info " \ + "GLX_EXT_visual_rating " \ + /*"GLX_SGI_video_sync "*/ \ + "GLX_SGIX_fbconfig " \ + "GLX_SGIX_pbuffer " +/* + * Our fake GLX context will contain a "real" GLX context and an XMesa context. + * + * Note that a pointer to a __GLXcontext is a pointer to a fake_glx_context, + * and vice versa. + * + * We really just need this structure in order to make the libGL functions + * glXGetCurrentContext(), glXGetCurrentDrawable() and glXGetCurrentDisplay() + * work correctly. + */ +struct fake_glx_context { + __GLXcontext glxContext; /* this MUST be first! */ + XMesaContext xmesaContext; +}; -/* Silence compiler warnings */ -extern void Fake_glXDummyFunc( void ); -void Fake_glXDummyFunc( void ) -{ - (void) kernel8; - (void) DitherValues; - (void) HPCR_DRGB; - (void) kernel1; -} +/**********************************************************************/ +/*** GLX Visual Code ***/ +/**********************************************************************/ #define DONT_CARE -1 - -#define MAX_VISUALS 100 -static XMesaVisual VisualTable[MAX_VISUALS]; +static XMesaVisual *VisualTable = NULL; static int NumVisuals = 0; - /* * This struct and some code fragments borrowed * from Mark Kilgard's GLUT library. @@ -120,11 +139,11 @@ typedef struct _OverlayInfo { - /* * Test if the given XVisualInfo is usable for Mesa rendering. */ -static GLboolean is_usable_visual( XVisualInfo *vinfo ) +static GLboolean +is_usable_visual( XVisualInfo *vinfo ) { switch (vinfo->CLASS) { case StaticGray: @@ -152,25 +171,22 @@ static GLboolean is_usable_visual( XVisualInfo *vinfo ) -/* - * 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 +/** + * Get an array OverlayInfo records for specified screen. + * \param dpy the display + * \param screen screen number + * \param numOverlays returns numver of OverlayInfo records + * \return pointer to OverlayInfo array, free with XFree() */ -static int level_of_visual( Display *dpy, XVisualInfo *vinfo ) +static OverlayInfo * +GetOverlayInfo(Display *dpy, int screen, int *numOverlays) { Atom overlayVisualsAtom; - OverlayInfo *overlay_info = NULL; - int numOverlaysPerScreen; - Status status; Atom actualType; - int actualFormat; + Status status; + unsigned char *ovInfo; unsigned long sizeData, bytesLeft; - int i; + int actualFormat; /* * The SERVER_OVERLAY_VISUALS property on the root window contains @@ -181,25 +197,50 @@ static int level_of_visual( Display *dpy, XVisualInfo *vinfo ) return 0; } - status = XGetWindowProperty(dpy, RootWindow( dpy, vinfo->screen ), + status = XGetWindowProperty(dpy, RootWindow(dpy, screen), overlayVisualsAtom, 0L, (long) 10000, False, overlayVisualsAtom, &actualType, &actualFormat, &sizeData, &bytesLeft, - (unsigned char **) &overlay_info ); + &ovInfo); if (status != Success || actualType != overlayVisualsAtom || actualFormat != 32 || sizeData < 4) { /* something went wrong */ - XFree((void *) overlay_info); + XFree((void *) ovInfo); + *numOverlays = 0; + return NULL; + } + + *numOverlays = sizeData / 4; + return (OverlayInfo *) ovInfo; +} + + + +/** + * 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 ) +{ + OverlayInfo *overlay_info; + int numOverlaysPerScreen, i; + + overlay_info = GetOverlayInfo(dpy, vinfo->screen, &numOverlaysPerScreen); + if (!overlay_info) { return 0; } /* search the overlay visual list for the visual ID of interest */ - numOverlaysPerScreen = (int) (sizeData / 4); - for (i=0;ioverlay_visual==vinfo->visualid) { + for (i = 0; i < numOverlaysPerScreen; i++) { + const OverlayInfo *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; @@ -232,7 +273,7 @@ save_glx_visual( Display *dpy, XVisualInfo *vinfo, GLint depth_size, GLint stencil_size, GLint accumRedSize, GLint accumGreenSize, GLint accumBlueSize, GLint accumAlphaSize, - GLint level ) + GLint level, GLint numAuxBuffers ) { GLboolean ximageFlag = GL_TRUE; XMesaVisual xmvis; @@ -241,7 +282,7 @@ save_glx_visual( Display *dpy, XVisualInfo *vinfo, if (dbFlag) { /* Check if the MESA_BACK_BUFFER env var is set */ - char *backbuffer = getenv("MESA_BACK_BUFFER"); + char *backbuffer = _mesa_getenv("MESA_BACK_BUFFER"); if (backbuffer) { if (backbuffer[0]=='p' || backbuffer[0]=='P') { ximageFlag = GL_FALSE; @@ -250,35 +291,39 @@ save_glx_visual( Display *dpy, XVisualInfo *vinfo, ximageFlag = GL_TRUE; } else { - fprintf(stderr, "Mesa: invalid value for MESA_BACK_BUFFER "); - fprintf(stderr, "environment variable, using an XImage.\n"); + _mesa_warning(NULL, "Mesa: invalid value for MESA_BACK_BUFFER environment variable, using an XImage."); } } } /* Comparing IDs uses less memory but sometimes fails. */ /* XXX revisit this after 3.0 is finished. */ - if (getenv("MESA_GLX_VISUAL_HACK")) + if (_mesa_getenv("MESA_GLX_VISUAL_HACK")) comparePointers = GL_TRUE; else comparePointers = GL_FALSE; + /* Force the visual to have an alpha channel */ + if (rgbFlag && _mesa_getenv("MESA_GLX_FORCE_ALPHA")) + alphaFlag = GL_TRUE; + /* First check if a matching visual is already in the list */ for (i=0; idisplay == dpy - && v->level == level + && v->mesa_visual.level == level + && v->mesa_visual.numAuxBuffers == numAuxBuffers && v->ximage_flag == ximageFlag - && v->gl_visual->rgbMode == rgbFlag - && v->gl_visual->doubleBufferMode == dbFlag - && v->gl_visual->stereoMode == 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->accumRedBits >= accumRedSize || accumRedSize == 0) - && (v->gl_visual->accumGreenBits >= accumGreenSize || accumGreenSize == 0) - && (v->gl_visual->accumBlueBits >= accumBlueSize || accumBlueSize == 0) - && (v->gl_visual->accumAlphaBits >= accumAlphaSize || accumAlphaSize == 0)) { + && v->mesa_visual.rgbMode == rgbFlag + && v->mesa_visual.doubleBufferMode == dbFlag + && v->mesa_visual.stereoMode == stereoFlag + && (v->mesa_visual.alphaBits > 0) == alphaFlag + && (v->mesa_visual.depthBits >= depth_size || depth_size == 0) + && (v->mesa_visual.stencilBits >= stencil_size || stencil_size == 0) + && (v->mesa_visual.accumRedBits >= accumRedSize || accumRedSize == 0) + && (v->mesa_visual.accumGreenBits >= accumGreenSize || accumGreenSize == 0) + && (v->mesa_visual.accumBlueBits >= accumBlueSize || accumBlueSize == 0) + && (v->mesa_visual.accumAlphaBits >= accumAlphaSize || accumAlphaSize == 0)) { /* now either compare XVisualInfo pointers or visual IDs */ if ((!comparePointers && v->visinfo->visualid == vinfo->visualid) || (comparePointers && v->vishandle == vinfo)) { @@ -289,11 +334,6 @@ save_glx_visual( Display *dpy, XVisualInfo *vinfo, /* 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, @@ -301,13 +341,63 @@ save_glx_visual( Display *dpy, XVisualInfo *vinfo, accumBlueSize, accumAlphaSize, 0, level, GLX_NONE_EXT ); if (xmvis) { + /* Save a copy of the pointer now so we can find this visual again + * if we need to search for it in find_glx_visual(). + */ + xmvis->vishandle = vinfo; + /* Allocate more space for additional visual */ + VisualTable = (XMesaVisual *) _mesa_realloc( VisualTable, + sizeof(XMesaVisual) * NumVisuals, + sizeof(XMesaVisual) * (NumVisuals + 1)); + /* add xmvis to the list */ VisualTable[NumVisuals] = xmvis; NumVisuals++; + /* XXX minor hack, because XMesaCreateVisual doesn't support an + * aux buffers parameter. + */ + xmvis->mesa_visual.numAuxBuffers = numAuxBuffers; } return xmvis; } +/** + * Return the default number of bits for the Z buffer. + * If defined, use the MESA_GLX_DEPTH_BITS env var value. + * Otherwise, use the DEFAULT_SOFTWARE_DEPTH_BITS constant. + * XXX probably do the same thing for stencil, accum, etc. + */ +static GLint +default_depth_bits(void) +{ + int zBits; + const char *zEnv = _mesa_getenv("MESA_GLX_DEPTH_BITS"); + if (zEnv) + zBits = _mesa_atoi(zEnv); + else + zBits = DEFAULT_SOFTWARE_DEPTH_BITS; + return zBits; +} + +static GLint +default_alpha_bits(void) +{ + int aBits; + const char *aEnv = _mesa_getenv("MESA_GLX_ALPHA_BITS"); + if (aEnv) + aBits = _mesa_atoi(aEnv); + else + aBits = 0; + return aBits; +} + +static GLint +default_accum_bits(void) +{ + return 16; +} + + /* * Create a GLX visual from a regular XVisualInfo. @@ -321,6 +411,9 @@ static XMesaVisual create_glx_visual( Display *dpy, XVisualInfo *visinfo ) { int vislevel; + GLint zBits = default_depth_bits(); + GLint accBits = default_accum_bits(); + GLboolean alphaFlag = default_alpha_bits() > 0; vislevel = level_of_visual( dpy, visinfo ); if (vislevel) { @@ -333,24 +426,23 @@ create_glx_visual( Display *dpy, XVisualInfo *visinfo ) 0, /* depth bits */ 0, /* stencil bits */ 0,0,0,0, /* accum bits */ - vislevel /* level */ + vislevel, /* level */ + 0 /* numAux */ ); } else if (is_usable_visual( visinfo )) { - if (getenv("MESA_GLX_FORCE_CI")) { + if (_mesa_getenv("MESA_GLX_FORCE_CI")) { /* Configure this visual as a COLOR INDEX visual. */ return save_glx_visual( dpy, visinfo, GL_FALSE, /* rgb */ GL_FALSE, /* alpha */ GL_TRUE, /* double */ GL_FALSE, /* stereo */ - DEFAULT_SOFTWARE_DEPTH_BITS, - 8 * sizeof(GLstencil), - 0 * sizeof(GLaccum), /* r */ - 0 * sizeof(GLaccum), /* g */ - 0 * sizeof(GLaccum), /* b */ - 0 * sizeof(GLaccum), /* a */ - 0 /* level */ + zBits, + STENCIL_BITS, + 0, 0, 0, 0, /* accum bits */ + 0, /* level */ + 0 /* numAux */ ); } else { @@ -359,21 +451,22 @@ create_glx_visual( Display *dpy, XVisualInfo *visinfo ) /* can be done? They should use glXChooseVisual(). */ return save_glx_visual( dpy, visinfo, GL_TRUE, /* rgb */ - GL_FALSE, /* alpha */ + alphaFlag, /* alpha */ GL_TRUE, /* double */ GL_FALSE, /* stereo */ - DEFAULT_SOFTWARE_DEPTH_BITS, - 8 * sizeof(GLstencil), - 8 * sizeof(GLaccum), /* r */ - 8 * sizeof(GLaccum), /* g */ - 8 * sizeof(GLaccum), /* b */ - 8 * sizeof(GLaccum), /* a */ - 0 /* level */ + zBits, + STENCIL_BITS, + accBits, /* r */ + accBits, /* g */ + accBits, /* b */ + accBits, /* a */ + 0, /* level */ + 0 /* numAux */ ); } } else { - fprintf(stderr,"Mesa: error in glXCreateContext: bad visual\n"); + _mesa_warning(NULL, "Mesa: error in glXCreateContext: bad visual\n"); return NULL; } } @@ -388,72 +481,49 @@ find_glx_visual( Display *dpy, XVisualInfo *vinfo ) { int i; - /* First try to match pointers */ + /* try to match visual id */ for (i=0;idisplay==dpy && VisualTable[i]->vishandle==vinfo) { + if (VisualTable[i]->display==dpy + && VisualTable[i]->visinfo->visualid == vinfo->visualid) { return VisualTable[i]; } } - /* try to match visual id */ + + /* if that fails, try to match pointers */ for (i=0;idisplay==dpy - && VisualTable[i]->visinfo->visualid == vinfo->visualid) { + if (VisualTable[i]->display==dpy && VisualTable[i]->vishandle==vinfo) { 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 ) +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 ); + OverlayInfo *overlay_info; + int numOverlaysPerScreen, i; - if (status != Success || actualType != overlayVisualsAtom || - actualFormat != 32 || sizeData < 4) { - /* something went wrong */ - XFree((void *) overlay_info); + overlay_info = GetOverlayInfo(dpy, vinfo->screen, &numOverlaysPerScreen); + if (!overlay_info) { return -1; } - /* search the overlay visual list for the visual ID of interest */ - numOverlaysPerScreen = (int) (sizeData / 4); - for (i=0;ioverlay_visual==vinfo->visualid) { + for (i = 0; i < numOverlaysPerScreen; i++) { + const OverlayInfo *ov = overlay_info + i; + if (ov->overlay_visual == vinfo->visualid) { /* found it! */ - if (ov->transparent_type==0) { + if (ov->transparent_type == 0) { /* type 0 indicates no transparency */ XFree((void *) overlay_info); return -1; @@ -473,11 +543,11 @@ static int transparent_pixel( XMesaVisual glxvis ) -/* +/** * Try to get an X visual which matches the given arguments. */ -static XVisualInfo *get_visual( Display *dpy, int scr, - unsigned int depth, int xclass ) +static XVisualInfo * +get_visual( Display *dpy, int scr, unsigned int depth, int xclass ) { XVisualInfo temp, *vis; long mask; @@ -530,27 +600,28 @@ static XVisualInfo *get_visual( Display *dpy, int scr, * 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) +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 )) { + if (!_mesa_getenv( varname )) { return NULL; } - strncpy( value, getenv(varname), 100 ); + _mesa_strncpy( value, _mesa_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 (_mesa_strcmp(type,"TrueColor")==0) xclass = TrueColor; + else if (_mesa_strcmp(type,"DirectColor")==0) xclass = DirectColor; + else if (_mesa_strcmp(type,"PseudoColor")==0) xclass = PseudoColor; + else if (_mesa_strcmp(type,"StaticColor")==0) xclass = StaticColor; + else if (_mesa_strcmp(type,"GrayScale")==0) xclass = GrayScale; + else if (_mesa_strcmp(type,"StaticGray")==0) xclass = StaticGray; if (xclass>-1 && depth>0) { vis = get_visual( dpy, scr, depth, xclass ); @@ -559,8 +630,9 @@ static XVisualInfo *get_env_visual(Display *dpy, int scr, const char *varname) } } - fprintf( stderr, "Mesa: GLX unable to find visual class=%s, depth=%d.\n", - type, depth ); + _mesa_warning(NULL, "GLX unable to find visual class=%s, depth=%d.", + type, depth); + return NULL; } @@ -574,9 +646,9 @@ static XVisualInfo *get_env_visual(Display *dpy, int scr, const char *varname) * 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 ) +static XVisualInfo * +choose_x_visual( Display *dpy, int screen, GLboolean rgba, int min_depth, + int preferred_class ) { XVisualInfo *vis; int xclass, visclass = 0; @@ -744,20 +816,13 @@ static XVisualInfo *choose_x_visual( Display *dpy, int screen, * 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, - GLboolean rgbFlag, - int level, int trans_type, - int trans_value, - int min_depth, - int preferred_class ) +static XVisualInfo * +choose_x_overlay_visual( Display *dpy, int scr, GLboolean rgbFlag, + 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; @@ -774,24 +839,8 @@ static XVisualInfo *choose_x_overlay_visual( Display *dpy, int scr, 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 */ + overlay_info = GetOverlayInfo(dpy, scr, &numOverlaysPerScreen); + if (!overlay_info) { return NULL; } @@ -799,12 +848,10 @@ static XVisualInfo *choose_x_overlay_visual( Display *dpy, int scr, deepest = min_depth; deepvis = NULL; - numOverlaysPerScreen = (int) (sizeData / 4); - for (i=0;ilayer!=level) { /* failed overlay level criteria */ @@ -869,15 +916,101 @@ static XVisualInfo *choose_x_overlay_visual( Display *dpy, int scr, } +/**********************************************************************/ +/*** Display-related functions ***/ +/**********************************************************************/ -static XVisualInfo * -Fake_glXChooseVisual( Display *dpy, int screen, int *list ) + +/** + * Free all XMesaVisuals which are associated with the given display. + */ +static void +destroy_visuals_on_display(Display *dpy) +{ + int i; + for (i = 0; i < NumVisuals; i++) { + if (VisualTable[i]->display == dpy) { + /* remove this visual */ + int j; + free(VisualTable[i]); + for (j = i; j < NumVisuals - 1; j++) + VisualTable[j] = VisualTable[j + 1]; + NumVisuals--; + } + } +} + + +/** + * Called from XCloseDisplay() to let us free our display-related data. + */ +static int +close_display_callback(Display *dpy, XExtCodes *codes) +{ + destroy_visuals_on_display(dpy); + xmesa_destroy_buffers_on_display(dpy); + return 0; +} + + +/** + * Look for the named extension on given display and return a pointer + * to the _XExtension data, or NULL if extension not found. + */ +static _XExtension * +lookup_extension(Display *dpy, const char *extName) +{ + _XExtension *ext; + for (ext = dpy->ext_procs; ext; ext = ext->next) { + if (ext->name && strcmp(ext->name, extName) == 0) { + return ext; + } + } + return NULL; +} + + +/** + * Whenever we're given a new Display pointer, call this function to + * register our close_display_callback function. + */ +static void +register_with_display(Display *dpy) +{ + const char *extName = "MesaGLX"; + _XExtension *ext; + + ext = lookup_extension(dpy, extName); + if (!ext) { + XExtCodes *c = XAddExtension(dpy); + ext = dpy->ext_procs; /* new extension is at head of list */ + assert(c->extension == ext->codes.extension); + ext->name = _mesa_strdup(extName); + ext->close_display = close_display_callback; + } +} + + +/**********************************************************************/ +/*** Begin Fake GLX API Functions ***/ +/**********************************************************************/ + + +/** + * Helper used by glXChooseVisual and glXChooseFBConfig. + * The fbConfig parameter must be GL_FALSE for the former and GL_TRUE for + * the later. + * In either case, the attribute list is terminated with the value 'None'. + */ +static XMesaVisual +choose_visual( Display *dpy, int screen, const int *list, GLboolean fbConfig ) { - int *parselist; + const GLboolean rgbModeDefault = fbConfig; + const int *parselist; XVisualInfo *vis; int min_ci = 0; int min_red=0, min_green=0, min_blue=0; - GLboolean rgb_flag = GL_FALSE; + GLboolean rgb_flag = rgbModeDefault; GLboolean alpha_flag = GL_FALSE; GLboolean double_flag = GL_FALSE; GLboolean stereo_flag = GL_FALSE; @@ -892,6 +1025,9 @@ Fake_glXChooseVisual( Display *dpy, int screen, int *list ) int trans_type = DONT_CARE; int trans_value = DONT_CARE; GLint caveat = DONT_CARE; + XMesaVisual xmvis = NULL; + int desiredVisualID = -1; + int numAux = 0; parselist = list; @@ -899,8 +1035,14 @@ Fake_glXChooseVisual( Display *dpy, int screen, int *list ) switch (*parselist) { case GLX_USE_GL: - /* ignore */ - parselist++; + if (fbConfig) { + /* invalid token */ + return NULL; + } + else { + /* skip */ + parselist++; + } break; case GLX_BUFFER_SIZE: parselist++; @@ -911,20 +1053,38 @@ Fake_glXChooseVisual( Display *dpy, int screen, int *list ) level = *parselist++; break; case GLX_RGBA: - rgb_flag = GL_TRUE; - parselist++; + if (fbConfig) { + /* invalid token */ + return NULL; + } + else { + rgb_flag = GL_TRUE; + parselist++; + } break; case GLX_DOUBLEBUFFER: - double_flag = GL_TRUE; - parselist++; + parselist++; + if (fbConfig) { + double_flag = *parselist++; + } + else { + double_flag = GL_TRUE; + } break; case GLX_STEREO: - stereo_flag = GL_TRUE; - return NULL; + parselist++; + if (fbConfig) { + stereo_flag = *parselist++; + } + else { + stereo_flag = GL_TRUE; + } + return NULL; /* stereo not supported */ case GLX_AUX_BUFFERS: - /* ignore */ - parselist++; parselist++; + numAux = *parselist++; + if (numAux > MAX_AUX_BUFFERS) + return NULL; break; case GLX_RED_SIZE: parselist++; @@ -942,7 +1102,7 @@ Fake_glXChooseVisual( Display *dpy, int screen, int *list ) parselist++; { GLint size = *parselist++; - alpha_flag = size>0 ? 1 : 0; + alpha_flag = size ? GL_TRUE : GL_FALSE; } break; case GLX_DEPTH_SIZE: @@ -1014,14 +1174,94 @@ Fake_glXChooseVisual( Display *dpy, int screen, int *list ) caveat = *parselist++; /* ignored for now */ break; + /* + * GLX_ARB_multisample + */ + case GLX_SAMPLE_BUFFERS_ARB: + /* ms not supported */ + return NULL; + case GLX_SAMPLES_ARB: + /* ms not supported */ + return NULL; + + /* + * FBConfig attribs. + */ + case GLX_RENDER_TYPE: + if (!fbConfig) + return NULL; + parselist++; + if (*parselist == GLX_RGBA_BIT) { + rgb_flag = GL_TRUE; + } + else if (*parselist == GLX_COLOR_INDEX_BIT) { + rgb_flag = GL_FALSE; + } + else if (*parselist == 0) { + rgb_flag = GL_TRUE; + } + parselist++; + break; + case GLX_DRAWABLE_TYPE: + if (!fbConfig) + return NULL; + parselist++; + if (*parselist & ~(GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT)) { + return NULL; /* bad bit */ + } + parselist++; + break; + case GLX_FBCONFIG_ID: + if (!fbConfig) + return NULL; + parselist++; + desiredVisualID = *parselist++; + break; + case GLX_X_RENDERABLE: + if (!fbConfig) + return NULL; + parselist += 2; + /* ignore */ + break; + +#ifdef GLX_EXT_texture_from_pixmap + case GLX_BIND_TO_TEXTURE_RGB_EXT: + parselist++; /*skip*/ + break; + case GLX_BIND_TO_TEXTURE_RGBA_EXT: + parselist++; /*skip*/ + break; + case GLX_BIND_TO_MIPMAP_TEXTURE_EXT: + parselist++; /*skip*/ + break; + case GLX_BIND_TO_TEXTURE_TARGETS_EXT: + parselist++; + if (*parselist & ~(GLX_TEXTURE_1D_BIT_EXT | + GLX_TEXTURE_2D_BIT_EXT | + GLX_TEXTURE_RECTANGLE_BIT_EXT)) { + /* invalid bit */ + return NULL; + } + break; + case GLX_Y_INVERTED_EXT: + parselist++; /*skip*/ + break; +#endif + case None: + /* end of list */ break; + default: /* undefined attribute */ + _mesa_warning(NULL, "unexpected attrib 0x%x in choose_visual()", + *parselist); return NULL; } } + (void) caveat; + /* * 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 @@ -1029,7 +1269,24 @@ Fake_glXChooseVisual( Display *dpy, int screen, int *list ) * double buffering, depth buffer, etc. will be associated with the X * visual and stored in the VisualTable[]. */ - if (level==0) { + if (desiredVisualID != -1) { + /* try to get a specific visual, by visualID */ + XVisualInfo temp; + int n; + temp.visualid = desiredVisualID; + temp.screen = screen; + vis = XGetVisualInfo(dpy, VisualIDMask | VisualScreenMask, &temp, &n); + if (vis) { + /* give the visual some useful GLX attributes */ + double_flag = GL_TRUE; + if (vis->depth > 8) + rgb_flag = GL_TRUE; + depth_size = default_depth_bits(); + stencil_size = STENCIL_BITS; + /* XXX accum??? */ + } + } + else if (level==0) { /* normal color planes */ if (rgb_flag) { /* Get an RGB visual */ @@ -1072,80 +1329,131 @@ Fake_glXChooseVisual( Display *dpy, int screen, int *list ) * return 16 to maintain performance with earlier versions of Mesa. */ if (depth_size > 24) - depth_size = 31; /* 32 causes int overflow problems */ + depth_size = 32; else if (depth_size > 16) depth_size = 24; - else if (depth_size > 0) - depth_size = DEFAULT_SOFTWARE_DEPTH_BITS; /*16*/ + else if (depth_size > 0) { + depth_size = default_depth_bits(); + } + + if (!alpha_flag) { + alpha_flag = default_alpha_bits() > 0; + } /* we only support one size of stencil and accum buffers. */ if (stencil_size > 0) stencil_size = STENCIL_BITS; - if (accumRedSize > 0) - accumRedSize = ACCUM_BITS; - if (accumGreenSize > 0) - accumGreenSize = ACCUM_BITS; - if (accumBlueSize > 0) - accumBlueSize = ACCUM_BITS; - if (accumAlphaSize > 0) - accumAlphaSize = ACCUM_BITS; - if (!save_glx_visual( dpy, vis, rgb_flag, alpha_flag, double_flag, - stereo_flag, depth_size, stencil_size, - accumRedSize, accumGreenSize, - accumBlueSize, accumAlphaSize, - level )) - return NULL; + if (accumRedSize > 0 || accumGreenSize > 0 || accumBlueSize > 0 || + accumAlphaSize > 0) { + accumRedSize = + accumGreenSize = + accumBlueSize = default_accum_bits(); + accumAlphaSize = alpha_flag ? accumRedSize : 0; + } + + xmvis = save_glx_visual( dpy, vis, rgb_flag, alpha_flag, double_flag, + stereo_flag, depth_size, stencil_size, + accumRedSize, accumGreenSize, + accumBlueSize, accumAlphaSize, level, numAux ); } - return vis; + return xmvis; } +static XVisualInfo * +Fake_glXChooseVisual( Display *dpy, int screen, int *list ) +{ + XMesaVisual xmvis; + + /* register ourselves as an extension on this display */ + register_with_display(dpy); + + xmvis = choose_visual(dpy, screen, list, GL_FALSE); + if (xmvis) { +#if 0 + return xmvis->vishandle; +#else + /* create a new vishandle - the cached one may be stale */ + xmvis->vishandle = (XVisualInfo *) _mesa_malloc(sizeof(XVisualInfo)); + if (xmvis->vishandle) { + _mesa_memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo)); + } + return xmvis->vishandle; +#endif + } + else + return NULL; +} static GLXContext Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo, GLXContext share_list, Bool direct ) { - XMesaVisual glxvis; - XMesaContext xmctx; + XMesaVisual xmvis; + struct fake_glx_context *glxCtx; + struct fake_glx_context *shareCtx = (struct fake_glx_context *) share_list; + + if (!dpy || !visinfo) + return 0; + + glxCtx = CALLOC_STRUCT(fake_glx_context); + if (!glxCtx) + return 0; /* deallocate unused windows/buffers */ +#if 0 XMesaGarbageCollect(); +#endif - glxvis = find_glx_visual( dpy, visinfo ); - if (!glxvis) { + xmvis = find_glx_visual( dpy, visinfo ); + if (!xmvis) { /* This visual wasn't found with glXChooseVisual() */ - glxvis = create_glx_visual( dpy, visinfo ); - if (!glxvis) { + xmvis = create_glx_visual( dpy, visinfo ); + if (!xmvis) { /* unusable visual */ + _mesa_free(glxCtx); return NULL; } } - xmctx = XMesaCreateContext( glxvis, (XMesaContext) share_list ); - if (xmctx) { - /* set the direct/indirect flag */ - xmctx->direct = direct; + glxCtx->xmesaContext = XMesaCreateContext(xmvis, + shareCtx ? shareCtx->xmesaContext : NULL); + if (!glxCtx->xmesaContext) { + _mesa_free(glxCtx); + return NULL; } - return (GLXContext) xmctx; + + glxCtx->xmesaContext->direct = GL_FALSE; + glxCtx->glxContext.isDirect = GL_FALSE; + glxCtx->glxContext.currentDpy = dpy; + glxCtx->glxContext.xid = (XID) glxCtx; /* self pointer */ + + assert((void *) glxCtx == (void *) &(glxCtx->glxContext)); + + return (GLXContext) glxCtx; } +/* XXX these may have to be removed due to thread-safety issues. */ static GLXContext MakeCurrent_PrevContext = 0; static GLXDrawable MakeCurrent_PrevDrawable = 0; static GLXDrawable MakeCurrent_PrevReadable = 0; static XMesaBuffer MakeCurrent_PrevDrawBuffer = 0; static XMesaBuffer MakeCurrent_PrevReadBuffer = 0; + /* GLX 1.3 and later */ static Bool Fake_glXMakeContextCurrent( Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx ) { + struct fake_glx_context *glxCtx = (struct fake_glx_context *) ctx; + if (ctx && draw && read) { XMesaBuffer drawBuffer, readBuffer; - XMesaContext xmctx = (XMesaContext) ctx; + XMesaContext xmctx = glxCtx->xmesaContext; /* Find the XMesaBuffer which corresponds to the GLXDrawable 'draw' */ if (ctx == MakeCurrent_PrevContext @@ -1157,12 +1465,15 @@ Fake_glXMakeContextCurrent( Display *dpy, GLXDrawable draw, } if (!drawBuffer) { /* drawable must be a new window! */ - drawBuffer = XMesaCreateWindowBuffer2( xmctx->xm_visual, draw, (XMesaContext) ctx ); + drawBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, draw ); if (!drawBuffer) { /* Out of memory, or context/drawable depth mismatch */ return False; } - } +#ifdef FX + FXcreateContext( xmctx->xm_visual, draw, xmctx, drawBuffer ); +#endif + } /* Find the XMesaBuffer which corresponds to the GLXDrawable 'read' */ if (ctx == MakeCurrent_PrevContext @@ -1174,11 +1485,14 @@ Fake_glXMakeContextCurrent( Display *dpy, GLXDrawable draw, } if (!readBuffer) { /* drawable must be a new window! */ - readBuffer = XMesaCreateWindowBuffer2( xmctx->xm_visual, read, (XMesaContext) ctx ); + readBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, read ); if (!readBuffer) { /* Out of memory, or context/drawable depth mismatch */ return False; } +#ifdef FX + FXcreateContext( xmctx->xm_visual, read, xmctx, readBuffer ); +#endif } MakeCurrent_PrevContext = ctx; @@ -1188,7 +1502,15 @@ Fake_glXMakeContextCurrent( Display *dpy, GLXDrawable draw, MakeCurrent_PrevReadBuffer = readBuffer; /* Now make current! */ - return (Bool) XMesaMakeCurrent2((XMesaContext) ctx, drawBuffer, readBuffer); + if (XMesaMakeCurrent2(xmctx, drawBuffer, readBuffer)) { + ((__GLXcontext *) ctx)->currentDpy = dpy; + ((__GLXcontext *) ctx)->currentDrawable = draw; + ((__GLXcontext *) ctx)->currentReadable = read; + return True; + } + else { + return False; + } } else if (!ctx && !draw && !read) { /* release current context w/out assigning new one. */ @@ -1209,7 +1531,6 @@ Fake_glXMakeContextCurrent( Display *dpy, GLXDrawable draw, } - static Bool Fake_glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx ) { @@ -1217,7 +1538,6 @@ Fake_glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx ) } - static GLXPixmap Fake_glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, Pixmap pixmap ) { @@ -1237,11 +1557,12 @@ Fake_glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, Pixmap pixmap ) if (!b) { return 0; } - return b->frontbuffer; + return b->frontxrb->pixmap; } -#ifdef GLX_MESA_pixmap_colormap +/*** GLX_MESA_pixmap_colormap ***/ + static GLXPixmap Fake_glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo, Pixmap pixmap, Colormap cmap ) @@ -1262,9 +1583,8 @@ Fake_glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo, if (!b) { return 0; } - return b->frontbuffer; + return b->frontxrb->pixmap; } -#endif static void @@ -1274,25 +1594,28 @@ Fake_glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap ) if (b) { XMesaDestroyBuffer(b); } - else if (getenv("MESA_DEBUG")) { - fprintf( stderr, "Mesa: glXDestroyGLXPixmap: invalid pixmap\n"); + else if (_mesa_getenv("MESA_DEBUG")) { + _mesa_warning(NULL, "Mesa: glXDestroyGLXPixmap: invalid pixmap\n"); } } - static void Fake_glXCopyContext( Display *dpy, GLXContext src, GLXContext dst, unsigned long mask ) { - XMesaContext xm_src = (XMesaContext) src; - XMesaContext xm_dst = (XMesaContext) dst; + struct fake_glx_context *fakeSrc = (struct fake_glx_context *) src; + struct fake_glx_context *fakeDst = (struct fake_glx_context *) dst; + XMesaContext xm_src = fakeSrc->xmesaContext; + XMesaContext xm_dst = fakeDst->xmesaContext; (void) dpy; - _mesa_copy_context( xm_src->gl_ctx, xm_dst->gl_ctx, (GLuint) mask ); + if (MakeCurrent_PrevContext == src) { + _mesa_Flush(); + } + _mesa_copy_context( &(xm_src->mesa), &(xm_dst->mesa), (GLuint) mask ); } - static Bool Fake_glXQueryExtension( Display *dpy, int *errorb, int *event ) { @@ -1315,23 +1638,25 @@ void _kw_ungrab_all( Display *dpy ) static void Fake_glXDestroyContext( Display *dpy, GLXContext ctx ) { + struct fake_glx_context *glxCtx = (struct fake_glx_context *) ctx; (void) dpy; MakeCurrent_PrevContext = 0; MakeCurrent_PrevDrawable = 0; MakeCurrent_PrevReadable = 0; MakeCurrent_PrevDrawBuffer = 0; MakeCurrent_PrevReadBuffer = 0; - XMesaDestroyContext( (XMesaContext) ctx ); + XMesaDestroyContext( glxCtx->xmesaContext ); XMesaGarbageCollect(); + _mesa_free(glxCtx); } - static Bool Fake_glXIsDirect( Display *dpy, GLXContext ctx ) { + struct fake_glx_context *glxCtx = (struct fake_glx_context *) ctx; (void) dpy; - return ((XMesaContext) ctx)->direct; + return glxCtx->xmesaContext->direct; } @@ -1344,14 +1669,16 @@ Fake_glXSwapBuffers( Display *dpy, GLXDrawable drawable ) if (buffer) { XMesaSwapBuffers(buffer); } - else if (getenv("MESA_DEBUG")) { - fprintf(stderr, "Mesa Warning: glXSwapBuffers: invalid drawable\n"); + else if (_mesa_getenv("MESA_DEBUG")) { + _mesa_warning(NULL, "glXSwapBuffers: invalid drawable 0x%x\n", + (int) drawable); } } -#ifdef GLX_MESA_copy_sub_buffer +/*** GLX_MESA_copy_sub_buffer ***/ + static void Fake_glXCopySubBufferMESA( Display *dpy, GLXDrawable drawable, int x, int y, int width, int height ) @@ -1360,12 +1687,10 @@ Fake_glXCopySubBufferMESA( Display *dpy, GLXDrawable drawable, if (buffer) { XMesaCopySubBuffer(buffer, x, y, width, height); } - else if (getenv("MESA_DEBUG")) { - fprintf(stderr, "Mesa Warning: glXCopySubBufferMESA: invalid drawable\n"); + else if (_mesa_getenv("MESA_DEBUG")) { + _mesa_warning(NULL, "Mesa: glXCopySubBufferMESA: invalid drawable\n"); } } -#endif - static Bool @@ -1380,45 +1705,29 @@ Fake_glXQueryVersion( Display *dpy, int *maj, int *min ) } - /* * Query the GLX attributes of the given XVisualInfo. */ static int -Fake_glXGetConfig( Display *dpy, XVisualInfo *visinfo, - int attrib, int *value ) +get_config( XMesaVisual xmvis, int attrib, int *value, GLboolean fbconfig ) { - 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; - } - } - } - + ASSERT(xmvis); switch(attrib) { case GLX_USE_GL: + if (fbconfig) + return GLX_BAD_ATTRIBUTE; *value = (int) True; return 0; case GLX_BUFFER_SIZE: - *value = visinfo->depth; + *value = xmvis->visinfo->depth; return 0; case GLX_LEVEL: - *value = glxvis->level; + *value = xmvis->mesa_visual.level; return 0; case GLX_RGBA: - if (glxvis->gl_visual->rgbMode) { + if (fbconfig) + return GLX_BAD_ATTRIBUTE; + if (xmvis->mesa_visual.rgbMode) { *value = True; } else { @@ -1426,50 +1735,50 @@ Fake_glXGetConfig( Display *dpy, XVisualInfo *visinfo, } return 0; case GLX_DOUBLEBUFFER: - *value = (int) glxvis->gl_visual->doubleBufferMode; + *value = (int) xmvis->mesa_visual.doubleBufferMode; return 0; case GLX_STEREO: - *value = (int) glxvis->gl_visual->stereoMode; + *value = (int) xmvis->mesa_visual.stereoMode; return 0; case GLX_AUX_BUFFERS: - *value = (int) False; + *value = xmvis->mesa_visual.numAuxBuffers; return 0; case GLX_RED_SIZE: - *value = glxvis->gl_visual->redBits; + *value = xmvis->mesa_visual.redBits; return 0; case GLX_GREEN_SIZE: - *value = glxvis->gl_visual->greenBits; + *value = xmvis->mesa_visual.greenBits; return 0; case GLX_BLUE_SIZE: - *value = glxvis->gl_visual->blueBits; + *value = xmvis->mesa_visual.blueBits; return 0; case GLX_ALPHA_SIZE: - *value = glxvis->gl_visual->alphaBits; + *value = xmvis->mesa_visual.alphaBits; return 0; case GLX_DEPTH_SIZE: - *value = glxvis->gl_visual->depthBits; + *value = xmvis->mesa_visual.depthBits; return 0; case GLX_STENCIL_SIZE: - *value = glxvis->gl_visual->stencilBits; + *value = xmvis->mesa_visual.stencilBits; return 0; case GLX_ACCUM_RED_SIZE: - *value = glxvis->gl_visual->accumRedBits; + *value = xmvis->mesa_visual.accumRedBits; return 0; case GLX_ACCUM_GREEN_SIZE: - *value = glxvis->gl_visual->accumGreenBits; + *value = xmvis->mesa_visual.accumGreenBits; return 0; case GLX_ACCUM_BLUE_SIZE: - *value = glxvis->gl_visual->accumBlueBits; + *value = xmvis->mesa_visual.accumBlueBits; return 0; case GLX_ACCUM_ALPHA_SIZE: - *value = glxvis->gl_visual->accumAlphaBits; + *value = xmvis->mesa_visual.accumAlphaBits; return 0; /* * GLX_EXT_visual_info extension */ case GLX_X_VISUAL_TYPE_EXT: - switch (glxvis->visinfo->CLASS) { + switch (xmvis->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; @@ -1479,27 +1788,27 @@ Fake_glXGetConfig( Display *dpy, XVisualInfo *visinfo, } return 0; case GLX_TRANSPARENT_TYPE_EXT: - if (glxvis->level==0) { + if (xmvis->mesa_visual.level==0) { /* normal planes */ *value = GLX_NONE_EXT; } - else if (glxvis->level>0) { + else if (xmvis->mesa_visual.level>0) { /* overlay */ - if (glxvis->gl_visual->rgbMode) { + if (xmvis->mesa_visual.rgbMode) { *value = GLX_TRANSPARENT_RGB_EXT; } else { *value = GLX_TRANSPARENT_INDEX_EXT; } } - else if (glxvis->level<0) { + else if (xmvis->mesa_visual.level<0) { /* underlay */ *value = GLX_NONE_EXT; } return 0; case GLX_TRANSPARENT_INDEX_VALUE_EXT: { - int pixel = transparent_pixel( glxvis ); + int pixel = transparent_pixel( xmvis ); if (pixel>=0) { *value = pixel; } @@ -1524,21 +1833,133 @@ Fake_glXGetConfig( Display *dpy, XVisualInfo *visinfo, */ case GLX_VISUAL_CAVEAT_EXT: /* test for zero, just in case */ - if (glxvis->VisualCaveat > 0) - *value = glxvis->VisualCaveat; + if (xmvis->mesa_visual.visualRating > 0) + *value = xmvis->mesa_visual.visualRating; else *value = GLX_NONE_EXT; return 0; /* - * Extensions + * GLX_ARB_multisample */ + case GLX_SAMPLE_BUFFERS_ARB: + *value = 0; + return 0; + case GLX_SAMPLES_ARB: + *value = 0; + return 0; + + /* + * For FBConfigs: + */ + case GLX_SCREEN_EXT: + if (!fbconfig) + return GLX_BAD_ATTRIBUTE; + *value = xmvis->visinfo->screen; + break; + case GLX_DRAWABLE_TYPE: /*SGIX too */ + if (!fbconfig) + return GLX_BAD_ATTRIBUTE; + *value = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT; + break; + case GLX_RENDER_TYPE_SGIX: + if (!fbconfig) + return GLX_BAD_ATTRIBUTE; + if (xmvis->mesa_visual.rgbMode) + *value = GLX_RGBA_BIT; + else + *value = GLX_COLOR_INDEX_BIT; + break; + case GLX_X_RENDERABLE_SGIX: + if (!fbconfig) + return GLX_BAD_ATTRIBUTE; + *value = True; /* XXX really? */ + break; + case GLX_FBCONFIG_ID_SGIX: + if (!fbconfig) + return GLX_BAD_ATTRIBUTE; + *value = xmvis->visinfo->visualid; + break; + case GLX_MAX_PBUFFER_WIDTH: + if (!fbconfig) + return GLX_BAD_ATTRIBUTE; + /* XXX or MAX_WIDTH? */ + *value = DisplayWidth(xmvis->display, xmvis->visinfo->screen); + break; + case GLX_MAX_PBUFFER_HEIGHT: + if (!fbconfig) + return GLX_BAD_ATTRIBUTE; + *value = DisplayHeight(xmvis->display, xmvis->visinfo->screen); + break; + case GLX_MAX_PBUFFER_PIXELS: + if (!fbconfig) + return GLX_BAD_ATTRIBUTE; + *value = DisplayWidth(xmvis->display, xmvis->visinfo->screen) * + DisplayHeight(xmvis->display, xmvis->visinfo->screen); + break; + case GLX_VISUAL_ID: + if (!fbconfig) + return GLX_BAD_ATTRIBUTE; + *value = xmvis->visinfo->visualid; + break; + +#ifdef GLX_EXT_texture_from_pixmap + case GLX_BIND_TO_TEXTURE_RGB_EXT: + *value = True; /*XXX*/ + break; + case GLX_BIND_TO_TEXTURE_RGBA_EXT: + /* XXX review */ + *value = xmvis->mesa_visual.alphaBits > 0 ? True : False; + break; + case GLX_BIND_TO_MIPMAP_TEXTURE_EXT: + *value = True; /*XXX*/ + break; + case GLX_BIND_TO_TEXTURE_TARGETS_EXT: + *value = (GLX_TEXTURE_1D_BIT_EXT | + GLX_TEXTURE_2D_BIT_EXT | + GLX_TEXTURE_RECTANGLE_BIT_EXT); /*XXX*/ + break; + case GLX_Y_INVERTED_EXT: + *value = True; /*XXX*/ + break; +#endif + default: return GLX_BAD_ATTRIBUTE; } + return Success; } +static int +Fake_glXGetConfig( Display *dpy, XVisualInfo *visinfo, + int attrib, int *value ) +{ + XMesaVisual xmvis; + int k; + if (!dpy || !visinfo) + return GLX_BAD_ATTRIBUTE; + + xmvis = find_glx_visual( dpy, visinfo ); + if (!xmvis) { + /* this visual wasn't obtained with glXChooseVisual */ + xmvis = create_glx_visual( dpy, visinfo ); + if (!xmvis) { + /* this visual can't be used for GL rendering */ + if (attrib==GLX_USE_GL) { + *value = (int) False; + return 0; + } + else { + return GLX_BAD_VISUAL; + } + } + } + + k = get_config(xmvis, attrib, value, GL_FALSE); + return k; +} + static void Fake_glXWaitGL( void ) @@ -1557,18 +1978,16 @@ Fake_glXWaitX( void ) } -/* - * Return the extensions string, which is 3Dfx-dependant. - */ -static const char *get_extensions( void ) +static const char * +get_extensions( void ) { #ifdef FX - const char *fx = getenv("MESA_GLX_FX"); + const char *fx = _mesa_getenv("MESA_GLX_FX"); if (fx && fx[0] != 'd') { - return "GLX_MESA_pixmap_colormap GLX_EXT_visual_info GLX_EXT_visual_rating GLX_MESA_release_buffers GLX_MESA_copy_sub_buffer GLX_SGI_video_sync GLX_MESA_set_3dfx_mode GLX_ARB_get_proc_address"; + return EXTENSIONS; } #endif - return "GLX_MESA_pixmap_colormap GLX_EXT_visual_info GLX_EXT_visual_rating GLX_MESA_release_buffers GLX_MESA_copy_sub_buffer GLX_SGI_video_sync GLX_ARB_get_proc_address"; + return EXTENSIONS + 23; /* skip "GLX_MESA_set_3dfx_mode" */ } @@ -1589,8 +2008,8 @@ static const char * Fake_glXQueryServerString( Display *dpy, int screen, int name ) { static char version[1000]; - sprintf(version, "%d.%d %s", SERVER_MAJOR_VERSION, SERVER_MINOR_VERSION, - MESA_GLX_VERSION); + _mesa_sprintf(version, "%d.%d %s", + SERVER_MAJOR_VERSION, SERVER_MINOR_VERSION, MESA_GLX_VERSION); (void) dpy; (void) screen; @@ -1614,8 +2033,8 @@ static const char * Fake_glXGetClientString( Display *dpy, int name ) { static char version[1000]; - sprintf(version, "%d.%d %s", CLIENT_MAJOR_VERSION, CLIENT_MINOR_VERSION, - MESA_GLX_VERSION); + _mesa_sprintf(version, "%d.%d %s", CLIENT_MAJOR_VERSION, + CLIENT_MINOR_VERSION, MESA_GLX_VERSION); (void) dpy; @@ -1637,46 +2056,96 @@ Fake_glXGetClientString( Display *dpy, int name ) * GLX 1.3 and later */ -static GLXFBConfig * -Fake_glXChooseFBConfig( Display *dpy, int screen, - const int *attribList, int *nitems ) -{ - (void) dpy; - (void) screen; - (void) attribList; - (void) nitems; - return 0; -} - static int Fake_glXGetFBConfigAttrib( Display *dpy, GLXFBConfig config, int attribute, int *value ) { + XMesaVisual v = (XMesaVisual) config; (void) dpy; (void) config; - (void) attribute; - (void) value; - return 0; + + if (!dpy || !config || !value) + return -1; + + return get_config(v, attribute, value, GL_TRUE); } static GLXFBConfig * Fake_glXGetFBConfigs( Display *dpy, int screen, int *nelements ) { - (void) dpy; - (void) screen; - (void) nelements; - return 0; + XVisualInfo *visuals, visTemplate; + const long visMask = VisualScreenMask; + int i; + + /* Get list of all X visuals */ + visTemplate.screen = screen; + visuals = XGetVisualInfo(dpy, visMask, &visTemplate, nelements); + if (*nelements > 0) { + XMesaVisual *results; + results = (XMesaVisual *) _mesa_malloc(*nelements * sizeof(XMesaVisual)); + if (!results) { + *nelements = 0; + return NULL; + } + for (i = 0; i < *nelements; i++) { + results[i] = create_glx_visual(dpy, visuals + i); + } + return (GLXFBConfig *) results; + } + return NULL; +} + + +static GLXFBConfig * +Fake_glXChooseFBConfig( Display *dpy, int screen, + const int *attribList, int *nitems ) +{ + XMesaVisual xmvis; + + if (!attribList || !attribList[0]) { + /* return list of all configs (per GLX_SGIX_fbconfig spec) */ + return Fake_glXGetFBConfigs(dpy, screen, nitems); + } + + xmvis = choose_visual(dpy, screen, attribList, GL_TRUE); + if (xmvis) { + GLXFBConfig *config = (GLXFBConfig *) _mesa_malloc(sizeof(XMesaVisual)); + if (!config) { + *nitems = 0; + return NULL; + } + *nitems = 1; + config[0] = (GLXFBConfig) xmvis; + return (GLXFBConfig *) config; + } + else { + *nitems = 0; + return NULL; + } } static XVisualInfo * Fake_glXGetVisualFromFBConfig( Display *dpy, GLXFBConfig config ) { - (void) dpy; - (void) config; - return 0; + if (dpy && config) { + XMesaVisual xmvis = (XMesaVisual) config; +#if 0 + return xmvis->vishandle; +#else + /* create a new vishandle - the cached one may be stale */ + xmvis->vishandle = (XVisualInfo *) _mesa_malloc(sizeof(XVisualInfo)); + if (xmvis->vishandle) { + _mesa_memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo)); + } + return xmvis->vishandle; +#endif + } + else { + return NULL; + } } @@ -1684,41 +2153,155 @@ static GLXWindow Fake_glXCreateWindow( Display *dpy, GLXFBConfig config, Window win, const int *attribList ) { + XMesaVisual xmvis = (XMesaVisual) config; + XMesaBuffer xmbuf; + if (!xmvis) + return 0; + + xmbuf = XMesaCreateWindowBuffer(xmvis, win); + if (!xmbuf) + return 0; + +#ifdef FX + /* XXX this will segfault if actually called */ + FXcreateContext(xmvis, win, NULL, xmbuf); +#endif + (void) dpy; - (void) config; - (void) win; - (void) attribList; - return 0; + (void) attribList; /* Ignored in GLX 1.3 */ + + return win; /* A hack for now */ } static void Fake_glXDestroyWindow( Display *dpy, GLXWindow window ) { - (void) dpy; - (void) window; - return; + XMesaBuffer b = XMesaFindBuffer(dpy, (XMesaDrawable) window); + if (b) + XMesaDestroyBuffer(b); + /* don't destroy X window */ } +/* XXX untested */ static GLXPixmap Fake_glXCreatePixmap( Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attribList ) { - (void) dpy; - (void) config; - (void) pixmap; - (void) attribList; - return 0; + XMesaVisual v = (XMesaVisual) config; + XMesaBuffer b; + const int *attr; + int target = 0, format = 0, mipmap = 0; + int value; + + if (!dpy || !config || !pixmap) + return 0; + + for (attr = attribList; *attr; attr++) { + switch (*attr) { + case GLX_TEXTURE_FORMAT_EXT: + attr++; + switch (*attr) { + case GLX_TEXTURE_FORMAT_NONE_EXT: + case GLX_TEXTURE_FORMAT_RGB_EXT: + case GLX_TEXTURE_FORMAT_RGBA_EXT: + format = *attr; + break; + default: + /* error */ + return 0; + } + break; + case GLX_TEXTURE_TARGET_EXT: + attr++; + switch (*attr) { + case GLX_TEXTURE_1D_EXT: + case GLX_TEXTURE_2D_EXT: + case GLX_TEXTURE_RECTANGLE_EXT: + target = *attr; + break; + default: + /* error */ + return 0; + } + break; + case GLX_MIPMAP_TEXTURE_EXT: + attr++; + if (*attr) + mipmap = 1; + break; + default: + /* error */ + return 0; + } + } + + if (format == GLX_TEXTURE_FORMAT_RGB_EXT) { + if (get_config(v, GLX_BIND_TO_TEXTURE_RGB_EXT, + &value, GL_TRUE) != Success + || !value) { + return 0; /* error! */ + } + } + else if (format == GLX_TEXTURE_FORMAT_RGBA_EXT) { + if (get_config(v, GLX_BIND_TO_TEXTURE_RGBA_EXT, + &value, GL_TRUE) != Success + || !value) { + return 0; /* error! */ + } + } + if (mipmap) { + if (get_config(v, GLX_BIND_TO_MIPMAP_TEXTURE_EXT, + &value, GL_TRUE) != Success + || !value) { + return 0; /* error! */ + } + } + if (target == GLX_TEXTURE_1D_EXT) { + if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT, + &value, GL_TRUE) != Success + || (value & GLX_TEXTURE_1D_BIT_EXT) == 0) { + return 0; /* error! */ + } + } + else if (target == GLX_TEXTURE_2D_EXT) { + if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT, + &value, GL_TRUE) != Success + || (value & GLX_TEXTURE_2D_BIT_EXT) == 0) { + return 0; /* error! */ + } + } + if (target == GLX_TEXTURE_RECTANGLE_EXT) { + if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT, + &value, GL_TRUE) != Success + || (value & GLX_TEXTURE_RECTANGLE_BIT_EXT) == 0) { + return 0; /* error! */ + } + } + + if (format || target || mipmap) { + /* texture from pixmap */ + b = XMesaCreatePixmapTextureBuffer(v, pixmap, 0, format, target, mipmap); + } + else { + b = XMesaCreatePixmapBuffer( v, pixmap, 0 ); + } + if (!b) { + return 0; + } + + return pixmap; } static void Fake_glXDestroyPixmap( Display *dpy, GLXPixmap pixmap ) { - (void) dpy; - (void) pixmap; - return; + XMesaBuffer b = XMesaFindBuffer(dpy, (XMesaDrawable)pixmap); + if (b) + XMesaDestroyBuffer(b); + /* don't destroy X pixmap */ } @@ -1726,18 +2309,62 @@ static GLXPbuffer Fake_glXCreatePbuffer( Display *dpy, GLXFBConfig config, const int *attribList ) { + XMesaVisual xmvis = (XMesaVisual) config; + XMesaBuffer xmbuf; + const int *attrib; + int width = 0, height = 0; + GLboolean useLargest = GL_FALSE, preserveContents = GL_FALSE; + (void) dpy; - (void) config; - (void) attribList; - return 0; + + for (attrib = attribList; *attrib; attrib++) { + switch (*attrib) { + case GLX_PBUFFER_WIDTH: + attrib++; + width = *attrib; + break; + case GLX_PBUFFER_HEIGHT: + attrib++; + height = *attrib; + break; + case GLX_PRESERVED_CONTENTS: + attrib++; + preserveContents = *attrib; /* ignored */ + break; + case GLX_LARGEST_PBUFFER: + attrib++; + useLargest = *attrib; /* ignored */ + break; + default: + return 0; + } + } + + /* not used at this time */ + (void) useLargest; + (void) preserveContents; + + if (width == 0 || height == 0) + return 0; + + xmbuf = XMesaCreatePBuffer( xmvis, 0, width, height); + /* A GLXPbuffer handle must be an X Drawable because that's what + * glXMakeCurrent takes. + */ + if (xmbuf) + return (GLXPbuffer) xmbuf->frontxrb->pixmap; + else + return 0; } static void Fake_glXDestroyPbuffer( Display *dpy, GLXPbuffer pbuf ) { - (void) dpy; - (void) pbuf; + XMesaBuffer b = XMesaFindBuffer(dpy, pbuf); + if (b) { + XMesaDestroyBuffer(b); + } } @@ -1745,10 +2372,41 @@ static void Fake_glXQueryDrawable( Display *dpy, GLXDrawable draw, int attribute, unsigned int *value ) { - (void) dpy; - (void) draw; - (void) attribute; - (void) value; + XMesaBuffer xmbuf = XMesaFindBuffer(dpy, draw); + if (!xmbuf) + return; + + switch (attribute) { + case GLX_WIDTH: + *value = xmbuf->mesa_buffer.Width; + break; + case GLX_HEIGHT: + *value = xmbuf->mesa_buffer.Height; + break; + case GLX_PRESERVED_CONTENTS: + *value = True; + break; + case GLX_LARGEST_PBUFFER: + *value = xmbuf->mesa_buffer.Width * xmbuf->mesa_buffer.Height; + break; + case GLX_FBCONFIG_ID: + *value = xmbuf->xm_visual->visinfo->visualid; + return; +#ifdef GLX_EXT_texture_from_pixmap + case GLX_TEXTURE_FORMAT_EXT: + *value = xmbuf->TextureFormat; + break; + case GLX_TEXTURE_TARGET_EXT: + *value = xmbuf->TextureTarget; + break; + case GLX_MIPMAP_TEXTURE_EXT: + *value = xmbuf->TextureMipmap; + break; +#endif + + default: + return; /* raise BadValue error */ + } } @@ -1756,22 +2414,64 @@ static GLXContext Fake_glXCreateNewContext( Display *dpy, GLXFBConfig config, int renderType, GLXContext shareList, Bool direct ) { - (void) dpy; - (void) config; - (void) renderType; - (void) shareList; - (void) direct; - return 0; + struct fake_glx_context *glxCtx; + struct fake_glx_context *shareCtx = (struct fake_glx_context *) shareList; + XMesaVisual xmvis = (XMesaVisual) config; + + if (!dpy || !config || + (renderType != GLX_RGBA_TYPE && renderType != GLX_COLOR_INDEX_TYPE)) + return 0; + + glxCtx = CALLOC_STRUCT(fake_glx_context); + if (!glxCtx) + return 0; + + /* deallocate unused windows/buffers */ + XMesaGarbageCollect(); + + glxCtx->xmesaContext = XMesaCreateContext(xmvis, + shareCtx ? shareCtx->xmesaContext : NULL); + if (!glxCtx->xmesaContext) { + _mesa_free(glxCtx); + return NULL; + } + + glxCtx->xmesaContext->direct = GL_FALSE; + glxCtx->glxContext.isDirect = GL_FALSE; + glxCtx->glxContext.currentDpy = dpy; + glxCtx->glxContext.xid = (XID) glxCtx; /* self pointer */ + + assert((void *) glxCtx == (void *) &(glxCtx->glxContext)); + + return (GLXContext) glxCtx; } static int Fake_glXQueryContext( Display *dpy, GLXContext ctx, int attribute, int *value ) { + struct fake_glx_context *glxCtx = (struct fake_glx_context *) ctx; + XMesaContext xmctx = glxCtx->xmesaContext; + (void) dpy; (void) ctx; - (void) attribute; - (void) value; + + switch (attribute) { + case GLX_FBCONFIG_ID: + *value = xmctx->xm_visual->visinfo->visualid; + break; + case GLX_RENDER_TYPE: + if (xmctx->xm_visual->mesa_visual.rgbMode) + *value = GLX_RGBA_BIT; + else + *value = GLX_COLOR_INDEX_BIT; + break; + case GLX_SCREEN: + *value = 0; + return Success; + default: + return GLX_BAD_ATTRIBUTE; + } return 0; } @@ -1779,9 +2479,9 @@ Fake_glXQueryContext( Display *dpy, GLXContext ctx, int attribute, int *value ) static void Fake_glXSelectEvent( Display *dpy, GLXDrawable drawable, unsigned long mask ) { - (void) dpy; - (void) drawable; - (void) mask; + XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); + if (xmbuf) + xmbuf->selectedEvents = mask; } @@ -1789,14 +2489,16 @@ static void Fake_glXGetSelectedEvent( Display *dpy, GLXDrawable drawable, unsigned long *mask ) { - (void) dpy; - (void) drawable; - (void) mask; + XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); + if (xmbuf) + *mask = xmbuf->selectedEvents; + else + *mask = 0; } -#ifdef GLX_SGI_swap_control +/*** GLX_SGI_swap_control ***/ static int Fake_glXSwapIntervalSGI(int interval) @@ -1805,52 +2507,54 @@ Fake_glXSwapIntervalSGI(int interval) return 0; } -#endif -#ifdef GLX_SGI_video_sync +/*** GLX_SGI_video_sync ***/ + +static unsigned int FrameCounter = 0; static int Fake_glXGetVideoSyncSGI(unsigned int *count) { - (void) count; + /* this is a bogus implementation */ + *count = FrameCounter++; return 0; } static int Fake_glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count) { - (void) divisor; - (void) remainder; - (void) count; + if (divisor <= 0 || remainder < 0) + return GLX_BAD_VALUE; + /* this is a bogus implementation */ + FrameCounter++; + while (FrameCounter % divisor != remainder) + FrameCounter++; + *count = FrameCounter; return 0; } -#endif -#ifdef GLX_SGI_make_current_read +/*** GLX_SGI_make_current_read ***/ static Bool Fake_glXMakeCurrentReadSGI(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx) { - (void) dpy; - (void) draw; - (void) read; - (void) ctx; - return False; + return Fake_glXMakeContextCurrent( dpy, draw, read, ctx ); } +/* not used static GLXDrawable Fake_glXGetCurrentReadDrawableSGI(void) { return 0; } - -#endif +*/ -#if defined(_VL_H) && defined(GLX_SGIX_video_source) +/*** GLX_SGIX_video_source ***/ +#if defined(_VL_H) static GLXVideoSourceSGIX Fake_glXCreateGLXVideoSourceSGIX(Display *dpy, int screen, VLServer server, VLPath path, int nodeClass, VLNode drainNode) @@ -1874,7 +2578,7 @@ Fake_glXDestroyGLXVideoSourceSGIX(Display *dpy, GLXVideoSourceSGIX src) #endif -#ifdef GLX_EXT_import_context +/*** GLX_EXT_import_context ***/ static void Fake_glXFreeContextEXT(Display *dpy, GLXContext context) @@ -1890,12 +2594,6 @@ Fake_glXGetContextIDEXT(const GLXContext context) return 0; } -static Display * -Fake_glXGetCurrentDisplayEXT(void) -{ - return glXGetCurrentDisplay(); -} - static GLXContext Fake_glXImportContextEXT(Display *dpy, GLXContextID contextID) { @@ -1914,120 +2612,195 @@ Fake_glXQueryContextInfoEXT(Display *dpy, GLXContext context, int attribute, int return 0; } -#endif -#ifdef GLX_SGIX_fbconfig +/*** GLX_SGIX_fbconfig ***/ static int Fake_glXGetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config, int attribute, int *value) { - (void) dpy; - (void) config; - (void) attribute; - (void) value; - return 0; + return Fake_glXGetFBConfigAttrib(dpy, config, attribute, value); } static GLXFBConfigSGIX * Fake_glXChooseFBConfigSGIX(Display *dpy, int screen, int *attrib_list, int *nelements) { - (void) dpy; - (void) screen; - (void) attrib_list; - (void) nelements; - return 0; + return (GLXFBConfig *) Fake_glXChooseFBConfig(dpy, screen, attrib_list, nelements); } + static GLXPixmap Fake_glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, Pixmap pixmap) { - (void) dpy; - (void) config; - (void) pixmap; - return 0; + XMesaVisual xmvis = (XMesaVisual) config; + XMesaBuffer xmbuf = XMesaCreatePixmapBuffer(xmvis, pixmap, 0); + return xmbuf->frontxrb->pixmap; /* need to return an X ID */ } + static GLXContext Fake_glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct) { - (void) dpy; - (void) config; - (void) render_type; - (void) share_list; - (void) direct; - return 0; + XMesaVisual xmvis = (XMesaVisual) config; + struct fake_glx_context *glxCtx; + struct fake_glx_context *shareCtx = (struct fake_glx_context *) share_list; + + glxCtx = CALLOC_STRUCT(fake_glx_context); + if (!glxCtx) + return 0; + + /* deallocate unused windows/buffers */ + XMesaGarbageCollect(); + + glxCtx->xmesaContext = XMesaCreateContext(xmvis, + shareCtx ? shareCtx->xmesaContext : NULL); + if (!glxCtx->xmesaContext) { + _mesa_free(glxCtx); + return NULL; + } + + glxCtx->xmesaContext->direct = GL_FALSE; + glxCtx->glxContext.isDirect = GL_FALSE; + glxCtx->glxContext.currentDpy = dpy; + glxCtx->glxContext.xid = (XID) glxCtx; /* self pointer */ + + assert((void *) glxCtx == (void *) &(glxCtx->glxContext)); + + return (GLXContext) glxCtx; } + static XVisualInfo * Fake_glXGetVisualFromFBConfigSGIX(Display *dpy, GLXFBConfigSGIX config) { - (void) dpy; - (void) config; - return NULL; + return Fake_glXGetVisualFromFBConfig(dpy, config); } + static GLXFBConfigSGIX Fake_glXGetFBConfigFromVisualSGIX(Display *dpy, XVisualInfo *vis) { - (void) dpy; - (void) vis; - return 0; + XMesaVisual xmvis = find_glx_visual(dpy, vis); + if (!xmvis) { + /* This visual wasn't found with glXChooseVisual() */ + xmvis = create_glx_visual(dpy, vis); + } + + return (GLXFBConfigSGIX) xmvis; } -#endif -#ifdef GLX_SGIX_pbuffer +/*** GLX_SGIX_pbuffer ***/ static GLXPbufferSGIX -Fake_glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height, int *attrib_list) +Fake_glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config, + unsigned int width, unsigned int height, + int *attribList) { + XMesaVisual xmvis = (XMesaVisual) config; + XMesaBuffer xmbuf; + const int *attrib; + GLboolean useLargest = GL_FALSE, preserveContents = GL_FALSE; + (void) dpy; - (void) config; - (void) width; - (void) height; - (void) attrib_list; - return 0; + + for (attrib = attribList; attrib && *attrib; attrib++) { + switch (*attrib) { + case GLX_PRESERVED_CONTENTS_SGIX: + attrib++; + preserveContents = *attrib; /* ignored */ + break; + case GLX_LARGEST_PBUFFER_SGIX: + attrib++; + useLargest = *attrib; /* ignored */ + break; + default: + return 0; + } + } + + /* not used at this time */ + (void) useLargest; + (void) preserveContents; + + xmbuf = XMesaCreatePBuffer( xmvis, 0, width, height); + /* A GLXPbuffer handle must be an X Drawable because that's what + * glXMakeCurrent takes. + */ + return (GLXPbuffer) xmbuf->frontxrb->pixmap; } + static void Fake_glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf) { - (void) dpy; - (void) pbuf; + XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf); + if (xmbuf) { + XMesaDestroyBuffer(xmbuf); + } } + static int Fake_glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int *value) { - (void) dpy; - (void) pbuf; - (void) attribute; - (void) value; + const XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf); + + if (!xmbuf) { + /* Generate GLXBadPbufferSGIX for bad pbuffer */ + return 0; + } + + switch (attribute) { + case GLX_PRESERVED_CONTENTS_SGIX: + *value = True; + break; + case GLX_LARGEST_PBUFFER_SGIX: + *value = xmbuf->mesa_buffer.Width * xmbuf->mesa_buffer.Height; + break; + case GLX_WIDTH_SGIX: + *value = xmbuf->mesa_buffer.Width; + break; + case GLX_HEIGHT_SGIX: + *value = xmbuf->mesa_buffer.Height; + break; + case GLX_EVENT_MASK_SGIX: + *value = 0; /* XXX might be wrong */ + break; + default: + *value = 0; + } return 0; } + static void Fake_glXSelectEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long mask) { - (void) dpy; - (void) drawable; - (void) mask; + XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); + if (xmbuf) { + /* Note: we'll never generate clobber events */ + xmbuf->selectedEvents = mask; + } } + static void Fake_glXGetSelectedEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long *mask) { - (void) dpy; - (void) drawable; - (void) mask; + XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); + if (xmbuf) { + *mask = xmbuf->selectedEvents; + } + else { + *mask = 0; + } } -#endif -#ifdef GLX_SGI_cushion +/*** GLX_SGI_cushion ***/ static void Fake_glXCushionSGI(Display *dpy, Window win, float cushion) @@ -2037,10 +2810,9 @@ Fake_glXCushionSGI(Display *dpy, Window win, float cushion) (void) cushion; } -#endif -#ifdef GLX_SGIX_video_resize +/*** GLX_SGIX_video_resize ***/ static int Fake_glXBindChannelToWindowSGIX(Display *dpy, int screen, int channel , Window window) @@ -2101,11 +2873,11 @@ Fake_glXChannelRectSyncSGIX(Display *dpy, int screen, int channel, GLenum syncty return 0; } -#endif -#if defined(_DM_BUFFER_H_) && defined(GLX_SGIX_dmbuffer) +/*** GLX_SGIX_dmbuffer **/ +#if defined(_DM_BUFFER_H_) static Bool Fake_glXAssociateDMPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuffer, DMparams *params, DMbuffer dmbuffer) { @@ -2115,11 +2887,10 @@ Fake_glXAssociateDMPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuffer, DMparams *p (void) dmbuffer; return False; } - #endif -#ifdef GLX_SGIX_swap_group +/*** GLX_SGIX_swap_group ***/ static void Fake_glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable, GLXDrawable member) @@ -2129,10 +2900,9 @@ Fake_glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable, GLXDrawable member (void) member; } -#endif -#ifdef GLX_SGIX_swap_barrier +/*** GLX_SGIX_swap_barrier ***/ static void Fake_glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable, int barrier) @@ -2151,10 +2921,9 @@ Fake_glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max) return False; } -#endif -#ifdef GLX_SUN_get_transparent_index +/*** GLX_SUN_get_transparent_index ***/ static Status Fake_glXGetTransparentIndexSUN(Display *dpy, Window overlay, Window underlay, long *pTransparent) @@ -2166,10 +2935,10 @@ Fake_glXGetTransparentIndexSUN(Display *dpy, Window overlay, Window underlay, lo return 0; } -#endif -#ifdef GLX_MESA_release_buffers +/*** GLX_MESA_release_buffers ***/ + /* * Release the depth, stencil, accum buffers attached to a GLXDrawable * (a window or pixmap) prior to destroying the GLXDrawable. @@ -2184,23 +2953,84 @@ Fake_glXReleaseBuffersMESA( Display *dpy, GLXDrawable d ) } return False; } -#endif -#ifdef GLX_MESA_set_3dfx_mode +/*** GLX_MESA_set_3dfx_mode ***/ + static Bool Fake_glXSet3DfxModeMESA( int mode ) { return XMesaSetFXmode( mode ); } -#endif +/*** GLX_NV_vertex_array range ***/ +static void * +Fake_glXAllocateMemoryNV( GLsizei size, + GLfloat readFrequency, + GLfloat writeFrequency, + GLfloat priority ) +{ + (void) size; + (void) readFrequency; + (void) writeFrequency; + (void) priority; + return NULL; +} + + +static void +Fake_glXFreeMemoryNV( GLvoid *pointer ) +{ + (void) pointer; +} + + +/*** GLX_MESA_agp_offset ***/ + +static GLuint +Fake_glXGetAGPOffsetMESA( const GLvoid *pointer ) +{ + (void) pointer; + return ~0; +} + +/*** GLX_EXT_texture_from_pixmap ***/ + +static void +Fake_glXBindTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer, + const int *attrib_list) +{ + XMesaBuffer b = XMesaFindBuffer(dpy, drawable); + if (b) + XMesaBindTexImage(dpy, b, buffer, attrib_list); +} + +static void +Fake_glXReleaseTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer) +{ + XMesaBuffer b = XMesaFindBuffer(dpy, drawable); + if (b) + XMesaReleaseTexImage(dpy, b, buffer); +} + + +/* silence warning */ extern struct _glxapi_table *_mesa_GetGLXDispatchTable(void); -struct _glxapi_table *_mesa_GetGLXDispatchTable(void) + + +/** + * Create a new GLX API dispatch table with its function pointers + * initialized to point to Mesa's "fake" GLX API functions. + * Note: there's a similar function (_real_GetGLXDispatchTable) that + * returns a new dispatch table with all pointers initalized to point + * to "real" GLX functions (which understand GLX wire protocol, etc). + */ +struct _glxapi_table * +_mesa_GetGLXDispatchTable(void) { static struct _glxapi_table glx; @@ -2233,17 +3063,15 @@ struct _glxapi_table *_mesa_GetGLXDispatchTable(void) glx.WaitGL = Fake_glXWaitGL; glx.WaitX = Fake_glXWaitX; -#ifdef GLX_VERSION_1_1 + /*** GLX_VERSION_1_1 ***/ glx.GetClientString = Fake_glXGetClientString; glx.QueryExtensionsString = Fake_glXQueryExtensionsString; glx.QueryServerString = Fake_glXQueryServerString; -#endif -#ifdef GLX_VERSION_1_2 + /*** GLX_VERSION_1_2 ***/ /*glx.GetCurrentDisplay = Fake_glXGetCurrentDisplay;*/ -#endif -#ifdef GLX_VERSION_1_3 + /*** GLX_VERSION_1_3 ***/ glx.ChooseFBConfig = Fake_glXChooseFBConfig; glx.CreateNewContext = Fake_glXCreateNewContext; glx.CreatePbuffer = Fake_glXCreatePbuffer; @@ -2261,96 +3089,93 @@ struct _glxapi_table *_mesa_GetGLXDispatchTable(void) glx.QueryContext = Fake_glXQueryContext; glx.QueryDrawable = Fake_glXQueryDrawable; glx.SelectEvent = Fake_glXSelectEvent; -#endif -#ifdef GLX_SGI_swap_control + /*** GLX_SGI_swap_control ***/ glx.SwapIntervalSGI = Fake_glXSwapIntervalSGI; -#endif -#ifdef GLX_SGI_video_sync + /*** GLX_SGI_video_sync ***/ glx.GetVideoSyncSGI = Fake_glXGetVideoSyncSGI; glx.WaitVideoSyncSGI = Fake_glXWaitVideoSyncSGI; -#endif -#ifdef GLX_SGI_make_current_read + /*** GLX_SGI_make_current_read ***/ glx.MakeCurrentReadSGI = Fake_glXMakeCurrentReadSGI; - glx.GetCurrentReadDrawableSGI = Fake_glXGetCurrentReadDrawableSGI; -#endif + /*glx.GetCurrentReadDrawableSGI = Fake_glXGetCurrentReadDrawableSGI;*/ -#if defined(_VL_H) && defined(GLX_SGIX_video_source) +/*** GLX_SGIX_video_source ***/ +#if defined(_VL_H) glx.CreateGLXVideoSourceSGIX = Fake_glXCreateGLXVideoSourceSGIX; glx.DestroyGLXVideoSourceSGIX = Fake_glXDestroyGLXVideoSourceSGIX; #endif -#ifdef GLX_EXT_import_context + /*** GLX_EXT_import_context ***/ glx.FreeContextEXT = Fake_glXFreeContextEXT; glx.GetContextIDEXT = Fake_glXGetContextIDEXT; - glx.GetCurrentDisplayEXT = Fake_glXGetCurrentDisplayEXT; + /*glx.GetCurrentDisplayEXT = Fake_glXGetCurrentDisplayEXT;*/ glx.ImportContextEXT = Fake_glXImportContextEXT; glx.QueryContextInfoEXT = Fake_glXQueryContextInfoEXT; -#endif -#ifdef GLX_SGIX_fbconfig + /*** GLX_SGIX_fbconfig ***/ glx.GetFBConfigAttribSGIX = Fake_glXGetFBConfigAttribSGIX; glx.ChooseFBConfigSGIX = Fake_glXChooseFBConfigSGIX; glx.CreateGLXPixmapWithConfigSGIX = Fake_glXCreateGLXPixmapWithConfigSGIX; glx.CreateContextWithConfigSGIX = Fake_glXCreateContextWithConfigSGIX; glx.GetVisualFromFBConfigSGIX = Fake_glXGetVisualFromFBConfigSGIX; glx.GetFBConfigFromVisualSGIX = Fake_glXGetFBConfigFromVisualSGIX; -#endif -#ifdef GLX_SGIX_pbuffer + /*** GLX_SGIX_pbuffer ***/ glx.CreateGLXPbufferSGIX = Fake_glXCreateGLXPbufferSGIX; glx.DestroyGLXPbufferSGIX = Fake_glXDestroyGLXPbufferSGIX; glx.QueryGLXPbufferSGIX = Fake_glXQueryGLXPbufferSGIX; glx.SelectEventSGIX = Fake_glXSelectEventSGIX; glx.GetSelectedEventSGIX = Fake_glXGetSelectedEventSGIX; -#endif -#ifdef GLX_SGI_cushion + /*** GLX_SGI_cushion ***/ glx.CushionSGI = Fake_glXCushionSGI; -#endif -#ifdef GLX_SGIX_video_resize + /*** GLX_SGIX_video_resize ***/ glx.BindChannelToWindowSGIX = Fake_glXBindChannelToWindowSGIX; glx.ChannelRectSGIX = Fake_glXChannelRectSGIX; glx.QueryChannelRectSGIX = Fake_glXQueryChannelRectSGIX; glx.QueryChannelDeltasSGIX = Fake_glXQueryChannelDeltasSGIX; glx.ChannelRectSyncSGIX = Fake_glXChannelRectSyncSGIX; -#endif -#if defined(_DM_BUFFER_H_) && defined(GLX_SGIX_dmbuffer) + /*** GLX_SGIX_dmbuffer **/ +#if defined(_DM_BUFFER_H_) glx.AssociateDMPbufferSGIX = NULL; #endif -#ifdef GLX_SGIX_swap_group + /*** GLX_SGIX_swap_group ***/ glx.JoinSwapGroupSGIX = Fake_glXJoinSwapGroupSGIX; -#endif -#ifdef GLX_SGIX_swap_barrier + /*** GLX_SGIX_swap_barrier ***/ glx.BindSwapBarrierSGIX = Fake_glXBindSwapBarrierSGIX; glx.QueryMaxSwapBarriersSGIX = Fake_glXQueryMaxSwapBarriersSGIX; -#endif -#ifdef GLX_SUN_get_transparent_index + /*** GLX_SUN_get_transparent_index ***/ glx.GetTransparentIndexSUN = Fake_glXGetTransparentIndexSUN; -#endif -#ifdef GLX_MESA_copy_sub_buffer + /*** GLX_MESA_copy_sub_buffer ***/ glx.CopySubBufferMESA = Fake_glXCopySubBufferMESA; -#endif -#ifdef GLX_MESA_release_buffers + /*** GLX_MESA_release_buffers ***/ glx.ReleaseBuffersMESA = Fake_glXReleaseBuffersMESA; -#endif -#ifdef GLX_MESA_pixmap_colormap + /*** GLX_MESA_pixmap_colormap ***/ glx.CreateGLXPixmapMESA = Fake_glXCreateGLXPixmapMESA; -#endif -#ifdef GLX_MESA_set_3dfx_mode + /*** GLX_MESA_set_3dfx_mode ***/ glx.Set3DfxModeMESA = Fake_glXSet3DfxModeMESA; -#endif + + /*** GLX_NV_vertex_array_range ***/ + glx.AllocateMemoryNV = Fake_glXAllocateMemoryNV; + glx.FreeMemoryNV = Fake_glXFreeMemoryNV; + + /*** GLX_MESA_agp_offset ***/ + glx.GetAGPOffsetMESA = Fake_glXGetAGPOffsetMESA; + + /*** GLX_EXT_texture_from_pixmap ***/ + glx.BindTexImageEXT = Fake_glXBindTexImageEXT; + glx.ReleaseTexImageEXT = Fake_glXReleaseTexImageEXT; return &glx; }