summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichel Dänzer <michel@tungstengraphics.com>2007-07-10 09:02:08 +0200
committerMichel Dänzer <michel@tungstengraphics.com>2007-07-10 09:02:08 +0200
commit4abd00dab7e648dab8172f6009371e4e63d0c521 (patch)
tree5e14974581a23fbedf33a221f050ede09d6d2baa
parent5957aa6fdc580ccad4557eeefa0636ffad823f33 (diff)
Make sure DRI drawables are cleaned up when client dies.
The previous scheme didn't work when the client didn't create the core drawable, e.g. the root or composite overlay window. Use refcounting via special client resources to fix that.
-rw-r--r--GL/glx/glxdri.c26
-rw-r--r--GL/glx/glxext.c7
-rw-r--r--GL/glx/glxserver.h2
-rw-r--r--hw/xfree86/dri/dri.c139
-rw-r--r--hw/xfree86/dri/dri.h6
-rw-r--r--hw/xfree86/dri/dristruct.h1
-rw-r--r--hw/xfree86/dri/xf86dri.c11
7 files changed, 130 insertions, 62 deletions
diff --git a/GL/glx/glxdri.c b/GL/glx/glxdri.c
index efa02f842..db564c098 100644
--- a/GL/glx/glxdri.c
+++ b/GL/glx/glxdri.c
@@ -758,9 +758,16 @@ static __DRIscreen *findScreen(__DRInativeDisplay *dpy, int scrn)
static GLboolean windowExists(__DRInativeDisplay *dpy, __DRIid draw)
{
- WindowPtr pWin = (WindowPtr) LookupIDByType(draw, RT_WINDOW);
-
- return pWin == NULL ? GL_FALSE : GL_TRUE;
+ DrawablePtr pDrawable = (DrawablePtr) LookupIDByType(draw, RT_WINDOW);
+ int unused;
+ drm_clip_rect_t *pRects;
+
+ return pDrawable ? DRIGetDrawableInfo(pDrawable->pScreen, pDrawable,
+ (unsigned*)&unused, (unsigned*)&unused,
+ &unused, &unused, &unused, &unused,
+ &unused, &pRects, &unused, &unused,
+ &unused, &pRects)
+ : GL_FALSE;
}
static GLboolean createContext(__DRInativeDisplay *dpy, int screen,
@@ -815,10 +822,8 @@ createDrawable(__DRInativeDisplay *dpy, int screen,
return GL_FALSE;
__glXDRIenterServer(GL_FALSE);
- retval = DRICreateDrawable(screenInfo.screens[screen],
- drawable,
- pDrawable,
- hHWDrawable);
+ retval = DRICreateDrawable(screenInfo.screens[screen], __pGlxClient,
+ pDrawable, hHWDrawable);
__glXDRIleaveServer(GL_FALSE);
return retval;
}
@@ -834,9 +839,8 @@ destroyDrawable(__DRInativeDisplay *dpy, int screen, __DRIid drawable)
return GL_FALSE;
__glXDRIenterServer(GL_FALSE);
- retval = DRIDestroyDrawable(screenInfo.screens[screen],
- drawable,
- pDrawable);
+ retval = DRIDestroyDrawable(screenInfo.screens[screen], __pGlxClient,
+ pDrawable);
__glXDRIleaveServer(GL_FALSE);
return retval;
}
@@ -927,7 +931,7 @@ getDrawableInfo(__DRInativeDisplay *dpy, int screen,
*ppBackClipRects = NULL;
}
- return GL_TRUE;
+ return retval;
}
static int
diff --git a/GL/glx/glxext.c b/GL/glx/glxext.c
index c09120c12..b4f3105aa 100644
--- a/GL/glx/glxext.c
+++ b/GL/glx/glxext.c
@@ -62,6 +62,11 @@ xGLXSingleReply __glXReply;
static __GLXclientState *__glXClients[MAXCLIENTS + 1];
/*
+** Client that called into GLX dispatch.
+*/
+ClientPtr __pGlxClient;
+
+/*
** Forward declarations.
*/
static int __glXDispatch(ClientPtr);
@@ -549,6 +554,8 @@ static int __glXDispatch(ClientPtr client)
GLboolean rendering = opcode <= X_GLXRenderLarge;
__glXleaveServer(rendering);
+ __pGlxClient = client;
+
retval = (*proc)(cl, (GLbyte *) stuff);
__glXenterServer(rendering);
diff --git a/GL/glx/glxserver.h b/GL/glx/glxserver.h
index fa09c1546..b6b55927e 100644
--- a/GL/glx/glxserver.h
+++ b/GL/glx/glxserver.h
@@ -110,6 +110,8 @@ void __glXScreenInitVisuals(__GLXscreen *screen);
extern __GLXcontext *__glXLastContext;
extern __GLXcontext *__glXForceCurrent(__GLXclientState*, GLXContextTag, int*);
+extern ClientPtr __pGlxClient;
+
int __glXError(int error);
/*
diff --git a/hw/xfree86/dri/dri.c b/hw/xfree86/dri/dri.c
index 2a53eae1a..6c640d806 100644
--- a/hw/xfree86/dri/dri.c
+++ b/hw/xfree86/dri/dri.c
@@ -593,6 +593,10 @@ DRIFinishScreenInit(ScreenPtr pScreen)
pDRIPriv->wrap.WindowExposures = pScreen->WindowExposures;
pScreen->WindowExposures = pDRIInfo->wrap.WindowExposures;
}
+
+ pDRIPriv->DestroyWindow = pScreen->DestroyWindow;
+ pScreen->DestroyWindow = DRIDestroyWindow;
+
if (pDRIInfo->wrap.CopyWindow) {
pDRIPriv->wrap.CopyWindow = pScreen->CopyWindow;
pScreen->CopyWindow = pDRIInfo->wrap.CopyWindow;
@@ -642,6 +646,10 @@ DRICloseScreen(ScreenPtr pScreen)
pScreen->WindowExposures = pDRIPriv->wrap.WindowExposures;
pDRIPriv->wrap.WindowExposures = NULL;
}
+ if (pDRIPriv->DestroyWindow) {
+ pScreen->DestroyWindow = pDRIPriv->DestroyWindow;
+ pDRIPriv->DestroyWindow = NULL;
+ }
if (pDRIInfo->wrap.CopyWindow) {
pScreen->CopyWindow = pDRIPriv->wrap.CopyWindow;
pDRIPriv->wrap.CopyWindow = NULL;
@@ -1248,8 +1256,8 @@ DRIDecreaseNumberVisible(ScreenPtr pScreen)
}
Bool
-DRICreateDrawable(ScreenPtr pScreen, Drawable id,
- DrawablePtr pDrawable, drm_drawable_t * hHWDrawable)
+DRICreateDrawable(ScreenPtr pScreen, ClientPtr client, DrawablePtr pDrawable,
+ drm_drawable_t * hHWDrawable)
{
DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
DRIDrawablePrivPtr pDRIDrawablePriv;
@@ -1291,11 +1299,12 @@ DRICreateDrawable(ScreenPtr pScreen, Drawable id,
if (pDRIDrawablePriv->nrects)
DRIIncreaseNumberVisible(pScreen);
-
- /* track this in case this window is destroyed */
- AddResource(id, DRIDrawablePrivResType, (pointer)pWin);
}
+ /* track this in case the client dies */
+ AddResource(FakeClientID(client->index), DRIDrawablePrivResType,
+ (pointer)pDrawable->id);
+
if (pDRIDrawablePriv->hwDrawable) {
drmUpdateDrawableInfo(pDRIPriv->drmFD,
pDRIDrawablePriv->hwDrawable,
@@ -1313,21 +1322,59 @@ DRICreateDrawable(ScreenPtr pScreen, Drawable id,
return TRUE;
}
-Bool
-DRIDestroyDrawable(ScreenPtr pScreen, Drawable id, DrawablePtr pDrawable)
+static void
+DRIDrawablePrivDestroy(WindowPtr pWin)
{
- DRIDrawablePrivPtr pDRIDrawablePriv;
- WindowPtr pWin;
+ DRIDrawablePrivPtr pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
+ ScreenPtr pScreen;
+ DRIScreenPrivPtr pDRIPriv;
+
+ if (!pDRIDrawablePriv)
+ return;
+
+ pScreen = pWin->drawable.pScreen;
+ pDRIPriv = DRI_SCREEN_PRIV(pScreen);
+
+ if (pDRIDrawablePriv->drawableIndex != -1) {
+ /* bump stamp to force outstanding 3D requests to resync */
+ pDRIPriv->pSAREA->drawableTable[pDRIDrawablePriv->drawableIndex].stamp
+ = DRIDrawableValidationStamp++;
+
+ /* release drawable table entry */
+ pDRIPriv->DRIDrawables[pDRIDrawablePriv->drawableIndex] = NULL;
+ }
+
+ pDRIPriv->nrWindows--;
+
+ if (pDRIDrawablePriv->nrects)
+ DRIDecreaseNumberVisible(pScreen);
+
+ drmDestroyDrawable(pDRIPriv->drmFD, pDRIDrawablePriv->hwDrawable);
+
+ xfree(pDRIDrawablePriv);
+ pWin->devPrivates[DRIWindowPrivIndex].ptr = NULL;
+}
+
+static Bool
+DRIDestroyDrawableCB(pointer value, XID id, pointer data)
+{
+ if (value == data) {
+ /* This calls back DRIDrawablePrivDelete which frees private area */
+ FreeResourceByType(id, DRIDrawablePrivResType, FALSE);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+Bool
+DRIDestroyDrawable(ScreenPtr pScreen, ClientPtr client, DrawablePtr pDrawable)
+{
if (pDrawable->type == DRAWABLE_WINDOW) {
- pWin = (WindowPtr)pDrawable;
- pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
- pDRIDrawablePriv->refCount--;
- if (pDRIDrawablePriv->refCount <= 0) {
- /* This calls back DRIDrawablePrivDelete which frees private area */
- FreeResourceByType(id, DRIDrawablePrivResType, FALSE);
- }
+ LookupClientResourceComplex(client, DRIDrawablePrivResType,
+ DRIDestroyDrawableCB,
+ (pointer)pDrawable->id);
}
else { /* pixmap (or for GLX 1.3, a PBuffer) */
/* NOT_DONE */
@@ -1340,43 +1387,26 @@ DRIDestroyDrawable(ScreenPtr pScreen, Drawable id, DrawablePtr pDrawable)
Bool
DRIDrawablePrivDelete(pointer pResource, XID id)
{
- DrawablePtr pDrawable = (DrawablePtr)pResource;
- DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pDrawable->pScreen);
- DRIDrawablePrivPtr pDRIDrawablePriv;
- WindowPtr pWin;
-
- if (pDrawable->type == DRAWABLE_WINDOW) {
- pWin = (WindowPtr)pDrawable;
- pDRIDrawablePriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
+ WindowPtr pWin;
- if (pDRIDrawablePriv->drawableIndex != -1) {
- /* bump stamp to force outstanding 3D requests to resync */
- pDRIPriv->pSAREA->drawableTable[pDRIDrawablePriv->drawableIndex].stamp
- = DRIDrawableValidationStamp++;
+ id = (XID)pResource;
+ pWin = LookupIDByType(id, RT_WINDOW);
- /* release drawable table entry */
- pDRIPriv->DRIDrawables[pDRIDrawablePriv->drawableIndex] = NULL;
- }
+ if (pWin) {
+ DRIDrawablePrivPtr pDRIDrwPriv = DRI_DRAWABLE_PRIV_FROM_WINDOW(pWin);
- if (drmDestroyDrawable(pDRIPriv->drmFD,
- pDRIDrawablePriv->hwDrawable)) {
+ if (!pDRIDrwPriv)
return FALSE;
- }
- xfree(pDRIDrawablePriv);
- pWin->devPrivates[DRIWindowPrivIndex].ptr = NULL;
+ if (--pDRIDrwPriv->refCount == 0)
+ DRIDrawablePrivDestroy(pWin);
- pDRIPriv->nrWindows--;
-
- if (REGION_NUM_RECTS(&pWin->clipList))
- DRIDecreaseNumberVisible(pDrawable->pScreen);
+ return TRUE;
}
else { /* pixmap (or for GLX 1.3, a PBuffer) */
/* NOT_DONE */
return FALSE;
}
-
- return TRUE;
}
Bool
@@ -1884,6 +1914,31 @@ DRITreeTraversal(WindowPtr pWin, pointer data)
return WT_WALKCHILDREN;
}
+Bool
+DRIDestroyWindow(WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ DRIScreenPrivPtr pDRIPriv = DRI_SCREEN_PRIV(pScreen);
+ Bool retval = TRUE;
+
+ DRIDrawablePrivDestroy(pWin);
+
+ /* call lower wrapped functions */
+ if(pDRIPriv->DestroyWindow) {
+ /* unwrap */
+ pScreen->DestroyWindow = pDRIPriv->DestroyWindow;
+
+ /* call lower layers */
+ retval = (*pScreen->DestroyWindow)(pWin);
+
+ /* rewrap */
+ pDRIPriv->DestroyWindow = pScreen->DestroyWindow;
+ pScreen->DestroyWindow = DRIDestroyWindow;
+ }
+
+ return retval;
+}
+
void
DRICopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
{
diff --git a/hw/xfree86/dri/dri.h b/hw/xfree86/dri/dri.h
index e49bb6fa0..c0da7001e 100644
--- a/hw/xfree86/dri/dri.h
+++ b/hw/xfree86/dri/dri.h
@@ -231,12 +231,12 @@ extern Bool DRIDestroyContext(ScreenPtr pScreen, XID context);
extern Bool DRIContextPrivDelete(pointer pResource, XID id);
extern Bool DRICreateDrawable(ScreenPtr pScreen,
- Drawable id,
+ ClientPtr client,
DrawablePtr pDrawable,
drm_drawable_t * hHWDrawable);
extern Bool DRIDestroyDrawable(ScreenPtr pScreen,
- Drawable id,
+ ClientPtr client,
DrawablePtr pDrawable);
extern Bool DRIDrawablePrivDelete(pointer pResource,
@@ -299,6 +299,8 @@ extern void DRIWindowExposures(WindowPtr pWin,
RegionPtr prgn,
RegionPtr bsreg);
+extern Bool DRIDestroyWindow(WindowPtr pWin);
+
extern void DRICopyWindow(WindowPtr pWin,
DDXPointRec ptOldOrg,
RegionPtr prgnSrc);
diff --git a/hw/xfree86/dri/dristruct.h b/hw/xfree86/dri/dristruct.h
index a3bac8556..5d981b820 100644
--- a/hw/xfree86/dri/dristruct.h
+++ b/hw/xfree86/dri/dristruct.h
@@ -99,6 +99,7 @@ typedef struct _DRIScreenPrivRec
DrawablePtr fullscreen; /* pointer to fullscreen drawable */
drm_clip_rect_t fullscreen_rect; /* fake rect for fullscreen mode */
DRIWrappedFuncsRec wrap;
+ DestroyWindowProcPtr DestroyWindow;
DrawablePtr DRIDrawables[SAREA_MAX_DRAWABLES];
DRIContextPrivPtr dummyCtxPriv; /* Pointer to dummy context */
Bool createDummyCtx;
diff --git a/hw/xfree86/dri/xf86dri.c b/hw/xfree86/dri/xf86dri.c
index 9690e8895..fdf0e9983 100644
--- a/hw/xfree86/dri/xf86dri.c
+++ b/hw/xfree86/dri/xf86dri.c
@@ -404,10 +404,8 @@ ProcXF86DRICreateDrawable(
if (rc != Success)
return rc;
- if (!DRICreateDrawable( screenInfo.screens[stuff->screen],
- (Drawable)stuff->drawable,
- pDrawable,
- (drm_drawable_t *)&rep.hHWDrawable)) {
+ if (!DRICreateDrawable(screenInfo.screens[stuff->screen], client,
+ pDrawable, (drm_drawable_t *)&rep.hHWDrawable)) {
return BadValue;
}
@@ -435,9 +433,8 @@ ProcXF86DRIDestroyDrawable(
if (rc != Success)
return rc;
- if (!DRIDestroyDrawable( screenInfo.screens[stuff->screen],
- (Drawable)stuff->drawable,
- pDrawable)) {
+ if (!DRIDestroyDrawable(screenInfo.screens[stuff->screen], client,
+ pDrawable)) {
return BadValue;
}