summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/glx/dri2.c8
-rw-r--r--src/glx/dri2_glx.c4
-rw-r--r--src/glx/dri_common.c25
-rw-r--r--src/glx/dri_common.h3
-rw-r--r--src/glx/dri_glx.c4
-rw-r--r--src/glx/drisw_glx.c4
-rw-r--r--src/glx/glxcmds.c50
-rw-r--r--src/glx/glxcurrent.c6
-rw-r--r--src/glx/indirect_glx.c3
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.