diff options
Diffstat (limited to 'src/glx/glx_pbuffer.c')
-rw-r--r-- | src/glx/glx_pbuffer.c | 914 |
1 files changed, 914 insertions, 0 deletions
diff --git a/src/glx/glx_pbuffer.c b/src/glx/glx_pbuffer.c new file mode 100644 index 0000000000..b8d0f21bf0 --- /dev/null +++ b/src/glx/glx_pbuffer.c @@ -0,0 +1,914 @@ +/* + * (C) Copyright IBM Corporation 2004 + * 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 + * on the rights to use, copy, modify, merge, publish, distribute, sub + * license, 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 (including the next + * paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL + * IBM AND/OR THEIR SUPPLIERS 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. + */ + +/** + * \file glx_pbuffer.c + * Implementation of pbuffer related functions. + * + * \author Ian Romanick <idr@us.ibm.com> + */ + +#include <inttypes.h> +#include "glxclient.h" +#include <X11/extensions/extutil.h> +#include <X11/extensions/Xext.h> +#include <assert.h> +#include <string.h> +#include "glxextensions.h" + +#ifdef GLX_USE_APPLEGL +#include <pthread.h> +#include "apple_glx_drawable.h" +#include "glx_error.h" +#endif + +#define WARN_ONCE_GLX_1_3(a, b) { \ + static int warned=1; \ + if(warned) { \ + warn_GLX_1_3((a), b ); \ + warned=0; \ + } \ + } + +/** + * Emit a warning when clients use GLX 1.3 functions on pre-1.3 systems. + */ +static void +warn_GLX_1_3(Display * dpy, const char *function_name) +{ + __GLXdisplayPrivate *priv = __glXInitialize(dpy); + + if (priv->minorVersion < 3) { + fprintf(stderr, + "WARNING: Application calling GLX 1.3 function \"%s\" " + "when GLX 1.3 is not supported! This is an application bug!\n", + function_name); + } +} + +#ifndef GLX_USE_APPLEGL +/** + * Change a drawable's attribute. + * + * This function is used to implement \c glXSelectEvent and + * \c glXSelectEventSGIX. + * + * \note + * This function dynamically determines whether to use the SGIX_pbuffer + * version of the protocol or the GLX 1.3 version of the protocol. + * + * \todo + * This function needs to be modified to work with direct-rendering drivers. + */ +static void +ChangeDrawableAttribute(Display * dpy, GLXDrawable drawable, + const CARD32 * attribs, size_t num_attribs) +{ + __GLXdisplayPrivate *priv = __glXInitialize(dpy); + CARD32 *output; + CARD8 opcode; + + if ((dpy == NULL) || (drawable == 0)) { + return; + } + + opcode = __glXSetupForCommand(dpy); + if (!opcode) + return; + + LockDisplay(dpy); + + if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) { + xGLXChangeDrawableAttributesReq *req; + + GetReqExtra(GLXChangeDrawableAttributes, 8 + (8 * num_attribs), req); + output = (CARD32 *) (req + 1); + + req->reqType = opcode; + req->glxCode = X_GLXChangeDrawableAttributes; + req->drawable = drawable; + req->numAttribs = (CARD32) num_attribs; + } + else { + xGLXVendorPrivateWithReplyReq *vpreq; + + GetReqExtra(GLXVendorPrivateWithReply, 4 + (8 * num_attribs), vpreq); + output = (CARD32 *) (vpreq + 1); + + vpreq->reqType = opcode; + vpreq->glxCode = X_GLXVendorPrivateWithReply; + vpreq->vendorCode = X_GLXvop_ChangeDrawableAttributesSGIX; + + output[0] = (CARD32) drawable; + output++; + } + + (void) memcpy(output, attribs, sizeof(CARD32) * 2 * num_attribs); + + UnlockDisplay(dpy); + SyncHandle(); + + return; +} + + +#ifdef GLX_DIRECT_RENDERING +static GLenum +determineTextureTarget(const int *attribs, int numAttribs) +{ + GLenum target = 0; + int i; + + for (i = 0; i < numAttribs; i++) { + if (attribs[2 * i] == GLX_TEXTURE_TARGET_EXT) { + switch (attribs[2 * i + 1]) { + case GLX_TEXTURE_2D_EXT: + target = GL_TEXTURE_2D; + break; + case GLX_TEXTURE_RECTANGLE_EXT: + target = GL_TEXTURE_RECTANGLE_ARB; + break; + } + } + } + + return target; +} + +static GLenum +determineTextureFormat(const int *attribs, int numAttribs) +{ + int i; + + for (i = 0; i < numAttribs; i++) { + if (attribs[2 * i] == GLX_TEXTURE_FORMAT_EXT) + return attribs[2 * i + 1]; + } + + return 0; +} + +static void +CreateDRIDrawable(Display *dpy, const __GLcontextModes *fbconfig, + XID drawable, XID glxdrawable, + const int *attrib_list, size_t num_attribs) +{ + __GLXdisplayPrivate *const priv = __glXInitialize(dpy); + __GLXDRIdrawable *pdraw; + __GLXscreenConfigs *psc; + + psc = &priv->screenConfigs[fbconfig->screen]; + if (psc->driScreen == NULL) + return; + + pdraw = psc->driScreen->createDrawable(psc, drawable, + glxdrawable, fbconfig); + if (pdraw == NULL) { + fprintf(stderr, "failed to create drawable\n"); + return; + } + + if (__glxHashInsert(psc->drawHash, glxdrawable, pdraw)) { + (*pdraw->destroyDrawable) (pdraw); + return; /* FIXME: Check what we're supposed to do here... */ + } + + pdraw->textureTarget = determineTextureTarget(attrib_list, num_attribs); + pdraw->textureFormat = determineTextureFormat(attrib_list, num_attribs); +} + +static void +DestroyDRIDrawable(Display *dpy, GLXDrawable drawable, int destroy_xdrawable) +{ + int screen; + __GLXdisplayPrivate *const priv = __glXInitialize(dpy); + __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); + __GLXscreenConfigs *psc = &priv->screenConfigs[screen]; + + if (pdraw != NULL) { + if (destroy_xdrawable) + XFreePixmap(psc->dpy, pdraw->xDrawable); + (*pdraw->destroyDrawable) (pdraw); + __glxHashDelete(psc->drawHash, drawable); + } +} + +#else + +static void +CreateDRIDrawable(Display *dpy, const __GLcontextModes * fbconfig, + XID drawable, XID glxdrawable, + const int *attrib_list, size_t num_attribs) +{ +} + +static void +DestroyDRIDrawable(Display *dpy, GLXDrawable drawable, int destroy_xdrawable) +{ +} + +#endif + +/** + * Get a drawable's attribute. + * + * This function is used to implement \c glXGetSelectedEvent and + * \c glXGetSelectedEventSGIX. + * + * \note + * This function dynamically determines whether to use the SGIX_pbuffer + * version of the protocol or the GLX 1.3 version of the protocol. + * + * \todo + * The number of attributes returned is likely to be small, probably less than + * 10. Given that, this routine should try to use an array on the stack to + * capture the reply rather than always calling Xmalloc. + * + * \todo + * This function needs to be modified to work with direct-rendering drivers. + */ +static int +GetDrawableAttribute(Display * dpy, GLXDrawable drawable, + int attribute, unsigned int *value) +{ + __GLXdisplayPrivate *priv; + xGLXGetDrawableAttributesReply reply; + CARD32 *data; + CARD8 opcode; + unsigned int length; + unsigned int i; + unsigned int num_attributes; + GLboolean use_glx_1_3; + + if ((dpy == NULL) || (drawable == 0)) { + return 0; + } + + priv = __glXInitialize(dpy); + use_glx_1_3 = ((priv->majorVersion > 1) || (priv->minorVersion >= 3)); + + *value = 0; + + + opcode = __glXSetupForCommand(dpy); + if (!opcode) + return 0; + + LockDisplay(dpy); + + if (use_glx_1_3) { + xGLXGetDrawableAttributesReq *req; + + GetReqExtra(GLXGetDrawableAttributes, 4, req); + req->reqType = opcode; + req->glxCode = X_GLXGetDrawableAttributes; + req->drawable = drawable; + } + else { + xGLXVendorPrivateWithReplyReq *vpreq; + + GetReqExtra(GLXVendorPrivateWithReply, 4, vpreq); + data = (CARD32 *) (vpreq + 1); + data[0] = (CARD32) drawable; + + vpreq->reqType = opcode; + vpreq->glxCode = X_GLXVendorPrivateWithReply; + vpreq->vendorCode = X_GLXvop_GetDrawableAttributesSGIX; + } + + _XReply(dpy, (xReply *) & reply, 0, False); + + if (reply.type == X_Error) { + UnlockDisplay(dpy); + SyncHandle(); + return 0; + } + + length = reply.length; + if (length) { + num_attributes = (use_glx_1_3) ? reply.numAttribs : length / 2; + data = (CARD32 *) Xmalloc(length * sizeof(CARD32)); + if (data == NULL) { + /* Throw data on the floor */ + _XEatData(dpy, length); + } + else { + _XRead(dpy, (char *) data, length * sizeof(CARD32)); + + /* Search the set of returned attributes for the attribute requested by + * the caller. + */ + for (i = 0; i < num_attributes; i++) { + if (data[i * 2] == attribute) { + *value = data[(i * 2) + 1]; + break; + } + } + +#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) + { + __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL); + + if (pdraw != NULL && !pdraw->textureTarget) + pdraw->textureTarget = + determineTextureTarget((const int *) data, num_attributes); + if (pdraw != NULL && !pdraw->textureFormat) + pdraw->textureFormat = + determineTextureFormat((const int *) data, num_attributes); + } +#endif + + Xfree(data); + } + } + + UnlockDisplay(dpy); + SyncHandle(); + + return 0; +} + +/** + * Create a non-pbuffer GLX drawable. + * + * \todo + * This function needs to be modified to work with direct-rendering drivers. + */ +static GLXDrawable +CreateDrawable(Display * dpy, const __GLcontextModes * fbconfig, + Drawable drawable, const int *attrib_list, CARD8 glxCode) +{ + xGLXCreateWindowReq *req; + CARD32 *data; + unsigned int i; + CARD8 opcode; + + i = 0; + if (attrib_list) { + while (attrib_list[i * 2] != None) + i++; + } + + opcode = __glXSetupForCommand(dpy); + if (!opcode) + return None; + + LockDisplay(dpy); + GetReqExtra(GLXCreateWindow, 8 * i, req); + data = (CARD32 *) (req + 1); + + req->reqType = opcode; + req->glxCode = glxCode; + req->screen = (CARD32) fbconfig->screen; + req->fbconfig = fbconfig->fbconfigID; + req->window = (CARD32) drawable; + req->glxwindow = (GLXWindow) XAllocID(dpy); + req->numAttribs = (CARD32) i; + + if (attrib_list) + memcpy(data, attrib_list, 8 * i); + + UnlockDisplay(dpy); + SyncHandle(); + + CreateDRIDrawable(dpy, fbconfig, drawable, req->glxwindow, attrib_list, i); + + return (GLXDrawable) req->glxwindow; +} + + +/** + * Destroy a non-pbuffer GLX drawable. + */ +static void +DestroyDrawable(Display * dpy, GLXDrawable drawable, CARD32 glxCode) +{ + xGLXDestroyPbufferReq *req; + CARD8 opcode; + + if ((dpy == NULL) || (drawable == 0)) { + return; + } + + + opcode = __glXSetupForCommand(dpy); + if (!opcode) + return; + + LockDisplay(dpy); + + GetReqExtra(GLXDestroyPbuffer, 4, req); + req->reqType = opcode; + req->glxCode = glxCode; + req->pbuffer = (GLXPbuffer) drawable; + + UnlockDisplay(dpy); + SyncHandle(); + + DestroyDRIDrawable(dpy, drawable, GL_FALSE); + + return; +} + + +/** + * Create a pbuffer. + * + * This function is used to implement \c glXCreatePbuffer and + * \c glXCreateGLXPbufferSGIX. + * + * \note + * This function dynamically determines whether to use the SGIX_pbuffer + * version of the protocol or the GLX 1.3 version of the protocol. + * + * \todo + * This function needs to be modified to work with direct-rendering drivers. + */ +static GLXDrawable +CreatePbuffer(Display * dpy, const __GLcontextModes * fbconfig, + unsigned int width, unsigned int height, + const int *attrib_list, GLboolean size_in_attribs) +{ + __GLXdisplayPrivate *priv = __glXInitialize(dpy); + GLXDrawable id = 0; + CARD32 *data; + CARD8 opcode; + unsigned int i; + Pixmap pixmap; + + i = 0; + if (attrib_list) { + while (attrib_list[i * 2]) + i++; + } + + opcode = __glXSetupForCommand(dpy); + if (!opcode) + return None; + + LockDisplay(dpy); + id = XAllocID(dpy); + + if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) { + xGLXCreatePbufferReq *req; + unsigned int extra = (size_in_attribs) ? 0 : 2; + + GetReqExtra(GLXCreatePbuffer, (8 * (i + extra)), req); + data = (CARD32 *) (req + 1); + + req->reqType = opcode; + req->glxCode = X_GLXCreatePbuffer; + req->screen = (CARD32) fbconfig->screen; + req->fbconfig = fbconfig->fbconfigID; + req->pbuffer = (GLXPbuffer) id; + req->numAttribs = (CARD32) (i + extra); + + if (!size_in_attribs) { + data[(2 * i) + 0] = GLX_PBUFFER_WIDTH; + data[(2 * i) + 1] = width; + data[(2 * i) + 2] = GLX_PBUFFER_HEIGHT; + data[(2 * i) + 3] = height; + data += 4; + } + } + else { + xGLXVendorPrivateReq *vpreq; + + GetReqExtra(GLXVendorPrivate, 20 + (8 * i), vpreq); + data = (CARD32 *) (vpreq + 1); + + vpreq->reqType = opcode; + vpreq->glxCode = X_GLXVendorPrivate; + vpreq->vendorCode = X_GLXvop_CreateGLXPbufferSGIX; + + data[0] = (CARD32) fbconfig->screen; + data[1] = (CARD32) fbconfig->fbconfigID; + data[2] = (CARD32) id; + data[3] = (CARD32) width; + data[4] = (CARD32) height; + data += 5; + } + + (void) memcpy(data, attrib_list, sizeof(CARD32) * 2 * i); + + UnlockDisplay(dpy); + SyncHandle(); + + pixmap = XCreatePixmap(dpy, RootWindow(dpy, fbconfig->screen), + width, height, fbconfig->rgbBits); + + CreateDRIDrawable(dpy, fbconfig, pixmap, id, attrib_list, i); + + return id; +} + +/** + * Destroy a pbuffer. + * + * This function is used to implement \c glXDestroyPbuffer and + * \c glXDestroyGLXPbufferSGIX. + * + * \note + * This function dynamically determines whether to use the SGIX_pbuffer + * version of the protocol or the GLX 1.3 version of the protocol. + */ +static void +DestroyPbuffer(Display * dpy, GLXDrawable drawable) +{ + __GLXdisplayPrivate *priv = __glXInitialize(dpy); + CARD8 opcode; + + if ((dpy == NULL) || (drawable == 0)) { + return; + } + + opcode = __glXSetupForCommand(dpy); + if (!opcode) + return; + + LockDisplay(dpy); + + if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) { + xGLXDestroyPbufferReq *req; + + GetReq(GLXDestroyPbuffer, req); + req->reqType = opcode; + req->glxCode = X_GLXDestroyPbuffer; + req->pbuffer = (GLXPbuffer) drawable; + } + else { + xGLXVendorPrivateWithReplyReq *vpreq; + CARD32 *data; + + GetReqExtra(GLXVendorPrivateWithReply, 4, vpreq); + data = (CARD32 *) (vpreq + 1); + + data[0] = (CARD32) drawable; + + vpreq->reqType = opcode; + vpreq->glxCode = X_GLXVendorPrivateWithReply; + vpreq->vendorCode = X_GLXvop_DestroyGLXPbufferSGIX; + } + + UnlockDisplay(dpy); + SyncHandle(); + + DestroyDRIDrawable(dpy, drawable, GL_TRUE); + + return; +} + +/** + * Create a new pbuffer. + */ +PUBLIC GLXPbufferSGIX +glXCreateGLXPbufferSGIX(Display * dpy, GLXFBConfigSGIX config, + unsigned int width, unsigned int height, + int *attrib_list) +{ + return (GLXPbufferSGIX) CreatePbuffer(dpy, (__GLcontextModes *) config, + width, height, + attrib_list, GL_FALSE); +} + +#endif /* GLX_USE_APPLEGL */ + +/** + * Create a new pbuffer. + */ +PUBLIC GLXPbuffer +glXCreatePbuffer(Display * dpy, GLXFBConfig config, const int *attrib_list) +{ + int i, width, height; +#ifdef GLX_USE_APPLEGL + GLXPbuffer result; + int errorcode; +#endif + + width = 0; + height = 0; + + WARN_ONCE_GLX_1_3(dpy, __func__); + +#ifdef GLX_USE_APPLEGL + for (i = 0; attrib_list[i]; ++i) { + switch (attrib_list[i]) { + case GLX_PBUFFER_WIDTH: + width = attrib_list[i + 1]; + ++i; + break; + + case GLX_PBUFFER_HEIGHT: + height = attrib_list[i + 1]; + ++i; + break; + + case GLX_LARGEST_PBUFFER: + /* This is a hint we should probably handle, but how? */ + ++i; + break; + + case GLX_PRESERVED_CONTENTS: + /* The contents are always preserved with AppleSGLX with CGL. */ + ++i; + break; + + default: + return None; + } + } + + if (apple_glx_pbuffer_create(dpy, config, width, height, &errorcode, + &result)) { + /* + * apple_glx_pbuffer_create only sets the errorcode to core X11 + * errors. + */ + __glXSendError(dpy, errorcode, 0, X_GLXCreatePbuffer, true); + + return None; + } + + return result; +#else + for (i = 0; attrib_list[i * 2]; i++) { + switch (attrib_list[i * 2]) { + case GLX_PBUFFER_WIDTH: + width = attrib_list[i * 2 + 1]; + break; + case GLX_PBUFFER_HEIGHT: + height = attrib_list[i * 2 + 1]; + break; + } + } + + return (GLXPbuffer) CreatePbuffer(dpy, (__GLcontextModes *) config, + width, height, attrib_list, GL_TRUE); +#endif +} + + +/** + * Destroy an existing pbuffer. + */ +PUBLIC void +glXDestroyPbuffer(Display * dpy, GLXPbuffer pbuf) +{ +#ifdef GLX_USE_APPLEGL + if (apple_glx_pbuffer_destroy(dpy, pbuf)) { + __glXSendError(dpy, GLXBadPbuffer, pbuf, X_GLXDestroyPbuffer, false); + } +#else + DestroyPbuffer(dpy, pbuf); +#endif +} + + +/** + * Query an attribute of a drawable. + */ +PUBLIC void +glXQueryDrawable(Display * dpy, GLXDrawable drawable, + int attribute, unsigned int *value) +{ + WARN_ONCE_GLX_1_3(dpy, __func__); +#ifdef GLX_USE_APPLEGL + Window root; + int x, y; + unsigned int width, height, bd, depth; + + if (apple_glx_pixmap_query(drawable, attribute, value)) + return; /*done */ + + if (apple_glx_pbuffer_query(drawable, attribute, value)) + return; /*done */ + + /* + * The OpenGL spec states that we should report GLXBadDrawable if + * the drawable is invalid, however doing so would require that we + * use XSetErrorHandler(), which is known to not be thread safe. + * If we use a round-trip call to validate the drawable, there could + * be a race, so instead we just opt in favor of letting the + * XGetGeometry request fail with a GetGeometry request X error + * rather than GLXBadDrawable, in what is hoped to be a rare + * case of an invalid drawable. In practice most and possibly all + * X11 apps using GLX shouldn't notice a difference. + */ + if (XGetGeometry + (dpy, drawable, &root, &x, &y, &width, &height, &bd, &depth)) { + switch (attribute) { + case GLX_WIDTH: + *value = width; + break; + + case GLX_HEIGHT: + *value = height; + break; + } + } +#else + GetDrawableAttribute(dpy, drawable, attribute, value); +#endif +} + + +#ifndef GLX_USE_APPLEGL +/** + * Query an attribute of a pbuffer. + */ +PUBLIC int +glXQueryGLXPbufferSGIX(Display * dpy, GLXPbufferSGIX drawable, + int attribute, unsigned int *value) +{ + return GetDrawableAttribute(dpy, drawable, attribute, value); +} +#endif + +/** + * Select the event mask for a drawable. + */ +PUBLIC void +glXSelectEvent(Display * dpy, GLXDrawable drawable, unsigned long mask) +{ +#ifdef GLX_USE_APPLEGL + XWindowAttributes xwattr; + + if (apple_glx_pbuffer_set_event_mask(drawable, mask)) + return; /*done */ + + /* + * The spec allows a window, but currently there are no valid + * events for a window, so do nothing. + */ + if (XGetWindowAttributes(dpy, drawable, &xwattr)) + return; /*done */ + /* The drawable seems to be invalid. Report an error. */ + + __glXSendError(dpy, GLXBadDrawable, drawable, + X_GLXChangeDrawableAttributes, false); +#else + CARD32 attribs[2]; + + attribs[0] = (CARD32) GLX_EVENT_MASK; + attribs[1] = (CARD32) mask; + + ChangeDrawableAttribute(dpy, drawable, attribs, 1); +#endif +} + + +/** + * Get the selected event mask for a drawable. + */ +PUBLIC void +glXGetSelectedEvent(Display * dpy, GLXDrawable drawable, unsigned long *mask) +{ +#ifdef GLX_USE_APPLEGL + XWindowAttributes xwattr; + + if (apple_glx_pbuffer_get_event_mask(drawable, mask)) + return; /*done */ + + /* + * The spec allows a window, but currently there are no valid + * events for a window, so do nothing, but set the mask to 0. + */ + if (XGetWindowAttributes(dpy, drawable, &xwattr)) { + /* The window is valid, so set the mask to 0. */ + *mask = 0; + return; /*done */ + } + /* The drawable seems to be invalid. Report an error. */ + + __glXSendError(dpy, GLXBadDrawable, drawable, X_GLXGetDrawableAttributes, + true); +#else + unsigned int value; + + + /* The non-sense with value is required because on LP64 platforms + * sizeof(unsigned int) != sizeof(unsigned long). On little-endian + * we could just type-cast the pointer, but why? + */ + + GetDrawableAttribute(dpy, drawable, GLX_EVENT_MASK_SGIX, &value); + *mask = value; +#endif +} + + +PUBLIC GLXPixmap +glXCreatePixmap(Display * dpy, GLXFBConfig config, Pixmap pixmap, + const int *attrib_list) +{ + WARN_ONCE_GLX_1_3(dpy, __func__); + +#ifdef GLX_USE_APPLEGL + const __GLcontextModes *modes = (const __GLcontextModes *) config; + + if (apple_glx_pixmap_create(dpy, modes->screen, pixmap, modes)) + return None; + + return pixmap; +#else + return CreateDrawable(dpy, (__GLcontextModes *) config, + (Drawable) pixmap, attrib_list, X_GLXCreatePixmap); +#endif +} + + +PUBLIC GLXWindow +glXCreateWindow(Display * dpy, GLXFBConfig config, Window win, + const int *attrib_list) +{ + WARN_ONCE_GLX_1_3(dpy, __func__); +#ifdef GLX_USE_APPLEGL + XWindowAttributes xwattr; + XVisualInfo *visinfo; + + (void) attrib_list; /*unused according to GLX 1.4 */ + + XGetWindowAttributes(dpy, win, &xwattr); + + visinfo = glXGetVisualFromFBConfig(dpy, config); + + if (NULL == visinfo) { + __glXSendError(dpy, GLXBadFBConfig, 0, X_GLXCreateWindow, false); + return None; + } + + if (visinfo->visualid != XVisualIDFromVisual(xwattr.visual)) { + __glXSendError(dpy, BadMatch, 0, X_GLXCreateWindow, true); + return None; + } + + XFree(visinfo); + + return win; +#else + return CreateDrawable(dpy, (__GLcontextModes *) config, + (Drawable) win, attrib_list, X_GLXCreateWindow); +#endif +} + + +PUBLIC void +glXDestroyPixmap(Display * dpy, GLXPixmap pixmap) +{ + WARN_ONCE_GLX_1_3(dpy, __func__); +#ifdef GLX_USE_APPLEGL + if (apple_glx_pixmap_destroy(dpy, pixmap)) + __glXSendError(dpy, GLXBadPixmap, pixmap, X_GLXDestroyPixmap, false); +#else + DestroyDrawable(dpy, (GLXDrawable) pixmap, X_GLXDestroyPixmap); +#endif +} + + +PUBLIC void +glXDestroyWindow(Display * dpy, GLXWindow win) +{ + WARN_ONCE_GLX_1_3(dpy, __func__); +#ifndef GLX_USE_APPLEGL + DestroyDrawable(dpy, (GLXDrawable) win, X_GLXDestroyWindow); +#endif +} + +#ifndef GLX_USE_APPLEGL +PUBLIC +GLX_ALIAS_VOID(glXDestroyGLXPbufferSGIX, + (Display * dpy, GLXPbufferSGIX pbuf), + (dpy, pbuf), glXDestroyPbuffer) + +PUBLIC +GLX_ALIAS_VOID(glXSelectEventSGIX, + (Display * dpy, GLXDrawable drawable, + unsigned long mask), (dpy, drawable, mask), glXSelectEvent) + +PUBLIC +GLX_ALIAS_VOID(glXGetSelectedEventSGIX, + (Display * dpy, GLXDrawable drawable, + unsigned long *mask), (dpy, drawable, mask), + glXGetSelectedEvent) +#endif |