diff options
author | Kristian Høgsberg <krh@bitplanet.net> | 2010-04-09 17:16:33 -0400 |
---|---|---|
committer | Kristian Høgsberg <krh@bitplanet.net> | 2010-04-09 17:16:33 -0400 |
commit | 5a43dbac687c63ea543035319e44ca7a0acf9ff9 (patch) | |
tree | c9726410d59f0452cf90300ec0f0e2f7ad3f452f /src/glx | |
parent | edb5253dfa0751e451dca7c9a494be4609390545 (diff) |
glx: Support direct rendering pbuffers
We've supported indirect rendering pbuffers for a while, but not direct
rendering pbuffers. The way we do this is by creating a hidden pixmap
and wrap that in a GLX pbuffer. This only works when we have DRI2 on
the server, but if the server doesn't have DRI2, it won't expose configs
with pbuffer bits enabled.
Diffstat (limited to 'src/glx')
-rw-r--r-- | src/glx/glx_pbuffer.c | 226 |
1 files changed, 123 insertions, 103 deletions
diff --git a/src/glx/glx_pbuffer.c b/src/glx/glx_pbuffer.c index 52e067165c..2098cc6a52 100644 --- a/src/glx/glx_pbuffer.c +++ b/src/glx/glx_pbuffer.c @@ -127,64 +127,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 +150,6 @@ determineTextureTarget(const int *attribs, int numAttribs) return target; } - static GLenum determineTextureFormat(const int *attribs, int numAttribs) { @@ -221,6 +162,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 /** @@ -385,34 +386,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 +394,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 +420,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 +449,7 @@ CreatePbuffer(Display * dpy, const __GLcontextModes * fbconfig, CARD32 *data; CARD8 opcode; unsigned int i; + Pixmap pixmap; i = 0; if (attrib_list) { @@ -549,9 +509,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. |