diff options
Diffstat (limited to 'src/glx/glx_pbuffer.c')
-rw-r--r-- | src/glx/glx_pbuffer.c | 372 |
1 files changed, 211 insertions, 161 deletions
diff --git a/src/glx/glx_pbuffer.c b/src/glx/glx_pbuffer.c index c145ee92405..dc64ab64701 100644 --- a/src/glx/glx_pbuffer.c +++ b/src/glx/glx_pbuffer.c @@ -38,6 +38,9 @@ #include <limits.h> #include "glxextensions.h" +#include <X11/Xlib-xcb.h> +#include <xcb/xproto.h> + #ifdef GLX_USE_APPLEGL #include <pthread.h> #include "apple/apple_glx_drawable.h" @@ -45,16 +48,12 @@ #include "glx_error.h" -#ifndef GLX_USE_APPLEGL +#if !defined(GLX_USE_APPLEGL) || defined(GLX_USE_APPLE) /** * 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. */ static void ChangeDrawableAttribute(Display * dpy, GLXDrawable drawable, @@ -78,31 +77,14 @@ ChangeDrawableAttribute(Display * dpy, GLXDrawable drawable, LockDisplay(dpy); - if (priv->minorVersion >= 3) { - xGLXChangeDrawableAttributesReq *req; - - GetReqExtra(GLXChangeDrawableAttributes, 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, 8 + (8 * num_attribs), vpreq); - output = (CARD32 *) (vpreq + 1); - - vpreq->reqType = opcode; - vpreq->glxCode = X_GLXVendorPrivateWithReply; - vpreq->vendorCode = X_GLXvop_ChangeDrawableAttributesSGIX; + xGLXChangeDrawableAttributesReq *req; + GetReqExtra(GLXChangeDrawableAttributes, 8 * num_attribs, req); + output = (CARD32 *) (req + 1); - output[0] = (CARD32) drawable; - output[1] = num_attribs; - output += 2; - } + req->reqType = opcode; + req->glxCode = X_GLXChangeDrawableAttributes; + req->drawable = drawable; + req->numAttribs = (CARD32) num_attribs; (void) memcpy(output, attribs, sizeof(CARD32) * 2 * num_attribs); @@ -168,7 +150,7 @@ determineTextureFormat(const int *attribs, int numAttribs) static GLboolean CreateDRIDrawable(Display *dpy, struct glx_config *config, - XID drawable, XID glxdrawable, + XID drawable, XID glxdrawable, int type, const int *attrib_list, size_t num_attribs) { #ifdef GLX_DIRECT_RENDERING @@ -185,39 +167,37 @@ CreateDRIDrawable(Display *dpy, struct glx_config *config, if (psc->driScreen == NULL) return GL_TRUE; - pdraw = psc->driScreen->createDrawable(psc, drawable, - glxdrawable, config); + pdraw = psc->driScreen->createDrawable(psc, drawable, glxdrawable, + type, config); if (pdraw == NULL) { fprintf(stderr, "failed to create drawable\n"); return GL_FALSE; } if (__glxHashInsert(priv->drawHash, glxdrawable, pdraw)) { - (*pdraw->destroyDrawable) (pdraw); + pdraw->destroyDrawable(pdraw); return GL_FALSE; } pdraw->textureTarget = determineTextureTarget(attrib_list, num_attribs); pdraw->textureFormat = determineTextureFormat(attrib_list, num_attribs); + + pdraw->refcount = 1; #endif return GL_TRUE; } static void -DestroyDRIDrawable(Display *dpy, GLXDrawable drawable, int destroy_xdrawable) +DestroyDRIDrawable(Display *dpy, GLXDrawable drawable) { #ifdef GLX_DIRECT_RENDERING 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); + pdraw->destroyDrawable(pdraw); __glxHashDelete(priv->drawHash, drawable); - if (destroy_xdrawable) - XFreePixmap(priv->dpy, xid); } #endif } @@ -228,10 +208,6 @@ DestroyDRIDrawable(Display *dpy, GLXDrawable drawable, int destroy_xdrawable) * 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 @@ -263,6 +239,7 @@ __glXGetDrawableAttribute(Display * dpy, GLXDrawable drawable, * generated." */ if (drawable == 0) { + XNoOp(dpy); __glXSendError(dpy, GLXBadDrawable, 0, X_GLXGetDrawableAttributes, false); return 0; } @@ -293,6 +270,7 @@ __glXGetDrawableAttribute(Display * dpy, GLXDrawable drawable, if (pdraw == NULL || gc == &dummyContext || gc->currentDpy != dpy || (gc->currentDrawable != drawable && gc->currentReadable != drawable)) { + XNoOp(dpy); __glXSendError(dpy, GLXBadDrawable, drawable, X_GLXGetDrawableAttributes, false); return 0; @@ -303,45 +281,31 @@ __glXGetDrawableAttribute(Display * dpy, GLXDrawable drawable, if (psc->driScreen->getBufferAge != NULL) *value = psc->driScreen->getBufferAge(pdraw); - return 0; + return 1; } if (pdraw) { if (attribute == GLX_SWAP_INTERVAL_EXT) { *value = pdraw->psc->driScreen->getSwapInterval(pdraw); - return 0; + return 1; } else if (attribute == GLX_MAX_SWAP_INTERVAL_EXT) { - *value = INT_MAX; - return 0; + *value = pdraw->psc->driScreen->maxSwapInterval; + return 1; } else if (attribute == GLX_LATE_SWAPS_TEAR_EXT) { *value = __glXExtensionBitIsEnabled(pdraw->psc, EXT_swap_control_tear_bit); - return 0; + return 1; } } #endif LockDisplay(dpy); - if (priv->minorVersion >= 3) { - xGLXGetDrawableAttributesReq *req; - - GetReq(GLXGetDrawableAttributes, 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; - } + xGLXGetDrawableAttributesReq *req; + GetReq(GLXGetDrawableAttributes, req); + req->reqType = opcode; + req->glxCode = X_GLXGetDrawableAttributes; + req->drawable = drawable; _XReply(dpy, (xReply *) & reply, 0, False); @@ -353,7 +317,7 @@ __glXGetDrawableAttribute(Display * dpy, GLXDrawable drawable, length = reply.length; if (length) { - num_attributes = (priv->minorVersion > 2) ? reply.numAttribs : length / 2; + num_attributes = reply.numAttribs; data = malloc(length * sizeof(CARD32)); if (data == NULL) { /* Throw data on the floor */ @@ -391,9 +355,41 @@ __glXGetDrawableAttribute(Display * dpy, GLXDrawable drawable, UnlockDisplay(dpy); SyncHandle(); +#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) + if (pdraw && attribute == GLX_FBCONFIG_ID && !found) { + /* If we failed to lookup the GLX_FBCONFIG_ID, it may be because the drawable is + * a bare Window, so try differently by first figure out its visual, then GLX + * visual like driInferDrawableConfig does. + */ + xcb_get_window_attributes_cookie_t cookie = { 0 }; + xcb_get_window_attributes_reply_t *attr = NULL; + + xcb_connection_t *conn = XGetXCBConnection(dpy); + + if (conn) { + cookie = xcb_get_window_attributes(conn, drawable); + attr = xcb_get_window_attributes_reply(conn, cookie, NULL); + if (attr) { + /* Find the Window's GLX Visual */ + struct glx_config *conf = glx_config_find_visual(pdraw->psc->configs, attr->visual); + free(attr); + + if (conf) + *value = conf->fbconfigID; + } + } + } +#endif + return found; } +static int dummyErrorHandler(Display *display, xError *err, XExtCodes *codes, + int *ret_code) +{ + return 1; /* do nothing */ +} + static void protocolDestroyDrawable(Display *dpy, GLXDrawable drawable, CARD32 glxCode) { @@ -413,6 +409,19 @@ protocolDestroyDrawable(Display *dpy, GLXDrawable drawable, CARD32 glxCode) UnlockDisplay(dpy); SyncHandle(); + + /* Viewperf2020/Sw calls XDestroyWindow(win) and then glXDestroyWindow(win), + * causing an X error and abort. This is the workaround. + */ + struct glx_display *priv = __glXInitialize(dpy); + + if (priv->screens[0] && + priv->screens[0]->allow_invalid_glx_destroy_window) { + void *old = XESetError(priv->dpy, priv->codes.extension, + dummyErrorHandler); + XSync(dpy, false); + XESetError(priv->dpy, priv->codes.extension, old); + } } /** @@ -420,7 +429,7 @@ protocolDestroyDrawable(Display *dpy, GLXDrawable drawable, CARD32 glxCode) */ static GLXDrawable CreateDrawable(Display *dpy, struct glx_config *config, - Drawable drawable, const int *attrib_list, CARD8 glxCode) + Drawable drawable, int type, const int *attrib_list) { xGLXCreateWindowReq *req; struct glx_drawable *glxDraw; @@ -451,13 +460,17 @@ CreateDrawable(Display *dpy, struct glx_config *config, data = (CARD32 *) (req + 1); req->reqType = opcode; - req->glxCode = glxCode; req->screen = config->screen; req->fbconfig = config->fbconfigID; req->window = drawable; req->glxwindow = xid = XAllocID(dpy); req->numAttribs = i; + if (type == GLX_WINDOW_BIT) + req->glxCode = X_GLXCreateWindow; + else + req->glxCode = X_GLXCreatePixmap; + if (attrib_list) memcpy(data, attrib_list, 8 * i); @@ -469,8 +482,9 @@ CreateDrawable(Display *dpy, struct glx_config *config, return None; } - if (!CreateDRIDrawable(dpy, config, drawable, xid, attrib_list, i)) { - if (glxCode == X_GLXCreatePixmap) + if (!CreateDRIDrawable(dpy, config, drawable, xid, type, attrib_list, i)) { + CARD8 glxCode; + if (type == GLX_PIXMAP_BIT) glxCode = X_GLXDestroyPixmap; else glxCode = X_GLXDestroyWindow; @@ -488,14 +502,10 @@ CreateDrawable(Display *dpy, struct glx_config *config, static void DestroyDrawable(Display * dpy, GLXDrawable drawable, CARD32 glxCode) { - if ((dpy == NULL) || (drawable == 0)) { - return; - } - protocolDestroyDrawable(dpy, drawable, glxCode); DestroyGLXDrawable(dpy, drawable); - DestroyDRIDrawable(dpy, drawable, GL_FALSE); + DestroyDRIDrawable(dpy, drawable); return; } @@ -506,10 +516,6 @@ DestroyDrawable(Display * dpy, GLXDrawable drawable, CARD32 glxCode) * * 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. */ static GLXDrawable CreatePbuffer(Display * dpy, struct glx_config *config, @@ -521,9 +527,6 @@ CreatePbuffer(Display * dpy, struct glx_config *config, CARD32 *data; CARD8 opcode; unsigned int i; - Pixmap pixmap; - GLboolean glx_1_3 = GL_FALSE; - int depth = config->rgbBits; if (priv == NULL) return None; @@ -541,46 +544,24 @@ CreatePbuffer(Display * dpy, struct glx_config *config, LockDisplay(dpy); id = XAllocID(dpy); - if (priv->minorVersion >= 3) { - 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 = config->screen; - req->fbconfig = config->fbconfigID; - req->pbuffer = id; - req->numAttribs = 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; + xGLXCreatePbufferReq *req; + unsigned int extra = (size_in_attribs) ? 0 : 2; + GetReqExtra(GLXCreatePbuffer, (8 * (i + extra)), req); + data = (CARD32 *) (req + 1); - data[0] = config->screen; - data[1] = config->fbconfigID; - data[2] = id; - data[3] = width; - data[4] = height; - data += 5; + req->reqType = opcode; + req->glxCode = X_GLXCreatePbuffer; + 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; + data[(2 * i) + 1] = width; + data[(2 * i) + 2] = GLX_PBUFFER_HEIGHT; + data[(2 * i) + 3] = height; + data += 4; } (void) memcpy(data, attrib_list, sizeof(CARD32) * 2 * i); @@ -588,16 +569,9 @@ CreatePbuffer(Display * dpy, struct glx_config *config, UnlockDisplay(dpy); SyncHandle(); - if (depth == 30) - depth = 32; - - pixmap = XCreatePixmap(dpy, RootWindow(dpy, config->screen), - width, height, depth); - - 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); + /* xserver created a pixmap with the same id as pbuffer */ + if (!CreateDRIDrawable(dpy, config, id, id, GLX_PBUFFER_BIT, attrib_list, i)) { + protocolDestroyDrawable(dpy, id, X_GLXDestroyPbuffer); id = None; } @@ -609,10 +583,6 @@ CreatePbuffer(Display * dpy, struct glx_config *config, * * 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) @@ -630,32 +600,16 @@ DestroyPbuffer(Display * dpy, GLXDrawable drawable) LockDisplay(dpy); - if (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; - } + xGLXDestroyPbufferReq *req; + GetReq(GLXDestroyPbuffer, req); + req->reqType = opcode; + req->glxCode = X_GLXDestroyPbuffer; + req->pbuffer = (GLXPbuffer) drawable; UnlockDisplay(dpy); SyncHandle(); - DestroyDRIDrawable(dpy, drawable, GL_TRUE); + DestroyDRIDrawable(dpy, drawable); return; } @@ -909,7 +863,7 @@ glXCreatePixmap(Display * dpy, GLXFBConfig config, Pixmap pixmap, return pixmap; #else return CreateDrawable(dpy, (struct glx_config *) config, - (Drawable) pixmap, attrib_list, X_GLXCreatePixmap); + (Drawable) pixmap, GLX_PIXMAP_BIT, attrib_list); #endif } @@ -943,7 +897,7 @@ glXCreateWindow(Display * dpy, GLXFBConfig config, Window win, return win; #else return CreateDrawable(dpy, (struct glx_config *) config, - (Drawable) win, attrib_list, X_GLXCreateWindow); + (Drawable) win, GLX_WINDOW_BIT, attrib_list); #endif } @@ -983,3 +937,99 @@ GLX_ALIAS_VOID(glXGetSelectedEventSGIX, (Display * dpy, GLXDrawable drawable, unsigned long *mask), (dpy, drawable, mask), glXGetSelectedEvent) + +_GLX_PUBLIC GLXPixmap +glXCreateGLXPixmap(Display * dpy, XVisualInfo * vis, Pixmap pixmap) +{ +#ifdef GLX_USE_APPLEGL + int screen = vis->screen; + struct glx_screen *const psc = GetGLXScreenConfigs(dpy, screen); + const struct glx_config *config; + + config = glx_config_find_visual(psc->visuals, vis->visualid); + + if(apple_glx_pixmap_create(dpy, vis->screen, pixmap, config)) + return None; + + return pixmap; +#else + xGLXCreateGLXPixmapReq *req; + struct glx_drawable *glxDraw; + GLXPixmap xid; + CARD8 opcode; + +#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) + struct glx_display *const priv = __glXInitialize(dpy); + + if (priv == NULL) + return None; +#endif + + opcode = __glXSetupForCommand(dpy); + if (!opcode) { + return None; + } + + glxDraw = malloc(sizeof(*glxDraw)); + if (!glxDraw) + return None; + + /* Send the glXCreateGLXPixmap request */ + LockDisplay(dpy); + GetReq(GLXCreateGLXPixmap, req); + req->reqType = opcode; + req->glxCode = X_GLXCreateGLXPixmap; + req->screen = vis->screen; + req->visual = vis->visualid; + req->pixmap = pixmap; + req->glxpixmap = xid = XAllocID(dpy); + UnlockDisplay(dpy); + SyncHandle(); + + if (InitGLXDrawable(dpy, glxDraw, pixmap, req->glxpixmap)) { + free(glxDraw); + return None; + } + +#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) + do { + /* FIXME: Maybe delay __DRIdrawable creation until the drawable + * is actually bound to a context... */ + + struct glx_screen *psc = GetGLXScreenConfigs(dpy, vis->screen); + struct glx_config *config = glx_config_find_visual(psc->visuals, + vis->visualid); + + if (!CreateDRIDrawable(dpy, config, pixmap, xid, GLX_PIXMAP_BIT, + NULL, 0)) { + protocolDestroyDrawable(dpy, xid, X_GLXDestroyGLXPixmap); + xid = None; + } + } while (0); +#endif + + return xid; +#endif +} + +/* +** Destroy the named pixmap +*/ +_GLX_PUBLIC void +glXDestroyGLXPixmap(Display * dpy, GLXPixmap glxpixmap) +{ +#ifdef GLX_USE_APPLEGL + if(apple_glx_pixmap_destroy(dpy, glxpixmap)) + __glXSendError(dpy, GLXBadPixmap, glxpixmap, X_GLXDestroyPixmap, false); +#else + DestroyDrawable(dpy, glxpixmap, X_GLXDestroyGLXPixmap); +#endif /* GLX_USE_APPLEGL */ +} + +_GLX_PUBLIC GLXPixmap +glXCreateGLXPixmapWithConfigSGIX(Display * dpy, + GLXFBConfigSGIX fbconfig, + Pixmap pixmap) +{ + return glXCreatePixmap(dpy, fbconfig, pixmap, NULL); +} |