diff options
Diffstat (limited to 'src/glx/glx_pbuffer.c')
-rw-r--r-- | src/glx/glx_pbuffer.c | 423 |
1 files changed, 308 insertions, 115 deletions
diff --git a/src/glx/glx_pbuffer.c b/src/glx/glx_pbuffer.c index 52e067165c8..b8d0f21bf06 100644 --- a/src/glx/glx_pbuffer.c +++ b/src/glx/glx_pbuffer.c @@ -37,6 +37,12 @@ #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) { \ @@ -49,19 +55,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); 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); + 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. * @@ -127,64 +133,6 @@ ChangeDrawableAttribute(Display * dpy, GLXDrawable drawable, } -/** - * 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; - } - - 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(); - - return; -} - - #ifdef GLX_DIRECT_RENDERING static GLenum determineTextureTarget(const int *attribs, int numAttribs) @@ -208,7 +156,6 @@ determineTextureTarget(const int *attribs, int numAttribs) return target; } - static GLenum determineTextureFormat(const int *attribs, int numAttribs) { @@ -221,6 +168,66 @@ determineTextureFormat(const int *attribs, int numAttribs) 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 /** @@ -319,7 +326,7 @@ GetDrawableAttribute(Display * dpy, GLXDrawable drawable, } } -#ifdef GLX_DIRECT_RENDERING +#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) { __GLXDRIdrawable *pdraw = GetGLXDRIDrawable(dpy, drawable, NULL); @@ -385,34 +392,7 @@ CreateDrawable(Display * dpy, const __GLcontextModes * fbconfig, 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... */ - } - - pdraw->textureTarget = determineTextureTarget(attrib_list, i); - pdraw->textureFormat = determineTextureFormat(attrib_list, i); - } while (0); -#endif + CreateDRIDrawable(dpy, fbconfig, drawable, req->glxwindow, attrib_list, i); return (GLXDrawable) req->glxwindow; } @@ -420,9 +400,6 @@ CreateDrawable(Display * dpy, const __GLcontextModes * fbconfig, /** * 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) @@ -449,19 +426,7 @@ DestroyDrawable(Display * dpy, GLXDrawable drawable, CARD32 glxCode) 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 + DestroyDRIDrawable(dpy, drawable, GL_FALSE); return; } @@ -490,6 +455,7 @@ CreatePbuffer(Display * dpy, const __GLcontextModes * fbconfig, CARD32 *data; CARD8 opcode; unsigned int i; + Pixmap pixmap; i = 0; if (attrib_list) { @@ -549,9 +515,69 @@ CreatePbuffer(Display * dpy, const __GLcontextModes * fbconfig, 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. @@ -566,6 +592,7 @@ glXCreateGLXPbufferSGIX(Display * dpy, GLXFBConfigSGIX config, attrib_list, GL_FALSE); } +#endif /* GLX_USE_APPLEGL */ /** * Create a new pbuffer. @@ -574,12 +601,57 @@ 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: @@ -593,6 +665,7 @@ glXCreatePbuffer(Display * dpy, GLXFBConfig config, const int *attrib_list) return (GLXPbuffer) CreatePbuffer(dpy, (__GLcontextModes *) config, width, height, attrib_list, GL_TRUE); +#endif } @@ -602,7 +675,13 @@ glXCreatePbuffer(Display * dpy, GLXFBConfig config, const int *attrib_list) 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 } @@ -614,10 +693,47 @@ 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. */ @@ -627,7 +743,7 @@ glXQueryGLXPbufferSGIX(Display * dpy, GLXPbufferSGIX drawable, { return GetDrawableAttribute(dpy, drawable, attribute, value); } - +#endif /** * Select the event mask for a drawable. @@ -635,12 +751,30 @@ glXQueryGLXPbufferSGIX(Display * dpy, GLXPbufferSGIX 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 } @@ -650,6 +784,26 @@ glXSelectEvent(Display * dpy, GLXDrawable drawable, unsigned long mask) 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; @@ -660,6 +814,7 @@ glXGetSelectedEvent(Display * dpy, GLXDrawable drawable, unsigned long *mask) GetDrawableAttribute(dpy, drawable, GLX_EVENT_MASK_SGIX, &value); *mask = value; +#endif } @@ -669,8 +824,17 @@ glXCreatePixmap(Display * dpy, GLXFBConfig config, Pixmap pixmap, { 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 } @@ -679,9 +843,33 @@ 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 } @@ -689,8 +877,12 @@ 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 } @@ -698,11 +890,12 @@ 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), @@ -718,4 +911,4 @@ GLX_ALIAS_VOID(glXGetSelectedEventSGIX, (Display * dpy, GLXDrawable drawable, unsigned long *mask), (dpy, drawable, mask), glXGetSelectedEvent) - +#endif |