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;
}
if (context->extensions)
XFree((char *) context->extensions);
- GarbageCollectDRIDrawables(context->psc);
-
(*psc->core->destroyContext) (pcp->driContext);
Xfree(pcp);
struct dri2_screen *psc = (struct dri2_screen *) pcp->base.psc;
(*psc->core->unbindContext) (pcp->driContext);
+
+ driReleaseDrawables(&pcp->base);
}
static struct glx_context *
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 */
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, ...);
if (context->extensions)
XFree((char *) context->extensions);
- GarbageCollectDRIDrawables(context->psc);
-
(*psc->core->destroyContext) (pcp->driContext);
XF86DRIDestroyContext(psc->base.dpy, psc->base.scr, pcp->hwContextID);
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 = {
if (context->extensions)
XFree((char *) context->extensions);
- GarbageCollectDRIDrawables(context->psc);
-
(*psc->core->destroyContext) (pcp->driContext);
Xfree(pcp);
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 = {
#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
*
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.
}
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();
}
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.