/*
* Mesa 3-D graphics library
- * Version: 7.6
*
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
* Copyright (C) 2009 VMware, Inc. All Rights Reserved.
* 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
- * THE AUTHORS 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.
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
*/
#define GLX_GLXEXT_PROTOTYPES
#include "GL/glx.h"
+#include <stdio.h>
+#include <string.h>
+#include <X11/Xmd.h>
+#include <GL/glxproto.h>
+
#include "xm_api.h"
+#include "main/imports.h"
+#include "main/errors.h"
+#include "util/u_math.h"
+/* An "Atrribs/Attribs" typo was fixed in glxproto.h in Nov 2014.
+ * This is in case we don't have the updated header.
+ */
+#if !defined(X_GLXCreateContextAttribsARB) && \
+ defined(X_GLXCreateContextAtrribsARB)
+#define X_GLXCreateContextAttribsARB X_GLXCreateContextAtrribsARB
+#endif
/* This indicates the client-side GLX API and GLX encoder version. */
#define CLIENT_MAJOR_VERSION 1
"GLX_ARB_create_context " \
"GLX_ARB_create_context_profile " \
"GLX_ARB_get_proc_address " \
+ "GLX_EXT_create_context_es_profile " \
+ "GLX_EXT_create_context_es2_profile " \
"GLX_EXT_texture_from_pixmap " \
"GLX_EXT_visual_info " \
"GLX_EXT_visual_rating " \
GLint depth_size, GLint stencil_size,
GLint accumRedSize, GLint accumGreenSize,
GLint accumBlueSize, GLint accumAlphaSize,
- GLint level, GLint numAuxBuffers )
+ GLint level, GLint numAuxBuffers, GLuint num_samples )
{
GLboolean ximageFlag = GL_TRUE;
XMesaVisual xmvis;
if (dbFlag) {
/* Check if the MESA_BACK_BUFFER env var is set */
- char *backbuffer = _mesa_getenv("MESA_BACK_BUFFER");
+ char *backbuffer = getenv("MESA_BACK_BUFFER");
if (backbuffer) {
if (backbuffer[0]=='p' || backbuffer[0]=='P') {
ximageFlag = GL_FALSE;
/* Comparing IDs uses less memory but sometimes fails. */
/* XXX revisit this after 3.0 is finished. */
- if (_mesa_getenv("MESA_GLX_VISUAL_HACK"))
+ if (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"))
+ if (rgbFlag && getenv("MESA_GLX_FORCE_ALPHA"))
alphaFlag = GL_TRUE;
/* First check if a matching visual is already in the list */
if (v->display == dpy
&& v->mesa_visual.level == level
&& v->mesa_visual.numAuxBuffers == numAuxBuffers
+ && v->mesa_visual.samples == num_samples
&& v->ximage_flag == ximageFlag
&& v->mesa_visual.rgbMode == rgbFlag
&& v->mesa_visual.doubleBufferMode == dbFlag
stereoFlag, ximageFlag,
depth_size, stencil_size,
accumRedSize, accumBlueSize,
- accumBlueSize, accumAlphaSize, 0, level,
+ accumBlueSize, accumAlphaSize, num_samples, level,
GLX_NONE_EXT );
if (xmvis) {
/* Save a copy of the pointer now so we can find this visual again
*/
xmvis->vishandle = vinfo;
/* Allocate more space for additional visual */
- VisualTable = (XMesaVisual *) _mesa_realloc( VisualTable,
- sizeof(XMesaVisual) * NumVisuals,
- sizeof(XMesaVisual) * (NumVisuals + 1));
+ VisualTable = realloc(VisualTable, sizeof(XMesaVisual) * (NumVisuals + 1));
/* add xmvis to the list */
VisualTable[NumVisuals] = xmvis;
NumVisuals++;
default_depth_bits(void)
{
int zBits;
- const char *zEnv = _mesa_getenv("MESA_GLX_DEPTH_BITS");
+ const char *zEnv = getenv("MESA_GLX_DEPTH_BITS");
if (zEnv)
zBits = atoi(zEnv);
else
default_alpha_bits(void)
{
int aBits;
- const char *aEnv = _mesa_getenv("MESA_GLX_ALPHA_BITS");
+ const char *aEnv = getenv("MESA_GLX_ALPHA_BITS");
if (aEnv)
aBits = atoi(aEnv);
else
accBits, /* b */
accBits, /* a */
0, /* level */
- 0 /* numAux */
+ 0, /* numAux */
+ 0 /* numSamples */
);
}
else {
* 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) {
+ if (util_bitcount((GLuint) vis->red_mask ) <= 8 &&
+ util_bitcount((GLuint) vis->green_mask) <= 8 &&
+ util_bitcount((GLuint) vis->blue_mask ) <= 8) {
return vis;
}
else {
int depth, xclass = -1;
XVisualInfo *vis;
- if (!_mesa_getenv( varname )) {
+ if (!getenv( varname )) {
return NULL;
}
- strncpy( value, _mesa_getenv(varname), 100 );
+ strncpy( value, getenv(varname), 100 );
value[99] = 0;
sscanf( value, "%s %d", type, &depth );
{
xmesa_destroy_buffers_on_display(dpy);
destroy_visuals_on_display(dpy);
+ xmesa_close_display(dpy);
return 0;
}
ext = dpy->ext_procs; /* new extension is at head of list */
assert(c->extension == ext->codes.extension);
(void) c;
- ext->name = _mesa_strdup(extName);
+ ext->name = strdup(extName);
ext->close_display = close_display_callback;
}
}
+/**
+ * Fake an error.
+ */
+static int
+generate_error(Display *dpy,
+ unsigned char error_code,
+ XID resourceid,
+ unsigned char minor_code,
+ Bool core)
+{
+ XErrorHandler handler;
+ int major_opcode;
+ int first_event;
+ int first_error;
+ XEvent event;
+
+ handler = XSetErrorHandler(NULL);
+ XSetErrorHandler(handler);
+ if (!handler) {
+ return 0;
+ }
+
+ if (!XQueryExtension(dpy, GLX_EXTENSION_NAME, &major_opcode, &first_event, &first_error)) {
+ major_opcode = 0;
+ first_event = 0;
+ first_error = 0;
+ }
+
+ if (!core) {
+ error_code += first_error;
+ }
+
+ memset(&event, 0, sizeof event);
+
+ event.xerror.type = X_Error;
+ event.xerror.display = dpy;
+ event.xerror.resourceid = resourceid;
+ event.xerror.serial = NextRequest(dpy) - 1;
+ event.xerror.error_code = error_code;
+ event.xerror.request_code = major_opcode;
+ event.xerror.minor_code = minor_code;
+
+ return handler(dpy, &event.xerror);
+}
+
+
/**********************************************************************/
/*** Begin Fake GLX API Functions ***/
/**********************************************************************/
XMesaVisual xmvis = NULL;
int desiredVisualID = -1;
int numAux = 0;
+ GLint num_samples = 0;
- xmesa_init( dpy );
+ if (xmesa_init( dpy ) != 0) {
+ _mesa_warning(NULL, "Failed to initialize display");
+ return NULL;
+ }
parselist = list;
* GLX_ARB_multisample
*/
case GLX_SAMPLE_BUFFERS_ARB:
+ /* ignore */
+ parselist++;
+ parselist++;
+ break;
case GLX_SAMPLES_ARB:
parselist++;
- if (*parselist++ != 0) {
- /* ms not supported */
- return NULL;
- }
+ num_samples = *parselist++;
break;
/*
parselist += 2; /* ignore the parameter */
break;
-#ifdef GLX_EXT_texture_from_pixmap
case GLX_BIND_TO_TEXTURE_RGB_EXT:
parselist++; /*skip*/
break;
case GLX_Y_INVERTED_EXT:
parselist++; /*skip*/
break;
-#endif
case None:
/* end of list */
(void) caveat;
+ if (num_samples < 0) {
+ _mesa_warning(NULL, "GLX_SAMPLES_ARB: number of samples must not be negative");
+ return NULL;
+ }
/*
* Since we're only simulating the GLX extension this function will never
xmvis = save_glx_visual( dpy, vis, rgb_flag, alpha_flag, double_flag,
stereo_flag, depth_size, stencil_size,
accumRedSize, accumGreenSize,
- accumBlueSize, accumAlphaSize, level, numAux );
+ accumBlueSize, accumAlphaSize, level, numAux,
+ num_samples );
}
return xmvis;
xmvis = choose_visual(dpy, screen, list, GL_FALSE);
if (xmvis) {
/* create a new vishandle - the cached one may be stale */
- xmvis->vishandle = (XVisualInfo *) malloc(sizeof(XVisualInfo));
+ xmvis->vishandle = malloc(sizeof(XVisualInfo));
if (xmvis->vishandle) {
memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo));
}
if (b) {
XMesaDestroyBuffer(b);
}
- else if (_mesa_getenv("MESA_DEBUG")) {
+ else if (getenv("MESA_DEBUG")) {
_mesa_warning(NULL, "Mesa: glXDestroyGLXPixmap: invalid pixmap\n");
}
}
PUBLIC void
glXDestroyContext( Display *dpy, GLXContext ctx )
{
- GLXContext glxCtx = ctx;
- (void) dpy;
- MakeCurrent_PrevContext = 0;
- MakeCurrent_PrevDrawable = 0;
- MakeCurrent_PrevReadable = 0;
- MakeCurrent_PrevDrawBuffer = 0;
- MakeCurrent_PrevReadBuffer = 0;
- XMesaDestroyContext( glxCtx->xmesaContext );
- XMesaGarbageCollect();
- free(glxCtx);
+ if (ctx) {
+ GLXContext glxCtx = ctx;
+ (void) dpy;
+ MakeCurrent_PrevContext = 0;
+ MakeCurrent_PrevDrawable = 0;
+ MakeCurrent_PrevReadable = 0;
+ MakeCurrent_PrevDrawBuffer = 0;
+ MakeCurrent_PrevReadBuffer = 0;
+ XMesaDestroyContext( glxCtx->xmesaContext );
+ XMesaGarbageCollect();
+ free(glxCtx);
+ }
}
PUBLIC Bool
glXIsDirect( Display *dpy, GLXContext ctx )
{
- GLXContext glxCtx = ctx;
- (void) ctx;
- return glxCtx->isDirect;
+ return ctx ? ctx->isDirect : False;
}
if (buffer) {
XMesaSwapBuffers(buffer);
}
- else if (_mesa_getenv("MESA_DEBUG")) {
+ else if (getenv("MESA_DEBUG")) {
_mesa_warning(NULL, "glXSwapBuffers: invalid drawable 0x%x\n",
(int) drawable);
}
if (buffer) {
XMesaCopySubBuffer(buffer, x, y, width, height);
}
- else if (_mesa_getenv("MESA_DEBUG")) {
+ else if (getenv("MESA_DEBUG")) {
_mesa_warning(NULL, "Mesa: glXCopySubBufferMESA: invalid drawable\n");
}
}
static int
get_config( XMesaVisual xmvis, int attrib, int *value, GLboolean fbconfig )
{
- ASSERT(xmvis);
+ assert(xmvis);
switch(attrib) {
case GLX_USE_GL:
if (fbconfig)
* GLX_ARB_multisample
*/
case GLX_SAMPLE_BUFFERS_ARB:
- *value = 0;
+ *value = xmvis->mesa_visual.sampleBuffers;
return 0;
case GLX_SAMPLES_ARB:
- *value = 0;
+ *value = xmvis->mesa_visual.samples;
return 0;
/*
case GLX_MAX_PBUFFER_WIDTH:
if (!fbconfig)
return GLX_BAD_ATTRIBUTE;
- /* XXX or MAX_WIDTH? */
+ /* XXX should be same as ctx->Const.MaxRenderbufferSize */
*value = DisplayWidth(xmvis->display, xmvis->visinfo->screen);
break;
case GLX_MAX_PBUFFER_HEIGHT:
*value = xmvis->visinfo->visualid;
break;
-#ifdef GLX_EXT_texture_from_pixmap
case GLX_BIND_TO_TEXTURE_RGB_EXT:
*value = True; /*XXX*/
break;
case GLX_Y_INVERTED_EXT:
*value = True; /*XXX*/
break;
-#endif
default:
return GLX_BAD_ATTRIBUTE;
visTemplate.screen = screen;
visuals = XGetVisualInfo(dpy, visMask, &visTemplate, nelements);
if (*nelements > 0) {
- XMesaVisual *results;
- results = (XMesaVisual *) malloc(*nelements * sizeof(XMesaVisual));
+ XMesaVisual *results = malloc(*nelements * sizeof(XMesaVisual));
if (!results) {
*nelements = 0;
return NULL;
xmvis = choose_visual(dpy, screen, attribList, GL_TRUE);
if (xmvis) {
- GLXFBConfig *config = (GLXFBConfig *) malloc(sizeof(XMesaVisual));
+ GLXFBConfig *config = malloc(sizeof(XMesaVisual));
if (!config) {
*nitems = 0;
return NULL;
return xmvis->vishandle;
#else
/* create a new vishandle - the cached one may be stale */
- xmvis->vishandle = (XVisualInfo *) malloc(sizeof(XVisualInfo));
+ xmvis->vishandle = malloc(sizeof(XVisualInfo));
if (xmvis->vishandle) {
memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo));
}
{
GLuint width, height;
XMesaBuffer xmbuf = XMesaFindBuffer(dpy, draw);
- if (!xmbuf)
+ if (!xmbuf) {
+ generate_error(dpy, GLXBadDrawable, draw, X_GLXGetDrawableAttributes, False);
return;
+ }
/* make sure buffer's dimensions are up to date */
xmesa_get_window_size(dpy, xmbuf, &width, &height);
case GLX_FBCONFIG_ID:
*value = xmbuf->xm_visual->visinfo->visualid;
return;
-#ifdef GLX_EXT_texture_from_pixmap
case GLX_TEXTURE_FORMAT_EXT:
*value = xmbuf->TextureFormat;
break;
case GLX_MIPMAP_TEXTURE_EXT:
*value = xmbuf->TextureMipmap;
break;
-#endif
default:
- return; /* raise BadValue error */
+ generate_error(dpy, BadValue, 0, X_GLXCreateContextAttribsARB, true);
+ return;
}
}
}
-PUBLIC int
+PUBLIC void
glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute,
unsigned int *value)
{
if (!xmbuf) {
/* Generate GLXBadPbufferSGIX for bad pbuffer */
- return 0;
+ return;
}
switch (attribute) {
default:
*value = 0;
}
- return 0;
}
#endif
-/*** GLX_SGIX_swap_group ***/
-
-PUBLIC void
-glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable, GLXDrawable member)
-{
- (void) dpy;
- (void) drawable;
- (void) member;
-}
-
-
-
-/*** GLX_SGIX_swap_barrier ***/
-
-PUBLIC void
-glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable, int barrier)
-{
- (void) dpy;
- (void) drawable;
- (void) barrier;
-}
-
-PUBLIC Bool
-glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max)
-{
- (void) dpy;
- (void) screen;
- (void) max;
- return False;
-}
-
-
-
/*** GLX_SUN_get_transparent_index ***/
PUBLIC Status
glXGetTransparentIndexSUN(Display *dpy, Window overlay, Window underlay,
- long *pTransparent)
+ unsigned long *pTransparent)
{
(void) dpy;
(void) overlay;
/*** GLX_ARB_create_context ***/
+
GLXContext
glXCreateContextAttribsARB(Display *dpy, GLXFBConfig config,
GLXContext shareCtx, Bool direct,
Bool done = False;
const int contextFlagsAll = (GLX_CONTEXT_DEBUG_BIT_ARB |
GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB);
+ GLXContext ctx;
/* parse attrib_list */
for (i = 0; !done && attrib_list && attrib_list[i]; i++) {
break;
default:
/* bad attribute */
- /* XXX generate BadValue X Error */
+ generate_error(dpy, BadValue, 0, X_GLXCreateContextAttribsARB, True);
return NULL;
}
}
/* check contextFlags */
if (contextFlags & ~contextFlagsAll) {
- return NULL; /* generate BadValue X Error */
+ generate_error(dpy, BadValue, 0, X_GLXCreateContextAttribsARB, True);
+ return NULL;
}
/* check profileMask */
if (profileMask != GLX_CONTEXT_CORE_PROFILE_BIT_ARB &&
- profileMask != GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB) {
- return NULL; /* generate BadValue X Error */
+ profileMask != GLX_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB &&
+ profileMask != GLX_CONTEXT_ES_PROFILE_BIT_EXT) {
+ generate_error(dpy, GLXBadProfileARB, 0, X_GLXCreateContextAttribsARB, False);
+ return NULL;
}
- /* check version (generate BadMatch if bad) */
- switch (majorVersion) {
- case 1:
- if (minorVersion < 0 || minorVersion > 5)
- return NULL;
- break;
- case 2:
- if (minorVersion < 0 || minorVersion > 1)
- return NULL;
- break;
- case 3:
- if (minorVersion < 0 || minorVersion > 2)
- return NULL;
- break;
- case 4:
- if (minorVersion < 0 || minorVersion > 0)
- return NULL;
- break;
- default:
+ /* check renderType */
+ if (renderType != GLX_RGBA_TYPE &&
+ renderType != GLX_COLOR_INDEX_TYPE) {
+ generate_error(dpy, BadValue, 0, X_GLXCreateContextAttribsARB, True);
+ return NULL;
+ }
+
+ /* check version */
+ if (majorVersion <= 0 ||
+ minorVersion < 0 ||
+ (profileMask != GLX_CONTEXT_ES_PROFILE_BIT_EXT &&
+ ((majorVersion == 1 && minorVersion > 5) ||
+ (majorVersion == 2 && minorVersion > 1) ||
+ (majorVersion == 3 && minorVersion > 3) ||
+ (majorVersion == 4 && minorVersion > 5) ||
+ majorVersion > 4))) {
+ generate_error(dpy, BadMatch, 0, X_GLXCreateContextAttribsARB, True);
+ return NULL;
+ }
+ if (profileMask == GLX_CONTEXT_ES_PROFILE_BIT_EXT &&
+ ((majorVersion == 1 && minorVersion > 1) ||
+ (majorVersion == 2 && minorVersion > 0) ||
+ (majorVersion == 3 && minorVersion > 1) ||
+ majorVersion > 3)) {
+ /* GLX_EXT_create_context_es2_profile says nothing to justifying a
+ * different error code for invalid ES versions, but this is what NVIDIA
+ * does and piglit expects.
+ */
+ generate_error(dpy, GLXBadProfileARB, 0, X_GLXCreateContextAttribsARB, False);
return NULL;
}
if ((contextFlags & GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB) &&
- majorVersion < 3)
- return NULL; /* generate GLXBadProfileARB */
+ majorVersion < 3) {
+ generate_error(dpy, BadMatch, 0, X_GLXCreateContextAttribsARB, True);
+ return NULL;
+ }
+
+ if (renderType == GLX_COLOR_INDEX_TYPE && majorVersion >= 3) {
+ generate_error(dpy, BadMatch, 0, X_GLXCreateContextAttribsARB, True);
+ return NULL;
+ }
- if (renderType == GLX_COLOR_INDEX_TYPE && majorVersion >= 3)
- return NULL; /* generate BadMatch */
+ ctx = create_context(dpy, xmvis,
+ shareCtx ? shareCtx->xmesaContext : NULL,
+ direct,
+ majorVersion, minorVersion,
+ profileMask, contextFlags);
+ if (!ctx) {
+ generate_error(dpy, GLXBadFBConfig, 0, X_GLXCreateContextAttribsARB, False);
+ }
- return create_context(dpy, xmvis,
- shareCtx ? shareCtx->xmesaContext : NULL,
- direct,
- majorVersion, minorVersion,
- profileMask, contextFlags);
+ return ctx;
}