summaryrefslogtreecommitdiff
path: root/glx
diff options
context:
space:
mode:
authorKristian Høgsberg <krh@redhat.com>2009-04-09 13:16:37 -0400
committerAdam Jackson <ajax@redhat.com>2009-04-13 16:15:24 -0400
commit6ff60c626141771b365d557fe64bc93f200d1c9c (patch)
treefffa2a1889df963ac615b82edc2950ef8e32d684 /glx
parent50894e13545538ed93f20823f7ba81d1ab8906bb (diff)
glx: Fix drawable private leak on destroy
When a drawable goes away, we don't destroy the GLX drawable in full, since it may be current for a context. This means that when the drawable is destroyed in full later, the backend doesn't get a chance to destroy resources associated with the drawable (the DRI2Drawable). With this patch, we destroy the GLX drawable in full when it goes away and then track down all contexts that reference it and NULL their pointers. (cherry picked from commit 7b6400a1b8d2f228fcbedf17c30a7e3924e4dd2a)
Diffstat (limited to 'glx')
-rw-r--r--glx/Makefile.am1
-rw-r--r--glx/glxcmds.c44
-rw-r--r--glx/glxdrawable.h5
-rw-r--r--glx/glxdri.c2
-rw-r--r--glx/glxdri2.c2
-rw-r--r--glx/glxdriswrast.c2
-rw-r--r--glx/glxext.c42
-rw-r--r--glx/glxext.h1
-rw-r--r--glx/glxutil.h9
9 files changed, 69 insertions, 39 deletions
diff --git a/glx/Makefile.am b/glx/Makefile.am
index bec35bf21..6facc2011 100644
--- a/glx/Makefile.am
+++ b/glx/Makefile.am
@@ -79,7 +79,6 @@ libglx_la_SOURCES = \
glxscreens.c \
glxscreens.h \
glxserver.h \
- glxutil.c \
glxutil.h \
render2.c \
render2swap.c \
diff --git a/glx/glxcmds.c b/glx/glxcmds.c
index ab2d91b1b..24ef893b5 100644
--- a/glx/glxcmds.c
+++ b/glx/glxcmds.c
@@ -142,16 +142,9 @@ validGlxFBConfigForWindow(ClientPtr client, __GLXconfig *config,
void
__glXContextDestroy(__GLXcontext *context)
{
- if (!context->isDirect) {
- if (context->drawPriv)
- __glXUnrefDrawable(context->drawPriv);
- if (context->readPriv)
- __glXUnrefDrawable(context->readPriv);
- }
__glXFlushContextCache();
}
-
static void __glXdirectContextDestroy(__GLXcontext *context)
{
__glXContextDestroy(context);
@@ -267,6 +260,8 @@ DoCreateContext(__GLXclientState *cl, GLXContextID gcId,
glxc->isDirect = isDirect;
glxc->renderMode = GL_RENDER;
+ __glXAddToContextList(glxc);
+
return Success;
}
@@ -618,10 +613,8 @@ DoMakeCurrent(__GLXclientState *cl,
}
__glXFlushContextCache();
if (!prevglxc->isDirect) {
- if (prevglxc->drawPriv)
- __glXUnrefDrawable(prevglxc->drawPriv);
- if (prevglxc->readPriv)
- __glXUnrefDrawable(prevglxc->readPriv);
+ prevglxc->drawPriv = NULL;
+ prevglxc->readPriv = NULL;
}
}
@@ -639,8 +632,6 @@ DoMakeCurrent(__GLXclientState *cl,
}
glxc->isCurrent = GL_TRUE;
- __glXRefDrawable(glxc->drawPriv);
- __glXRefDrawable(glxc->readPriv);
}
if (prevglxc) {
@@ -1064,6 +1055,33 @@ int __glXDisp_GetFBConfigsSGIX(__GLXclientState *cl, GLbyte *pc)
return DoGetFBConfigs(cl, req->screen);
}
+GLboolean
+__glXDrawableInit(__GLXdrawable *drawable,
+ __GLXscreen *screen, DrawablePtr pDraw, int type,
+ XID drawId, __GLXconfig *config)
+{
+ drawable->pDraw = pDraw;
+ drawable->type = type;
+ drawable->drawId = drawId;
+ drawable->config = config;
+ drawable->eventMask = 0;
+
+ return GL_TRUE;
+}
+
+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)
diff --git a/glx/glxdrawable.h b/glx/glxdrawable.h
index 45000bfb7..60aacd792 100644
--- a/glx/glxdrawable.h
+++ b/glx/glxdrawable.h
@@ -64,11 +64,6 @@ struct __GLXdrawable {
*/
__GLXconfig *config;
- /*
- ** reference count
- */
- int refCount;
-
GLenum target;
/*
diff --git a/glx/glxdri.c b/glx/glxdri.c
index 223b06e8b..8d614d08a 100644
--- a/glx/glxdri.c
+++ b/glx/glxdri.c
@@ -238,6 +238,8 @@ __glXDRIdrawableDestroy(__GLXdrawable *drawable)
__glXleaveServer(GL_FALSE);
}
+ __glXDrawableRelease(drawable);
+
xfree(private);
}
diff --git a/glx/glxdri2.c b/glx/glxdri2.c
index 4e76c7135..4544a2c50 100644
--- a/glx/glxdri2.c
+++ b/glx/glxdri2.c
@@ -107,6 +107,8 @@ __glXDRIdrawableDestroy(__GLXdrawable *drawable)
if (drawable->pDraw != NULL)
DRI2DestroyDrawable(drawable->pDraw);
+ __glXDrawableRelease(drawable);
+
xfree(private);
}
diff --git a/glx/glxdriswrast.c b/glx/glxdriswrast.c
index b42501280..f8c441e65 100644
--- a/glx/glxdriswrast.c
+++ b/glx/glxdriswrast.c
@@ -95,6 +95,8 @@ __glXDRIdrawableDestroy(__GLXdrawable *drawable)
FreeScratchGC(private->gc);
FreeScratchGC(private->swapgc);
+ __glXDrawableRelease(drawable);
+
xfree(private);
}
diff --git a/glx/glxext.c b/glx/glxext.c
index c88237209..fe99e4e80 100644
--- a/glx/glxext.c
+++ b/glx/glxext.c
@@ -51,6 +51,7 @@
** from the server's perspective.
*/
__GLXcontext *__glXLastContext;
+__GLXcontext *__glXContextList;
/*
** X resources.
@@ -112,31 +113,46 @@ static int ContextGone(__GLXcontext* cx, XID id)
return True;
}
+static __GLXcontext *glxPendingDestroyContexts;
+static __GLXcontext *glxAllContexts;
+static int glxServerLeaveCount;
+static int glxBlockClients;
+
/*
** Destroy routine that gets called when a drawable is freed. A drawable
** contains the ancillary buffers needed for rendering.
*/
static Bool DrawableGone(__GLXdrawable *glxPriv, XID xid)
{
- ScreenPtr pScreen = glxPriv->pDraw->pScreen;
+ __GLXcontext *c;
- switch (glxPriv->type) {
- case GLX_DRAWABLE_PIXMAP:
- case GLX_DRAWABLE_PBUFFER:
- (*pScreen->DestroyPixmap)((PixmapPtr) glxPriv->pDraw);
- break;
+ for (c = glxAllContexts; c; c = c->next) {
+ if (c->drawPriv == glxPriv)
+ c->drawPriv = NULL;
+ if (c->readPriv == glxPriv)
+ c->readPriv = NULL;
}
- glxPriv->pDraw = NULL;
- glxPriv->drawId = 0;
- __glXUnrefDrawable(glxPriv);
+ glxPriv->destroy(glxPriv);
return True;
}
-static __GLXcontext *glxPendingDestroyContexts;
-static int glxServerLeaveCount;
-static int glxBlockClients;
+void __glXAddToContextList(__GLXcontext *cx)
+{
+ cx->next = glxAllContexts;
+ glxAllContexts = cx;
+}
+
+void __glXRemoveFromContextList(__GLXcontext *cx)
+{
+ __GLXcontext *c, **prev;
+
+ prev = &glxAllContexts;
+ for (c = glxAllContexts; c; c = c->next)
+ if (c == cx)
+ *prev = c->next;
+}
/*
** Free a context.
@@ -151,6 +167,8 @@ GLboolean __glXFreeContext(__GLXcontext *cx)
__glXFlushContextCache();
}
+ __glXRemoveFromContextList(cx);
+
/* We can get here through both regular dispatching from
* __glXDispatch() or as a callback from the resource manager. In
* the latter case we need to lift the DRI lock manually. */
diff --git a/glx/glxext.h b/glx/glxext.h
index 72092f34a..7008c4763 100644
--- a/glx/glxext.h
+++ b/glx/glxext.h
@@ -38,6 +38,7 @@
extern GLboolean __glXFreeContext(__GLXcontext *glxc);
extern void __glXFlushContextCache(void);
+extern void __glXAddToContextList(__GLXcontext *cx);
extern void __glXErrorCallBack(GLenum code);
extern void __glXClearErrorOccured(void);
extern GLboolean __glXErrorOccured(void);
diff --git a/glx/glxutil.h b/glx/glxutil.h
index baa490500..d1a715b4b 100644
--- a/glx/glxutil.h
+++ b/glx/glxutil.h
@@ -35,18 +35,11 @@
* Silicon Graphics, Inc.
*/
-/* relate contexts with drawables */
-extern void __glXAssociateContext(__GLXcontext *glxc);
-extern void __glXDeassociateContext(__GLXcontext *glxc);
-
-/* drawable management */
-extern void __glXRefDrawable(__GLXdrawable *glxPriv);
-extern void __glXUnrefDrawable(__GLXdrawable *glxPriv);
-
extern GLboolean __glXDrawableInit(__GLXdrawable *drawable,
__GLXscreen *screen,
DrawablePtr pDraw, int type, XID drawID,
__GLXconfig *config);
+extern void __glXDrawableRelease(__GLXdrawable *drawable);
/* context helper routines */
extern __GLXcontext *__glXLookupContextByTag(__GLXclientState*, GLXContextTag);