From 69cbca0b83a86ad1ab266314e76304ca4e35f57b Mon Sep 17 00:00:00 2001 From: Owen Taylor Date: Fri, 30 Apr 2010 13:17:18 -0400 Subject: [PATCH] Merge fixes for DRI drawable handling from master MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit commit a92b2c2c8dd1e86ee852168146f01bdf72bfe2d0 Author: Kristian Høgsberg Date: Fri Apr 16 05:55:35 2010 -0400 glx: Drop DestroyWindow hook Now that glx doesn't call DRI2DestroyDrawable anymore, we don't need to force a specific resource destruction order in the DestroyWindow hook. Signed-off-by: Kristian Høgsberg Reviewed-by: Michel Dänzer https://bugs.freedesktop.org/show_bug.cgi?id=26394 Signed-off-by: Keith Packard commit 2b3f755254675933475b068ff20bd322ffb8631f Author: Kristian Høgsberg Date: Thu, 29 Apr 2010 16:36:10 -0400 dri2: Take an XID for tracking the DRI2 drawable Some pixmaps (window pixmaps and scratch pixmaps) don't have the drawable->id set and thus DRI2 gets confused when using that field for looking up the DRI2 drawable. Go back to using privates for getting at the DRI2 drawable from a DrawablePtr. We need to keep the resource tracking in place so we can remove the DRI2 drawable when the X resource it was created for goes away. Additionally, we also now track the DRI2 drawable using a client XID so we can reclaim the DRI2 drawable even if the client goes before the drawable and doesn't destroy the DRI2 drawable. commit 1da1f33f2dd5b437dd56cd9f5d6782de4ad5a1bc Author: Kristian Høgsberg Date: Fri Apr 16 05:55:34 2010 -0400 DRI2: Track DRI2 drawables as resources, not privates The main motivation here is to have the resource system clean up the DRI2 drawable automatically so glx doesn't have to. Right now, the glx drawable resource must be destroyed before the X drawable, so that calling DRI2DestroyDrawable doesn't crash. By making the DRI2 drawable a resource, GLX doesn't have to worry about that and the resource destruction order becomes irrelevant. https://bugs.freedesktop.org/show_bug.cgi?id=26394 Signed-off-by: Kristian Høgsberg Signed-off-by: Keith Packard commit f0006aa58f6cf7552a239e169ff6e7e4fda532f4 Author: Kristian Høgsberg Date: Fri Apr 16 05:55:32 2010 -0400 glx: Track GLX 1.3 style GLX drawables under their X drawable ID as well This ensures that the DrawableGone callback gets called as necessary when the X drawable goes away. Otherwise, using a GLX drawable (say, glXSwapBuffers) in indirect mode after the X drawable has been destroyed will crash the server. Signed-off-by: Kristian Høgsberg Reviewed-by: Michel Dänzer Signed-off-by: Keith Packard commit 22da7aa9d743deee198aaf6df5d370a446db9763 Author: Kristian Høgsberg Date: Fri Apr 16 05:55:33 2010 -0400 glx: Let the resource system destroy pixmaps GLX pbuffers are implemented using a pixmap allocated by the server. With the change to DRI2 to track DRI2 drawables as resources, we need to make sure that every drawable we create a DRI2 drawable for has an XID. By using the XID of the pbuffer, the resource system will automatically reclaim the hidden pixmap and the DRI2 drawable when the pbuffer is destroyed or the client exits. Signed-off-by: Kristian Høgsberg Signed-off-by: Keith Packard --- glx/glxcmds.c | 60 ++++++++----- glx/glxdri.c | 8 +- glx/glxdri2.c | 17 ++-- glx/glxdriswrast.c | 8 +- glx/glxext.c | 11 +++ glx/glxscreens.c | 28 ------ glx/glxscreens.h | 7 +- hw/xfree86/dri2/dri2.c | 215 +++++++++++++++++++++++++++------------------ hw/xfree86/dri2/dri2.h | 3 +- hw/xfree86/dri2/dri2ext.c | 24 +----- include/list.h | 6 ++ 11 files changed, 209 insertions(+), 178 deletions(-) diff --git a/glx/glxcmds.c b/glx/glxcmds.c index 77afbf4..ec3bbe6 100644 --- a/glx/glxcmds.c +++ b/glx/glxcmds.c @@ -161,7 +161,11 @@ validGlxDrawable(ClientPtr client, XID id, int type, int access_mode, return FALSE; } + /* If the ID of the glx drawable we looked up doesn't match the id + * we looked for, it's because we looked it up under the X + * drawable ID (see DoCreateGLXDrawable). */ if (rc == BadValue || + (*drawable)->drawId != id || (type != GLX_DRAWABLE_ANY && type != (*drawable)->type)) { client->errorValue = id; switch (type) { @@ -508,8 +512,9 @@ __glXGetDrawable(__GLXcontext *glxc, GLXDrawable drawId, ClientPtr client, if (!validGlxFBConfigForWindow(client, glxc->config, pDraw, error)) return NULL; - pGlxDraw = glxc->pGlxScreen->createDrawable(glxc->pGlxScreen, - pDraw, GLX_DRAWABLE_WINDOW, + pGlxDraw = glxc->pGlxScreen->createDrawable(client, glxc->pGlxScreen, + pDraw, drawId, + GLX_DRAWABLE_WINDOW, drawId, glxc->config); /* since we are creating the drawablePrivate, drawId should be new */ @@ -1097,28 +1102,20 @@ __glXDrawableInit(__GLXdrawable *drawable, void __glXDrawableRelease(__GLXdrawable *drawable) { - ScreenPtr pScreen = drawable->pDraw->pScreen; - - switch (drawable->type) { - case GLX_DRAWABLE_PIXMAP: - case GLX_DRAWABLE_PBUFFER: - (*pScreen->DestroyPixmap)((PixmapPtr) drawable->pDraw); - break; - } } static int -DoCreateGLXDrawable(ClientPtr client, __GLXscreen *pGlxScreen, __GLXconfig *config, - DrawablePtr pDraw, XID glxDrawableId, int type) +DoCreateGLXDrawable(ClientPtr client, __GLXscreen *pGlxScreen, + __GLXconfig *config, DrawablePtr pDraw, XID drawableId, + XID glxDrawableId, int type) { __GLXdrawable *pGlxDraw; - LEGAL_NEW_RESOURCE(glxDrawableId, client); - if (pGlxScreen->pScreen != pDraw->pScreen) return BadMatch; - pGlxDraw = pGlxScreen->createDrawable(pGlxScreen, pDraw, type, + pGlxDraw = pGlxScreen->createDrawable(client, pGlxScreen, pDraw, + drawableId, type, glxDrawableId, config); if (pGlxDraw == NULL) return BadAlloc; @@ -1128,6 +1125,15 @@ DoCreateGLXDrawable(ClientPtr client, __GLXscreen *pGlxScreen, __GLXconfig *conf return BadAlloc; } + /* Add the glx drawable under the XID of the underlying X drawable + * too. That way we'll get a callback in DrawableGone and can + * clean up properly when the drawable is destroyed. */ + if (drawableId != glxDrawableId && + !AddResource(pDraw->id, __glXDrawableRes, pGlxDraw)) { + pGlxDraw->destroy (pGlxDraw); + return BadAlloc; + } + return Success; } @@ -1138,6 +1144,8 @@ DoCreateGLXPixmap(ClientPtr client, __GLXscreen *pGlxScreen, __GLXconfig *config DrawablePtr pDraw; int err; + LEGAL_NEW_RESOURCE(glxDrawableId, client); + err = dixLookupDrawable(&pDraw, drawableId, client, 0, DixAddAccess); if (err != Success) { client->errorValue = drawableId; @@ -1148,12 +1156,9 @@ DoCreateGLXPixmap(ClientPtr client, __GLXscreen *pGlxScreen, __GLXconfig *config return BadPixmap; } - err = DoCreateGLXDrawable(client, pGlxScreen, config, pDraw, + err = DoCreateGLXDrawable(client, pGlxScreen, config, pDraw, drawableId, glxDrawableId, GLX_DRAWABLE_PIXMAP); - if (err == Success) - ((PixmapPtr) pDraw)->refcnt++; - return err; } @@ -1294,6 +1299,8 @@ DoCreatePbuffer(ClientPtr client, int screenNum, XID fbconfigId, PixmapPtr pPixmap; int err; + LEGAL_NEW_RESOURCE(glxDrawableId, client); + if (!validGlxScreen(client, screenNum, &pGlxScreen, &err)) return err; if (!validGlxFBConfig(client, pGlxScreen, fbconfigId, &config, &err)) @@ -1304,8 +1311,16 @@ DoCreatePbuffer(ClientPtr client, int screenNum, XID fbconfigId, width, height, config->rgbBits, 0); __glXleaveServer(GL_FALSE); + /* Assign the pixmap the same id as the pbuffer and add it as a + * resource so it and the DRI2 drawable will be reclaimed when the + * pbuffer is destroyed. */ + pPixmap->drawable.id = glxDrawableId; + if (!AddResource(pPixmap->drawable.id, RT_PIXMAP, pPixmap)) + return BadAlloc; + return DoCreateGLXDrawable(client, pGlxScreen, config, &pPixmap->drawable, - glxDrawableId, GLX_DRAWABLE_PBUFFER); + glxDrawableId, glxDrawableId, + GLX_DRAWABLE_PBUFFER); } int __glXDisp_CreatePbuffer(__GLXclientState *cl, GLbyte *pc) @@ -1411,6 +1426,8 @@ int __glXDisp_CreateWindow(__GLXclientState *cl, GLbyte *pc) DrawablePtr pDraw; int err; + LEGAL_NEW_RESOURCE(req->glxwindow, client); + if (!validGlxScreen(client, req->screen, &pGlxScreen, &err)) return err; if (!validGlxFBConfig(client, pGlxScreen, req->fbconfig, &config, &err)) @@ -1426,7 +1443,8 @@ int __glXDisp_CreateWindow(__GLXclientState *cl, GLbyte *pc) return err; return DoCreateGLXDrawable(client, pGlxScreen, config, - pDraw, req->glxwindow, GLX_DRAWABLE_WINDOW); + pDraw, req->window, + req->glxwindow, GLX_DRAWABLE_WINDOW); } int __glXDisp_DestroyWindow(__GLXclientState *cl, GLbyte *pc) diff --git a/glx/glxdri.c b/glx/glxdri.c index 30b820c..51b602d 100644 --- a/glx/glxdri.c +++ b/glx/glxdri.c @@ -682,10 +682,12 @@ __glXDRIscreenCreateContext(__GLXscreen *baseScreen, } static __GLXdrawable * -__glXDRIscreenCreateDrawable(__GLXscreen *screen, +__glXDRIscreenCreateDrawable(ClientPtr client, + __GLXscreen *screen, DrawablePtr pDraw, - int type, XID drawId, + int type, + XID glxDrawId, __GLXconfig *glxConfig) { __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen; @@ -699,7 +701,7 @@ __glXDRIscreenCreateDrawable(__GLXscreen *screen, return NULL; if (!__glXDrawableInit(&private->base, screen, - pDraw, type, drawId, glxConfig)) { + pDraw, type, glxDrawId, glxConfig)) { xfree(private); return NULL; } diff --git a/glx/glxdri2.c b/glx/glxdri2.c index bc37285..5bdeedb 100644 --- a/glx/glxdri2.c +++ b/glx/glxdri2.c @@ -105,11 +105,6 @@ __glXDRIdrawableDestroy(__GLXdrawable *drawable) (*core->destroyDrawable)(private->driDrawable); - /* If the X window was destroyed, the dri DestroyWindow hook will - * aready have taken care of this, so only call if pDraw isn't NULL. */ - if (drawable->pDraw != NULL) - DRI2DestroyDrawable(drawable->pDraw); - __glXDrawableRelease(drawable); xfree(private); @@ -435,10 +430,12 @@ __glXDRIscreenCreateContext(__GLXscreen *baseScreen, } static __GLXdrawable * -__glXDRIscreenCreateDrawable(__GLXscreen *screen, +__glXDRIscreenCreateDrawable(ClientPtr client, + __GLXscreen *screen, DrawablePtr pDraw, - int type, XID drawId, + int type, + XID glxDrawId, __GLXconfig *glxConfig) { __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen; @@ -451,7 +448,7 @@ __glXDRIscreenCreateDrawable(__GLXscreen *screen, private->screen = driScreen; if (!__glXDrawableInit(&private->base, screen, - pDraw, type, drawId, glxConfig)) { + pDraw, type, glxDrawId, glxConfig)) { xfree(private); return NULL; } @@ -462,7 +459,7 @@ __glXDRIscreenCreateDrawable(__GLXscreen *screen, private->base.waitGL = __glXDRIdrawableWaitGL; private->base.waitX = __glXDRIdrawableWaitX; - if (DRI2CreateDrawable(pDraw)) { + if (DRI2CreateDrawable(client, pDraw, drawId)) { xfree(private); return NULL; } @@ -725,7 +722,7 @@ __glXDRIscreenProbe(ScreenPtr pScreen) screen->core = (const __DRIcoreExtension *) extensions[i]; } if (strcmp(extensions[i]->name, __DRI_DRI2) == 0 && - extensions[i]->version >= __DRI_DRI2_VERSION) { + extensions[i]->version >= 1) { screen->dri2 = (const __DRIdri2Extension *) extensions[i]; } } diff --git a/glx/glxdriswrast.c b/glx/glxdriswrast.c index c647d83..6a34393 100644 --- a/glx/glxdriswrast.c +++ b/glx/glxdriswrast.c @@ -301,10 +301,12 @@ glxChangeGC(GCPtr gc, BITS32 mask, CARD32 val) } static __GLXdrawable * -__glXDRIscreenCreateDrawable(__GLXscreen *screen, +__glXDRIscreenCreateDrawable(ClientPtr client, + __GLXscreen *screen, DrawablePtr pDraw, - int type, XID drawId, + int type, + XID glxDrawId, __GLXconfig *glxConfig) { __GLXDRIscreen *driScreen = (__GLXDRIscreen *) screen; @@ -319,7 +321,7 @@ __glXDRIscreenCreateDrawable(__GLXscreen *screen, private->screen = driScreen; if (!__glXDrawableInit(&private->base, screen, - pDraw, type, drawId, glxConfig)) { + pDraw, type, glxDrawId, glxConfig)) { xfree(private); return NULL; } diff --git a/glx/glxext.c b/glx/glxext.c index 59bcfbe..89e58b0 100644 --- a/glx/glxext.c +++ b/glx/glxext.c @@ -126,6 +126,17 @@ static Bool DrawableGone(__GLXdrawable *glxPriv, XID xid) { __GLXcontext *c; + /* If this drawable was created using glx 1.3 drawable + * constructors, we added it as a glx drawable resource under both + * its glx drawable ID and it X drawable ID. Remove the other + * resource now so we don't a callback for freed memory. */ + if (glxPriv->drawId != glxPriv->pDraw->id) { + if (xid == glxPriv->drawId) + FreeResourceByType(glxPriv->pDraw->id, __glXDrawableRes, TRUE); + else + FreeResourceByType(glxPriv->drawId, __glXDrawableRes, TRUE); + } + for (c = glxAllContexts; c; c = c->next) { if (c->isCurrent && (c->drawPriv == glxPriv || c->readPriv == glxPriv)) { int i; diff --git a/glx/glxscreens.c b/glx/glxscreens.c index 58d8ee0..b75aea6 100644 --- a/glx/glxscreens.c +++ b/glx/glxscreens.c @@ -215,7 +215,6 @@ glxCloseScreen (int index, ScreenPtr pScreen) __GLXscreen *pGlxScreen = glxGetScreen(pScreen); pScreen->CloseScreen = pGlxScreen->CloseScreen; - pScreen->DestroyWindow = pGlxScreen->DestroyWindow; pGlxScreen->destroy(pGlxScreen); @@ -347,31 +346,6 @@ pickFBConfig(__GLXscreen *pGlxScreen, VisualPtr visual) return best; } -static Bool -glxDestroyWindow(WindowPtr pWin) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - __GLXscreen *pGlxScreen = glxGetScreen(pScreen); - Bool retval = TRUE; - - FreeResource(pWin->drawable.id, FALSE); - - /* call lower wrapped functions */ - if (pGlxScreen->DestroyWindow) { - /* unwrap */ - pScreen->DestroyWindow = pGlxScreen->DestroyWindow; - - /* call lower layers */ - retval = (*pScreen->DestroyWindow)(pWin); - - /* rewrap */ - pGlxScreen->DestroyWindow = pScreen->DestroyWindow; - pScreen->DestroyWindow = glxDestroyWindow; - } - - return retval; -} - void __glXScreenInit(__GLXscreen *pGlxScreen, ScreenPtr pScreen) { __GLXconfig *m; @@ -394,8 +368,6 @@ void __glXScreenInit(__GLXscreen *pGlxScreen, ScreenPtr pScreen) pGlxScreen->CloseScreen = pScreen->CloseScreen; pScreen->CloseScreen = glxCloseScreen; - pGlxScreen->DestroyWindow = pScreen->DestroyWindow; - pScreen->DestroyWindow = glxDestroyWindow; i = 0; for (m = pGlxScreen->fbconfigs; m != NULL; m = m->next) { diff --git a/glx/glxscreens.h b/glx/glxscreens.h index bff4363..861e03c 100644 --- a/glx/glxscreens.h +++ b/glx/glxscreens.h @@ -134,10 +134,12 @@ struct __GLXscreen { __GLXconfig *modes, __GLXcontext *shareContext); - __GLXdrawable *(*createDrawable)(__GLXscreen *context, + __GLXdrawable *(*createDrawable)(ClientPtr client, + __GLXscreen *context, DrawablePtr pDraw, - int type, XID drawId, + int type, + XID glxDrawId, __GLXconfig *modes); int (*swapInterval) (__GLXdrawable *drawable, int interval); @@ -173,7 +175,6 @@ struct __GLXscreen { /*@}*/ Bool (*CloseScreen)(int index, ScreenPtr pScreen); - Bool (*DestroyWindow)(WindowPtr pWindow); }; diff --git a/hw/xfree86/dri2/dri2.c b/hw/xfree86/dri2/dri2.c index 2bdb733..11442d0 100644 --- a/hw/xfree86/dri2/dri2.c +++ b/hw/xfree86/dri2/dri2.c @@ -37,6 +37,7 @@ #include #include #include "xf86Module.h" +#include "list.h" #include "scrnintstr.h" #include "windowstr.h" #include "dixstruct.h" @@ -48,15 +49,20 @@ CARD8 dri2_major; /* version of DRI2 supported by DDX */ CARD8 dri2_minor; -static int dri2ScreenPrivateKeyIndex; +static int dri2ScreenPrivateKeyIndex; static DevPrivateKey dri2ScreenPrivateKey = &dri2ScreenPrivateKeyIndex; static int dri2WindowPrivateKeyIndex; static DevPrivateKey dri2WindowPrivateKey = &dri2WindowPrivateKeyIndex; static int dri2PixmapPrivateKeyIndex; static DevPrivateKey dri2PixmapPrivateKey = &dri2PixmapPrivateKeyIndex; +static RESTYPE dri2DrawableRes; + +typedef struct _DRI2Screen *DRI2ScreenPtr; typedef struct _DRI2Drawable { - unsigned int refCount; + DRI2ScreenPtr dri2_screen; + DrawablePtr drawable; + struct list reference_list; int width; int height; DRI2BufferPtr *buffers; @@ -73,9 +79,9 @@ typedef struct _DRI2Drawable { int swap_limit; /* for N-buffering */ } DRI2DrawableRec, *DRI2DrawablePtr; -typedef struct _DRI2Screen *DRI2ScreenPtr; - typedef struct _DRI2Screen { + ScreenPtr screen; + int refcnt; unsigned int numDrivers; const char **driverNames; const char *deviceName; @@ -101,45 +107,33 @@ DRI2GetScreen(ScreenPtr pScreen) static DRI2DrawablePtr DRI2GetDrawable(DrawablePtr pDraw) { - WindowPtr pWin; - PixmapPtr pPixmap; + WindowPtr pWin; + PixmapPtr pPixmap; - if (!pDraw) - return NULL; - - if (pDraw->type == DRAWABLE_WINDOW) - { + if (pDraw->type == DRAWABLE_WINDOW) { pWin = (WindowPtr) pDraw; return dixLookupPrivate(&pWin->devPrivates, dri2WindowPrivateKey); - } - else - { + } else { pPixmap = (PixmapPtr) pDraw; return dixLookupPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey); } } -int -DRI2CreateDrawable(DrawablePtr pDraw) +static DRI2DrawablePtr +DRI2AllocateDrawable(DrawablePtr pDraw) { DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen); - WindowPtr pWin; - PixmapPtr pPixmap; DRI2DrawablePtr pPriv; CARD64 ust; - - pPriv = DRI2GetDrawable(pDraw); - if (pPriv != NULL) - { - pPriv->refCount++; - return Success; - } + WindowPtr pWin; + PixmapPtr pPixmap; pPriv = xalloc(sizeof *pPriv); if (pPriv == NULL) - return BadAlloc; + return NULL; - pPriv->refCount = 1; + pPriv->dri2_screen = ds; + pPriv->drawable = pDraw; pPriv->width = pDraw->width; pPriv->height = pDraw->height; pPriv->buffers = NULL; @@ -157,44 +151,131 @@ DRI2CreateDrawable(DrawablePtr pDraw) pPriv->swap_limit = 1; /* default to double buffering */ pPriv->last_swap_msc = 0; pPriv->last_swap_ust = 0; + list_init(&pPriv->reference_list); - if (pDraw->type == DRAWABLE_WINDOW) - { + if (pDraw->type == DRAWABLE_WINDOW) { pWin = (WindowPtr) pDraw; dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, pPriv); - } - else - { + } else { pPixmap = (PixmapPtr) pDraw; dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, pPriv); } + return pPriv; +} + +typedef struct DRI2DrawableRefRec { + XID id; + XID dri2_id; + struct list link; +} DRI2DrawableRefRec, *DRI2DrawableRefPtr; + +static DRI2DrawableRefPtr +DRI2LookupDrawableRef(DRI2DrawablePtr pPriv, XID id) +{ + DRI2DrawableRefPtr ref; + + list_for_each_entry(ref, &pPriv->reference_list, link) { + if (ref->id == id) + return ref; + } + + return NULL; +} + +static int +DRI2AddDrawableRef(DRI2DrawablePtr pPriv, XID id, XID dri2_id) +{ + DRI2DrawableRefPtr ref; + + ref = malloc(sizeof *ref); + if (ref == NULL) + return BadAlloc; + + if (!AddResource(dri2_id, dri2DrawableRes, pPriv)) + return BadAlloc; + if (!DRI2LookupDrawableRef(pPriv, id)) + if (!AddResource(id, dri2DrawableRes, pPriv)) + return BadAlloc; + + ref->id = id; + ref->dri2_id = dri2_id; + list_add(&ref->link, &pPriv->reference_list); + return Success; } -static void -DRI2FreeDrawable(DrawablePtr pDraw) +int +DRI2CreateDrawable(ClientPtr client, DrawablePtr pDraw, XID id) { DRI2DrawablePtr pPriv; - WindowPtr pWin; - PixmapPtr pPixmap; + XID dri2_id; + int rc; pPriv = DRI2GetDrawable(pDraw); if (pPriv == NULL) - return; + pPriv = DRI2AllocateDrawable(pDraw); + if (pPriv == NULL) + return BadAlloc; + + dri2_id = FakeClientID(client->index); + rc = DRI2AddDrawableRef(pPriv, id, dri2_id); + if (rc != Success) + return rc; - xfree(pPriv); + return Success; +} - if (pDraw->type == DRAWABLE_WINDOW) - { +static int DRI2DrawableGone(pointer p, XID id) +{ + DRI2DrawablePtr pPriv = p; + DRI2ScreenPtr ds = pPriv->dri2_screen; + DRI2DrawableRefPtr ref, next; + WindowPtr pWin; + PixmapPtr pPixmap; + DrawablePtr pDraw; + int i; + + list_for_each_entry_safe(ref, next, &pPriv->reference_list, link) { + if (ref->dri2_id == id) { + list_del(&ref->link); + /* If this was the last ref under this X drawable XID, + * unregister the X drawable resource. */ + if (!DRI2LookupDrawableRef(pPriv, ref->id)) + FreeResourceByType(ref->id, dri2DrawableRes, TRUE); + free(ref); + break; + } + + if (ref->id == id) { + list_del(&ref->link); + FreeResourceByType(ref->dri2_id, dri2DrawableRes, TRUE); + free(ref); + } + } + + if (!list_is_empty(&pPriv->reference_list)) + return Success; + + pDraw = pPriv->drawable; + if (pDraw->type == DRAWABLE_WINDOW) { pWin = (WindowPtr) pDraw; dixSetPrivate(&pWin->devPrivates, dri2WindowPrivateKey, NULL); - } - else - { + } else { pPixmap = (PixmapPtr) pDraw; dixSetPrivate(&pPixmap->devPrivates, dri2PixmapPrivateKey, NULL); } + + if (pPriv->buffers != NULL) { + for (i = 0; i < pPriv->bufferCount; i++) + (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]); + + xfree(pPriv->buffers); + } + + xfree(pPriv); + + return Success; } static int @@ -505,10 +586,6 @@ DRI2WaitMSCComplete(ClientPtr client, DrawablePtr pDraw, int frame, pPriv->blockedClient = NULL; pPriv->blockedOnMsc = FALSE; - - /* If there's still a swap pending, let DRI2SwapComplete free it */ - if (pPriv->refCount == 0 && pPriv->swapsPending == 0) - DRI2FreeDrawable(pDraw); } static void @@ -576,13 +653,6 @@ DRI2SwapComplete(ClientPtr client, DrawablePtr pDraw, int frame, pPriv->last_swap_ust = ust; DRI2WakeClient(client, pDraw, frame, tv_sec, tv_usec); - - /* - * It's normal for the app to have exited with a swap outstanding, but - * don't free the drawable until they're all complete. - */ - if (pPriv->swapsPending == 0 && pPriv->refCount == 0) - DRI2FreeDrawable(pDraw); } Bool @@ -750,7 +820,7 @@ DRI2WaitMSC(ClientPtr client, DrawablePtr pDraw, CARD64 target_msc, Bool ret; pPriv = DRI2GetDrawable(pDraw); - if (pPriv == NULL || pPriv->refCount == 0) + if (pPriv == NULL) return BadDrawable; /* Old DDX just completes immediately */ @@ -774,7 +844,7 @@ DRI2WaitSBC(ClientPtr client, DrawablePtr pDraw, CARD64 target_sbc, DRI2DrawablePtr pPriv; pPriv = DRI2GetDrawable(pDraw); - if (pPriv == NULL || pPriv->refCount == 0) + if (pPriv == NULL) return BadDrawable; /* target_sbc == 0 means to block until all pending swaps are @@ -800,36 +870,6 @@ DRI2WaitSBC(ClientPtr client, DrawablePtr pDraw, CARD64 target_sbc, return Success; } -void -DRI2DestroyDrawable(DrawablePtr pDraw) -{ - DRI2ScreenPtr ds = DRI2GetScreen(pDraw->pScreen); - DRI2DrawablePtr pPriv; - - pPriv = DRI2GetDrawable(pDraw); - if (pPriv == NULL) - return; - - pPriv->refCount--; - if (pPriv->refCount > 0) - return; - - if (pPriv->buffers != NULL) { - int i; - - for (i = 0; i < pPriv->bufferCount; i++) - (*ds->DestroyBuffer)(pDraw, pPriv->buffers[i]); - - xfree(pPriv->buffers); - } - - /* If the window is destroyed while we have a swap or wait pending, don't - * actually free the priv yet. We'll need it in the DRI2SwapComplete() - * callback and we'll free it there once we're done. */ - if (!pPriv->swapsPending && !pPriv->blockedClient) - DRI2FreeDrawable(pDraw); -} - Bool DRI2HasSwapControl(ScreenPtr pScreen) { @@ -890,6 +930,7 @@ DRI2ScreenInit(ScreenPtr pScreen, DRI2InfoPtr info) if (!ds) return FALSE; + ds->screen = pScreen; ds->fd = info->fd; ds->deviceName = info->deviceName; dri2_major = 1; @@ -961,6 +1002,8 @@ DRI2Setup(pointer module, pointer opts, int *errmaj, int *errmin) { static Bool setupDone = FALSE; + dri2DrawableRes = CreateNewResourceType(DRI2DrawableGone, "DRI2Drawable"); + if (!setupDone) { setupDone = TRUE; diff --git a/hw/xfree86/dri2/dri2.h b/hw/xfree86/dri2/dri2.h index ce8a5df..5415a0b 100644 --- a/hw/xfree86/dri2/dri2.h +++ b/hw/xfree86/dri2/dri2.h @@ -198,7 +198,8 @@ extern _X_EXPORT Bool DRI2Connect(ScreenPtr pScreen, extern _X_EXPORT Bool DRI2Authenticate(ScreenPtr pScreen, drm_magic_t magic); -extern _X_EXPORT int DRI2CreateDrawable(DrawablePtr pDraw); +extern _X_EXPORT int DRI2CreateDrawable(ClientPtr client, + DrawablePtr pDraw, XID id); extern _X_EXPORT void DRI2DestroyDrawable(DrawablePtr pDraw); diff --git a/hw/xfree86/dri2/dri2ext.c b/hw/xfree86/dri2/dri2ext.c index 094d54d..58eaa10 100644 --- a/hw/xfree86/dri2/dri2ext.c +++ b/hw/xfree86/dri2/dri2ext.c @@ -51,7 +51,6 @@ #include "xf86Module.h" static ExtensionEntry *dri2Extension; -static RESTYPE dri2DrawableRes; static Bool validDrawable(ClientPtr client, XID drawable, Mask access_mode, @@ -168,15 +167,10 @@ ProcDRI2CreateDrawable(ClientPtr client) &pDrawable, &status)) return status; - status = DRI2CreateDrawable(pDrawable); + status = DRI2CreateDrawable(client, pDrawable, stuff->drawable); if (status != Success) return status; - if (!AddResource(stuff->drawable, dri2DrawableRes, pDrawable)) { - DRI2DestroyDrawable(pDrawable); - return BadAlloc; - } - return client->noClientException; } @@ -192,8 +186,6 @@ ProcDRI2DestroyDrawable(ClientPtr client) &pDrawable, &status)) return status; - FreeResourceByType(stuff->drawable, dri2DrawableRes, FALSE); - return client->noClientException; } @@ -627,25 +619,11 @@ SProcDRI2Dispatch (ClientPtr client) } } -static int DRI2DrawableGone(pointer p, XID id) -{ - DrawablePtr pDrawable = p; - - DRI2DestroyDrawable(pDrawable); - - return Success; -} - int DRI2EventBase; static void DRI2ExtensionInit(void) { - dri2DrawableRes = CreateNewResourceType(DRI2DrawableGone, "DRI2Drawable"); - - if (!dri2DrawableRes) - return; - dri2Extension = AddExtension(DRI2_NAME, DRI2NumberEvents, DRI2NumberErrors, diff --git a/include/list.h b/include/list.h index a126a65..89dc29d 100644 --- a/include/list.h +++ b/include/list.h @@ -94,4 +94,10 @@ list_is_empty(struct list *head) &pos->member != (head); \ pos = __container_of(pos->member.next, pos, member)) +#define list_for_each_entry_safe(pos, next, head, member) \ + for (pos = __container_of((head)->next, pos, member), \ + next = __container_of(pos->member.next, pos, member); \ + &pos->member != (head); \ + pos = next, next = __container_of(next->member.next, next, member)) + #endif -- 1.7.0.1