Path: blob/21.2-virgl/src/gallium/frontends/glx/xlib/glx_api.c
4561 views
/*1* Mesa 3-D graphics library2*3* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.4* Copyright (C) 2009 VMware, Inc. All Rights Reserved.5*6* Permission is hereby granted, free of charge, to any person obtaining a7* copy of this software and associated documentation files (the "Software"),8* to deal in the Software without restriction, including without limitation9* the rights to use, copy, modify, merge, publish, distribute, sublicense,10* and/or sell copies of the Software, and to permit persons to whom the11* Software is furnished to do so, subject to the following conditions:12*13* The above copyright notice and this permission notice shall be included14* in all copies or substantial portions of the Software.15*16* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS17* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,18* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL19* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR20* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,21* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR22* OTHER DEALINGS IN THE SOFTWARE.23*/242526/**27* "Fake" GLX API implemented in terms of the XMesa*() functions.28*/29303132#define GLX_GLXEXT_PROTOTYPES33#include "GL/glx.h"3435#include <stdio.h>36#include <string.h>37#include <X11/Xmd.h>38#include <GL/glxproto.h>3940#include "xm_api.h"41#include "main/errors.h"42#include "util/u_math.h"43#include "util/u_memory.h"4445/* An "Atrribs/Attribs" typo was fixed in glxproto.h in Nov 2014.46* This is in case we don't have the updated header.47*/48#if !defined(X_GLXCreateContextAttribsARB) && \49defined(X_GLXCreateContextAtrribsARB)50#define X_GLXCreateContextAttribsARB X_GLXCreateContextAtrribsARB51#endif5253/* This indicates the client-side GLX API and GLX encoder version. */54#define CLIENT_MAJOR_VERSION 155#define CLIENT_MINOR_VERSION 4 /* but don't have 1.3's pbuffers, etc yet */5657/* This indicates the server-side GLX decoder version.58* GLX 1.4 indicates OpenGL 1.3 support59*/60#define SERVER_MAJOR_VERSION 161#define SERVER_MINOR_VERSION 46263/* Who implemented this GLX? */64#define VENDOR "Brian Paul"6566#define EXTENSIONS \67"GLX_MESA_copy_sub_buffer " \68"GLX_MESA_pixmap_colormap " \69"GLX_MESA_release_buffers " \70"GLX_ARB_create_context " \71"GLX_ARB_create_context_profile " \72"GLX_ARB_get_proc_address " \73"GLX_EXT_create_context_es_profile " \74"GLX_EXT_create_context_es2_profile " \75"GLX_EXT_texture_from_pixmap " \76"GLX_EXT_visual_info " \77"GLX_EXT_visual_rating " \78/*"GLX_SGI_video_sync "*/ \79"GLX_SGIX_fbconfig " \80"GLX_SGIX_pbuffer "8182#define DEFAULT_DIRECT GL_TRUE838485/** XXX this could be based on gallium's max texture size */86#define PBUFFER_MAX_SIZE 16384878889/**90* The GLXContext typedef is defined as a pointer to this structure.91*/92struct __GLXcontextRec93{94Display *currentDpy;95GLboolean isDirect;96GLXDrawable currentDrawable;97GLXDrawable currentReadable;98XID xid;99100XMesaContext xmesaContext;101};102103104105static pipe_tsd ContextTSD;106107/** Set current context for calling thread */108static void109SetCurrentContext(GLXContext c)110{111pipe_tsd_set(&ContextTSD, c);112}113114/** Get current context for calling thread */115static GLXContext116GetCurrentContext(void)117{118return pipe_tsd_get(&ContextTSD);119}120121122123/**********************************************************************/124/*** GLX Visual Code ***/125/**********************************************************************/126127#define DONT_CARE -1128129130static XMesaVisual *VisualTable = NULL;131static int NumVisuals = 0;132133134135/* Macro to handle c_class vs class field name in XVisualInfo struct */136#if defined(__cplusplus) || defined(c_plusplus)137#define CLASS c_class138#else139#define CLASS class140#endif141142143144/*145* Test if the given XVisualInfo is usable for Mesa rendering.146*/147static GLboolean148is_usable_visual( XVisualInfo *vinfo )149{150switch (vinfo->CLASS) {151case StaticGray:152case GrayScale:153/* Any StaticGray/GrayScale visual works in RGB or CI mode */154return GL_TRUE;155case StaticColor:156case PseudoColor:157/* Any StaticColor/PseudoColor visual of at least 4 bits */158if (vinfo->depth>=4) {159return GL_TRUE;160}161else {162return GL_FALSE;163}164case TrueColor:165case DirectColor:166/* Any depth of TrueColor or DirectColor works in RGB mode */167return GL_TRUE;168default:169/* This should never happen */170return GL_FALSE;171}172}173174175/*176* Given an XVisualInfo and RGB, Double, and Depth buffer flags, save the177* configuration in our list of GLX visuals.178*/179static XMesaVisual180save_glx_visual( Display *dpy, XVisualInfo *vinfo,181GLboolean rgbFlag, GLboolean alphaFlag, GLboolean dbFlag,182GLboolean stereoFlag,183GLint depth_size, GLint stencil_size,184GLint accumRedSize, GLint accumGreenSize,185GLint accumBlueSize, GLint accumAlphaSize,186GLint level, GLint numAuxBuffers, GLuint num_samples )187{188GLboolean ximageFlag = GL_TRUE;189XMesaVisual xmvis;190GLint i;191GLboolean comparePointers;192193if (!rgbFlag)194return NULL;195196if (dbFlag) {197/* Check if the MESA_BACK_BUFFER env var is set */198char *backbuffer = getenv("MESA_BACK_BUFFER");199if (backbuffer) {200if (backbuffer[0]=='p' || backbuffer[0]=='P') {201ximageFlag = GL_FALSE;202}203else if (backbuffer[0]=='x' || backbuffer[0]=='X') {204ximageFlag = GL_TRUE;205}206else {207_mesa_warning(NULL, "Mesa: invalid value for MESA_BACK_BUFFER environment variable, using an XImage.");208}209}210}211212if (stereoFlag) {213/* stereo not supported */214return NULL;215}216217if (stencil_size > 0 && depth_size > 0)218depth_size = 24;219220/* Comparing IDs uses less memory but sometimes fails. */221/* XXX revisit this after 3.0 is finished. */222if (getenv("MESA_GLX_VISUAL_HACK"))223comparePointers = GL_TRUE;224else225comparePointers = GL_FALSE;226227/* Force the visual to have an alpha channel */228if (rgbFlag && getenv("MESA_GLX_FORCE_ALPHA"))229alphaFlag = GL_TRUE;230231/* First check if a matching visual is already in the list */232for (i=0; i<NumVisuals; i++) {233XMesaVisual v = VisualTable[i];234if (v->display == dpy235&& v->mesa_visual.samples == num_samples236&& v->ximage_flag == ximageFlag237&& v->mesa_visual.doubleBufferMode == dbFlag238&& v->mesa_visual.stereoMode == stereoFlag239&& (v->mesa_visual.alphaBits > 0) == alphaFlag240&& (v->mesa_visual.depthBits >= depth_size || depth_size == 0)241&& (v->mesa_visual.stencilBits >= stencil_size || stencil_size == 0)242&& (v->mesa_visual.accumRedBits >= accumRedSize || accumRedSize == 0)243&& (v->mesa_visual.accumGreenBits >= accumGreenSize || accumGreenSize == 0)244&& (v->mesa_visual.accumBlueBits >= accumBlueSize || accumBlueSize == 0)245&& (v->mesa_visual.accumAlphaBits >= accumAlphaSize || accumAlphaSize == 0)) {246/* now either compare XVisualInfo pointers or visual IDs */247if ((!comparePointers && v->visinfo->visualid == vinfo->visualid)248|| (comparePointers && v->vishandle == vinfo)) {249return v;250}251}252}253254/* Create a new visual and add it to the list. */255256xmvis = XMesaCreateVisual( dpy, vinfo, rgbFlag, alphaFlag, dbFlag,257stereoFlag, ximageFlag,258depth_size, stencil_size,259accumRedSize, accumBlueSize,260accumBlueSize, accumAlphaSize, num_samples, level,261GLX_NONE_EXT );262if (xmvis) {263/* Save a copy of the pointer now so we can find this visual again264* if we need to search for it in find_glx_visual().265*/266xmvis->vishandle = vinfo;267/* Allocate more space for additional visual */268VisualTable = realloc(VisualTable, sizeof(XMesaVisual) * (NumVisuals + 1));269/* add xmvis to the list */270VisualTable[NumVisuals] = xmvis;271NumVisuals++;272}273return xmvis;274}275276277/**278* Return the default number of bits for the Z buffer.279* If defined, use the MESA_GLX_DEPTH_BITS env var value.280* Otherwise, use the DEFAULT_SOFTWARE_DEPTH_BITS constant.281* XXX probably do the same thing for stencil, accum, etc.282*/283static GLint284default_depth_bits(void)285{286int zBits;287const char *zEnv = getenv("MESA_GLX_DEPTH_BITS");288if (zEnv)289zBits = atoi(zEnv);290else291zBits = 24;292return zBits;293}294295static GLint296default_alpha_bits(void)297{298int aBits;299const char *aEnv = getenv("MESA_GLX_ALPHA_BITS");300if (aEnv)301aBits = atoi(aEnv);302else303aBits = 0;304return aBits;305}306307static GLint308default_accum_bits(void)309{310return 16;311}312313314315/*316* Create a GLX visual from a regular XVisualInfo.317* This is called when Fake GLX is given an XVisualInfo which wasn't318* returned by glXChooseVisual. Since this is the first time we're319* considering this visual we'll take a guess at reasonable values320* for depth buffer size, stencil size, accum size, etc.321* This is the best we can do with a client-side emulation of GLX.322*/323static XMesaVisual324create_glx_visual( Display *dpy, XVisualInfo *visinfo )325{326GLint zBits = default_depth_bits();327GLint accBits = default_accum_bits();328GLboolean alphaFlag = default_alpha_bits() > 0;329330if (is_usable_visual( visinfo )) {331/* Configure this visual as RGB, double-buffered, depth-buffered. */332/* This is surely wrong for some people's needs but what else */333/* can be done? They should use glXChooseVisual(). */334return save_glx_visual( dpy, visinfo,335GL_TRUE, /* rgb */336alphaFlag, /* alpha */337GL_TRUE, /* double */338GL_FALSE, /* stereo */339zBits,3408, /* stencil bits */341accBits, /* r */342accBits, /* g */343accBits, /* b */344accBits, /* a */3450, /* level */3460, /* numAux */3470 /* numSamples */348);349}350else {351_mesa_warning(NULL, "Mesa: error in glXCreateContext: bad visual\n");352return NULL;353}354}355356357358/*359* Find the GLX visual associated with an XVisualInfo.360*/361static XMesaVisual362find_glx_visual( Display *dpy, XVisualInfo *vinfo )363{364int i;365366/* try to match visual id */367for (i=0;i<NumVisuals;i++) {368if (VisualTable[i]->display==dpy369&& VisualTable[i]->visinfo->visualid == vinfo->visualid) {370return VisualTable[i];371}372}373374/* if that fails, try to match pointers */375for (i=0;i<NumVisuals;i++) {376if (VisualTable[i]->display==dpy && VisualTable[i]->vishandle==vinfo) {377return VisualTable[i];378}379}380381return NULL;382}383384385/**386* Try to get an X visual which matches the given arguments.387*/388static XVisualInfo *389get_visual( Display *dpy, int scr, unsigned int depth, int xclass )390{391XVisualInfo temp, *vis;392long mask;393int n;394unsigned int default_depth;395int default_class;396397mask = VisualScreenMask | VisualDepthMask | VisualClassMask;398temp.screen = scr;399temp.depth = depth;400temp.CLASS = xclass;401402default_depth = DefaultDepth(dpy,scr);403default_class = DefaultVisual(dpy,scr)->CLASS;404405if (depth==default_depth && xclass==default_class) {406/* try to get root window's visual */407temp.visualid = DefaultVisual(dpy,scr)->visualid;408mask |= VisualIDMask;409}410411vis = XGetVisualInfo( dpy, mask, &temp, &n );412413/* In case bits/pixel > 24, make sure color channels are still <=8 bits.414* An SGI Infinite Reality system, for example, can have 30bpp pixels:415* 10 bits per color channel. Mesa's limited to a max of 8 bits/channel.416*/417if (vis && depth > 24 && (xclass==TrueColor || xclass==DirectColor)) {418if (util_bitcount((GLuint) vis->red_mask ) <= 8 &&419util_bitcount((GLuint) vis->green_mask) <= 8 &&420util_bitcount((GLuint) vis->blue_mask ) <= 8) {421return vis;422}423else {424free((void *) vis);425return NULL;426}427}428429return vis;430}431432433/*434* Retrieve the value of the given environment variable and find435* the X visual which matches it.436* Input: dpy - the display437* screen - the screen number438* varname - the name of the environment variable439* Return: an XVisualInfo pointer to NULL if error.440*/441static XVisualInfo *442get_env_visual(Display *dpy, int scr, const char *varname)443{444char value[100], type[100];445int depth, xclass = -1;446XVisualInfo *vis;447448if (!getenv( varname )) {449return NULL;450}451452strncpy( value, getenv(varname), 100 );453value[99] = 0;454455sscanf( value, "%s %d", type, &depth );456457if (strcmp(type,"TrueColor")==0) xclass = TrueColor;458else if (strcmp(type,"DirectColor")==0) xclass = DirectColor;459else if (strcmp(type,"PseudoColor")==0) xclass = PseudoColor;460else if (strcmp(type,"StaticColor")==0) xclass = StaticColor;461else if (strcmp(type,"GrayScale")==0) xclass = GrayScale;462else if (strcmp(type,"StaticGray")==0) xclass = StaticGray;463464if (xclass>-1 && depth>0) {465vis = get_visual( dpy, scr, depth, xclass );466if (vis) {467return vis;468}469}470471_mesa_warning(NULL, "GLX unable to find visual class=%s, depth=%d.",472type, depth);473474return NULL;475}476477478479/*480* Select an X visual which satisfies the RGBA flag and minimum depth.481* Input: dpy,482* screen - X display and screen number483* min_depth - minimum visual depth484* preferred_class - preferred GLX visual class or DONT_CARE485* Return: pointer to an XVisualInfo or NULL.486*/487static XVisualInfo *488choose_x_visual( Display *dpy, int screen, int min_depth,489int preferred_class )490{491XVisualInfo *vis;492int xclass, visclass = 0;493int depth;494495/* First see if the MESA_RGB_VISUAL env var is defined */496vis = get_env_visual( dpy, screen, "MESA_RGB_VISUAL" );497if (vis) {498return vis;499}500/* Otherwise, search for a suitable visual */501if (preferred_class==DONT_CARE) {502for (xclass=0;xclass<6;xclass++) {503switch (xclass) {504case 0: visclass = TrueColor; break;505case 1: visclass = DirectColor; break;506case 2: visclass = PseudoColor; break;507case 3: visclass = StaticColor; break;508case 4: visclass = GrayScale; break;509case 5: visclass = StaticGray; break;510}511if (min_depth==0) {512/* start with shallowest */513for (depth=0;depth<=32;depth++) {514if (visclass==TrueColor && depth==8) {515/* Special case: try to get 8-bit PseudoColor before */516/* 8-bit TrueColor */517vis = get_visual( dpy, screen, 8, PseudoColor );518if (vis) {519return vis;520}521}522vis = get_visual( dpy, screen, depth, visclass );523if (vis) {524return vis;525}526}527}528else {529/* start with deepest */530for (depth=32;depth>=min_depth;depth--) {531if (visclass==TrueColor && depth==8) {532/* Special case: try to get 8-bit PseudoColor before */533/* 8-bit TrueColor */534vis = get_visual( dpy, screen, 8, PseudoColor );535if (vis) {536return vis;537}538}539vis = get_visual( dpy, screen, depth, visclass );540if (vis) {541return vis;542}543}544}545}546}547else {548/* search for a specific visual class */549switch (preferred_class) {550case GLX_TRUE_COLOR_EXT: visclass = TrueColor; break;551case GLX_DIRECT_COLOR_EXT: visclass = DirectColor; break;552case GLX_PSEUDO_COLOR_EXT: visclass = PseudoColor; break;553case GLX_STATIC_COLOR_EXT: visclass = StaticColor; break;554case GLX_GRAY_SCALE_EXT: visclass = GrayScale; break;555case GLX_STATIC_GRAY_EXT: visclass = StaticGray; break;556default: return NULL;557}558if (min_depth==0) {559/* start with shallowest */560for (depth=0;depth<=32;depth++) {561vis = get_visual( dpy, screen, depth, visclass );562if (vis) {563return vis;564}565}566}567else {568/* start with deepest */569for (depth=32;depth>=min_depth;depth--) {570vis = get_visual( dpy, screen, depth, visclass );571if (vis) {572return vis;573}574}575}576}577578/* didn't find a visual */579return NULL;580}581582583584585/**********************************************************************/586/*** Display-related functions ***/587/**********************************************************************/588589590/**591* Free all XMesaVisuals which are associated with the given display.592*/593static void594destroy_visuals_on_display(Display *dpy)595{596int i;597for (i = 0; i < NumVisuals; i++) {598if (VisualTable[i]->display == dpy) {599/* remove this visual */600int j;601free(VisualTable[i]);602for (j = i; j < NumVisuals - 1; j++)603VisualTable[j] = VisualTable[j + 1];604NumVisuals--;605}606}607}608609610/**611* Called from XCloseDisplay() to let us free our display-related data.612*/613static int614close_display_callback(Display *dpy, XExtCodes *codes)615{616xmesa_destroy_buffers_on_display(dpy);617destroy_visuals_on_display(dpy);618xmesa_close_display(dpy);619return 0;620}621622623/**624* Look for the named extension on given display and return a pointer625* to the _XExtension data, or NULL if extension not found.626*/627static _XExtension *628lookup_extension(Display *dpy, const char *extName)629{630_XExtension *ext;631for (ext = dpy->ext_procs; ext; ext = ext->next) {632if (ext->name && strcmp(ext->name, extName) == 0) {633return ext;634}635}636return NULL;637}638639640/**641* Whenever we're given a new Display pointer, call this function to642* register our close_display_callback function.643*/644static void645register_with_display(Display *dpy)646{647const char *extName = "MesaGLX";648_XExtension *ext;649650ext = lookup_extension(dpy, extName);651if (!ext) {652XExtCodes *c = XAddExtension(dpy);653ext = dpy->ext_procs; /* new extension is at head of list */654assert(c->extension == ext->codes.extension);655(void) c;656ext->name = strdup(extName);657ext->close_display = close_display_callback;658}659}660661662/**663* Fake an error.664*/665static int666generate_error(Display *dpy,667unsigned char error_code,668XID resourceid,669unsigned char minor_code,670Bool core)671{672XErrorHandler handler;673int major_opcode;674int first_event;675int first_error;676XEvent event;677678handler = XSetErrorHandler(NULL);679XSetErrorHandler(handler);680if (!handler) {681return 0;682}683684if (!XQueryExtension(dpy, GLX_EXTENSION_NAME, &major_opcode, &first_event, &first_error)) {685major_opcode = 0;686first_event = 0;687first_error = 0;688}689690if (!core) {691error_code += first_error;692}693694memset(&event, 0, sizeof event);695696event.xerror.type = X_Error;697event.xerror.display = dpy;698event.xerror.resourceid = resourceid;699event.xerror.serial = NextRequest(dpy) - 1;700event.xerror.error_code = error_code;701event.xerror.request_code = major_opcode;702event.xerror.minor_code = minor_code;703704return handler(dpy, &event.xerror);705}706707708/**********************************************************************/709/*** Begin Fake GLX API Functions ***/710/**********************************************************************/711712713/**714* Helper used by glXChooseVisual and glXChooseFBConfig.715* The fbConfig parameter must be GL_FALSE for the former and GL_TRUE for716* the later.717* In either case, the attribute list is terminated with the value 'None'.718*/719static XMesaVisual720choose_visual( Display *dpy, int screen, const int *list, GLboolean fbConfig )721{722const GLboolean rgbModeDefault = fbConfig;723const int *parselist;724XVisualInfo *vis;725int min_red=0, min_green=0, min_blue=0;726GLboolean rgb_flag = rgbModeDefault;727GLboolean alpha_flag = GL_FALSE;728GLboolean double_flag = GL_FALSE;729GLboolean stereo_flag = GL_FALSE;730GLint depth_size = 0;731GLint stencil_size = 0;732GLint accumRedSize = 0;733GLint accumGreenSize = 0;734GLint accumBlueSize = 0;735GLint accumAlphaSize = 0;736int level = 0;737int visual_type = DONT_CARE;738GLint caveat = DONT_CARE;739XMesaVisual xmvis = NULL;740int desiredVisualID = -1;741int numAux = 0;742GLint num_samples = 0;743744if (xmesa_init( dpy ) != 0) {745_mesa_warning(NULL, "Failed to initialize display");746return NULL;747}748749parselist = list;750751while (*parselist) {752753if (fbConfig &&754parselist[1] == GLX_DONT_CARE &&755parselist[0] != GLX_LEVEL) {756/* For glXChooseFBConfig(), skip attributes whose value is757* GLX_DONT_CARE, unless it's GLX_LEVEL (which can legitimately be758* a negative value).759*760* From page 17 (23 of the pdf) of the GLX 1.4 spec:761* GLX DONT CARE may be specified for all attributes except GLX LEVEL.762*/763parselist += 2;764continue;765}766767switch (*parselist) {768case GLX_USE_GL:769if (fbConfig) {770/* invalid token */771return NULL;772}773else {774/* skip */775parselist++;776}777break;778case GLX_BUFFER_SIZE:779parselist++;780parselist++;781break;782case GLX_LEVEL:783parselist++;784level = *parselist++;785break;786case GLX_RGBA:787if (fbConfig) {788/* invalid token */789return NULL;790}791else {792rgb_flag = GL_TRUE;793parselist++;794}795break;796case GLX_DOUBLEBUFFER:797parselist++;798if (fbConfig) {799double_flag = *parselist++;800}801else {802double_flag = GL_TRUE;803}804break;805case GLX_STEREO:806parselist++;807if (fbConfig) {808stereo_flag = *parselist++;809}810else {811stereo_flag = GL_TRUE;812}813break;814case GLX_AUX_BUFFERS:815parselist++;816numAux = *parselist++;817if (numAux > MAX_AUX_BUFFERS)818return NULL;819break;820case GLX_RED_SIZE:821parselist++;822min_red = *parselist++;823break;824case GLX_GREEN_SIZE:825parselist++;826min_green = *parselist++;827break;828case GLX_BLUE_SIZE:829parselist++;830min_blue = *parselist++;831break;832case GLX_ALPHA_SIZE:833parselist++;834{835GLint size = *parselist++;836alpha_flag = size ? GL_TRUE : GL_FALSE;837}838break;839case GLX_DEPTH_SIZE:840parselist++;841depth_size = *parselist++;842break;843case GLX_STENCIL_SIZE:844parselist++;845stencil_size = *parselist++;846break;847case GLX_ACCUM_RED_SIZE:848parselist++;849{850GLint size = *parselist++;851accumRedSize = MAX2( accumRedSize, size );852}853break;854case GLX_ACCUM_GREEN_SIZE:855parselist++;856{857GLint size = *parselist++;858accumGreenSize = MAX2( accumGreenSize, size );859}860break;861case GLX_ACCUM_BLUE_SIZE:862parselist++;863{864GLint size = *parselist++;865accumBlueSize = MAX2( accumBlueSize, size );866}867break;868case GLX_ACCUM_ALPHA_SIZE:869parselist++;870{871GLint size = *parselist++;872accumAlphaSize = MAX2( accumAlphaSize, size );873}874break;875876/*877* GLX_EXT_visual_info extension878*/879case GLX_X_VISUAL_TYPE_EXT:880parselist++;881visual_type = *parselist++;882break;883case GLX_TRANSPARENT_TYPE_EXT:884parselist++;885parselist++;886break;887case GLX_TRANSPARENT_INDEX_VALUE_EXT:888parselist++;889parselist++;890break;891case GLX_TRANSPARENT_RED_VALUE_EXT:892case GLX_TRANSPARENT_GREEN_VALUE_EXT:893case GLX_TRANSPARENT_BLUE_VALUE_EXT:894case GLX_TRANSPARENT_ALPHA_VALUE_EXT:895/* ignore */896parselist++;897parselist++;898break;899900/*901* GLX_EXT_visual_info extension902*/903case GLX_VISUAL_CAVEAT_EXT:904parselist++;905caveat = *parselist++; /* ignored for now */906break;907908/*909* GLX_ARB_multisample910*/911case GLX_SAMPLE_BUFFERS_ARB:912/* ignore */913parselist++;914parselist++;915break;916case GLX_SAMPLES_ARB:917parselist++;918num_samples = *parselist++;919break;920921/*922* FBConfig attribs.923*/924case GLX_RENDER_TYPE:925if (!fbConfig)926return NULL;927parselist++;928if (*parselist & GLX_RGBA_BIT) {929rgb_flag = GL_TRUE;930}931else if (*parselist & GLX_COLOR_INDEX_BIT) {932rgb_flag = GL_FALSE;933}934else if (*parselist == 0) {935rgb_flag = GL_TRUE;936}937parselist++;938break;939case GLX_DRAWABLE_TYPE:940if (!fbConfig)941return NULL;942parselist++;943if (*parselist & ~(GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT)) {944return NULL; /* bad bit */945}946parselist++;947break;948case GLX_FBCONFIG_ID:949case GLX_VISUAL_ID:950if (!fbConfig)951return NULL;952parselist++;953desiredVisualID = *parselist++;954break;955case GLX_X_RENDERABLE:956case GLX_MAX_PBUFFER_WIDTH:957case GLX_MAX_PBUFFER_HEIGHT:958case GLX_MAX_PBUFFER_PIXELS:959if (!fbConfig)960return NULL; /* invalid config option */961parselist += 2; /* ignore the parameter */962break;963964case GLX_BIND_TO_TEXTURE_RGB_EXT:965parselist++; /*skip*/966break;967case GLX_BIND_TO_TEXTURE_RGBA_EXT:968parselist++; /*skip*/969break;970case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:971parselist++; /*skip*/972break;973case GLX_BIND_TO_TEXTURE_TARGETS_EXT:974parselist++;975if (*parselist & ~(GLX_TEXTURE_1D_BIT_EXT |976GLX_TEXTURE_2D_BIT_EXT |977GLX_TEXTURE_RECTANGLE_BIT_EXT)) {978/* invalid bit */979return NULL;980}981break;982case GLX_Y_INVERTED_EXT:983parselist++; /*skip*/984break;985986case None:987/* end of list */988break;989990default:991/* undefined attribute */992_mesa_warning(NULL, "unexpected attrib 0x%x in choose_visual()",993*parselist);994return NULL;995}996}997998(void) caveat;9991000if (num_samples < 0) {1001_mesa_warning(NULL, "GLX_SAMPLES_ARB: number of samples must not be negative");1002return NULL;1003}10041005/*1006* Since we're only simulating the GLX extension this function will never1007* find any real GL visuals. Instead, all we can do is try to find an RGB1008* or CI visual of appropriate depth. Other requested attributes such as1009* double buffering, depth buffer, etc. will be associated with the X1010* visual and stored in the VisualTable[].1011*/1012if (desiredVisualID != -1) {1013/* try to get a specific visual, by visualID */1014XVisualInfo temp;1015int n;1016temp.visualid = desiredVisualID;1017temp.screen = screen;1018vis = XGetVisualInfo(dpy, VisualIDMask | VisualScreenMask, &temp, &n);1019if (vis) {1020/* give the visual some useful GLX attributes */1021double_flag = GL_TRUE;1022rgb_flag = GL_TRUE;1023}1024}1025else if (level==0) {1026/* normal color planes */1027/* Get an RGB visual */1028int min_rgb = min_red + min_green + min_blue;1029if (min_rgb>1 && min_rgb<8) {1030/* a special case to be sure we can get a monochrome visual */1031min_rgb = 1;1032}1033vis = choose_x_visual( dpy, screen, min_rgb, visual_type );1034}1035else {1036_mesa_warning(NULL, "overlay not supported");1037return NULL;1038}10391040if (vis) {1041/* Note: we're not exactly obeying the glXChooseVisual rules here.1042* When GLX_DEPTH_SIZE = 1 is specified we're supposed to choose the1043* largest depth buffer size, which is 32bits/value. Instead, we1044* return 16 to maintain performance with earlier versions of Mesa.1045*/1046if (stencil_size > 0)1047depth_size = 24; /* if Z and stencil, always use 24+8 format */1048else if (depth_size > 24)1049depth_size = 32;1050else if (depth_size > 16)1051depth_size = 24;1052else if (depth_size > 0) {1053depth_size = default_depth_bits();1054}10551056if (!alpha_flag) {1057alpha_flag = default_alpha_bits() > 0;1058}10591060/* we only support one size of stencil and accum buffers. */1061if (stencil_size > 0)1062stencil_size = 8;10631064if (accumRedSize > 0 ||1065accumGreenSize > 0 ||1066accumBlueSize > 0 ||1067accumAlphaSize > 0) {10681069accumRedSize =1070accumGreenSize =1071accumBlueSize = default_accum_bits();10721073accumAlphaSize = alpha_flag ? accumRedSize : 0;1074}10751076xmvis = save_glx_visual( dpy, vis, rgb_flag, alpha_flag, double_flag,1077stereo_flag, depth_size, stencil_size,1078accumRedSize, accumGreenSize,1079accumBlueSize, accumAlphaSize, level, numAux,1080num_samples );1081}10821083return xmvis;1084}108510861087PUBLIC XVisualInfo *1088glXChooseVisual( Display *dpy, int screen, int *list )1089{1090XMesaVisual xmvis;10911092/* register ourselves as an extension on this display */1093register_with_display(dpy);10941095xmvis = choose_visual(dpy, screen, list, GL_FALSE);1096if (xmvis) {1097/* create a new vishandle - the cached one may be stale */1098xmvis->vishandle = malloc(sizeof(XVisualInfo));1099if (xmvis->vishandle) {1100memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo));1101}1102return xmvis->vishandle;1103}1104else1105return NULL;1106}110711081109/**1110* Helper function used by other glXCreateContext functions.1111*/1112static GLXContext1113create_context(Display *dpy, XMesaVisual xmvis,1114XMesaContext shareCtx, Bool direct,1115unsigned major, unsigned minor,1116unsigned profileMask, unsigned contextFlags)1117{1118GLXContext glxCtx;11191120if (!dpy || !xmvis)1121return 0;11221123glxCtx = CALLOC_STRUCT(__GLXcontextRec);1124if (!glxCtx)1125return 0;11261127/* deallocate unused windows/buffers */1128#if 01129XMesaGarbageCollect();1130#endif11311132glxCtx->xmesaContext = XMesaCreateContext(xmvis, shareCtx, major, minor,1133profileMask, contextFlags);1134if (!glxCtx->xmesaContext) {1135free(glxCtx);1136return NULL;1137}11381139glxCtx->isDirect = DEFAULT_DIRECT;1140glxCtx->currentDpy = dpy;1141glxCtx->xid = (XID) glxCtx; /* self pointer */11421143return glxCtx;1144}114511461147PUBLIC GLXContext1148glXCreateContext( Display *dpy, XVisualInfo *visinfo,1149GLXContext shareCtx, Bool direct )1150{1151XMesaVisual xmvis;11521153xmvis = find_glx_visual( dpy, visinfo );1154if (!xmvis) {1155/* This visual wasn't found with glXChooseVisual() */1156xmvis = create_glx_visual( dpy, visinfo );1157if (!xmvis) {1158/* unusable visual */1159return NULL;1160}1161}11621163return create_context(dpy, xmvis,1164shareCtx ? shareCtx->xmesaContext : NULL,1165direct,11661, 0, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, 0x0);1167}116811691170/* GLX 1.3 and later */1171PUBLIC Bool1172glXMakeContextCurrent( Display *dpy, GLXDrawable draw,1173GLXDrawable read, GLXContext ctx )1174{1175GLXContext glxCtx = ctx;1176GLXContext current = GetCurrentContext();1177static boolean firsttime = 1, no_rast = 0;11781179if (firsttime) {1180no_rast = getenv("SP_NO_RAST") != NULL;1181firsttime = 0;1182}11831184if (ctx) {1185XMesaBuffer drawBuffer = NULL, readBuffer = NULL;1186XMesaContext xmctx = glxCtx->xmesaContext;11871188/* either both must be null, or both must be non-null */1189if (!draw != !read)1190return False;11911192if (draw) {1193/* Find the XMesaBuffer which corresponds to 'draw' */1194drawBuffer = XMesaFindBuffer( dpy, draw );1195if (!drawBuffer) {1196/* drawable must be a new window! */1197drawBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, draw );1198if (!drawBuffer) {1199/* Out of memory, or context/drawable depth mismatch */1200return False;1201}1202}1203}12041205if (read) {1206/* Find the XMesaBuffer which corresponds to 'read' */1207readBuffer = XMesaFindBuffer( dpy, read );1208if (!readBuffer) {1209/* drawable must be a new window! */1210readBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, read );1211if (!readBuffer) {1212/* Out of memory, or context/drawable depth mismatch */1213return False;1214}1215}1216}12171218if (no_rast && current == ctx)1219return True;12201221/* Now make current! */1222if (XMesaMakeCurrent2(xmctx, drawBuffer, readBuffer)) {1223ctx->currentDpy = dpy;1224ctx->currentDrawable = draw;1225ctx->currentReadable = read;1226SetCurrentContext(ctx);1227return True;1228}1229else {1230return False;1231}1232}1233else if (!ctx && !draw && !read) {1234/* release current context w/out assigning new one. */1235XMesaMakeCurrent2( NULL, NULL, NULL );1236SetCurrentContext(NULL);1237return True;1238}1239else {1240/* We were given an invalid set of arguments */1241return False;1242}1243}124412451246PUBLIC Bool1247glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx )1248{1249return glXMakeContextCurrent( dpy, drawable, drawable, ctx );1250}125112521253PUBLIC GLXContext1254glXGetCurrentContext(void)1255{1256return GetCurrentContext();1257}125812591260PUBLIC Display *1261glXGetCurrentDisplay(void)1262{1263GLXContext glxCtx = glXGetCurrentContext();12641265return glxCtx ? glxCtx->currentDpy : NULL;1266}126712681269PUBLIC Display *1270glXGetCurrentDisplayEXT(void)1271{1272return glXGetCurrentDisplay();1273}127412751276PUBLIC GLXDrawable1277glXGetCurrentDrawable(void)1278{1279GLXContext gc = glXGetCurrentContext();1280return gc ? gc->currentDrawable : 0;1281}128212831284PUBLIC GLXDrawable1285glXGetCurrentReadDrawable(void)1286{1287GLXContext gc = glXGetCurrentContext();1288return gc ? gc->currentReadable : 0;1289}129012911292PUBLIC GLXDrawable1293glXGetCurrentReadDrawableSGI(void)1294{1295return glXGetCurrentReadDrawable();1296}129712981299PUBLIC GLXPixmap1300glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, Pixmap pixmap )1301{1302XMesaVisual v;1303XMesaBuffer b;13041305v = find_glx_visual( dpy, visinfo );1306if (!v) {1307v = create_glx_visual( dpy, visinfo );1308if (!v) {1309/* unusable visual */1310return 0;1311}1312}13131314b = XMesaCreatePixmapBuffer( v, pixmap, 0 );1315if (!b) {1316return 0;1317}1318return b->ws.drawable;1319}132013211322/*** GLX_MESA_pixmap_colormap ***/13231324PUBLIC GLXPixmap1325glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo,1326Pixmap pixmap, Colormap cmap )1327{1328XMesaVisual v;1329XMesaBuffer b;13301331v = find_glx_visual( dpy, visinfo );1332if (!v) {1333v = create_glx_visual( dpy, visinfo );1334if (!v) {1335/* unusable visual */1336return 0;1337}1338}13391340b = XMesaCreatePixmapBuffer( v, pixmap, cmap );1341if (!b) {1342return 0;1343}1344return b->ws.drawable;1345}134613471348PUBLIC void1349glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap )1350{1351XMesaBuffer b = XMesaFindBuffer(dpy, pixmap);1352if (b) {1353XMesaDestroyBuffer(b);1354}1355else if (getenv("MESA_DEBUG")) {1356_mesa_warning(NULL, "Mesa: glXDestroyGLXPixmap: invalid pixmap\n");1357}1358}135913601361PUBLIC void1362glXCopyContext( Display *dpy, GLXContext src, GLXContext dst,1363unsigned long mask )1364{1365XMesaContext xm_src = src->xmesaContext;1366XMesaContext xm_dst = dst->xmesaContext;1367(void) dpy;1368if (GetCurrentContext() == src) {1369glFlush();1370}1371XMesaCopyContext(xm_src, xm_dst, mask);1372}137313741375PUBLIC Bool1376glXQueryExtension( Display *dpy, int *errorBase, int *eventBase )1377{1378int op, ev, err;1379/* Mesa's GLX isn't really an X extension but we try to act like one. */1380if (!XQueryExtension(dpy, GLX_EXTENSION_NAME, &op, &ev, &err))1381ev = err = 0;1382if (errorBase)1383*errorBase = err;1384if (eventBase)1385*eventBase = ev;1386return True; /* we're faking GLX so always return success */1387}138813891390PUBLIC void1391glXDestroyContext( Display *dpy, GLXContext ctx )1392{1393if (ctx) {1394GLXContext glxCtx = ctx;1395(void) dpy;1396XMesaDestroyContext( glxCtx->xmesaContext );1397XMesaGarbageCollect();1398free(glxCtx);1399}1400}140114021403PUBLIC Bool1404glXIsDirect( Display *dpy, GLXContext ctx )1405{1406return ctx ? ctx->isDirect : False;1407}1408140914101411PUBLIC void1412glXSwapBuffers( Display *dpy, GLXDrawable drawable )1413{1414XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable );1415static boolean firsttime = 1, no_rast = 0;14161417if (firsttime) {1418no_rast = getenv("SP_NO_RAST") != NULL;1419firsttime = 0;1420}14211422if (no_rast)1423return;14241425if (buffer) {1426XMesaSwapBuffers(buffer);1427}1428else if (getenv("MESA_DEBUG")) {1429_mesa_warning(NULL, "glXSwapBuffers: invalid drawable 0x%x\n",1430(int) drawable);1431}1432}1433143414351436/*** GLX_MESA_copy_sub_buffer ***/14371438PUBLIC void1439glXCopySubBufferMESA(Display *dpy, GLXDrawable drawable,1440int x, int y, int width, int height)1441{1442XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable );1443if (buffer) {1444XMesaCopySubBuffer(buffer, x, y, width, height);1445}1446else if (getenv("MESA_DEBUG")) {1447_mesa_warning(NULL, "Mesa: glXCopySubBufferMESA: invalid drawable\n");1448}1449}145014511452PUBLIC Bool1453glXQueryVersion( Display *dpy, int *maj, int *min )1454{1455(void) dpy;1456/* Return GLX version, not Mesa version */1457assert(CLIENT_MAJOR_VERSION == SERVER_MAJOR_VERSION);1458*maj = CLIENT_MAJOR_VERSION;1459*min = MIN2( CLIENT_MINOR_VERSION, SERVER_MINOR_VERSION );1460return True;1461}146214631464/*1465* Query the GLX attributes of the given XVisualInfo.1466*/1467static int1468get_config( XMesaVisual xmvis, int attrib, int *value, GLboolean fbconfig )1469{1470assert(xmvis);1471switch(attrib) {1472case GLX_USE_GL:1473if (fbconfig)1474return GLX_BAD_ATTRIBUTE;1475*value = (int) True;1476return 0;1477case GLX_BUFFER_SIZE:1478*value = xmvis->visinfo->depth;1479return 0;1480case GLX_LEVEL:1481*value = 0;1482return 0;1483case GLX_RGBA:1484if (fbconfig)1485return GLX_BAD_ATTRIBUTE;1486*value = True;1487return 0;1488case GLX_DOUBLEBUFFER:1489*value = (int) xmvis->mesa_visual.doubleBufferMode;1490return 0;1491case GLX_STEREO:1492*value = (int) xmvis->mesa_visual.stereoMode;1493return 0;1494case GLX_AUX_BUFFERS:1495*value = 0;1496return 0;1497case GLX_RED_SIZE:1498*value = xmvis->mesa_visual.redBits;1499return 0;1500case GLX_GREEN_SIZE:1501*value = xmvis->mesa_visual.greenBits;1502return 0;1503case GLX_BLUE_SIZE:1504*value = xmvis->mesa_visual.blueBits;1505return 0;1506case GLX_ALPHA_SIZE:1507*value = xmvis->mesa_visual.alphaBits;1508return 0;1509case GLX_DEPTH_SIZE:1510*value = xmvis->mesa_visual.depthBits;1511return 0;1512case GLX_STENCIL_SIZE:1513*value = xmvis->mesa_visual.stencilBits;1514return 0;1515case GLX_ACCUM_RED_SIZE:1516*value = xmvis->mesa_visual.accumRedBits;1517return 0;1518case GLX_ACCUM_GREEN_SIZE:1519*value = xmvis->mesa_visual.accumGreenBits;1520return 0;1521case GLX_ACCUM_BLUE_SIZE:1522*value = xmvis->mesa_visual.accumBlueBits;1523return 0;1524case GLX_ACCUM_ALPHA_SIZE:1525*value = xmvis->mesa_visual.accumAlphaBits;1526return 0;15271528/*1529* GLX_EXT_visual_info extension1530*/1531case GLX_X_VISUAL_TYPE_EXT:1532switch (xmvis->visinfo->CLASS) {1533case StaticGray: *value = GLX_STATIC_GRAY_EXT; return 0;1534case GrayScale: *value = GLX_GRAY_SCALE_EXT; return 0;1535case StaticColor: *value = GLX_STATIC_GRAY_EXT; return 0;1536case PseudoColor: *value = GLX_PSEUDO_COLOR_EXT; return 0;1537case TrueColor: *value = GLX_TRUE_COLOR_EXT; return 0;1538case DirectColor: *value = GLX_DIRECT_COLOR_EXT; return 0;1539}1540return 0;1541case GLX_TRANSPARENT_TYPE_EXT:1542/* normal planes */1543*value = GLX_NONE_EXT;1544return 0;1545case GLX_TRANSPARENT_INDEX_VALUE_EXT:1546/* undefined */1547return 0;1548case GLX_TRANSPARENT_RED_VALUE_EXT:1549/* undefined */1550return 0;1551case GLX_TRANSPARENT_GREEN_VALUE_EXT:1552/* undefined */1553return 0;1554case GLX_TRANSPARENT_BLUE_VALUE_EXT:1555/* undefined */1556return 0;1557case GLX_TRANSPARENT_ALPHA_VALUE_EXT:1558/* undefined */1559return 0;15601561/*1562* GLX_EXT_visual_info extension1563*/1564case GLX_VISUAL_CAVEAT_EXT:1565*value = GLX_NONE_EXT;1566return 0;15671568/*1569* GLX_ARB_multisample1570*/1571case GLX_SAMPLE_BUFFERS_ARB:1572*value = xmvis->mesa_visual.samples > 0;1573return 0;1574case GLX_SAMPLES_ARB:1575*value = xmvis->mesa_visual.samples;1576return 0;15771578/*1579* For FBConfigs:1580*/1581case GLX_SCREEN_EXT:1582if (!fbconfig)1583return GLX_BAD_ATTRIBUTE;1584*value = xmvis->visinfo->screen;1585break;1586case GLX_DRAWABLE_TYPE: /*SGIX too */1587if (!fbconfig)1588return GLX_BAD_ATTRIBUTE;1589*value = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT;1590break;1591case GLX_RENDER_TYPE_SGIX:1592if (!fbconfig)1593return GLX_BAD_ATTRIBUTE;1594*value = GLX_RGBA_BIT;1595break;1596case GLX_X_RENDERABLE_SGIX:1597if (!fbconfig)1598return GLX_BAD_ATTRIBUTE;1599*value = True; /* XXX really? */1600break;1601case GLX_FBCONFIG_ID_SGIX:1602if (!fbconfig)1603return GLX_BAD_ATTRIBUTE;1604*value = xmvis->visinfo->visualid;1605break;1606case GLX_MAX_PBUFFER_WIDTH:1607if (!fbconfig)1608return GLX_BAD_ATTRIBUTE;1609/* XXX should be same as ctx->Const.MaxRenderbufferSize */1610*value = DisplayWidth(xmvis->display, xmvis->visinfo->screen);1611break;1612case GLX_MAX_PBUFFER_HEIGHT:1613if (!fbconfig)1614return GLX_BAD_ATTRIBUTE;1615*value = DisplayHeight(xmvis->display, xmvis->visinfo->screen);1616break;1617case GLX_MAX_PBUFFER_PIXELS:1618if (!fbconfig)1619return GLX_BAD_ATTRIBUTE;1620*value = DisplayWidth(xmvis->display, xmvis->visinfo->screen) *1621DisplayHeight(xmvis->display, xmvis->visinfo->screen);1622break;1623case GLX_VISUAL_ID:1624if (!fbconfig)1625return GLX_BAD_ATTRIBUTE;1626*value = xmvis->visinfo->visualid;1627break;16281629case GLX_BIND_TO_TEXTURE_RGB_EXT:1630*value = True; /*XXX*/1631break;1632case GLX_BIND_TO_TEXTURE_RGBA_EXT:1633/* XXX review */1634*value = xmvis->mesa_visual.alphaBits > 0 ? True : False;1635break;1636case GLX_BIND_TO_MIPMAP_TEXTURE_EXT:1637*value = True; /*XXX*/1638break;1639case GLX_BIND_TO_TEXTURE_TARGETS_EXT:1640*value = (GLX_TEXTURE_1D_BIT_EXT |1641GLX_TEXTURE_2D_BIT_EXT |1642GLX_TEXTURE_RECTANGLE_BIT_EXT); /*XXX*/1643break;1644case GLX_Y_INVERTED_EXT:1645*value = True; /*XXX*/1646break;16471648default:1649return GLX_BAD_ATTRIBUTE;1650}1651return Success;1652}165316541655PUBLIC int1656glXGetConfig( Display *dpy, XVisualInfo *visinfo,1657int attrib, int *value )1658{1659XMesaVisual xmvis;1660int k;1661if (!dpy || !visinfo)1662return GLX_BAD_ATTRIBUTE;16631664xmvis = find_glx_visual( dpy, visinfo );1665if (!xmvis) {1666/* this visual wasn't obtained with glXChooseVisual */1667xmvis = create_glx_visual( dpy, visinfo );1668if (!xmvis) {1669/* this visual can't be used for GL rendering */1670if (attrib==GLX_USE_GL) {1671*value = (int) False;1672return 0;1673}1674else {1675return GLX_BAD_VISUAL;1676}1677}1678}16791680k = get_config(xmvis, attrib, value, GL_FALSE);1681return k;1682}168316841685PUBLIC void1686glXWaitGL( void )1687{1688XMesaContext xmesa = XMesaGetCurrentContext();1689XMesaFlush( xmesa );1690}1691169216931694PUBLIC void1695glXWaitX( void )1696{1697XMesaContext xmesa = XMesaGetCurrentContext();1698XMesaFlush( xmesa );1699}170017011702static const char *1703get_extensions( void )1704{1705return EXTENSIONS;1706}1707170817091710/* GLX 1.1 and later */1711PUBLIC const char *1712glXQueryExtensionsString( Display *dpy, int screen )1713{1714(void) dpy;1715(void) screen;1716return get_extensions();1717}1718171917201721/* GLX 1.1 and later */1722PUBLIC const char *1723glXQueryServerString( Display *dpy, int screen, int name )1724{1725static char version[1000];1726sprintf(version, "%d.%d %s",1727SERVER_MAJOR_VERSION, SERVER_MINOR_VERSION, xmesa_get_name());17281729(void) dpy;1730(void) screen;17311732switch (name) {1733case GLX_EXTENSIONS:1734return get_extensions();1735case GLX_VENDOR:1736return VENDOR;1737case GLX_VERSION:1738return version;1739default:1740return NULL;1741}1742}1743174417451746/* GLX 1.1 and later */1747PUBLIC const char *1748glXGetClientString( Display *dpy, int name )1749{1750static char version[1000];1751sprintf(version, "%d.%d %s", CLIENT_MAJOR_VERSION,1752CLIENT_MINOR_VERSION, xmesa_get_name());17531754(void) dpy;17551756switch (name) {1757case GLX_EXTENSIONS:1758return get_extensions();1759case GLX_VENDOR:1760return VENDOR;1761case GLX_VERSION:1762return version;1763default:1764return NULL;1765}1766}1767176817691770/*1771* GLX 1.3 and later1772*/177317741775PUBLIC int1776glXGetFBConfigAttrib(Display *dpy, GLXFBConfig config,1777int attribute, int *value)1778{1779XMesaVisual v = (XMesaVisual) config;1780(void) dpy;1781(void) config;17821783if (!dpy || !config || !value)1784return -1;17851786return get_config(v, attribute, value, GL_TRUE);1787}178817891790PUBLIC GLXFBConfig *1791glXGetFBConfigs( Display *dpy, int screen, int *nelements )1792{1793XVisualInfo *visuals, visTemplate;1794const long visMask = VisualScreenMask;1795int i;17961797/* Get list of all X visuals */1798visTemplate.screen = screen;1799visuals = XGetVisualInfo(dpy, visMask, &visTemplate, nelements);1800if (*nelements > 0) {1801XMesaVisual *results = malloc(*nelements * sizeof(XMesaVisual));1802if (!results) {1803*nelements = 0;1804return NULL;1805}1806for (i = 0; i < *nelements; i++) {1807results[i] = create_glx_visual(dpy, visuals + i);1808if (!results[i]) {1809*nelements = i;1810break;1811}1812}1813return (GLXFBConfig *) results;1814}1815return NULL;1816}181718181819PUBLIC GLXFBConfig *1820glXChooseFBConfig(Display *dpy, int screen,1821const int *attribList, int *nitems)1822{1823XMesaVisual xmvis;18241825/* register ourselves as an extension on this display */1826register_with_display(dpy);18271828if (!attribList || !attribList[0]) {1829/* return list of all configs (per GLX_SGIX_fbconfig spec) */1830return glXGetFBConfigs(dpy, screen, nitems);1831}18321833xmvis = choose_visual(dpy, screen, attribList, GL_TRUE);1834if (xmvis) {1835GLXFBConfig *config = malloc(sizeof(XMesaVisual));1836if (!config) {1837*nitems = 0;1838return NULL;1839}1840*nitems = 1;1841config[0] = (GLXFBConfig) xmvis;1842return (GLXFBConfig *) config;1843}1844else {1845*nitems = 0;1846return NULL;1847}1848}184918501851PUBLIC XVisualInfo *1852glXGetVisualFromFBConfig( Display *dpy, GLXFBConfig config )1853{1854if (dpy && config) {1855XMesaVisual xmvis = (XMesaVisual) config;1856#if 01857return xmvis->vishandle;1858#else1859/* create a new vishandle - the cached one may be stale */1860xmvis->vishandle = malloc(sizeof(XVisualInfo));1861if (xmvis->vishandle) {1862memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo));1863}1864return xmvis->vishandle;1865#endif1866}1867else {1868return NULL;1869}1870}187118721873PUBLIC GLXWindow1874glXCreateWindow(Display *dpy, GLXFBConfig config, Window win,1875const int *attribList)1876{1877XMesaVisual xmvis = (XMesaVisual) config;1878XMesaBuffer xmbuf;1879if (!xmvis)1880return 0;18811882xmbuf = XMesaCreateWindowBuffer(xmvis, win);1883if (!xmbuf)1884return 0;18851886(void) dpy;1887(void) attribList; /* Ignored in GLX 1.3 */18881889return win; /* A hack for now */1890}189118921893PUBLIC void1894glXDestroyWindow( Display *dpy, GLXWindow window )1895{1896XMesaBuffer b = XMesaFindBuffer(dpy, (Drawable) window);1897if (b)1898XMesaDestroyBuffer(b);1899/* don't destroy X window */1900}190119021903/* XXX untested */1904PUBLIC GLXPixmap1905glXCreatePixmap(Display *dpy, GLXFBConfig config, Pixmap pixmap,1906const int *attribList)1907{1908XMesaVisual v = (XMesaVisual) config;1909XMesaBuffer b;1910const int *attr;1911int target = 0, format = 0, mipmap = 0;1912int value;19131914if (!dpy || !config || !pixmap)1915return 0;19161917for (attr = attribList; attr && *attr; attr++) {1918switch (*attr) {1919case GLX_TEXTURE_FORMAT_EXT:1920attr++;1921switch (*attr) {1922case GLX_TEXTURE_FORMAT_NONE_EXT:1923case GLX_TEXTURE_FORMAT_RGB_EXT:1924case GLX_TEXTURE_FORMAT_RGBA_EXT:1925format = *attr;1926break;1927default:1928/* error */1929return 0;1930}1931break;1932case GLX_TEXTURE_TARGET_EXT:1933attr++;1934switch (*attr) {1935case GLX_TEXTURE_1D_EXT:1936case GLX_TEXTURE_2D_EXT:1937case GLX_TEXTURE_RECTANGLE_EXT:1938target = *attr;1939break;1940default:1941/* error */1942return 0;1943}1944break;1945case GLX_MIPMAP_TEXTURE_EXT:1946attr++;1947if (*attr)1948mipmap = 1;1949break;1950default:1951/* error */1952return 0;1953}1954}19551956if (format == GLX_TEXTURE_FORMAT_RGB_EXT) {1957if (get_config(v, GLX_BIND_TO_TEXTURE_RGB_EXT,1958&value, GL_TRUE) != Success1959|| !value) {1960return 0; /* error! */1961}1962}1963else if (format == GLX_TEXTURE_FORMAT_RGBA_EXT) {1964if (get_config(v, GLX_BIND_TO_TEXTURE_RGBA_EXT,1965&value, GL_TRUE) != Success1966|| !value) {1967return 0; /* error! */1968}1969}1970if (mipmap) {1971if (get_config(v, GLX_BIND_TO_MIPMAP_TEXTURE_EXT,1972&value, GL_TRUE) != Success1973|| !value) {1974return 0; /* error! */1975}1976}1977if (target == GLX_TEXTURE_1D_EXT) {1978if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT,1979&value, GL_TRUE) != Success1980|| (value & GLX_TEXTURE_1D_BIT_EXT) == 0) {1981return 0; /* error! */1982}1983}1984else if (target == GLX_TEXTURE_2D_EXT) {1985if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT,1986&value, GL_TRUE) != Success1987|| (value & GLX_TEXTURE_2D_BIT_EXT) == 0) {1988return 0; /* error! */1989}1990}1991if (target == GLX_TEXTURE_RECTANGLE_EXT) {1992if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT,1993&value, GL_TRUE) != Success1994|| (value & GLX_TEXTURE_RECTANGLE_BIT_EXT) == 0) {1995return 0; /* error! */1996}1997}19981999if (format || target || mipmap) {2000/* texture from pixmap */2001b = XMesaCreatePixmapTextureBuffer(v, pixmap, 0, format, target, mipmap);2002}2003else {2004b = XMesaCreatePixmapBuffer( v, pixmap, 0 );2005}2006if (!b) {2007return 0;2008}20092010return pixmap;2011}201220132014PUBLIC void2015glXDestroyPixmap( Display *dpy, GLXPixmap pixmap )2016{2017XMesaBuffer b = XMesaFindBuffer(dpy, (Drawable)pixmap);2018if (b)2019XMesaDestroyBuffer(b);2020/* don't destroy X pixmap */2021}202220232024PUBLIC GLXPbuffer2025glXCreatePbuffer(Display *dpy, GLXFBConfig config, const int *attribList)2026{2027XMesaVisual xmvis = (XMesaVisual) config;2028XMesaBuffer xmbuf;2029const int *attrib;2030int width = 0, height = 0;2031GLboolean useLargest = GL_FALSE, preserveContents = GL_FALSE;20322033(void) dpy;20342035for (attrib = attribList; *attrib; attrib++) {2036switch (*attrib) {2037case GLX_PBUFFER_WIDTH:2038attrib++;2039width = *attrib;2040break;2041case GLX_PBUFFER_HEIGHT:2042attrib++;2043height = *attrib;2044break;2045case GLX_PRESERVED_CONTENTS:2046attrib++;2047preserveContents = *attrib;2048break;2049case GLX_LARGEST_PBUFFER:2050attrib++;2051useLargest = *attrib;2052break;2053default:2054return 0;2055}2056}20572058if (width == 0 || height == 0)2059return 0;20602061if (width > PBUFFER_MAX_SIZE || height > PBUFFER_MAX_SIZE) {2062/* If allocation would have failed and GLX_LARGEST_PBUFFER is set,2063* allocate the largest possible buffer.2064*/2065if (useLargest) {2066width = PBUFFER_MAX_SIZE;2067height = PBUFFER_MAX_SIZE;2068}2069}20702071xmbuf = XMesaCreatePBuffer( xmvis, 0, width, height);2072/* A GLXPbuffer handle must be an X Drawable because that's what2073* glXMakeCurrent takes.2074*/2075if (xmbuf) {2076xmbuf->largestPbuffer = useLargest;2077xmbuf->preservedContents = preserveContents;2078return (GLXPbuffer) xmbuf->ws.drawable;2079}2080else {2081return 0;2082}2083}208420852086PUBLIC void2087glXDestroyPbuffer( Display *dpy, GLXPbuffer pbuf )2088{2089XMesaBuffer b = XMesaFindBuffer(dpy, pbuf);2090if (b) {2091XMesaDestroyBuffer(b);2092}2093}209420952096PUBLIC void2097glXQueryDrawable(Display *dpy, GLXDrawable draw, int attribute,2098unsigned int *value)2099{2100GLuint width, height;2101XMesaBuffer xmbuf = XMesaFindBuffer(dpy, draw);2102if (!xmbuf) {2103generate_error(dpy, GLXBadDrawable, draw, X_GLXGetDrawableAttributes, False);2104return;2105}21062107/* make sure buffer's dimensions are up to date */2108xmesa_get_window_size(dpy, xmbuf, &width, &height);21092110switch (attribute) {2111case GLX_WIDTH:2112*value = width;2113break;2114case GLX_HEIGHT:2115*value = height;2116break;2117case GLX_PRESERVED_CONTENTS:2118*value = xmbuf->preservedContents;2119break;2120case GLX_LARGEST_PBUFFER:2121*value = xmbuf->largestPbuffer;2122break;2123case GLX_FBCONFIG_ID:2124*value = xmbuf->xm_visual->visinfo->visualid;2125return;2126case GLX_TEXTURE_FORMAT_EXT:2127*value = xmbuf->TextureFormat;2128break;2129case GLX_TEXTURE_TARGET_EXT:2130*value = xmbuf->TextureTarget;2131break;2132case GLX_MIPMAP_TEXTURE_EXT:2133*value = xmbuf->TextureMipmap;2134break;21352136default:2137generate_error(dpy, BadValue, 0, X_GLXCreateContextAttribsARB, true);2138return;2139}2140}214121422143PUBLIC GLXContext2144glXCreateNewContext( Display *dpy, GLXFBConfig config,2145int renderType, GLXContext shareCtx, Bool direct )2146{2147XMesaVisual xmvis = (XMesaVisual) config;21482149if (!dpy || !config ||2150(renderType != GLX_RGBA_TYPE && renderType != GLX_COLOR_INDEX_TYPE))2151return 0;21522153return create_context(dpy, xmvis,2154shareCtx ? shareCtx->xmesaContext : NULL,2155direct,21561, 0, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, 0x0);2157}215821592160PUBLIC int2161glXQueryContext( Display *dpy, GLXContext ctx, int attribute, int *value )2162{2163GLXContext glxCtx = ctx;2164XMesaContext xmctx = glxCtx->xmesaContext;21652166(void) dpy;2167(void) ctx;21682169switch (attribute) {2170case GLX_FBCONFIG_ID:2171*value = xmctx->xm_visual->visinfo->visualid;2172break;2173case GLX_RENDER_TYPE:2174*value = GLX_RGBA_TYPE;2175break;2176case GLX_SCREEN:2177*value = 0;2178return Success;2179default:2180return GLX_BAD_ATTRIBUTE;2181}2182return 0;2183}218421852186PUBLIC void2187glXSelectEvent( Display *dpy, GLXDrawable drawable, unsigned long mask )2188{2189XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);2190if (xmbuf)2191xmbuf->selectedEvents = mask;2192}219321942195PUBLIC void2196glXGetSelectedEvent(Display *dpy, GLXDrawable drawable, unsigned long *mask)2197{2198XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);2199if (xmbuf)2200*mask = xmbuf->selectedEvents;2201else2202*mask = 0;2203}2204220522062207/*** GLX_SGI_swap_control ***/22082209PUBLIC int2210glXSwapIntervalSGI(int interval)2211{2212(void) interval;2213return 0;2214}2215221622172218/*** GLX_SGI_video_sync ***/22192220static unsigned int FrameCounter = 0;22212222PUBLIC int2223glXGetVideoSyncSGI(unsigned int *count)2224{2225/* this is a bogus implementation */2226*count = FrameCounter++;2227return 0;2228}22292230PUBLIC int2231glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count)2232{2233if (divisor <= 0 || remainder < 0)2234return GLX_BAD_VALUE;2235/* this is a bogus implementation */2236FrameCounter++;2237while (FrameCounter % divisor != remainder)2238FrameCounter++;2239*count = FrameCounter;2240return 0;2241}2242224322442245/*** GLX_SGI_make_current_read ***/22462247PUBLIC Bool2248glXMakeCurrentReadSGI(Display *dpy, GLXDrawable draw, GLXDrawable read,2249GLXContext ctx)2250{2251return glXMakeContextCurrent( dpy, draw, read, ctx );2252}22532254/* not used2255static GLXDrawable2256glXGetCurrentReadDrawableSGI(void)2257{2258return 0;2259}2260*/226122622263/*** GLX_SGIX_video_source ***/2264#if defined(_VL_H)22652266PUBLIC GLXVideoSourceSGIX2267glXCreateGLXVideoSourceSGIX(Display *dpy, int screen, VLServer server,2268VLPath path, int nodeClass, VLNode drainNode)2269{2270(void) dpy;2271(void) screen;2272(void) server;2273(void) path;2274(void) nodeClass;2275(void) drainNode;2276return 0;2277}22782279PUBLIC void2280glXDestroyGLXVideoSourceSGIX(Display *dpy, GLXVideoSourceSGIX src)2281{2282(void) dpy;2283(void) src;2284}22852286#endif228722882289/*** GLX_EXT_import_context ***/22902291PUBLIC void2292glXFreeContextEXT(Display *dpy, GLXContext context)2293{2294(void) dpy;2295(void) context;2296}22972298PUBLIC GLXContextID2299glXGetContextIDEXT(const GLXContext context)2300{2301(void) context;2302return 0;2303}23042305PUBLIC GLXContext2306glXImportContextEXT(Display *dpy, GLXContextID contextID)2307{2308(void) dpy;2309(void) contextID;2310return 0;2311}23122313PUBLIC int2314glXQueryContextInfoEXT(Display *dpy, GLXContext context, int attribute,2315int *value)2316{2317(void) dpy;2318(void) context;2319(void) attribute;2320(void) value;2321return 0;2322}2323232423252326/*** GLX_SGIX_fbconfig ***/23272328PUBLIC int2329glXGetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config,2330int attribute, int *value)2331{2332return glXGetFBConfigAttrib(dpy, config, attribute, value);2333}23342335PUBLIC GLXFBConfigSGIX *2336glXChooseFBConfigSGIX(Display *dpy, int screen, int *attrib_list,2337int *nelements)2338{2339return (GLXFBConfig *) glXChooseFBConfig(dpy, screen,2340attrib_list, nelements);2341}234223432344PUBLIC GLXPixmap2345glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config,2346Pixmap pixmap)2347{2348XMesaVisual xmvis = (XMesaVisual) config;2349XMesaBuffer xmbuf = XMesaCreatePixmapBuffer(xmvis, pixmap, 0);2350return xmbuf->ws.drawable; /* need to return an X ID */2351}235223532354PUBLIC GLXContext2355glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config,2356int renderType, GLXContext shareCtx,2357Bool direct)2358{2359XMesaVisual xmvis = (XMesaVisual) config;23602361if (!dpy || !config ||2362(renderType != GLX_RGBA_TYPE && renderType != GLX_COLOR_INDEX_TYPE))2363return 0;23642365return create_context(dpy, xmvis,2366shareCtx ? shareCtx->xmesaContext : NULL,2367direct,23681, 0, GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB, 0x0);2369}237023712372PUBLIC XVisualInfo *2373glXGetVisualFromFBConfigSGIX(Display *dpy, GLXFBConfigSGIX config)2374{2375return glXGetVisualFromFBConfig(dpy, config);2376}237723782379PUBLIC GLXFBConfigSGIX2380glXGetFBConfigFromVisualSGIX(Display *dpy, XVisualInfo *vis)2381{2382XMesaVisual xmvis = find_glx_visual(dpy, vis);2383if (!xmvis) {2384/* This visual wasn't found with glXChooseVisual() */2385xmvis = create_glx_visual(dpy, vis);2386}23872388return (GLXFBConfigSGIX) xmvis;2389}2390239123922393/*** GLX_SGIX_pbuffer ***/23942395PUBLIC GLXPbufferSGIX2396glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config,2397unsigned int width, unsigned int height,2398int *attribList)2399{2400XMesaVisual xmvis = (XMesaVisual) config;2401XMesaBuffer xmbuf;2402const int *attrib;2403GLboolean useLargest = GL_FALSE, preserveContents = GL_FALSE;24042405(void) dpy;24062407for (attrib = attribList; attrib && *attrib; attrib++) {2408switch (*attrib) {2409case GLX_PRESERVED_CONTENTS_SGIX:2410attrib++;2411preserveContents = *attrib; /* ignored */2412break;2413case GLX_LARGEST_PBUFFER_SGIX:2414attrib++;2415useLargest = *attrib; /* ignored */2416break;2417default:2418return 0;2419}2420}24212422/* not used at this time */2423(void) useLargest;2424(void) preserveContents;24252426xmbuf = XMesaCreatePBuffer( xmvis, 0, width, height);2427/* A GLXPbuffer handle must be an X Drawable because that's what2428* glXMakeCurrent takes.2429*/2430return (GLXPbuffer) xmbuf->ws.drawable;2431}243224332434PUBLIC void2435glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf)2436{2437XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf);2438if (xmbuf) {2439XMesaDestroyBuffer(xmbuf);2440}2441}244224432444PUBLIC void2445glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute,2446unsigned int *value)2447{2448const XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf);24492450if (!xmbuf) {2451/* Generate GLXBadPbufferSGIX for bad pbuffer */2452return;2453}24542455switch (attribute) {2456case GLX_PRESERVED_CONTENTS_SGIX:2457*value = True;2458break;2459case GLX_LARGEST_PBUFFER_SGIX:2460*value = xmesa_buffer_width(xmbuf) * xmesa_buffer_height(xmbuf);2461break;2462case GLX_WIDTH_SGIX:2463*value = xmesa_buffer_width(xmbuf);2464break;2465case GLX_HEIGHT_SGIX:2466*value = xmesa_buffer_height(xmbuf);2467break;2468case GLX_EVENT_MASK_SGIX:2469*value = 0; /* XXX might be wrong */2470break;2471default:2472*value = 0;2473}2474}247524762477PUBLIC void2478glXSelectEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long mask)2479{2480XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);2481if (xmbuf) {2482/* Note: we'll never generate clobber events */2483xmbuf->selectedEvents = mask;2484}2485}248624872488PUBLIC void2489glXGetSelectedEventSGIX(Display *dpy, GLXDrawable drawable,2490unsigned long *mask)2491{2492XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable);2493if (xmbuf) {2494*mask = xmbuf->selectedEvents;2495}2496else {2497*mask = 0;2498}2499}2500250125022503/*** GLX_SGI_cushion ***/25042505PUBLIC void2506glXCushionSGI(Display *dpy, Window win, float cushion)2507{2508(void) dpy;2509(void) win;2510(void) cushion;2511}2512251325142515/*** GLX_SGIX_video_resize ***/25162517PUBLIC int2518glXBindChannelToWindowSGIX(Display *dpy, int screen, int channel,2519Window window)2520{2521(void) dpy;2522(void) screen;2523(void) channel;2524(void) window;2525return 0;2526}25272528PUBLIC int2529glXChannelRectSGIX(Display *dpy, int screen, int channel,2530int x, int y, int w, int h)2531{2532(void) dpy;2533(void) screen;2534(void) channel;2535(void) x;2536(void) y;2537(void) w;2538(void) h;2539return 0;2540}25412542PUBLIC int2543glXQueryChannelRectSGIX(Display *dpy, int screen, int channel,2544int *x, int *y, int *w, int *h)2545{2546(void) dpy;2547(void) screen;2548(void) channel;2549(void) x;2550(void) y;2551(void) w;2552(void) h;2553return 0;2554}25552556PUBLIC int2557glXQueryChannelDeltasSGIX(Display *dpy, int screen, int channel,2558int *dx, int *dy, int *dw, int *dh)2559{2560(void) dpy;2561(void) screen;2562(void) channel;2563(void) dx;2564(void) dy;2565(void) dw;2566(void) dh;2567return 0;2568}25692570PUBLIC int2571glXChannelRectSyncSGIX(Display *dpy, int screen, int channel, GLenum synctype)2572{2573(void) dpy;2574(void) screen;2575(void) channel;2576(void) synctype;2577return 0;2578}2579258025812582/*** GLX_SGIX_dmbuffer **/25832584#if defined(_DM_BUFFER_H_)2585PUBLIC Bool2586glXAssociateDMPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuffer,2587DMparams *params, DMbuffer dmbuffer)2588{2589(void) dpy;2590(void) pbuffer;2591(void) params;2592(void) dmbuffer;2593return False;2594}2595#endif259625972598/*** GLX_SUN_get_transparent_index ***/25992600PUBLIC Status2601glXGetTransparentIndexSUN(Display *dpy, Window overlay, Window underlay,2602unsigned long *pTransparent)2603{2604(void) dpy;2605(void) overlay;2606(void) underlay;2607(void) pTransparent;2608return 0;2609}2610261126122613/*** GLX_MESA_release_buffers ***/26142615/*2616* Release the depth, stencil, accum buffers attached to a GLXDrawable2617* (a window or pixmap) prior to destroying the GLXDrawable.2618*/2619PUBLIC Bool2620glXReleaseBuffersMESA( Display *dpy, GLXDrawable d )2621{2622XMesaBuffer b = XMesaFindBuffer(dpy, d);2623if (b) {2624XMesaDestroyBuffer(b);2625return True;2626}2627return False;2628}26292630/*** GLX_EXT_texture_from_pixmap ***/26312632PUBLIC void2633glXBindTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer,2634const int *attrib_list)2635{2636XMesaBuffer b = XMesaFindBuffer(dpy, drawable);2637if (b)2638XMesaBindTexImage(dpy, b, buffer, attrib_list);2639}26402641PUBLIC void2642glXReleaseTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer)2643{2644XMesaBuffer b = XMesaFindBuffer(dpy, drawable);2645if (b)2646XMesaReleaseTexImage(dpy, b, buffer);2647}2648264926502651/*** GLX_ARB_create_context ***/265226532654GLXContext2655glXCreateContextAttribsARB(Display *dpy, GLXFBConfig config,2656GLXContext shareCtx, Bool direct,2657const int *attrib_list)2658{2659XMesaVisual xmvis = (XMesaVisual) config;2660int majorVersion = 1, minorVersion = 0;2661int contextFlags = 0x0;2662int profileMask = GLX_CONTEXT_CORE_PROFILE_BIT_ARB;2663int renderType = GLX_RGBA_TYPE;2664unsigned i;2665Bool done = False;2666const int contextFlagsAll = (GLX_CONTEXT_DEBUG_BIT_ARB |2667GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB);2668GLXContext ctx;26692670/* parse attrib_list */2671for (i = 0; !done && attrib_list && attrib_list[i]; i++) {2672switch (attrib_list[i]) {2673case GLX_CONTEXT_MAJOR_VERSION_ARB:2674majorVersion = attrib_list[++i];2675break;2676case GLX_CONTEXT_MINOR_VERSION_ARB:2677minorVersion = attrib_list[++i];2678break;2679case GLX_CONTEXT_FLAGS_ARB:2680contextFlags = attrib_list[++i];2681break;2682case GLX_CONTEXT_PROFILE_MASK_ARB:2683profileMask = attrib_list[++i];2684break;2685case GLX_RENDER_TYPE:2686renderType = attrib_list[++i];2687break;2688case 0:2689/* end of list */2690done = True;2691break;2692default:2693/* bad attribute */2694generate_error(dpy, BadValue, 0, X_GLXCreateContextAttribsARB, True);2695return NULL;2696}2697}26982699/* check contextFlags */2700if (contextFlags & ~contextFlagsAll) {2701generate_error(dpy, BadValue, 0, X_GLXCreateContextAttribsARB, True);2702return NULL;2703}27042705/* check profileMask */2706if (profileMask != GLX_CONTEXT_CORE_PROFILE_BIT_ARB &&2707profileMask != GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB &&2708profileMask != GLX_CONTEXT_ES_PROFILE_BIT_EXT) {2709generate_error(dpy, GLXBadProfileARB, 0, X_GLXCreateContextAttribsARB, False);2710return NULL;2711}27122713/* check renderType */2714if (renderType != GLX_RGBA_TYPE &&2715renderType != GLX_COLOR_INDEX_TYPE) {2716generate_error(dpy, BadValue, 0, X_GLXCreateContextAttribsARB, True);2717return NULL;2718}27192720/* check version */2721if (majorVersion <= 0 ||2722minorVersion < 0 ||2723(profileMask != GLX_CONTEXT_ES_PROFILE_BIT_EXT &&2724((majorVersion == 1 && minorVersion > 5) ||2725(majorVersion == 2 && minorVersion > 1) ||2726(majorVersion == 3 && minorVersion > 3) ||2727(majorVersion == 4 && minorVersion > 5) ||2728majorVersion > 4))) {2729generate_error(dpy, BadMatch, 0, X_GLXCreateContextAttribsARB, True);2730return NULL;2731}2732if (profileMask == GLX_CONTEXT_ES_PROFILE_BIT_EXT &&2733((majorVersion == 1 && minorVersion > 1) ||2734(majorVersion == 2 && minorVersion > 0) ||2735(majorVersion == 3 && minorVersion > 1) ||2736majorVersion > 3)) {2737/* GLX_EXT_create_context_es2_profile says nothing to justifying a2738* different error code for invalid ES versions, but this is what NVIDIA2739* does and piglit expects.2740*/2741generate_error(dpy, GLXBadProfileARB, 0, X_GLXCreateContextAttribsARB, False);2742return NULL;2743}27442745if ((contextFlags & GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB) &&2746majorVersion < 3) {2747generate_error(dpy, BadMatch, 0, X_GLXCreateContextAttribsARB, True);2748return NULL;2749}27502751if (renderType == GLX_COLOR_INDEX_TYPE && majorVersion >= 3) {2752generate_error(dpy, BadMatch, 0, X_GLXCreateContextAttribsARB, True);2753return NULL;2754}27552756ctx = create_context(dpy, xmvis,2757shareCtx ? shareCtx->xmesaContext : NULL,2758direct,2759majorVersion, minorVersion,2760profileMask, contextFlags);2761if (!ctx) {2762generate_error(dpy, GLXBadFBConfig, 0, X_GLXCreateContextAttribsARB, False);2763}27642765return ctx;2766}276727682769