X-Git-Url: https://git.libre-soc.org/?p=mesa.git;a=blobdiff_plain;f=src%2Fglx%2Fglx_pbuffer.c;h=515099aa0d8767121fb5e7ceda383274d885a2be;hp=4c122ba6ddc99c109b4414bfe0b468acecd1aaec;hb=84395190ec8cae6158737777c8def7cc3304eb3f;hpb=7ccbeb41acd2f5c416005bd48c11996a054a869a diff --git a/src/glx/glx_pbuffer.c b/src/glx/glx_pbuffer.c index 4c122ba6ddc..515099aa0d8 100644 --- a/src/glx/glx_pbuffer.c +++ b/src/glx/glx_pbuffer.c @@ -37,6 +37,13 @@ #include #include "glxextensions.h" +#ifdef GLX_USE_APPLEGL +#include +#include "apple/apple_glx_drawable.h" +#endif + +#include "glx_error.h" + #define WARN_ONCE_GLX_1_3(a, b) { \ static int warned=1; \ if(warned) { \ @@ -49,19 +56,19 @@ * 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) +warn_GLX_1_3(Display * dpy, const char *function_name) { - __GLXdisplayPrivate *priv = __glXInitialize(dpy); + struct glx_display *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); + if (priv && 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. * @@ -71,19 +78,20 @@ warn_GLX_1_3(Display *dpy, const char *function_name) * \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); + struct glx_display *priv = __glXInitialize(dpy); +#ifdef GLX_DIRECT_RENDERING + __GLXDRIdrawable *pdraw; +#endif CARD32 *output; CARD8 opcode; + int i; - if ((dpy == NULL) || (drawable == 0)) { + if ((priv == NULL) || (dpy == NULL) || (drawable == 0)) { return; } @@ -96,7 +104,7 @@ ChangeDrawableAttribute(Display * dpy, GLXDrawable drawable, if ((priv->majorVersion > 1) || (priv->minorVersion >= 3)) { xGLXChangeDrawableAttributesReq *req; - GetReqExtra(GLXChangeDrawableAttributes, 8 + (8 * num_attribs), req); + GetReqExtra(GLXChangeDrawableAttributes, 8 * num_attribs, req); output = (CARD32 *) (req + 1); req->reqType = opcode; @@ -107,7 +115,7 @@ ChangeDrawableAttribute(Display * dpy, GLXDrawable drawable, else { xGLXVendorPrivateWithReplyReq *vpreq; - GetReqExtra(GLXVendorPrivateWithReply, 4 + (8 * num_attribs), vpreq); + GetReqExtra(GLXVendorPrivateWithReply, 8 + (8 * num_attribs), vpreq); output = (CARD32 *) (vpreq + 1); vpreq->reqType = opcode; @@ -115,7 +123,8 @@ ChangeDrawableAttribute(Display * dpy, GLXDrawable drawable, vpreq->vendorCode = X_GLXvop_ChangeDrawableAttributesSGIX; output[0] = (CARD32) drawable; - output++; + output[1] = num_attribs; + output += 2; } (void) memcpy(output, attribs, sizeof(CARD32) * 2 * num_attribs); @@ -123,63 +132,21 @@ ChangeDrawableAttribute(Display * dpy, GLXDrawable drawable, UnlockDisplay(dpy); SyncHandle(); - return; -} - - -/** - * 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. - * - * \todo - * This function needs to be modified to work with direct-rendering drivers. - */ -static void -DestroyPbuffer(Display * dpy, GLXDrawable drawable) -{ - __GLXdisplayPrivate *priv = __glXInitialize(dpy); - CARD8 opcode; - - if ((dpy == NULL) || (drawable == 0)) { - return; - } +#ifdef GLX_DIRECT_RENDERING + pdraw = GetGLXDRIDrawable(dpy, drawable); - opcode = __glXSetupForCommand(dpy); - if (!opcode) + if (!pdraw) 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; + for (i = 0; i < num_attribs; i++) { + switch(attribs[i * 2]) { + case GLX_EVENT_MASK: + /* Keep a local copy for masking out DRI2 proto events as needed */ + pdraw->eventMask = attribs[i * 2 + 1]; + break; + } } - - UnlockDisplay(dpy); - SyncHandle(); +#endif return; } @@ -208,7 +175,6 @@ determineTextureTarget(const int *attribs, int numAttribs) return target; } - static GLenum determineTextureFormat(const int *attribs, int numAttribs) { @@ -221,6 +187,74 @@ determineTextureFormat(const int *attribs, int numAttribs) return 0; } + +static GLboolean +CreateDRIDrawable(Display *dpy, struct glx_config *config, + XID drawable, XID glxdrawable, + const int *attrib_list, size_t num_attribs) +{ + struct glx_display *const priv = __glXInitialize(dpy); + __GLXDRIdrawable *pdraw; + struct glx_screen *psc; + + if (priv == NULL) { + fprintf(stderr, "failed to create drawable\n"); + return GL_FALSE; + } + + psc = priv->screens[config->screen]; + if (psc->driScreen == NULL) + return GL_TRUE; + + pdraw = psc->driScreen->createDrawable(psc, drawable, + glxdrawable, config); + if (pdraw == NULL) { + fprintf(stderr, "failed to create drawable\n"); + return GL_FALSE; + } + + if (__glxHashInsert(priv->drawHash, glxdrawable, pdraw)) { + (*pdraw->destroyDrawable) (pdraw); + return GL_FALSE; + } + + pdraw->textureTarget = determineTextureTarget(attrib_list, num_attribs); + pdraw->textureFormat = determineTextureFormat(attrib_list, num_attribs); + + return GL_TRUE; +} + +static void +DestroyDRIDrawable(Display *dpy, GLXDrawable drawable, int destroy_xdrawable) +{ + struct glx_display *const priv = __glXInitialize(dpy); + __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable); + XID xid; + + if (priv != NULL && pdraw != NULL) { + xid = pdraw->xDrawable; + (*pdraw->destroyDrawable) (pdraw); + __glxHashDelete(priv->drawHash, drawable); + if (destroy_xdrawable) + XFreePixmap(priv->dpy, xid); + } +} + +#else + +static GLboolean +CreateDRIDrawable(Display *dpy, const struct glx_config * fbconfig, + XID drawable, XID glxdrawable, + const int *attrib_list, size_t num_attribs) +{ + return GL_TRUE; +} + +static void +DestroyDRIDrawable(Display *dpy, GLXDrawable drawable, int destroy_xdrawable) +{ +} + #endif /** @@ -237,15 +271,12 @@ determineTextureFormat(const int *attribs, int numAttribs) * 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) +int +__glXGetDrawableAttribute(Display * dpy, GLXDrawable drawable, + int attribute, unsigned int *value) { - __GLXdisplayPrivate *priv; + struct glx_display *priv; xGLXGetDrawableAttributesReply reply; CARD32 *data; CARD8 opcode; @@ -254,11 +285,27 @@ GetDrawableAttribute(Display * dpy, GLXDrawable drawable, unsigned int num_attributes; GLboolean use_glx_1_3; - if ((dpy == NULL) || (drawable == 0)) { +#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) + __GLXDRIdrawable *pdraw; +#endif + + if (dpy == NULL) + return 0; + + /* Page 38 (page 52 of the PDF) of glxencode1.3.pdf says: + * + * "If drawable is not a valid GLX drawable, a GLXBadDrawable error is + * generated." + */ + if (drawable == 0) { + __glXSendError(dpy, GLXBadDrawable, 0, X_GLXGetDrawableAttributes, false); return 0; } priv = __glXInitialize(dpy); + if (priv == NULL) + return 0; + use_glx_1_3 = ((priv->majorVersion > 1) || (priv->minorVersion >= 3)); *value = 0; @@ -268,12 +315,42 @@ GetDrawableAttribute(Display * dpy, GLXDrawable drawable, if (!opcode) return 0; +#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) + pdraw = GetGLXDRIDrawable(dpy, drawable); + + if (attribute == GLX_BACK_BUFFER_AGE_EXT) { + struct glx_context *gc = __glXGetCurrentContext(); + struct glx_screen *psc; + + /* The GLX_EXT_buffer_age spec says: + * + * "If querying GLX_BACK_BUFFER_AGE_EXT and is not bound to + * the calling thread's current context a GLXBadDrawable error is + * generated." + */ + if (pdraw == NULL || gc == &dummyContext || gc->currentDpy != dpy || + (gc->currentDrawable != drawable && + gc->currentReadable != drawable)) { + __glXSendError(dpy, GLXBadDrawable, drawable, + X_GLXGetDrawableAttributes, false); + return 0; + } + + psc = pdraw->psc; + + if (psc->driScreen->getBufferAge != NULL) + *value = psc->driScreen->getBufferAge(pdraw); + + return 0; + } +#endif + LockDisplay(dpy); if (use_glx_1_3) { xGLXGetDrawableAttributesReq *req; - GetReqExtra(GLXGetDrawableAttributes, 4, req); + GetReq(GLXGetDrawableAttributes, req); req->reqType = opcode; req->glxCode = X_GLXGetDrawableAttributes; req->drawable = drawable; @@ -301,7 +378,7 @@ GetDrawableAttribute(Display * dpy, GLXDrawable drawable, length = reply.length; if (length) { num_attributes = (use_glx_1_3) ? reply.numAttribs : length / 2; - data = (CARD32 *) Xmalloc(length * sizeof(CARD32)); + data = malloc(length * sizeof(CARD32)); if (data == NULL) { /* Throw data on the floor */ _XEatData(dpy, length); @@ -319,43 +396,61 @@ GetDrawableAttribute(Display * dpy, GLXDrawable drawable, } } -#ifdef GLX_DIRECT_RENDERING - { - __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL); - - if (pdraw != NULL && !pdraw->textureTarget) +#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) + if (pdraw != NULL) { + if (!pdraw->textureTarget) pdraw->textureTarget = determineTextureTarget((const int *) data, num_attributes); - if (pdraw != NULL && !pdraw->textureFormat) + if (!pdraw->textureFormat) pdraw->textureFormat = determineTextureFormat((const int *) data, num_attributes); } #endif - Xfree(data); + free(data); } } UnlockDisplay(dpy); SyncHandle(); - return 0; + return 1; +} + +static void +protocolDestroyDrawable(Display *dpy, GLXDrawable drawable, CARD32 glxCode) +{ + xGLXDestroyPbufferReq *req; + CARD8 opcode; + + opcode = __glXSetupForCommand(dpy); + if (!opcode) + return; + + LockDisplay(dpy); + + GetReq(GLXDestroyPbuffer, req); + req->reqType = opcode; + req->glxCode = glxCode; + req->pbuffer = (GLXPbuffer) drawable; + + UnlockDisplay(dpy); + SyncHandle(); } /** * 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, +CreateDrawable(Display *dpy, struct glx_config *config, Drawable drawable, const int *attrib_list, CARD8 glxCode) { xGLXCreateWindowReq *req; + struct glx_drawable *glxDraw; CARD32 *data; unsigned int i; CARD8 opcode; + GLXDrawable xid; i = 0; if (attrib_list) { @@ -367,100 +462,60 @@ CreateDrawable(Display * dpy, const __GLcontextModes * fbconfig, if (!opcode) return None; + glxDraw = malloc(sizeof(*glxDraw)); + if (!glxDraw) + 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; + req->screen = config->screen; + req->fbconfig = config->fbconfigID; + req->window = drawable; + req->glxwindow = xid = XAllocID(dpy); + req->numAttribs = i; - memcpy(data, attrib_list, 8 * i); + if (attrib_list) + memcpy(data, attrib_list, 8 * i); UnlockDisplay(dpy); SyncHandle(); -#ifdef GLX_DIRECT_RENDERING - do { - /* FIXME: Maybe delay __DRIdrawable creation until the drawable - * is actually bound to a context... */ - - __GLXdisplayPrivate *const priv = __glXInitialize(dpy); - __GLXDRIdrawable *pdraw; - __GLXscreenConfigs *psc; - - psc = &priv->screenConfigs[fbconfig->screen]; - if (psc->driScreen == NULL) - break; - pdraw = psc->driScreen->createDrawable(psc, drawable, - req->glxwindow, fbconfig); - if (pdraw == NULL) { - fprintf(stderr, "failed to create drawable\n"); - break; - } - - if (__glxHashInsert(psc->drawHash, req->glxwindow, pdraw)) { - (*pdraw->destroyDrawable) (pdraw); - return None; /* FIXME: Check what we're supposed to do here... */ - } + if (InitGLXDrawable(dpy, glxDraw, drawable, xid)) { + free(glxDraw); + return None; + } - pdraw->textureTarget = determineTextureTarget(attrib_list, i); - pdraw->textureFormat = determineTextureFormat(attrib_list, i); - } while (0); -#endif + if (!CreateDRIDrawable(dpy, config, drawable, xid, attrib_list, i)) { + if (glxCode == X_GLXCreatePixmap) + glxCode = X_GLXDestroyPixmap; + else + glxCode = X_GLXDestroyWindow; + protocolDestroyDrawable(dpy, xid, glxCode); + xid = None; + } - return (GLXDrawable) req->glxwindow; + return xid; } /** * Destroy a non-pbuffer GLX drawable. - * - * \todo - * This function needs to be modified to work with direct-rendering drivers. */ static void DestroyDrawable(Display * dpy, GLXDrawable drawable, CARD32 glxCode) { - xGLXDestroyPbufferReq *req; - CARD8 opcode; - if ((dpy == NULL) || (drawable == 0)) { return; } + protocolDestroyDrawable(dpy, drawable, glxCode); - 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(); - -#ifdef GLX_DIRECT_RENDERING - { - int screen; - __GLXdisplayPrivate *const priv = __glXInitialize(dpy); - __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, &screen); - __GLXscreenConfigs *psc = &priv->screenConfigs[screen]; - - if (pdraw != NULL) { - (*pdraw->destroyDrawable) (pdraw); - __glxHashDelete(psc->drawHash, drawable); - } - } -#endif + DestroyGLXDrawable(dpy, drawable); + DestroyDRIDrawable(dpy, drawable, GL_FALSE); return; } @@ -475,20 +530,22 @@ DestroyDrawable(Display * dpy, GLXDrawable drawable, CARD32 glxCode) * \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, +CreatePbuffer(Display * dpy, struct glx_config *config, unsigned int width, unsigned int height, const int *attrib_list, GLboolean size_in_attribs) { - __GLXdisplayPrivate *priv = __glXInitialize(dpy); + struct glx_display *priv = __glXInitialize(dpy); GLXDrawable id = 0; CARD32 *data; CARD8 opcode; unsigned int i; + Pixmap pixmap; + GLboolean glx_1_3 = GL_FALSE; + + if (priv == NULL) + return None; i = 0; if (attrib_list) { @@ -507,15 +564,17 @@ CreatePbuffer(Display * dpy, const __GLcontextModes * fbconfig, xGLXCreatePbufferReq *req; unsigned int extra = (size_in_attribs) ? 0 : 2; + glx_1_3 = GL_TRUE; + 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); + req->screen = config->screen; + req->fbconfig = config->fbconfigID; + req->pbuffer = id; + req->numAttribs = i + extra; if (!size_in_attribs) { data[(2 * i) + 0] = GLX_PBUFFER_WIDTH; @@ -535,11 +594,11 @@ CreatePbuffer(Display * dpy, const __GLcontextModes * fbconfig, 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[0] = config->screen; + data[1] = config->fbconfigID; + data[2] = id; + data[3] = width; + data[4] = height; data += 5; } @@ -548,37 +607,148 @@ CreatePbuffer(Display * dpy, const __GLcontextModes * fbconfig, UnlockDisplay(dpy); SyncHandle(); + pixmap = XCreatePixmap(dpy, RootWindow(dpy, config->screen), + width, height, config->rgbBits); + + if (!CreateDRIDrawable(dpy, config, pixmap, id, attrib_list, i)) { + CARD32 o = glx_1_3 ? X_GLXDestroyPbuffer : X_GLXvop_DestroyGLXPbufferSGIX; + XFreePixmap(dpy, pixmap); + protocolDestroyDrawable(dpy, id, o); + id = None; + } + 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) +{ + struct glx_display *priv = __glXInitialize(dpy); + CARD8 opcode; + + if ((priv == NULL) || (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 +_GLX_PUBLIC GLXPbufferSGIX glXCreateGLXPbufferSGIX(Display * dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height, int *attrib_list) { - return (GLXPbufferSGIX) CreatePbuffer(dpy, (__GLcontextModes *) config, + return (GLXPbufferSGIX) CreatePbuffer(dpy, (struct glx_config *) config, width, height, attrib_list, GL_FALSE); } +#endif /* GLX_USE_APPLEGL */ /** * Create a new pbuffer. */ -PUBLIC GLXPbuffer +_GLX_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: @@ -590,66 +760,148 @@ glXCreatePbuffer(Display * dpy, GLXFBConfig config, const int *attrib_list) } } - return (GLXPbuffer) CreatePbuffer(dpy, (__GLcontextModes *) config, + return (GLXPbuffer) CreatePbuffer(dpy, (struct glx_config *) config, width, height, attrib_list, GL_TRUE); +#endif } /** * Destroy an existing pbuffer. */ -PUBLIC void +_GLX_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 +_GLX_PUBLIC void glXQueryDrawable(Display * dpy, GLXDrawable drawable, int attribute, unsigned int *value) { WARN_ONCE_GLX_1_3(dpy, __func__); - GetDrawableAttribute(dpy, drawable, attribute, value); +#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 + __glXGetDrawableAttribute(dpy, drawable, attribute, value); +#endif } +#ifndef GLX_USE_APPLEGL /** * Query an attribute of a pbuffer. */ -PUBLIC int +_GLX_PUBLIC void glXQueryGLXPbufferSGIX(Display * dpy, GLXPbufferSGIX drawable, int attribute, unsigned int *value) { - return GetDrawableAttribute(dpy, drawable, attribute, value); + __glXGetDrawableAttribute(dpy, drawable, attribute, value); } - +#endif /** * Select the event mask for a drawable. */ -PUBLIC void +_GLX_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 +_GLX_PUBLIC void glXGetSelectedEvent(Display * dpy, GLXDrawable drawable, unsigned long *mask) { - unsigned int value; +#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 = 0; /* The non-sense with value is required because on LP64 platforms @@ -657,64 +909,101 @@ glXGetSelectedEvent(Display * dpy, GLXDrawable drawable, unsigned long *mask) * we could just type-cast the pointer, but why? */ - GetDrawableAttribute(dpy, drawable, GLX_EVENT_MASK_SGIX, &value); + __glXGetDrawableAttribute(dpy, drawable, GLX_EVENT_MASK_SGIX, &value); *mask = value; +#endif } -PUBLIC GLXPixmap +_GLX_PUBLIC GLXPixmap glXCreatePixmap(Display * dpy, GLXFBConfig config, Pixmap pixmap, const int *attrib_list) { WARN_ONCE_GLX_1_3(dpy, __func__); - return CreateDrawable(dpy, (__GLcontextModes *) config, +#ifdef GLX_USE_APPLEGL + const struct glx_config *modes = (const struct glx_config *) config; + + if (apple_glx_pixmap_create(dpy, modes->screen, pixmap, modes)) + return None; + + return pixmap; +#else + return CreateDrawable(dpy, (struct glx_config *) config, (Drawable) pixmap, attrib_list, X_GLXCreatePixmap); +#endif } -PUBLIC GLXWindow +_GLX_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; + } + + free(visinfo); - return CreateDrawable(dpy, (__GLcontextModes *) config, + return win; +#else + return CreateDrawable(dpy, (struct glx_config *) config, (Drawable) win, attrib_list, X_GLXCreateWindow); +#endif } -PUBLIC void +_GLX_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 +_GLX_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 } - -PUBLIC +_GLX_PUBLIC GLX_ALIAS_VOID(glXDestroyGLXPbufferSGIX, (Display * dpy, GLXPbufferSGIX pbuf), (dpy, pbuf), glXDestroyPbuffer) -PUBLIC +_GLX_PUBLIC GLX_ALIAS_VOID(glXSelectEventSGIX, (Display * dpy, GLXDrawable drawable, unsigned long mask), (dpy, drawable, mask), glXSelectEvent) -PUBLIC +_GLX_PUBLIC GLX_ALIAS_VOID(glXGetSelectedEventSGIX, (Display * dpy, GLXDrawable drawable, unsigned long *mask), (dpy, drawable, mask), glXGetSelectedEvent) -