diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/glx/dri2.c | 8 | ||||
-rw-r--r-- | src/glx/dri2_glx.c | 4 | ||||
-rw-r--r-- | src/glx/dri_common.c | 25 | ||||
-rw-r--r-- | src/glx/dri_common.h | 3 | ||||
-rw-r--r-- | src/glx/dri_glx.c | 4 | ||||
-rw-r--r-- | src/glx/drisw_glx.c | 4 | ||||
-rw-r--r-- | src/glx/glxcmds.c | 50 | ||||
-rw-r--r-- | src/glx/glxcurrent.c | 6 | ||||
-rw-r--r-- | src/glx/indirect_glx.c | 3 |
9 files changed, 48 insertions, 59 deletions
diff --git a/src/glx/dri2.c b/src/glx/dri2.c index d70ec5a3ec..d410898648 100644 --- a/src/glx/dri2.c +++ b/src/glx/dri2.c @@ -175,6 +175,14 @@ DRI2Error(Display *display, xError *err, XExtCodes *codes, int *ret_code) err->minorCode == X_DRI2CopyRegion) return True; + /* If the X drawable was destroyed before the GLX drawable, the + * DRI2 drawble will be gone by the time we call + * DRI2DestroyDrawable. So just ignore BadDrawable here. */ + if (err->majorCode == codes->major_opcode && + err->errorCode == BadDrawable && + err->minorCode == X_DRI2DestroyDrawable) + return True; + return False; } diff --git a/src/glx/dri2_glx.c b/src/glx/dri2_glx.c index ff48c79c27..e38a40ce53 100644 --- a/src/glx/dri2_glx.c +++ b/src/glx/dri2_glx.c @@ -124,8 +124,6 @@ dri2_destroy_context(struct glx_context *context) if (context->extensions) XFree((char *) context->extensions); - GarbageCollectDRIDrawables(context->psc); - (*psc->core->destroyContext) (pcp->driContext); Xfree(pcp); @@ -159,6 +157,8 @@ dri2_unbind_context(struct glx_context *context, struct glx_context *new) struct dri2_screen *psc = (struct dri2_screen *) pcp->base.psc; (*psc->core->unbindContext) (pcp->driContext); + + driReleaseDrawables(&pcp->base); } static struct glx_context * diff --git a/src/glx/dri_common.c b/src/glx/dri_common.c index a7fb4c6424..5fb5255416 100644 --- a/src/glx/dri_common.c +++ b/src/glx/dri_common.c @@ -380,4 +380,29 @@ driFetchDrawable(struct glx_context *gc, GLXDrawable glxDrawable) return pdraw; } +_X_HIDDEN void +driReleaseDrawables(struct glx_context *gc) +{ + struct glx_display *const priv = __glXInitialize(gc->psc->dpy); + __GLXDRIdrawable *pdraw; + + if (priv == NULL) + return; + + if (__glxHashLookup(priv->drawHash, + gc->currentDrawable, (void *) &pdraw) == 0) { + if (pdraw->drawable == pdraw->xDrawable) + (*pdraw->destroyDrawable)(pdraw); + __glxHashDelete(priv->drawHash, gc->currentDrawable); + } + + if (gc->currentDrawable != gc->currentReadable && + __glxHashLookup(priv->drawHash, + gc->currentReadable, (void *) &pdraw) == 0) { + if (pdraw->drawable == pdraw->xDrawable) + (*pdraw->destroyDrawable)(pdraw); + __glxHashDelete(priv->drawHash, gc->currentReadable); + } +} + #endif /* GLX_DIRECT_RENDERING */ diff --git a/src/glx/dri_common.h b/src/glx/dri_common.h index 846a905a88..13b5ae471d 100644 --- a/src/glx/dri_common.h +++ b/src/glx/dri_common.h @@ -55,6 +55,9 @@ extern void driDestroyConfigs(const __DRIconfig **configs); extern __GLXDRIdrawable * driFetchDrawable(struct glx_context *gc, GLXDrawable glxDrawable); +extern void +driReleaseDrawables(struct glx_context *gc); + extern const __DRIsystemTimeExtension systemTimeExtension; extern void InfoMessageF(const char *f, ...); diff --git a/src/glx/dri_glx.c b/src/glx/dri_glx.c index 43a2aa495a..42b263c637 100644 --- a/src/glx/dri_glx.c +++ b/src/glx/dri_glx.c @@ -509,8 +509,6 @@ dri_destroy_context(struct glx_context * context) if (context->extensions) XFree((char *) context->extensions); - GarbageCollectDRIDrawables(context->psc); - (*psc->core->destroyContext) (pcp->driContext); XF86DRIDestroyContext(psc->base.dpy, psc->base.scr, pcp->hwContextID); @@ -545,6 +543,8 @@ dri_unbind_context(struct glx_context *context, struct glx_context *new) struct dri_screen *psc = (struct dri_screen *) pcp->base.psc; (*psc->core->unbindContext) (pcp->driContext); + + driReleaseDrawables(&pcp->base); } static const struct glx_context_vtable dri_context_vtable = { diff --git a/src/glx/drisw_glx.c b/src/glx/drisw_glx.c index c5b179157b..237ce17617 100644 --- a/src/glx/drisw_glx.c +++ b/src/glx/drisw_glx.c @@ -250,8 +250,6 @@ drisw_destroy_context(struct glx_context *context) if (context->extensions) XFree((char *) context->extensions); - GarbageCollectDRIDrawables(context->psc); - (*psc->core->destroyContext) (pcp->driContext); Xfree(pcp); @@ -285,6 +283,8 @@ drisw_unbind_context(struct glx_context *context, struct glx_context *new) struct drisw_screen *psc = (struct drisw_screen *) pcp->base.psc; (*psc->core->unbindContext) (pcp->driContext); + + driReleaseDrawables(&pcp->base); } static const struct glx_context_vtable drisw_context_vtable = { diff --git a/src/glx/glxcmds.c b/src/glx/glxcmds.c index 9575156080..4f7e84ef5f 100644 --- a/src/glx/glxcmds.c +++ b/src/glx/glxcmds.c @@ -63,56 +63,6 @@ static const char __glXGLXClientVersion[] = "1.4"; #if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL) -static Bool windowExistsFlag; -static int -windowExistsErrorHandler(Display * dpy, XErrorEvent * xerr) -{ - (void) dpy; - - if (xerr->error_code == BadWindow) { - windowExistsFlag = GL_FALSE; - } - return 0; -} - -/** - * Find drawables in the local hash that have been destroyed on the - * server. - * - * \param dpy Display to destroy drawables for - * \param screen Screen number to destroy drawables for - */ -_X_HIDDEN void -GarbageCollectDRIDrawables(struct glx_screen * sc) -{ - XID draw; - __GLXDRIdrawable *pdraw; - struct glx_display *priv = sc->display; - XWindowAttributes xwa; - int (*oldXErrorHandler) (Display *, XErrorEvent *); - - /* Set no-op error handler so Xlib doesn't bail out if the windows - * has alreay been destroyed on the server. */ - XSync(priv->dpy, GL_FALSE); - oldXErrorHandler = XSetErrorHandler(windowExistsErrorHandler); - - if (__glxHashFirst(priv->drawHash, &draw, (void *) &pdraw) == 1) { - do { - windowExistsFlag = GL_TRUE; - XGetWindowAttributes(priv->dpy, draw, &xwa); /* dummy request */ - if (!windowExistsFlag) { - /* Destroy the local drawable data, if the drawable no - longer exists in the Xserver */ - (*pdraw->destroyDrawable) (pdraw); - __glxHashDelete(priv->drawHash, draw); - } - } while (__glxHashNext(priv->drawHash, &draw, (void *) &pdraw) == 1); - } - - XSync(priv->dpy, GL_FALSE); - XSetErrorHandler(oldXErrorHandler); -} - /** * Get the __DRIdrawable for the drawable associated with a GLXContext * diff --git a/src/glx/glxcurrent.c b/src/glx/glxcurrent.c index 98f66c2289..710985b02c 100644 --- a/src/glx/glxcurrent.c +++ b/src/glx/glxcurrent.c @@ -242,13 +242,13 @@ MakeContextCurrent(Display * dpy, GLXDrawable draw, return False; } - if (oldGC != &dummyContext && oldGC != gc) { + if (oldGC != &dummyContext) { oldGC->vtable->unbind(oldGC, gc); oldGC->currentDpy = 0; oldGC->currentDrawable = None; oldGC->currentReadable = None; oldGC->thread_id = 0; - if (oldGC->xid == None) + if (oldGC->xid == None && oldGC != gc) /* We are switching away from a context that was * previously destroyed, so we need to free the memory * for the old handle. @@ -257,12 +257,12 @@ MakeContextCurrent(Display * dpy, GLXDrawable draw, } if (gc) { - ret = gc->vtable->bind(gc, oldGC, draw, read); gc->currentDpy = dpy; gc->currentDrawable = draw; gc->currentReadable = read; gc->thread_id = _glthread_GetID(); __glXSetCurrentContext(gc); + ret = gc->vtable->bind(gc, oldGC, draw, read); } else { __glXSetCurrentContextNull(); } diff --git a/src/glx/indirect_glx.c b/src/glx/indirect_glx.c index 61ceed3d43..1870edee37 100644 --- a/src/glx/indirect_glx.c +++ b/src/glx/indirect_glx.c @@ -168,6 +168,9 @@ indirect_unbind_context(struct glx_context *gc, struct glx_context *new) int opcode = __glXSetupForCommand(dpy); xGLXMakeCurrentReply reply; + if (gc == new) + return; + /* We are either switching to no context, away from a indirect * context to a direct context or from one dpy to another and have * to send a request to the dpy to unbind the previous context. |