From 2702c90d7a39fca2a3319c5e915fd290cb31fc70 Mon Sep 17 00:00:00 2001 From: Radosław Kujawa Date: Fri, 17 Jul 2026 14:54:32 +0200 Subject: Initial import. --- src/mesa/drivers/x11/descrip.mms | 50 + src/mesa/drivers/x11/fakeglx.c | 2929 +++++++++++++++++++++++ src/mesa/drivers/x11/glxapi.c | 1343 +++++++++++ src/mesa/drivers/x11/glxapi.h | 236 ++ src/mesa/drivers/x11/glxheader.h | 71 + src/mesa/drivers/x11/realglx.c | 185 ++ src/mesa/drivers/x11/realglx.h | 326 +++ src/mesa/drivers/x11/xfonts.c | 377 +++ src/mesa/drivers/x11/xfonts.h | 41 + src/mesa/drivers/x11/xm_api.c | 2676 +++++++++++++++++++++ src/mesa/drivers/x11/xm_dd.c | 1220 ++++++++++ src/mesa/drivers/x11/xm_line.c | 617 +++++ src/mesa/drivers/x11/xm_span.c | 4777 ++++++++++++++++++++++++++++++++++++++ src/mesa/drivers/x11/xm_tri.c | 1609 +++++++++++++ src/mesa/drivers/x11/xmesaP.h | 531 +++++ 15 files changed, 16988 insertions(+) create mode 100644 src/mesa/drivers/x11/descrip.mms create mode 100644 src/mesa/drivers/x11/fakeglx.c create mode 100644 src/mesa/drivers/x11/glxapi.c create mode 100644 src/mesa/drivers/x11/glxapi.h create mode 100644 src/mesa/drivers/x11/glxheader.h create mode 100644 src/mesa/drivers/x11/realglx.c create mode 100644 src/mesa/drivers/x11/realglx.h create mode 100644 src/mesa/drivers/x11/xfonts.c create mode 100644 src/mesa/drivers/x11/xfonts.h create mode 100644 src/mesa/drivers/x11/xm_api.c create mode 100644 src/mesa/drivers/x11/xm_dd.c create mode 100644 src/mesa/drivers/x11/xm_line.c create mode 100644 src/mesa/drivers/x11/xm_span.c create mode 100644 src/mesa/drivers/x11/xm_tri.c create mode 100644 src/mesa/drivers/x11/xmesaP.h (limited to 'src/mesa/drivers/x11') diff --git a/src/mesa/drivers/x11/descrip.mms b/src/mesa/drivers/x11/descrip.mms new file mode 100644 index 0000000..ffac99f --- /dev/null +++ b/src/mesa/drivers/x11/descrip.mms @@ -0,0 +1,50 @@ +# Makefile for core library for VMS +# contributed by Jouk Jansen joukj@hrem.stm.tudelft.nl +# Last revision : 16 June 2003 + +.first + define gl [----.include.gl] + define math [--.math] + define tnl [--.tnl] + define swrast [--.swrast] + define swrast_setup [--.swrast_setup] + define array_cache [--.array_cache] + define drivers [-] + +.include [----]mms-config. + +##### MACROS ##### + +VPATH = RCS + +INCDIR = [----.include],[--.main],[--.glapi] +LIBDIR = [----.lib] +CFLAGS = /include=($(INCDIR),[])/define=(PTHREADS=1)/name=(as_is,short) + +SOURCES = fakeglx.c glxapi.c xfonts.c xm_api.c xm_dd.c xm_line.c xm_span.c\ + xm_tri.c + +OBJECTS =fakeglx.obj,glxapi.obj,xfonts.obj,xm_api.obj,xm_dd.obj,xm_line.obj,\ + xm_span.obj,xm_tri.obj + +##### RULES ##### + +VERSION=Mesa V3.4 + +##### TARGETS ##### +# Make the library +$(LIBDIR)$(GL_LIB) : $(OBJECTS) + @ library $(LIBDIR)$(GL_LIB) $(OBJECTS) + +clean : + purge + delete *.obj;* + +fakeglx.obj : fakeglx.c +glxapi.obj : glxapi.c +xfonts.obj : xfonts.c +xm_api.obj : xm_api.c +xm_dd.obj : xm_dd.c +xm_line.obj : xm_line.c +xm_span.obj : xm_span.c +xm_tri.obj : xm_tri.c diff --git a/src/mesa/drivers/x11/fakeglx.c b/src/mesa/drivers/x11/fakeglx.c new file mode 100644 index 0000000..fd7861f --- /dev/null +++ b/src/mesa/drivers/x11/fakeglx.c @@ -0,0 +1,2929 @@ +/* + * Mesa 3-D graphics library + * Version: 6.2.2 + * + * Copyright (C) 1999-2005 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. + */ + + +/* + * This is an emulation of the GLX API which allows Mesa/GLX-based programs + * to run on X servers which do not have the real GLX extension. + * + * Thanks to the contributors: + * + * Initial version: Philip Brown (phil@bolthole.com) + * Better glXGetConfig() support: Armin Liebchen (liebchen@asylum.cs.utah.edu) + * Further visual-handling refinements: Wolfram Gloger + * (wmglo@Dent.MED.Uni-Muenchen.DE). + * + * Notes: + * Don't be fooled, stereo isn't supported yet. + */ + + + +#include "glxheader.h" +#include "glxapi.h" +#include "GL/xmesa.h" +#include "context.h" +#include "config.h" +#include "macros.h" +#include "imports.h" +#include "mtypes.h" +#include "version.h" +#include "xfonts.h" +#include "xmesaP.h" + + +/* This indicates the client-side GLX API and GLX encoder version. */ +#define CLIENT_MAJOR_VERSION 1 +#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.4 indicates OpenGL 1.3 support + */ +#define SERVER_MAJOR_VERSION 1 +#define SERVER_MINOR_VERSION 4 + +/* This is appended onto the glXGetClient/ServerString version strings. */ +#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_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; +}; + + + +/**********************************************************************/ +/*** GLX Visual Code ***/ +/**********************************************************************/ + +#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;ioverlay_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 accumRedSize, GLint accumGreenSize, + GLint accumBlueSize, GLint accumAlphaSize, + GLint level, GLint numAuxBuffers ) +{ + GLboolean ximageFlag = GL_TRUE; + XMesaVisual xmvis; + GLint i; + GLboolean comparePointers; + + if (dbFlag) { + /* Check if the MESA_BACK_BUFFER env var is set */ + char *backbuffer = _mesa_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 { + _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 (_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->mesa_visual.level == level + && v->mesa_visual.numAuxBuffers == numAuxBuffers + && v->ximage_flag == ximageFlag + && 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)) { + return v; + } + } + } + + /* Create a new visual and add it to the list. */ + + if (NumVisuals >= MAX_VISUALS) { + _mesa_problem(NULL, "GLX Error: maximum number of visuals exceeded"); + return NULL; + } + + xmvis = XMesaCreateVisual( dpy, vinfo, rgbFlag, alphaFlag, dbFlag, + stereoFlag, ximageFlag, + depth_size, stencil_size, + accumRedSize, accumBlueSize, + 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; + /* 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; +} + + + +/* + * Create a GLX visual from a regular XVisualInfo. + * This is called when Fake GLX is given an XVisualInfo which wasn't + * returned by glXChooseVisual. Since this is the first time we're + * considering this visual we'll take a guess at reasonable values + * for depth buffer size, stencil size, accum size, etc. + * This is the best we can do with a client-side emulation of GLX. + */ +static XMesaVisual +create_glx_visual( Display *dpy, XVisualInfo *visinfo ) +{ + int vislevel; + GLint zBits = default_depth_bits(); + + 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,0,0,0, /* accum bits */ + vislevel, /* level */ + 0 /* numAux */ + ); + } + else if (is_usable_visual( visinfo )) { + 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 */ + zBits, + 8 * sizeof(GLstencil), + 0 * sizeof(GLaccum), /* r */ + 0 * sizeof(GLaccum), /* g */ + 0 * sizeof(GLaccum), /* b */ + 0 * sizeof(GLaccum), /* a */ + 0, /* level */ + 0 /* numAux */ + ); + } + else { + /* 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 */ + zBits, + 8 * sizeof(GLstencil), + 8 * sizeof(GLaccum), /* r */ + 8 * sizeof(GLaccum), /* g */ + 8 * sizeof(GLaccum), /* b */ + 8 * sizeof(GLaccum), /* a */ + 0, /* level */ + 0 /* numAux */ + ); + } + } + else { + _mesa_warning(NULL, "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; + + /* try to match visual id */ + for (i=0;idisplay==dpy + && VisualTable[i]->visinfo->visualid == vinfo->visualid) { + return VisualTable[i]; + } + } + + /* if that fails, try to match pointers */ + for (i=0;idisplay==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 ) +{ + 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;ioverlay_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; +} + + + +/* + * 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 (_mesa_bitcount((GLuint) vis->red_mask ) <= 8 && + _mesa_bitcount((GLuint) vis->green_mask) <= 8 && + _mesa_bitcount((GLuint) 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 (!_mesa_getenv( varname )) { + return NULL; + } + + _mesa_strncpy( value, _mesa_getenv(varname), 100 ); + value[99] = 0; + + sscanf( value, "%s %d", type, &depth ); + + 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 ); + if (vis) { + return vis; + } + } + + _mesa_warning(NULL, "GLX unable to find visual class=%s, depth=%d.", + 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 = 0; + 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, 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; + + /*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;ilayer!=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 RGB was requested, make sure we have True/DirectColor */ + if (rgbFlag && vislist->CLASS != TrueColor + && vislist->CLASS != DirectColor) + continue; + + /* if CI was requested, make sure we have a color indexed visual */ + if (!rgbFlag + && (vislist->CLASS == TrueColor || vislist->CLASS == DirectColor)) + continue; + + if (deepvis==NULL || vislist->depth > deepest) { + /* YES! found a satisfactory visual */ + if (deepvis) { + XFree( 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; +} + + +/**********************************************************************/ +/*** Begin Fake GLX API Functions ***/ +/**********************************************************************/ + + +static XMesaVisual +choose_visual( Display *dpy, int screen, const int *list, GLboolean fbConfig ) +{ + 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 = rgbModeDefault; + GLboolean alpha_flag = GL_FALSE; + GLboolean double_flag = GL_FALSE; + GLboolean stereo_flag = GL_FALSE; + GLint depth_size = 0; + GLint stencil_size = 0; + GLint accumRedSize = 0; + GLint accumGreenSize = 0; + GLint accumBlueSize = 0; + GLint accumAlphaSize = 0; + int level = 0; + int visual_type = DONT_CARE; + 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; + + while (*parselist) { + + switch (*parselist) { + case GLX_USE_GL: + if (fbConfig) { + /* invalid token */ + return NULL; + } + else { + /* skip */ + parselist++; + } + break; + case GLX_BUFFER_SIZE: + parselist++; + min_ci = *parselist++; + break; + case GLX_LEVEL: + parselist++; + level = *parselist++; + break; + case GLX_RGBA: + if (fbConfig) { + /* invalid token */ + return NULL; + } + else { + rgb_flag = GL_TRUE; + parselist++; + } + break; + case GLX_DOUBLEBUFFER: + parselist++; + if (fbConfig) { + double_flag = *parselist++; + } + else { + double_flag = GL_TRUE; + } + break; + case GLX_STEREO: + parselist++; + if (fbConfig) { + stereo_flag = *parselist++; + } + else { + stereo_flag = GL_TRUE; + } + return NULL; /* stereo not supported */ + case GLX_AUX_BUFFERS: + parselist++; + numAux = *parselist++; + if (numAux > MAX_AUX_BUFFERS) + return NULL; + 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: + parselist++; + { + GLint size = *parselist++; + accumRedSize = MAX2( accumRedSize, size ); + } + break; + case GLX_ACCUM_GREEN_SIZE: + parselist++; + { + GLint size = *parselist++; + accumGreenSize = MAX2( accumGreenSize, size ); + } + break; + case GLX_ACCUM_BLUE_SIZE: + parselist++; + { + GLint size = *parselist++; + accumBlueSize = MAX2( accumBlueSize, size ); + } + break; + case GLX_ACCUM_ALPHA_SIZE: + parselist++; + { + GLint size = *parselist++; + accumAlphaSize = MAX2( accumAlphaSize, 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; + + /* + * GLX_EXT_visual_info extension + */ + case GLX_VISUAL_CAVEAT_EXT: + parselist++; + 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: + 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: + parselist++; + if (*parselist & ~(GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT)) { + return NULL; /* bad bit */ + } + parselist++; + break; + case GLX_FBCONFIG_ID: + parselist++; + desiredVisualID = *parselist; + break; + + 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 + * 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 (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 */ + 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 ); + accumRedSize = accumGreenSize = accumBlueSize = accumAlphaSize = 0; + } + } + else { + /* over/underlay planes */ + if (rgb_flag) { + /* rgba overlay */ + 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_overlay_visual( dpy, screen, rgb_flag, level, + trans_type, trans_value, min_rgb, visual_type ); + } + else { + /* color index overlay */ + vis = choose_x_overlay_visual( dpy, screen, rgb_flag, level, + trans_type, trans_value, min_ci, visual_type ); + } + } + + if (vis) { + /* Note: we're not exactly obeying the glXChooseVisual rules here. + * When GLX_DEPTH_SIZE = 1 is specified we're supposed to choose the + * largest depth buffer size, which is 32bits/value. Instead, we + * return 16 to maintain performance with earlier versions of Mesa. + */ + if (depth_size > 24) + depth_size = 31; /* 32 causes int overflow problems */ + else if (depth_size > 16) + depth_size = 24; + else if (depth_size > 0) { + depth_size = default_depth_bits(); + } + + /* we only support one size of stencil and accum buffers. */ + if (stencil_size > 0) + stencil_size = STENCIL_BITS; + if (accumRedSize > 0 || accumGreenSize > 0 || accumBlueSize > 0 || + accumAlphaSize > 0) { + accumRedSize = ACCUM_BITS; + accumGreenSize = ACCUM_BITS; + accumBlueSize = ACCUM_BITS; + accumAlphaSize = alpha_flag ? ACCUM_BITS : 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 xmvis; +} + + +static XVisualInfo * +Fake_glXChooseVisual( Display *dpy, int screen, int *list ) +{ + XMesaVisual 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 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 */ + XMesaGarbageCollect(); + + xmvis = find_glx_visual( dpy, visinfo ); + if (!xmvis) { + /* This visual wasn't found with glXChooseVisual() */ + xmvis = create_glx_visual( dpy, visinfo ); + if (!xmvis) { + /* unusable visual */ + FREE(glxCtx); + return NULL; + } + } + + glxCtx->xmesaContext = XMesaCreateContext(xmvis, + shareCtx ? shareCtx->xmesaContext : NULL); + if (!glxCtx->xmesaContext) { + 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; +} + + +/* 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 = glxCtx->xmesaContext; + + /* Find the XMesaBuffer which corresponds to the GLXDrawable 'draw' */ + if (ctx == MakeCurrent_PrevContext + && draw == MakeCurrent_PrevDrawable) { + drawBuffer = MakeCurrent_PrevDrawBuffer; + } + else { + drawBuffer = XMesaFindBuffer( dpy, draw ); + } + if (!drawBuffer) { + /* drawable must be a new window! */ + drawBuffer = XMesaCreateWindowBuffer2( xmctx->xm_visual, draw, xmctx); + if (!drawBuffer) { + /* Out of memory, or context/drawable depth mismatch */ + return False; + } + } + + /* Find the XMesaBuffer which corresponds to the GLXDrawable 'read' */ + if (ctx == MakeCurrent_PrevContext + && read == MakeCurrent_PrevReadable) { + readBuffer = MakeCurrent_PrevReadBuffer; + } + else { + readBuffer = XMesaFindBuffer( dpy, read ); + } + if (!readBuffer) { + /* drawable must be a new window! */ + readBuffer = XMesaCreateWindowBuffer2(glxCtx->xmesaContext->xm_visual, + read, xmctx); + if (!readBuffer) { + /* Out of memory, or context/drawable depth mismatch */ + return False; + } + } + + MakeCurrent_PrevContext = ctx; + MakeCurrent_PrevDrawable = draw; + MakeCurrent_PrevReadable = read; + MakeCurrent_PrevDrawBuffer = drawBuffer; + MakeCurrent_PrevReadBuffer = readBuffer; + + /* Now make current! */ + if (XMesaMakeCurrent2(xmctx, drawBuffer, readBuffer)) { + ((__GLXcontext *) ctx)->currentDpy = dpy; + ((__GLXcontext *) ctx)->currentDrawable = draw; +#ifndef GLX_BUILT_IN_XMESA + ((__GLXcontext *) ctx)->currentReadable = read; +#else + __glXSetCurrentContext(ctx); +#endif + return True; + } + else { + return False; + } + } + else if (!ctx && !draw && !read) { + /* release current context w/out assigning new one. */ + XMesaMakeCurrent( NULL, NULL ); + MakeCurrent_PrevContext = 0; + MakeCurrent_PrevDrawable = 0; + MakeCurrent_PrevReadable = 0; + MakeCurrent_PrevDrawBuffer = 0; + MakeCurrent_PrevReadBuffer = 0; +#ifdef GLX_BUILT_IN_XMESA + /* XXX bind dummy context with __glXSetCurrentContext(ctx); */ +#endif + return True; + } + else { + /* The args must either all be non-zero or all zero. + * This is an error. + */ + return False; + } +} + + +static Bool +Fake_glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx ) +{ + return Fake_glXMakeContextCurrent( dpy, drawable, drawable, ctx ); +} + + +static 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; +} + + +/*** GLX_MESA_pixmap_colormap ***/ + +static 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; +} + + +static void +Fake_glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap ) +{ + XMesaBuffer b = XMesaFindBuffer(dpy, pixmap); + if (b) { + XMesaDestroyBuffer(b); + } + 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 ) +{ + 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->mesa), &(xm_dst->mesa), (GLuint) mask ); +} + + +static 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; +} + + +extern void _kw_ungrab_all( Display *dpy ); +void _kw_ungrab_all( Display *dpy ) +{ + XUngrabPointer( dpy, CurrentTime ); + XUngrabKeyboard( dpy, CurrentTime ); +} + + +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( glxCtx->xmesaContext ); + XMesaGarbageCollect(); +} + + +static Bool +Fake_glXIsDirect( Display *dpy, GLXContext ctx ) +{ + struct fake_glx_context *glxCtx = (struct fake_glx_context *) ctx; + (void) dpy; + return glxCtx->xmesaContext->direct; +} + + + +static void +Fake_glXSwapBuffers( Display *dpy, GLXDrawable drawable ) +{ + XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable ); + + if (buffer) { + XMesaSwapBuffers(buffer); + } + else if (_mesa_getenv("MESA_DEBUG")) { + _mesa_warning(NULL, "Mesa: glXSwapBuffers: invalid drawable\n"); + } +} + + + +/*** GLX_MESA_copy_sub_buffer ***/ + +static 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 (_mesa_getenv("MESA_DEBUG")) { + _mesa_warning(NULL, "Mesa: glXCopySubBufferMESA: invalid drawable\n"); + } +} + + +static Bool +Fake_glXQueryVersion( Display *dpy, int *maj, int *min ) +{ + (void) dpy; + /* Return GLX version, not Mesa version */ + assert(CLIENT_MAJOR_VERSION == SERVER_MAJOR_VERSION); + *maj = CLIENT_MAJOR_VERSION; + *min = MIN2( CLIENT_MINOR_VERSION, SERVER_MINOR_VERSION ); + return True; +} + + +/* + * Query the GLX attributes of the given XVisualInfo. + */ +static int +get_config( XMesaVisual xmvis, int attrib, int *value, GLboolean fbconfig ) +{ + ASSERT(xmvis); + switch(attrib) { + case GLX_USE_GL: + if (fbconfig) + return GLX_BAD_ATTRIBUTE; + *value = (int) True; + return 0; + case GLX_BUFFER_SIZE: + *value = xmvis->visinfo->depth; + return 0; + case GLX_LEVEL: + *value = xmvis->mesa_visual.level; + return 0; + case GLX_RGBA: + if (fbconfig) + return GLX_BAD_ATTRIBUTE; + if (xmvis->mesa_visual.rgbMode) { + *value = True; + } + else { + *value = False; + } + return 0; + case GLX_DOUBLEBUFFER: + *value = (int) xmvis->mesa_visual.doubleBufferMode; + return 0; + case GLX_STEREO: + *value = (int) xmvis->mesa_visual.stereoMode; + return 0; + case GLX_AUX_BUFFERS: + *value = xmvis->mesa_visual.numAuxBuffers; + return 0; + case GLX_RED_SIZE: + *value = xmvis->mesa_visual.redBits; + return 0; + case GLX_GREEN_SIZE: + *value = xmvis->mesa_visual.greenBits; + return 0; + case GLX_BLUE_SIZE: + *value = xmvis->mesa_visual.blueBits; + return 0; + case GLX_ALPHA_SIZE: + *value = xmvis->mesa_visual.alphaBits; + return 0; + case GLX_DEPTH_SIZE: + *value = xmvis->mesa_visual.depthBits; + return 0; + case GLX_STENCIL_SIZE: + *value = xmvis->mesa_visual.stencilBits; + return 0; + case GLX_ACCUM_RED_SIZE: + *value = xmvis->mesa_visual.accumRedBits; + return 0; + case GLX_ACCUM_GREEN_SIZE: + *value = xmvis->mesa_visual.accumGreenBits; + return 0; + case GLX_ACCUM_BLUE_SIZE: + *value = xmvis->mesa_visual.accumBlueBits; + return 0; + case GLX_ACCUM_ALPHA_SIZE: + *value = xmvis->mesa_visual.accumAlphaBits; + return 0; + + /* + * GLX_EXT_visual_info extension + */ + case GLX_X_VISUAL_TYPE_EXT: + 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; + 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 (xmvis->mesa_visual.level==0) { + /* normal planes */ + *value = GLX_NONE_EXT; + } + else if (xmvis->mesa_visual.level>0) { + /* overlay */ + if (xmvis->mesa_visual.rgbMode) { + *value = GLX_TRANSPARENT_RGB_EXT; + } + else { + *value = GLX_TRANSPARENT_INDEX_EXT; + } + } + else if (xmvis->mesa_visual.level<0) { + /* underlay */ + *value = GLX_NONE_EXT; + } + return 0; + case GLX_TRANSPARENT_INDEX_VALUE_EXT: + { + int pixel = transparent_pixel( xmvis ); + 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; + + /* + * GLX_EXT_visual_info extension + */ + case GLX_VISUAL_CAVEAT_EXT: + /* test for zero, just in case */ + if (xmvis->mesa_visual.visualRating > 0) + *value = xmvis->mesa_visual.visualRating; + else + *value = GLX_NONE_EXT; + return 0; + + /* + * 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; + + default: + return GLX_BAD_ATTRIBUTE; + } + return Success; +} + + +static int +Fake_glXGetConfig( Display *dpy, XVisualInfo *visinfo, + int attrib, int *value ) +{ + XMesaVisual xmvis; + + 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; + } + } + } + + return get_config(xmvis, attrib, value, GL_FALSE); +} + + +static void +Fake_glXWaitGL( void ) +{ + XMesaContext xmesa = XMesaGetCurrentContext(); + XMesaFlush( xmesa ); +} + + + +static void +Fake_glXWaitX( void ) +{ + XMesaContext xmesa = XMesaGetCurrentContext(); + XMesaFlush( xmesa ); +} + + +static const char * +get_extensions( void ) +{ +#ifdef FX + const char *fx = _mesa_getenv("MESA_GLX_FX"); + if (fx && fx[0] != 'd') { + return EXTENSIONS; + } +#endif + return EXTENSIONS + 23; /* skip "GLX_MESA_set_3dfx_mode" */ +} + + + +/* GLX 1.1 and later */ +static const char * +Fake_glXQueryExtensionsString( Display *dpy, int screen ) +{ + (void) dpy; + (void) screen; + return get_extensions(); +} + + + +/* GLX 1.1 and later */ +static const char * +Fake_glXQueryServerString( Display *dpy, int screen, int name ) +{ + static char version[1000]; + _mesa_sprintf(version, "%d.%d %s", + SERVER_MAJOR_VERSION, SERVER_MINOR_VERSION, MESA_GLX_VERSION); + + (void) dpy; + (void) screen; + + switch (name) { + case GLX_EXTENSIONS: + return get_extensions(); + case GLX_VENDOR: + return VENDOR; + case GLX_VERSION: + return version; + default: + return NULL; + } +} + + + +/* GLX 1.1 and later */ +static const char * +Fake_glXGetClientString( Display *dpy, int name ) +{ + static char version[1000]; + _mesa_sprintf(version, "%d.%d %s", CLIENT_MAJOR_VERSION, + CLIENT_MINOR_VERSION, MESA_GLX_VERSION); + + (void) dpy; + + switch (name) { + case GLX_EXTENSIONS: + return get_extensions(); + case GLX_VENDOR: + return VENDOR; + case GLX_VERSION: + return version; + default: + return NULL; + } +} + + + +/* + * GLX 1.3 and later + */ + + +static int +Fake_glXGetFBConfigAttrib( Display *dpy, GLXFBConfig config, + int attribute, int *value ) +{ + XMesaVisual v = (XMesaVisual) config; + (void) dpy; + (void) config; + + if (!dpy || !config || !value) + return -1; + + return get_config(v, attribute, value, GL_TRUE); +} + + +static GLXFBConfig * +Fake_glXGetFBConfigs( Display *dpy, int screen, int *nelements ) +{ + 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 ) +{ + 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; + } +} + + +static GLXWindow +Fake_glXCreateWindow( Display *dpy, GLXFBConfig config, Window win, + const int *attribList ) +{ + XMesaVisual xmvis = (XMesaVisual) config; + XMesaBuffer xmbuf; + if (!xmvis) + return 0; + + xmbuf = XMesaCreateWindowBuffer2(xmvis, win, NULL); + if (!xmbuf) + return 0; + + (void) dpy; + (void) attribList; /* Ignored in GLX 1.3 */ + + return win; /* A hack for now */ +} + + +static void +Fake_glXDestroyWindow( Display *dpy, GLXWindow window ) +{ + 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 ) +{ + XMesaVisual v = (XMesaVisual) config; + XMesaBuffer b; + + (void) dpy; + (void) config; + (void) pixmap; + (void) attribList; /* Ignored in GLX 1.3 */ + + if (!dpy || !config || !pixmap) + return 0; + + b = XMesaCreatePixmapBuffer( v, pixmap, 0 ); + if (!b) { + return 0; + } + + return pixmap; +} + + +static void +Fake_glXDestroyPixmap( Display *dpy, GLXPixmap pixmap ) +{ + XMesaBuffer b = XMesaFindBuffer(dpy, (XMesaDrawable)pixmap); + if (b) + XMesaDestroyBuffer(b); + /* don't destroy X pixmap */ +} + + +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; + + 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. + */ + return (GLXPbuffer) xmbuf->frontbuffer; +} + + +static void +Fake_glXDestroyPbuffer( Display *dpy, GLXPbuffer pbuf ) +{ + XMesaBuffer b = XMesaFindBuffer(dpy, pbuf); + if (b) { + XMesaDestroyBuffer(b); + } +} + + +static void +Fake_glXQueryDrawable( Display *dpy, GLXDrawable draw, int attribute, + unsigned int *value ) +{ + XMesaBuffer xmbuf = XMesaFindBuffer(dpy, draw); + if (!xmbuf) + return; + + switch (attribute) { + case GLX_WIDTH: + *value = xmbuf->width; + break; + case GLX_HEIGHT: + *value = xmbuf->height; + break; + case GLX_PRESERVED_CONTENTS: + *value = True; + break; + case GLX_LARGEST_PBUFFER: + *value = xmbuf->width * xmbuf->height; + break; + case GLX_FBCONFIG_ID: + *value = xmbuf->xm_visual->visinfo->visualid; + return; + default: + return; /* GLX_BAD_ATTRIBUTE? */ + } +} + + +static GLXContext +Fake_glXCreateNewContext( Display *dpy, GLXFBConfig config, + int renderType, GLXContext shareList, Bool direct ) +{ + 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) { + 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; + + 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; +} + + +static void +Fake_glXSelectEvent( Display *dpy, GLXDrawable drawable, unsigned long mask ) +{ + XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); + if (xmbuf) + xmbuf->selectedEvents = mask; +} + + +static void +Fake_glXGetSelectedEvent( Display *dpy, GLXDrawable drawable, + unsigned long *mask ) +{ + XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); + if (xmbuf) + *mask = xmbuf->selectedEvents; + else + *mask = 0; +} + + + +/*** GLX_SGI_swap_control ***/ + +static int +Fake_glXSwapIntervalSGI(int interval) +{ + (void) interval; + return 0; +} + + + +/*** GLX_SGI_video_sync ***/ + +static int +Fake_glXGetVideoSyncSGI(unsigned int *count) +{ + (void) count; + return 0; +} + +static int +Fake_glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count) +{ + (void) divisor; + (void) remainder; + (void) count; + return 0; +} + + + +/*** GLX_SGI_make_current_read ***/ + +static Bool +Fake_glXMakeCurrentReadSGI(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx) +{ + return Fake_glXMakeContextCurrent( dpy, draw, read, ctx ); +} + +/* not used +static GLXDrawable +Fake_glXGetCurrentReadDrawableSGI(void) +{ + return 0; +} +*/ + + +/*** GLX_SGIX_video_source ***/ +#if defined(_VL_H) + +static GLXVideoSourceSGIX +Fake_glXCreateGLXVideoSourceSGIX(Display *dpy, int screen, VLServer server, VLPath path, int nodeClass, VLNode drainNode) +{ + (void) dpy; + (void) screen; + (void) server; + (void) path; + (void) nodeClass; + (void) drainNode; + return 0; +} + +static void +Fake_glXDestroyGLXVideoSourceSGIX(Display *dpy, GLXVideoSourceSGIX src) +{ + (void) dpy; + (void) src; +} + +#endif + + +/*** GLX_EXT_import_context ***/ + +static void +Fake_glXFreeContextEXT(Display *dpy, GLXContext context) +{ + (void) dpy; + (void) context; +} + +static GLXContextID +Fake_glXGetContextIDEXT(const GLXContext context) +{ + (void) context; + return 0; +} + +static GLXContext +Fake_glXImportContextEXT(Display *dpy, GLXContextID contextID) +{ + (void) dpy; + (void) contextID; + return 0; +} + +static int +Fake_glXQueryContextInfoEXT(Display *dpy, GLXContext context, int attribute, int *value) +{ + (void) dpy; + (void) context; + (void) attribute; + (void) value; + return 0; +} + + + +/*** GLX_SGIX_fbconfig ***/ + +static int +Fake_glXGetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config, int attribute, int *value) +{ + return Fake_glXGetFBConfigAttrib(dpy, config, attribute, value); +} + +static GLXFBConfigSGIX * +Fake_glXChooseFBConfigSGIX(Display *dpy, int screen, int *attrib_list, int *nelements) +{ + return (GLXFBConfig *) Fake_glXChooseFBConfig(dpy, screen, attrib_list, nelements); +} + + +static GLXPixmap +Fake_glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, Pixmap pixmap) +{ + XMesaVisual xmvis = (XMesaVisual) config; + XMesaBuffer xmbuf = XMesaCreatePixmapBuffer(xmvis, pixmap, 0); + return xmbuf->frontbuffer; /* need to return an X ID */ +} + + +static GLXContext +Fake_glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct) +{ + 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) { + 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) +{ + return Fake_glXGetVisualFromFBConfig(dpy, config); +} + + +static GLXFBConfigSGIX +Fake_glXGetFBConfigFromVisualSGIX(Display *dpy, XVisualInfo *vis) +{ + 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; +} + + + +/*** GLX_SGIX_pbuffer ***/ + +static GLXPbufferSGIX +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; + + 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->frontbuffer; +} + + +static void +Fake_glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf) +{ + XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf); + if (xmbuf) { + XMesaDestroyBuffer(xmbuf); + } +} + + +static int +Fake_glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int *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->width * xmbuf->height; + break; + case GLX_WIDTH_SGIX: + *value = xmbuf->width; + break; + case GLX_HEIGHT_SGIX: + *value = xmbuf->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) +{ + 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) +{ + XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); + if (xmbuf) { + *mask = xmbuf->selectedEvents; + } + else { + *mask = 0; + } +} + + + +/*** GLX_SGI_cushion ***/ + +static void +Fake_glXCushionSGI(Display *dpy, Window win, float cushion) +{ + (void) dpy; + (void) win; + (void) cushion; +} + + + +/*** GLX_SGIX_video_resize ***/ + +static int +Fake_glXBindChannelToWindowSGIX(Display *dpy, int screen, int channel , Window window) +{ + (void) dpy; + (void) screen; + (void) channel; + (void) window; + return 0; +} + +static int +Fake_glXChannelRectSGIX(Display *dpy, int screen, int channel, int x, int y, int w, int h) +{ + (void) dpy; + (void) screen; + (void) channel; + (void) x; + (void) y; + (void) w; + (void) h; + return 0; +} + +static int +Fake_glXQueryChannelRectSGIX(Display *dpy, int screen, int channel, int *x, int *y, int *w, int *h) +{ + (void) dpy; + (void) screen; + (void) channel; + (void) x; + (void) y; + (void) w; + (void) h; + return 0; +} + +static int +Fake_glXQueryChannelDeltasSGIX(Display *dpy, int screen, int channel, int *dx, int *dy, int *dw, int *dh) +{ + (void) dpy; + (void) screen; + (void) channel; + (void) dx; + (void) dy; + (void) dw; + (void) dh; + return 0; +} + +static int +Fake_glXChannelRectSyncSGIX(Display *dpy, int screen, int channel, GLenum synctype) +{ + (void) dpy; + (void) screen; + (void) channel; + (void) synctype; + return 0; +} + + + +/*** GLX_SGIX_dmbuffer **/ + +#if defined(_DM_BUFFER_H_) +static Bool +Fake_glXAssociateDMPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuffer, DMparams *params, DMbuffer dmbuffer) +{ + (void) dpy; + (void) pbuffer; + (void) params; + (void) dmbuffer; + return False; +} +#endif + + +/*** GLX_SGIX_swap_group ***/ + +static void +Fake_glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable, GLXDrawable member) +{ + (void) dpy; + (void) drawable; + (void) member; +} + + + +/*** GLX_SGIX_swap_barrier ***/ + +static void +Fake_glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable, int barrier) +{ + (void) dpy; + (void) drawable; + (void) barrier; +} + +static Bool +Fake_glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max) +{ + (void) dpy; + (void) screen; + (void) max; + return False; +} + + + +/*** GLX_SUN_get_transparent_index ***/ + +static Status +Fake_glXGetTransparentIndexSUN(Display *dpy, Window overlay, Window underlay, long *pTransparent) +{ + (void) dpy; + (void) overlay; + (void) underlay; + (void) pTransparent; + return 0; +} + + + +/*** GLX_MESA_release_buffers ***/ + +/* + * Release the depth, stencil, accum buffers attached to a GLXDrawable + * (a window or pixmap) prior to destroying the GLXDrawable. + */ +static Bool +Fake_glXReleaseBuffersMESA( Display *dpy, GLXDrawable d ) +{ + XMesaBuffer b = XMesaFindBuffer(dpy, d); + if (b) { + XMesaDestroyBuffer(b); + return True; + } + return False; +} + + + +/*** GLX_MESA_set_3dfx_mode ***/ + +static Bool +Fake_glXSet3DfxModeMESA( int mode ) +{ + return XMesaSetFXmode( mode ); +} + + + +/*** 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_ARB_render_texture ***/ + +static Bool +Fake_glXBindTexImageARB( Display *dpy, GLXPbuffer pbuffer, int buffer ) +{ + return False; +} + + +static Bool +Fake_glXReleaseTexImageARB(Display *dpy, GLXPbuffer pbuffer, int buffer ) +{ + return False; +} + + +static Bool +Fake_glXDrawableAttribARB( Display *dpy, GLXDrawable draw, const int *attribList ) +{ + return False; +} + + +/* silence warning */ +extern 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; + + /* be sure our dispatch table size <= libGL's table */ + { + GLuint size = sizeof(struct _glxapi_table) / sizeof(void *); + (void) size; + assert(_glxapi_get_dispatch_table_size() >= size); + } + + /* initialize the whole table to no-ops */ + _glxapi_set_no_op_table(&glx); + + /* now initialize the table with the functions I implement */ + glx.ChooseVisual = Fake_glXChooseVisual; + glx.CopyContext = Fake_glXCopyContext; + glx.CreateContext = Fake_glXCreateContext; + glx.CreateGLXPixmap = Fake_glXCreateGLXPixmap; + glx.DestroyContext = Fake_glXDestroyContext; + glx.DestroyGLXPixmap = Fake_glXDestroyGLXPixmap; + glx.GetConfig = Fake_glXGetConfig; + /*glx.GetCurrentContext = Fake_glXGetCurrentContext;*/ + /*glx.GetCurrentDrawable = Fake_glXGetCurrentDrawable;*/ + glx.IsDirect = Fake_glXIsDirect; + glx.MakeCurrent = Fake_glXMakeCurrent; + glx.QueryExtension = Fake_glXQueryExtension; + glx.QueryVersion = Fake_glXQueryVersion; + glx.SwapBuffers = Fake_glXSwapBuffers; + glx.UseXFont = Fake_glXUseXFont; + glx.WaitGL = Fake_glXWaitGL; + glx.WaitX = Fake_glXWaitX; + + /*** GLX_VERSION_1_1 ***/ + glx.GetClientString = Fake_glXGetClientString; + glx.QueryExtensionsString = Fake_glXQueryExtensionsString; + glx.QueryServerString = Fake_glXQueryServerString; + + /*** GLX_VERSION_1_2 ***/ + /*glx.GetCurrentDisplay = Fake_glXGetCurrentDisplay;*/ + + /*** GLX_VERSION_1_3 ***/ + glx.ChooseFBConfig = Fake_glXChooseFBConfig; + glx.CreateNewContext = Fake_glXCreateNewContext; + glx.CreatePbuffer = Fake_glXCreatePbuffer; + glx.CreatePixmap = Fake_glXCreatePixmap; + glx.CreateWindow = Fake_glXCreateWindow; + glx.DestroyPbuffer = Fake_glXDestroyPbuffer; + glx.DestroyPixmap = Fake_glXDestroyPixmap; + glx.DestroyWindow = Fake_glXDestroyWindow; + /*glx.GetCurrentReadDrawable = Fake_glXGetCurrentReadDrawable;*/ + glx.GetFBConfigAttrib = Fake_glXGetFBConfigAttrib; + glx.GetFBConfigs = Fake_glXGetFBConfigs; + glx.GetSelectedEvent = Fake_glXGetSelectedEvent; + glx.GetVisualFromFBConfig = Fake_glXGetVisualFromFBConfig; + glx.MakeContextCurrent = Fake_glXMakeContextCurrent; + glx.QueryContext = Fake_glXQueryContext; + glx.QueryDrawable = Fake_glXQueryDrawable; + glx.SelectEvent = Fake_glXSelectEvent; + + /*** GLX_SGI_swap_control ***/ + glx.SwapIntervalSGI = Fake_glXSwapIntervalSGI; + + /*** GLX_SGI_video_sync ***/ + glx.GetVideoSyncSGI = Fake_glXGetVideoSyncSGI; + glx.WaitVideoSyncSGI = Fake_glXWaitVideoSyncSGI; + + /*** GLX_SGI_make_current_read ***/ + glx.MakeCurrentReadSGI = Fake_glXMakeCurrentReadSGI; + /*glx.GetCurrentReadDrawableSGI = Fake_glXGetCurrentReadDrawableSGI;*/ + +/*** GLX_SGIX_video_source ***/ +#if defined(_VL_H) + glx.CreateGLXVideoSourceSGIX = Fake_glXCreateGLXVideoSourceSGIX; + glx.DestroyGLXVideoSourceSGIX = Fake_glXDestroyGLXVideoSourceSGIX; +#endif + + /*** GLX_EXT_import_context ***/ + glx.FreeContextEXT = Fake_glXFreeContextEXT; + glx.GetContextIDEXT = Fake_glXGetContextIDEXT; + /*glx.GetCurrentDisplayEXT = Fake_glXGetCurrentDisplayEXT;*/ + glx.ImportContextEXT = Fake_glXImportContextEXT; + glx.QueryContextInfoEXT = Fake_glXQueryContextInfoEXT; + + /*** 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; + + /*** GLX_SGIX_pbuffer ***/ + glx.CreateGLXPbufferSGIX = Fake_glXCreateGLXPbufferSGIX; + glx.DestroyGLXPbufferSGIX = Fake_glXDestroyGLXPbufferSGIX; + glx.QueryGLXPbufferSGIX = Fake_glXQueryGLXPbufferSGIX; + glx.SelectEventSGIX = Fake_glXSelectEventSGIX; + glx.GetSelectedEventSGIX = Fake_glXGetSelectedEventSGIX; + + /*** GLX_SGI_cushion ***/ + glx.CushionSGI = Fake_glXCushionSGI; + + /*** GLX_SGIX_video_resize ***/ + glx.BindChannelToWindowSGIX = Fake_glXBindChannelToWindowSGIX; + glx.ChannelRectSGIX = Fake_glXChannelRectSGIX; + glx.QueryChannelRectSGIX = Fake_glXQueryChannelRectSGIX; + glx.QueryChannelDeltasSGIX = Fake_glXQueryChannelDeltasSGIX; + glx.ChannelRectSyncSGIX = Fake_glXChannelRectSyncSGIX; + + /*** GLX_SGIX_dmbuffer **/ +#if defined(_DM_BUFFER_H_) + glx.AssociateDMPbufferSGIX = NULL; +#endif + + /*** GLX_SGIX_swap_group ***/ + glx.JoinSwapGroupSGIX = Fake_glXJoinSwapGroupSGIX; + + /*** GLX_SGIX_swap_barrier ***/ + glx.BindSwapBarrierSGIX = Fake_glXBindSwapBarrierSGIX; + glx.QueryMaxSwapBarriersSGIX = Fake_glXQueryMaxSwapBarriersSGIX; + + /*** GLX_SUN_get_transparent_index ***/ + glx.GetTransparentIndexSUN = Fake_glXGetTransparentIndexSUN; + + /*** GLX_MESA_copy_sub_buffer ***/ + glx.CopySubBufferMESA = Fake_glXCopySubBufferMESA; + + /*** GLX_MESA_release_buffers ***/ + glx.ReleaseBuffersMESA = Fake_glXReleaseBuffersMESA; + + /*** GLX_MESA_pixmap_colormap ***/ + glx.CreateGLXPixmapMESA = Fake_glXCreateGLXPixmapMESA; + + /*** GLX_MESA_set_3dfx_mode ***/ + glx.Set3DfxModeMESA = Fake_glXSet3DfxModeMESA; + + /*** GLX_NV_vertex_array_range ***/ + glx.AllocateMemoryNV = Fake_glXAllocateMemoryNV; + glx.FreeMemoryNV = Fake_glXFreeMemoryNV; + + /*** GLX_MESA_agp_offset ***/ + glx.GetAGPOffsetMESA = Fake_glXGetAGPOffsetMESA; + + /*** GLX_ARB_render_texture ***/ + glx.BindTexImageARB = Fake_glXBindTexImageARB; + glx.ReleaseTexImageARB = Fake_glXReleaseTexImageARB; + glx.DrawableAttribARB = Fake_glXDrawableAttribARB; + + return &glx; +} diff --git a/src/mesa/drivers/x11/glxapi.c b/src/mesa/drivers/x11/glxapi.c new file mode 100644 index 0000000..99fc4e2 --- /dev/null +++ b/src/mesa/drivers/x11/glxapi.c @@ -0,0 +1,1343 @@ +/* + * Mesa 3-D graphics library + * Version: 6.2.1 + * + * Copyright (C) 1999-2004 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. + */ + + +/* + * This is the GLX API dispatcher. Calls to the glX* functions are + * either routed to the real GLX encoders or to Mesa's pseudo-GLX functions. + * See the glxapi.h file for more details. + */ + + +#include +#include +#include +#include +#include "glapi.h" +#include "glxapi.h" + + +extern struct _glxapi_table *_real_GetGLXDispatchTable(void); +extern struct _glxapi_table *_mesa_GetGLXDispatchTable(void); + + +struct display_dispatch { + Display *Dpy; + struct _glxapi_table *Table; + struct display_dispatch *Next; +}; + +static struct display_dispatch *DispatchList = NULL; + + +/* Display -> Dispatch caching */ +static Display *prevDisplay = NULL; +static struct _glxapi_table *prevTable = NULL; + + +static struct _glxapi_table * +get_dispatch(Display *dpy) +{ + if (!dpy) + return NULL; + + /* search list of display/dispatch pairs for this display */ + { + const struct display_dispatch *d = DispatchList; + while (d) { + if (d->Dpy == dpy) { + prevDisplay = dpy; + prevTable = d->Table; + return d->Table; /* done! */ + } + d = d->Next; + } + } + + /* A new display, determine if we should use real GLX + * or Mesa's pseudo-GLX. + */ + { + struct _glxapi_table *t = NULL; + +#ifdef GLX_BUILT_IN_XMESA + if (!getenv("LIBGL_FORCE_XMESA")) { + int ignore; + if (XQueryExtension( dpy, "GLX", &ignore, &ignore, &ignore )) { + /* the X server has the GLX extension */ + t = _real_GetGLXDispatchTable(); + } + } +#endif + + if (!t) { + /* Fallback to Mesa with Xlib driver */ +#ifdef GLX_BUILT_IN_XMESA + if (getenv("LIBGL_DEBUG")) { + fprintf(stderr, + "libGL: server %s lacks the GLX extension.", + dpy->display_name); + fprintf(stderr, " Using Mesa Xlib renderer.\n"); + } +#endif + t = _mesa_GetGLXDispatchTable(); + assert(t); /* this has to work */ + } + + if (t) { + struct display_dispatch *d; + d = (struct display_dispatch *) malloc(sizeof(struct display_dispatch)); + if (d) { + d->Dpy = dpy; + d->Table = t; + /* insert at head of list */ + d->Next = DispatchList; + DispatchList = d; + /* update cache */ + prevDisplay = dpy; + prevTable = t; + return t; + } + } + } + + /* If we get here that means we can't use real GLX on this display + * and the Mesa pseudo-GLX software renderer wasn't compiled in. + * Or, we ran out of memory! + */ + return NULL; +} + + +#define GET_DISPATCH(DPY, TABLE) \ + if (DPY == prevDisplay) { \ + TABLE = prevTable; \ + } \ + else if (!DPY) { \ + TABLE = NULL; \ + } \ + else { \ + TABLE = get_dispatch(DPY); \ + } + + + + +/* Set by glXMakeCurrent() and glXMakeContextCurrent() only */ +#ifndef GLX_BUILT_IN_XMESA +static GLXContext CurrentContext = 0; +#define __glXGetCurrentContext() CurrentContext; +#endif + + +/* + * GLX API entrypoints + */ + +/*** GLX_VERSION_1_0 ***/ + +XVisualInfo *glXChooseVisual(Display *dpy, int screen, int *list) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return NULL; + return (t->ChooseVisual)(dpy, screen, list); +} + + +void glXCopyContext(Display *dpy, GLXContext src, GLXContext dst, unsigned long mask) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->CopyContext)(dpy, src, dst, mask); +} + + +GLXContext glXCreateContext(Display *dpy, XVisualInfo *visinfo, GLXContext shareList, Bool direct) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->CreateContext)(dpy, visinfo, shareList, direct); +} + + +GLXPixmap glXCreateGLXPixmap(Display *dpy, XVisualInfo *visinfo, Pixmap pixmap) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->CreateGLXPixmap)(dpy, visinfo, pixmap); +} + + +void glXDestroyContext(Display *dpy, GLXContext ctx) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->DestroyContext)(dpy, ctx); +} + + +void glXDestroyGLXPixmap(Display *dpy, GLXPixmap pixmap) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->DestroyGLXPixmap)(dpy, pixmap); +} + + +int glXGetConfig(Display *dpy, XVisualInfo *visinfo, int attrib, int *value) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return GLX_NO_EXTENSION; + return (t->GetConfig)(dpy, visinfo, attrib, value); +} + + +#ifdef GLX_BUILT_IN_XMESA +/* Use real libGL's glXGetCurrentContext() function */ +#else +/* stand-alone Mesa */ +GLXContext glXGetCurrentContext(void) +{ + return CurrentContext; +} +#endif + + +#ifdef GLX_BUILT_IN_XMESA +/* Use real libGL's glXGetCurrentContext() function */ +#else +/* stand-alone Mesa */ +GLXDrawable glXGetCurrentDrawable(void) +{ + __GLXcontext *gc = (__GLXcontext *) glXGetCurrentContext(); + return gc ? gc->currentDrawable : 0; +} +#endif + + +Bool glXIsDirect(Display *dpy, GLXContext ctx) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return False; + return (t->IsDirect)(dpy, ctx); +} + + +Bool glXMakeCurrent(Display *dpy, GLXDrawable drawable, GLXContext ctx) +{ + Bool b; + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) { + return False; + } + b = (*t->MakeCurrent)(dpy, drawable, ctx); +#ifndef GLX_BUILT_IN_XMESA + if (b) { + CurrentContext = ctx; + } +#endif + return b; +} + + +Bool glXQueryExtension(Display *dpy, int *errorb, int *event) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return False; + return (t->QueryExtension)(dpy, errorb, event); +} + + +Bool glXQueryVersion(Display *dpy, int *maj, int *min) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return False; + return (t->QueryVersion)(dpy, maj, min); +} + + +void glXSwapBuffers(Display *dpy, GLXDrawable drawable) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->SwapBuffers)(dpy, drawable); +} + + +void glXUseXFont(Font font, int first, int count, int listBase) +{ + struct _glxapi_table *t; + Display *dpy = glXGetCurrentDisplay(); + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->UseXFont)(font, first, count, listBase); +} + + +void glXWaitGL(void) +{ + struct _glxapi_table *t; + Display *dpy = glXGetCurrentDisplay(); + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->WaitGL)(); +} + + +void glXWaitX(void) +{ + struct _glxapi_table *t; + Display *dpy = glXGetCurrentDisplay(); + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->WaitX)(); +} + + + +/*** GLX_VERSION_1_1 ***/ + +const char *glXGetClientString(Display *dpy, int name) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return NULL; + return (t->GetClientString)(dpy, name); +} + + +const char *glXQueryExtensionsString(Display *dpy, int screen) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return NULL; + return (t->QueryExtensionsString)(dpy, screen); +} + + +const char *glXQueryServerString(Display *dpy, int screen, int name) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return NULL; + return (t->QueryServerString)(dpy, screen, name); +} + + +/*** GLX_VERSION_1_2 ***/ + +#if !defined(GLX_BUILT_IN_XMESA) +Display *glXGetCurrentDisplay(void) +{ + /* Same code as in libGL's glxext.c */ + __GLXcontext *gc = (__GLXcontext *) glXGetCurrentContext(); + if (NULL == gc) return NULL; + return gc->currentDpy; +} +#endif + + + +/*** GLX_VERSION_1_3 ***/ + +GLXFBConfig *glXChooseFBConfig(Display *dpy, int screen, const int *attribList, int *nitems) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->ChooseFBConfig)(dpy, screen, attribList, nitems); +} + + +GLXContext glXCreateNewContext(Display *dpy, GLXFBConfig config, int renderType, GLXContext shareList, Bool direct) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->CreateNewContext)(dpy, config, renderType, shareList, direct); +} + + +GLXPbuffer glXCreatePbuffer(Display *dpy, GLXFBConfig config, const int *attribList) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->CreatePbuffer)(dpy, config, attribList); +} + + +GLXPixmap glXCreatePixmap(Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attribList) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->CreatePixmap)(dpy, config, pixmap, attribList); +} + + +GLXWindow glXCreateWindow(Display *dpy, GLXFBConfig config, Window win, const int *attribList) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->CreateWindow)(dpy, config, win, attribList); +} + + +void glXDestroyPbuffer(Display *dpy, GLXPbuffer pbuf) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->DestroyPbuffer)(dpy, pbuf); +} + + +void glXDestroyPixmap(Display *dpy, GLXPixmap pixmap) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->DestroyPixmap)(dpy, pixmap); +} + + +void glXDestroyWindow(Display *dpy, GLXWindow window) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->DestroyWindow)(dpy, window); +} + + +#ifdef GLX_BUILT_IN_XMESA +/* Use the glXGetCurrentReadDrawable() function from libGL */ +#else +GLXDrawable glXGetCurrentReadDrawable(void) +{ + __GLXcontext *gc = (__GLXcontext *) glXGetCurrentContext(); + return gc ? gc->currentReadable : 0; +} +#endif + + +int glXGetFBConfigAttrib(Display *dpy, GLXFBConfig config, int attribute, int *value) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return GLX_NO_EXTENSION; + return (t->GetFBConfigAttrib)(dpy, config, attribute, value); +} + + +GLXFBConfig *glXGetFBConfigs(Display *dpy, int screen, int *nelements) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->GetFBConfigs)(dpy, screen, nelements); +} + +void glXGetSelectedEvent(Display *dpy, GLXDrawable drawable, unsigned long *mask) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->GetSelectedEvent)(dpy, drawable, mask); +} + + +XVisualInfo *glXGetVisualFromFBConfig(Display *dpy, GLXFBConfig config) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return NULL; + return (t->GetVisualFromFBConfig)(dpy, config); +} + + +Bool glXMakeContextCurrent(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx) +{ + Bool b; + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return False; + b = (t->MakeContextCurrent)(dpy, draw, read, ctx); +#ifndef GLX_BUILT_IN_XMESA + if (b) { + CurrentContext = ctx; + } +#endif + return b; +} + + +int glXQueryContext(Display *dpy, GLXContext ctx, int attribute, int *value) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + assert(t); + if (!t) + return 0; /* XXX correct? */ + return (t->QueryContext)(dpy, ctx, attribute, value); +} + + +void glXQueryDrawable(Display *dpy, GLXDrawable draw, int attribute, unsigned int *value) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->QueryDrawable)(dpy, draw, attribute, value); +} + + +void glXSelectEvent(Display *dpy, GLXDrawable drawable, unsigned long mask) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->SelectEvent)(dpy, drawable, mask); +} + + + +/*** GLX_SGI_swap_control ***/ + +int glXSwapIntervalSGI(int interval) +{ + struct _glxapi_table *t; + Display *dpy = glXGetCurrentDisplay(); + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->SwapIntervalSGI)(interval); +} + + + +/*** GLX_SGI_video_sync ***/ + +int glXGetVideoSyncSGI(unsigned int *count) +{ + struct _glxapi_table *t; + Display *dpy = glXGetCurrentDisplay(); + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->GetVideoSyncSGI)(count); +} + +int glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count) +{ + struct _glxapi_table *t; + Display *dpy = glXGetCurrentDisplay(); + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->WaitVideoSyncSGI)(divisor, remainder, count); +} + + + +/*** GLX_SGI_make_current_read ***/ + +Bool glXMakeCurrentReadSGI(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->MakeCurrentReadSGI)(dpy, draw, read, ctx); +} + +#ifdef GLX_BUILT_IN_XMESA +/* Use glXGetCurrentReadDrawableSGI() from libGL */ +#else +/* stand-alone Mesa */ +GLXDrawable glXGetCurrentReadDrawableSGI(void) +{ + return glXGetCurrentReadDrawable(); +} +#endif + + +#if defined(_VL_H) + +GLXVideoSourceSGIX glXCreateGLXVideoSourceSGIX(Display *dpy, int screen, VLServer server, VLPath path, int nodeClass, VLNode drainNode) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->CreateGLXVideoSourceSGIX)(dpy, screen, server, path, nodeClass, drainNode); +} + +void glXDestroyGLXVideoSourceSGIX(Display *dpy, GLXVideoSourceSGIX src) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->DestroyGLXVideoSourceSGIX)(dpy, src); +} + +#endif + + +/*** GLX_EXT_import_context ***/ + +void glXFreeContextEXT(Display *dpy, GLXContext context) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->FreeContextEXT)(dpy, context); +} + +#ifdef GLX_BUILT_IN_XMESA +/* Use real libGL's glXGetContextIDEXT() function */ +#else +/* stand-alone Mesa */ +GLXContextID glXGetContextIDEXT(const GLXContext context) +{ + return ((__GLXcontext *) context)->xid; +} +#endif + +#ifdef GLX_BUILT_IN_XMESA +/* Use real libGL's glXGetCurrentDisplayEXT() function */ +#else +/* stand-alone Mesa */ +Display *glXGetCurrentDisplayEXT(void) +{ + return glXGetCurrentDisplay(); +} +#endif + +GLXContext glXImportContextEXT(Display *dpy, GLXContextID contextID) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->ImportContextEXT)(dpy, contextID); +} + +int glXQueryContextInfoEXT(Display *dpy, GLXContext context, int attribute,int *value) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; /* XXX ok? */ + return (t->QueryContextInfoEXT)(dpy, context, attribute, value); +} + + + +/*** GLX_SGIX_fbconfig ***/ + +int glXGetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config, int attribute, int *value) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->GetFBConfigAttribSGIX)(dpy, config, attribute, value); +} + +GLXFBConfigSGIX *glXChooseFBConfigSGIX(Display *dpy, int screen, int *attrib_list, int *nelements) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->ChooseFBConfigSGIX)(dpy, screen, attrib_list, nelements); +} + +GLXPixmap glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, Pixmap pixmap) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->CreateGLXPixmapWithConfigSGIX)(dpy, config, pixmap); +} + +GLXContext glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->CreateContextWithConfigSGIX)(dpy, config, render_type, share_list, direct); +} + +XVisualInfo * glXGetVisualFromFBConfigSGIX(Display *dpy, GLXFBConfigSGIX config) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->GetVisualFromFBConfigSGIX)(dpy, config); +} + +GLXFBConfigSGIX glXGetFBConfigFromVisualSGIX(Display *dpy, XVisualInfo *vis) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->GetFBConfigFromVisualSGIX)(dpy, vis); +} + + + +/*** GLX_SGIX_pbuffer ***/ + +GLXPbufferSGIX glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height, int *attrib_list) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->CreateGLXPbufferSGIX)(dpy, config, width, height, attrib_list); +} + +void glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->DestroyGLXPbufferSGIX)(dpy, pbuf); +} + +int glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int *value) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->QueryGLXPbufferSGIX)(dpy, pbuf, attribute, value); +} + +void glXSelectEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long mask) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->SelectEventSGIX)(dpy, drawable, mask); +} + +void glXGetSelectedEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long *mask) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->GetSelectedEventSGIX)(dpy, drawable, mask); +} + + + +/*** GLX_SGI_cushion ***/ + +void glXCushionSGI(Display *dpy, Window win, float cushion) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->CushionSGI)(dpy, win, cushion); +} + + + +/*** GLX_SGIX_video_resize ***/ + +int glXBindChannelToWindowSGIX(Display *dpy, int screen, int channel , Window window) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->BindChannelToWindowSGIX)(dpy, screen, channel, window); +} + +int glXChannelRectSGIX(Display *dpy, int screen, int channel, int x, int y, int w, int h) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->ChannelRectSGIX)(dpy, screen, channel, x, y, w, h); +} + +int glXQueryChannelRectSGIX(Display *dpy, int screen, int channel, int *x, int *y, int *w, int *h) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->QueryChannelRectSGIX)(dpy, screen, channel, x, y, w, h); +} + +int glXQueryChannelDeltasSGIX(Display *dpy, int screen, int channel, int *dx, int *dy, int *dw, int *dh) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->QueryChannelDeltasSGIX)(dpy, screen, channel, dx, dy, dw, dh); +} + +int glXChannelRectSyncSGIX(Display *dpy, int screen, int channel, GLenum synctype) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->ChannelRectSyncSGIX)(dpy, screen, channel, synctype); +} + + + +#if defined(_DM_BUFFER_H_) + +Bool glXAssociateDMPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuffer, DMparams *params, DMbuffer dmbuffer) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return False; + return (t->AssociateDMPbufferSGIX)(dpy, pbuffer, params, dmbuffer); +} + +#endif + + +/*** GLX_SGIX_swap_group ***/ + +void glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable, GLXDrawable member) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (*t->JoinSwapGroupSGIX)(dpy, drawable, member); +} + + +/*** GLX_SGIX_swap_barrier ***/ + +void glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable, int barrier) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (*t->BindSwapBarrierSGIX)(dpy, drawable, barrier); +} + +Bool glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return False; + return (*t->QueryMaxSwapBarriersSGIX)(dpy, screen, max); +} + + + +/*** GLX_SUN_get_transparent_index ***/ + +Status glXGetTransparentIndexSUN(Display *dpy, Window overlay, Window underlay, long *pTransparent) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return False; + return (*t->GetTransparentIndexSUN)(dpy, overlay, underlay, pTransparent); +} + + + +/*** GLX_MESA_copy_sub_buffer ***/ + +void glXCopySubBufferMESA(Display *dpy, GLXDrawable drawable, int x, int y, int width, int height) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->CopySubBufferMESA)(dpy, drawable, x, y, width, height); +} + + + +/*** GLX_MESA_release_buffers ***/ + +Bool glXReleaseBuffersMESA(Display *dpy, Window w) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return False; + return (t->ReleaseBuffersMESA)(dpy, w); +} + + + +/*** GLX_MESA_pixmap_colormap ***/ + +GLXPixmap glXCreateGLXPixmapMESA(Display *dpy, XVisualInfo *visinfo, Pixmap pixmap, Colormap cmap) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->CreateGLXPixmapMESA)(dpy, visinfo, pixmap, cmap); +} + + + +/*** GLX_MESA_set_3dfx_mode ***/ + +Bool glXSet3DfxModeMESA(int mode) +{ + struct _glxapi_table *t; + Display *dpy = glXGetCurrentDisplay(); + GET_DISPATCH(dpy, t); + if (!t) + return False; + return (t->Set3DfxModeMESA)(mode); +} + + + +/*** GLX_NV_vertex_array_range ***/ + +void * +glXAllocateMemoryNV( GLsizei size, + GLfloat readFrequency, + GLfloat writeFrequency, + GLfloat priority ) +{ + struct _glxapi_table *t; + Display *dpy = glXGetCurrentDisplay(); + GET_DISPATCH(dpy, t); + if (!t) + return NULL; + return (t->AllocateMemoryNV)(size, readFrequency, writeFrequency, priority); +} + + +void +glXFreeMemoryNV( GLvoid *pointer ) +{ + struct _glxapi_table *t; + Display *dpy = glXGetCurrentDisplay(); + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->FreeMemoryNV)(pointer); +} + + +/*** GLX_MESA_agp_offset */ + +GLuint +glXGetAGPOffsetMESA( const GLvoid *pointer ) +{ + struct _glxapi_table *t; + Display *dpy = glXGetCurrentDisplay(); + GET_DISPATCH(dpy, t); + if (!t) + return ~0; + return (t->GetAGPOffsetMESA)(pointer); +} + + +/*** GLX_ARB_render_Texture ***/ + +Bool +glXBindTexImageARB( Display *dpy, GLXPbuffer pbuffer, int buffer ) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return False; + return (t->BindTexImageARB)(dpy, pbuffer, buffer); +} + + +Bool +glXReleaseTexImageARB(Display *dpy, GLXPbuffer pbuffer, int buffer ) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return False; + return (t->ReleaseTexImageARB)(dpy, pbuffer, buffer); +} + + +Bool +glXDrawableAttribARB( Display *dpy, GLXDrawable draw, const int *attribList ) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return False; + return (t->DrawableAttribARB)(dpy, draw, attribList); +} + + + +/**********************************************************************/ +/* GLX API management functions */ +/**********************************************************************/ + + +const char * +_glxapi_get_version(void) +{ + return "1.3"; +} + + +/* + * Return array of extension strings. + */ +const char ** +_glxapi_get_extensions(void) +{ + static const char *extensions[] = { +#ifdef GLX_EXT_import_context + "GLX_EXT_import_context", +#endif +#ifdef GLX_SGI_video_sync + "GLX_SGI_video_sync", +#endif +#ifdef GLX_MESA_copy_sub_buffer + "GLX_MESA_copy_sub_buffer", +#endif +#ifdef GLX_MESA_release_buffers + "GLX_MESA_release_buffers", +#endif +#ifdef GLX_MESA_pixmap_colormap + "GLX_MESA_pixmap_colormap", +#endif +#ifdef GLX_MESA_set_3dfx_mode + "GLX_MESA_set_3dfx_mode", +#endif +#ifdef GLX_SGIX_fbconfig + "GLX_SGIX_fbconfig", +#endif +#ifdef GLX_SGIX_pbuffer + "GLX_SGIX_pbuffer", +#endif +#ifdef GLX_ARB_render_texture + "GLX_ARB_render_texture", +#endif + NULL + }; + return extensions; +} + + +/* + * Return size of the GLX dispatch table, in entries, not bytes. + */ +GLuint +_glxapi_get_dispatch_table_size(void) +{ + return sizeof(struct _glxapi_table) / sizeof(void *); +} + + +static int +generic_no_op_func(void) +{ + return 0; +} + + +/* + * Initialize all functions in given dispatch table to be no-ops + */ +void +_glxapi_set_no_op_table(struct _glxapi_table *t) +{ + typedef int (*nop_func)(void); + nop_func *dispatch = (nop_func *) t; + GLuint n = _glxapi_get_dispatch_table_size(); + GLuint i; + for (i = 0; i < n; i++) { + dispatch[i] = generic_no_op_func; + } +} + + +struct name_address_pair { + const char *Name; + __GLXextFuncPtr Address; +}; + +static struct name_address_pair GLX_functions[] = { + /*** GLX_VERSION_1_0 ***/ + { "glXChooseVisual", (__GLXextFuncPtr) glXChooseVisual }, + { "glXCopyContext", (__GLXextFuncPtr) glXCopyContext }, + { "glXCreateContext", (__GLXextFuncPtr) glXCreateContext }, + { "glXCreateGLXPixmap", (__GLXextFuncPtr) glXCreateGLXPixmap }, + { "glXDestroyContext", (__GLXextFuncPtr) glXDestroyContext }, + { "glXDestroyGLXPixmap", (__GLXextFuncPtr) glXDestroyGLXPixmap }, + { "glXGetConfig", (__GLXextFuncPtr) glXGetConfig }, + { "glXGetCurrentContext", (__GLXextFuncPtr) glXGetCurrentContext }, + { "glXGetCurrentDrawable", (__GLXextFuncPtr) glXGetCurrentDrawable }, + { "glXIsDirect", (__GLXextFuncPtr) glXIsDirect }, + { "glXMakeCurrent", (__GLXextFuncPtr) glXMakeCurrent }, + { "glXQueryExtension", (__GLXextFuncPtr) glXQueryExtension }, + { "glXQueryVersion", (__GLXextFuncPtr) glXQueryVersion }, + { "glXSwapBuffers", (__GLXextFuncPtr) glXSwapBuffers }, + { "glXUseXFont", (__GLXextFuncPtr) glXUseXFont }, + { "glXWaitGL", (__GLXextFuncPtr) glXWaitGL }, + { "glXWaitX", (__GLXextFuncPtr) glXWaitX }, + + /*** GLX_VERSION_1_1 ***/ + { "glXGetClientString", (__GLXextFuncPtr) glXGetClientString }, + { "glXQueryExtensionsString", (__GLXextFuncPtr) glXQueryExtensionsString }, + { "glXQueryServerString", (__GLXextFuncPtr) glXQueryServerString }, + + /*** GLX_VERSION_1_2 ***/ + { "glXGetCurrentDisplay", (__GLXextFuncPtr) glXGetCurrentDisplay }, + + /*** GLX_VERSION_1_3 ***/ + { "glXChooseFBConfig", (__GLXextFuncPtr) glXChooseFBConfig }, + { "glXCreateNewContext", (__GLXextFuncPtr) glXCreateNewContext }, + { "glXCreatePbuffer", (__GLXextFuncPtr) glXCreatePbuffer }, + { "glXCreatePixmap", (__GLXextFuncPtr) glXCreatePixmap }, + { "glXCreateWindow", (__GLXextFuncPtr) glXCreateWindow }, + { "glXDestroyPbuffer", (__GLXextFuncPtr) glXDestroyPbuffer }, + { "glXDestroyPixmap", (__GLXextFuncPtr) glXDestroyPixmap }, + { "glXDestroyWindow", (__GLXextFuncPtr) glXDestroyWindow }, + { "glXGetCurrentReadDrawable", (__GLXextFuncPtr) glXGetCurrentReadDrawable }, + { "glXGetFBConfigAttrib", (__GLXextFuncPtr) glXGetFBConfigAttrib }, + { "glXGetFBConfigs", (__GLXextFuncPtr) glXGetFBConfigs }, + { "glXGetSelectedEvent", (__GLXextFuncPtr) glXGetSelectedEvent }, + { "glXGetVisualFromFBConfig", (__GLXextFuncPtr) glXGetVisualFromFBConfig }, + { "glXMakeContextCurrent", (__GLXextFuncPtr) glXMakeContextCurrent }, + { "glXQueryContext", (__GLXextFuncPtr) glXQueryContext }, + { "glXQueryDrawable", (__GLXextFuncPtr) glXQueryDrawable }, + { "glXSelectEvent", (__GLXextFuncPtr) glXSelectEvent }, + + /*** GLX_VERSION_1_4 ***/ + { "glXGetProcAddress", (__GLXextFuncPtr) glXGetProcAddress }, + + /*** GLX_SGI_swap_control ***/ + { "glXSwapIntervalSGI", (__GLXextFuncPtr) glXSwapIntervalSGI }, + + /*** GLX_SGI_video_sync ***/ + { "glXGetVideoSyncSGI", (__GLXextFuncPtr) glXGetVideoSyncSGI }, + { "glXWaitVideoSyncSGI", (__GLXextFuncPtr) glXWaitVideoSyncSGI }, + + /*** GLX_SGI_make_current_read ***/ + { "glXMakeCurrentReadSGI", (__GLXextFuncPtr) glXMakeCurrentReadSGI }, + { "glXGetCurrentReadDrawableSGI", (__GLXextFuncPtr) glXGetCurrentReadDrawableSGI }, + + /*** GLX_SGIX_video_source ***/ +#if defined(_VL_H) + { "glXCreateGLXVideoSourceSGIX", (__GLXextFuncPtr) glXCreateGLXVideoSourceSGIX }, + { "glXDestroyGLXVideoSourceSGIX", (__GLXextFuncPtr) glXDestroyGLXVideoSourceSGIX }, +#endif + + /*** GLX_EXT_import_context ***/ + { "glXFreeContextEXT", (__GLXextFuncPtr) glXFreeContextEXT }, + { "glXGetContextIDEXT", (__GLXextFuncPtr) glXGetContextIDEXT }, + { "glXGetCurrentDisplayEXT", (__GLXextFuncPtr) glXGetCurrentDisplayEXT }, + { "glXImportContextEXT", (__GLXextFuncPtr) glXImportContextEXT }, + { "glXQueryContextInfoEXT", (__GLXextFuncPtr) glXQueryContextInfoEXT }, + + /*** GLX_SGIX_fbconfig ***/ + { "glXGetFBConfigAttribSGIX", (__GLXextFuncPtr) glXGetFBConfigAttribSGIX }, + { "glXChooseFBConfigSGIX", (__GLXextFuncPtr) glXChooseFBConfigSGIX }, + { "glXCreateGLXPixmapWithConfigSGIX", (__GLXextFuncPtr) glXCreateGLXPixmapWithConfigSGIX }, + { "glXCreateContextWithConfigSGIX", (__GLXextFuncPtr) glXCreateContextWithConfigSGIX }, + { "glXGetVisualFromFBConfigSGIX", (__GLXextFuncPtr) glXGetVisualFromFBConfigSGIX }, + { "glXGetFBConfigFromVisualSGIX", (__GLXextFuncPtr) glXGetFBConfigFromVisualSGIX }, + + /*** GLX_SGIX_pbuffer ***/ + { "glXCreateGLXPbufferSGIX", (__GLXextFuncPtr) glXCreateGLXPbufferSGIX }, + { "glXDestroyGLXPbufferSGIX", (__GLXextFuncPtr) glXDestroyGLXPbufferSGIX }, + { "glXQueryGLXPbufferSGIX", (__GLXextFuncPtr) glXQueryGLXPbufferSGIX }, + { "glXSelectEventSGIX", (__GLXextFuncPtr) glXSelectEventSGIX }, + { "glXGetSelectedEventSGIX", (__GLXextFuncPtr) glXGetSelectedEventSGIX }, + + /*** GLX_SGI_cushion ***/ + { "glXCushionSGI", (__GLXextFuncPtr) glXCushionSGI }, + + /*** GLX_SGIX_video_resize ***/ + { "glXBindChannelToWindowSGIX", (__GLXextFuncPtr) glXBindChannelToWindowSGIX }, + { "glXChannelRectSGIX", (__GLXextFuncPtr) glXChannelRectSGIX }, + { "glXQueryChannelRectSGIX", (__GLXextFuncPtr) glXQueryChannelRectSGIX }, + { "glXQueryChannelDeltasSGIX", (__GLXextFuncPtr) glXQueryChannelDeltasSGIX }, + { "glXChannelRectSyncSGIX", (__GLXextFuncPtr) glXChannelRectSyncSGIX }, + + /*** GLX_SGIX_dmbuffer **/ +#if defined(_DM_BUFFER_H_) + { "glXAssociateDMPbufferSGIX", (__GLXextFuncPtr) glXAssociateDMPbufferSGIX }, +#endif + + /*** GLX_SGIX_swap_group ***/ + { "glXJoinSwapGroupSGIX", (__GLXextFuncPtr) glXJoinSwapGroupSGIX }, + + /*** GLX_SGIX_swap_barrier ***/ + { "glXBindSwapBarrierSGIX", (__GLXextFuncPtr) glXBindSwapBarrierSGIX }, + { "glXQueryMaxSwapBarriersSGIX", (__GLXextFuncPtr) glXQueryMaxSwapBarriersSGIX }, + + /*** GLX_SUN_get_transparent_index ***/ + { "glXGetTransparentIndexSUN", (__GLXextFuncPtr) glXGetTransparentIndexSUN }, + + /*** GLX_MESA_copy_sub_buffer ***/ + { "glXCopySubBufferMESA", (__GLXextFuncPtr) glXCopySubBufferMESA }, + + /*** GLX_MESA_pixmap_colormap ***/ + { "glXCreateGLXPixmapMESA", (__GLXextFuncPtr) glXCreateGLXPixmapMESA }, + + /*** GLX_MESA_release_buffers ***/ + { "glXReleaseBuffersMESA", (__GLXextFuncPtr) glXReleaseBuffersMESA }, + + /*** GLX_MESA_set_3dfx_mode ***/ + { "glXSet3DfxModeMESA", (__GLXextFuncPtr) glXSet3DfxModeMESA }, + + /*** GLX_ARB_get_proc_address ***/ + { "glXGetProcAddressARB", (__GLXextFuncPtr) glXGetProcAddressARB }, + + /*** GLX_NV_vertex_array_range ***/ + { "glXAllocateMemoryNV", (__GLXextFuncPtr) glXAllocateMemoryNV }, + { "glXFreeMemoryNV", (__GLXextFuncPtr) glXFreeMemoryNV }, + + /*** GLX_MESA_agp_offset ***/ + { "glXGetAGPOffsetMESA", (__GLXextFuncPtr) glXGetAGPOffsetMESA }, + + /*** GLX_ARB_render_texture ***/ + { "glXBindTexImageARB", (__GLXextFuncPtr) glXBindTexImageARB }, + { "glXReleaseTexImageARB", (__GLXextFuncPtr) glXReleaseTexImageARB }, + { "glXDrawableAttribARB", (__GLXextFuncPtr) glXDrawableAttribARB }, + + { NULL, NULL } /* end of list */ +}; + + + +/* + * Return address of named glX function, or NULL if not found. + */ +__GLXextFuncPtr +_glxapi_get_proc_address(const char *funcName) +{ + GLuint i; + for (i = 0; GLX_functions[i].Name; i++) { + if (strcmp(GLX_functions[i].Name, funcName) == 0) + return GLX_functions[i].Address; + } + return NULL; +} + + + +/* + * This function does not get dispatched through the dispatch table + * since it's really a "meta" function. + */ +__GLXextFuncPtr +glXGetProcAddressARB(const GLubyte *procName) +{ + __GLXextFuncPtr f; + + f = _glxapi_get_proc_address((const char *) procName); + if (f) { + return f; + } + + f = (__GLXextFuncPtr) _glapi_get_proc_address((const char *) procName); + return f; +} + + +/* GLX 1.4 */ +void (*glXGetProcAddress(const GLubyte *procName))() +{ + return glXGetProcAddressARB(procName); +} diff --git a/src/mesa/drivers/x11/glxapi.h b/src/mesa/drivers/x11/glxapi.h new file mode 100644 index 0000000..d6bc157 --- /dev/null +++ b/src/mesa/drivers/x11/glxapi.h @@ -0,0 +1,236 @@ + +/* + * Mesa 3-D graphics library + * Version: 5.1 + * + * Copyright (C) 1999-2002 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. + */ + + +#ifndef _glxapi_h_ +#define _glxapi_h_ + + +#define GLX_GLXEXT_PROTOTYPES +#include "GL/glx.h" + + +#ifdef GLX_BUILT_IN_XMESA +/* The GLX API dispatcher (i.e. this code) is being built into XFree86's + * libGL so we'll use the __GLXContextRec defined in xc/lib/GL/glx/glxclient.h +*/ +#include "glxclient.h" +#else +/* The GLX API dispatcher (i.e. this code) is being built into stand-alone + * Mesa. We don't know anything about XFree86 or real GLX so we define a + * minimal __GLXContextRec here so some of the functions in this file can + * work properly. + */ +typedef struct __GLXcontextRec { + Display *currentDpy; + GLboolean isDirect; + GLXDrawable currentDrawable; + GLXDrawable currentReadable; + XID xid; +} __GLXcontext; +#endif + + +/* + * Almost all the GLX API functions get routed through this dispatch table. + * The exceptions are the glXGetCurrentXXX() functions. + * + * This dispatch table allows multiple GLX client-side modules to coexist. + * Specifically, a real GLX library (like SGI's or the Utah GLX) and Mesa's + * pseudo-GLX can be present at the same time. The former being used on + * GLX-enabled X servers and the later on non-GLX X servers. + * + * Red Hat has been using this since Red Hat Linux 7.0 (I think). + * This'll be a standard feature in XFree86 4.3. It basically allows one + * libGL to do both DRI-rendering and "fake GLX" rendering to X displays + * that lack the GLX extension. + */ +struct _glxapi_table { + /*** GLX_VERSION_1_0 ***/ + XVisualInfo *(*ChooseVisual)(Display *dpy, int screen, int *list); + void (*CopyContext)(Display *dpy, GLXContext src, GLXContext dst, unsigned long mask); + GLXContext (*CreateContext)(Display *dpy, XVisualInfo *visinfo, GLXContext shareList, Bool direct); + GLXPixmap (*CreateGLXPixmap)(Display *dpy, XVisualInfo *visinfo, Pixmap pixmap); + void (*DestroyContext)(Display *dpy, GLXContext ctx); + void (*DestroyGLXPixmap)(Display *dpy, GLXPixmap pixmap); + int (*GetConfig)(Display *dpy, XVisualInfo *visinfo, int attrib, int *value); + /*GLXContext (*GetCurrentContext)(void);*/ + /*GLXDrawable (*GetCurrentDrawable)(void);*/ + Bool (*IsDirect)(Display *dpy, GLXContext ctx); + Bool (*MakeCurrent)(Display *dpy, GLXDrawable drawable, GLXContext ctx); + Bool (*QueryExtension)(Display *dpy, int *errorb, int *event); + Bool (*QueryVersion)(Display *dpy, int *maj, int *min); + void (*SwapBuffers)(Display *dpy, GLXDrawable drawable); + void (*UseXFont)(Font font, int first, int count, int listBase); + void (*WaitGL)(void); + void (*WaitX)(void); + + /*** GLX_VERSION_1_1 ***/ + const char *(*GetClientString)(Display *dpy, int name); + const char *(*QueryExtensionsString)(Display *dpy, int screen); + const char *(*QueryServerString)(Display *dpy, int screen, int name); + + /*** GLX_VERSION_1_2 ***/ + /*Display *(*GetCurrentDisplay)(void);*/ + + /*** GLX_VERSION_1_3 ***/ + GLXFBConfig *(*ChooseFBConfig)(Display *dpy, int screen, const int *attribList, int *nitems); + GLXContext (*CreateNewContext)(Display *dpy, GLXFBConfig config, int renderType, GLXContext shareList, Bool direct); + GLXPbuffer (*CreatePbuffer)(Display *dpy, GLXFBConfig config, const int *attribList); + GLXPixmap (*CreatePixmap)(Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attribList); + GLXWindow (*CreateWindow)(Display *dpy, GLXFBConfig config, Window win, const int *attribList); + void (*DestroyPbuffer)(Display *dpy, GLXPbuffer pbuf); + void (*DestroyPixmap)(Display *dpy, GLXPixmap pixmap); + void (*DestroyWindow)(Display *dpy, GLXWindow window); + /*GLXDrawable (*GetCurrentReadDrawable)(void);*/ + int (*GetFBConfigAttrib)(Display *dpy, GLXFBConfig config, int attribute, int *value); + GLXFBConfig *(*GetFBConfigs)(Display *dpy, int screen, int *nelements); + void (*GetSelectedEvent)(Display *dpy, GLXDrawable drawable, unsigned long *mask); + XVisualInfo *(*GetVisualFromFBConfig)(Display *dpy, GLXFBConfig config); + Bool (*MakeContextCurrent)(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx); + int (*QueryContext)(Display *dpy, GLXContext ctx, int attribute, int *value); + void (*QueryDrawable)(Display *dpy, GLXDrawable draw, int attribute, unsigned int *value); + void (*SelectEvent)(Display *dpy, GLXDrawable drawable, unsigned long mask); + + /*** GLX_SGI_swap_control ***/ + int (*SwapIntervalSGI)(int); + + /*** GLX_SGI_video_sync ***/ + int (*GetVideoSyncSGI)(unsigned int *count); + int (*WaitVideoSyncSGI)(int divisor, int remainder, unsigned int *count); + + /*** GLX_SGI_make_current_read ***/ + Bool (*MakeCurrentReadSGI)(Display *, GLXDrawable, GLXDrawable, GLXContext); + /*GLXDrawable (*GetCurrentReadDrawableSGI)(void);*/ + + /*** GLX_SGIX_video_source (needs video library) ***/ +#if defined(_VL_H_) + GLXVideoSourceSGIX (*CreateGLXVideoSourceSGIX)(Display *, int, VLServer, VLPath, int, VLNode); + void (*DestroyGLXVideoSourceSGIX)(Display *, GLXVideoSourceSGIX); +#else + void *CreateGLXVideoSourceSGIX; + void *DestroyGLXVideoSourceSGIX; +#endif + + /*** GLX_EXT_import_context ***/ + void (*FreeContextEXT)(Display *dpy, GLXContext context); + GLXContextID (*GetContextIDEXT)(const GLXContext context); + /*Display *(*GetCurrentDisplayEXT)(void);*/ + GLXContext (*ImportContextEXT)(Display *dpy, GLXContextID contextID); + int (*QueryContextInfoEXT)(Display *dpy, GLXContext context, int attribute,int *value); + + /*** GLX_SGIX_fbconfig ***/ + int (*GetFBConfigAttribSGIX)(Display *, GLXFBConfigSGIX, int, int *); + GLXFBConfigSGIX * (*ChooseFBConfigSGIX)(Display *, int, int *, int *); + GLXPixmap (*CreateGLXPixmapWithConfigSGIX)(Display *, GLXFBConfigSGIX, Pixmap); + GLXContext (*CreateContextWithConfigSGIX)(Display *, GLXFBConfigSGIX, int, GLXContext, Bool); + XVisualInfo * (*GetVisualFromFBConfigSGIX)(Display *, GLXFBConfigSGIX); + GLXFBConfigSGIX (*GetFBConfigFromVisualSGIX)(Display *, XVisualInfo *); + + /*** GLX_SGIX_pbuffer ***/ + GLXPbufferSGIX (*CreateGLXPbufferSGIX)(Display *, GLXFBConfigSGIX, unsigned int, unsigned int, int *); + void (*DestroyGLXPbufferSGIX)(Display *, GLXPbufferSGIX); + int (*QueryGLXPbufferSGIX)(Display *, GLXPbufferSGIX, int, unsigned int *); + void (*SelectEventSGIX)(Display *, GLXDrawable, unsigned long); + void (*GetSelectedEventSGIX)(Display *, GLXDrawable, unsigned long *); + + /*** GLX_SGI_cushion ***/ + void (*CushionSGI)(Display *, Window, float); + + /*** GLX_SGIX_video_resize ***/ + int (*BindChannelToWindowSGIX)(Display *, int, int, Window); + int (*ChannelRectSGIX)(Display *, int, int, int, int, int, int); + int (*QueryChannelRectSGIX)(Display *, int, int, int *, int *, int *, int *); + int (*QueryChannelDeltasSGIX)(Display *, int, int, int *, int *, int *, int *); + int (*ChannelRectSyncSGIX)(Display *, int, int, GLenum); + + /*** GLX_SGIX_dmbuffer (needs dmedia library) ***/ +#if defined (_DM_BUFFER_H_) + Bool (*AssociateDMPbufferSGIX)(Display *, GLXPbufferSGIX, DMparams *, DMbuffer); +#else + void *AssociciateDMPbufferSGIX; +#endif + + /*** GLX_SGIX_swap_group ***/ + void (*JoinSwapGroupSGIX)(Display *, GLXDrawable, GLXDrawable); + + /*** GLX_SGIX_swap_barrier ***/ + void (*BindSwapBarrierSGIX)(Display *, GLXDrawable, int); + Bool (*QueryMaxSwapBarriersSGIX)(Display *, int, int *); + + /*** GLX_SUN_get_transparent_index ***/ + Status (*GetTransparentIndexSUN)(Display *, Window, Window, long *); + + /*** GLX_MESA_copy_sub_buffer ***/ + void (*CopySubBufferMESA)(Display *dpy, GLXDrawable drawable, int x, int y, int width, int height); + + /*** GLX_MESA_release_buffers ***/ + Bool (*ReleaseBuffersMESA)(Display *dpy, Window w); + + /*** GLX_MESA_pixmap_colormap ***/ + GLXPixmap (*CreateGLXPixmapMESA)(Display *dpy, XVisualInfo *visinfo, Pixmap pixmap, Colormap cmap); + + /*** GLX_MESA_set_3dfx_mode ***/ + Bool (*Set3DfxModeMESA)(int mode); + + /*** GLX_NV_vertex_array_range ***/ + void * (*AllocateMemoryNV)( GLsizei size, + GLfloat readFrequency, + GLfloat writeFrequency, + GLfloat priority ); + void (*FreeMemoryNV)( GLvoid *pointer ); + + /*** GLX_MESA_agp_offset ***/ + GLuint (*GetAGPOffsetMESA)( const GLvoid *pointer ); + + /*** GLX_ARB_render_texture ***/ + Bool (*BindTexImageARB)(Display *dpy, GLXPbuffer pbuffer, int buffer); + Bool (*ReleaseTexImageARB)(Display *dpy, GLXPbuffer pbuffer, int buffer); + Bool (*DrawableAttribARB)(Display *dpy, GLXDrawable draw, const int *attribList); +}; + + + +extern const char * +_glxapi_get_version(void); + + +extern const char ** +_glxapi_get_extensions(void); + + +extern GLuint +_glxapi_get_dispatch_table_size(void); + + +extern void +_glxapi_set_no_op_table(struct _glxapi_table *t); + + +extern __GLXextFuncPtr +_glxapi_get_proc_address(const char *funcName); + + +#endif diff --git a/src/mesa/drivers/x11/glxheader.h b/src/mesa/drivers/x11/glxheader.h new file mode 100644 index 0000000..b583400 --- /dev/null +++ b/src/mesa/drivers/x11/glxheader.h @@ -0,0 +1,71 @@ + +/* + * Mesa 3-D graphics library + * Version: 4.1 + * + * Copyright (C) 1999-2002 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. + */ + + +#ifndef GLX_HEADER_H +#define GLX_HEADER_H + +#ifdef __VMS +#include +#endif + +#ifdef HAVE_CONFIG_H +#include "conf.h" +#endif + + +#include "glheader.h" + + +#ifdef XFree86Server + +# include "resource.h" +# include "windowstr.h" +# include "gcstruct.h" +# include "GL/xf86glx.h" +# include "xf86glx_util.h" + +#else + +# include +# include +# ifdef USE_XSHM /* was SHM */ +# include +# include +# include +# endif +# include + +#endif + + + +/* this silences a compiler warning on several systems */ +struct timespec; +struct itimerspec; + + + +#endif /*GLX_HEADER*/ diff --git a/src/mesa/drivers/x11/realglx.c b/src/mesa/drivers/x11/realglx.c new file mode 100644 index 0000000..520f0f1 --- /dev/null +++ b/src/mesa/drivers/x11/realglx.c @@ -0,0 +1,185 @@ + +/* + * Mesa 3-D graphics library + * Version: 5.1 + * + * Copyright (C) 1999-2002 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. + */ + + +#include +#include +#include "realglx.h" +#include "glxapi.h" + + +struct _glxapi_table * +_real_GetGLXDispatchTable(void) +{ + static struct _glxapi_table glx; + + /* be sure our dispatch table size <= libGL's table */ + { + GLuint size = sizeof(struct _glxapi_table) / sizeof(void *); + (void) size; + assert(_glxapi_get_dispatch_table_size() >= size); + } + + /* initialize the whole table to no-ops */ + _glxapi_set_no_op_table(&glx); + + /* now initialize the table with the functions I implement */ + + /*** GLX_VERSION_1_0 ***/ + glx.ChooseVisual = _real_glXChooseVisual; + glx.CopyContext = _real_glXCopyContext; + glx.CreateContext = _real_glXCreateContext; + glx.CreateGLXPixmap = _real_glXCreateGLXPixmap; + glx.DestroyContext = _real_glXDestroyContext; + glx.DestroyGLXPixmap = _real_glXDestroyGLXPixmap; + glx.GetConfig = _real_glXGetConfig; + /*glx.GetCurrentContext = _real_glXGetCurrentContext;*/ + /*glx.GetCurrentDrawable = _real_glXGetCurrentDrawable;*/ + glx.IsDirect = _real_glXIsDirect; + glx.MakeCurrent = _real_glXMakeCurrent; + glx.QueryExtension = _real_glXQueryExtension; + glx.QueryVersion = _real_glXQueryVersion; + glx.SwapBuffers = _real_glXSwapBuffers; + glx.UseXFont = _real_glXUseXFont; + glx.WaitGL = _real_glXWaitGL; + glx.WaitX = _real_glXWaitX; + + /*** GLX_VERSION_1_1 ***/ + glx.GetClientString = _real_glXGetClientString; + glx.QueryExtensionsString = _real_glXQueryExtensionsString; + glx.QueryServerString = _real_glXQueryServerString; + + /*** GLX_VERSION_1_2 ***/ + /*glx.GetCurrentDisplay = _real_glXGetCurrentDisplay;*/ + + /*** GLX_VERSION_1_3 ***/ + glx.ChooseFBConfig = _real_glXChooseFBConfig; + glx.CreateNewContext = _real_glXCreateNewContext; + glx.CreatePbuffer = _real_glXCreatePbuffer; + glx.CreatePixmap = _real_glXCreatePixmap; + glx.CreateWindow = _real_glXCreateWindow; + glx.DestroyPbuffer = _real_glXDestroyPbuffer; + glx.DestroyPixmap = _real_glXDestroyPixmap; + glx.DestroyWindow = _real_glXDestroyWindow; + /*glx.GetCurrentReadDrawable = _real_glXGetCurrentReadDrawable;*/ + glx.GetFBConfigAttrib = _real_glXGetFBConfigAttrib; + glx.GetFBConfigs = _real_glXGetFBConfigs; + glx.GetSelectedEvent = _real_glXGetSelectedEvent; + glx.GetVisualFromFBConfig = _real_glXGetVisualFromFBConfig; + glx.MakeContextCurrent = _real_glXMakeContextCurrent; + glx.QueryContext = _real_glXQueryContext; + glx.QueryDrawable = _real_glXQueryDrawable; + glx.SelectEvent = _real_glXSelectEvent; + + /*** GLX_SGI_swap_control ***/ + glx.SwapIntervalSGI = _real_glXSwapIntervalSGI; + + /*** GLX_SGI_video_sync ***/ + glx.GetVideoSyncSGI = _real_glXGetVideoSyncSGI; + glx.WaitVideoSyncSGI = _real_glXWaitVideoSyncSGI; + + /*** GLX_SGI_make_current_read ***/ + glx.MakeCurrentReadSGI = _real_glXMakeCurrentReadSGI; + /*glx.GetCurrentReadDrawableSGI = _real_glXGetCurrentReadDrawableSGI;*/ + +#if defined(_VL_H) + /*** GLX_SGIX_video_source ***/ + glx.CreateGLXVideoSourceSGIX = _real_glXCreateGLXVideoSourceSGIX; + glx.DestroyGLXVideoSourceSGIX = _real_glXDestroyGLXVideoSourceSGIX; +#endif + + /*** GLX_EXT_import_context ***/ + glx.FreeContextEXT = _real_glXFreeContextEXT; + /*glx.GetContextIDEXT = _real_glXGetContextIDEXT;*/ + /*glx.GetCurrentDisplayEXT = _real_glXGetCurrentDisplayEXT;*/ + glx.ImportContextEXT = _real_glXImportContextEXT; + glx.QueryContextInfoEXT = _real_glXQueryContextInfoEXT; + + /*** GLX_SGIX_fbconfig ***/ + glx.GetFBConfigAttribSGIX = _real_glXGetFBConfigAttribSGIX; + glx.ChooseFBConfigSGIX = _real_glXChooseFBConfigSGIX; + glx.CreateGLXPixmapWithConfigSGIX = _real_glXCreateGLXPixmapWithConfigSGIX; + glx.CreateContextWithConfigSGIX = _real_glXCreateContextWithConfigSGIX; + glx.GetVisualFromFBConfigSGIX = _real_glXGetVisualFromFBConfigSGIX; + glx.GetFBConfigFromVisualSGIX = _real_glXGetFBConfigFromVisualSGIX; + + /*** GLX_SGIX_pbuffer ***/ + glx.CreateGLXPbufferSGIX = _real_glXCreateGLXPbufferSGIX; + glx.DestroyGLXPbufferSGIX = _real_glXDestroyGLXPbufferSGIX; + glx.QueryGLXPbufferSGIX = _real_glXQueryGLXPbufferSGIX; + glx.SelectEventSGIX = _real_glXSelectEventSGIX; + glx.GetSelectedEventSGIX = _real_glXGetSelectedEventSGIX; + + /*** GLX_SGI_cushion ***/ + glx.CushionSGI = _real_glXCushionSGI; + + /*** GLX_SGIX_video_resize ***/ + glx.BindChannelToWindowSGIX = _real_glXBindChannelToWindowSGIX; + glx.ChannelRectSGIX = _real_glXChannelRectSGIX; + glx.QueryChannelRectSGIX = _real_glXQueryChannelRectSGIX; + glx.QueryChannelDeltasSGIX = _real_glXQueryChannelDeltasSGIX; + glx.ChannelRectSyncSGIX = _real_glXChannelRectSyncSGIX; + +#if defined(_DM_BUFFER_H_) + /*** (GLX_SGIX_dmbuffer ***/ + glx.AssociateDMPbufferSGIX = NULL; +#endif + + /*** GLX_SGIX_swap_group ***/ + glx.JoinSwapGroupSGIX = _real_glXJoinSwapGroupSGIX; + + /*** GLX_SGIX_swap_barrier ***/ + glx.BindSwapBarrierSGIX = _real_glXBindSwapBarrierSGIX; + glx.QueryMaxSwapBarriersSGIX = _real_glXQueryMaxSwapBarriersSGIX; + + /*** GLX_SUN_get_transparent_index ***/ + glx.GetTransparentIndexSUN = _real_glXGetTransparentIndexSUN; + + /*** GLX_MESA_copy_sub_buffer ***/ + glx.CopySubBufferMESA = _real_glXCopySubBufferMESA; + + /*** GLX_MESA_release_buffers ***/ + glx.ReleaseBuffersMESA = _real_glXReleaseBuffersMESA; + + /*** GLX_MESA_pixmap_colormap ***/ + glx.CreateGLXPixmapMESA = _real_glXCreateGLXPixmapMESA; + + /*** GLX_MESA_set_3dfx_mode ***/ + glx.Set3DfxModeMESA = _real_glXSet3DfxModeMESA; + + /*** GLX_NV_vertex_array_range ***/ + glx.AllocateMemoryNV = _real_glXAllocateMemoryNV; + glx.FreeMemoryNV = _real_glXFreeMemoryNV; + + /*** GLX_MESA_agp_offset ***/ + glx.GetAGPOffsetMESA = _real_glXGetAGPOffsetMESA; + + /*** GLX_ARB_render_texture ***/ + glx.BindTexImageARB = _real_glXBindTexImageARB; + glx.ReleaseTexImageARB = _real_glXReleaseTexImageARB; + glx.DrawableAttribARB = _real_glXDrawableAttribARB; + + return &glx; +} diff --git a/src/mesa/drivers/x11/realglx.h b/src/mesa/drivers/x11/realglx.h new file mode 100644 index 0000000..150129d --- /dev/null +++ b/src/mesa/drivers/x11/realglx.h @@ -0,0 +1,326 @@ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2001 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. + */ + + +#ifndef REALGLX_H +#define REALGLX_H + + +extern struct _glxapi_table * +_real_GetGLXDispatchTable(void); + + +/* + * Basically just need these to prevent compiler warnings. + */ + + +extern XVisualInfo * +_real_glXChooseVisual( Display *dpy, int screen, int *list ); + +extern GLXContext +_real_glXCreateContext( Display *dpy, XVisualInfo *visinfo, + GLXContext share_list, Bool direct ); + +extern GLXPixmap +_real_glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, Pixmap pixmap ); + +extern GLXPixmap +_real_glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo, + Pixmap pixmap, Colormap cmap ); + +extern void +_real_glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap ); + +extern void +_real_glXCopyContext( Display *dpy, GLXContext src, GLXContext dst, + unsigned long mask ); + +extern Bool +_real_glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx ); + +extern Bool +_real_glXQueryExtension( Display *dpy, int *errorb, int *event ); + +extern void +_real_glXDestroyContext( Display *dpy, GLXContext ctx ); + +extern Bool +_real_glXIsDirect( Display *dpy, GLXContext ctx ); + +extern void +_real_glXSwapBuffers( Display *dpy, GLXDrawable drawable ); + +extern void +_real_glXUseXFont( Font font, int first, int count, int listbase ); + +extern Bool +_real_glXQueryVersion( Display *dpy, int *maj, int *min ); + +extern int +_real_glXGetConfig( Display *dpy, XVisualInfo *visinfo, + int attrib, int *value ); + +extern void +_real_glXWaitGL( void ); + + +extern void +_real_glXWaitX( void ); + +/* GLX 1.1 and later */ +extern const char * +_real_glXQueryExtensionsString( Display *dpy, int screen ); + +/* GLX 1.1 and later */ +extern const char * +_real_glXQueryServerString( Display *dpy, int screen, int name ); + +/* GLX 1.1 and later */ +extern const char * +_real_glXGetClientString( Display *dpy, int name ); + + +/* + * GLX 1.3 and later + */ + +extern GLXFBConfig * +_real_glXChooseFBConfig( Display *dpy, int screen, + const int *attribList, int *nitems ); + +extern int +_real_glXGetFBConfigAttrib( Display *dpy, GLXFBConfig config, + int attribute, int *value ); + +extern GLXFBConfig * +_real_glXGetFBConfigs( Display *dpy, int screen, int *nelements ); + +extern XVisualInfo * +_real_glXGetVisualFromFBConfig( Display *dpy, GLXFBConfig config ); + +extern GLXWindow +_real_glXCreateWindow( Display *dpy, GLXFBConfig config, Window win, + const int *attribList ); + +extern void +_real_glXDestroyWindow( Display *dpy, GLXWindow window ); + +extern GLXPixmap +_real_glXCreatePixmap( Display *dpy, GLXFBConfig config, Pixmap pixmap, + const int *attribList ); + +extern void +_real_glXDestroyPixmap( Display *dpy, GLXPixmap pixmap ); + +extern GLXPbuffer +_real_glXCreatePbuffer( Display *dpy, GLXFBConfig config, + const int *attribList ); + +extern void +_real_glXDestroyPbuffer( Display *dpy, GLXPbuffer pbuf ); + +extern void +_real_glXQueryDrawable( Display *dpy, GLXDrawable draw, int attribute, + unsigned int *value ); + +extern GLXContext +_real_glXCreateNewContext( Display *dpy, GLXFBConfig config, + int renderType, GLXContext shareList, Bool direct ); + + +extern Bool +_real_glXMakeContextCurrent( Display *dpy, GLXDrawable draw, + GLXDrawable read, GLXContext ctx ); + +extern int +_real_glXQueryContext( Display *dpy, GLXContext ctx, int attribute, int *value ); + +extern void +_real_glXSelectEvent( Display *dpy, GLXDrawable drawable, unsigned long mask ); + +extern void +_real_glXGetSelectedEvent( Display *dpy, GLXDrawable drawable, + unsigned long *mask ); + +#ifdef GLX_SGI_swap_control +extern int +_real_glXSwapIntervalSGI(int interval); +#endif + + +#ifdef GLX_SGI_video_sync +extern int +_real_glXGetVideoSyncSGI(unsigned int *count); + +extern int +_real_glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count); +#endif + + +#ifdef GLX_SGI_make_current_read +extern Bool +_real_glXMakeCurrentReadSGI(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx); + +extern GLXDrawable +_real_glXGetCurrentReadDrawableSGI(void); +#endif + +#if defined(_VL_H) && defined(GLX_SGIX_video_source) +extern GLXVideoSourceSGIX +_real_glXCreateGLXVideoSourceSGIX(Display *dpy, int screen, VLServer server, VLPath path, int nodeClass, VLNode drainNode); + +extern void +_real_glXDestroyGLXVideoSourceSGIX(Display *dpy, GLXVideoSourceSGIX src); +#endif + +#ifdef GLX_EXT_import_context +extern void +_real_glXFreeContextEXT(Display *dpy, GLXContext context); + +extern GLXContextID +_real_glXGetContextIDEXT(const GLXContext context); + +extern Display * +_real_glXGetCurrentDisplayEXT(void); + +extern GLXContext +_real_glXImportContextEXT(Display *dpy, GLXContextID contextID); + +extern int +_real_glXQueryContextInfoEXT(Display *dpy, GLXContext context, int attribute, int *value); +#endif + +#ifdef GLX_SGIX_fbconfig +extern int +_real_glXGetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config, int attribute, int *value); + +extern GLXFBConfigSGIX * +_real_glXChooseFBConfigSGIX(Display *dpy, int screen, int *attrib_list, int *nelements); + +extern GLXPixmap +_real_glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, Pixmap pixmap); + +extern GLXContext +_real_glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct); + +extern XVisualInfo * +_real_glXGetVisualFromFBConfigSGIX(Display *dpy, GLXFBConfigSGIX config); + +extern GLXFBConfigSGIX +_real_glXGetFBConfigFromVisualSGIX(Display *dpy, XVisualInfo *vis); +#endif + +#ifdef GLX_SGIX_pbuffer +extern GLXPbufferSGIX +_real_glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height, int *attrib_list); + +extern void +_real_glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf); + +extern int +_real_glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int *value); + +extern void +_real_glXSelectEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long mask); + +extern void +_real_glXGetSelectedEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long *mask); +#endif + +#ifdef GLX_SGI_cushion +extern void +_real_glXCushionSGI(Display *dpy, Window win, float cushion); +#endif + +#ifdef GLX_SGIX_video_resize +extern int +_real_glXBindChannelToWindowSGIX(Display *dpy, int screen, int channel , Window window); + +extern int +_real_glXChannelRectSGIX(Display *dpy, int screen, int channel, int x, int y, int w, int h); + +extern int +_real_glXQueryChannelRectSGIX(Display *dpy, int screen, int channel, int *x, int *y, int *w, int *h); + +extern int +_real_glXQueryChannelDeltasSGIX(Display *dpy, int screen, int channel, int *dx, int *dy, int *dw, int *dh); + +extern int +_real_glXChannelRectSyncSGIX(Display *dpy, int screen, int channel, GLenum synctype); +#endif + +#if defined(_DM_BUFFER_H_) && defined(GLX_SGIX_dmbuffer) +extern Bool +_real_glXAssociateDMPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuffer, DMparams *params, DMbuffer dmbuffer); +#endif + +#ifdef GLX_SGIX_swap_group +extern void +_real_glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable, GLXDrawable member); +#endif + +#ifdef GLX_SGIX_swap_barrier +extern void +_real_glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable, int barrier); + +extern Bool +_real_glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max); +#endif + +#ifdef GLX_SUN_get_transparent_index +extern Status +_real_glXGetTransparentIndexSUN(Display *dpy, Window overlay, Window underlay, long *pTransparent); +#endif + +#ifdef GLX_MESA_release_buffers +extern Bool +_real_glXReleaseBuffersMESA( Display *dpy, GLXDrawable d ); +#endif + +#ifdef GLX_MESA_set_3dfx_mode +extern Bool +_real_glXSet3DfxModeMESA( int mode ); +#endif + +#ifdef GLX_NV_vertex_array_range +extern void * +_real_glXAllocateMemoryNV(GLsizei size, GLfloat readfreq, GLfloat writefreq, GLfloat priority); +extern void +_real_glXFreeMemoryNV(GLvoid *pointer); +#endif + +#ifdef GLX_MESA_agp_offset +extern GLuint +_real_glXGetAGPOffsetMESA(const GLvoid *pointer); +#endif + +#ifdef GLX_MESA_copy_sub_buffer +extern void +_real_glXCopySubBufferMESA( Display *dpy, GLXDrawable drawable, + int x, int y, int width, int height ); +#endif + +#endif /* REALGLX_H */ diff --git a/src/mesa/drivers/x11/xfonts.c b/src/mesa/drivers/x11/xfonts.c new file mode 100644 index 0000000..d72c600 --- /dev/null +++ b/src/mesa/drivers/x11/xfonts.c @@ -0,0 +1,377 @@ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2000 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. + */ + + +/* xfonts.c -- glXUseXFont() for Mesa written by + * Copyright (C) 1995 Thorsten.Ohl @ Physik.TH-Darmstadt.de + */ + +#ifdef __VMS +#include +#endif + +#include "glxheader.h" +#include "context.h" +#include "imports.h" +#include "xfonts.h" + + +/* Some debugging info. */ + +#ifdef DEBUG +#undef _R +#undef _G +#undef _B +#include + +int debug_xfonts = 0; + +static void +dump_char_struct(XCharStruct * ch, char *prefix) +{ + printf("%slbearing = %d, rbearing = %d, width = %d\n", + prefix, ch->lbearing, ch->rbearing, ch->width); + printf("%sascent = %d, descent = %d, attributes = %u\n", + prefix, ch->ascent, ch->descent, (unsigned int) ch->attributes); +} + +static void +dump_font_struct(XFontStruct * font) +{ + printf("ascent = %d, descent = %d\n", font->ascent, font->descent); + printf("char_or_byte2 = (%u,%u)\n", + font->min_char_or_byte2, font->max_char_or_byte2); + printf("byte1 = (%u,%u)\n", font->min_byte1, font->max_byte1); + printf("all_chars_exist = %s\n", font->all_chars_exist ? "True" : "False"); + printf("default_char = %c (\\%03o)\n", + (char) (isprint(font->default_char) ? font->default_char : ' '), + font->default_char); + dump_char_struct(&font->min_bounds, "min> "); + dump_char_struct(&font->max_bounds, "max> "); +#if 0 + for (c = font->min_char_or_byte2; c <= font->max_char_or_byte2; c++) { + char prefix[8]; + sprintf(prefix, "%d> ", c); + dump_char_struct(&font->per_char[c], prefix); + } +#endif +} + +static void +dump_bitmap(unsigned int width, unsigned int height, GLubyte * bitmap) +{ + unsigned int x, y; + + printf(" "); + for (x = 0; x < 8 * width; x++) + printf("%o", 7 - (x % 8)); + putchar('\n'); + for (y = 0; y < height; y++) { + printf("%3o:", y); + for (x = 0; x < 8 * width; x++) + putchar((bitmap[width * (height - y - 1) + x / 8] & (1 << (7 - (x % + 8)))) + ? '*' : '.'); + printf(" "); + for (x = 0; x < width; x++) + printf("0x%02x, ", bitmap[width * (height - y - 1) + x]); + putchar('\n'); + } +} +#endif /* DEBUG */ + + +/* Implementation. */ + +/* Fill a BITMAP with a character C from thew current font + in the graphics context GC. WIDTH is the width in bytes + and HEIGHT is the height in bits. + + Note that the generated bitmaps must be used with + + glPixelStorei (GL_UNPACK_SWAP_BYTES, GL_FALSE); + glPixelStorei (GL_UNPACK_LSB_FIRST, GL_FALSE); + glPixelStorei (GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei (GL_UNPACK_SKIP_ROWS, 0); + glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + + Possible optimizations: + + * use only one reusable pixmap with the maximum dimensions. + * draw the entire font into a single pixmap (careful with + proportional fonts!). +*/ + + +/* + * Generate OpenGL-compatible bitmap. + */ +static void +fill_bitmap(Display * dpy, Window win, GC gc, + unsigned int width, unsigned int height, + int x0, int y0, unsigned int c, GLubyte * bitmap) +{ + XImage *image; + unsigned int x, y; + Pixmap pixmap; + XChar2b char2b; + + pixmap = XCreatePixmap(dpy, win, 8 * width, height, 1); + XSetForeground(dpy, gc, 0); + XFillRectangle(dpy, pixmap, gc, 0, 0, 8 * width, height); + XSetForeground(dpy, gc, 1); + + char2b.byte1 = (c >> 8) & 0xff; + char2b.byte2 = (c & 0xff); + + XDrawString16(dpy, pixmap, gc, x0, y0, &char2b, 1); + + image = XGetImage(dpy, pixmap, 0, 0, 8 * width, height, 1, XYPixmap); + if (image) { + /* Fill the bitmap (X11 and OpenGL are upside down wrt each other). */ + for (y = 0; y < height; y++) + for (x = 0; x < 8 * width; x++) + if (XGetPixel(image, x, y)) + bitmap[width * (height - y - 1) + x / 8] |= + (1 << (7 - (x % 8))); + XDestroyImage(image); + } + + XFreePixmap(dpy, pixmap); +} + +/* + * determine if a given glyph is valid and return the + * corresponding XCharStruct. + */ +static XCharStruct * +isvalid(XFontStruct * fs, unsigned int which) +{ + unsigned int rows, pages; + unsigned int byte1 = 0, byte2 = 0; + int i, valid = 1; + + rows = fs->max_byte1 - fs->min_byte1 + 1; + pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1; + + if (rows == 1) { + /* "linear" fonts */ + if ((fs->min_char_or_byte2 > which) || (fs->max_char_or_byte2 < which)) + valid = 0; + } + else { + /* "matrix" fonts */ + byte2 = which & 0xff; + byte1 = which >> 8; + if ((fs->min_char_or_byte2 > byte2) || + (fs->max_char_or_byte2 < byte2) || + (fs->min_byte1 > byte1) || (fs->max_byte1 < byte1)) + valid = 0; + } + + if (valid) { + if (fs->per_char) { + if (rows == 1) { + /* "linear" fonts */ + return (fs->per_char + (which - fs->min_char_or_byte2)); + } + else { + /* "matrix" fonts */ + i = ((byte1 - fs->min_byte1) * pages) + + (byte2 - fs->min_char_or_byte2); + return (fs->per_char + i); + } + } + else { + return (&fs->min_bounds); + } + } + return (NULL); +} + + +void +Fake_glXUseXFont(Font font, int first, int count, int listbase) +{ + Display *dpy; + Window win; + Pixmap pixmap; + GC gc; + XGCValues values; + unsigned long valuemask; + XFontStruct *fs; + GLint swapbytes, lsbfirst, rowlength; + GLint skiprows, skippixels, alignment; + unsigned int max_width, max_height, max_bm_width, max_bm_height; + GLubyte *bm; + int i; + + dpy = glXGetCurrentDisplay(); + if (!dpy) + return; /* I guess glXMakeCurrent wasn't called */ + win = RootWindow(dpy, DefaultScreen(dpy)); + + fs = XQueryFont(dpy, font); + if (!fs) { + _mesa_error(NULL, GL_INVALID_VALUE, + "Couldn't get font structure information"); + return; + } + + /* Allocate a bitmap that can fit all characters. */ + max_width = fs->max_bounds.rbearing - fs->min_bounds.lbearing; + max_height = fs->max_bounds.ascent + fs->max_bounds.descent; + max_bm_width = (max_width + 7) / 8; + max_bm_height = max_height; + + bm = (GLubyte *) MALLOC((max_bm_width * max_bm_height) * sizeof(GLubyte)); + if (!bm) { + XFreeFontInfo(NULL, fs, 1); + _mesa_error(NULL, GL_OUT_OF_MEMORY, + "Couldn't allocate bitmap in glXUseXFont()"); + return; + } + +#if 0 + /* get the page info */ + pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1; + firstchar = (fs->min_byte1 << 8) + fs->min_char_or_byte2; + lastchar = (fs->max_byte1 << 8) + fs->max_char_or_byte2; + rows = fs->max_byte1 - fs->min_byte1 + 1; + unsigned int first_char, last_char, pages, rows; +#endif + + /* Save the current packing mode for bitmaps. */ + glGetIntegerv(GL_UNPACK_SWAP_BYTES, &swapbytes); + glGetIntegerv(GL_UNPACK_LSB_FIRST, &lsbfirst); + glGetIntegerv(GL_UNPACK_ROW_LENGTH, &rowlength); + glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skiprows); + glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skippixels); + glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment); + + /* Enforce a standard packing mode which is compatible with + fill_bitmap() from above. This is actually the default mode, + except for the (non)alignment. */ + glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); + glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + pixmap = XCreatePixmap(dpy, win, 10, 10, 1); + values.foreground = BlackPixel(dpy, DefaultScreen(dpy)); + values.background = WhitePixel(dpy, DefaultScreen(dpy)); + values.font = fs->fid; + valuemask = GCForeground | GCBackground | GCFont; + gc = XCreateGC(dpy, pixmap, valuemask, &values); + XFreePixmap(dpy, pixmap); + +#ifdef DEBUG + if (debug_xfonts) + dump_font_struct(fs); +#endif + + for (i = 0; i < count; i++) { + unsigned int width, height, bm_width, bm_height; + GLfloat x0, y0, dx, dy; + XCharStruct *ch; + int x, y; + unsigned int c = first + i; + int list = listbase + i; + int valid; + + /* check on index validity and get the bounds */ + ch = isvalid(fs, c); + if (!ch) { + ch = &fs->max_bounds; + valid = 0; + } + else { + valid = 1; + } + +#ifdef DEBUG + if (debug_xfonts) { + char s[7]; + sprintf(s, isprint(c) ? "%c> " : "\\%03o> ", c); + dump_char_struct(ch, s); + } +#endif + + /* glBitmap()' parameters: + straight from the glXUseXFont(3) manpage. */ + width = ch->rbearing - ch->lbearing; + height = ch->ascent + ch->descent; + x0 = -ch->lbearing; + y0 = ch->descent - 0; /* XXX used to subtract 1 here */ + /* but that caused a conformace failure */ + dx = ch->width; + dy = 0; + + /* X11's starting point. */ + x = -ch->lbearing; + y = ch->ascent; + + /* Round the width to a multiple of eight. We will use this also + for the pixmap for capturing the X11 font. This is slightly + inefficient, but it makes the OpenGL part real easy. */ + bm_width = (width + 7) / 8; + bm_height = height; + + glNewList(list, GL_COMPILE); + if (valid && (bm_width > 0) && (bm_height > 0)) { + + MEMSET(bm, '\0', bm_width * bm_height); + fill_bitmap(dpy, win, gc, bm_width, bm_height, x, y, c, bm); + + glBitmap(width, height, x0, y0, dx, dy, bm); +#ifdef DEBUG + if (debug_xfonts) { + printf("width/height = %u/%u\n", width, height); + printf("bm_width/bm_height = %u/%u\n", bm_width, bm_height); + dump_bitmap(bm_width, bm_height, bm); + } +#endif + } + else { + glBitmap(0, 0, 0.0, 0.0, dx, dy, NULL); + } + glEndList(); + } + + FREE(bm); + XFreeFontInfo(NULL, fs, 1); + XFreeGC(dpy, gc); + + /* Restore saved packing modes. */ + glPixelStorei(GL_UNPACK_SWAP_BYTES, swapbytes); + glPixelStorei(GL_UNPACK_LSB_FIRST, lsbfirst); + glPixelStorei(GL_UNPACK_ROW_LENGTH, rowlength); + glPixelStorei(GL_UNPACK_SKIP_ROWS, skiprows); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, skippixels); + glPixelStorei(GL_UNPACK_ALIGNMENT, alignment); +} diff --git a/src/mesa/drivers/x11/xfonts.h b/src/mesa/drivers/x11/xfonts.h new file mode 100644 index 0000000..e36f42f --- /dev/null +++ b/src/mesa/drivers/x11/xfonts.h @@ -0,0 +1,41 @@ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2000 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. + */ + + +#ifndef XFONTS_H +#define XFONTS_H + +#ifdef __VMS +#include +#endif + +#include + + +extern void Fake_glXUseXFont( Font font, int first, int count, int listbase ); + + +#endif + diff --git a/src/mesa/drivers/x11/xm_api.c b/src/mesa/drivers/x11/xm_api.c new file mode 100644 index 0000000..d714b55 --- /dev/null +++ b/src/mesa/drivers/x11/xm_api.c @@ -0,0 +1,2676 @@ +/* + * Mesa 3-D graphics library + * Version: 6.2.2 + * + * Copyright (C) 1999-2005 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. + */ + +/* + * This file contains the implementations of all the XMesa* functions. + * + * + * NOTES: + * + * The window coordinate system origin (0,0) is in the lower-left corner + * of the window. X11's window coordinate origin is in the upper-left + * corner of the window. Therefore, most drawing functions in this + * file have to flip Y coordinates. + * + * Define USE_XSHM in the Makefile with -DUSE_XSHM if you want to compile + * in support for the MIT Shared Memory extension. If enabled, when you + * use an Ximage for the back buffer in double buffered mode, the "swap" + * operation will be faster. You must also link with -lXext. + * + * Byte swapping: If the Mesa host and the X display use a different + * byte order then there's some trickiness to be aware of when using + * XImages. The byte ordering used for the XImage is that of the X + * display, not the Mesa host. + * The color-to-pixel encoding for True/DirectColor must be done + * according to the display's visual red_mask, green_mask, and blue_mask. + * If XPutPixel is used to put a pixel into an XImage then XPutPixel will + * do byte swapping if needed. If one wants to directly "poke" the pixel + * into the XImage's buffer then the pixel must be byte swapped first. In + * Mesa, when byte swapping is needed we use the PF_TRUECOLOR pixel format + * and use XPutPixel everywhere except in the implementation of + * glClear(GL_COLOR_BUFFER_BIT). We want this function to be fast so + * instead of using XPutPixel we "poke" our values after byte-swapping + * the clear pixel value if needed. + * + */ + +#ifdef __CYGWIN__ +#undef WIN32 +#undef __WIN32__ +#endif + +#include "glxheader.h" +#include "GL/xmesa.h" +#include "xmesaP.h" +#include "context.h" +#include "extensions.h" +#include "glthread.h" +#include "imports.h" +#include "matrix.h" +#include "mtypes.h" +#include "macros.h" +#include "texformat.h" +#include "texobj.h" +#include "texstore.h" +#include "swrast/swrast.h" +#include "swrast_setup/swrast_setup.h" +#include "array_cache/acache.h" +#include "tnl/tnl.h" +#include "tnl/t_context.h" +#include "tnl/t_pipeline.h" +#include "drivers/common/driverfuncs.h" + +#ifdef XFree86Server +#include +#endif + +/* + * Global X driver lock + */ +_glthread_Mutex _xmesa_lock; + + + +/* + * Lookup tables for HPCR pixel format: + */ +static short hpcr_rgbTbl[3][256] = { +{ + 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, + 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31, + 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, +112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, +128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, +144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, +160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, +176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, +192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, +208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, +224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239 +}, +{ + 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 23, + 24, 24, 25, 25, 26, 26, 27, 27, 28, 28, 29, 29, 30, 30, 31, 31, + 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39, + 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, + 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, +112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, +128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, +144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, +160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, +176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, +192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, +208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, +224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239 +}, +{ + 32, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37, 38, 38, 39, 39, + 40, 40, 41, 41, 42, 42, 43, 43, 44, 44, 45, 45, 46, 46, 47, 47, + 48, 48, 49, 49, 50, 50, 51, 51, 52, 52, 53, 53, 54, 54, 55, 55, + 56, 56, 57, 57, 58, 58, 59, 59, 60, 60, 61, 61, 62, 62, 63, 63, + 64, 64, 65, 65, 66, 66, 67, 67, 68, 68, 69, 69, 70, 70, 71, 71, + 72, 72, 73, 73, 74, 74, 75, 75, 76, 76, 77, 77, 78, 78, 79, 79, + 80, 80, 81, 81, 82, 82, 83, 83, 84, 84, 85, 85, 86, 86, 87, 87, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, + 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, +112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, +128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, +144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, +160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, +176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, +192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, +208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223 +} +}; + + + +/**********************************************************************/ +/***** X Utility Functions *****/ +/**********************************************************************/ + + +/* + * Return the host's byte order as LSBFirst or MSBFirst ala X. + */ +#ifndef XFree86Server +static int host_byte_order( void ) +{ + int i = 1; + char *cptr = (char *) &i; + return (*cptr==1) ? LSBFirst : MSBFirst; +} +#endif + + +/* + * Error handling. + */ +#ifndef XFree86Server +static volatile int mesaXErrorFlag = 0; + +static int mesaHandleXError( XMesaDisplay *dpy, XErrorEvent *event ) +{ + (void) dpy; + (void) event; + mesaXErrorFlag = 1; + return 0; +} +#endif + + +/* + * Check if the X Shared Memory extension is available. + * Return: 0 = not available + * 1 = shared XImage support available + * 2 = shared Pixmap support available also + */ +#ifndef XFree86Server +static int check_for_xshm( XMesaDisplay *display ) +{ +#ifdef USE_XSHM + int major, minor, ignore; + Bool pixmaps; + + if (XQueryExtension( display, "MIT-SHM", &ignore, &ignore, &ignore )) { + if (XShmQueryVersion( display, &major, &minor, &pixmaps )==True) { + return (pixmaps==True) ? 2 : 1; + } + else { + return 0; + } + } + else { + return 0; + } +#else + /* Can't compile XSHM support */ + return 0; +#endif +} +#endif + + +/* + * Return the width and height of the given drawable. + */ +static void get_drawable_size( XMesaDisplay *dpy, XMesaDrawable d, + unsigned int *width, unsigned int *height) +{ +#ifdef XFree86Server + (void) dpy; + *width = d->width; + *height = d->height; +#else + Window root; + int x, y; + unsigned int bw, depth; + + _glthread_LOCK_MUTEX(_xmesa_lock); + XGetGeometry( dpy, d, &root, &x, &y, width, height, &bw, &depth ); + _glthread_UNLOCK_MUTEX(_xmesa_lock); +#endif +} + + +/* + * Apply gamma correction to an intensity value in [0..max]. Return the + * new intensity value. + */ +static GLint gamma_adjust( GLfloat gamma, GLint value, GLint max ) +{ + if (gamma == 1.0) { + return value; + } + else { + double x = (double) value / (double) max; + return IROUND_POS((GLfloat) max * _mesa_pow(x, 1.0F/gamma)); + } +} + + + +/* + * Return the true number of bits per pixel for XImages. + * For example, if we request a 24-bit deep visual we may actually need/get + * 32bpp XImages. This function returns the appropriate bpp. + * Input: dpy - the X display + * visinfo - desribes the visual to be used for XImages + * Return: true number of bits per pixel for XImages + */ +#ifdef XFree86Server + +static int bits_per_pixel( XMesaVisual xmv ) +{ + const int depth = xmv->nplanes; + int i; + for (i = 0; i < screenInfo.numPixmapFormats; i++) { + if (screenInfo.formats[i].depth == depth) + return screenInfo.formats[i].bitsPerPixel; + } + return depth; /* should never get here, but this should be safe */ +} + +#else + +static int bits_per_pixel( XMesaVisual xmv ) +{ + XMesaDisplay *dpy = xmv->display; + XMesaVisualInfo visinfo = xmv->visinfo; + XMesaImage *img; + int bitsPerPixel; + /* Create a temporary XImage */ + img = XCreateImage( dpy, visinfo->visual, visinfo->depth, + ZPixmap, 0, /*format, offset*/ + (char*) MALLOC(8), /*data*/ + 1, 1, /*width, height*/ + 32, /*bitmap_pad*/ + 0 /*bytes_per_line*/ + ); + assert(img); + /* grab the bits/pixel value */ + bitsPerPixel = img->bits_per_pixel; + /* free the XImage */ + FREE( img->data ); + img->data = NULL; + XMesaDestroyImage( img ); + return bitsPerPixel; +} +#endif + + + +/* + * Determine if a given X window ID is valid (window exists). + * Do this by calling XGetWindowAttributes() for the window and + * checking if we catch an X error. + * Input: dpy - the display + * win - the window to check for existance + * Return: GL_TRUE - window exists + * GL_FALSE - window doesn't exist + */ +#ifndef XFree86Server +static GLboolean WindowExistsFlag; + +static int window_exists_err_handler( XMesaDisplay* dpy, XErrorEvent* xerr ) +{ + (void) dpy; + if (xerr->error_code == BadWindow) { + WindowExistsFlag = GL_FALSE; + } + return 0; +} + +static GLboolean window_exists( XMesaDisplay *dpy, Window win ) +{ + XWindowAttributes wa; + int (*old_handler)( XMesaDisplay*, XErrorEvent* ); + WindowExistsFlag = GL_TRUE; + old_handler = XSetErrorHandler(window_exists_err_handler); + XGetWindowAttributes( dpy, win, &wa ); /* dummy request */ + XSetErrorHandler(old_handler); + return WindowExistsFlag; +} +#endif + + + +/**********************************************************************/ +/***** Linked list of XMesaBuffers *****/ +/**********************************************************************/ + +static XMesaBuffer XMesaBufferList = NULL; + + +/* Allocate a new XMesaBuffer, add to linked list */ +static XMesaBuffer alloc_xmesa_buffer(void) +{ + XMesaBuffer b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer); + if (b) { + b->Next = XMesaBufferList; + XMesaBufferList = b; + } + return b; +} + + +/* + * Find an XMesaBuffer by matching X display and colormap but NOT matching + * the notThis buffer. + */ +static XMesaBuffer find_xmesa_buffer(XMesaDisplay *dpy, + XMesaColormap cmap, + XMesaBuffer notThis) +{ + XMesaBuffer b; + for (b=XMesaBufferList; b; b=b->Next) { + if (b->display==dpy && b->cmap==cmap && b!=notThis) { + return b; + } + } + return NULL; +} + + +/* + * Free an XMesaBuffer, remove from linked list, perhaps free X colormap + * entries. + */ +static void free_xmesa_buffer(int client, XMesaBuffer buffer) +{ + XMesaBuffer prev = NULL, b; + (void) client; + for (b=XMesaBufferList; b; b=b->Next) { + if (b==buffer) { + /* unlink bufer from list */ + if (prev) + prev->Next = buffer->Next; + else + XMesaBufferList = buffer->Next; + /* Check to free X colors */ + if (buffer->num_alloced>0) { + /* If no other buffer uses this X colormap then free the colors. */ + if (!find_xmesa_buffer(buffer->display, buffer->cmap, buffer)) { +#ifdef XFree86Server + (void)FreeColors(buffer->cmap, client, + buffer->num_alloced, buffer->alloced_colors, + 0); +#else + XFreeColors(buffer->display, buffer->cmap, + buffer->alloced_colors, buffer->num_alloced, 0); +#endif + } + } + + _mesa_free_framebuffer_data(&buffer->mesa_buffer); + FREE(buffer); + + return; + } + /* continue search */ + prev = b; + } + /* buffer not found in XMesaBufferList */ + _mesa_problem(NULL,"free_xmesa_buffer() - buffer not found\n"); +} + + +/* Copy X color table stuff from one XMesaBuffer to another. */ +static void copy_colortable_info(XMesaBuffer dst, const XMesaBuffer src) +{ + MEMCPY(dst->color_table, src->color_table, sizeof(src->color_table)); + MEMCPY(dst->pixel_to_r, src->pixel_to_r, sizeof(src->pixel_to_r)); + MEMCPY(dst->pixel_to_g, src->pixel_to_g, sizeof(src->pixel_to_g)); + MEMCPY(dst->pixel_to_b, src->pixel_to_b, sizeof(src->pixel_to_b)); + dst->num_alloced = src->num_alloced; + MEMCPY(dst->alloced_colors, src->alloced_colors, + sizeof(src->alloced_colors)); +} + + + +/**********************************************************************/ +/***** Misc Private Functions *****/ +/**********************************************************************/ + + +/* + * 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; +} + + + +/* + * Allocate a shared memory XImage back buffer for the given XMesaBuffer. + * Return: GL_TRUE if success, GL_FALSE if error + */ +#ifndef XFree86Server +static GLboolean alloc_shm_back_buffer( XMesaBuffer b ) +{ +#ifdef USE_XSHM + /* + * We have to do a _lot_ of error checking here to be sure we can + * really use the XSHM extension. It seems different servers trigger + * errors at different points if the extension won't work. Therefore + * we have to be very careful... + */ + GC gc; + int (*old_handler)( XMesaDisplay *, XErrorEvent * ); + + b->backimage = XShmCreateImage( b->xm_visual->display, + b->xm_visual->visinfo->visual, + b->xm_visual->visinfo->depth, + ZPixmap, NULL, &b->shminfo, + b->width, b->height ); + if (b->backimage == NULL) { + _mesa_warning(NULL, "alloc_back_buffer: Shared memory error (XShmCreateImage), disabling."); + b->shm = 0; + return GL_FALSE; + } + + b->shminfo.shmid = shmget( IPC_PRIVATE, b->backimage->bytes_per_line + * b->backimage->height, IPC_CREAT|0777 ); + if (b->shminfo.shmid < 0) { + _mesa_warning(NULL, "shmget failed while allocating back buffer"); + XDestroyImage( b->backimage ); + b->backimage = NULL; + _mesa_warning(NULL, "alloc_back_buffer: Shared memory error (shmget), disabling."); + b->shm = 0; + return GL_FALSE; + } + + b->shminfo.shmaddr = b->backimage->data + = (char*)shmat( b->shminfo.shmid, 0, 0 ); + if (b->shminfo.shmaddr == (char *) -1) { + _mesa_warning(NULL, "shmat() failed while allocating back buffer"); + XDestroyImage( b->backimage ); + shmctl( b->shminfo.shmid, IPC_RMID, 0 ); + b->backimage = NULL; + _mesa_warning(NULL, "alloc_back_buffer: Shared memory error (shmat), disabling."); + b->shm = 0; + return GL_FALSE; + } + + b->shminfo.readOnly = False; + mesaXErrorFlag = 0; + old_handler = XSetErrorHandler( mesaHandleXError ); + /* This may trigger the X protocol error we're ready to catch: */ + XShmAttach( b->xm_visual->display, &b->shminfo ); + XSync( b->xm_visual->display, False ); + + if (mesaXErrorFlag) { + /* we are on a remote display, this error is normal, don't print it */ + XFlush( b->xm_visual->display ); + mesaXErrorFlag = 0; + XDestroyImage( b->backimage ); + shmdt( b->shminfo.shmaddr ); + shmctl( b->shminfo.shmid, IPC_RMID, 0 ); + b->backimage = NULL; + b->shm = 0; + (void) XSetErrorHandler( old_handler ); + return GL_FALSE; + } + + shmctl( b->shminfo.shmid, IPC_RMID, 0 ); /* nobody else needs it */ + + /* Finally, try an XShmPutImage to be really sure the extension works */ + gc = XCreateGC( b->xm_visual->display, b->frontbuffer, 0, NULL ); + XShmPutImage( b->xm_visual->display, b->frontbuffer, gc, + b->backimage, 0, 0, 0, 0, 1, 1 /*one pixel*/, False ); + XSync( b->xm_visual->display, False ); + XFreeGC( b->xm_visual->display, gc ); + (void) XSetErrorHandler( old_handler ); + if (mesaXErrorFlag) { + XFlush( b->xm_visual->display ); + mesaXErrorFlag = 0; + XDestroyImage( b->backimage ); + shmdt( b->shminfo.shmaddr ); + shmctl( b->shminfo.shmid, IPC_RMID, 0 ); + b->backimage = NULL; + b->shm = 0; + return GL_FALSE; + } + + if (b->backimage) { + int height = b->backimage->height; + /* Needed by PIXELADDR1 macro */ + b->ximage_width1 = b->backimage->bytes_per_line; + b->ximage_origin1 = (GLubyte *) b->backimage->data + + b->ximage_width1 * (height-1); + /* Needed by PIXELADDR2 macro */ + b->ximage_width2 = b->backimage->bytes_per_line / 2; + b->ximage_origin2 = (GLushort *) b->backimage->data + + b->ximage_width2 * (height-1); + /* Needed by PIXELADDR3 macro */ + b->ximage_width3 = b->backimage->bytes_per_line; + b->ximage_origin3 = (GLubyte *) b->backimage->data + + b->ximage_width3 * (height-1); + /* Needed by PIXELADDR4 macro */ + b->ximage_width4 = b->backimage->width; + b->ximage_origin4 = (GLuint *) b->backimage->data + + b->ximage_width4 * (height-1); + } + + return GL_TRUE; +#else + /* Can't compile XSHM support */ + return GL_FALSE; +#endif +} +#endif + + + +/* + * Setup an off-screen pixmap or Ximage to use as the back buffer. + * Input: b - the X/Mesa buffer + */ +void xmesa_alloc_back_buffer( XMesaBuffer b ) +{ + if (b->db_state==BACK_XIMAGE) { + /* Deallocate the old backimage, if any */ + if (b->backimage) { +#if defined(USE_XSHM) && !defined(XFree86Server) + if (b->shm) { + XShmDetach( b->xm_visual->display, &b->shminfo ); + XDestroyImage( b->backimage ); + shmdt( b->shminfo.shmaddr ); + } + else +#endif + XMesaDestroyImage( b->backimage ); + b->backimage = NULL; + } + + /* Allocate new back buffer */ +#ifdef XFree86Server + { + /* Allocate a regular XImage for the back buffer. */ + b->backimage = XMesaCreateImage(b->xm_visual->BitsPerPixel, + b->width, b->height, NULL); +#else + if (b->shm==0 || alloc_shm_back_buffer(b)==GL_FALSE) { + /* Allocate a regular XImage for the back buffer. */ + b->backimage = XCreateImage( b->xm_visual->display, + b->xm_visual->visinfo->visual, + GET_VISUAL_DEPTH(b->xm_visual), + ZPixmap, 0, /* format, offset */ + NULL, b->width, b->height, + 8, 0 ); /* pad, bytes_per_line */ +#endif + if (!b->backimage) { + _mesa_warning(NULL, "alloc_back_buffer: XCreateImage failed."); + } + b->backimage->data = (char *) MALLOC( b->backimage->height + * b->backimage->bytes_per_line ); + if (!b->backimage->data) { + _mesa_warning(NULL, "alloc_back_buffer: MALLOC failed."); + XMesaDestroyImage( b->backimage ); + b->backimage = NULL; + } + } + b->backpixmap = None; + } + else if (b->db_state==BACK_PIXMAP) { + XMesaPixmap old_pixmap = b->backpixmap; + /* Free the old back pixmap */ + if (b->backpixmap) { + XMesaFreePixmap( b->xm_visual->display, b->backpixmap ); + } + /* Allocate new back pixmap */ + b->backpixmap = XMesaCreatePixmap( b->xm_visual->display, b->frontbuffer, + b->width, b->height, + GET_VISUAL_DEPTH(b->xm_visual) ); + b->backimage = NULL; + /* update other references to backpixmap */ + if (b->buffer==(XMesaDrawable)old_pixmap) { + b->buffer = (XMesaDrawable)b->backpixmap; + } + } +} + + + +/* + * A replacement for XAllocColor. This function should never + * fail to allocate a color. When XAllocColor fails, we return + * the nearest matching color. If we have to allocate many colors + * this function isn't too efficient; the XQueryColors() could be + * done just once. + * Written by Michael Pichler, Brian Paul, Mark Kilgard + * Input: dpy - X display + * cmap - X colormap + * cmapSize - size of colormap + * In/Out: color - the XColor struct + * Output: exact - 1=exact color match, 0=closest match + * alloced - 1=XAlloc worked, 0=XAlloc failed + */ +static void +noFaultXAllocColor( int client, + XMesaDisplay *dpy, + XMesaColormap cmap, + int cmapSize, + XMesaColor *color, + int *exact, int *alloced ) +{ +#ifdef XFree86Server + Pixel *ppixIn; + xrgb *ctable; +#else + /* we'll try to cache ctable for better remote display performance */ + static Display *prevDisplay = NULL; + static XMesaColormap prevCmap = 0; + static int prevCmapSize = 0; + static XMesaColor *ctable = NULL; +#endif + XMesaColor subColor; + int i, bestmatch; + double mindist; /* 3*2^16^2 exceeds long int precision. */ + + (void) client; + + /* First try just using XAllocColor. */ +#ifdef XFree86Server + if (AllocColor(cmap, + &color->red, &color->green, &color->blue, + &color->pixel, + client) == Success) { +#else + if (XAllocColor(dpy, cmap, color)) { +#endif + *exact = 1; + *alloced = 1; + return; + } + + /* Alloc failed, search for closest match */ + + /* Retrieve color table entries. */ + /* XXX alloca candidate. */ +#ifdef XFree86Server + ppixIn = (Pixel *) MALLOC(cmapSize * sizeof(Pixel)); + ctable = (xrgb *) MALLOC(cmapSize * sizeof(xrgb)); + for (i = 0; i < cmapSize; i++) { + ppixIn[i] = i; + } + QueryColors(cmap, cmapSize, ppixIn, ctable); +#else + if (prevDisplay != dpy || prevCmap != cmap + || prevCmapSize != cmapSize || !ctable) { + /* free previously cached color table */ + if (ctable) + FREE(ctable); + /* Get the color table from X */ + ctable = (XMesaColor *) MALLOC(cmapSize * sizeof(XMesaColor)); + assert(ctable); + for (i = 0; i < cmapSize; i++) { + ctable[i].pixel = i; + } + XQueryColors(dpy, cmap, ctable, cmapSize); + prevDisplay = dpy; + prevCmap = cmap; + prevCmapSize = cmapSize; + } +#endif + + /* Find best match. */ + bestmatch = -1; + mindist = 0.0; + for (i = 0; i < cmapSize; i++) { + double dr = 0.30 * ((double) color->red - (double) ctable[i].red); + double dg = 0.59 * ((double) color->green - (double) ctable[i].green); + double db = 0.11 * ((double) color->blue - (double) ctable[i].blue); + double dist = dr * dr + dg * dg + db * db; + if (bestmatch < 0 || dist < mindist) { + bestmatch = i; + mindist = dist; + } + } + + /* Return result. */ + subColor.red = ctable[bestmatch].red; + subColor.green = ctable[bestmatch].green; + subColor.blue = ctable[bestmatch].blue; + /* Try to allocate the closest match color. This should only + * fail if the cell is read/write. Otherwise, we're incrementing + * the cell's reference count. + */ +#ifdef XFree86Server + if (AllocColor(cmap, + &subColor.red, &subColor.green, &subColor.blue, + &subColor.pixel, + client) == Success) { +#else + if (XAllocColor(dpy, cmap, &subColor)) { +#endif + *alloced = 1; + } + else { + /* do this to work around a problem reported by Frank Ortega */ + subColor.pixel = (unsigned long) bestmatch; + subColor.red = ctable[bestmatch].red; + subColor.green = ctable[bestmatch].green; + subColor.blue = ctable[bestmatch].blue; + subColor.flags = DoRed | DoGreen | DoBlue; + *alloced = 0; + } +#ifdef XFree86Server + FREE(ppixIn); + FREE(ctable); +#else + /* don't free table, save it for next time */ +#endif + + *color = subColor; + *exact = 0; +} + + + + +/* + * Do setup for PF_GRAYSCALE pixel format. + * Note that buffer may be NULL. + */ +static GLboolean setup_grayscale( int client, XMesaVisual v, + XMesaBuffer buffer, XMesaColormap cmap ) +{ + if (GET_VISUAL_DEPTH(v)<4 || GET_VISUAL_DEPTH(v)>16) { + return GL_FALSE; + } + + if (buffer) { + XMesaBuffer prevBuffer; + + if (!cmap) { + return GL_FALSE; + } + + prevBuffer = find_xmesa_buffer(v->display, cmap, buffer); + if (prevBuffer && + (buffer->xm_visual->mesa_visual.rgbMode == + prevBuffer->xm_visual->mesa_visual.rgbMode)) { + /* Copy colormap stuff from previous XMesaBuffer which uses same + * X colormap. Do this to avoid time spent in noFaultXAllocColor. + */ + copy_colortable_info(buffer, prevBuffer); + } + else { + /* Allocate 256 shades of gray */ + int gray; + int colorsfailed = 0; + for (gray=0;gray<256;gray++) { + GLint r = gamma_adjust( v->RedGamma, gray, 255 ); + GLint g = gamma_adjust( v->GreenGamma, gray, 255 ); + GLint b = gamma_adjust( v->BlueGamma, gray, 255 ); + int exact, alloced; + XMesaColor xcol; + xcol.red = (r << 8) | r; + xcol.green = (g << 8) | g; + xcol.blue = (b << 8) | b; + noFaultXAllocColor( client, v->display, + cmap, GET_COLORMAP_SIZE(v), + &xcol, &exact, &alloced ); + if (!exact) { + colorsfailed++; + } + if (alloced) { + assert(buffer->num_alloced<256); + buffer->alloced_colors[buffer->num_alloced] = xcol.pixel; + buffer->num_alloced++; + } + + /*OLD + assert(gray < 576); + buffer->color_table[gray*3+0] = xcol.pixel; + buffer->color_table[gray*3+1] = xcol.pixel; + buffer->color_table[gray*3+2] = xcol.pixel; + assert(xcol.pixel < 65536); + buffer->pixel_to_r[xcol.pixel] = gray * 30 / 100; + buffer->pixel_to_g[xcol.pixel] = gray * 59 / 100; + buffer->pixel_to_b[xcol.pixel] = gray * 11 / 100; + */ + buffer->color_table[gray] = xcol.pixel; + assert(xcol.pixel < 65536); + buffer->pixel_to_r[xcol.pixel] = gray; + buffer->pixel_to_g[xcol.pixel] = gray; + buffer->pixel_to_b[xcol.pixel] = gray; + } + + if (colorsfailed && _mesa_getenv("MESA_DEBUG")) { + _mesa_warning(NULL, + "Note: %d out of 256 needed colors do not match exactly.\n", + colorsfailed ); + } + } + } + + v->dithered_pf = PF_Grayscale; + v->undithered_pf = PF_Grayscale; + return GL_TRUE; +} + + + +/* + * Setup RGB rendering for a window with a PseudoColor, StaticColor, + * or 8-bit TrueColor visual visual. We try to allocate a palette of 225 + * colors (5 red, 9 green, 5 blue) and dither to approximate a 24-bit RGB + * color. While this function was originally designed just for 8-bit + * visuals, it has also proven to work from 4-bit up to 16-bit visuals. + * Dithering code contributed by Bob Mercier. + */ +static GLboolean setup_dithered_color( int client, XMesaVisual v, + XMesaBuffer buffer, XMesaColormap cmap ) +{ + if (GET_VISUAL_DEPTH(v)<4 || GET_VISUAL_DEPTH(v)>16) { + return GL_FALSE; + } + + if (buffer) { + XMesaBuffer prevBuffer; + + if (!cmap) { + return GL_FALSE; + } + + prevBuffer = find_xmesa_buffer(v->display, cmap, buffer); + if (prevBuffer && + (buffer->xm_visual->mesa_visual.rgbMode == + prevBuffer->xm_visual->mesa_visual.rgbMode)) { + /* Copy colormap stuff from previous, matching XMesaBuffer. + * Do this to avoid time spent in noFaultXAllocColor. + */ + copy_colortable_info(buffer, prevBuffer); + } + else { + /* Allocate X colors and initialize color_table[], red_table[], etc */ + int r, g, b, i; + int colorsfailed = 0; + for (r = 0; r < DITH_R; r++) { + for (g = 0; g < DITH_G; g++) { + for (b = 0; b < DITH_B; b++) { + XMesaColor xcol; + int exact, alloced; + xcol.red =gamma_adjust(v->RedGamma, r*65535/(DITH_R-1),65535); + xcol.green=gamma_adjust(v->GreenGamma, g*65535/(DITH_G-1),65535); + xcol.blue =gamma_adjust(v->BlueGamma, b*65535/(DITH_B-1),65535); + noFaultXAllocColor( client, v->display, + cmap, GET_COLORMAP_SIZE(v), + &xcol, &exact, &alloced ); + if (!exact) { + colorsfailed++; + } + if (alloced) { + assert(buffer->num_alloced<256); + buffer->alloced_colors[buffer->num_alloced] = xcol.pixel; + buffer->num_alloced++; + } + i = DITH_MIX( r, g, b ); + assert(i < 576); + buffer->color_table[i] = xcol.pixel; + assert(xcol.pixel < 65536); + buffer->pixel_to_r[xcol.pixel] = r * 255 / (DITH_R-1); + buffer->pixel_to_g[xcol.pixel] = g * 255 / (DITH_G-1); + buffer->pixel_to_b[xcol.pixel] = b * 255 / (DITH_B-1); + } + } + } + + if (colorsfailed && _mesa_getenv("MESA_DEBUG")) { + _mesa_warning(NULL, + "Note: %d out of %d needed colors do not match exactly.\n", + colorsfailed, DITH_R * DITH_G * DITH_B ); + } + } + } + + v->dithered_pf = PF_Dither; + v->undithered_pf = PF_Lookup; + return GL_TRUE; +} + + +/* + * Setup for Hewlett Packard Color Recovery 8-bit TrueColor mode. + * HPCR simulates 24-bit color fidelity with an 8-bit frame buffer. + * Special dithering tables have to be initialized. + */ +static void setup_8bit_hpcr( XMesaVisual v ) +{ + /* HP Color Recovery contributed by: Alex De Bruyn (ad@lms.be) + * To work properly, the atom _HP_RGB_SMOOTH_MAP_LIST must be defined + * on the root window AND the colormap obtainable by XGetRGBColormaps + * for that atom must be set on the window. (see also tkInitWindow) + * If that colormap is not set, the output will look stripy. + */ + + /* Setup color tables with gamma correction */ + int i; + double g; + + g = 1.0 / v->RedGamma; + for (i=0; i<256; i++) { + GLint red = IROUND_POS(255.0 * _mesa_pow( hpcr_rgbTbl[0][i]/255.0, g )); + v->hpcr_rgbTbl[0][i] = CLAMP( red, 16, 239 ); + } + + g = 1.0 / v->GreenGamma; + for (i=0; i<256; i++) { + GLint green = IROUND_POS(255.0 * _mesa_pow( hpcr_rgbTbl[1][i]/255.0, g )); + v->hpcr_rgbTbl[1][i] = CLAMP( green, 16, 239 ); + } + + g = 1.0 / v->BlueGamma; + for (i=0; i<256; i++) { + GLint blue = IROUND_POS(255.0 * _mesa_pow( hpcr_rgbTbl[2][i]/255.0, g )); + v->hpcr_rgbTbl[2][i] = CLAMP( blue, 32, 223 ); + } + v->undithered_pf = PF_HPCR; /* can't really disable dithering for now */ + v->dithered_pf = PF_HPCR; + + /* which method should I use to clear */ + /* GL_FALSE: keep the ordinary method */ + /* GL_TRUE : clear with dither pattern */ + v->hpcr_clear_flag = _mesa_getenv("MESA_HPCR_CLEAR") ? GL_TRUE : GL_FALSE; + + if (v->hpcr_clear_flag) { + v->hpcr_clear_pixmap = XMesaCreatePixmap(v->display, + DefaultRootWindow(v->display), + 16, 2, 8); +#ifndef XFree86Server + v->hpcr_clear_ximage = XGetImage(v->display, v->hpcr_clear_pixmap, + 0, 0, 16, 2, AllPlanes, ZPixmap); +#endif + } +} + + +/* + * Setup RGB rendering for a window with a True/DirectColor visual. + */ +static void setup_truecolor( XMesaVisual v, XMesaBuffer buffer, + XMesaColormap cmap ) +{ + unsigned long rmask, gmask, bmask; + (void) buffer; + (void) cmap; + + /* Compute red multiplier (mask) and bit shift */ + v->rshift = 0; + rmask = GET_REDMASK(v); + while ((rmask & 1)==0) { + v->rshift++; + rmask = rmask >> 1; + } + + /* Compute green multiplier (mask) and bit shift */ + v->gshift = 0; + gmask = GET_GREENMASK(v); + while ((gmask & 1)==0) { + v->gshift++; + gmask = gmask >> 1; + } + + /* Compute blue multiplier (mask) and bit shift */ + v->bshift = 0; + bmask = GET_BLUEMASK(v); + while ((bmask & 1)==0) { + v->bshift++; + bmask = bmask >> 1; + } + + /* + * Compute component-to-pixel lookup tables and dithering kernel + */ + { + static GLubyte kernel[16] = { + 0*16, 8*16, 2*16, 10*16, + 12*16, 4*16, 14*16, 6*16, + 3*16, 11*16, 1*16, 9*16, + 15*16, 7*16, 13*16, 5*16, + }; + GLint rBits = bitcount(rmask); + GLint gBits = bitcount(gmask); + GLint bBits = bitcount(bmask); + GLint maxBits; + GLuint i; + + /* convert pixel components in [0,_mask] to RGB values in [0,255] */ + for (i=0; i<=rmask; i++) + v->PixelToR[i] = (unsigned char) ((i * 255) / rmask); + for (i=0; i<=gmask; i++) + v->PixelToG[i] = (unsigned char) ((i * 255) / gmask); + for (i=0; i<=bmask; i++) + v->PixelToB[i] = (unsigned char) ((i * 255) / bmask); + + /* convert RGB values from [0,255] to pixel components */ + + for (i=0;i<256;i++) { + GLint r = gamma_adjust(v->RedGamma, i, 255); + GLint g = gamma_adjust(v->GreenGamma, i, 255); + GLint b = gamma_adjust(v->BlueGamma, i, 255); + v->RtoPixel[i] = (r >> (8-rBits)) << v->rshift; + v->GtoPixel[i] = (g >> (8-gBits)) << v->gshift; + v->BtoPixel[i] = (b >> (8-bBits)) << v->bshift; + } + /* overflow protection */ + for (i=256;i<512;i++) { + v->RtoPixel[i] = v->RtoPixel[255]; + v->GtoPixel[i] = v->GtoPixel[255]; + v->BtoPixel[i] = v->BtoPixel[255]; + } + + /* setup dithering kernel */ + maxBits = rBits; + if (gBits > maxBits) maxBits = gBits; + if (bBits > maxBits) maxBits = bBits; + for (i=0;i<16;i++) { + v->Kernel[i] = kernel[i] >> maxBits; + } + + v->undithered_pf = PF_Truecolor; + v->dithered_pf = (GET_VISUAL_DEPTH(v)<24) ? PF_Dither_True : PF_Truecolor; + } + + /* + * Now check for TrueColor visuals which we can optimize. + */ + if ( GET_REDMASK(v) ==0x0000ff + && GET_GREENMASK(v)==0x00ff00 + && GET_BLUEMASK(v) ==0xff0000 + && CHECK_BYTE_ORDER(v) + && v->BitsPerPixel==32 + && sizeof(GLuint)==4 + && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) { + /* common 32 bpp config used on SGI, Sun */ + v->undithered_pf = v->dithered_pf = PF_8A8B8G8R; + } + else if (GET_REDMASK(v) ==0xff0000 + && GET_GREENMASK(v)==0x00ff00 + && GET_BLUEMASK(v) ==0x0000ff + && CHECK_BYTE_ORDER(v) + && v->BitsPerPixel==32 + && sizeof(GLuint)==4 + && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) { + /* common 32 bpp config used on Linux, HP, IBM */ + if (GET_VISUAL_DEPTH(v)==32) + v->undithered_pf = v->dithered_pf = PF_8A8R8G8B; + else + v->undithered_pf = v->dithered_pf = PF_8R8G8B; + } + else if (GET_REDMASK(v) ==0xff0000 + && GET_GREENMASK(v)==0x00ff00 + && GET_BLUEMASK(v) ==0x0000ff + && CHECK_BYTE_ORDER(v) + && v->BitsPerPixel==24 + && sizeof(GLuint)==4 + && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) { + /* common packed 24 bpp config used on Linux */ + v->undithered_pf = v->dithered_pf = PF_8R8G8B24; + } + else if (GET_REDMASK(v) ==0xf800 + && GET_GREENMASK(v)==0x07e0 + && GET_BLUEMASK(v) ==0x001f + && CHECK_BYTE_ORDER(v) + && v->BitsPerPixel==16 + && sizeof(GLushort)==2 + && v->RedGamma==1.0 && v->GreenGamma==1.0 && v->BlueGamma==1.0) { + /* 5-6-5 color weight on common PC VGA boards */ + v->undithered_pf = PF_5R6G5B; + v->dithered_pf = PF_Dither_5R6G5B; + } + else if (GET_REDMASK(v) ==0xe0 + && GET_GREENMASK(v)==0x1c + && GET_BLUEMASK(v) ==0x03 + && CHECK_FOR_HPCR(v)) { + setup_8bit_hpcr( v ); + } +} + + + +/* + * Setup RGB rendering for a window with a monochrome visual. + */ +static void setup_monochrome( XMesaVisual v, XMesaBuffer b ) +{ + (void) b; + v->dithered_pf = v->undithered_pf = PF_1Bit; + /* if black=1 then we must flip pixel values */ + v->bitFlip = (GET_BLACK_PIXEL(v) != 0); +} + + + +/* + * When a context is "made current" for the first time, we can finally + * finish initializing the context's visual and buffer information. + * Input: v - the XMesaVisual to initialize + * b - the XMesaBuffer to initialize (may be NULL) + * rgb_flag - TRUE = RGBA mode, FALSE = color index mode + * window - the window/pixmap we're rendering into + * cmap - the colormap associated with the window/pixmap + * Return: GL_TRUE=success, GL_FALSE=failure + */ +static GLboolean initialize_visual_and_buffer( int client, + XMesaVisual v, + XMesaBuffer b, + GLboolean rgb_flag, + XMesaDrawable window, + XMesaColormap cmap ) +{ +#ifndef XFree86Server + XGCValues gcvalues; +#endif + + if (b) { + assert(b->xm_visual == v); + } + + /* Save true bits/pixel */ + v->BitsPerPixel = bits_per_pixel(v); + assert(v->BitsPerPixel > 0); + + + if (rgb_flag==GL_FALSE) { + /* COLOR-INDEXED WINDOW: + * Even if the visual is TrueColor or DirectColor we treat it as + * being color indexed. This is weird but might be useful to someone. + */ + v->dithered_pf = v->undithered_pf = PF_Index; + v->mesa_visual.indexBits = GET_VISUAL_DEPTH(v); + } + else { + /* RGB WINDOW: + * We support RGB rendering into almost any kind of visual. + */ + const int xclass = v->mesa_visual.visualType; + if (xclass==GLX_TRUE_COLOR || xclass==GLX_DIRECT_COLOR) { + setup_truecolor( v, b, cmap ); + } + else if (xclass==GLX_STATIC_GRAY && GET_VISUAL_DEPTH(v)==1) { + setup_monochrome( v, b ); + } + else if (xclass==GLX_GRAY_SCALE || xclass==GLX_STATIC_GRAY) { + if (!setup_grayscale( client, v, b, cmap )) { + return GL_FALSE; + } + } + else if ((xclass==GLX_PSEUDO_COLOR || xclass==GLX_STATIC_COLOR) + && GET_VISUAL_DEPTH(v)>=4 && GET_VISUAL_DEPTH(v)<=16) { + if (!setup_dithered_color( client, v, b, cmap )) { + return GL_FALSE; + } + } + else { + _mesa_warning(NULL, "XMesa: RGB mode rendering not supported in given visual."); + return GL_FALSE; + } + v->mesa_visual.indexBits = 0; + + if (_mesa_getenv("MESA_NO_DITHER")) { + v->dithered_pf = v->undithered_pf; + } + } + + + /* + * If MESA_INFO env var is set print out some debugging info + * which can help Brian figure out what's going on when a user + * reports bugs. + */ + if (_mesa_getenv("MESA_INFO")) { + _mesa_printf("X/Mesa visual = %p\n", (void *) v); + _mesa_printf("X/Mesa dithered pf = %u\n", v->dithered_pf); + _mesa_printf("X/Mesa undithered pf = %u\n", v->undithered_pf); + _mesa_printf("X/Mesa level = %d\n", v->mesa_visual.level); + _mesa_printf("X/Mesa depth = %d\n", GET_VISUAL_DEPTH(v)); + _mesa_printf("X/Mesa bits per pixel = %d\n", v->BitsPerPixel); + } + + if (b && window) { + /* Do window-specific initializations */ + + /* Window dimensions */ + unsigned int w, h; + get_drawable_size( v->display, window, &w, &h ); + b->width = w; + b->height = h; + + b->frontbuffer = window; + + /* Setup for single/double buffering */ + if (v->mesa_visual.doubleBufferMode) { + /* Double buffered */ +#ifndef XFree86Server + b->shm = check_for_xshm( v->display ); +#endif + xmesa_alloc_back_buffer( b ); + if (b->db_state==BACK_PIXMAP) { + b->buffer = (XMesaDrawable)b->backpixmap; + } + else { + b->buffer = XIMAGE; + } + } + else { + /* Single Buffered */ + b->buffer = b->frontbuffer; + } + + /* X11 graphics contexts */ +#ifdef XFree86Server + b->gc = CreateScratchGC(v->display, window->depth); +#else + b->gc = XCreateGC( v->display, window, 0, NULL ); +#endif + XMesaSetFunction( v->display, b->gc, GXcopy ); + + /* cleargc - for glClear() */ +#ifdef XFree86Server + b->cleargc = CreateScratchGC(v->display, window->depth); +#else + b->cleargc = XCreateGC( v->display, window, 0, NULL ); +#endif + XMesaSetFunction( v->display, b->cleargc, GXcopy ); + + /* + * Don't generate Graphics Expose/NoExpose events in swapbuffers(). + * Patch contributed by Michael Pichler May 15, 1995. + */ +#ifdef XFree86Server + b->swapgc = CreateScratchGC(v->display, window->depth); + { + CARD32 v[1]; + v[0] = FALSE; + dixChangeGC(NullClient, b->swapgc, GCGraphicsExposures, v, NULL); + } +#else + gcvalues.graphics_exposures = False; + b->swapgc = XCreateGC( v->display, window, + GCGraphicsExposures, &gcvalues); +#endif + XMesaSetFunction( v->display, b->swapgc, GXcopy ); + /* + * Set fill style and tile pixmap once for all for HPCR stuff + * (instead of doing it each time in clear_color_HPCR_pixmap()) + * Initialize whole stuff + * Patch contributed by Jacques Leroy March 8, 1998. + */ + if (v->hpcr_clear_flag && b->buffer!=XIMAGE) { + int i; + for (i=0; i<16; i++) + { + XMesaPutPixel(v->hpcr_clear_ximage, i, 0, 0); + XMesaPutPixel(v->hpcr_clear_ximage, i, 1, 0); + } + XMesaPutImage(b->display, (XMesaDrawable)v->hpcr_clear_pixmap, + b->cleargc, v->hpcr_clear_ximage, 0, 0, 0, 0, 16, 2); + XMesaSetFillStyle( v->display, b->cleargc, FillTiled); + XMesaSetTile( v->display, b->cleargc, v->hpcr_clear_pixmap ); + } + + /* Initialize the row buffer XImage for use in write_color_span() */ +#ifdef XFree86Server + b->rowimage = XMesaCreateImage(GET_VISUAL_DEPTH(v), MAX_WIDTH, 1, + (char *)MALLOC(MAX_WIDTH*4)); +#else + b->rowimage = XCreateImage( v->display, + v->visinfo->visual, + v->visinfo->depth, + ZPixmap, 0, /*format, offset*/ + (char*) MALLOC(MAX_WIDTH*4), /*data*/ + MAX_WIDTH, 1, /*width, height*/ + 32, /*bitmap_pad*/ + 0 /*bytes_per_line*/ ); +#endif + if (!b->rowimage) + return GL_FALSE; + } + + return GL_TRUE; +} + + + +/* + * Convert an RGBA color to a pixel value. + */ +unsigned long +xmesa_color_to_pixel( XMesaContext xmesa, GLubyte r, GLubyte g, GLubyte b, GLubyte a, + GLuint pixelFormat) +{ + switch (pixelFormat) { + case PF_Index: + return 0; + case PF_Truecolor: + { + unsigned long p; + PACK_TRUECOLOR( p, r, g, b ); + return p; + } + case PF_8A8B8G8R: + return PACK_8A8B8G8R( r, g, b, a ); + case PF_8A8R8G8B: + return PACK_8A8R8G8B( r, g, b, a ); + case PF_8R8G8B: + /* fall through */ + case PF_8R8G8B24: + return PACK_8R8G8B( r, g, b ); + case PF_5R6G5B: + return PACK_5R6G5B( r, g, b ); + case PF_Dither: + { + DITHER_SETUP; + return DITHER( 1, 0, r, g, b ); + } + case PF_1Bit: + /* 382 = (3*255)/2 */ + return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip; + case PF_HPCR: + return DITHER_HPCR(1, 1, r, g, b); + case PF_Lookup: + { + LOOKUP_SETUP; + return LOOKUP( r, g, b ); + } + case PF_Grayscale: + return GRAY_RGB( r, g, b ); + case PF_Dither_True: + /* fall through */ + case PF_Dither_5R6G5B: + { + unsigned long p; + PACK_TRUEDITHER(p, 1, 0, r, g, b); + return p; + } + default: + _mesa_problem(NULL, "Bad pixel format in xmesa_color_to_pixel"); + } + return 0; +} + + +#define NUM_VISUAL_TYPES 6 + +/** + * Convert an X visual type to a GLX visual type. + * + * \param visualType X visual type (i.e., \c TrueColor, \c StaticGray, etc.) + * to be converted. + * \return If \c visualType is a valid X visual type, a GLX visual type will + * be returned. Otherwise \c GLX_NONE will be returned. + * + * \note + * This code was lifted directly from lib/GL/glx/glcontextmodes.c in the + * DRI CVS tree. + */ +static GLint +xmesa_convert_from_x_visual_type( int visualType ) +{ + static const int glx_visual_types[ NUM_VISUAL_TYPES ] = { + GLX_STATIC_GRAY, GLX_GRAY_SCALE, + GLX_STATIC_COLOR, GLX_PSEUDO_COLOR, + GLX_TRUE_COLOR, GLX_DIRECT_COLOR + }; + + return ( (unsigned) visualType < NUM_VISUAL_TYPES ) + ? glx_visual_types[ visualType ] : GLX_NONE; +} + + +/**********************************************************************/ +/***** Public Functions *****/ +/**********************************************************************/ + + +/* + * Create a new X/Mesa visual. + * Input: display - X11 display + * visinfo - an XVisualInfo pointer + * rgb_flag - GL_TRUE = RGB mode, + * GL_FALSE = color index mode + * alpha_flag - alpha buffer requested? + * db_flag - GL_TRUE = double-buffered, + * GL_FALSE = single buffered + * stereo_flag - stereo visual? + * ximage_flag - GL_TRUE = use an XImage for back buffer, + * GL_FALSE = use an off-screen pixmap for back buffer + * depth_size - requested bits/depth values, or zero + * stencil_size - requested bits/stencil values, or zero + * accum_red_size - requested bits/red accum values, or zero + * accum_green_size - requested bits/green accum values, or zero + * accum_blue_size - requested bits/blue accum values, or zero + * accum_alpha_size - requested bits/alpha accum values, or zero + * num_samples - number of samples/pixel if multisampling, or zero + * level - visual level, usually 0 + * visualCaveat - ala the GLX extension, usually GLX_NONE + * Return; a new XMesaVisual or 0 if error. + */ +XMesaVisual XMesaCreateVisual( XMesaDisplay *display, + XMesaVisualInfo visinfo, + GLboolean rgb_flag, + GLboolean alpha_flag, + GLboolean db_flag, + GLboolean stereo_flag, + GLboolean ximage_flag, + GLint depth_size, + GLint stencil_size, + GLint accum_red_size, + GLint accum_green_size, + GLint accum_blue_size, + GLint accum_alpha_size, + GLint num_samples, + GLint level, + GLint visualCaveat ) +{ + char *gamma; + XMesaVisual v; + GLint red_bits, green_bits, blue_bits, alpha_bits; + + /* For debugging only */ + if (_mesa_getenv("MESA_XSYNC")) { + /* This makes debugging X easier. + * In your debugger, set a breakpoint on _XError to stop when an + * X protocol error is generated. + */ +#ifdef XFree86Server + /* NOT_NEEDED */ +#else + XSynchronize( display, 1 ); +#endif + } + + v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual); + if (!v) { + return NULL; + } + + /* + * In the X server, NULL is passed in for the display. It will have + * to be set before using this visual. See XMesaSetVisualDisplay() + * below. + */ + v->display = display; + + /* Save a copy of the XVisualInfo struct because the user may XFREE() + * the struct but we may need some of the information contained in it + * at a later time. + */ +#ifndef XFree86Server + v->visinfo = (XVisualInfo *) MALLOC(sizeof(*visinfo)); + if(!v->visinfo) { + FREE(v); + return NULL; + } + MEMCPY(v->visinfo, visinfo, sizeof(*visinfo)); +#endif + + /* check for MESA_GAMMA environment variable */ + gamma = _mesa_getenv("MESA_GAMMA"); + if (gamma) { + v->RedGamma = v->GreenGamma = v->BlueGamma = 0.0; + sscanf( gamma, "%f %f %f", &v->RedGamma, &v->GreenGamma, &v->BlueGamma ); + if (v->RedGamma<=0.0) v->RedGamma = 1.0; + if (v->GreenGamma<=0.0) v->GreenGamma = v->RedGamma; + if (v->BlueGamma<=0.0) v->BlueGamma = v->RedGamma; + } + else { + v->RedGamma = v->GreenGamma = v->BlueGamma = 1.0; + } + + v->ximage_flag = ximage_flag; + +#ifdef XFree86Server + /* We could calculate these values by ourselves. nplanes is either the sum + * of the red, green, and blue bits or the number index bits. + * ColormapEntries is either (1U << index_bits) or + * (1U << max(redBits, greenBits, blueBits)). + */ + v->nplanes = visinfo->nplanes; + v->ColormapEntries = visinfo->ColormapEntries; + + v->mesa_visual.redMask = visinfo->redMask; + v->mesa_visual.greenMask = visinfo->greenMask; + v->mesa_visual.blueMask = visinfo->blueMask; + v->mesa_visual.visualID = visinfo->vid; + v->mesa_visual.screen = 0; /* FIXME: What should be done here? */ +#else + v->mesa_visual.redMask = visinfo->red_mask; + v->mesa_visual.greenMask = visinfo->green_mask; + v->mesa_visual.blueMask = visinfo->blue_mask; + v->mesa_visual.visualID = visinfo->visualid; + v->mesa_visual.screen = visinfo->screen; +#endif + +#if defined(XFree86Server) || !(defined(__cplusplus) || defined(c_plusplus)) + v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->class); +#else + v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->c_class); +#endif + + v->mesa_visual.visualRating = visualCaveat; + + (void) initialize_visual_and_buffer( 0, v, NULL, rgb_flag, 0, 0 ); + + { + const int xclass = v->mesa_visual.visualType; + if (xclass==GLX_TRUE_COLOR || xclass==GLX_DIRECT_COLOR) { + red_bits = bitcount(GET_REDMASK(v)); + green_bits = bitcount(GET_GREENMASK(v)); + blue_bits = bitcount(GET_BLUEMASK(v)); + alpha_bits = 0; + } + else { + /* this is an approximation */ + int depth; + depth = GET_VISUAL_DEPTH(v); + red_bits = depth / 3; + depth -= red_bits; + green_bits = depth / 2; + depth -= green_bits; + blue_bits = depth; + alpha_bits = 0; + assert( red_bits + green_bits + blue_bits == GET_VISUAL_DEPTH(v) ); + } + } + + if (alpha_flag && alpha_bits == 0) + alpha_bits = 8; + + _mesa_initialize_visual( &v->mesa_visual, + rgb_flag, db_flag, stereo_flag, + red_bits, green_bits, + blue_bits, alpha_bits, + v->mesa_visual.indexBits, + depth_size, + stencil_size, + accum_red_size, accum_green_size, + accum_blue_size, accum_alpha_size, + 0 ); + + /* XXX minor hack */ + v->mesa_visual.level = level; + return v; +} + + +void XMesaSetVisualDisplay( XMesaDisplay *dpy, XMesaVisual v ) +{ + v->display = dpy; +} + + +void XMesaDestroyVisual( XMesaVisual v ) +{ +#ifndef XFree86Server + FREE(v->visinfo); +#endif + FREE(v); +} + + + +/** + * Create a new XMesaContext. + * \param v the XMesaVisual + * \param share_list another XMesaContext with which to share display + * lists or NULL if no sharing is wanted. + * \return an XMesaContext or NULL if error. + */ +XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) +{ + static GLboolean firstTime = GL_TRUE; + XMesaContext c; + GLcontext *mesaCtx; + struct dd_function_table functions; + TNLcontext *tnl; + + if (firstTime) { + _glthread_INIT_MUTEX(_xmesa_lock); + firstTime = GL_FALSE; + } + + /* Note: the XMesaContext contains a Mesa GLcontext struct (inheritance) */ + c = (XMesaContext) CALLOC_STRUCT(xmesa_context); + if (!c) + return NULL; + + mesaCtx = &(c->mesa); + + /* initialize with default driver functions, then plug in XMesa funcs */ + _mesa_init_driver_functions(&functions); + xmesa_init_driver_functions(v, &functions); + if (!_mesa_initialize_context(mesaCtx, &v->mesa_visual, + share_list ? &(share_list->mesa) : (GLcontext *) NULL, + &functions, (void *) c)) { + FREE(c); + return NULL; + } + + _mesa_enable_sw_extensions(mesaCtx); + _mesa_enable_1_3_extensions(mesaCtx); + _mesa_enable_1_4_extensions(mesaCtx); + _mesa_enable_1_5_extensions(mesaCtx); + + /* finish up xmesa context initializations */ + c->swapbytes = CHECK_BYTE_ORDER(v) ? GL_FALSE : GL_TRUE; + c->xm_visual = v; + c->xm_draw_buffer = NULL; /* set later by XMesaMakeCurrent */ + c->xm_read_buffer = NULL; /* set later by XMesaMakeCurrent */ + c->xm_buffer = NULL; /* set later by XMesaMakeCurrent */ + c->display = v->display; + c->pixelformat = v->dithered_pf; /* Dithering is enabled by default */ + + /* Initialize the software rasterizer and helper modules. + */ + if (!_swrast_CreateContext( mesaCtx ) || + !_ac_CreateContext( mesaCtx ) || + !_tnl_CreateContext( mesaCtx ) || + !_swsetup_CreateContext( mesaCtx )) { + _mesa_free_context_data(&c->mesa); + _mesa_free(c); + return NULL; + } + + /* tnl setup */ + tnl = TNL_CONTEXT(mesaCtx); + tnl->Driver.RunPipeline = _tnl_run_pipeline; + /* swrast setup */ + xmesa_register_swrast_functions( mesaCtx ); + _swsetup_Wakeup(mesaCtx); + + return c; +} + + + +void XMesaDestroyContext( XMesaContext c ) +{ + GLcontext *mesaCtx = &c->mesa; +#ifdef FX + if (c->xm_draw_buffer && c->xm_buffer->FXctx) + fxMesaDestroyContext(c->xm_draw_buffer->FXctx); +#endif + _swsetup_DestroyContext( mesaCtx ); + _swrast_DestroyContext( mesaCtx ); + _tnl_DestroyContext( mesaCtx ); + _ac_DestroyContext( mesaCtx ); + _mesa_free_context_data( mesaCtx ); + _mesa_free( c ); +} + + + +/* + * XXX this isn't a public function! It's a hack for the 3Dfx driver. + * Create a new XMesaBuffer from an X window. + * Input: v - the XMesaVisual + * w - the window + * c - the context + * Return: new XMesaBuffer or NULL if error + */ +XMesaBuffer XMesaCreateWindowBuffer2( XMesaVisual v, XMesaWindow w, + XMesaContext c ) +{ +#ifndef XFree86Server + XWindowAttributes attr; +#endif +#ifdef FX + char *fxEnvVar; +#endif + int client = 0; + + XMesaBuffer b = alloc_xmesa_buffer(); + if (!b) { + return NULL; + } + + (void) c; + +#ifdef XFree86Server + client = CLIENT_ID(((XMesaDrawable)w)->id); +#endif + + assert(v); + +#ifdef XFree86Server + if (GET_VISUAL_DEPTH(v) != ((XMesaDrawable)w)->depth) { +#else + XGetWindowAttributes( v->display, w, &attr ); + + if (GET_VISUAL_DEPTH(v) != attr.depth) { +#endif + _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual and window!\n"); + return NULL; + } + + b->xm_visual = v; + b->type = WINDOW; + b->display = v->display; +#ifdef XFree86Server + b->cmap = (ColormapPtr)LookupIDByType(wColormap(w), RT_COLORMAP); +#else + if (attr.colormap) { + b->cmap = attr.colormap; + } + else { + _mesa_warning(NULL, "Window %u has no colormap!\n", (unsigned int) w); + /* this is weird, a window w/out a colormap!? */ + /* OK, let's just allocate a new one and hope for the best */ + b->cmap = XCreateColormap(v->display, w, attr.visual, AllocNone); + } +#endif + + /* determine back buffer implementation */ + if (v->mesa_visual.doubleBufferMode) { + if (v->ximage_flag) { + b->db_state = BACK_XIMAGE; + } + else { + b->db_state = BACK_PIXMAP; + } + } + else { + b->db_state = 0; + } + + _mesa_initialize_framebuffer(&b->mesa_buffer, + &v->mesa_visual, + v->mesa_visual.depthBits > 0, + v->mesa_visual.stencilBits > 0, + v->mesa_visual.accumRedBits > 0, + v->mesa_visual.alphaBits > 0 ); + /* XXX hack */ + b->mesa_buffer.UseSoftwareAuxBuffers = GL_TRUE; + + if (!initialize_visual_and_buffer( client, v, b, v->mesa_visual.rgbMode, + (XMesaDrawable)w, b->cmap )) { + free_xmesa_buffer(client, b); + return NULL; + } + +#ifdef FX + fxEnvVar = _mesa_getenv("MESA_GLX_FX"); + if (fxEnvVar) { + if (fxEnvVar[0]!='d') { + int attribs[100]; + int numAttribs = 0; + int hw; + if (v->mesa_visual.depthBits > 0) { + attribs[numAttribs++] = FXMESA_DEPTH_SIZE; + attribs[numAttribs++] = v->mesa_visual.depthBits; + } + if (v->mesa_visual.doubleBufferMode) { + attribs[numAttribs++] = FXMESA_DOUBLEBUFFER; + } + if (v->mesa_visual.accumRedBits > 0) { + attribs[numAttribs++] = FXMESA_ACCUM_SIZE; + attribs[numAttribs++] = v->mesa_visual.accumRedBits; + } + if (v->mesa_visual.stencilBits > 0) { + attribs[numAttribs++] = FXMESA_STENCIL_SIZE; + attribs[numAttribs++] = v->mesa_visual.stencilBits; + } + if (v->mesa_visual.alphaBits > 0) { + attribs[numAttribs++] = FXMESA_ALPHA_SIZE; + attribs[numAttribs++] = v->mesa_visual.alphaBits; + } + if (1) { + attribs[numAttribs++] = FXMESA_SHARE_CONTEXT; + attribs[numAttribs++] = (int) &(c->mesa); + } + attribs[numAttribs++] = FXMESA_NONE; + + /* [dBorca] we should take an envvar for `fxMesaSelectCurrentBoard'!!! */ + hw = fxMesaSelectCurrentBoard(0); + if ((hw == GR_SSTTYPE_VOODOO) || (hw == GR_SSTTYPE_Voodoo2)) { + b->FXctx = fxMesaCreateBestContext(0, b->width, b->height, attribs); + if ((v->undithered_pf!=PF_Index) && (b->backimage)) { + b->FXisHackUsable = b->FXctx ? GL_TRUE : GL_FALSE; + if (b->FXctx && (fxEnvVar[0]=='w' || fxEnvVar[0]=='W')) { + b->FXwindowHack = GL_TRUE; + FX_grSstControl(GR_CONTROL_DEACTIVATE); + } + else { + b->FXwindowHack = GL_FALSE; + } + } + } + else { + if (fxEnvVar[0]=='w' || fxEnvVar[0]=='W') + b->FXctx = fxMesaCreateContext(w, GR_RESOLUTION_NONE, + GR_REFRESH_75Hz, attribs); + else + b->FXctx = fxMesaCreateBestContext(0, b->width, b->height, attribs); + b->FXisHackUsable = GL_FALSE; + b->FXwindowHack = GL_FALSE; + } + /* + fprintf(stderr, + "voodoo %d, wid %d height %d hack: usable %d active %d\n", + hw, b->width, b->height, b->FXisHackUsable, b->FXwindowHack); + */ + } + } + else { + _mesa_warning(NULL, "WARNING: This Mesa Library includes the Glide driver but\n"); + _mesa_warning(NULL, " you have not defined the MESA_GLX_FX env. var.\n"); + _mesa_warning(NULL, " (check the README.3DFX file for more information).\n\n"); + _mesa_warning(NULL, " you can disable this message with a 'export MESA_GLX_FX=disable'.\n"); + } +#endif + + return b; +} + + +XMesaBuffer XMesaCreateWindowBuffer( XMesaVisual v, XMesaWindow w ) +{ + return XMesaCreateWindowBuffer2( v, w, NULL ); +} + + +/** + * Create a new XMesaBuffer from an X pixmap. + * + * \param v the XMesaVisual + * \param p the pixmap + * \param cmap the colormap, may be 0 if using a \c GLX_TRUE_COLOR or + * \c GLX_DIRECT_COLOR visual for the pixmap + * \returns new XMesaBuffer or NULL if error + */ +XMesaBuffer XMesaCreatePixmapBuffer( XMesaVisual v, + XMesaPixmap p, XMesaColormap cmap ) +{ + int client = 0; + XMesaBuffer b = alloc_xmesa_buffer(); + if (!b) { + return NULL; + } + + +#ifdef XFree86Server + client = CLIENT_ID(((XMesaDrawable)p)->id); +#endif + + assert(v); + + b->xm_visual = v; + b->type = PIXMAP; + b->display = v->display; + b->cmap = cmap; + + /* determine back buffer implementation */ + if (v->mesa_visual.doubleBufferMode) { + if (v->ximage_flag) { + b->db_state = BACK_XIMAGE; + } + else { + b->db_state = BACK_PIXMAP; + } + } + else { + b->db_state = 0; + } + + _mesa_initialize_framebuffer(&b->mesa_buffer, + &v->mesa_visual, + v->mesa_visual.depthBits > 0, + v->mesa_visual.stencilBits > 0, + v->mesa_visual.accumRedBits + + v->mesa_visual.accumGreenBits + + v->mesa_visual.accumBlueBits > 0, + v->mesa_visual.alphaBits > 0 ); + + if (!initialize_visual_and_buffer(client, v, b, v->mesa_visual.rgbMode, + (XMesaDrawable)p, cmap)) { + free_xmesa_buffer(client, b); + return NULL; + } + + return b; +} + + + +XMesaBuffer XMesaCreatePBuffer( XMesaVisual v, XMesaColormap cmap, + unsigned int width, unsigned int height ) +{ +#ifdef XFree86Server + return 0; +#else + int client = 0; + XMesaWindow root; + XMesaDrawable drawable; /* X Pixmap Drawable */ + XMesaBuffer b = alloc_xmesa_buffer(); + if (!b) { + return NULL; + } + + b->xm_visual = v; + b->type = PBUFFER; + b->display = v->display; + b->cmap = cmap; + + /* allocate pixmap for front buffer */ + root = RootWindow( v->display, v->visinfo->screen ); + drawable = XCreatePixmap( v->display, root, width, height, v->visinfo->depth ); + + /* determine back buffer implementation */ + if (v->mesa_visual.doubleBufferMode) { + if (v->ximage_flag) { + b->db_state = BACK_XIMAGE; + } + else { + b->db_state = BACK_PIXMAP; + } + } + else { + b->db_state = 0; + } + + _mesa_initialize_framebuffer(&b->mesa_buffer, + &v->mesa_visual, + v->mesa_visual.depthBits > 0, + v->mesa_visual.stencilBits > 0, + v->mesa_visual.accumRedBits + + v->mesa_visual.accumGreenBits + + v->mesa_visual.accumBlueBits > 0, + v->mesa_visual.alphaBits > 0 ); + + if (!initialize_visual_and_buffer(client, v, b, v->mesa_visual.rgbMode, + drawable, cmap)) { + free_xmesa_buffer(client, b); + return NULL; + } + + return b; +#endif +} + + + +/* + * Deallocate an XMesaBuffer structure and all related info. + */ +void XMesaDestroyBuffer( XMesaBuffer b ) +{ + int client = 0; + +#ifdef XFree86Server + if (b->frontbuffer) + client = CLIENT_ID(b->frontbuffer->id); +#endif + + if (b->gc) XMesaFreeGC( b->xm_visual->display, b->gc ); + if (b->cleargc) XMesaFreeGC( b->xm_visual->display, b->cleargc ); + if (b->swapgc) XMesaFreeGC( b->xm_visual->display, b->swapgc ); + + if (b->backimage) { +#if defined(USE_XSHM) && !defined(XFree86Server) + if (b->shm) { + XShmDetach( b->xm_visual->display, &b->shminfo ); + XDestroyImage( b->backimage ); + shmdt( b->shminfo.shmaddr ); + } + else +#endif + XMesaDestroyImage( b->backimage ); + } + if (b->backpixmap) { + XMesaFreePixmap( b->xm_visual->display, b->backpixmap ); + if (b->xm_visual->hpcr_clear_flag) { + XMesaFreePixmap( b->xm_visual->display, + b->xm_visual->hpcr_clear_pixmap ); + XMesaDestroyImage( b->xm_visual->hpcr_clear_ximage ); + } + } + if (b->rowimage) { + FREE( b->rowimage->data ); + b->rowimage->data = NULL; + XMesaDestroyImage( b->rowimage ); + } + + free_xmesa_buffer(client, b); +} + + + +/* + * Bind buffer b to context c and make c the current rendering context. + */ +GLboolean XMesaMakeCurrent( XMesaContext c, XMesaBuffer b ) +{ + return XMesaMakeCurrent2( c, b, b ); +} + + +/* + * Bind buffer b to context c and make c the current rendering context. + */ +GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer, + XMesaBuffer readBuffer ) +{ + if (c) { + if (!drawBuffer || !readBuffer) + return GL_FALSE; /* must specify buffers! */ + +#ifdef FX + if (drawBuffer->FXctx) { + fxMesaMakeCurrent(drawBuffer->FXctx); + + c->xm_draw_buffer = drawBuffer; + c->xm_read_buffer = readBuffer; + c->xm_buffer = drawBuffer; + + return GL_TRUE; + } +#endif + if (&(c->mesa) == _mesa_get_current_context() + && c->xm_draw_buffer == drawBuffer + && c->xm_read_buffer == readBuffer + && c->xm_draw_buffer->wasCurrent) { + /* same context and buffer, do nothing */ + return GL_TRUE; + } + + c->xm_draw_buffer = drawBuffer; + c->xm_read_buffer = readBuffer; + c->xm_buffer = drawBuffer; + + _mesa_make_current2(&(c->mesa), + &drawBuffer->mesa_buffer, + &readBuffer->mesa_buffer); + + if (c->mesa.Viewport.Width == 0) { + /* initialize viewport to window size */ + _mesa_Viewport( 0, 0, drawBuffer->width, drawBuffer->height ); + c->mesa.Scissor.Width = drawBuffer->width; + c->mesa.Scissor.Height = drawBuffer->height; + } + + if (c->xm_visual->mesa_visual.rgbMode) { + /* + * Must recompute and set these pixel values because colormap + * can be different for different windows. + */ + c->clearpixel = xmesa_color_to_pixel( c, + c->clearcolor[0], + c->clearcolor[1], + c->clearcolor[2], + c->clearcolor[3], + c->xm_visual->undithered_pf); + XMesaSetForeground(c->display, c->xm_draw_buffer->cleargc, c->clearpixel); + } + + /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */ + c->xm_draw_buffer->wasCurrent = GL_TRUE; + } + else { + /* Detach */ + _mesa_make_current2( NULL, NULL, NULL ); + } + return GL_TRUE; +} + + +/* + * Unbind the context c from its buffer. + */ +GLboolean XMesaUnbindContext( XMesaContext c ) +{ + /* A no-op for XFree86 integration purposes */ + return GL_TRUE; +} + + +XMesaContext XMesaGetCurrentContext( void ) +{ + GET_CURRENT_CONTEXT(ctx); + if (ctx) { + XMesaContext xmesa = XMESA_CONTEXT(ctx); + return xmesa; + } + else { + return 0; + } +} + + +XMesaBuffer XMesaGetCurrentBuffer( void ) +{ + GET_CURRENT_CONTEXT(ctx); + if (ctx) { + XMesaContext xmesa = XMESA_CONTEXT(ctx); + return xmesa->xm_draw_buffer; + } + else { + return 0; + } +} + + +/* New in Mesa 3.1 */ +XMesaBuffer XMesaGetCurrentReadBuffer( void ) +{ + GET_CURRENT_CONTEXT(ctx); + if (ctx) { + XMesaContext xmesa = XMESA_CONTEXT(ctx); + return xmesa->xm_read_buffer; + } + else { + return 0; + } +} + + +GLboolean XMesaForceCurrent(XMesaContext c) +{ + if (c) { + if (&(c->mesa) != _mesa_get_current_context()) { + _mesa_make_current(&(c->mesa), &c->xm_draw_buffer->mesa_buffer); + } + } + else { + _mesa_make_current(NULL, NULL); + } + return GL_TRUE; +} + + +GLboolean XMesaLoseCurrent(XMesaContext c) +{ + (void) c; + _mesa_make_current(NULL, NULL); + return GL_TRUE; +} + + +/* + * Switch 3Dfx support hack between window and full-screen mode. + */ +GLboolean XMesaSetFXmode( GLint mode ) +{ +#ifdef FX + const char *fx = _mesa_getenv("MESA_GLX_FX"); + if (fx && fx[0] != 'd') { + GET_CURRENT_CONTEXT(ctx); + GrHwConfiguration hw; + if (!FX_grSstQueryHardware(&hw)) { + /*fprintf(stderr, "!grSstQueryHardware\n");*/ + return GL_FALSE; + } + if (hw.num_sst < 1) { + /*fprintf(stderr, "hw.num_sst < 1\n");*/ + return GL_FALSE; + } + if (ctx) { + /* [dBorca] Hack alert: + * oh, this is sooo wrong: ctx above is + * really an fxMesaContext, not an XMesaContext + */ + XMesaContext xmesa = XMESA_CONTEXT(ctx); + if (mode == XMESA_FX_WINDOW) { + if (xmesa->xm_draw_buffer->FXisHackUsable) { + FX_grSstControl(GR_CONTROL_DEACTIVATE); + xmesa->xm_draw_buffer->FXwindowHack = GL_TRUE; + return GL_TRUE; + } + } + else if (mode == XMESA_FX_FULLSCREEN) { + FX_grSstControl(GR_CONTROL_ACTIVATE); + xmesa->xm_draw_buffer->FXwindowHack = GL_FALSE; + return GL_TRUE; + } + else { + /* Error: Bad mode value */ + } + } + } + /*fprintf(stderr, "fallthrough\n");*/ +#else + (void) mode; +#endif + return GL_FALSE; +} + + + +#ifdef FX +/* + * Read image from VooDoo frame buffer into X/Mesa's back XImage. + */ +static void FXgetImage( XMesaBuffer b ) +{ + GET_CURRENT_CONTEXT(ctx); + static unsigned short pixbuf[MAX_WIDTH]; + GLuint x, y; + int xpos, ypos; + XMesaWindow root; + unsigned int bw, depth, width, height; + XMesaContext xmesa = XMESA_CONTEXT(ctx); + +#ifdef XFree86Server + x = b->frontbuffer->x; + y = b->frontbuffer->y; + width = b->frontbuffer->width; + height = b->frontbuffer->height; + depth = b->frontbuffer->depth; +#else + XGetGeometry( b->xm_visual->display, b->frontbuffer, + &root, &xpos, &ypos, &width, &height, &bw, &depth); +#endif + if (b->width != width || b->height != height) { + b->width = MIN2((int)width, b->FXctx->width); + b->height = MIN2((int)height, b->FXctx->height); + if (b->width & 1) + b->width--; /* prevent odd width */ + xmesa_alloc_back_buffer( b ); + } + + /* [dBorca] we're always in the right GR_COLORFORMAT... aren't we? */ + /* grLfbWriteColorFormat(GR_COLORFORMAT_ARGB); */ + if (b->xm_visual->undithered_pf==PF_5R6G5B) { + /* Special case: 16bpp RGB */ + grLfbReadRegion( GR_BUFFER_FRONTBUFFER, /* src buffer */ + 0, b->FXctx->height - b->height, /*pos*/ + b->width, b->height, /* size */ + b->width * sizeof(GLushort), /* stride */ + b->backimage->data); /* dest buffer */ + } + else if (b->xm_visual->dithered_pf==PF_Dither + && GET_VISUAL_DEPTH(b->xm_visual)==8) { + /* Special case: 8bpp RGB */ + for (y=0;yheight;y++) { + GLubyte *ptr = (GLubyte*) b->backimage->data + + b->backimage->bytes_per_line * y; + XDITHER_SETUP(y); + + /* read row from 3Dfx frame buffer */ + grLfbReadRegion( GR_BUFFER_FRONTBUFFER, + 0, b->FXctx->height-(b->height-y), + b->width, 1, + 0, + pixbuf ); + + /* write to XImage back buffer */ + for (x=0;xwidth;x++) { + GLubyte r = (pixbuf[x] & 0xf800) >> 8; + GLubyte g = (pixbuf[x] & 0x07e0) >> 3; + GLubyte b = (pixbuf[x] & 0x001f) << 3; + *ptr++ = XDITHER( x, r, g, b); + } + } + } + else { + /* General case: slow! */ + for (y=0;yheight;y++) { + /* read row from 3Dfx frame buffer */ + grLfbReadRegion( GR_BUFFER_FRONTBUFFER, + 0, b->FXctx->height-(b->height-y), + b->width, 1, + 0, + pixbuf ); + + /* write to XImage back buffer */ + for (x=0;xwidth;x++) { + XMesaPutPixel(b->backimage,x,y, + xmesa_color_to_pixel(xmesa, + (pixbuf[x] & 0xf800) >> 8, + (pixbuf[x] & 0x07e0) >> 3, + (pixbuf[x] & 0x001f) << 3, + 0xff, + b->xm_visual->undithered_pf)); + } + } + } + /* grLfbWriteColorFormat(GR_COLORFORMAT_ABGR); */ +} +#endif + + +/* + * Copy the back buffer to the front buffer. If there's no back buffer + * this is a no-op. + */ +void XMesaSwapBuffers( XMesaBuffer b ) +{ + GET_CURRENT_CONTEXT(ctx); + + /* If we're swapping the buffer associated with the current context + * we have to flush any pending rendering commands first. + */ + if (ctx && ctx->DrawBuffer == &(b->mesa_buffer)) + _mesa_notifySwapBuffers(ctx); + + if (b->db_state) { +#ifdef FX + if (b->FXctx) { + fxMesaSwapBuffers(); + + if (b->FXwindowHack) + FXgetImage(b); + else + return; + } +#endif + if (b->backimage) { + /* Copy Ximage from host's memory to server's window */ +#if defined(USE_XSHM) && !defined(XFree86Server) + if (b->shm) { + /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ + XShmPutImage( b->xm_visual->display, b->frontbuffer, + b->swapgc, + b->backimage, 0, 0, + 0, 0, b->width, b->height, False ); + /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/ + } + else +#endif + { + /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ + XMesaPutImage( b->xm_visual->display, b->frontbuffer, + b->swapgc, + b->backimage, 0, 0, + 0, 0, b->width, b->height ); + /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/ + } + } + else { + /* Copy pixmap to window on server */ + /*_glthread_LOCK_MUTEX(_xmesa_lock);*/ + XMesaCopyArea( b->xm_visual->display, + b->backpixmap, /* source drawable */ + b->frontbuffer, /* dest. drawable */ + b->swapgc, + 0, 0, b->width, b->height, /* source region */ + 0, 0 /* dest region */ + ); + /*_glthread_UNLOCK_MUTEX(_xmesa_lock);*/ + } + } +#if !defined(XFree86Server) + XSync( b->xm_visual->display, False ); +#endif +} + + + +/* + * Copy sub-region of back buffer to front buffer + */ +void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height ) +{ + GET_CURRENT_CONTEXT(ctx); + + /* If we're swapping the buffer associated with the current context + * we have to flush any pending rendering commands first. + */ + if (ctx && ctx->DrawBuffer == &(b->mesa_buffer)) + _mesa_notifySwapBuffers(ctx); + + if (b->db_state) { + int yTop = b->height - y - height; +#ifdef FX + if (b->FXctx) { + fxMesaSwapBuffers(); + if (b->FXwindowHack) + FXgetImage(b); + else + return; + } +#endif + if (b->backimage) { + /* Copy Ximage from host's memory to server's window */ +#if defined(USE_XSHM) && !defined(XFree86Server) + if (b->shm) { + /* XXX assuming width and height aren't too large! */ + XShmPutImage( b->xm_visual->display, b->frontbuffer, + b->swapgc, + b->backimage, x, yTop, + x, yTop, width, height, False ); + /* wait for finished event??? */ + } + else +#endif + { + /* XXX assuming width and height aren't too large! */ + XMesaPutImage( b->xm_visual->display, b->frontbuffer, + b->swapgc, + b->backimage, x, yTop, + x, yTop, width, height ); + } + } + else { + /* Copy pixmap to window on server */ + XMesaCopyArea( b->xm_visual->display, + b->backpixmap, /* source drawable */ + b->frontbuffer, /* dest. drawable */ + b->swapgc, + x, yTop, width, height, /* source region */ + x, yTop /* dest region */ + ); + } + } +} + + +/* + * Return a pointer to the XMesa backbuffer Pixmap or XImage. This function + * is a way to get "under the hood" of X/Mesa so one can manipulate the + * back buffer directly. + * Output: pixmap - pointer to back buffer's Pixmap, or 0 + * ximage - pointer to back buffer's XImage, or NULL + * Return: GL_TRUE = context is double buffered + * GL_FALSE = context is single buffered + */ +GLboolean XMesaGetBackBuffer( XMesaBuffer b, + XMesaPixmap *pixmap, + XMesaImage **ximage ) +{ + if (b->db_state) { + if (pixmap) *pixmap = b->backpixmap; + if (ximage) *ximage = b->backimage; + return GL_TRUE; + } + else { + *pixmap = 0; + *ximage = NULL; + return GL_FALSE; + } +} + + +/* + * Return the depth buffer associated with an XMesaBuffer. + * Input: b - the XMesa buffer handle + * Output: width, height - size of buffer in pixels + * bytesPerValue - bytes per depth value (2 or 4) + * buffer - pointer to depth buffer values + * Return: GL_TRUE or GL_FALSE to indicate success or failure. + */ +GLboolean XMesaGetDepthBuffer( XMesaBuffer b, GLint *width, GLint *height, + GLint *bytesPerValue, void **buffer ) +{ + if (!b->mesa_buffer.DepthBuffer) { + *width = 0; + *height = 0; + *bytesPerValue = 0; + *buffer = 0; + return GL_FALSE; + } + else { + *width = b->mesa_buffer.Width; + *height = b->mesa_buffer.Height; + *bytesPerValue = b->mesa_buffer.Visual.depthBits <= 16 + ? sizeof(GLushort) : sizeof(GLuint); + *buffer = b->mesa_buffer.DepthBuffer; + return GL_TRUE; + } +} + + +void XMesaFlush( XMesaContext c ) +{ + if (c && c->xm_visual) { +#ifdef XFree86Server + /* NOT_NEEDED */ +#else + XSync( c->xm_visual->display, False ); +#endif + } +} + + + +const char *XMesaGetString( XMesaContext c, int name ) +{ + (void) c; + if (name==XMESA_VERSION) { + return "5.0"; + } + else if (name==XMESA_EXTENSIONS) { + return ""; + } + else { + return NULL; + } +} + + + +XMesaBuffer XMesaFindBuffer( XMesaDisplay *dpy, XMesaDrawable d ) +{ + XMesaBuffer b; + for (b=XMesaBufferList; b; b=b->Next) { + if (b->frontbuffer==d && b->display==dpy) { + return b; + } + } + return NULL; +} + + + +/* + * Look for XMesaBuffers whose X window has been destroyed. + * Deallocate any such XMesaBuffers. + */ +void XMesaGarbageCollect( void ) +{ + XMesaBuffer b, next; + for (b=XMesaBufferList; b; b=next) { + next = b->Next; + if (b->display && b->frontbuffer && b->type == WINDOW) { +#ifdef XFree86Server + /* NOT_NEEDED */ +#else + XSync(b->display, False); + if (!window_exists( b->display, b->frontbuffer )) { + /* found a dead window, free the ancillary info */ + XMesaDestroyBuffer( b ); + } +#endif + } + } +} + + +void XMesaReset( void ) +{ + while (XMesaBufferList) + XMesaDestroyBuffer(XMesaBufferList); + + XMesaBufferList = NULL; +} + + +unsigned long XMesaDitherColor( XMesaContext xmesa, GLint x, GLint y, + GLfloat red, GLfloat green, + GLfloat blue, GLfloat alpha ) +{ + GLint r = (GLint) (red * 255.0F); + GLint g = (GLint) (green * 255.0F); + GLint b = (GLint) (blue * 255.0F); + GLint a = (GLint) (alpha * 255.0F); + + switch (xmesa->pixelformat) { + case PF_Index: + return 0; + case PF_Truecolor: + { + unsigned long p; + PACK_TRUECOLOR( p, r, g, b ); + return p; + } + case PF_8A8B8G8R: + return PACK_8A8B8G8R( r, g, b, a ); + case PF_8A8R8G8B: + return PACK_8A8R8G8B( r, g, b, a ); + case PF_8R8G8B: + return PACK_8R8G8B( r, g, b ); + case PF_5R6G5B: + return PACK_5R6G5B( r, g, b ); + case PF_Dither: + { + DITHER_SETUP; + return DITHER( x, y, r, g, b ); + } + case PF_1Bit: + /* 382 = (3*255)/2 */ + return ((r+g+b) > 382) ^ xmesa->xm_visual->bitFlip; + case PF_HPCR: + return DITHER_HPCR(x, y, r, g, b); + case PF_Lookup: + { + LOOKUP_SETUP; + return LOOKUP( r, g, b ); + } + case PF_Grayscale: + return GRAY_RGB( r, g, b ); + case PF_Dither_5R6G5B: + /* fall through */ + case PF_Dither_True: + { + unsigned long p; + PACK_TRUEDITHER(p, x, y, r, g, b); + return p; + } + default: + _mesa_problem(NULL, "Bad pixel format in XMesaDitherColor"); + } + return 0; +} + + +/* + * This is typically called when the window size changes and we need + * to reallocate the buffer's back/depth/stencil/accum buffers. + */ +void XMesaResizeBuffers( XMesaBuffer b ) +{ + xmesa_resize_buffers( &(b->mesa_buffer) ); + +} + diff --git a/src/mesa/drivers/x11/xm_dd.c b/src/mesa/drivers/x11/xm_dd.c new file mode 100644 index 0000000..ebd75cd --- /dev/null +++ b/src/mesa/drivers/x11/xm_dd.c @@ -0,0 +1,1220 @@ +/* + * Mesa 3-D graphics library + * Version: 6.1 + * + * Copyright (C) 1999-2004 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. + */ + + +#include "glxheader.h" +#include "bufferobj.h" +#include "context.h" +#include "colormac.h" +#include "depth.h" +#include "drawpix.h" +#include "extensions.h" +#include "macros.h" +#include "imports.h" +#include "mtypes.h" +#include "state.h" +#include "texobj.h" +#include "teximage.h" +#include "texstore.h" +#include "texformat.h" +#include "xmesaP.h" +#include "array_cache/acache.h" +#include "swrast/swrast.h" +#include "swrast/s_auxbuffer.h" +#include "swrast/s_context.h" +#include "swrast/s_drawpix.h" +#include "swrast/s_alphabuf.h" +#include "swrast_setup/swrast_setup.h" +#include "tnl/tnl.h" +#include "tnl/t_context.h" + +#ifdef XFree86Server +#include +#endif + + + +/* + * Dithering kernels and lookup tables. + */ + +const int xmesa_kernel8[DITH_DY * DITH_DX] = { + 0 * MAXC, 8 * MAXC, 2 * MAXC, 10 * MAXC, + 12 * MAXC, 4 * MAXC, 14 * MAXC, 6 * MAXC, + 3 * MAXC, 11 * MAXC, 1 * MAXC, 9 * MAXC, + 15 * MAXC, 7 * MAXC, 13 * MAXC, 5 * MAXC, +}; + +const short xmesa_HPCR_DRGB[3][2][16] = { + { + { 16, -4, 1,-11, 14, -6, 3, -9, 15, -5, 2,-10, 13, -7, 4, -8}, + {-15, 5, 0, 12,-13, 7, -2, 10,-14, 6, -1, 11,-12, 8, -3, 9} + }, + { + {-11, 15, -7, 3, -8, 14, -4, 2,-10, 16, -6, 4, -9, 13, -5, 1}, + { 12,-14, 8, -2, 9,-13, 5, -1, 11,-15, 7, -3, 10,-12, 6, 0} + }, + { + { 6,-18, 26,-14, 2,-22, 30,-10, 8,-16, 28,-12, 4,-20, 32, -8}, + { -4, 20,-24, 16, 0, 24,-28, 12, -6, 18,-26, 14, -2, 22,-30, 10} + } +}; + +const int xmesa_kernel1[16] = { + 0*47, 9*47, 4*47, 12*47, /* 47 = (255*3)/16 */ + 6*47, 2*47, 14*47, 8*47, + 10*47, 1*47, 5*47, 11*47, + 7*47, 13*47, 3*47, 15*47 +}; + + +/* + * Return the size (width, height) of the X window for the given GLframebuffer. + * Output: width - width of buffer in pixels. + * height - height of buffer in pixels. + */ +static void +get_buffer_size( GLframebuffer *buffer, GLuint *width, GLuint *height ) +{ + /* We can do this cast because the first field in the XMesaBuffer + * struct is a GLframebuffer struct. If this weren't true, we'd + * need a pointer from the GLframebuffer to the XMesaBuffer. + */ + const XMesaBuffer xmBuffer = (XMesaBuffer) buffer; + unsigned int winwidth, winheight; +#ifdef XFree86Server + /* XFree86 GLX renderer */ + winwidth = MIN2(xmBuffer->frontbuffer->width, MAX_WIDTH); + winheight = MIN2(xmBuffer->frontbuffer->height, MAX_HEIGHT); +#else + Window root; + int winx, winy; + unsigned int bw, d; + + _glthread_LOCK_MUTEX(_xmesa_lock); + XSync(xmBuffer->xm_visual->display, 0); /* added for Chromium */ + XGetGeometry( xmBuffer->xm_visual->display, xmBuffer->frontbuffer, &root, + &winx, &winy, &winwidth, &winheight, &bw, &d ); + _glthread_UNLOCK_MUTEX(_xmesa_lock); +#endif + + *width = winwidth; + *height = winheight; +} + + +static void +finish_or_flush( GLcontext *ctx ) +{ +#ifdef XFree86Server + /* NOT_NEEDED */ +#else + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + if (xmesa) { + _glthread_LOCK_MUTEX(_xmesa_lock); + XSync( xmesa->display, False ); + _glthread_UNLOCK_MUTEX(_xmesa_lock); + } +#endif +} + + + +/* + * This chooses the color buffer for reading and writing spans, points, + * lines, and triangles. + */ +void +xmesa_set_buffer( GLcontext *ctx, GLframebuffer *buffer, GLuint bufferBit ) +{ + /* We can make this cast since the XMesaBuffer wraps GLframebuffer. + * GLframebuffer is the first member in a XMesaBuffer struct. + */ + XMesaBuffer target = (XMesaBuffer) buffer; + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + + /* This assignment tells the span/point/line/triangle functions + * which XMesaBuffer to use. + */ + xmesa->xm_buffer = target; + + /* + * Now determine front vs back color buffer. + */ + if (bufferBit == DD_FRONT_LEFT_BIT) { + target->buffer = target->frontbuffer; + xmesa_update_span_funcs(ctx); + } + else if (bufferBit == DD_BACK_LEFT_BIT) { + ASSERT(target->db_state); + if (target->backpixmap) { + /* back buffer is a pixmap */ + target->buffer = (XMesaDrawable) target->backpixmap; + } + else if (target->backimage) { + /* back buffer is an XImage */ + target->buffer = None; + } + else { + /* No back buffer!!!! Must be out of memory, use front buffer */ + target->buffer = target->frontbuffer; + } + xmesa_update_span_funcs(ctx); + } + else if (bufferBit & (DD_AUX0_BIT | DD_AUX1_BIT | DD_AUX2_BIT | DD_AUX3_BIT)) { + _swrast_use_aux_buffer(ctx, buffer, bufferBit); + } + else { + _mesa_problem(ctx, "invalid buffer 0x%x in set_buffer() in xm_dd.c"); + return; + } +} + + + +static void +clear_index( GLcontext *ctx, GLuint index ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + xmesa->clearpixel = (unsigned long) index; + XMesaSetForeground( xmesa->display, xmesa->xm_draw_buffer->cleargc, + (unsigned long) index ); +} + + +static void +clear_color( GLcontext *ctx, const GLfloat color[4] ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[0], color[0]); + CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[1], color[1]); + CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[2], color[2]); + CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[3], color[3]); + xmesa->clearpixel = xmesa_color_to_pixel( xmesa, + xmesa->clearcolor[0], + xmesa->clearcolor[1], + xmesa->clearcolor[2], + xmesa->clearcolor[3], + xmesa->xm_visual->undithered_pf ); + _glthread_LOCK_MUTEX(_xmesa_lock); + XMesaSetForeground( xmesa->display, xmesa->xm_draw_buffer->cleargc, + xmesa->clearpixel ); + _glthread_UNLOCK_MUTEX(_xmesa_lock); +} + + + +/* Set index mask ala glIndexMask */ +static void +index_mask( GLcontext *ctx, GLuint mask ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + if (xmesa->xm_draw_buffer->buffer != XIMAGE) { + unsigned long m; + if (mask==0xffffffff) { + m = ((unsigned long)~0L); + } + else { + m = (unsigned long) mask; + } + XMesaSetPlaneMask( xmesa->display, xmesa->xm_draw_buffer->cleargc, m ); + XMesaSetPlaneMask( xmesa->display, xmesa->xm_draw_buffer->gc, m ); + } +} + + +/* Implements glColorMask() */ +static void +color_mask(GLcontext *ctx, + GLboolean rmask, GLboolean gmask, GLboolean bmask, GLboolean amask) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + const int xclass = xmesa->xm_visual->mesa_visual.visualType; + (void) amask; + + if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) { + unsigned long m; + if (rmask && gmask && bmask) { + m = ((unsigned long)~0L); + } + else { + m = 0; + if (rmask) m |= GET_REDMASK(xmesa->xm_visual); + if (gmask) m |= GET_GREENMASK(xmesa->xm_visual); + if (bmask) m |= GET_BLUEMASK(xmesa->xm_visual); + } + XMesaSetPlaneMask( xmesa->display, xmesa->xm_draw_buffer->cleargc, m ); + XMesaSetPlaneMask( xmesa->display, xmesa->xm_draw_buffer->gc, m ); + } +} + + + +/**********************************************************************/ +/*** glClear implementations ***/ +/**********************************************************************/ + + +static void +clear_front_pixmap( GLcontext *ctx, GLboolean all, + GLint x, GLint y, GLint width, GLint height ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + if (all) { + XMesaFillRectangle( xmesa->display, xmesa->xm_draw_buffer->frontbuffer, + xmesa->xm_draw_buffer->cleargc, + 0, 0, + xmesa->xm_draw_buffer->width+1, + xmesa->xm_draw_buffer->height+1 ); + } + else { + XMesaFillRectangle( xmesa->display, xmesa->xm_draw_buffer->frontbuffer, + xmesa->xm_draw_buffer->cleargc, + x, xmesa->xm_draw_buffer->height - y - height, + width, height ); + } +} + + +static void +clear_back_pixmap( GLcontext *ctx, GLboolean all, + GLint x, GLint y, GLint width, GLint height ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + if (all) { + XMesaFillRectangle( xmesa->display, xmesa->xm_draw_buffer->backpixmap, + xmesa->xm_draw_buffer->cleargc, + 0, 0, + xmesa->xm_draw_buffer->width+1, + xmesa->xm_draw_buffer->height+1 ); + } + else { + XMesaFillRectangle( xmesa->display, xmesa->xm_draw_buffer->backpixmap, + xmesa->xm_draw_buffer->cleargc, + x, xmesa->xm_draw_buffer->height - y - height, + width, height ); + } +} + + +static void +clear_8bit_ximage( GLcontext *ctx, GLboolean all, + GLint x, GLint y, GLint width, GLint height ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + if (all) { + size_t n = xmesa->xm_draw_buffer->backimage->bytes_per_line + * xmesa->xm_draw_buffer->backimage->height; + MEMSET( xmesa->xm_draw_buffer->backimage->data, xmesa->clearpixel, n ); + } + else { + GLint i; + for (i=0;ixm_draw_buffer, x, y+i ); + MEMSET( ptr, xmesa->clearpixel, width ); + } + } +} + + +static void +clear_HPCR_ximage( GLcontext *ctx, GLboolean all, + GLint x, GLint y, GLint width, GLint height ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + if (all) { + GLint i, c16 = (xmesa->xm_draw_buffer->backimage->bytes_per_line>>4)<<4; + GLubyte *ptr = (GLubyte *)xmesa->xm_draw_buffer->backimage->data; + for (i=0; ixm_draw_buffer->backimage->height; i++) { + GLint j; + GLubyte *sptr = xmesa->xm_visual->hpcr_clear_ximage_pattern[0]; + if (i&1) { + sptr += 16; + } + for (j=0; jxm_draw_buffer->backimage->bytes_per_line; j++) { + *ptr = sptr[j&15]; + ptr++; + } + } + } + else { + GLint i; + for (i=y; ixm_draw_buffer, x, i ); + int j; + GLubyte *sptr = xmesa->xm_visual->hpcr_clear_ximage_pattern[0]; + if (i&1) { + sptr += 16; + } + for (j=x; jclearpixel; + if (xmesa->swapbytes) { + pixel = ((pixel >> 8) & 0x00ff) | ((pixel << 8) & 0xff00); + } + if (all) { + register GLuint n; + register GLuint *ptr4 = (GLuint *) xmesa->xm_draw_buffer->backimage->data; + if ((pixel & 0xff) == ((pixel >> 8) & 0xff)) { + /* low and high bytes are equal so use memset() */ + n = xmesa->xm_draw_buffer->backimage->bytes_per_line + * xmesa->xm_draw_buffer->height; + MEMSET( ptr4, pixel & 0xff, n ); + } + else { + pixel = pixel | (pixel<<16); + n = xmesa->xm_draw_buffer->backimage->bytes_per_line + * xmesa->xm_draw_buffer->height / 4; + do { + *ptr4++ = pixel; + n--; + } while (n!=0); + + if ((xmesa->xm_draw_buffer->backimage->bytes_per_line * + xmesa->xm_draw_buffer->height) & 0x2) + *(GLushort *)ptr4 = pixel & 0xffff; + } + } + else { + register int i, j; + for (j=0;jxm_draw_buffer, x, y+j ); + for (i=0;i */ +static void +clear_24bit_ximage( GLcontext *ctx, GLboolean all, + GLint x, GLint y, GLint width, GLint height ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + const GLubyte r = xmesa->clearcolor[0]; + const GLubyte g = xmesa->clearcolor[1]; + const GLubyte b = xmesa->clearcolor[2]; +#if 0 /* See below */ + register GLuint clearPixel; + if (xmesa->swapbytes) { + clearPixel = (b << 16) | (g << 8) | r; + } + else { + clearPixel = (r << 16) | (g << 8) | b; + } +#endif + + if (all) { + if (r==g && g==b) { + /* same value for all three components (gray) */ + const GLint w3 = xmesa->xm_draw_buffer->width * 3; + const GLint h = xmesa->xm_draw_buffer->height; + GLint i; + for (i = 0; i < h; i++) { + bgr_t *ptr3 = PIXELADDR3(xmesa->xm_draw_buffer, 0, i); + MEMSET(ptr3, r, w3); + } + } + else { + /* the usual case */ + const GLint w = xmesa->xm_draw_buffer->width; + const GLint h = xmesa->xm_draw_buffer->height; + GLint i, j; + for (i = 0; i < h; i++) { + bgr_t *ptr3 = PIXELADDR3(xmesa->xm_draw_buffer, 0, i); + for (j = 0; j < w; j++) { + ptr3->r = r; + ptr3->g = g; + ptr3->b = b; + ptr3++; + } + } +#if 0 /* this code doesn't work for all window widths */ + register GLuint *ptr4 = (GLuint *) ptr3; + register GLuint px; + GLuint pixel4[3]; + register GLuint *p = pixel4; + pixel4[0] = clearPixel | (clearPixel << 24); + pixel4[1] = (clearPixel << 16) | (clearPixel >> 8); + pixel4[2] = (clearPixel << 8) | (clearPixel >> 16); + switch (3 & (int)(ptr3 - (bgr_t*) ptr4)){ + case 0: + break; + case 1: + px = *ptr4 & 0x00ffffff; + px |= pixel4[0] & 0xff000000; + *ptr4++ = px; + px = *ptr4 & 0xffff0000; + px |= pixel4[2] & 0x0000ffff; + *ptr4 = px; + if (0 == --n) + break; + case 2: + px = *ptr4 & 0x0000fffff; + px |= pixel4[1] & 0xffff0000; + *ptr4++ = px; + px = *ptr4 & 0xffffff00; + px |= pixel4[2] & 0x000000ff; + *ptr4 = px; + if (0 == --n) + break; + case 3: + px = *ptr4 & 0x000000ff; + px |= pixel4[2] & 0xffffff00; + *ptr4++ = px; + --n; + break; + } + while (n > 3) { + p = pixel4; + *ptr4++ = *p++; + *ptr4++ = *p++; + *ptr4++ = *p++; + n -= 4; + } + switch (n) { + case 3: + p = pixel4; + *ptr4++ = *p++; + *ptr4++ = *p++; + px = *ptr4 & 0xffffff00; + px |= clearPixel & 0xff; + *ptr4 = px; + break; + case 2: + p = pixel4; + *ptr4++ = *p++; + px = *ptr4 & 0xffff0000; + px |= *p & 0xffff; + *ptr4 = px; + break; + case 1: + px = *ptr4 & 0xff000000; + px |= *p & 0xffffff; + *ptr4 = px; + break; + case 0: + break; + } +#endif + } + } + else { + /* only clear subrect of color buffer */ + if (r==g && g==b) { + /* same value for all three components (gray) */ + GLint j; + for (j=0;jxm_draw_buffer, x, y+j ); + MEMSET(ptr3, r, 3 * width); + } + } + else { + /* non-gray clear color */ + GLint i, j; + for (j = 0; j < height; j++) { + bgr_t *ptr3 = PIXELADDR3( xmesa->xm_draw_buffer, x, y+j ); + for (i = 0; i < width; i++) { + ptr3->r = r; + ptr3->g = g; + ptr3->b = b; + ptr3++; + } + } +#if 0 /* this code might not always (seems ptr3 always == ptr4) */ + GLint j; + GLuint pixel4[3]; + pixel4[0] = clearPixel | (clearPixel << 24); + pixel4[1] = (clearPixel << 16) | (clearPixel >> 8); + pixel4[2] = (clearPixel << 8) | (clearPixel >> 16); + for (j=0;jxm_draw_buffer, x, y+j ); + register GLuint *ptr4 = (GLuint *)ptr3; + register GLuint *p, px; + GLuint w = width; + switch (3 & (int)(ptr3 - (bgr_t*) ptr4)){ + case 0: + break; + case 1: + px = *ptr4 & 0x00ffffff; + px |= pixel4[0] & 0xff000000; + *ptr4++ = px; + px = *ptr4 & 0xffff0000; + px |= pixel4[2] & 0x0000ffff; + *ptr4 = px; + if (0 == --w) + break; + case 2: + px = *ptr4 & 0x0000fffff; + px |= pixel4[1] & 0xffff0000; + *ptr4++ = px; + px = *ptr4 & 0xffffff00; + px |= pixel4[2] & 0x000000ff; + *ptr4 = px; + if (0 == --w) + break; + case 3: + px = *ptr4 & 0x000000ff; + px |= pixel4[2] & 0xffffff00; + *ptr4++ = px; + --w; + break; + } + while (w > 3){ + p = pixel4; + *ptr4++ = *p++; + *ptr4++ = *p++; + *ptr4++ = *p++; + w -= 4; + } + switch (w) { + case 3: + p = pixel4; + *ptr4++ = *p++; + *ptr4++ = *p++; + px = *ptr4 & 0xffffff00; + px |= *p & 0xff; + *ptr4 = px; + break; + case 2: + p = pixel4; + *ptr4++ = *p++; + px = *ptr4 & 0xffff0000; + px |= *p & 0xffff; + *ptr4 = px; + break; + case 1: + px = *ptr4 & 0xff000000; + px |= pixel4[0] & 0xffffff; + *ptr4 = px; + break; + case 0: + break; + } + } +#endif + } + } +} + + +static void +clear_32bit_ximage( GLcontext *ctx, GLboolean all, + GLint x, GLint y, GLint width, GLint height ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + register GLuint pixel = (GLuint) xmesa->clearpixel; + if (xmesa->swapbytes) { + pixel = ((pixel >> 24) & 0x000000ff) + | ((pixel >> 8) & 0x0000ff00) + | ((pixel << 8) & 0x00ff0000) + | ((pixel << 24) & 0xff000000); + } + if (all) { + register GLint n = xmesa->xm_draw_buffer->width * xmesa->xm_draw_buffer->height; + register GLuint *ptr4 = (GLuint *) xmesa->xm_draw_buffer->backimage->data; + if (pixel==0) { + MEMSET( ptr4, pixel, 4*n ); + } + else { + do { + *ptr4++ = pixel; + n--; + } while (n!=0); + } + } + else { + register int i, j; + for (j=0;jxm_draw_buffer, x, y+j ); + for (i=0;ixm_draw_buffer->backimage; + if (all) { + register int i, j; + width = xmesa->xm_draw_buffer->width; + height = xmesa->xm_draw_buffer->height; + for (j=0;jclearpixel ); + } + } + } + else { + /* TODO: optimize this */ + register int i, j; + y = FLIP(xmesa->xm_draw_buffer, y); + for (j=0;jclearpixel ); + } + } + } +} + + + +static void +clear_buffers( GLcontext *ctx, GLbitfield mask, + GLboolean all, GLint x, GLint y, GLint width, GLint height ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + const GLuint *colorMask = (GLuint *) &ctx->Color.ColorMask; + + if ((mask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) && + xmesa->xm_draw_buffer->mesa_buffer.UseSoftwareAlphaBuffers && + ctx->Color.ColorMask[ACOMP]) { + _swrast_clear_alpha_buffers(ctx); + } + + /* we can't handle color or index masking */ + if (*colorMask == 0xffffffff && ctx->Color.IndexMask == 0xffffffff) { + if (mask & DD_FRONT_LEFT_BIT) { + ASSERT(xmesa->xm_draw_buffer->front_clear_func); + (*xmesa->xm_draw_buffer->front_clear_func)( ctx, all, x, y, width, height ); + mask &= ~DD_FRONT_LEFT_BIT; + } + if (mask & DD_BACK_LEFT_BIT) { + ASSERT(xmesa->xm_draw_buffer->back_clear_func); + (*xmesa->xm_draw_buffer->back_clear_func)( ctx, all, x, y, width, height ); + mask &= ~DD_BACK_LEFT_BIT; + } + } + + if (mask) + _swrast_Clear( ctx, mask, all, x, y, width, height ); +} + + +/* + * When we detect that the user has resized the window this function will + * get called. Here we'll reallocate the back buffer, depth buffer, + * stencil buffer etc. to match the new window size. + */ +void +xmesa_resize_buffers( GLframebuffer *buffer ) +{ + int height = (int) buffer->Height; + /* We can do this cast because the first field in the XMesaBuffer + * struct is a GLframebuffer struct. If this weren't true, we'd + * need a pointer from the GLframebuffer to the XMesaBuffer. + */ + XMesaBuffer xmBuffer = (XMesaBuffer) buffer; + + xmBuffer->width = buffer->Width; + xmBuffer->height = buffer->Height; + xmesa_alloc_back_buffer( xmBuffer ); + + /* Needed by FLIP macro */ + xmBuffer->bottom = height - 1; + + if (xmBuffer->backimage) { + /* Needed by PIXELADDR1 macro */ + xmBuffer->ximage_width1 = xmBuffer->backimage->bytes_per_line; + xmBuffer->ximage_origin1 = (GLubyte *) xmBuffer->backimage->data + + xmBuffer->ximage_width1 * (height-1); + + /* Needed by PIXELADDR2 macro */ + xmBuffer->ximage_width2 = xmBuffer->backimage->bytes_per_line / 2; + xmBuffer->ximage_origin2 = (GLushort *) xmBuffer->backimage->data + + xmBuffer->ximage_width2 * (height-1); + + /* Needed by PIXELADDR3 macro */ + xmBuffer->ximage_width3 = xmBuffer->backimage->bytes_per_line; + xmBuffer->ximage_origin3 = (GLubyte *) xmBuffer->backimage->data + + xmBuffer->ximage_width3 * (height-1); + + /* Needed by PIXELADDR4 macro */ + xmBuffer->ximage_width4 = xmBuffer->backimage->width; + xmBuffer->ximage_origin4 = (GLuint *) xmBuffer->backimage->data + + xmBuffer->ximage_width4 * (height-1); + } + + _swrast_alloc_buffers( buffer ); +} + + +#ifndef XFree86Server +/* XXX this was never tested in the Xserver environment */ + +/** + * This function implements glDrawPixels() with an XPutImage call when + * drawing to the front buffer (X Window drawable). + * The image format must be GL_BGRA to match the PF_8R8G8B pixel format. + */ +static void +xmesa_DrawPixels_8R8G8B( GLcontext *ctx, + GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *unpack, + const GLvoid *pixels ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + const SWcontext *swrast = SWRAST_CONTEXT( ctx ); + XMesaDisplay *dpy = xmesa->xm_visual->display; + const XMesaDrawable buffer = xmesa->xm_draw_buffer->buffer; + const XMesaGC gc = xmesa->xm_draw_buffer->gc; + + ASSERT(dpy); + ASSERT(gc); + ASSERT(xmesa->xm_visual->dithered_pf == PF_8R8G8B); + ASSERT(xmesa->xm_visual->undithered_pf == PF_8R8G8B); + + if (swrast->NewState) + _swrast_validate_derived( ctx ); + + if (buffer && /* buffer != 0 means it's a Window or Pixmap */ + format == GL_BGRA && + type == GL_UNSIGNED_BYTE && + (swrast->_RasterMask & ~CLIP_BIT) == 0 && /* no blend, z-test, etc */ + ctx->_ImageTransferState == 0 && /* no color tables, scale/bias, etc */ + ctx->Pixel.ZoomX == 1.0 && /* no zooming */ + ctx->Pixel.ZoomY == 1.0) { + int dstX = x; + int dstY = y; + int w = width; + int h = height; + int srcX = unpack->SkipPixels; + int srcY = unpack->SkipRows; + int rowLength = unpack->RowLength ? unpack->RowLength : width; + + pixels = _swrast_validate_pbo_access(unpack, width, height, 1, + format, type, (GLvoid *) pixels); + if (!pixels) + return; + + if (_swrast_clip_pixelrect(ctx, &dstX, &dstY, &w, &h, &srcX, &srcY)) { + /* This is a little tricky since all coordinates up to now have + * been in the OpenGL bottom-to-top orientation. X is top-to-bottom + * so we have to carefully compute the Y coordinates/addresses here. + */ + XMesaImage ximage; + MEMSET(&ximage, 0, sizeof(XMesaImage)); + ximage.width = width; + ximage.height = height; + ximage.format = ZPixmap; + ximage.data = (char *) pixels + + ((srcY + h - 1) * rowLength + srcX) * 4; + ximage.byte_order = LSBFirst; + ximage.bitmap_unit = 32; + ximage.bitmap_bit_order = LSBFirst; + ximage.bitmap_pad = 32; + ximage.depth = 24; + ximage.bytes_per_line = -rowLength * 4; /* negative to flip image */ + ximage.bits_per_pixel = 32; + /* it seems we don't need to set the ximage.red/green/blue_mask fields */ + /* flip Y axis for dest position */ + dstY = FLIP(xmesa->xm_draw_buffer, dstY) - h + 1; + XPutImage(dpy, buffer, gc, &ximage, 0, 0, dstX, dstY, w, h); + } + } + else { + /* software fallback */ + _swrast_DrawPixels(ctx, x, y, width, height, + format, type, unpack, pixels); + } +} + + + +/** + * This function implements glDrawPixels() with an XPutImage call when + * drawing to the front buffer (X Window drawable). The image format + * must be GL_RGB and image type must be GL_UNSIGNED_SHORT_5_6_5 to + * match the PF_5R6G5B pixel format. + */ +static void +xmesa_DrawPixels_5R6G5B( GLcontext *ctx, + GLint x, GLint y, GLsizei width, GLsizei height, + GLenum format, GLenum type, + const struct gl_pixelstore_attrib *unpack, + const GLvoid *pixels ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + const SWcontext *swrast = SWRAST_CONTEXT( ctx ); + XMesaDisplay *dpy = xmesa->xm_visual->display; + const XMesaDrawable buffer = xmesa->xm_draw_buffer->buffer; + const XMesaGC gc = xmesa->xm_draw_buffer->gc; + + ASSERT(dpy); + ASSERT(gc); + ASSERT(xmesa->xm_visual->undithered_pf == PF_5R6G5B); + + if (swrast->NewState) + _swrast_validate_derived( ctx ); + + if (buffer && /* buffer != 0 means it's a Window or Pixmap */ + format == GL_RGB && + type == GL_UNSIGNED_SHORT_5_6_5 && + !ctx->Color.DitherFlag && /* no dithering */ + (swrast->_RasterMask & ~CLIP_BIT) == 0 && /* no blend, z-test, etc */ + ctx->_ImageTransferState == 0 && /* no color tables, scale/bias, etc */ + ctx->Pixel.ZoomX == 1.0 && /* no zooming */ + ctx->Pixel.ZoomY == 1.0) { + int dstX = x; + int dstY = y; + int w = width; + int h = height; + int srcX = unpack->SkipPixels; + int srcY = unpack->SkipRows; + int rowLength = unpack->RowLength ? unpack->RowLength : width; + + pixels = _swrast_validate_pbo_access(unpack, width, height, 1, + format, type, (GLvoid *) pixels); + if (!pixels) + return; + + if (_swrast_clip_pixelrect(ctx, &dstX, &dstY, &w, &h, &srcX, &srcY)) { + /* This is a little tricky since all coordinates up to now have + * been in the OpenGL bottom-to-top orientation. X is top-to-bottom + * so we have to carefully compute the Y coordinates/addresses here. + */ + XMesaImage ximage; + MEMSET(&ximage, 0, sizeof(XMesaImage)); + ximage.width = width; + ximage.height = height; + ximage.format = ZPixmap; + ximage.data = (char *) pixels + + ((srcY + h - 1) * rowLength + srcX) * 2; + ximage.byte_order = LSBFirst; + ximage.bitmap_unit = 16; + ximage.bitmap_bit_order = LSBFirst; + ximage.bitmap_pad = 16; + ximage.depth = 16; + ximage.bytes_per_line = -rowLength * 2; /* negative to flip image */ + ximage.bits_per_pixel = 16; + /* it seems we don't need to set the ximage.red/green/blue_mask fields */ + /* flip Y axis for dest position */ + dstY = FLIP(xmesa->xm_draw_buffer, dstY) - h + 1; + XPutImage(dpy, buffer, gc, &ximage, 0, 0, dstX, dstY, w, h); + } + } + else { + /* software fallback */ + _swrast_DrawPixels(ctx, x, y, width, height, + format, type, unpack, pixels); + } +} + + + +/** + * Implement glCopyPixels for the front color buffer (or back buffer Pixmap) + * for the color buffer. Don't support zooming, pixel transfer, etc. + * We do support copying from one window to another, ala glXMakeCurrentRead. + */ +static void +xmesa_CopyPixels( GLcontext *ctx, + GLint srcx, GLint srcy, GLsizei width, GLsizei height, + GLint destx, GLint desty, GLenum type ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + const SWcontext *swrast = SWRAST_CONTEXT( ctx ); + XMesaDisplay *dpy = xmesa->xm_visual->display; + const XMesaDrawable drawBuffer = xmesa->xm_draw_buffer->buffer; + const XMesaDrawable readBuffer = xmesa->xm_read_buffer->buffer; + const XMesaGC gc = xmesa->xm_draw_buffer->gc; + + ASSERT(dpy); + ASSERT(gc); + + if (swrast->NewState) + _swrast_validate_derived( ctx ); + + if (ctx->Color.DrawBuffer == GL_FRONT && + ctx->Pixel.ReadBuffer == GL_FRONT && + drawBuffer && /* buffer != 0 means it's a Window or Pixmap */ + readBuffer && + type == GL_COLOR && + (swrast->_RasterMask & ~CLIP_BIT) == 0 && /* no blend, z-test, etc */ + ctx->_ImageTransferState == 0 && /* no color tables, scale/bias, etc */ + ctx->Pixel.ZoomX == 1.0 && /* no zooming */ + ctx->Pixel.ZoomY == 1.0) { + /* Note: we don't do any special clipping work here. We could, + * but X will do it for us. + */ + srcy = FLIP(xmesa->xm_read_buffer, srcy) - height + 1; + desty = FLIP(xmesa->xm_draw_buffer, desty) - height + 1; + XCopyArea(dpy, readBuffer, drawBuffer, gc, + srcx, srcy, width, height, destx, desty); + } + else { + _swrast_CopyPixels(ctx, srcx, srcy, width, height, destx, desty, type ); + } +} +#endif /* XFree86Server */ + + + +/* + * Every driver should implement a GetString function in order to + * return a meaningful GL_RENDERER string. + */ +static const GLubyte * +get_string( GLcontext *ctx, GLenum name ) +{ + (void) ctx; + switch (name) { + case GL_RENDERER: +#ifdef XFree86Server + return (const GLubyte *) "Mesa GLX Indirect"; +#else + return (const GLubyte *) "Mesa X11"; +#endif + case GL_VENDOR: +#ifdef XFree86Server + return (const GLubyte *) "Mesa project: www.mesa3d.org"; +#else + return NULL; +#endif + default: + return NULL; + } +} + + +/* + * We implement the glEnable function only because we care about + * dither enable/disable. + */ +static void +enable( GLcontext *ctx, GLenum pname, GLboolean state ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + + switch (pname) { + case GL_DITHER: + if (state) + xmesa->pixelformat = xmesa->xm_visual->dithered_pf; + else + xmesa->pixelformat = xmesa->xm_visual->undithered_pf; + break; + default: + ; /* silence compiler warning */ + } +} + + +void xmesa_update_state( GLcontext *ctx, GLuint new_state ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + + /* Propogate statechange information to swrast and swrast_setup + * modules. The X11 driver has no internal GL-dependent state. + */ + _swrast_InvalidateState( ctx, new_state ); + _ac_InvalidateState( ctx, new_state ); + _tnl_InvalidateState( ctx, new_state ); + _swsetup_InvalidateState( ctx, new_state ); + + + /* setup pointers to front and back buffer clear functions */ + xmesa->xm_draw_buffer->front_clear_func = clear_front_pixmap; + if (xmesa->xm_draw_buffer->backpixmap != XIMAGE) { + xmesa->xm_draw_buffer->back_clear_func = clear_back_pixmap; + } + else if (sizeof(GLushort)!=2 || sizeof(GLuint)!=4) { + xmesa->xm_draw_buffer->back_clear_func = clear_nbit_ximage; + } + else switch (xmesa->xm_visual->BitsPerPixel) { + case 8: + if (xmesa->xm_visual->hpcr_clear_flag) { + xmesa->xm_draw_buffer->back_clear_func = clear_HPCR_ximage; + } + else { + xmesa->xm_draw_buffer->back_clear_func = clear_8bit_ximage; + } + break; + case 16: + xmesa->xm_draw_buffer->back_clear_func = clear_16bit_ximage; + break; + case 24: + xmesa->xm_draw_buffer->back_clear_func = clear_24bit_ximage; + break; + case 32: + xmesa->xm_draw_buffer->back_clear_func = clear_32bit_ximage; + break; + default: + xmesa->xm_draw_buffer->back_clear_func = clear_nbit_ximage; + break; + } + + if (ctx->Color._DrawDestMask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) { + xmesa_update_span_funcs(ctx); + } +} + + + +/** + * Called via ctx->Driver.TestProxyTeximage(). Normally, we'd just use + * the _mesa_test_proxy_teximage() fallback function, but we're going to + * special-case the 3D texture case to allow textures up to 512x512x32 + * texels. + */ +static GLboolean +test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level, + GLint internalFormat, GLenum format, GLenum type, + GLint width, GLint height, GLint depth, GLint border) +{ + if (target == GL_PROXY_TEXTURE_3D) { + /* special case for 3D textures */ + if (width * height * depth > 512 * 512 * 64 || + width < 2 * border || + (!ctx->Extensions.ARB_texture_non_power_of_two && + _mesa_bitcount(width - 2 * border) != 1) || + height < 2 * border || + (!ctx->Extensions.ARB_texture_non_power_of_two && + _mesa_bitcount(height - 2 * border) != 1) || + depth < 2 * border || + (!ctx->Extensions.ARB_texture_non_power_of_two && + _mesa_bitcount(depth - 2 * border) != 1)) { + /* Bad size, or too many texels */ + return GL_FALSE; + } + return GL_TRUE; + } + else { + /* use the fallback routine for 1D, 2D, cube and rect targets */ + return _mesa_test_proxy_teximage(ctx, target, level, internalFormat, + format, type, width, height, depth, + border); + } +} + + +/** + * Initialize the device driver function table with the functions + * we implement in this driver. + */ +void xmesa_init_driver_functions( XMesaVisual xmvisual, + struct dd_function_table *driver ) +{ + driver->GetString = get_string; + driver->UpdateState = xmesa_update_state; + driver->GetBufferSize = get_buffer_size; + driver->Flush = finish_or_flush; + driver->Finish = finish_or_flush; + driver->ClearIndex = clear_index; + driver->ClearColor = clear_color; + driver->IndexMask = index_mask; + driver->ColorMask = color_mask; + driver->Enable = enable; + driver->Clear = clear_buffers; + driver->ResizeBuffers = xmesa_resize_buffers; +#ifndef XFree86Server + driver->CopyPixels = /*_swrast_CopyPixels;*/xmesa_CopyPixels; + if (xmvisual->undithered_pf == PF_8R8G8B && + xmvisual->dithered_pf == PF_8R8G8B) { + driver->DrawPixels = xmesa_DrawPixels_8R8G8B; + } + else if (xmvisual->undithered_pf == PF_5R6G5B) { + driver->DrawPixels = xmesa_DrawPixels_5R6G5B; + } +#endif + driver->TestProxyTexImage = test_proxy_teximage; +} + + +#define XMESA_NEW_POINT (_NEW_POINT | \ + _NEW_RENDERMODE | \ + _SWRAST_NEW_RASTERMASK) + +#define XMESA_NEW_LINE (_NEW_LINE | \ + _NEW_TEXTURE | \ + _NEW_LIGHT | \ + _NEW_DEPTH | \ + _NEW_RENDERMODE | \ + _SWRAST_NEW_RASTERMASK) + +#define XMESA_NEW_TRIANGLE (_NEW_POLYGON | \ + _NEW_TEXTURE | \ + _NEW_LIGHT | \ + _NEW_DEPTH | \ + _NEW_RENDERMODE | \ + _SWRAST_NEW_RASTERMASK) + + +/* Extend the software rasterizer with our line/point/triangle + * functions. + */ +void xmesa_register_swrast_functions( GLcontext *ctx ) +{ + SWcontext *swrast = SWRAST_CONTEXT( ctx ); + struct swrast_device_driver *dd = _swrast_GetDeviceDriverReference(ctx); + + dd->SetBuffer = xmesa_set_buffer; + + swrast->choose_point = xmesa_choose_point; + swrast->choose_line = xmesa_choose_line; + swrast->choose_triangle = xmesa_choose_triangle; + + swrast->invalidate_point |= XMESA_NEW_POINT; + swrast->invalidate_line |= XMESA_NEW_LINE; + swrast->invalidate_triangle |= XMESA_NEW_TRIANGLE; +} diff --git a/src/mesa/drivers/x11/xm_line.c b/src/mesa/drivers/x11/xm_line.c new file mode 100644 index 0000000..5cd5cf7 --- /dev/null +++ b/src/mesa/drivers/x11/xm_line.c @@ -0,0 +1,617 @@ + +/* + * Mesa 3-D graphics library + * Version: 5.1 + * + * Copyright (C) 1999-2002 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. + */ + + +/* + * This file contains "accelerated" point, line, and triangle functions. + * It should be fairly easy to write new special-purpose point, line or + * triangle functions and hook them into this module. + */ + + +#include "glxheader.h" +#include "depth.h" +#include "macros.h" +#include "mtypes.h" +#include "xmesaP.h" + +/* Internal swrast includes: + */ +#include "swrast/s_depth.h" +#include "swrast/s_points.h" +#include "swrast/s_lines.h" +#include "swrast/s_context.h" + + +/**********************************************************************/ +/*** Point rendering ***/ +/**********************************************************************/ + + +/* + * Render an array of points into a pixmap, any pixel format. + */ +#if 000 +/* XXX don't use this, it doesn't dither correctly */ +static void draw_points_ANY_pixmap( GLcontext *ctx, const SWvertex *vert ) +{ + XMesaContext xmesa = XMESA_CONTEXT(ctx); + XMesaDisplay *dpy = xmesa->xm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + + if (xmesa->xm_visual->mesa_visual.RGBAflag) { + register int x, y; + const GLubyte *color = vert->color; + unsigned long pixel = xmesa_color_to_pixel( xmesa, + color[0], color[1], + color[2], color[3], + xmesa->pixelformat); + XMesaSetForeground( dpy, gc, pixel ); + x = (GLint) vert->win[0]; + y = FLIP( xmesa->xm_buffer, (GLint) vert->win[1] ); + XMesaDrawPoint( dpy, buffer, gc, x, y); + } + else { + /* Color index mode */ + register int x, y; + XMesaSetForeground( dpy, gc, vert->index ); + x = (GLint) vert->win[0]; + y = FLIP( xmesa->xm_buffer, (GLint) vert->win[1] ); + XMesaDrawPoint( dpy, buffer, gc, x, y); + } +} +#endif + + +/* Override the swrast point-selection function. Try to use one of + * our internal point functions, otherwise fall back to the standard + * swrast functions. + */ +void xmesa_choose_point( GLcontext *ctx ) +{ +#if 0 + XMesaContext xmesa = XMESA_CONTEXT(ctx); + SWcontext *swrast = SWRAST_CONTEXT(ctx); + + if (ctx->RenderMode == GL_RENDER + && ctx->Point.Size == 1.0F && !ctx->Point.SmoothFlag + && swrast->_RasterMask == 0 + && !ctx->Texture._EnabledUnits + && xmesa->xm_buffer->buffer != XIMAGE) { + swrast->Point = draw_points_ANY_pixmap; + } + else { + _swrast_choose_point( ctx ); + } +#else + _swrast_choose_point( ctx ); +#endif +} + + + +/**********************************************************************/ +/*** Line rendering ***/ +/**********************************************************************/ + + +/* + * Draw a flat-shaded, PF_TRUECOLOR line into an XImage. + */ +#define NAME flat_TRUECOLOR_line +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + const GLubyte *color = vert1->color; \ + XMesaImage *img = xmesa->xm_buffer->backimage; \ + unsigned long pixel; \ + PACK_TRUECOLOR( pixel, color[0], color[1], color[2] ); +#define CLIP_HACK 1 +#define PLOT(X,Y) XMesaPutPixel( img, X, FLIP(xmesa->xm_buffer, Y), pixel ); +#include "swrast/s_linetemp.h" + + + +/* + * Draw a flat-shaded, PF_8A8B8G8R line into an XImage. + */ +#define NAME flat_8A8B8G8R_line +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + const GLubyte *color = vert1->color; \ + GLuint pixel = PACK_8B8G8R( color[0], color[1], color[2] ); +#define PIXEL_TYPE GLuint +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y) +#define CLIP_HACK 1 +#define PLOT(X,Y) *pixelPtr = pixel; +#include "swrast/s_linetemp.h" + + + +/* + * Draw a flat-shaded, PF_8A8R8G8B line into an XImage. + */ +#define NAME flat_8A8R8G8B_line +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + const GLubyte *color = vert1->color; \ + GLuint pixel = PACK_8R8G8B( color[0], color[1], color[2] ); +#define PIXEL_TYPE GLuint +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y) +#define CLIP_HACK 1 +#define PLOT(X,Y) *pixelPtr = pixel; +#include "swrast/s_linetemp.h" + + + +/* + * Draw a flat-shaded, PF_8R8G8B line into an XImage. + */ +#define NAME flat_8R8G8B_line +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + const GLubyte *color = vert1->color; \ + GLuint pixel = PACK_8R8G8B( color[0], color[1], color[2] ); +#define PIXEL_TYPE GLuint +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y) +#define CLIP_HACK 1 +#define PLOT(X,Y) *pixelPtr = pixel; +#include "swrast/s_linetemp.h" + + + +/* + * Draw a flat-shaded, PF_8R8G8B24 line into an XImage. + */ +#define NAME flat_8R8G8B24_line +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + const GLubyte *color = vert1->color; +#define PIXEL_TYPE bgr_t +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define PIXEL_ADDRESS(X,Y) PIXELADDR3(xmesa->xm_buffer,X,Y) +#define CLIP_HACK 1 +#define PLOT(X,Y) { \ + pixelPtr->r = color[RCOMP]; \ + pixelPtr->g = color[GCOMP]; \ + pixelPtr->b = color[BCOMP]; \ +} +#include "swrast/s_linetemp.h" + + + +/* + * Draw a flat-shaded, PF_5R6G5B line into an XImage. + */ +#define NAME flat_5R6G5B_line +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + const GLubyte *color = vert1->color; \ + GLushort pixel = PACK_5R6G5B( color[0], color[1], color[2] ); +#define PIXEL_TYPE GLushort +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define PIXEL_ADDRESS(X,Y) PIXELADDR2(xmesa->xm_buffer,X,Y) +#define CLIP_HACK 1 +#define PLOT(X,Y) *pixelPtr = pixel; +#include "swrast/s_linetemp.h" + + + +/* + * Draw a flat-shaded, PF_DITHER_5R6G5B line into an XImage. + */ +#define NAME flat_DITHER_5R6G5B_line +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + const GLubyte *color = vert1->color; +#define PIXEL_TYPE GLushort +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define PIXEL_ADDRESS(X,Y) PIXELADDR2(xmesa->xm_buffer,X,Y) +#define CLIP_HACK 1 +#define PLOT(X,Y) PACK_TRUEDITHER( *pixelPtr, X, Y, color[0], color[1], color[2] ); +#include "swrast/s_linetemp.h" + + + + +/* + * Draw a flat-shaded, PF_DITHER 8-bit line into an XImage. + */ +#define NAME flat_DITHER8_line +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + const GLubyte *color = vert1->color; \ + GLint r = color[0], g = color[1], b = color[2]; \ + DITHER_SETUP; +#define PIXEL_TYPE GLubyte +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y) +#define CLIP_HACK 1 +#define PLOT(X,Y) *pixelPtr = DITHER(X,Y,r,g,b); +#include "swrast/s_linetemp.h" + + + +/* + * Draw a flat-shaded, PF_LOOKUP 8-bit line into an XImage. + */ +#define NAME flat_LOOKUP8_line +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + const GLubyte *color = vert1->color; \ + GLubyte pixel; \ + LOOKUP_SETUP; \ + pixel = (GLubyte) LOOKUP( color[0], color[1], color[2] ); +#define PIXEL_TYPE GLubyte +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y) +#define CLIP_HACK 1 +#define PLOT(X,Y) *pixelPtr = pixel; +#include "swrast/s_linetemp.h" + + + +/* + * Draw a flat-shaded, PF_HPCR line into an XImage. + */ +#define NAME flat_HPCR_line +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + const GLubyte *color = vert1->color; \ + GLint r = color[0], g = color[1], b = color[2]; +#define PIXEL_TYPE GLubyte +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y) +#define CLIP_HACK 1 +#define PLOT(X,Y) *pixelPtr = (GLubyte) DITHER_HPCR(X,Y,r,g,b); +#include "swrast/s_linetemp.h" + + + + +/* + * Draw a flat-shaded, Z-less, PF_TRUECOLOR line into an XImage. + */ +#define NAME flat_TRUECOLOR_z_line +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + const GLubyte *color = vert1->color; \ + XMesaImage *img = xmesa->xm_buffer->backimage; \ + unsigned long pixel; \ + PACK_TRUECOLOR( pixel, color[0], color[1], color[2] ); +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define CLIP_HACK 1 +#define PLOT(X,Y) \ + if (Z < *zPtr) { \ + *zPtr = Z; \ + XMesaPutPixel( img, X, FLIP(xmesa->xm_buffer, Y), pixel ); \ + } +#include "swrast/s_linetemp.h" + + + +/* + * Draw a flat-shaded, Z-less, PF_8A8B8G8R line into an XImage. + */ +#define NAME flat_8A8B8G8R_z_line +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + const GLubyte *color = vert1->color; \ + GLuint pixel = PACK_8B8G8R( color[0], color[1], color[2] ); +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define PIXEL_TYPE GLuint +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y) +#define CLIP_HACK 1 +#define PLOT(X,Y) \ + if (Z < *zPtr) { \ + *zPtr = Z; \ + *pixelPtr = pixel; \ + } +#include "swrast/s_linetemp.h" + + + +/* + * Draw a flat-shaded, Z-less, PF_8A8R8G8B line into an XImage. + */ +#define NAME flat_8A8R8G8B_z_line +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + const GLubyte *color = vert1->color; \ + GLuint pixel = PACK_8R8G8B( color[0], color[1], color[2] ); +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define PIXEL_TYPE GLuint +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y) +#define CLIP_HACK 1 +#define PLOT(X,Y) \ + if (Z < *zPtr) { \ + *zPtr = Z; \ + *pixelPtr = pixel; \ + } +#include "swrast/s_linetemp.h" + + + +/* + * Draw a flat-shaded, Z-less, PF_8R8G8B line into an XImage. + */ +#define NAME flat_8R8G8B_z_line +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + const GLubyte *color = vert1->color; \ + GLuint pixel = PACK_8R8G8B( color[0], color[1], color[2] ); +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define PIXEL_TYPE GLuint +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y) +#define CLIP_HACK 1 +#define PLOT(X,Y) \ + if (Z < *zPtr) { \ + *zPtr = Z; \ + *pixelPtr = pixel; \ + } +#include "swrast/s_linetemp.h" + + + +/* + * Draw a flat-shaded, Z-less, PF_8R8G8B24 line into an XImage. + */ +#define NAME flat_8R8G8B24_z_line +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + const GLubyte *color = vert1->color; +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define PIXEL_TYPE bgr_t +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define PIXEL_ADDRESS(X,Y) PIXELADDR3(xmesa->xm_buffer,X,Y) +#define CLIP_HACK 1 +#define PLOT(X,Y) \ + if (Z < *zPtr) { \ + *zPtr = Z; \ + pixelPtr->r = color[RCOMP]; \ + pixelPtr->g = color[GCOMP]; \ + pixelPtr->b = color[BCOMP]; \ + } +#include "swrast/s_linetemp.h" + + + +/* + * Draw a flat-shaded, Z-less, PF_5R6G5B line into an XImage. + */ +#define NAME flat_5R6G5B_z_line +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + const GLubyte *color = vert1->color; \ + GLushort pixel = PACK_5R6G5B( color[0], color[1], color[2] ); +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define PIXEL_TYPE GLushort +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define PIXEL_ADDRESS(X,Y) PIXELADDR2(xmesa->xm_buffer,X,Y) +#define CLIP_HACK 1 +#define PLOT(X,Y) \ + if (Z < *zPtr) { \ + *zPtr = Z; \ + *pixelPtr = pixel; \ + } +#include "swrast/s_linetemp.h" + + + +/* + * Draw a flat-shaded, Z-less, PF_DITHER_5R6G5B line into an XImage. + */ +#define NAME flat_DITHER_5R6G5B_z_line +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + const GLubyte *color = vert1->color; +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define PIXEL_TYPE GLushort +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define PIXEL_ADDRESS(X,Y) PIXELADDR2(xmesa->xm_buffer,X,Y) +#define CLIP_HACK 1 +#define PLOT(X,Y) \ + if (Z < *zPtr) { \ + *zPtr = Z; \ + PACK_TRUEDITHER(*pixelPtr, X, Y, color[0], color[1], color[2]); \ + } +#include "swrast/s_linetemp.h" + + + +/* + * Draw a flat-shaded, Z-less, PF_DITHER 8-bit line into an XImage. + */ +#define NAME flat_DITHER8_z_line +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + const GLubyte *color = vert1->color; \ + GLint r = color[0], g = color[1], b = color[2]; \ + DITHER_SETUP; +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define PIXEL_TYPE GLubyte +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y) +#define CLIP_HACK 1 +#define PLOT(X,Y) \ + if (Z < *zPtr) { \ + *zPtr = Z; \ + *pixelPtr = (GLubyte) DITHER( X, Y, r, g, b); \ + } +#include "swrast/s_linetemp.h" + + + +/* + * Draw a flat-shaded, Z-less, PF_LOOKUP 8-bit line into an XImage. + */ +#define NAME flat_LOOKUP8_z_line +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + const GLubyte *color = vert1->color; \ + GLubyte pixel; \ + LOOKUP_SETUP; \ + pixel = (GLubyte) LOOKUP( color[0], color[1], color[2] ); +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define PIXEL_TYPE GLubyte +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y) +#define CLIP_HACK 1 +#define PLOT(X,Y) \ + if (Z < *zPtr) { \ + *zPtr = Z; \ + *pixelPtr = pixel; \ + } +#include "swrast/s_linetemp.h" + + + +/* + * Draw a flat-shaded, Z-less, PF_HPCR line into an XImage. + */ +#define NAME flat_HPCR_z_line +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + const GLubyte *color = vert1->color; \ + GLint r = color[0], g = color[1], b = color[2]; +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define PIXEL_TYPE GLubyte +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y) +#define CLIP_HACK 1 +#define PLOT(X,Y) \ + if (Z < *zPtr) { \ + *zPtr = Z; \ + *pixelPtr = (GLubyte) DITHER_HPCR( X, Y, r, g, b); \ + } +#include "swrast/s_linetemp.h" + + + +static swrast_line_func get_line_func( GLcontext *ctx ) +{ + XMesaContext xmesa = XMESA_CONTEXT(ctx); + SWcontext *swrast = SWRAST_CONTEXT(ctx); + int depth = GET_VISUAL_DEPTH(xmesa->xm_visual); + + if ((ctx->Color._DrawDestMask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) ==0) + return (swrast_line_func) NULL; + if (ctx->RenderMode != GL_RENDER) return (swrast_line_func) NULL; + if (ctx->Line.SmoothFlag) return (swrast_line_func) NULL; + if (ctx->Texture._EnabledUnits) return (swrast_line_func) NULL; + if (ctx->Light.ShadeModel != GL_FLAT) return (swrast_line_func) NULL; + if (ctx->Line.StippleFlag) return (swrast_line_func) NULL; + if (swrast->_RasterMask & MULTI_DRAW_BIT) return (swrast_line_func) NULL; + + if (xmesa->xm_buffer->buffer==XIMAGE + && swrast->_RasterMask==DEPTH_BIT + && ctx->Depth.Func==GL_LESS + && ctx->Depth.Mask==GL_TRUE + && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS + && ctx->Line.Width==1.0F) { + switch (xmesa->pixelformat) { + case PF_Truecolor: + return flat_TRUECOLOR_z_line; + case PF_8A8B8G8R: + return flat_8A8B8G8R_z_line; + case PF_8A8R8G8B: + return flat_8A8R8G8B_z_line; + case PF_8R8G8B: + return flat_8R8G8B_z_line; + case PF_8R8G8B24: + return flat_8R8G8B24_z_line; + case PF_5R6G5B: + return flat_5R6G5B_z_line; + case PF_Dither_5R6G5B: + return flat_DITHER_5R6G5B_z_line; + case PF_Dither: + return (depth==8) ? flat_DITHER8_z_line : (swrast_line_func) NULL; + case PF_Lookup: + return (depth==8) ? flat_LOOKUP8_z_line : (swrast_line_func) NULL; + case PF_HPCR: + return flat_HPCR_z_line; + default: + return (swrast_line_func)NULL; + } + } + if (xmesa->xm_buffer->buffer==XIMAGE + && swrast->_RasterMask==0 + && ctx->Line.Width==1.0F) { + switch (xmesa->pixelformat) { + case PF_Truecolor: + return flat_TRUECOLOR_line; + case PF_8A8B8G8R: + return flat_8A8B8G8R_line; + case PF_8A8R8G8B: + return flat_8A8R8G8B_line; + case PF_8R8G8B: + return flat_8R8G8B_line; + case PF_8R8G8B24: + return flat_8R8G8B24_line; + case PF_5R6G5B: + return flat_5R6G5B_line; + case PF_Dither_5R6G5B: + return flat_DITHER_5R6G5B_line; + case PF_Dither: + return (depth==8) ? flat_DITHER8_line : (swrast_line_func) NULL; + case PF_Lookup: + return (depth==8) ? flat_LOOKUP8_line : (swrast_line_func) NULL; + case PF_HPCR: + return flat_HPCR_line; + default: + return (swrast_line_func)NULL; + } + } + + return (swrast_line_func) NULL; +} + +/* Override for the swrast line-selection function. Try to use one + * of our internal line functions, otherwise fall back to the + * standard swrast functions. + */ +void xmesa_choose_line( GLcontext *ctx ) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + + if (!(swrast->Line = get_line_func( ctx ))) + _swrast_choose_line( ctx ); +} diff --git a/src/mesa/drivers/x11/xm_span.c b/src/mesa/drivers/x11/xm_span.c new file mode 100644 index 0000000..807be39 --- /dev/null +++ b/src/mesa/drivers/x11/xm_span.c @@ -0,0 +1,4777 @@ +/* + * Mesa 3-D graphics library + * Version: 6.2.1 + * + * Copyright (C) 1999-2004 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. + */ +/* $XFree86: xc/extras/Mesa/src/X/xm_span.c,v 1.3 2002/02/27 21:07:54 tsi Exp $ */ + +#include "glxheader.h" +#include "colormac.h" +#include "context.h" +#include "depth.h" +#include "drawpix.h" +#include "extensions.h" +#include "macros.h" +#include "imports.h" +#include "mtypes.h" +#include "state.h" +#include "xmesaP.h" + +#include "swrast/swrast.h" + + +/* + * The following functions are used to trap XGetImage() calls which + * generate BadMatch errors if the drawable isn't mapped. + */ + +#ifndef XFree86Server +static int caught_xgetimage_error = 0; +static int (*old_xerror_handler)( XMesaDisplay *dpy, XErrorEvent *ev ); +static unsigned long xgetimage_serial; + +/* + * This is the error handler which will be called if XGetImage fails. + */ +static int xgetimage_error_handler( XMesaDisplay *dpy, XErrorEvent *ev ) +{ + if (ev->serial==xgetimage_serial && ev->error_code==BadMatch) { + /* caught the expected error */ + caught_xgetimage_error = 0; + } + else { + /* call the original X error handler, if any. otherwise ignore */ + if (old_xerror_handler) { + (*old_xerror_handler)( dpy, ev ); + } + } + return 0; +} + + +/* + * Call this right before XGetImage to setup error trap. + */ +static void catch_xgetimage_errors( XMesaDisplay *dpy ) +{ + xgetimage_serial = NextRequest( dpy ); + old_xerror_handler = XSetErrorHandler( xgetimage_error_handler ); + caught_xgetimage_error = 0; +} + + +/* + * Call this right after XGetImage to check if an error occured. + */ +static int check_xgetimage_errors( void ) +{ + /* restore old handler */ + (void) XSetErrorHandler( old_xerror_handler ); + /* return 0=no error, 1=error caught */ + return caught_xgetimage_error; +} +#endif + + +/* + * Read a pixel from an X drawable. + */ +static unsigned long read_pixel( XMesaDisplay *dpy, + XMesaDrawable d, int x, int y ) +{ + unsigned long p; +#ifndef XFree86Server + XMesaImage *pixel = NULL; + int error; + + catch_xgetimage_errors( dpy ); + pixel = XGetImage( dpy, d, x, y, 1, 1, AllPlanes, ZPixmap ); + error = check_xgetimage_errors(); + if (pixel && !error) { + p = XMesaGetPixel( pixel, 0, 0 ); + } + else { + p = 0; + } + if (pixel) { + XMesaDestroyImage( pixel ); + } +#else + (*dpy->GetImage)(d, x, y, 1, 1, ZPixmap, ~0L, (pointer)&p); +#endif + return p; +} + + + +/* + * The Mesa library needs to be able to draw pixels in a number of ways: + * 1. RGB vs Color Index + * 2. as horizontal spans (polygons, images) vs random locations (points, + * lines) + * 3. different color per-pixel or same color for all pixels + * + * Furthermore, the X driver needs to support rendering to 3 possible + * "buffers", usually one, but sometimes two at a time: + * 1. The front buffer as an X window + * 2. The back buffer as a Pixmap + * 3. The back buffer as an XImage + * + * Finally, if the back buffer is an XImage, we can avoid using XPutPixel and + * optimize common cases such as 24-bit and 8-bit modes. + * + * By multiplication, there's at least 48 possible combinations of the above. + * + * Below are implementations of the most commonly used combinations. They are + * accessed through function pointers which get initialized here and are used + * directly from the Mesa library. The 8 function pointers directly correspond + * to the first 3 cases listed above. + * + * + * The function naming convention is: + * + * write_[span|pixels]_[mono]_[format]_[pixmap|ximage] + * + * New functions optimized for specific cases can be added without too much + * trouble. An example might be the 24-bit TrueColor mode 8A8R8G8B which is + * found on IBM RS/6000 X servers. + */ + + + + +/**********************************************************************/ +/*** Write COLOR SPAN functions ***/ +/**********************************************************************/ + + +#define RGBA_SPAN_ARGS const GLcontext *ctx, \ + GLuint n, GLint x, GLint y, \ + CONST GLubyte rgba[][4], const GLubyte mask[] + +#define RGB_SPAN_ARGS const GLcontext *ctx, \ + GLuint n, GLint x, GLint y, \ + CONST GLubyte rgb[][3], const GLubyte mask[] + + +/* NOTE: if mask==NULL, draw all pixels */ + + +/* + * Write a span of PF_TRUECOLOR pixels to a pixmap. + */ +static void write_span_TRUECOLOR_pixmap( RGBA_SPAN_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + XMesaDisplay *dpy = xmesa->xm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer->rowimage; + for (i=0;ixm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer->rowimage; + for (i=0;ixm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer->rowimage; + for (i=0;ixm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer->rowimage; + for (i=0;ixm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer->rowimage; + register GLuint *ptr4 = (GLuint *) rowimg->data; + for (i=0;ixm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer->rowimage; + register GLuint *ptr4 = (GLuint *) rowimg->data; + for (i=0;ixm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer->rowimage; + register GLuint *ptr4 = (GLuint *) rowimg->data; + for (i=0;ixm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer->rowimage; + register GLuint *ptr4 = (GLuint *) rowimg->data; + for (i=0;ixm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer->rowimage; + register GLuint *ptr4 = (GLuint *) rowimg->data; + for (i=0;ixm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + register GLuint i; + for (i=0;ixm_buffer->rowimage; + register GLuint *ptr4 = (GLuint *) rowimg->data; + register GLuint pixel; + static const GLuint shift[4] = {0, 8, 16, 24}; + register GLuint i = 0; + int w = n; + while (w > 3) { + pixel = rgba[i][BCOMP] /* << shift[0]*/; + pixel |= rgba[i][GCOMP] << shift[1]; + pixel |= rgba[i++][RCOMP] << shift[2]; + pixel |= rgba[i][BCOMP] << shift[3]; + *ptr4++ = pixel; + + pixel = rgba[i][GCOMP] /* << shift[0]*/; + pixel |= rgba[i++][RCOMP] << shift[1]; + pixel |= rgba[i][BCOMP] << shift[2]; + pixel |= rgba[i][GCOMP] << shift[3]; + *ptr4++ = pixel; + + pixel = rgba[i++][RCOMP]/* << shift[0]*/; + pixel |= rgba[i][BCOMP] << shift[1]; + pixel |= rgba[i][GCOMP] << shift[2]; + pixel |= rgba[i++][RCOMP] << shift[3]; + *ptr4++ = pixel; + + w -= 4; + } + switch (w) { + case 3: + pixel = 0; + pixel |= rgba[i][BCOMP] /*<< shift[0]*/; + pixel |= rgba[i][GCOMP] << shift[1]; + pixel |= rgba[i++][RCOMP] << shift[2]; + pixel |= rgba[i][BCOMP] << shift[3]; + *ptr4++ = pixel; + pixel = 0; + pixel |= rgba[i][GCOMP] /*<< shift[0]*/; + pixel |= rgba[i++][RCOMP] << shift[1]; + pixel |= rgba[i][BCOMP] << shift[2]; + pixel |= rgba[i][GCOMP] << shift[3]; + *ptr4++ = pixel; + pixel = 0xffffff00 & *ptr4; + pixel |= rgba[i][RCOMP] /*<< shift[0]*/; + *ptr4 = pixel; + break; + case 2: + pixel = 0; + pixel |= rgba[i][BCOMP] /*<< shift[0]*/; + pixel |= rgba[i][GCOMP] << shift[1]; + pixel |= rgba[i++][RCOMP] << shift[2]; + pixel |= rgba[i][BCOMP] << shift[3]; + *ptr4++ = pixel; + pixel = 0xffff0000 & *ptr4; + pixel |= rgba[i][GCOMP] /*<< shift[0]*/; + pixel |= rgba[i][RCOMP] << shift[1]; + *ptr4 = pixel; + break; + case 1: + pixel = 0xff000000 & *ptr4; + pixel |= rgba[i][BCOMP] /*<< shift[0]*/; + pixel |= rgba[i][GCOMP] << shift[1]; + pixel |= rgba[i][RCOMP] << shift[2]; + *ptr4 = pixel; + break; + case 0: + break; + } + XMesaPutImage( dpy, buffer, gc, rowimg, 0, 0, x, y, n, 1 ); + } +} + + +/* + * Write a span of PF_8R8G8B pixels to a pixmap (no alpha). + */ +static void write_span_rgb_8R8G8B_pixmap( RGB_SPAN_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + XMesaDisplay *dpy = xmesa->xm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer->rowimage; + register GLuint *ptr4 = (GLuint *) rowimg->data; + for (i=0;ixm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + register GLuint i; + for (i=0;ixm_buffer->rowimage; + register GLuint *ptr4 = (GLuint *) rowimg->data; + register GLuint pixel; + static const GLuint shift[4] = {0, 8, 16, 24}; + unsigned w = n; + register GLuint i = 0; + while (w > 3) { + pixel = 0; + pixel |= rgb[i][BCOMP]/* << shift[0]*/; + pixel |= rgb[i][GCOMP] << shift[1]; + pixel |= rgb[i++][RCOMP] << shift[2]; + pixel |= rgb[i][BCOMP] <xm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer->rowimage; + register GLushort *ptr2 = (GLushort *) rowimg->data; + for (i=0;ixm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer->rowimage; + register GLushort *ptr2 = (GLushort *) rowimg->data; + for (i=0;ixm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer->rowimage; + register GLushort *ptr2 = (GLushort *) rowimg->data; + for (i=0;ixm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer->rowimage; + register GLushort *ptr2 = (GLushort *) rowimg->data; + for (i=0;ixm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + XDITHER_SETUP(y); + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer->rowimage; + for (i=0;ixm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + XDITHER_SETUP(y); + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer->rowimage; + for (i=0;ixm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + SETUP_1BIT; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer->rowimage; + for (i=0;ixm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + SETUP_1BIT; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer->rowimage; + for (i=0;ixm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer->rowimage; + register GLubyte *ptr = (GLubyte *) xmesa->xm_buffer->rowimage->data; + for (i=0;ixm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer->rowimage; + register GLubyte *ptr = (GLubyte *) xmesa->xm_buffer->rowimage->data; + for (i=0;ixm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + LOOKUP_SETUP; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer->rowimage; + for (i=0;ixm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + LOOKUP_SETUP; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer->rowimage; + for (i=0;ixm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer->rowimage; + for (i=0;ixm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer->rowimage; + for (i=0;ixm_buffer->backimage; + register GLuint i; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer->backimage; + register GLuint i; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer->backimage; + register GLuint i; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer->backimage; + register GLuint i; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer, x, y ); + if (mask) { + for (i=0;ixm_buffer, x, y ); + if (mask) { + for (i=0;ixm_buffer, x, y ); + if (mask) { + for (i=0;ixm_buffer, x, y ); + if (mask) { + for (i=0;ixm_buffer, x, y ); + if (mask) { + for (i=0;ixm_buffer, x, y ); + if (mask) { + for (i=0;i 3) { + pixel = rgba[i][BCOMP]; + pixel |= rgba[i][GCOMP] << 8; + pixel |= rgba[i++][RCOMP] << 16; + pixel |= rgba[i][BCOMP] << 24; + *ptr4++ = pixel; + pixel = rgba[i][GCOMP]; + pixel |= rgba[i++][RCOMP] << 8; + pixel |= rgba[i][BCOMP] << 16; + pixel |= rgba[i][GCOMP] << 24; + *ptr4++ = pixel; + pixel = rgba[i++][RCOMP]; + pixel |= rgba[i][BCOMP] << 8; + pixel |= rgba[i][GCOMP] << 16; + pixel |= rgba[i++][RCOMP] << 24; + *ptr4++ = pixel; + w -= 4; + } + switch (w) { + case 0: + break; + case 1: + pixel = *ptr4 & 0xff000000; + pixel |= rgba[i][BCOMP]; + pixel |= rgba[i][GCOMP] << 8; + pixel |= rgba[i][RCOMP] << 16; + *ptr4 = pixel; + break; + case 2: + pixel = rgba[i][BCOMP]; + pixel |= rgba[i][GCOMP] << 8; + pixel |= rgba[i++][RCOMP] << 16; + pixel |= rgba[i][BCOMP] << 24; + *ptr4++ = pixel; + pixel = *ptr4 & 0xffff0000; + pixel |= rgba[i][GCOMP]; + pixel |= rgba[i][RCOMP] << 8; + *ptr4 = pixel; + break; + case 3: + pixel = rgba[i][BCOMP]; + pixel |= rgba[i][GCOMP] << 8; + pixel |= rgba[i++][RCOMP] << 16; + pixel |= rgba[i][BCOMP] << 24; + *ptr4++ = pixel; + pixel = rgba[i][GCOMP]; + pixel |= rgba[i++][RCOMP] << 8; + pixel |= rgba[i][BCOMP] << 16; + pixel |= rgba[i][GCOMP] << 24; + *ptr4++ = pixel; + pixel = *ptr4 & 0xffffff00; + pixel |= rgba[i][RCOMP]; + *ptr4 = pixel; + break; + } + } +} + + +/* + * Write a span of PF_8R8G8B-format pixels to an ximage (no alpha). + */ +static void write_span_rgb_8R8G8B_ximage( RGB_SPAN_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + register GLuint i; + register GLuint *ptr = PIXELADDR4( xmesa->xm_buffer, x, y ); + if (mask) { + for (i=0;ixm_buffer, x, y ); + if (mask) { + for (i=0;ixm_buffer, x, y ); + if (mask) { + for (i=0;ixm_buffer, x, y ); + const GLint y2 = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer, x, y ); + if (mask) { + for (i=0;ixm_buffer, x, y ); + if (mask) { + for (i=0;ixm_buffer->backimage; + register GLuint i; + int yy = FLIP(xmesa->xm_buffer, y); + XDITHER_SETUP(yy); + if (mask) { + for (i=0;ixm_buffer->backimage; + register GLuint i; + int yy = FLIP(xmesa->xm_buffer, y); + XDITHER_SETUP(yy); + if (mask) { + for (i=0;ixm_buffer, x, y ); + XDITHER_SETUP(y); + if (mask) { + for (i=0;ixm_buffer, x, y ); + XDITHER_SETUP(y); + if (mask) { + for (i=0;ixm_buffer->backimage; + register GLuint i; + SETUP_1BIT; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer->backimage; + register GLuint i; + SETUP_1BIT; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer, x, y ); + if (mask) { + for (i=0;ixm_buffer, x, y ); + if (mask) { + for (i=0;ixm_buffer->backimage; + register GLuint i; + LOOKUP_SETUP; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer->backimage; + register GLuint i; + LOOKUP_SETUP; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer, x, y ); + LOOKUP_SETUP; + if (mask) { + for (i=0;ixm_buffer, x, y ); + LOOKUP_SETUP; + if (mask) { + for (i=0;ixm_buffer->backimage; + register GLuint i; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer->backimage; + register GLuint i; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer, x, y ); + if (mask) { + for (i=0;ixm_buffer, x, y ); + if (mask) { + for (i=0;ixm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + for (i=0;ixm_buffer, y[i]) ); + } + } +} + + +/* + * Write an array of PF_TRUEDITHER pixels to a pixmap. + */ +static void write_pixels_TRUEDITHER_pixmap( RGBA_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + XMesaDisplay *dpy = xmesa->xm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + for (i=0;ixm_buffer, y[i]) ); + } + } +} + + +/* + * Write an array of PF_8A8B8G8R pixels to a pixmap. + */ +static void write_pixels_8A8B8G8R_pixmap( RGBA_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + XMesaDisplay *dpy = xmesa->xm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + for (i=0;ixm_buffer, y[i]) ); + } + } +} + +/* + * Write an array of PF_8A8R8G8B pixels to a pixmap. + */ +static void write_pixels_8A8R8G8B_pixmap( RGBA_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + XMesaDisplay *dpy = xmesa->xm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + for (i=0;ixm_buffer, y[i]) ); + } + } +} + +/* + * Write an array of PF_8R8G8B pixels to a pixmap. + */ +static void write_pixels_8R8G8B_pixmap( RGBA_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + XMesaDisplay *dpy = xmesa->xm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + for (i=0;ixm_buffer, y[i]) ); + } + } +} + + +/* + * Write an array of PF_8R8G8B24 pixels to a pixmap. + */ +static void write_pixels_8R8G8B24_pixmap( RGBA_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + XMesaDisplay *dpy = xmesa->xm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + for (i=0;ixm_buffer, y[i]) ); + } + } +} + + +/* + * Write an array of PF_5R6G5B pixels to a pixmap. + */ +static void write_pixels_5R6G5B_pixmap( RGBA_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + XMesaDisplay *dpy = xmesa->xm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + for (i=0;ixm_buffer, y[i]) ); + } + } +} + + +/* + * Write an array of PF_DITHER_5R6G5B pixels to a pixmap. + */ +static void write_pixels_DITHER_5R6G5B_pixmap( RGBA_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + XMesaDisplay *dpy = xmesa->xm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + for (i=0;ixm_buffer, y[i]) ); + } + } +} + + +/* + * Write an array of PF_DITHER pixels to a pixmap. + */ +static void write_pixels_DITHER_pixmap( RGBA_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + XMesaDisplay *dpy = xmesa->xm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + DITHER_SETUP; + for (i=0;ixm_buffer, y[i]) ); + } + } +} + + +/* + * Write an array of PF_1BIT pixels to a pixmap. + */ +static void write_pixels_1BIT_pixmap( RGBA_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + XMesaDisplay *dpy = xmesa->xm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + SETUP_1BIT; + for (i=0;ixm_buffer, y[i]) ); + } + } +} + + +/* + * Write an array of PF_HPCR pixels to a pixmap. + */ +static void write_pixels_HPCR_pixmap( RGBA_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + XMesaDisplay *dpy = xmesa->xm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + for (i=0;ixm_buffer, y[i]) ); + } + } +} + + +/* + * Write an array of PF_LOOKUP pixels to a pixmap. + */ +static void write_pixels_LOOKUP_pixmap( RGBA_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + XMesaDisplay *dpy = xmesa->xm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + LOOKUP_SETUP; + for (i=0;ixm_buffer, y[i]) ); + } + } +} + + +/* + * Write an array of PF_GRAYSCALE pixels to a pixmap. + */ +static void write_pixels_GRAYSCALE_pixmap( RGBA_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + XMesaDisplay *dpy = xmesa->xm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + for (i=0;ixm_buffer, y[i]) ); + } + } +} + + +/* + * Write an array of PF_TRUECOLOR pixels to an ximage. + */ +static void write_pixels_TRUECOLOR_ximage( RGBA_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + XMesaImage *img = xmesa->xm_buffer->backimage; + register GLuint i; + for (i=0;ixm_buffer, y[i]), p ); + } + } +} + + +/* + * Write an array of PF_TRUEDITHER pixels to an XImage. + */ +static void write_pixels_TRUEDITHER_ximage( RGBA_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + XMesaImage *img = xmesa->xm_buffer->backimage; + register GLuint i; + for (i=0;ixm_buffer, y[i]), p ); + } + } +} + + +/* + * Write an array of PF_8A8B8G8R pixels to an ximage. + */ +static void write_pixels_8A8B8G8R_ximage( RGBA_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + register GLuint i; + for (i=0;ixm_buffer, x[i], y[i] ); + *ptr = PACK_8A8B8G8R( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] ); + } + } +} + +/* + * Write an array of PF_8A8R8G8B pixels to an ximage. + */ +static void write_pixels_8A8R8G8B_ximage( RGBA_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + register GLuint i; + for (i=0;ixm_buffer, x[i], y[i] ); + *ptr = PACK_8A8R8G8B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP], rgba[i][ACOMP] ); + } + } +} + + +/* + * Write an array of PF_8R8G8B pixels to an ximage. + */ +static void write_pixels_8R8G8B_ximage( RGBA_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + register GLuint i; + for (i=0;ixm_buffer, x[i], y[i] ); + *ptr = PACK_8R8G8B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ); + } + } +} + + +/* + * Write an array of PF_8R8G8B24 pixels to an ximage. + */ +static void write_pixels_8R8G8B24_ximage( RGBA_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + register GLuint i; + for (i=0;ixm_buffer, x[i], y[i] ); + ptr->r = rgba[i][RCOMP]; + ptr->g = rgba[i][GCOMP]; + ptr->b = rgba[i][BCOMP]; + } + } +} + + +/* + * Write an array of PF_5R6G5B pixels to an ximage. + */ +static void write_pixels_5R6G5B_ximage( RGBA_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + register GLuint i; + for (i=0;ixm_buffer, x[i], y[i] ); + *ptr = PACK_5R6G5B( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ); + } + } +} + + +/* + * Write an array of PF_DITHER_5R6G5B pixels to an ximage. + */ +static void write_pixels_DITHER_5R6G5B_ximage( RGBA_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + register GLuint i; + for (i=0;ixm_buffer, x[i], y[i] ); + PACK_TRUEDITHER( *ptr, x[i], y[i], rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ); + } + } +} + + +/* + * Write an array of PF_DITHER pixels to an XImage. + */ +static void write_pixels_DITHER_ximage( RGBA_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + XMesaImage *img = xmesa->xm_buffer->backimage; + register GLuint i; + DITHER_SETUP; + for (i=0;ixm_buffer, y[i]), + DITHER( x[i], y[i], rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) ); + } + } +} + + +/* + * Write an array of 8-bit PF_DITHER pixels to an XImage. + */ +static void write_pixels_DITHER8_ximage( RGBA_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + register GLuint i; + DITHER_SETUP; + for (i=0;ixm_buffer,x[i],y[i]); + *ptr = (GLubyte) DITHER( x[i], y[i], rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ); + } + } +} + + +/* + * Write an array of PF_1BIT pixels to an XImage. + */ +static void write_pixels_1BIT_ximage( RGBA_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + XMesaImage *img = xmesa->xm_buffer->backimage; + register GLuint i; + SETUP_1BIT; + for (i=0;ixm_buffer, y[i]), + DITHER_1BIT( x[i], y[i], rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] )); + } + } +} + + +/* + * Write an array of PF_HPCR pixels to an XImage. + */ +static void write_pixels_HPCR_ximage( RGBA_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + register GLuint i; + for (i=0;ixm_buffer,x[i],y[i]); + *ptr = (GLubyte) DITHER_HPCR( x[i], y[i], rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ); + } + } +} + + +/* + * Write an array of PF_LOOKUP pixels to an XImage. + */ +static void write_pixels_LOOKUP_ximage( RGBA_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + XMesaImage *img = xmesa->xm_buffer->backimage; + register GLuint i; + LOOKUP_SETUP; + for (i=0;ixm_buffer, y[i]), LOOKUP(rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP]) ); + } + } +} + + +/* + * Write an array of 8-bit PF_LOOKUP pixels to an XImage. + */ +static void write_pixels_LOOKUP8_ximage( RGBA_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + register GLuint i; + LOOKUP_SETUP; + for (i=0;ixm_buffer,x[i],y[i]); + *ptr = (GLubyte) LOOKUP( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ); + } + } +} + + +/* + * Write an array of PF_GRAYSCALE pixels to an XImage. + */ +static void write_pixels_GRAYSCALE_ximage( RGBA_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + XMesaImage *img = xmesa->xm_buffer->backimage; + register GLuint i; + for (i=0;ixm_buffer, y[i]), + GRAY_RGB( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ) ); + } + } +} + + +/* + * Write an array of 8-bit PF_GRAYSCALE pixels to an XImage. + */ +static void write_pixels_GRAYSCALE8_ximage( RGBA_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + register GLuint i; + for (i=0;ixm_buffer, x[i], y[i] ); + *ptr = (GLubyte) GRAY_RGB( rgba[i][RCOMP], rgba[i][GCOMP], rgba[i][BCOMP] ); + } + } +} + + + + +/**********************************************************************/ +/*** Write MONO COLOR SPAN functions ***/ +/**********************************************************************/ + +#define MONO_SPAN_ARGS const GLcontext *ctx, \ + GLuint n, GLint x, GLint y, const GLchan color[4], \ + const GLubyte mask[] + + +/* + * Write a span of identical pixels to a pixmap. + */ +static void write_span_mono_pixmap( MONO_SPAN_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + XMesaDisplay *dpy = xmesa->xm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + const unsigned long pixel = xmesa_color_to_pixel(xmesa, color[RCOMP], + color[GCOMP], color[BCOMP], color[ACOMP], xmesa->pixelformat); + register GLuint i; + XMesaSetForeground( xmesa->display, gc, pixel ); + y = FLIP(xmesa->xm_buffer, y); + + /* New code contributed by Jeff Epler and cleaned up by Keith + * Whitwell. + */ + for (i = 0; i < n; ) { + GLuint start = i; + + /* Identify and emit contiguous rendered pixels + */ + while (i < n && (!mask || mask[i])) + i++; + + if (start < i) + XMesaFillRectangle( dpy, buffer, gc, + (int)(x+start), (int) y, + (int)(i-start), 1); + + /* Eat up non-rendered pixels + */ + while (i < n && !mask[i]) + i++; + } +} + + + +static void write_span_mono_index_pixmap( const GLcontext *ctx, GLuint n, + GLint x, GLint y, GLuint colorIndex, + const GLubyte mask[] ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + XMesaDisplay *dpy = xmesa->xm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + XMesaSetForeground( xmesa->display, gc, colorIndex ); + y = FLIP(xmesa->xm_buffer, y); + + for (i = 0 ; i < n ;) { + GLuint start = i; + + /* Identify and emit contiguous rendered pixels + */ + while (i < n && mask[i]) + i++; + + if (start < i) + XMesaFillRectangle( dpy, buffer, gc, + (int)(x+start), (int) y, + (int)(i-start), 1); + + /* Eat up non-rendered pixels + */ + while (i < n && !mask[i]) + i++; + } +} + + + +/* + * Write a span of PF_TRUEDITHER pixels to a pixmap. + */ +static void write_span_mono_TRUEDITHER_pixmap( MONO_SPAN_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + XMesaDisplay *dpy = xmesa->xm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP]; + register GLuint i; + int yy = FLIP(xmesa->xm_buffer, y); + for (i=0;ixm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP]; + register GLuint i; + int yy = FLIP(xmesa->xm_buffer, y); + XDITHER_SETUP(yy); + for (i=0;ixm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP]; + register GLuint i; + SETUP_1BIT; + y = FLIP(xmesa->xm_buffer, y); + for (i=0;ixm_buffer->backimage; + register GLuint i; + const unsigned long pixel = xmesa_color_to_pixel(xmesa, color[RCOMP], + color[GCOMP], color[BCOMP], color[ACOMP], xmesa->pixelformat); + y = FLIP(xmesa->xm_buffer, y); + for (i=0;ixm_buffer->backimage; + register GLuint i; + y = FLIP(xmesa->xm_buffer, y); + for (i=0;ixm_buffer->backimage; + const GLint r = color[RCOMP], g = color[GCOMP], b = color[BCOMP]; + GLuint i; + y = FLIP(xmesa->xm_buffer, y); + for (i=0;ipixelformat); + ptr = PIXELADDR4( xmesa->xm_buffer, x, y ); + for (i=0;ipixelformat); + ptr = PIXELADDR4( xmesa->xm_buffer, x, y ); + for (i=0;ixm_buffer, x, y ); + GLuint i; + for (i=0;ixm_buffer, x, y ); + for (i=0;ixm_buffer->backimage; + int yy = FLIP(xmesa->xm_buffer, y); + register GLuint i; + XDITHER_SETUP(yy); + for (i=0;ixm_buffer,x,y); + register GLuint i; + XDITHER_SETUP(y); + for (i=0;ixm_buffer,x,y); + GLubyte pixel; + LOOKUP_SETUP; + pixel = LOOKUP(color[RCOMP], color[GCOMP], color[BCOMP]); + for (i=0;ixm_buffer->backimage; + register GLuint i; + SETUP_1BIT; + y = FLIP(xmesa->xm_buffer, y); + for (i=0;ixm_buffer,x,y); + register GLuint i; + for (i=0;ixm_buffer,x,y); + GLuint i; + for (i=0;ixm_buffer, x, y ); + const GLint r = color[RCOMP], g = color[GCOMP], b = color[BCOMP]; + GLuint i; + y = FLIP(xmesa->xm_buffer, y); + for (i=0;ixm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + const unsigned long pixel = xmesa_color_to_pixel(xmesa, color[RCOMP], + color[GCOMP], color[BCOMP], color[ACOMP], xmesa->pixelformat); + XMesaSetForeground( xmesa->display, gc, pixel ); + for (i=0;ixm_buffer, y[i]) ); + } + } +} + + +static void write_pixels_mono_index_pixmap(const GLcontext *ctx, + GLuint n, + const GLint x[], const GLint y[], + GLuint colorIndex, + const GLubyte mask[] ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + XMesaDisplay *dpy = xmesa->xm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + XMesaSetForeground( xmesa->display, gc, colorIndex ); + for (i=0;ixm_buffer, y[i]) ); + } + } +} + + +/* + * Write an array of PF_TRUEDITHER pixels to a pixmap. + */ +static void write_pixels_mono_TRUEDITHER_pixmap( MONO_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + XMesaDisplay *dpy = xmesa->xm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP]; + for (i=0;ixm_buffer, y[i]) ); + } + } +} + + +/* + * Write an array of PF_DITHER pixels to a pixmap. + */ +static void write_pixels_mono_DITHER_pixmap( MONO_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + XMesaDisplay *dpy = xmesa->xm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP]; + DITHER_SETUP; + for (i=0;ixm_buffer, y[i]) ); + } + } +} + + +/* + * Write an array of PF_1BIT pixels to a pixmap. + */ +static void write_pixels_mono_1BIT_pixmap( MONO_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + XMesaDisplay *dpy = xmesa->xm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP]; + SETUP_1BIT; + for (i=0;ixm_buffer, y[i]) ); + } + } +} + + +/* + * Write an array of identical pixels to an XImage. + */ +static void write_pixels_mono_ximage( MONO_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + XMesaImage *img = xmesa->xm_buffer->backimage; + register GLuint i; + const unsigned long pixel = xmesa_color_to_pixel(xmesa, color[RCOMP], + color[GCOMP], color[BCOMP], color[ACOMP], xmesa->pixelformat); + for (i=0;ixm_buffer, y[i]), pixel ); + } + } +} + + +static void write_pixels_mono_index_ximage( const GLcontext *ctx, GLuint n, + const GLint x[], const GLint y[], + GLuint colorIndex, + const GLubyte mask[] ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + XMesaImage *img = xmesa->xm_buffer->backimage; + register GLuint i; + for (i=0;ixm_buffer, y[i]), colorIndex ); + } + } +} + + +/* + * Write an array of identical TRUEDITHER pixels to an XImage. + */ +static void write_pixels_mono_TRUEDITHER_ximage( MONO_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + XMesaImage *img = xmesa->xm_buffer->backimage; + register GLuint i; + const int r = color[RCOMP], g = color[GCOMP], b = color[BCOMP]; + for (i=0;ixm_buffer, y[i]), r, g, b); + XMesaPutPixel( img, x[i], FLIP(xmesa->xm_buffer, y[i]), p ); + } + } +} + + + +/* + * Write an array of identical 8A8B8G8R pixels to an XImage + */ +static void write_pixels_mono_8A8B8G8R_ximage( MONO_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + const GLuint p = PACK_8A8B8G8R(color[RCOMP], color[GCOMP], + color[BCOMP], color[ACOMP]); + register GLuint i; + for (i=0;ixm_buffer, x[i], y[i] ); + *ptr = p; + } + } +} + +/* + * Write an array of identical 8A8R8G8B pixels to an XImage + */ +static void write_pixels_mono_8A8R8G8B_ximage( MONO_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + const GLuint p = PACK_8A8R8G8B(color[RCOMP], color[GCOMP], + color[BCOMP], color[ACOMP]); + register GLuint i; + for (i=0;ixm_buffer, x[i], y[i] ); + *ptr = p; + } + } +} + +/* + * Write an array of identical 8R8G8B pixels to an XImage. + */ +static void write_pixels_mono_8R8G8B_ximage( MONO_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + register GLuint i; + const GLuint p = PACK_8R8G8B(color[RCOMP], color[GCOMP], color[BCOMP]); + for (i=0;ixm_buffer, x[i], y[i] ); + *ptr = p; + } + } +} + + +/* + * Write an array of identical 8R8G8B pixels to an XImage. + */ +static void write_pixels_mono_8R8G8B24_ximage( MONO_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP]; + register GLuint i; + for (i=0;ixm_buffer, x[i], y[i] ); + ptr->r = r; + ptr->g = g; + ptr->b = b; + } + } +} + + +/* + * Write an array of identical PF_DITHER pixels to an XImage. + */ +static void write_pixels_mono_DITHER_ximage( MONO_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP]; + XMesaImage *img = xmesa->xm_buffer->backimage; + register GLuint i; + DITHER_SETUP; + for (i=0;ixm_buffer, y[i]), DITHER( x[i], y[i], r, g, b ) ); + } + } +} + + +/* + * Write an array of identical 8-bit PF_DITHER pixels to an XImage. + */ +static void write_pixels_mono_DITHER8_ximage( MONO_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP]; + register GLuint i; + DITHER_SETUP; + for (i=0;ixm_buffer,x[i],y[i]); + *ptr = (GLubyte) DITHER( x[i], y[i], r, g, b ); + } + } +} + + +/* + * Write an array of identical 8-bit PF_LOOKUP pixels to an XImage. + */ +static void write_pixels_mono_LOOKUP8_ximage( MONO_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + register GLuint i; + GLubyte pixel; + LOOKUP_SETUP; + pixel = LOOKUP(color[RCOMP], color[GCOMP], color[BCOMP]); + for (i=0;ixm_buffer,x[i],y[i]); + *ptr = pixel; + } + } +} + + + +/* + * Write an array of identical PF_1BIT pixels to an XImage. + */ +static void write_pixels_mono_1BIT_ximage( MONO_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP]; + XMesaImage *img = xmesa->xm_buffer->backimage; + register GLuint i; + SETUP_1BIT; + for (i=0;ixm_buffer, y[i]), + DITHER_1BIT( x[i], y[i], r, g, b )); + } + } +} + + +/* + * Write an array of identical PF_HPCR pixels to an XImage. + */ +static void write_pixels_mono_HPCR_ximage( MONO_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + const GLubyte r = color[RCOMP], g = color[GCOMP], b = color[BCOMP]; + register GLuint i; + for (i=0;ixm_buffer,x[i],y[i]); + *ptr = DITHER_HPCR( x[i], y[i], r, g, b ); + } + } +} + + +/* + * Write an array of identical 8-bit PF_GRAYSCALE pixels to an XImage. + */ +static void write_pixels_mono_GRAYSCALE8_ximage( MONO_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + register GLuint i; + register GLubyte p = GRAY_RGB(color[RCOMP], color[GCOMP], color[BCOMP]); + for (i=0;ixm_buffer,x[i],y[i]); + *ptr = p; + } + } +} + + +/* + * Write an array of identical PF_DITHER_5R6G5B pixels to an XImage. + */ +static void write_pixels_mono_DITHER_5R6G5B_ximage( MONO_PIXEL_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + const int r = color[RCOMP], g = color[GCOMP], b = color[BCOMP]; + register GLuint i; + for (i=0;ixm_buffer, x[i], y[i] ); + PACK_TRUEDITHER(*ptr, x[i], y[i], r, g, b); + } + } +} + + + +/**********************************************************************/ +/*** Write INDEX SPAN functions ***/ +/**********************************************************************/ + +#define INDEX_SPAN_ARGS const GLcontext *ctx, \ + GLuint n, GLint x, GLint y, const GLuint index[], \ + const GLubyte mask[] + +#define INDEX8_SPAN_ARGS const GLcontext *ctx, \ + GLuint n, GLint x, GLint y, const GLubyte index[], \ + const GLubyte mask[] + + +/* + * Write a span of CI pixels to a Pixmap. + */ +static void write_span_index_pixmap( INDEX_SPAN_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + XMesaDisplay *dpy = xmesa->xm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer->backimage; + register GLuint i; + y = FLIP(xmesa->xm_buffer, y); + if (mask) { + for (i=0;ixm_buffer->backimage, x+i, y, index[i]); + } + } + } + else { + GLuint i; + for (i=0;ixm_buffer->backimage, x+i, y, index[i]); + } + } +} + +/* + * Write a span of 8-bit CI pixels to an 8-bit XImage. + */ +static void write_span_index8_ximage8( INDEX8_SPAN_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + GLubyte *dst = PIXELADDR1( xmesa->xm_buffer,x,y); + if (mask) { + GLuint i; + for (i=0;ixm_visual->display; + XMesaDrawable buffer = xmesa->xm_buffer->buffer; + XMesaGC gc = xmesa->xm_buffer->gc; + register GLuint i; + for (i=0;ixm_buffer, y[i]) ); + } + } +} + + +/* + * Write an array of CI pixels to an XImage. + */ +static void write_pixels_index_ximage( INDEX_PIXELS_ARGS ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + XMesaImage *img = xmesa->xm_buffer->backimage; + register GLuint i; + for (i=0;ixm_buffer, y[i]), (unsigned long) index[i] ); + } + } +} + + + + +/**********************************************************************/ +/***** Pixel reading *****/ +/**********************************************************************/ + +#ifndef XFree86Server +/** + * Do clip testing prior to calling XGetImage. If any of the region lies + * outside the screen's bounds, XGetImage will return NULL. + * We use XTranslateCoordinates() to check if that's the case and + * adjust the x, y and length parameters accordingly. + * \return -1 if span is totally clipped away, + * else return number of pixels to skip in the destination array. + */ +static int +clip_for_xgetimage(XMesaContext xmesa, GLuint *n, GLint *x, GLint *y) +{ + XMesaBuffer source = xmesa->xm_buffer; + Window rootWin = RootWindow(xmesa->display, 0); + Window child; + int screenWidth = WidthOfScreen(DefaultScreenOfDisplay(xmesa->display)); + int dx, dy; + if (source->type == PBUFFER || source->type == PIXMAP) + return 0; + XTranslateCoordinates(xmesa->display, source->buffer, rootWin, + *x, *y, &dx, &dy, &child); + if (dx >= screenWidth) { + /* totally clipped on right */ + return -1; + } + if (dx < 0) { + /* clipped on left */ + int clip = -dx; + if (clip >= *n) + return -1; /* totally clipped on left */ + *x += clip; + *n -= clip; + dx = 0; + return clip; + } + if (dx + *n > screenWidth) { + /* clipped on right */ + int clip = dx + *n - screenWidth; + *n -= clip; + } + return 0; +} +#endif + + +/* + * Read a horizontal span of color-index pixels. + */ +static void read_index_span( const GLcontext *ctx, + GLuint n, GLint x, GLint y, GLuint index[] ) +{ + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + XMesaBuffer source = xmesa->xm_buffer; + GLuint i; + + y = FLIP(source, y); + + if (source->buffer) { +#ifndef XFree86Server + XMesaImage *span = NULL; + int error; + int k = clip_for_xgetimage(xmesa, &n, &x, &y); + if (k < 0) + return; + index += k; + + catch_xgetimage_errors( xmesa->display ); + span = XGetImage( xmesa->display, source->buffer, + x, y, n, 1, AllPlanes, ZPixmap ); + error = check_xgetimage_errors(); + if (span && !error) { + for (i=0;idisplay->GetImage)(source->buffer, + x, y, n, 1, ZPixmap, + ~0L, (pointer)index); +#endif + } + else if (source->backimage) { + XMesaImage *img = source->backimage; + for (i=0;ixm_buffer; + + if (source->buffer) { + /* Read from Pixmap or Window */ + XMesaImage *span = NULL; + int error; +#ifdef XFree86Server + span = XMesaCreateImage(xmesa->xm_visual->BitsPerPixel, n, 1, NULL); + span->data = (char *)MALLOC(span->height * span->bytes_per_line); + error = (!span->data); + (*xmesa->display->GetImage)(source->buffer, + x, FLIP(source, y), n, 1, ZPixmap, + ~0L, (pointer)span->data); +#else + int k; + y = FLIP(source, y); + k = clip_for_xgetimage(xmesa, &n, &x, &y); + if (k < 0) + return; + rgba += k; + catch_xgetimage_errors( xmesa->display ); + span = XGetImage( xmesa->display, source->buffer, + x, y, n, 1, AllPlanes, ZPixmap ); + error = check_xgetimage_errors(); +#endif + if (span && !error) { + switch (xmesa->pixelformat) { + case PF_Truecolor: + case PF_Dither_True: + { + const GLubyte *pixelToR = xmesa->xm_visual->PixelToR; + const GLubyte *pixelToG = xmesa->xm_visual->PixelToG; + const GLubyte *pixelToB = xmesa->xm_visual->PixelToB; + unsigned long rMask = GET_REDMASK(xmesa->xm_visual); + unsigned long gMask = GET_GREENMASK(xmesa->xm_visual); + unsigned long bMask = GET_BLUEMASK(xmesa->xm_visual); + GLint rShift = xmesa->xm_visual->rshift; + GLint gShift = xmesa->xm_visual->gshift; + GLint bShift = xmesa->xm_visual->bshift; + GLuint i; + for (i=0;i> rShift]; + rgba[i][GCOMP] = pixelToG[(p & gMask) >> gShift]; + rgba[i][BCOMP] = pixelToB[(p & bMask) >> bShift]; + rgba[i][ACOMP] = 255; + } + } + break; + case PF_5R6G5B: + case PF_Dither_5R6G5B: + { + const GLubyte *pixelToR = xmesa->xm_visual->PixelToR; + const GLubyte *pixelToG = xmesa->xm_visual->PixelToG; + const GLubyte *pixelToB = xmesa->xm_visual->PixelToB; + GLuint i; + for (i=0;i> 8) & 0xf8); + rgba[i][GCOMP] = ((p >> 3) & 0xfc); + rgba[i][BCOMP] = ((p << 3) & 0xff); + */ + rgba[i][RCOMP] = pixelToR[p >> 11]; + rgba[i][GCOMP] = pixelToG[(p >> 5) & 0x3f]; + rgba[i][BCOMP] = pixelToB[p & 0x1f]; + rgba[i][ACOMP] = 255; + } + } + break; + case PF_8A8B8G8R: + { + const GLuint *ptr4 = (GLuint *) span->data; + GLuint i; + for (i=0;i> 8) & 0xff); + rgba[i][BCOMP] = (GLubyte) ((p4 >> 16) & 0xff); + rgba[i][ACOMP] = (GLubyte) ((p4 >> 24) & 0xff); + } + } + break; + case PF_8A8R8G8B: + { + const GLuint *ptr4 = (GLuint *) span->data; + GLuint i; + for (i=0;i> 16) & 0xff); + rgba[i][GCOMP] = (GLubyte) ((p4 >> 8) & 0xff); + rgba[i][BCOMP] = (GLubyte) ( p4 & 0xff); + rgba[i][ACOMP] = (GLubyte) ((p4 >> 24) & 0xff); + } + } + break; + case PF_8R8G8B: + { + const GLuint *ptr4 = (GLuint *) span->data; + GLuint i; + for (i=0;i> 16) & 0xff); + rgba[i][GCOMP] = (GLubyte) ((p4 >> 8) & 0xff); + rgba[i][BCOMP] = (GLubyte) ( p4 & 0xff); + rgba[i][ACOMP] = 255; + } + } + break; + case PF_8R8G8B24: + { + const bgr_t *ptr3 = (bgr_t *) span->data; + GLuint i; + for (i=0;idata; + GLuint i; + for (i=0;ipixel_to_r; + GLubyte *gTable = source->pixel_to_g; + GLubyte *bTable = source->pixel_to_b; + if (GET_VISUAL_DEPTH(xmesa->xm_visual)==8) { + const GLubyte *ptr1 = (GLubyte *) span->data; + GLuint i; + for (i=0;ixm_visual->bitFlip; + GLuint i; + for (i=0;ibackimage) { + /* Read from XImage back buffer */ + switch (xmesa->pixelformat) { + case PF_Truecolor: + case PF_Dither_True: + { + const GLubyte *pixelToR = xmesa->xm_visual->PixelToR; + const GLubyte *pixelToG = xmesa->xm_visual->PixelToG; + const GLubyte *pixelToB = xmesa->xm_visual->PixelToB; + unsigned long rMask = GET_REDMASK(xmesa->xm_visual); + unsigned long gMask = GET_GREENMASK(xmesa->xm_visual); + unsigned long bMask = GET_BLUEMASK(xmesa->xm_visual); + GLint rShift = xmesa->xm_visual->rshift; + GLint gShift = xmesa->xm_visual->gshift; + GLint bShift = xmesa->xm_visual->bshift; + XMesaImage *img = source->backimage; + GLuint i; + y = FLIP(source, y); + for (i=0;i> rShift]; + rgba[i][GCOMP] = pixelToG[(p & gMask) >> gShift]; + rgba[i][BCOMP] = pixelToB[(p & bMask) >> bShift]; + rgba[i][ACOMP] = 255; + } + } + break; + case PF_5R6G5B: + case PF_Dither_5R6G5B: + { + const GLubyte *pixelToR = xmesa->xm_visual->PixelToR; + const GLubyte *pixelToG = xmesa->xm_visual->PixelToG; + const GLubyte *pixelToB = xmesa->xm_visual->PixelToB; + const GLushort *ptr2 = PIXELADDR2( source, x, y ); + GLuint i; +#if defined(__i386__) /* word stores don't have to be on 4-byte boundaries */ + const GLuint *ptr4 = (const GLuint *) ptr2; + GLuint extraPixel = (n & 1); + n -= extraPixel; + for (i = 0; i < n; i += 2) { + const GLuint p = *ptr4++; + const GLuint p0 = p & 0xffff; + const GLuint p1 = p >> 16; + /* fast, but not quite accurate + rgba[i][RCOMP] = ((p >> 8) & 0xf8); + rgba[i][GCOMP] = ((p >> 3) & 0xfc); + rgba[i][BCOMP] = ((p << 3) & 0xff); + */ + rgba[i][RCOMP] = pixelToR[p0 >> 11]; + rgba[i][GCOMP] = pixelToG[(p0 >> 5) & 0x3f]; + rgba[i][BCOMP] = pixelToB[p0 & 0x1f]; + rgba[i][ACOMP] = 255; + rgba[i+1][RCOMP] = pixelToR[p1 >> 11]; + rgba[i+1][GCOMP] = pixelToG[(p1 >> 5) & 0x3f]; + rgba[i+1][BCOMP] = pixelToB[p1 & 0x1f]; + rgba[i+1][ACOMP] = 255; + } + if (extraPixel) { + GLushort p = ptr2[n]; + rgba[n][RCOMP] = pixelToR[p >> 11]; + rgba[n][GCOMP] = pixelToG[(p >> 5) & 0x3f]; + rgba[n][BCOMP] = pixelToB[p & 0x1f]; + rgba[n][ACOMP] = 255; + } +#else + for (i = 0; i < n; i++) { + const GLushort p = ptr2[i]; + rgba[i][RCOMP] = pixelToR[p >> 11]; + rgba[i][GCOMP] = pixelToG[(p >> 5) & 0x3f]; + rgba[i][BCOMP] = pixelToB[p & 0x1f]; + rgba[i][ACOMP] = 255; + } +#endif + } + break; + case PF_8A8B8G8R: + { + const GLuint *ptr4 = PIXELADDR4( source, x, y ); + GLuint i; + for (i=0;i> 8) & 0xff); + rgba[i][BCOMP] = (GLubyte) ((p4 >> 16) & 0xff); + rgba[i][ACOMP] = (GLint) ((p4 >> 24) & 0xff); + } + } + break; + case PF_8A8R8G8B: + { + const GLuint *ptr4 = PIXELADDR4( source, x, y ); + GLuint i; + for (i=0;i> 16) & 0xff); + rgba[i][GCOMP] = (GLubyte) ((p4 >> 8) & 0xff); + rgba[i][BCOMP] = (GLubyte) ( p4 & 0xff); + rgba[i][ACOMP] = (GLint) ((p4 >> 24) & 0xff); + } + } + break; + case PF_8R8G8B: + { + const GLuint *ptr4 = PIXELADDR4( source, x, y ); + GLuint i; + for (i=0;i> 16) & 0xff); + rgba[i][GCOMP] = (GLubyte) ((p4 >> 8) & 0xff); + rgba[i][BCOMP] = (GLubyte) ( p4 & 0xff); + rgba[i][ACOMP] = 255; + } + } + break; + case PF_8R8G8B24: + { + const bgr_t *ptr3 = PIXELADDR3( source, x, y ); + GLuint i; + for (i=0;ipixel_to_r; + const GLubyte *gTable = source->pixel_to_g; + const GLubyte *bTable = source->pixel_to_b; + if (GET_VISUAL_DEPTH(xmesa->xm_visual)==8) { + GLubyte *ptr1 = PIXELADDR1( source, x, y ); + GLuint i; + for (i=0;ibackimage; + GLuint i; + y = FLIP(source, y); + for (i=0;ibackimage; + int bitFlip = xmesa->xm_visual->bitFlip; + GLuint i; + y = FLIP(source, y); + for (i=0;ixm_buffer; + + if (source->buffer) { + for (i=0;idisplay, + source->buffer, + x[i], FLIP(source, y[i]) ); + } + } + } + else if (source->backimage) { + XMesaImage *img = source->backimage; + for (i=0;ixm_visual->display; + register GLuint i; + XMesaBuffer source = xmesa->xm_buffer; + XMesaDrawable buffer = source->buffer; /* the X drawable */ + + if (source->buffer) { + switch (xmesa->pixelformat) { + case PF_Truecolor: + case PF_Dither_True: + case PF_5R6G5B: + case PF_Dither_5R6G5B: + { + unsigned long rMask = GET_REDMASK(xmesa->xm_visual); + unsigned long gMask = GET_GREENMASK(xmesa->xm_visual); + unsigned long bMask = GET_BLUEMASK(xmesa->xm_visual); + GLubyte *pixelToR = xmesa->xm_visual->PixelToR; + GLubyte *pixelToG = xmesa->xm_visual->PixelToG; + GLubyte *pixelToB = xmesa->xm_visual->PixelToB; + GLint rShift = xmesa->xm_visual->rshift; + GLint gShift = xmesa->xm_visual->gshift; + GLint bShift = xmesa->xm_visual->bshift; + for (i=0;i> rShift]; + rgba[i][GCOMP] = pixelToG[(p & gMask) >> gShift]; + rgba[i][BCOMP] = pixelToB[(p & bMask) >> bShift]; + rgba[i][ACOMP] = 255; + } + } + } + break; + case PF_8A8B8G8R: + for (i=0;i> 8) & 0xff); + rgba[i][BCOMP] = (GLubyte) ((p >> 16) & 0xff); + rgba[i][ACOMP] = (GLubyte) ((p >> 24) & 0xff); + } + } + break; + case PF_8A8R8G8B: + for (i=0;i> 16) & 0xff); + rgba[i][GCOMP] = (GLubyte) ((p >> 8) & 0xff); + rgba[i][BCOMP] = (GLubyte) ( p & 0xff); + rgba[i][ACOMP] = (GLubyte) ((p >> 24) & 0xff); + } + } + break; + case PF_8R8G8B: + for (i=0;i> 16) & 0xff); + rgba[i][GCOMP] = (GLubyte) ((p >> 8) & 0xff); + rgba[i][BCOMP] = (GLubyte) ( p & 0xff); + rgba[i][ACOMP] = 255; + } + } + break; + case PF_8R8G8B24: + for (i=0;i> 16) & 0xff); + rgba[i][GCOMP] = (GLubyte) ((p >> 8) & 0xff); + rgba[i][BCOMP] = (GLubyte) ( p & 0xff); + rgba[i][ACOMP] = 255; + } + } + break; + case PF_HPCR: + { + for (i=0;ipixel_to_r; + GLubyte *gTable = source->pixel_to_g; + GLubyte *bTable = source->pixel_to_b; + for (i=0;ixm_visual->bitFlip; + for (i=0;ibackimage) { + switch (xmesa->pixelformat) { + case PF_Truecolor: + case PF_Dither_True: + case PF_5R6G5B: + case PF_Dither_5R6G5B: + { + unsigned long rMask = GET_REDMASK(xmesa->xm_visual); + unsigned long gMask = GET_GREENMASK(xmesa->xm_visual); + unsigned long bMask = GET_BLUEMASK(xmesa->xm_visual); + GLubyte *pixelToR = xmesa->xm_visual->PixelToR; + GLubyte *pixelToG = xmesa->xm_visual->PixelToG; + GLubyte *pixelToB = xmesa->xm_visual->PixelToB; + GLint rShift = xmesa->xm_visual->rshift; + GLint gShift = xmesa->xm_visual->gshift; + GLint bShift = xmesa->xm_visual->bshift; + XMesaImage *img = source->backimage; + for (i=0;i> rShift]; + rgba[i][GCOMP] = pixelToG[(p & gMask) >> gShift]; + rgba[i][BCOMP] = pixelToB[(p & bMask) >> bShift]; + rgba[i][ACOMP] = 255; + } + } + } + break; + case PF_8A8B8G8R: + for (i=0;i> 8) & 0xff); + rgba[i][BCOMP] = (GLubyte) ((p4 >> 16) & 0xff); + rgba[i][ACOMP] = (GLubyte) ((p4 >> 24) & 0xff); + } + } + break; + case PF_8A8R8G8B: + for (i=0;i> 16) & 0xff); + rgba[i][GCOMP] = (GLubyte) ((p4 >> 8) & 0xff); + rgba[i][BCOMP] = (GLubyte) ( p4 & 0xff); + rgba[i][ACOMP] = (GLubyte) ((p4 >> 24) & 0xff); + } + } + break; + case PF_8R8G8B: + for (i=0;i> 16) & 0xff); + rgba[i][GCOMP] = (GLubyte) ((p4 >> 8) & 0xff); + rgba[i][BCOMP] = (GLubyte) ( p4 & 0xff); + rgba[i][ACOMP] = 255; + } + } + break; + case PF_8R8G8B24: + for (i=0;ir; + rgba[i][GCOMP] = ptr3->g; + rgba[i][BCOMP] = ptr3->b; + rgba[i][ACOMP] = 255; + } + } + break; + case PF_HPCR: + for (i=0;ipixel_to_r; + GLubyte *gTable = source->pixel_to_g; + GLubyte *bTable = source->pixel_to_b; + XMesaImage *img = source->backimage; + for (i=0;ibackimage; + int bitFlip = xmesa->xm_visual->bitFlip; + for (i=0;iclearcolor[0], color[0]); + CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[1], color[1]); + CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[2], color[2]); + CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[3], color[3]); + + if (color[0] == 0.0 && color[1] == 0.0 && color[2] == 0.0) { + /* black is black */ + MEMSET( xmesa->xm_visual->hpcr_clear_ximage_pattern, 0x0 , + sizeof(xmesa->xm_visual->hpcr_clear_ximage_pattern)); + } + else { + /* build clear pattern */ + for (i=0; i<16; i++) { + xmesa->xm_visual->hpcr_clear_ximage_pattern[0][i] = + DITHER_HPCR(i, 0, + xmesa->clearcolor[0], + xmesa->clearcolor[1], + xmesa->clearcolor[2]); + xmesa->xm_visual->hpcr_clear_ximage_pattern[1][i] = + DITHER_HPCR(i, 1, + xmesa->clearcolor[0], + xmesa->clearcolor[1], + xmesa->clearcolor[2]); + } + } +} + + +static void +clear_color_HPCR_pixmap( GLcontext *ctx, const GLfloat color[4] ) +{ + int i; + const XMesaContext xmesa = XMESA_CONTEXT(ctx); + + CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[0], color[0]); + CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[1], color[1]); + CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[2], color[2]); + CLAMPED_FLOAT_TO_UBYTE(xmesa->clearcolor[3], color[3]); + + if (color[0] == 0.0 && color[1] == 0.0 && color[2] == 0.0) { + /* black is black */ + for (i=0; i<16; i++) { + XMesaPutPixel(xmesa->xm_visual->hpcr_clear_ximage, i, 0, 0); + XMesaPutPixel(xmesa->xm_visual->hpcr_clear_ximage, i, 1, 0); + } + } + else { + for (i=0; i<16; i++) { + XMesaPutPixel(xmesa->xm_visual->hpcr_clear_ximage, i, 0, + DITHER_HPCR(i, 0, + xmesa->clearcolor[0], + xmesa->clearcolor[1], + xmesa->clearcolor[2])); + XMesaPutPixel(xmesa->xm_visual->hpcr_clear_ximage, i, 1, + DITHER_HPCR(i, 1, + xmesa->clearcolor[0], + xmesa->clearcolor[1], + xmesa->clearcolor[2])); + } + } + /* change tile pixmap content */ + XMesaPutImage(xmesa->display, + (XMesaDrawable)xmesa->xm_visual->hpcr_clear_pixmap, + xmesa->xm_buffer->cleargc, + xmesa->xm_visual->hpcr_clear_ximage, 0, 0, 0, 0, 16, 2); +} + + + +void xmesa_update_span_funcs( GLcontext *ctx ) +{ + XMesaContext xmesa = XMESA_CONTEXT(ctx); + int depth=GET_VISUAL_DEPTH(xmesa->xm_visual); + struct swrast_device_driver *dd = _swrast_GetDeviceDriverReference( ctx ); + + /* + * These drawing functions depend on color buffer config: + */ + if (xmesa->xm_buffer->buffer!=XIMAGE) { + /* Writing to window or back pixmap */ + switch (xmesa->pixelformat) { + case PF_Index: + dd->WriteCI32Span = write_span_index_pixmap; + dd->WriteCI8Span = write_span_index8_pixmap; + dd->WriteMonoCISpan = write_span_mono_index_pixmap; + dd->WriteCI32Pixels = write_pixels_index_pixmap; + dd->WriteMonoCIPixels = write_pixels_mono_index_pixmap; + break; + case PF_Truecolor: + dd->WriteRGBASpan = write_span_TRUECOLOR_pixmap; + dd->WriteRGBSpan = write_span_rgb_TRUECOLOR_pixmap; + dd->WriteMonoRGBASpan = write_span_mono_pixmap; + dd->WriteRGBAPixels = write_pixels_TRUECOLOR_pixmap; + dd->WriteMonoRGBAPixels = write_pixels_mono_pixmap; + break; + case PF_Dither_True: + dd->WriteRGBASpan = write_span_TRUEDITHER_pixmap; + dd->WriteRGBSpan = write_span_rgb_TRUEDITHER_pixmap; + dd->WriteMonoRGBASpan = write_span_mono_TRUEDITHER_pixmap; + dd->WriteRGBAPixels = write_pixels_TRUEDITHER_pixmap; + dd->WriteMonoRGBAPixels = write_pixels_mono_TRUEDITHER_pixmap; + break; + case PF_8A8B8G8R: + dd->WriteRGBASpan = write_span_8A8B8G8R_pixmap; + dd->WriteRGBSpan = write_span_rgb_8A8B8G8R_pixmap; + dd->WriteMonoRGBASpan = write_span_mono_pixmap; + dd->WriteRGBAPixels = write_pixels_8A8B8G8R_pixmap; + dd->WriteMonoRGBAPixels = write_pixels_mono_pixmap; + break; + case PF_8A8R8G8B: + dd->WriteRGBASpan = write_span_8A8R8G8B_pixmap; + dd->WriteRGBSpan = write_span_rgb_8A8R8G8B_pixmap; + dd->WriteMonoRGBASpan = write_span_mono_pixmap; + dd->WriteRGBAPixels = write_pixels_8A8R8G8B_pixmap; + dd->WriteMonoRGBAPixels = write_pixels_mono_pixmap; + break; + case PF_8R8G8B: + dd->WriteRGBASpan = write_span_8R8G8B_pixmap; + dd->WriteRGBSpan = write_span_rgb_8R8G8B_pixmap; + dd->WriteMonoRGBASpan = write_span_mono_pixmap; + dd->WriteRGBAPixels = write_pixels_8R8G8B_pixmap; + dd->WriteMonoRGBAPixels = write_pixels_mono_pixmap; + break; + case PF_8R8G8B24: + dd->WriteRGBASpan = write_span_8R8G8B24_pixmap; + dd->WriteRGBSpan = write_span_rgb_8R8G8B24_pixmap; + dd->WriteMonoRGBASpan = write_span_mono_pixmap; + dd->WriteRGBAPixels = write_pixels_8R8G8B24_pixmap; + dd->WriteMonoRGBAPixels = write_pixels_mono_pixmap; + break; + case PF_5R6G5B: + dd->WriteRGBASpan = write_span_5R6G5B_pixmap; + dd->WriteRGBSpan = write_span_rgb_5R6G5B_pixmap; + dd->WriteMonoRGBASpan = write_span_mono_pixmap; + dd->WriteRGBAPixels = write_pixels_5R6G5B_pixmap; + dd->WriteMonoRGBAPixels = write_pixels_mono_pixmap; + break; + case PF_Dither_5R6G5B: + dd->WriteRGBASpan = write_span_DITHER_5R6G5B_pixmap; + dd->WriteRGBSpan = write_span_rgb_DITHER_5R6G5B_pixmap; + dd->WriteMonoRGBASpan = write_span_mono_TRUEDITHER_pixmap; + dd->WriteRGBAPixels = write_pixels_DITHER_5R6G5B_pixmap; + dd->WriteMonoRGBAPixels = write_pixels_mono_TRUEDITHER_pixmap; + break; + case PF_Dither: + dd->WriteRGBASpan = write_span_DITHER_pixmap; + dd->WriteRGBSpan = write_span_rgb_DITHER_pixmap; + dd->WriteMonoRGBASpan = write_span_mono_DITHER_pixmap; + dd->WriteRGBAPixels = write_pixels_DITHER_pixmap; + dd->WriteMonoRGBAPixels = write_pixels_mono_DITHER_pixmap; + break; + case PF_1Bit: + dd->WriteRGBASpan = write_span_1BIT_pixmap; + dd->WriteRGBSpan = write_span_rgb_1BIT_pixmap; + dd->WriteMonoRGBASpan = write_span_mono_1BIT_pixmap; + dd->WriteRGBAPixels = write_pixels_1BIT_pixmap; + dd->WriteMonoRGBAPixels = write_pixels_mono_1BIT_pixmap; + break; + case PF_HPCR: + dd->WriteRGBASpan = write_span_HPCR_pixmap; + dd->WriteRGBSpan = write_span_rgb_HPCR_pixmap; + dd->WriteMonoRGBASpan = write_span_mono_pixmap; + dd->WriteRGBAPixels = write_pixels_HPCR_pixmap; + dd->WriteMonoRGBAPixels = write_pixels_mono_pixmap; + if (xmesa->xm_visual->hpcr_clear_flag) { + ctx->Driver.ClearColor = clear_color_HPCR_pixmap; + } + break; + case PF_Lookup: + dd->WriteRGBASpan = write_span_LOOKUP_pixmap; + dd->WriteRGBSpan = write_span_rgb_LOOKUP_pixmap; + dd->WriteMonoRGBASpan = write_span_mono_pixmap; + dd->WriteRGBAPixels = write_pixels_LOOKUP_pixmap; + dd->WriteMonoRGBAPixels = write_pixels_mono_pixmap; + break; + case PF_Grayscale: + dd->WriteRGBASpan = write_span_GRAYSCALE_pixmap; + dd->WriteRGBSpan = write_span_rgb_GRAYSCALE_pixmap; + dd->WriteMonoRGBASpan = write_span_mono_pixmap; + dd->WriteRGBAPixels = write_pixels_GRAYSCALE_pixmap; + dd->WriteMonoRGBAPixels = write_pixels_mono_pixmap; + break; + default: + _mesa_problem(NULL,"Bad pixel format in xmesa_update_state (1)"); + return; + } + } + else if (xmesa->xm_buffer->buffer==XIMAGE) { + /* Writing to back XImage */ + switch (xmesa->pixelformat) { + case PF_Index: + dd->WriteCI32Span = write_span_index_ximage; + if (depth==8) + dd->WriteCI8Span = write_span_index8_ximage8; + else + dd->WriteCI8Span = write_span_index8_ximage; + dd->WriteMonoCISpan = write_span_mono_index_ximage; + dd->WriteCI32Pixels = write_pixels_index_ximage; + dd->WriteMonoCIPixels = write_pixels_mono_index_ximage; + break; + case PF_Truecolor: + /* Generic RGB */ + dd->WriteRGBASpan = write_span_TRUECOLOR_ximage; + dd->WriteRGBSpan = write_span_rgb_TRUECOLOR_ximage; + dd->WriteMonoRGBASpan = write_span_mono_ximage; + dd->WriteRGBAPixels = write_pixels_TRUECOLOR_ximage; + dd->WriteMonoRGBAPixels = write_pixels_mono_ximage; + break; + case PF_Dither_True: + dd->WriteRGBASpan = write_span_TRUEDITHER_ximage; + dd->WriteRGBSpan = write_span_rgb_TRUEDITHER_ximage; + dd->WriteMonoRGBASpan = write_span_mono_TRUEDITHER_ximage; + dd->WriteRGBAPixels = write_pixels_TRUEDITHER_ximage; + dd->WriteMonoRGBAPixels = write_pixels_mono_TRUEDITHER_ximage; + break; + case PF_8A8B8G8R: + dd->WriteRGBASpan = write_span_8A8B8G8R_ximage; + dd->WriteRGBSpan = write_span_rgb_8A8B8G8R_ximage; + dd->WriteMonoRGBASpan = write_span_mono_8A8B8G8R_ximage; + dd->WriteRGBAPixels = write_pixels_8A8B8G8R_ximage; + dd->WriteMonoRGBAPixels = write_pixels_mono_8A8B8G8R_ximage; + break; + case PF_8A8R8G8B: + dd->WriteRGBASpan = write_span_8A8R8G8B_ximage; + dd->WriteRGBSpan = write_span_rgb_8A8R8G8B_ximage; + dd->WriteMonoRGBASpan = write_span_mono_8A8R8G8B_ximage; + dd->WriteRGBAPixels = write_pixels_8A8R8G8B_ximage; + dd->WriteMonoRGBAPixels = write_pixels_mono_8A8R8G8B_ximage; + break; + case PF_8R8G8B: + dd->WriteRGBASpan = write_span_8R8G8B_ximage; + dd->WriteRGBSpan = write_span_rgb_8R8G8B_ximage; + dd->WriteMonoRGBASpan = write_span_mono_8R8G8B_ximage; + dd->WriteRGBAPixels = write_pixels_8R8G8B_ximage; + dd->WriteMonoRGBAPixels = write_pixels_mono_8R8G8B_ximage; + break; + case PF_8R8G8B24: + dd->WriteRGBASpan = write_span_8R8G8B24_ximage; + dd->WriteRGBSpan = write_span_rgb_8R8G8B24_ximage; + dd->WriteMonoRGBASpan = write_span_mono_8R8G8B24_ximage; + dd->WriteRGBAPixels = write_pixels_8R8G8B24_ximage; + dd->WriteMonoRGBAPixels = write_pixels_mono_8R8G8B24_ximage; + break; + case PF_5R6G5B: + dd->WriteRGBASpan = write_span_5R6G5B_ximage; + dd->WriteRGBSpan = write_span_rgb_5R6G5B_ximage; + dd->WriteMonoRGBASpan = write_span_mono_ximage; + dd->WriteRGBAPixels = write_pixels_5R6G5B_ximage; + dd->WriteMonoRGBAPixels = write_pixels_mono_ximage; + break; + case PF_Dither_5R6G5B: + dd->WriteRGBASpan = write_span_DITHER_5R6G5B_ximage; + dd->WriteRGBSpan = write_span_rgb_DITHER_5R6G5B_ximage; + dd->WriteMonoRGBASpan = write_span_mono_DITHER_5R6G5B_ximage; + dd->WriteRGBAPixels = write_pixels_DITHER_5R6G5B_ximage; + dd->WriteMonoRGBAPixels = write_pixels_mono_DITHER_5R6G5B_ximage; + break; + case PF_Dither: + if (depth==8) { + dd->WriteRGBASpan = write_span_DITHER8_ximage; + dd->WriteRGBSpan = write_span_rgb_DITHER8_ximage; + dd->WriteMonoRGBASpan = write_span_mono_DITHER8_ximage; + dd->WriteRGBAPixels = write_pixels_DITHER8_ximage; + dd->WriteMonoRGBAPixels = write_pixels_mono_DITHER8_ximage; + } + else { + dd->WriteRGBASpan = write_span_DITHER_ximage; + dd->WriteRGBSpan = write_span_rgb_DITHER_ximage; + dd->WriteMonoRGBASpan = write_span_mono_DITHER_ximage; + dd->WriteRGBAPixels = write_pixels_DITHER_ximage; + dd->WriteMonoRGBAPixels = write_pixels_mono_DITHER_ximage; + } + break; + case PF_1Bit: + dd->WriteRGBASpan = write_span_1BIT_ximage; + dd->WriteRGBSpan = write_span_rgb_1BIT_ximage; + dd->WriteMonoRGBASpan = write_span_mono_1BIT_ximage; + dd->WriteRGBAPixels = write_pixels_1BIT_ximage; + dd->WriteMonoRGBAPixels = write_pixels_mono_1BIT_ximage; + break; + case PF_HPCR: + dd->WriteRGBASpan = write_span_HPCR_ximage; + dd->WriteRGBSpan = write_span_rgb_HPCR_ximage; + dd->WriteMonoRGBASpan = write_span_mono_HPCR_ximage; + dd->WriteRGBAPixels = write_pixels_HPCR_ximage; + dd->WriteMonoRGBAPixels = write_pixels_mono_HPCR_ximage; + if (xmesa->xm_visual->hpcr_clear_flag) { + ctx->Driver.ClearColor = clear_color_HPCR_ximage; + } + break; + case PF_Lookup: + if (depth==8) { + dd->WriteRGBASpan = write_span_LOOKUP8_ximage; + dd->WriteRGBSpan = write_rgb_LOOKUP8_ximage; + dd->WriteMonoRGBASpan = write_span_mono_LOOKUP8_ximage; + dd->WriteRGBAPixels = write_pixels_LOOKUP8_ximage; + dd->WriteMonoRGBAPixels = write_pixels_mono_LOOKUP8_ximage; + } + else { + dd->WriteRGBASpan = write_span_LOOKUP_ximage; + dd->WriteRGBSpan = write_span_rgb_LOOKUP_ximage; + dd->WriteMonoRGBASpan = write_span_mono_ximage; + dd->WriteRGBAPixels = write_pixels_LOOKUP_ximage; + dd->WriteMonoRGBAPixels = write_pixels_mono_ximage; + } + break; + case PF_Grayscale: + if (depth==8) { + dd->WriteRGBASpan = write_span_GRAYSCALE8_ximage; + dd->WriteRGBSpan = write_span_rgb_GRAYSCALE8_ximage; + dd->WriteMonoRGBASpan = write_span_mono_GRAYSCALE8_ximage; + dd->WriteRGBAPixels = write_pixels_GRAYSCALE8_ximage; + dd->WriteMonoRGBAPixels = write_pixels_mono_GRAYSCALE8_ximage; + } + else { + dd->WriteRGBASpan = write_span_GRAYSCALE_ximage; + dd->WriteRGBSpan = write_span_rgb_GRAYSCALE_ximage; + dd->WriteMonoRGBASpan = write_span_mono_ximage; + dd->WriteRGBAPixels = write_pixels_GRAYSCALE_ximage; + dd->WriteMonoRGBAPixels = write_pixels_mono_ximage; + } + break; + default: + _mesa_problem(NULL,"Bad pixel format in xmesa_update_state (2)"); + return; + } + } + + /* Pixel/span reading functions: */ + dd->ReadCI32Span = read_index_span; + dd->ReadRGBASpan = read_color_span; + dd->ReadCI32Pixels = read_index_pixels; + dd->ReadRGBAPixels = read_color_pixels; +} diff --git a/src/mesa/drivers/x11/xm_tri.c b/src/mesa/drivers/x11/xm_tri.c new file mode 100644 index 0000000..9a71f91 --- /dev/null +++ b/src/mesa/drivers/x11/xm_tri.c @@ -0,0 +1,1609 @@ + +/* + * Mesa 3-D graphics library + * Version: 5.1 + * + * Copyright (C) 1999-2002 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. + */ + + +/* + * This file contains "accelerated" triangle functions. It should be + * fairly easy to write new special-purpose triangle functions and hook + * them into this module. + */ + + +#include "glxheader.h" +#include "depth.h" +#include "macros.h" +#include "imports.h" +#include "mtypes.h" +#include "xmesaP.h" + +/* Internal swrast includes: + */ +#include "swrast/s_context.h" +#include "swrast/s_depth.h" +#include "swrast/s_triangle.h" + + + +/**********************************************************************/ +/*** Triangle rendering ***/ +/**********************************************************************/ + + +/* + * XImage, smooth, depth-buffered, PF_TRUECOLOR triangle. + */ +#define NAME smooth_TRUECOLOR_z_triangle +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define INTERP_RGB 1 +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + XMesaImage *img = xmesa->xm_buffer->backimage; + +#define RENDER_SPAN( span ) \ + GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \ + GLuint i; \ + for (i = 0; i < span.end; i++, x++) { \ + const DEPTH_TYPE z = FixedToDepth(span.z); \ + if (z < zRow[i]) { \ + unsigned long p; \ + PACK_TRUECOLOR(p, FixedToInt(span.red), \ + FixedToInt(span.green), FixedToInt(span.blue)); \ + XMesaPutPixel(img, x, y, p); \ + zRow[i] = z; \ + } \ + span.red += span.redStep; \ + span.green += span.greenStep; \ + span.blue += span.blueStep; \ + span.z += span.zStep; \ + } + +#include "swrast/s_tritemp.h" + + + + +/* + * XImage, smooth, depth-buffered, PF_8A8B8G8R triangle. + */ +#define NAME smooth_8A8B8G8R_z_triangle +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define INTERP_RGB 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE GLuint +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + +#define RENDER_SPAN( span ) \ + GLuint i; \ + for (i = 0; i < span.end; i++) { \ + const DEPTH_TYPE z = FixedToDepth(span.z); \ + if (z < zRow[i]) { \ + pRow[i] = PACK_8B8G8R(FixedToInt(span.red), \ + FixedToInt(span.green), FixedToInt(span.blue)); \ + zRow[i] = z; \ + } \ + span.red += span.redStep; \ + span.green += span.greenStep; \ + span.blue += span.blueStep; \ + span.z += span.zStep; \ + } + +#include "swrast/s_tritemp.h" + + + +/* + * XImage, smooth, depth-buffered, PF_8A8R8G8B triangle. + */ +#define NAME smooth_8A8R8G8B_z_triangle +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define INTERP_RGB 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE GLuint +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + +#define RENDER_SPAN( span ) \ + GLuint i; \ + for (i = 0; i < span.end; i++) { \ + const DEPTH_TYPE z = FixedToDepth(span.z); \ + if (z < zRow[i]) { \ + pRow[i] = PACK_8R8G8B(FixedToInt(span.red), \ + FixedToInt(span.green), FixedToInt(span.blue)); \ + zRow[i] = z; \ + } \ + span.red += span.redStep; \ + span.green += span.greenStep; \ + span.blue += span.blueStep; \ + span.z += span.zStep; \ + } + +#include "swrast/s_tritemp.h" + + + +/* + * XImage, smooth, depth-buffered, PF_8R8G8B triangle. + */ +#define NAME smooth_8R8G8B_z_triangle +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define INTERP_RGB 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE GLuint +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + +#define RENDER_SPAN( span ) \ + GLuint i; \ + for (i = 0; i < span.end; i++) { \ + const DEPTH_TYPE z = FixedToDepth(span.z); \ + if (z < zRow[i]) { \ + pRow[i] = PACK_8R8G8B(FixedToInt(span.red), \ + FixedToInt(span.green), FixedToInt(span.blue)); \ + zRow[i] = z; \ + } \ + span.red += span.redStep; \ + span.green += span.greenStep; \ + span.blue += span.blueStep; \ + span.z += span.zStep; \ + } + +#include "swrast/s_tritemp.h" + + + +/* + * XImage, smooth, depth-buffered, PF_8R8G8B24 triangle. + */ +#define NAME smooth_8R8G8B24_z_triangle +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define INTERP_RGB 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR3(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE bgr_t +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); +#define RENDER_SPAN( span ) \ + GLuint i; \ + for (i = 0; i < span.end; i++) { \ + const DEPTH_TYPE z = FixedToDepth(span.z); \ + if (z < zRow[i]) { \ + PIXEL_TYPE *ptr = pRow + i; \ + ptr->r = FixedToInt(span.red); \ + ptr->g = FixedToInt(span.green); \ + ptr->b = FixedToInt(span.blue); \ + zRow[i] = z; \ + } \ + span.red += span.redStep; \ + span.green += span.greenStep; \ + span.blue += span.blueStep; \ + span.z += span.zStep; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, smooth, depth-buffered, PF_TRUEDITHER triangle. + */ +#define NAME smooth_TRUEDITHER_z_triangle +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define INTERP_RGB 1 +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + XMesaImage *img = xmesa->xm_buffer->backimage; +#define RENDER_SPAN( span ) \ + GLuint i; \ + GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \ + for (i = 0; i < span.end; i++, x++) { \ + const DEPTH_TYPE z = FixedToDepth(span.z); \ + if (z < zRow[i]) { \ + unsigned long p; \ + PACK_TRUEDITHER(p, x, y, FixedToInt(span.red), \ + FixedToInt(span.green), FixedToInt(span.blue)); \ + XMesaPutPixel(img, x, y, p); \ + zRow[i] = z; \ + } \ + span.red += span.redStep; \ + span.green += span.greenStep; \ + span.blue += span.blueStep; \ + span.z += span.zStep; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, smooth, depth-buffered, PF_5R6G5B triangle. + */ +#define NAME smooth_5R6G5B_z_triangle +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define INTERP_RGB 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR2(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE GLushort +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); +#define RENDER_SPAN( span ) \ + GLuint i; \ + for (i = 0; i < span.end; i++) { \ + const DEPTH_TYPE z = FixedToDepth(span.z); \ + if (z < zRow[i]) { \ + pRow[i] = PACK_5R6G5B(FixedToInt(span.red), \ + FixedToInt(span.green), FixedToInt(span.blue)); \ + zRow[i] = z; \ + } \ + span.red += span.redStep; \ + span.green += span.greenStep; \ + span.blue += span.blueStep; \ + span.z += span.zStep; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, smooth, depth-buffered, PF_DITHER_5R6G5B triangle. + */ +#define NAME smooth_DITHER_5R6G5B_z_triangle +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define INTERP_RGB 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR2(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE GLushort +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); +#define RENDER_SPAN( span ) \ + GLuint i; \ + GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \ + for (i = 0; i < span.end; i++, x++) { \ + const DEPTH_TYPE z = FixedToDepth(span.z); \ + if (z < zRow[i]) { \ + PACK_TRUEDITHER(pRow[i], x, y, FixedToInt(span.red), \ + FixedToInt(span.green), FixedToInt(span.blue)); \ + zRow[i] = z; \ + } \ + span.red += span.redStep; \ + span.green += span.greenStep; \ + span.blue += span.blueStep; \ + span.z += span.zStep; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, smooth, depth-buffered, 8-bit, PF_DITHER8 triangle. + */ +#define NAME smooth_DITHER8_z_triangle +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define INTERP_RGB 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE GLubyte +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); +#define RENDER_SPAN( span ) \ + GLuint i; \ + GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \ + XDITHER_SETUP(y); \ + for (i = 0; i < span.end; i++, x++) { \ + const DEPTH_TYPE z = FixedToDepth(span.z); \ + if (z < zRow[i]) { \ + pRow[i] = (PIXEL_TYPE) XDITHER(x, FixedToInt(span.red),\ + FixedToInt(span.green), FixedToInt(span.blue) ); \ + zRow[i] = z; \ + } \ + span.red += span.redStep; \ + span.green += span.greenStep; \ + span.blue += span.blueStep; \ + span.z += span.zStep; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, smooth, depth-buffered, PF_DITHER triangle. + */ +#define NAME smooth_DITHER_z_triangle +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define INTERP_RGB 1 +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + XMesaImage *img = xmesa->xm_buffer->backimage; +#define RENDER_SPAN( span ) \ + GLuint i; \ + GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \ + XDITHER_SETUP(y); \ + for (i = 0; i < span.end; i++, x++) { \ + const DEPTH_TYPE z = FixedToDepth(span.z); \ + if (z < zRow[i]) { \ + unsigned long p = XDITHER(x, FixedToInt(span.red), \ + FixedToInt(span.green), FixedToInt(span.blue)); \ + XMesaPutPixel(img, x, y, p); \ + zRow[i] = z; \ + } \ + span.red += span.redStep; \ + span.green += span.greenStep; \ + span.blue += span.blueStep; \ + span.z += span.zStep; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, smooth, depth-buffered, 8-bit PF_LOOKUP triangle. + */ +#define NAME smooth_LOOKUP8_z_triangle +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define INTERP_RGB 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE GLubyte +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); +#define RENDER_SPAN( span ) \ + GLuint i; \ + LOOKUP_SETUP; \ + for (i = 0; i < span.end; i++) { \ + const DEPTH_TYPE z = FixedToDepth(span.z); \ + if (z < zRow[i]) { \ + pRow[i] = LOOKUP(FixedToInt(span.red), \ + FixedToInt(span.green), FixedToInt(span.blue)); \ + zRow[i] = z; \ + } \ + span.red += span.redStep; \ + span.green += span.greenStep; \ + span.blue += span.blueStep; \ + span.z += span.zStep; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, smooth, depth-buffered, 8-bit PF_HPCR triangle. + */ +#define NAME smooth_HPCR_z_triangle +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define INTERP_RGB 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE GLubyte +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); +#define RENDER_SPAN( span ) \ + GLuint i; \ + GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \ + for (i = 0; i < span.end; i++, x++) { \ + const DEPTH_TYPE z = FixedToDepth(span.z); \ + if (z < zRow[i]) { \ + pRow[i] = DITHER_HPCR(x, y, FixedToInt(span.red), \ + FixedToInt(span.green), FixedToInt(span.blue) ); \ + zRow[i] = z; \ + } \ + span.red += span.redStep; \ + span.green += span.greenStep; \ + span.blue += span.blueStep; \ + span.z += span.zStep; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, flat, depth-buffered, PF_TRUECOLOR triangle. + */ +#define NAME flat_TRUECOLOR_z_triangle +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + XMesaImage *img = xmesa->xm_buffer->backimage; \ + unsigned long pixel; \ + PACK_TRUECOLOR(pixel, v2->color[0], v2->color[1], v2->color[2]); +#define RENDER_SPAN( span ) \ + GLuint i; \ + GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \ + for (i = 0; i < span.end; i++, x++) { \ + const DEPTH_TYPE z = FixedToDepth(span.z); \ + if (z < zRow[i]) { \ + XMesaPutPixel(img, x, y, pixel); \ + zRow[i] = z; \ + } \ + span.z += span.zStep; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, flat, depth-buffered, PF_8A8B8G8R triangle. + */ +#define NAME flat_8A8B8G8R_z_triangle +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE GLuint +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + unsigned long p = PACK_8B8G8R( v2->color[0], \ + v2->color[1], v2->color[2] ); +#define RENDER_SPAN( span ) \ + GLuint i; \ + for (i = 0; i < span.end; i++) { \ + const DEPTH_TYPE z = FixedToDepth(span.z); \ + if (z < zRow[i]) { \ + pRow[i] = (PIXEL_TYPE) p; \ + zRow[i] = z; \ + } \ + span.z += span.zStep; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, flat, depth-buffered, PF_8A8R8G8B triangle. + */ +#define NAME flat_8A8R8G8B_z_triangle +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE GLuint +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + unsigned long p = PACK_8R8G8B( v2->color[0], \ + v2->color[1], v2->color[2] ); +#define RENDER_SPAN( span ) \ + GLuint i; \ + for (i = 0; i < span.end; i++) { \ + const DEPTH_TYPE z = FixedToDepth(span.z); \ + if (z < zRow[i]) { \ + pRow[i] = (PIXEL_TYPE) p; \ + zRow[i] = z; \ + } \ + span.z += span.zStep; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, flat, depth-buffered, PF_8R8G8B triangle. + */ +#define NAME flat_8R8G8B_z_triangle +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE GLuint +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + unsigned long p = PACK_8R8G8B( v2->color[0], \ + v2->color[1], v2->color[2] ); +#define RENDER_SPAN( span ) \ + GLuint i; \ + for (i = 0; i < span.end; i++) { \ + DEPTH_TYPE z = FixedToDepth(span.z); \ + if (z < zRow[i]) { \ + pRow[i] = (PIXEL_TYPE) p; \ + zRow[i] = z; \ + } \ + span.z += span.zStep; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, flat, depth-buffered, PF_8R8G8B24 triangle. + */ +#define NAME flat_8R8G8B24_z_triangle +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define PIXEL_ADDRESS(X,Y) PIXELADDR3(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE bgr_t +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + const GLubyte *color = v2->color; +#define RENDER_SPAN( span ) \ + GLuint i; \ + for (i = 0; i < span.end; i++) { \ + const DEPTH_TYPE z = FixedToDepth(span.z); \ + if (z < zRow[i]) { \ + PIXEL_TYPE *ptr = pRow + i; \ + ptr->r = color[RCOMP]; \ + ptr->g = color[GCOMP]; \ + ptr->b = color[BCOMP]; \ + zRow[i] = z; \ + } \ + span.z += span.zStep; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, flat, depth-buffered, PF_TRUEDITHER triangle. + */ +#define NAME flat_TRUEDITHER_z_triangle +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + XMesaImage *img = xmesa->xm_buffer->backimage; +#define RENDER_SPAN( span ) \ + GLuint i; \ + GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \ + for (i = 0; i < span.end; i++, x++) { \ + const DEPTH_TYPE z = FixedToDepth(span.z); \ + if (z < zRow[i]) { \ + unsigned long p; \ + PACK_TRUEDITHER(p, x, y, v2->color[0], \ + v2->color[1], v2->color[2]); \ + XMesaPutPixel(img, x, y, p); \ + zRow[i] = z; \ + } \ + span.z += span.zStep; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, flat, depth-buffered, PF_5R6G5B triangle. + */ +#define NAME flat_5R6G5B_z_triangle +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define PIXEL_ADDRESS(X,Y) PIXELADDR2(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE GLushort +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + unsigned long p = PACK_5R6G5B( v2->color[0], \ + v2->color[1], v2->color[2] ); +#define RENDER_SPAN( span ) \ + GLuint i; \ + for (i = 0; i < span.end; i++) { \ + const DEPTH_TYPE z = FixedToDepth(span.z); \ + if (z < zRow[i]) { \ + pRow[i] = (PIXEL_TYPE) p; \ + zRow[i] = z; \ + } \ + span.z += span.zStep; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, flat, depth-buffered, PF_DITHER_5R6G5B triangle. + */ +#define NAME flat_DITHER_5R6G5B_z_triangle +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define PIXEL_ADDRESS(X,Y) PIXELADDR2(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE GLushort +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + const GLubyte *color = v2->color; +#define RENDER_SPAN( span ) \ + GLuint i; \ + GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \ + for (i = 0; i < span.end; i++, x++) { \ + const DEPTH_TYPE z = FixedToDepth(span.z); \ + if (z < zRow[i]) { \ + PACK_TRUEDITHER(pRow[i], x, y, color[RCOMP], \ + color[GCOMP], color[BCOMP]); \ + zRow[i] = z; \ + } \ + span.z += span.zStep; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, flat, depth-buffered, 8-bit PF_DITHER triangle. + */ +#define NAME flat_DITHER8_z_triangle +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE GLubyte +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + FLAT_DITHER_SETUP( v2->color[0], v2->color[1], v2->color[2] ); +#define RENDER_SPAN( span ) \ + GLuint i; \ + GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \ + FLAT_DITHER_ROW_SETUP(FLIP(xmesa->xm_buffer, y)); \ + for (i = 0; i < span.end; i++, x++) { \ + const DEPTH_TYPE z = FixedToDepth(span.z); \ + if (z < zRow[i]) { \ + pRow[i] = (PIXEL_TYPE) FLAT_DITHER(x); \ + zRow[i] = z; \ + } \ + span.z += span.zStep; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, flat, depth-buffered, PF_DITHER triangle. + */ +#define NAME flat_DITHER_z_triangle +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + XMesaImage *img = xmesa->xm_buffer->backimage; \ + FLAT_DITHER_SETUP( v2->color[0], v2->color[1], v2->color[2] ); +#define RENDER_SPAN( span ) \ + GLuint i; \ + GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \ + FLAT_DITHER_ROW_SETUP(y); \ + for (i = 0; i < span.end; i++, x++) { \ + const DEPTH_TYPE z = FixedToDepth(span.z); \ + if (z < zRow[i]) { \ + unsigned long p = FLAT_DITHER(x); \ + XMesaPutPixel(img, x, y, p); \ + zRow[i] = z; \ + } \ + span.z += span.zStep; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, flat, depth-buffered, 8-bit PF_HPCR triangle. + */ +#define NAME flat_HPCR_z_triangle +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE GLubyte +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + GLubyte r = v2->color[0]; \ + GLubyte g = v2->color[1]; \ + GLubyte b = v2->color[2]; +#define RENDER_SPAN( span ) \ + GLuint i; \ + GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \ + for (i = 0; i < span.end; i++, x++) { \ + const DEPTH_TYPE z = FixedToDepth(span.z); \ + if (z < zRow[i]) { \ + pRow[i] = (PIXEL_TYPE) DITHER_HPCR(x, y, r, g, b); \ + zRow[i] = z; \ + } \ + span.z += span.zStep; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, flat, depth-buffered, 8-bit PF_LOOKUP triangle. + */ +#define NAME flat_LOOKUP8_z_triangle +#define INTERP_Z 1 +#define DEPTH_TYPE DEFAULT_SOFTWARE_DEPTH_TYPE +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE GLubyte +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + LOOKUP_SETUP; \ + GLubyte r = v2->color[0]; \ + GLubyte g = v2->color[1]; \ + GLubyte b = v2->color[2]; \ + GLubyte p = LOOKUP(r,g,b); +#define RENDER_SPAN( span ) \ + GLuint i; \ + for (i = 0; i < span.end; i++) { \ + const DEPTH_TYPE z = FixedToDepth(span.z); \ + if (z < zRow[i]) { \ + pRow[i] = p; \ + zRow[i] = z; \ + } \ + span.z += span.zStep; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, smooth, NON-depth-buffered, PF_TRUECOLOR triangle. + */ +#define NAME smooth_TRUECOLOR_triangle +#define INTERP_RGB 1 +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + XMesaImage *img = xmesa->xm_buffer->backimage; +#define RENDER_SPAN( span ) \ + GLuint i; \ + GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \ + for (i = 0; i < span.end; i++, x++) { \ + unsigned long p; \ + PACK_TRUECOLOR(p, FixedToInt(span.red), \ + FixedToInt(span.green), FixedToInt(span.blue)); \ + XMesaPutPixel(img, x, y, p); \ + span.red += span.redStep; \ + span.green += span.greenStep; \ + span.blue += span.blueStep; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, smooth, NON-depth-buffered, PF_8A8B8G8R triangle. + */ +#define NAME smooth_8A8B8G8R_triangle +#define INTERP_RGB 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE GLuint +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); +#define RENDER_SPAN( span ) \ + GLuint i; \ + for (i = 0; i < span.end; i++) { \ + pRow[i] = PACK_8B8G8R(FixedToInt(span.red), \ + FixedToInt(span.green), FixedToInt(span.blue) ); \ + span.red += span.redStep; \ + span.green += span.greenStep; \ + span.blue += span.blueStep; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, smooth, NON-depth-buffered, PF_8A8R8G8B triangle. + */ +#define NAME smooth_8A8R8G8B_triangle +#define INTERP_RGB 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE GLuint +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); +#define RENDER_SPAN( span ) \ + GLuint i; \ + for (i = 0; i < span.end; i++) { \ + pRow[i] = PACK_8R8G8B(FixedToInt(span.red), \ + FixedToInt(span.green), FixedToInt(span.blue) ); \ + span.red += span.redStep; \ + span.green += span.greenStep; \ + span.blue += span.blueStep; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, smooth, NON-depth-buffered, PF_8R8G8B triangle. + */ +#define NAME smooth_8R8G8B_triangle +#define INTERP_RGB 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE GLuint +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); +#define RENDER_SPAN( span ) \ + GLuint i; \ + for (i = 0; i < span.end; i++) { \ + pRow[i] = PACK_8R8G8B(FixedToInt(span.red), \ + FixedToInt(span.green), FixedToInt(span.blue) ); \ + span.red += span.redStep; \ + span.green += span.greenStep; \ + span.blue += span.blueStep; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, smooth, NON-depth-buffered, PF_8R8G8B triangle. + */ +#define NAME smooth_8R8G8B24_triangle +#define INTERP_RGB 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR3(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE bgr_t +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); +#define RENDER_SPAN( span ) \ + GLuint i; \ + PIXEL_TYPE *pixel = pRow; \ + for (i = 0; i < span.end; i++, pixel++) { \ + pixel->r = FixedToInt(span.red); \ + pixel->g = FixedToInt(span.green); \ + pixel->b = FixedToInt(span.blue); \ + span.red += span.redStep; \ + span.green += span.greenStep; \ + span.blue += span.blueStep; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, smooth, NON-depth-buffered, PF_TRUEDITHER triangle. + */ +#define NAME smooth_TRUEDITHER_triangle +#define INTERP_RGB 1 +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + XMesaImage *img = xmesa->xm_buffer->backimage; +#define RENDER_SPAN( span ) \ + GLuint i; \ + GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \ + for (i = 0; i < span.end; i++, x++) { \ + unsigned long p; \ + PACK_TRUEDITHER(p, x, y, FixedToInt(span.red), \ + FixedToInt(span.green), FixedToInt(span.blue)); \ + XMesaPutPixel(img, x, y, p ); \ + span.red += span.redStep; \ + span.green += span.greenStep; \ + span.blue += span.blueStep; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, smooth, NON-depth-buffered, PF_5R6G5B triangle. + */ +#define NAME smooth_5R6G5B_triangle +#define INTERP_RGB 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR2(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE GLushort +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); +#define RENDER_SPAN( span ) \ + GLuint i; \ + for (i = 0; i < span.end; i++) { \ + pRow[i] = (PIXEL_TYPE) PACK_5R6G5B(FixedToInt(span.red), \ + FixedToInt(span.green), FixedToInt(span.blue)); \ + span.red += span.redStep; \ + span.green += span.greenStep; \ + span.blue += span.blueStep; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, smooth, NON-depth-buffered, PF_DITHER_5R6G5B triangle. + */ +#define NAME smooth_DITHER_5R6G5B_triangle +#define INTERP_RGB 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR2(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE GLushort +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); +#define RENDER_SPAN( span ) \ + GLuint i; \ + GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \ + for (i = 0; i < span.end; i++, x++) { \ + PACK_TRUEDITHER(pRow[i], x, y, FixedToInt(span.red), \ + FixedToInt(span.green), FixedToInt(span.blue)); \ + span.red += span.redStep; \ + span.green += span.greenStep; \ + span.blue += span.blueStep; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, smooth, NON-depth-buffered, 8-bit PF_DITHER triangle. + */ +#define NAME smooth_DITHER8_triangle +#define INTERP_RGB 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE GLubyte +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); +#define RENDER_SPAN( span ) \ + GLuint i; \ + GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \ + XDITHER_SETUP(y); \ + for (i = 0; i < span.end; i++, x++) { \ + pRow[i] = (PIXEL_TYPE) XDITHER(x, FixedToInt(span.red), \ + FixedToInt(span.green), FixedToInt(span.blue) ); \ + span.red += span.redStep; \ + span.green += span.greenStep; \ + span.blue += span.blueStep; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, smooth, NON-depth-buffered, PF_DITHER triangle. + */ +#define NAME smooth_DITHER_triangle +#define INTERP_RGB 1 +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + XMesaImage *img = xmesa->xm_buffer->backimage; +#define RENDER_SPAN( span ) \ + GLuint i; \ + GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \ + XDITHER_SETUP(y); \ + for (i = 0; i < span.end; i++, x++) { \ + unsigned long p = XDITHER(x, FixedToInt(span.red), \ + FixedToInt(span.green), FixedToInt(span.blue) ); \ + XMesaPutPixel(img, x, y, p); \ + span.red += span.redStep; \ + span.green += span.greenStep; \ + span.blue += span.blueStep; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, smooth, NON-depth-buffered, 8-bit PF_LOOKUP triangle. + */ +#define NAME smooth_LOOKUP8_triangle +#define INTERP_RGB 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE GLubyte +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); +#define RENDER_SPAN( span ) \ + GLuint i; \ + LOOKUP_SETUP; \ + for (i = 0; i < span.end; i++) { \ + pRow[i] = LOOKUP(FixedToInt(span.red), \ + FixedToInt(span.green), FixedToInt(span.blue)); \ + span.red += span.redStep; \ + span.green += span.greenStep; \ + span.blue += span.blueStep; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, smooth, NON-depth-buffered, 8-bit PF_HPCR triangle. + */ +#define NAME smooth_HPCR_triangle +#define INTERP_RGB 1 +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE GLubyte +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); +#define RENDER_SPAN( span ) \ + GLuint i; \ + GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \ + for (i = 0; i < span.end; i++, x++) { \ + pRow[i] = DITHER_HPCR(x, y, FixedToInt(span.red), \ + FixedToInt(span.green), FixedToInt(span.blue)); \ + span.red += span.redStep; \ + span.green += span.greenStep; \ + span.blue += span.blueStep; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, flat, NON-depth-buffered, PF_TRUECOLOR triangle. + */ +#define NAME flat_TRUECOLOR_triangle +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + XMesaImage *img = xmesa->xm_buffer->backimage; \ + unsigned long pixel; \ + PACK_TRUECOLOR(pixel, v2->color[0], v2->color[1], v2->color[2]); +#define RENDER_SPAN( span ) \ + GLuint i; \ + GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \ + for (i = 0; i < span.end; i++, x++) { \ + XMesaPutPixel(img, x, y, pixel); \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, flat, NON-depth-buffered, PF_8A8B8G8R triangle. + */ +#define NAME flat_8A8B8G8R_triangle +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE GLuint +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + unsigned long p = PACK_8B8G8R( v2->color[0], \ + v2->color[1], v2->color[2] ); +#define RENDER_SPAN( span ) \ + GLuint i; \ + for (i = 0; i < span.end; i++) { \ + pRow[i] = (PIXEL_TYPE) p; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, flat, NON-depth-buffered, PF_8A8R8G8B triangle. + */ +#define NAME flat_8A8R8G8B_triangle +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE GLuint +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + unsigned long p = PACK_8R8G8B( v2->color[0], \ + v2->color[1], v2->color[2] ); +#define RENDER_SPAN( span ) \ + GLuint i; \ + for (i = 0; i < span.end; i++) { \ + pRow[i] = (PIXEL_TYPE) p; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, flat, NON-depth-buffered, PF_8R8G8B triangle. + */ +#define NAME flat_8R8G8B_triangle +#define PIXEL_ADDRESS(X,Y) PIXELADDR4(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE GLuint +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + unsigned long p = PACK_8R8G8B( v2->color[0], \ + v2->color[1], v2->color[2] ); +#define RENDER_SPAN( span ) \ + GLuint i; \ + for (i = 0; i < span.end; i++) { \ + pRow[i] = (PIXEL_TYPE) p; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, flat, NON-depth-buffered, PF_8R8G8B24 triangle. + */ +#define NAME flat_8R8G8B24_triangle +#define PIXEL_ADDRESS(X,Y) PIXELADDR3(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE bgr_t +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + const GLubyte *color = v2->color; +#define RENDER_SPAN( span ) \ + GLuint i; \ + PIXEL_TYPE *pixel = pRow; \ + for (i = 0; i < span.end; i++, pixel++) { \ + pixel->r = color[RCOMP]; \ + pixel->g = color[GCOMP]; \ + pixel->b = color[BCOMP]; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, flat, NON-depth-buffered, PF_TRUEDITHER triangle. + */ +#define NAME flat_TRUEDITHER_triangle +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + XMesaImage *img = xmesa->xm_buffer->backimage; +#define RENDER_SPAN( span ) \ + GLuint i; \ + GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \ + for (i = 0; i < span.end; i++, x++) { \ + unsigned long p; \ + PACK_TRUEDITHER(p, x, y, v2->color[0], \ + v2->color[1], v2->color[2] ); \ + XMesaPutPixel(img, x, y, p); \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, flat, NON-depth-buffered, PF_5R6G5B triangle. + */ +#define NAME flat_5R6G5B_triangle +#define PIXEL_ADDRESS(X,Y) PIXELADDR2(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE GLushort +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + unsigned long p = PACK_5R6G5B( v2->color[0], \ + v2->color[1], v2->color[2] ); +#define RENDER_SPAN( span ) \ + GLuint i; \ + for (i = 0; i < span.end; i++) { \ + pRow[i] = (PIXEL_TYPE) p; \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, flat, NON-depth-buffered, PF_DITHER_5R6G5B triangle. + */ +#define NAME flat_DITHER_5R6G5B_triangle +#define PIXEL_ADDRESS(X,Y) PIXELADDR2(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE GLushort +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + const GLubyte *color = v2->color; +#define RENDER_SPAN( span ) \ + GLuint i; \ + GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \ + for (i = 0; i < span.end; i++, x++) { \ + PACK_TRUEDITHER(pRow[i], x, y, color[RCOMP], \ + color[GCOMP], color[BCOMP]); \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, flat, NON-depth-buffered, 8-bit PF_DITHER triangle. + */ +#define NAME flat_DITHER8_triangle +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE GLubyte +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + FLAT_DITHER_SETUP( v2->color[0], v2->color[1], v2->color[2] ); +#define RENDER_SPAN( span ) \ + GLuint i; \ + GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \ + FLAT_DITHER_ROW_SETUP(FLIP(xmesa->xm_buffer, y)); \ + for (i = 0; i < span.end; i++, x++) { \ + pRow[i] = (PIXEL_TYPE) FLAT_DITHER(x); \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, flat, NON-depth-buffered, PF_DITHER triangle. + */ +#define NAME flat_DITHER_triangle +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + XMesaImage *img = xmesa->xm_buffer->backimage; \ + FLAT_DITHER_SETUP( v2->color[0], v2->color[1], v2->color[2] ); +#define RENDER_SPAN( span ) \ + GLuint i; \ + GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \ + FLAT_DITHER_ROW_SETUP(y); \ + for (i = 0; i < span.end; i++, x++) { \ + unsigned long p = FLAT_DITHER(x); \ + XMesaPutPixel(img, x, y, p ); \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, flat, NON-depth-buffered, 8-bit PF_HPCR triangle. + */ +#define NAME flat_HPCR_triangle +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE GLubyte +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + GLubyte r = v2->color[0]; \ + GLubyte g = v2->color[1]; \ + GLubyte b = v2->color[2]; +#define RENDER_SPAN( span ) \ + GLuint i; \ + GLint x = span.x, y = FLIP(xmesa->xm_buffer, span.y); \ + for (i = 0; i < span.end; i++, x++) { \ + pRow[i] = (PIXEL_TYPE) DITHER_HPCR(x, y, r, g, b); \ + } +#include "swrast/s_tritemp.h" + + + +/* + * XImage, flat, NON-depth-buffered, 8-bit PF_LOOKUP triangle. + */ +#define NAME flat_LOOKUP8_triangle +#define PIXEL_ADDRESS(X,Y) PIXELADDR1(xmesa->xm_buffer,X,Y) +#define PIXEL_TYPE GLubyte +#define BYTES_PER_ROW (xmesa->xm_buffer->backimage->bytes_per_line) +#define SETUP_CODE \ + XMesaContext xmesa = XMESA_CONTEXT(ctx); \ + LOOKUP_SETUP; \ + GLubyte r = v2->color[0]; \ + GLubyte g = v2->color[1]; \ + GLubyte b = v2->color[2]; \ + GLubyte p = LOOKUP(r,g,b); +#define RENDER_SPAN( span ) \ + GLuint i; \ + for (i = 0; i < span.end; i++) { \ + pRow[i] = (PIXEL_TYPE) p; \ + } +#include "swrast/s_tritemp.h" + + + +#ifdef DEBUG +extern void _xmesa_print_triangle_func( swrast_tri_func triFunc ); +void _xmesa_print_triangle_func( swrast_tri_func triFunc ) +{ + _mesa_printf("XMesa tri func = "); + if (triFunc ==smooth_TRUECOLOR_z_triangle) + _mesa_printf("smooth_TRUECOLOR_z_triangle\n"); + else if (triFunc ==smooth_8A8B8G8R_z_triangle) + _mesa_printf("smooth_8A8B8G8R_z_triangle\n"); + else if (triFunc ==smooth_8A8R8G8B_z_triangle) + _mesa_printf("smooth_8A8R8G8B_z_triangle\n"); + else if (triFunc ==smooth_8R8G8B_z_triangle) + _mesa_printf("smooth_8R8G8B_z_triangle\n"); + else if (triFunc ==smooth_8R8G8B24_z_triangle) + _mesa_printf("smooth_8R8G8B24_z_triangle\n"); + else if (triFunc ==smooth_TRUEDITHER_z_triangle) + _mesa_printf("smooth_TRUEDITHER_z_triangle\n"); + else if (triFunc ==smooth_5R6G5B_z_triangle) + _mesa_printf("smooth_5R6G5B_z_triangle\n"); + else if (triFunc ==smooth_DITHER_5R6G5B_z_triangle) + _mesa_printf("smooth_DITHER_5R6G5B_z_triangle\n"); + else if (triFunc ==smooth_HPCR_z_triangle) + _mesa_printf("smooth_HPCR_z_triangle\n"); + else if (triFunc ==smooth_DITHER8_z_triangle) + _mesa_printf("smooth_DITHER8_z_triangle\n"); + else if (triFunc ==smooth_LOOKUP8_z_triangle) + _mesa_printf("smooth_LOOKUP8_z_triangle\n"); + else if (triFunc ==flat_TRUECOLOR_z_triangle) + _mesa_printf("flat_TRUECOLOR_z_triangle\n"); + else if (triFunc ==flat_8A8B8G8R_z_triangle) + _mesa_printf("flat_8A8B8G8R_z_triangle\n"); + else if (triFunc ==flat_8A8R8G8B_z_triangle) + _mesa_printf("flat_8A8R8G8B_z_triangle\n"); + else if (triFunc ==flat_8R8G8B_z_triangle) + _mesa_printf("flat_8R8G8B_z_triangle\n"); + else if (triFunc ==flat_8R8G8B24_z_triangle) + _mesa_printf("flat_8R8G8B24_z_triangle\n"); + else if (triFunc ==flat_TRUEDITHER_z_triangle) + _mesa_printf("flat_TRUEDITHER_z_triangle\n"); + else if (triFunc ==flat_5R6G5B_z_triangle) + _mesa_printf("flat_5R6G5B_z_triangle\n"); + else if (triFunc ==flat_DITHER_5R6G5B_z_triangle) + _mesa_printf("flat_DITHER_5R6G5B_z_triangle\n"); + else if (triFunc ==flat_HPCR_z_triangle) + _mesa_printf("flat_HPCR_z_triangle\n"); + else if (triFunc ==flat_DITHER8_z_triangle) + _mesa_printf("flat_DITHER8_z_triangle\n"); + else if (triFunc ==flat_LOOKUP8_z_triangle) + _mesa_printf("flat_LOOKUP8_z_triangle\n"); + else if (triFunc ==smooth_TRUECOLOR_triangle) + _mesa_printf("smooth_TRUECOLOR_triangle\n"); + else if (triFunc ==smooth_8A8B8G8R_triangle) + _mesa_printf("smooth_8A8B8G8R_triangle\n"); + else if (triFunc ==smooth_8A8R8G8B_triangle) + _mesa_printf("smooth_8A8R8G8B_triangle\n"); + else if (triFunc ==smooth_8R8G8B_triangle) + _mesa_printf("smooth_8R8G8B_triangle\n"); + else if (triFunc ==smooth_8R8G8B24_triangle) + _mesa_printf("smooth_8R8G8B24_triangle\n"); + else if (triFunc ==smooth_TRUEDITHER_triangle) + _mesa_printf("smooth_TRUEDITHER_triangle\n"); + else if (triFunc ==smooth_5R6G5B_triangle) + _mesa_printf("smooth_5R6G5B_triangle\n"); + else if (triFunc ==smooth_DITHER_5R6G5B_triangle) + _mesa_printf("smooth_DITHER_5R6G5B_triangle\n"); + else if (triFunc ==smooth_HPCR_triangle) + _mesa_printf("smooth_HPCR_triangle\n"); + else if (triFunc ==smooth_DITHER8_triangle) + _mesa_printf("smooth_DITHER8_triangle\n"); + else if (triFunc ==smooth_LOOKUP8_triangle) + _mesa_printf("smooth_LOOKUP8_triangle\n"); + else if (triFunc ==flat_TRUECOLOR_triangle) + _mesa_printf("flat_TRUECOLOR_triangle\n"); + else if (triFunc ==flat_TRUEDITHER_triangle) + _mesa_printf("flat_TRUEDITHER_triangle\n"); + else if (triFunc ==flat_8A8B8G8R_triangle) + _mesa_printf("flat_8A8B8G8R_triangle\n"); + else if (triFunc ==flat_8A8R8G8B_triangle) + _mesa_printf("flat_8A8R8G8B_triangle\n"); + else if (triFunc ==flat_8R8G8B_triangle) + _mesa_printf("flat_8R8G8B_triangle\n"); + else if (triFunc ==flat_8R8G8B24_triangle) + _mesa_printf("flat_8R8G8B24_triangle\n"); + else if (triFunc ==flat_5R6G5B_triangle) + _mesa_printf("flat_5R6G5B_triangle\n"); + else if (triFunc ==flat_DITHER_5R6G5B_triangle) + _mesa_printf("flat_DITHER_5R6G5B_triangle\n"); + else if (triFunc ==flat_HPCR_triangle) + _mesa_printf("flat_HPCR_triangle\n"); + else if (triFunc ==flat_DITHER8_triangle) + _mesa_printf("flat_DITHER8_triangle\n"); + else if (triFunc ==flat_LOOKUP8_triangle) + _mesa_printf("flat_LOOKUP8_triangle\n"); + else + _mesa_printf("???\n"); +} +#endif + + +#ifdef DEBUG + +/* record the current triangle function name */ +static const char *triFuncName = NULL; + +#define USE(triFunc) \ +do { \ + triFuncName = #triFunc; \ + return triFunc; \ +} while (0) + +#else + +#define USE(triFunc) return triFunc + +#endif + + +static swrast_tri_func get_triangle_func( GLcontext *ctx ) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + XMesaContext xmesa = XMESA_CONTEXT(ctx); + int depth = GET_VISUAL_DEPTH(xmesa->xm_visual); + +#ifdef DEBUG + triFuncName = NULL; +#endif + + if ((ctx->Color._DrawDestMask & (DD_FRONT_LEFT_BIT | DD_BACK_LEFT_BIT)) ==0) + return (swrast_tri_func) NULL; + if (ctx->RenderMode != GL_RENDER) return (swrast_tri_func) NULL; + if (ctx->Polygon.SmoothFlag) return (swrast_tri_func) NULL; + if (ctx->Texture._EnabledUnits) return (swrast_tri_func) NULL; + if (swrast->_RasterMask & MULTI_DRAW_BIT) return (swrast_tri_func) NULL; + if (ctx->Polygon.CullFlag && + ctx->Polygon.CullFaceMode == GL_FRONT_AND_BACK) + return (swrast_tri_func) NULL; + + if (xmesa->xm_buffer->buffer==XIMAGE) { + if ( ctx->Light.ShadeModel==GL_SMOOTH + && swrast->_RasterMask==DEPTH_BIT + && ctx->Depth.Func==GL_LESS + && ctx->Depth.Mask==GL_TRUE + && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS + && ctx->Polygon.StippleFlag==GL_FALSE) { + switch (xmesa->pixelformat) { + case PF_Truecolor: + USE(smooth_TRUECOLOR_z_triangle); + case PF_8A8B8G8R: + USE(smooth_8A8B8G8R_z_triangle); + case PF_8A8R8G8B: + USE(smooth_8A8R8G8B_z_triangle); + case PF_8R8G8B: + USE(smooth_8R8G8B_z_triangle); + case PF_8R8G8B24: + USE(smooth_8R8G8B24_z_triangle); + case PF_Dither_True: + USE(smooth_TRUEDITHER_z_triangle); + case PF_5R6G5B: + USE(smooth_5R6G5B_z_triangle); + case PF_Dither_5R6G5B: + USE(smooth_DITHER_5R6G5B_z_triangle); + case PF_HPCR: + USE(smooth_HPCR_z_triangle); + case PF_Dither: + if (depth == 8) + USE(smooth_DITHER8_z_triangle); + else + USE(smooth_DITHER_z_triangle); + case PF_Lookup: + if (depth == 8) + USE(smooth_LOOKUP8_z_triangle); + else + return (swrast_tri_func) NULL; + default: + return (swrast_tri_func) NULL; + } + } + if ( ctx->Light.ShadeModel==GL_FLAT + && swrast->_RasterMask==DEPTH_BIT + && ctx->Depth.Func==GL_LESS + && ctx->Depth.Mask==GL_TRUE + && ctx->Visual.depthBits == DEFAULT_SOFTWARE_DEPTH_BITS + && ctx->Polygon.StippleFlag==GL_FALSE) { + switch (xmesa->pixelformat) { + case PF_Truecolor: + USE(flat_TRUECOLOR_z_triangle); + case PF_8A8B8G8R: + USE(flat_8A8B8G8R_z_triangle); + case PF_8A8R8G8B: + USE(flat_8A8R8G8B_z_triangle); + case PF_8R8G8B: + USE(flat_8R8G8B_z_triangle); + case PF_8R8G8B24: + USE(flat_8R8G8B24_z_triangle); + case PF_Dither_True: + USE(flat_TRUEDITHER_z_triangle); + case PF_5R6G5B: + USE(flat_5R6G5B_z_triangle); + case PF_Dither_5R6G5B: + USE(flat_DITHER_5R6G5B_z_triangle); + case PF_HPCR: + USE(flat_HPCR_z_triangle); + case PF_Dither: + if (depth == 8) + USE(flat_DITHER8_z_triangle); + else + USE(flat_DITHER_z_triangle); + case PF_Lookup: + if (depth == 8) + USE(flat_LOOKUP8_z_triangle); + else + return (swrast_tri_func) NULL; + default: + return (swrast_tri_func) NULL; + } + } + if ( swrast->_RasterMask==0 /* no depth test */ + && ctx->Light.ShadeModel==GL_SMOOTH + && ctx->Polygon.StippleFlag==GL_FALSE) { + switch (xmesa->pixelformat) { + case PF_Truecolor: + USE(smooth_TRUECOLOR_triangle); + case PF_8A8B8G8R: + USE(smooth_8A8B8G8R_triangle); + case PF_8A8R8G8B: + USE(smooth_8A8R8G8B_triangle); + case PF_8R8G8B: + USE(smooth_8R8G8B_triangle); + case PF_8R8G8B24: + USE(smooth_8R8G8B24_triangle); + case PF_Dither_True: + USE(smooth_TRUEDITHER_triangle); + case PF_5R6G5B: + USE(smooth_5R6G5B_triangle); + case PF_Dither_5R6G5B: + USE(smooth_DITHER_5R6G5B_triangle); + case PF_HPCR: + USE(smooth_HPCR_triangle); + case PF_Dither: + if (depth == 8) + USE(smooth_DITHER8_triangle); + else + USE(smooth_DITHER_triangle); + case PF_Lookup: + if (depth == 8) + USE(smooth_LOOKUP8_triangle); + else + return (swrast_tri_func) NULL; + default: + return (swrast_tri_func) NULL; + } + } + + if ( swrast->_RasterMask==0 /* no depth test */ + && ctx->Light.ShadeModel==GL_FLAT + && ctx->Polygon.StippleFlag==GL_FALSE) { + switch (xmesa->pixelformat) { + case PF_Truecolor: + USE(flat_TRUECOLOR_triangle); + case PF_Dither_True: + USE(flat_TRUEDITHER_triangle); + case PF_8A8B8G8R: + USE(flat_8A8B8G8R_triangle); + case PF_8A8R8G8B: + USE(flat_8A8R8G8B_triangle); + case PF_8R8G8B: + USE(flat_8R8G8B_triangle); + case PF_8R8G8B24: + USE(flat_8R8G8B24_triangle); + case PF_5R6G5B: + USE(flat_5R6G5B_triangle); + case PF_Dither_5R6G5B: + USE(flat_DITHER_5R6G5B_triangle); + case PF_HPCR: + USE(flat_HPCR_triangle); + case PF_Dither: + if (depth == 8) + USE(flat_DITHER8_triangle); + else + USE(flat_DITHER_triangle); + case PF_Lookup: + if (depth == 8) + USE(flat_LOOKUP8_triangle); + else + return (swrast_tri_func) NULL; + default: + return (swrast_tri_func) NULL; + } + } + + return (swrast_tri_func) NULL; + } + else { + /* draw to pixmap */ + return (swrast_tri_func) NULL; + } +} + + +/* Override for the swrast tri-selection function. Try to use one + * of our internal tri functions, otherwise fall back to the + * standard swrast functions. + */ +void xmesa_choose_triangle( GLcontext *ctx ) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + + if (!(swrast->Triangle = get_triangle_func( ctx ))) + _swrast_choose_triangle( ctx ); +} + diff --git a/src/mesa/drivers/x11/xmesaP.h b/src/mesa/drivers/x11/xmesaP.h new file mode 100644 index 0000000..455d7af --- /dev/null +++ b/src/mesa/drivers/x11/xmesaP.h @@ -0,0 +1,531 @@ +/* + * Mesa 3-D graphics library + * Version: 6.1 + * + * Copyright (C) 1999-2004 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. + */ + + +#ifndef XMESAP_H +#define XMESAP_H + + +#ifdef XFree86Server +# include "GL/xf86glx.h" +# include "xf86glx_util.h" +#elif defined(USE_XSHM) +# include +#endif +#include "GL/xmesa.h" +#include "mtypes.h" +#if defined(FX) +#include "GL/fxmesa.h" +#include "../glide/fxdrv.h" +#endif + + +extern _glthread_Mutex _xmesa_lock; + + +/* for PF_8R8G8B24 pixel format */ +typedef struct { + GLubyte b; + GLubyte g; + GLubyte r; +} bgr_t; + + +/* Function pointer for clearing color buffers */ +typedef void (*clear_func)( GLcontext *ctx, + GLboolean all, GLint x, GLint y, + GLint width, GLint height ); + + + + +/** Framebuffer pixel formats */ +enum pixel_format { + PF_Index, /**< Color Index mode */ + PF_Truecolor, /**< TrueColor or DirectColor, any depth */ + PF_Dither_True, /**< TrueColor with dithering */ + PF_8A8B8G8R, /**< 32-bit TrueColor: 8-A, 8-B, 8-G, 8-R */ + PF_8R8G8B, /**< 32-bit TrueColor: 8-R, 8-G, 8-B bits */ + PF_5R6G5B, /**< 16-bit TrueColor: 5-R, 6-G, 5-B bits */ + PF_Dither, /**< Color-mapped RGB with dither */ + PF_Lookup, /**< Color-mapped RGB without dither */ + PF_HPCR, /**< HP Color Recovery (ad@lms.be 30/08/95) */ + PF_1Bit, /**< monochrome dithering of RGB */ + PF_Grayscale, /**< Grayscale or StaticGray */ + PF_8R8G8B24, /**< 24-bit TrueColor: 8-R, 8-G, 8-B bits */ + PF_Dither_5R6G5B, /**< 16-bit dithered TrueColor: 5-R, 6-G, 5-B */ + PF_8A8R8G8B /**< 32-bit TrueColor: 8-A, 8-R, 8-G, 8-B */ +}; + + +/* + * "Derived" from GLvisual. Basically corresponds to an XVisualInfo. + */ +struct xmesa_visual { + GLvisual mesa_visual; /* Device independent visual parameters */ + XMesaDisplay *display; /* The X11 display */ +#ifdef XFree86Server + GLint ColormapEntries; + GLint nplanes; +#else + XMesaVisualInfo visinfo; /* X's visual info (pointer to private copy) */ + XVisualInfo *vishandle; /* Only used in fakeglx.c */ +#endif + GLint BitsPerPixel; /* True bits per pixel for XImages */ + + GLboolean ximage_flag; /* Use XImage for back buffer (not pixmap)? */ + + enum pixel_format dithered_pf; /* Pixel format when dithering */ + enum pixel_format undithered_pf;/* Pixel format when not dithering */ + + GLfloat RedGamma; /* Gamma values, 1.0 is default */ + GLfloat GreenGamma; + GLfloat BlueGamma; + + /* For PF_TRUECOLOR */ + GLint rshift, gshift, bshift;/* Pixel color component shifts */ + GLubyte Kernel[16]; /* Dither kernel */ + unsigned long RtoPixel[512]; /* RGB to pixel conversion */ + unsigned long GtoPixel[512]; + unsigned long BtoPixel[512]; + GLubyte PixelToR[256]; /* Pixel to RGB conversion */ + GLubyte PixelToG[256]; + GLubyte PixelToB[256]; + + /* For PF_HPCR */ + short hpcr_rgbTbl[3][256]; + GLboolean hpcr_clear_flag; + GLubyte hpcr_clear_ximage_pattern[2][16]; + XMesaImage *hpcr_clear_ximage; + XMesaPixmap hpcr_clear_pixmap; + + /* For PF_1BIT */ + int bitFlip; +}; + + +/* + * "Derived" from __GLcontextRec. Basically corresponds to a GLXContext. + */ +struct xmesa_context { + GLcontext mesa; /* the core library context (containment) */ + XMesaVisual xm_visual; /* Describes the buffers */ + XMesaBuffer xm_draw_buffer; /* current draw framebuffer */ + XMesaBuffer xm_read_buffer; /* current read framebuffer */ + XMesaBuffer xm_buffer; /* current span/point/line/triangle buffer */ + + XMesaDisplay *display; /* == xm_visual->display */ + GLboolean swapbytes; /* Host byte order != display byte order? */ + GLboolean direct; /* Direct rendering context? */ + + enum pixel_format pixelformat; + + GLubyte clearcolor[4]; /* current clearing color */ + unsigned long clearpixel; /* current clearing pixel value */ +}; + + + +typedef enum { + WINDOW, /* An X window */ + GLXWINDOW, /* GLX window */ + PIXMAP, /* GLX pixmap */ + PBUFFER /* GLX Pbuffer */ +} BufferType; + + +/* + * "Derived" from GLframebuffer. Basically corresponds to a GLXDrawable. + */ +struct xmesa_buffer { + GLframebuffer mesa_buffer; /* depth, stencil, accum, etc buffers */ + /* This MUST BE FIRST! */ + GLboolean wasCurrent; /* was ever the current buffer? */ + XMesaVisual xm_visual; /* the X/Mesa visual */ + + XMesaDisplay *display; + BufferType type; /* window, pixmap, pbuffer or glxwindow */ + XMesaDrawable frontbuffer; /* either a window or pixmap */ + XMesaPixmap backpixmap; /* back buffer Pixmap */ + XMesaImage *backimage; /* back buffer simulated XImage */ + + XMesaDrawable buffer; /* the current buffer, either equal to */ + /* frontbuffer, backpixmap or XIMAGE (None) */ + + XMesaColormap cmap; /* the X colormap */ + + unsigned long selectedEvents;/* for pbuffers only */ + + GLint db_state; /* 0 = single buffered */ + /* BACK_PIXMAP = use Pixmap for back buffer */ + /* BACK_XIMAGE = use XImage for back buffer */ + +#ifndef XFree86Server + GLuint shm; /* X Shared Memory extension status: */ + /* 0 = not available */ + /* 1 = XImage support available */ + /* 2 = Pixmap support available too */ +#ifdef USE_XSHM + XShmSegmentInfo shminfo; +#endif +#endif + + XMesaImage *rowimage; /* Used for optimized span writing */ + + GLuint width, height; /* size of buffer */ + + GLint bottom; /* used for FLIP macro below */ + GLubyte *ximage_origin1; /* used for PIXELADDR1 macro */ + GLint ximage_width1; + GLushort *ximage_origin2; /* used for PIXELADDR2 macro */ + GLint ximage_width2; + GLubyte *ximage_origin3; /* used for PIXELADDR3 macro */ + GLint ximage_width3; + GLuint *ximage_origin4; /* used for PIXELADDR4 macro */ + GLint ximage_width4; + + XMesaPixmap stipple_pixmap; /* For polygon stippling */ + XMesaGC stipple_gc; /* For polygon stippling */ + + XMesaGC gc; /* scratch GC for span, line, tri drawing */ + XMesaGC cleargc; /* GC for clearing the color buffer */ + XMesaGC swapgc; /* GC for swapping the color buffers */ + + /* The following are here instead of in the XMesaVisual + * because they depend on the window's colormap. + */ + + /* For PF_DITHER, PF_LOOKUP, PF_GRAYSCALE */ + unsigned long color_table[576]; /* RGB -> pixel value */ + + /* For PF_DITHER, PF_LOOKUP, PF_GRAYSCALE */ + GLubyte pixel_to_r[65536]; /* pixel value -> red */ + GLubyte pixel_to_g[65536]; /* pixel value -> green */ + GLubyte pixel_to_b[65536]; /* pixel value -> blue */ + + /* Used to do XAllocColor/XFreeColors accounting: */ + int num_alloced; +#if defined(XFree86Server) + Pixel alloced_colors[256]; +#else + unsigned long alloced_colors[256]; +#endif + +#if defined( FX ) + /* For 3Dfx Glide only */ + GLboolean FXisHackUsable; /* Can we render into window? */ + GLboolean FXwindowHack; /* Are we rendering into a window? */ + fxMesaContext FXctx; +#endif + + /* functions for clearing the front and back color buffers */ + clear_func front_clear_func; + clear_func back_clear_func; + + struct xmesa_buffer *Next; /* Linked list pointer: */ +}; + + + +/* Values for xmesa->dest: */ +#define FRONT_PIXMAP 1 +#define BACK_PIXMAP 2 +#define BACK_XIMAGE 4 + +/* Special value for X Drawable variables to indicate use of XImage instead */ +#define XIMAGE None + + +/* + * If pixelformat==PF_TRUECOLOR: + */ +#define PACK_TRUECOLOR( PIXEL, R, G, B ) \ + PIXEL = xmesa->xm_visual->RtoPixel[R] \ + | xmesa->xm_visual->GtoPixel[G] \ + | xmesa->xm_visual->BtoPixel[B]; \ + + +/* + * If pixelformat==PF_TRUEDITHER: + */ +#define PACK_TRUEDITHER( PIXEL, X, Y, R, G, B ) \ +{ \ + int d = xmesa->xm_visual->Kernel[((X)&3) | (((Y)&3)<<2)]; \ + PIXEL = xmesa->xm_visual->RtoPixel[(R)+d] \ + | xmesa->xm_visual->GtoPixel[(G)+d] \ + | xmesa->xm_visual->BtoPixel[(B)+d]; \ +} + + + +/* + * If pixelformat==PF_8A8B8G8R: + */ +#define PACK_8A8B8G8R( R, G, B, A ) \ + ( ((A) << 24) | ((B) << 16) | ((G) << 8) | (R) ) + + +/* + * Like PACK_8A8B8G8R() but don't use alpha. This is usually an acceptable + * shortcut. + */ +#define PACK_8B8G8R( R, G, B ) ( ((B) << 16) | ((G) << 8) | (R) ) + + + +/* + * If pixelformat==PF_8R8G8B: + */ +#define PACK_8R8G8B( R, G, B) ( ((R) << 16) | ((G) << 8) | (B) ) + + +/* + * If pixelformat==PF_5R6G5B: + */ +#define PACK_5R6G5B( R, G, B) ( (((R) & 0xf8) << 8) | (((G) & 0xfc) << 3) | ((B) >> 3) ) + + +/* + * If pixelformat==PF_8A8R8G8B: + */ +#define PACK_8A8R8G8B( R, G, B, A ) \ + ( ((A) << 24) | ((R) << 16) | ((G) << 8) | (B) ) + + + +/* + * If pixelformat==PF_DITHER: + * + * Improved 8-bit RGB dithering code contributed by Bob Mercier + * (mercier@hollywood.cinenet.net). Thanks Bob! + */ +#ifdef DITHER666 +# define DITH_R 6 +# define DITH_G 6 +# define DITH_B 6 +# define DITH_MIX(r,g,b) (((r) * DITH_G + (g)) * DITH_B + (b)) +#else +# define DITH_R 5 +# define DITH_G 9 +# define DITH_B 5 +# define DITH_MIX(r,g,b) (((g) << 6) | ((b) << 3) | (r)) +#endif +#define DITH_DX 4 +#define DITH_DY 4 +#define DITH_N (DITH_DX * DITH_DY) + +#define _dither(C, c, d) (((unsigned)((DITH_N * (C - 1) + 1) * c + d)) >> 12) + +#define MAXC 256 +extern const int xmesa_kernel8[DITH_DY * DITH_DX]; + +/* Dither for random X,Y */ +#define DITHER_SETUP \ + int __d; \ + unsigned long *ctable = xmesa->xm_buffer->color_table; + +#define DITHER( X, Y, R, G, B ) \ + (__d = xmesa_kernel8[(((Y)&3)<<2) | ((X)&3)], \ + ctable[DITH_MIX(_dither(DITH_R, (R), __d), \ + _dither(DITH_G, (G), __d), \ + _dither(DITH_B, (B), __d))]) + +/* Dither for random X, fixed Y */ +#define XDITHER_SETUP(Y) \ + int __d; \ + unsigned long *ctable = xmesa->xm_buffer->color_table; \ + const int *kernel = &xmesa_kernel8[ ((Y)&3) << 2 ]; + +#define XDITHER( X, R, G, B ) \ + (__d = kernel[(X)&3], \ + ctable[DITH_MIX(_dither(DITH_R, (R), __d), \ + _dither(DITH_G, (G), __d), \ + _dither(DITH_B, (B), __d))]) + + + +/* + * Dithering for flat-shaded triangles. Precompute all 16 possible + * pixel values given the triangle's RGB color. Contributed by Martin Shenk. + */ +#define FLAT_DITHER_SETUP( R, G, B ) \ + GLushort ditherValues[16]; \ + { \ + unsigned long *ctable = xmesa->xm_buffer->color_table; \ + int msdr = (DITH_N*((DITH_R)-1)+1) * (R); \ + int msdg = (DITH_N*((DITH_G)-1)+1) * (G); \ + int msdb = (DITH_N*((DITH_B)-1)+1) * (B); \ + int i; \ + for (i=0;i<16;i++) { \ + int k = xmesa_kernel8[i]; \ + int j = DITH_MIX( (msdr+k)>>12, (msdg+k)>>12, (msdb+k)>>12 );\ + ditherValues[i] = (GLushort) ctable[j]; \ + } \ + } + +#define FLAT_DITHER_ROW_SETUP(Y) \ + GLushort *ditherRow = ditherValues + ( ((Y)&3) << 2); + +#define FLAT_DITHER(X) ditherRow[(X)&3] + + + +/* + * If pixelformat==PF_LOOKUP: + */ +#define _dither_lookup(C, c) (((unsigned)((DITH_N * (C - 1) + 1) * c)) >> 12) + +#define LOOKUP_SETUP \ + unsigned long *ctable = xmesa->xm_buffer->color_table + +#define LOOKUP( R, G, B ) \ + ctable[DITH_MIX(_dither_lookup(DITH_R, (R)), \ + _dither_lookup(DITH_G, (G)), \ + _dither_lookup(DITH_B, (B)))] + + + +/* + * If pixelformat==PF_HPCR: + * + * HP Color Recovery dithering (ad@lms.be 30/08/95) + * HP has on it's 8-bit 700-series computers, a feature called + * 'Color Recovery'. This allows near 24-bit output (so they say). + * It is enabled by selecting the 8-bit TrueColor visual AND + * corresponding colormap (see tkInitWindow) AND doing some special + * dither. + */ +extern const short xmesa_HPCR_DRGB[3][2][16]; + +#define DITHER_HPCR( X, Y, R, G, B ) \ + ( ((xmesa->xm_visual->hpcr_rgbTbl[0][R] + xmesa_HPCR_DRGB[0][(Y)&1][(X)&15]) & 0xE0) \ + |(((xmesa->xm_visual->hpcr_rgbTbl[1][G] + xmesa_HPCR_DRGB[1][(Y)&1][(X)&15]) & 0xE0)>>3) \ + | ((xmesa->xm_visual->hpcr_rgbTbl[2][B] + xmesa_HPCR_DRGB[2][(Y)&1][(X)&15])>>6) \ + ) + + + +/* + * If pixelformat==PF_1BIT: + */ +extern const int xmesa_kernel1[16]; + +#define SETUP_1BIT int bitFlip = xmesa->xm_visual->bitFlip +#define DITHER_1BIT( X, Y, R, G, B ) \ + (( ((int)(R)+(int)(G)+(int)(B)) > xmesa_kernel1[(((Y)&3) << 2) | ((X)&3)] ) ^ bitFlip) + + + +/* + * If pixelformat==PF_GRAYSCALE: + */ +#define GRAY_RGB( R, G, B ) xmesa->xm_buffer->color_table[((R) + (G) + (B))/3] + + + +/* + * Converts a GL window Y coord to an X window Y coord: + */ +#define FLIP(BUFFER, Y) ((BUFFER)->bottom-(Y)) + + +/* + * Return the address of a 1, 2 or 4-byte pixel in the back XImage: + * X==0 is left, Y==0 is bottom. + */ +#define PIXELADDR1( BUFFER, X, Y ) \ + ( (BUFFER)->ximage_origin1 - (Y) * (BUFFER)->ximage_width1 + (X) ) + +#define PIXELADDR2( BUFFER, X, Y ) \ + ( (BUFFER)->ximage_origin2 - (Y) * (BUFFER)->ximage_width2 + (X) ) + +#define PIXELADDR3( BUFFER, X, Y ) \ + ( (bgr_t *) ( (BUFFER)->ximage_origin3 - (Y) * (BUFFER)->ximage_width3 + 3 * (X) )) + +#define PIXELADDR4( BUFFER, X, Y ) \ + ( (BUFFER)->ximage_origin4 - (Y) * (BUFFER)->ximage_width4 + (X) ) + + + + +/* + * Return pointer to XMesaContext corresponding to a Mesa GLcontext. + * Since we're using structure containment, it's just a cast!. + */ +#define XMESA_CONTEXT(MESACTX) (XMesaContext) (MESACTX) + + + +/* + * External functions: + */ + +extern unsigned long +xmesa_color_to_pixel( XMesaContext xmesa, + GLubyte r, GLubyte g, GLubyte b, GLubyte a, + GLuint pixelFormat ); + +extern void xmesa_alloc_back_buffer( XMesaBuffer b ); + +extern void xmesa_resize_buffers( GLframebuffer *buffer ); + +extern void xmesa_init_driver_functions( XMesaVisual xmvisual, + struct dd_function_table *driver ); + +extern void xmesa_update_state( GLcontext *ctx, GLuint new_state ); + +extern void xmesa_update_span_funcs( GLcontext *ctx ); + +extern void xmesa_set_buffer( GLcontext *ctx, GLframebuffer *buffer, + GLuint bufferBit ); + + +/* Plugged into the software rasterizer. Try to use internal + * swrast-style point, line and triangle functions. + */ +extern void xmesa_choose_point( GLcontext *ctx ); +extern void xmesa_choose_line( GLcontext *ctx ); +extern void xmesa_choose_triangle( GLcontext *ctx ); + + +extern void xmesa_register_swrast_functions( GLcontext *ctx ); + + + +/* XXX this is a hack to implement shared display lists with 3Dfx */ +extern XMesaBuffer XMesaCreateWindowBuffer2( XMesaVisual v, + XMesaWindow w, + XMesaContext c ); + +/* + * These are the extra routines required for integration with XFree86. + * None of these routines should be user visible. -KEM + */ +extern void XMesaSetVisualDisplay( XMesaDisplay *dpy, XMesaVisual v ); +extern GLboolean XMesaForceCurrent(XMesaContext c); +extern GLboolean XMesaLoseCurrent(XMesaContext c); +extern void XMesaReset( void ); + + +#endif -- cgit