mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-28 08:10:09 +01:00
glx: implement drawable refcounting.
The current dri context unbind logic will leak drawables until the process dies (they will then get released by the GEM code). There are two ways to fix this: either always call driReleaseDrawables every time we unbind a context (but that costs us round trips to the X server at getbuffers() time) or implement proper drawable refcounting. This patch implements the latter. Signed-off-by: Antoine Labour <piman@chromium.org> Signed-off-by: Stéphane Marchesin <marcheu@chromium.org> Reviewed-by: Adam Jackson <ajax@redhat.com>
This commit is contained in:
parent
8173471fc2
commit
bf69ce37f0
6 changed files with 37 additions and 21 deletions
|
|
@ -143,6 +143,8 @@ dri2_bind_context(struct glx_context *context, struct glx_context *old,
|
|||
pdraw = (struct dri2_drawable *) driFetchDrawable(context, draw);
|
||||
pread = (struct dri2_drawable *) driFetchDrawable(context, read);
|
||||
|
||||
driReleaseDrawables(&pcp->base);
|
||||
|
||||
if (pdraw == NULL || pread == NULL)
|
||||
return GLXBadDrawable;
|
||||
|
||||
|
|
@ -170,9 +172,6 @@ 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);
|
||||
|
||||
if (context == new)
|
||||
driReleaseDrawables(&pcp->base);
|
||||
}
|
||||
|
||||
static struct glx_context *
|
||||
|
|
|
|||
|
|
@ -369,8 +369,10 @@ driFetchDrawable(struct glx_context *gc, GLXDrawable glxDrawable)
|
|||
if (priv->drawHash == NULL)
|
||||
return NULL;
|
||||
|
||||
if (__glxHashLookup(priv->drawHash, glxDrawable, (void *) &pdraw) == 0)
|
||||
if (__glxHashLookup(priv->drawHash, glxDrawable, (void *) &pdraw) == 0) {
|
||||
pdraw->refcount ++;
|
||||
return pdraw;
|
||||
}
|
||||
|
||||
pdraw = psc->driScreen->createDrawable(psc, glxDrawable,
|
||||
glxDrawable, gc->config);
|
||||
|
|
@ -378,6 +380,7 @@ driFetchDrawable(struct glx_context *gc, GLXDrawable glxDrawable)
|
|||
(*pdraw->destroyDrawable) (pdraw);
|
||||
return NULL;
|
||||
}
|
||||
pdraw->refcount = 1;
|
||||
|
||||
return pdraw;
|
||||
}
|
||||
|
|
@ -394,19 +397,28 @@ driReleaseDrawables(struct glx_context *gc)
|
|||
if (__glxHashLookup(priv->drawHash,
|
||||
gc->currentDrawable, (void *) &pdraw) == 0) {
|
||||
if (pdraw->drawable == pdraw->xDrawable) {
|
||||
(*pdraw->destroyDrawable)(pdraw);
|
||||
__glxHashDelete(priv->drawHash, gc->currentDrawable);
|
||||
pdraw->refcount --;
|
||||
if (pdraw->refcount == 0) {
|
||||
(*pdraw->destroyDrawable)(pdraw);
|
||||
__glxHashDelete(priv->drawHash, gc->currentDrawable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (gc->currentDrawable != gc->currentReadable &&
|
||||
__glxHashLookup(priv->drawHash,
|
||||
if (__glxHashLookup(priv->drawHash,
|
||||
gc->currentReadable, (void *) &pdraw) == 0) {
|
||||
if (pdraw->drawable == pdraw->xDrawable) {
|
||||
(*pdraw->destroyDrawable)(pdraw);
|
||||
__glxHashDelete(priv->drawHash, gc->currentReadable);
|
||||
pdraw->refcount --;
|
||||
if (pdraw->refcount == 0) {
|
||||
(*pdraw->destroyDrawable)(pdraw);
|
||||
__glxHashDelete(priv->drawHash, gc->currentReadable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
gc->currentDrawable = None;
|
||||
gc->currentReadable = None;
|
||||
|
||||
}
|
||||
|
||||
#endif /* GLX_DIRECT_RENDERING */
|
||||
|
|
|
|||
|
|
@ -503,6 +503,8 @@ dri_destroy_context(struct glx_context * context)
|
|||
struct dri_context *pcp = (struct dri_context *) context;
|
||||
struct dri_screen *psc = (struct dri_screen *) context->psc;
|
||||
|
||||
driReleaseDrawables(&pcp->base);
|
||||
|
||||
if (context->xid)
|
||||
glx_send_destroy_context(psc->base.dpy, context->xid);
|
||||
|
||||
|
|
@ -526,6 +528,8 @@ dri_bind_context(struct glx_context *context, struct glx_context *old,
|
|||
pdraw = (struct dri_drawable *) driFetchDrawable(context, draw);
|
||||
pread = (struct dri_drawable *) driFetchDrawable(context, read);
|
||||
|
||||
driReleaseDrawables(&pcp->base);
|
||||
|
||||
if (pdraw == NULL || pread == NULL)
|
||||
return GLXBadDrawable;
|
||||
|
||||
|
|
@ -543,8 +547,6 @@ 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 = {
|
||||
|
|
|
|||
|
|
@ -242,6 +242,8 @@ drisw_destroy_context(struct glx_context *context)
|
|||
struct drisw_context *pcp = (struct drisw_context *) context;
|
||||
struct drisw_screen *psc = (struct drisw_screen *) context->psc;
|
||||
|
||||
driReleaseDrawables(&pcp->base);
|
||||
|
||||
if (context->xid)
|
||||
glx_send_destroy_context(psc->base.dpy, context->xid);
|
||||
|
||||
|
|
@ -264,6 +266,8 @@ drisw_bind_context(struct glx_context *context, struct glx_context *old,
|
|||
pdraw = (struct drisw_drawable *) driFetchDrawable(context, draw);
|
||||
pread = (struct drisw_drawable *) driFetchDrawable(context, read);
|
||||
|
||||
driReleaseDrawables(&pcp->base);
|
||||
|
||||
if (pdraw == NULL || pread == NULL)
|
||||
return GLXBadDrawable;
|
||||
|
||||
|
|
@ -281,8 +285,6 @@ 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 = {
|
||||
|
|
|
|||
|
|
@ -138,6 +138,7 @@ struct __GLXDRIdrawableRec
|
|||
GLenum textureTarget;
|
||||
GLenum textureFormat; /* EXT_texture_from_pixmap support */
|
||||
unsigned long eventMask;
|
||||
int refcount;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -255,8 +255,6 @@ MakeContextCurrent(Display * dpy, GLXDrawable draw,
|
|||
if (--oldGC->thread_refcount == 0) {
|
||||
oldGC->vtable->unbind(oldGC, gc);
|
||||
oldGC->currentDpy = 0;
|
||||
oldGC->currentDrawable = None;
|
||||
oldGC->currentReadable = None;
|
||||
|
||||
if (oldGC->xid == None && oldGC != gc) {
|
||||
/* We are switching away from a context that was
|
||||
|
|
@ -268,13 +266,15 @@ MakeContextCurrent(Display * dpy, GLXDrawable draw,
|
|||
}
|
||||
|
||||
if (gc) {
|
||||
if (gc->thread_refcount++ == 0) {
|
||||
gc->currentDpy = dpy;
|
||||
gc->currentDrawable = draw;
|
||||
gc->currentReadable = read;
|
||||
}
|
||||
if (gc->thread_refcount == 0)
|
||||
gc->currentDpy = dpy;
|
||||
__glXSetCurrentContext(gc);
|
||||
ret = gc->vtable->bind(gc, oldGC, draw, read);
|
||||
if (gc->thread_refcount == 0) {
|
||||
gc->currentDrawable = draw;
|
||||
gc->currentReadable = read;
|
||||
}
|
||||
gc->thread_refcount++;
|
||||
} else {
|
||||
__glXSetCurrentContextNull();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue