From dc4f845c37a8446de19036e24fd397a0aa864c02 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Sat, 23 Oct 2010 11:59:03 +0800 Subject: [PATCH] egl: Add reference count for resources. This is a really simple mechanism. There is no atomicity and the caller is expected to hold the display lock. --- src/egl/main/eglcontext.c | 3 +-- src/egl/main/eglcontext.h | 22 ++++++++++++++++++++++ src/egl/main/egldisplay.c | 42 +++++++++++++++++++++++++++++++++++++++++- src/egl/main/egldisplay.h | 13 +++++++++++++ src/egl/main/eglimage.c | 3 +-- src/egl/main/eglimage.h | 22 ++++++++++++++++++++++ src/egl/main/eglsurface.c | 3 +-- src/egl/main/eglsurface.h | 22 ++++++++++++++++++++++ src/egl/main/eglsync.c | 5 +---- src/egl/main/eglsync.h | 22 ++++++++++++++++++++++ 10 files changed, 146 insertions(+), 11 deletions(-) diff --git a/src/egl/main/eglcontext.c b/src/egl/main/eglcontext.c index 113e4e4..b4cc743 100644 --- a/src/egl/main/eglcontext.c +++ b/src/egl/main/eglcontext.c @@ -103,8 +103,7 @@ _eglInitContext(_EGLContext *ctx, _EGLDisplay *dpy, _EGLConfig *conf, return EGL_FALSE; } - memset(ctx, 0, sizeof(_EGLContext)); - ctx->Resource.Display = dpy; + _eglInitResource(&ctx->Resource, sizeof(*ctx), dpy); ctx->ClientAPI = api; ctx->Config = conf; ctx->WindowRenderBuffer = EGL_NONE; diff --git a/src/egl/main/eglcontext.h b/src/egl/main/eglcontext.h index c2b8280..9c1e218 100644 --- a/src/egl/main/eglcontext.h +++ b/src/egl/main/eglcontext.h @@ -43,6 +43,28 @@ _eglBindContext(_EGLContext **ctx, _EGLSurface **draw, _EGLSurface **read); /** + * Increment reference count for the context. + */ +static INLINE _EGLContext * +_eglGetContext(_EGLContext *ctx) +{ + if (ctx) + _eglGetResource(&ctx->Resource); + return ctx; +} + + +/** + * Decrement reference count for the context. + */ +static INLINE EGLBoolean +_eglPutContext(_EGLContext *ctx) +{ + return (ctx) ? _eglPutResource(&ctx->Resource) : EGL_FALSE; +} + + +/** * Return true if the context is bound to a thread. * * The binding is considered a reference to the context. Drivers should not diff --git a/src/egl/main/egldisplay.c b/src/egl/main/egldisplay.c index 47dcc3e..565e44d 100644 --- a/src/egl/main/egldisplay.c +++ b/src/egl/main/egldisplay.c @@ -233,6 +233,42 @@ _eglCheckResource(void *res, _EGLResourceType type, _EGLDisplay *dpy) /** + * Initialize a display resource. + */ +void +_eglInitResource(_EGLResource *res, EGLint size, _EGLDisplay *dpy) +{ + memset(res, 0, size); + res->Display = dpy; + res->RefCount = 1; +} + + +/** + * Increment reference count for the resource. + */ +void +_eglGetResource(_EGLResource *res) +{ + assert(res && res->RefCount > 0); + /* hopefully a resource is always manipulated with its display locked */ + res->RefCount++; +} + + +/** + * Decrement reference count for the resource. + */ +EGLBoolean +_eglPutResource(_EGLResource *res) +{ + assert(res && res->RefCount > 0); + res->RefCount--; + return (!res->RefCount); +} + + +/** * Link a resource to its display. */ void @@ -243,6 +279,7 @@ _eglLinkResource(_EGLResource *res, _EGLResourceType type) res->IsLinked = EGL_TRUE; res->Next = res->Display->ResourceLists[type]; res->Display->ResourceLists[type] = res; + _eglGetResource(res); } @@ -269,6 +306,9 @@ _eglUnlinkResource(_EGLResource *res, _EGLResourceType type) } res->Next = NULL; - /* do not reset res->Display */ res->IsLinked = EGL_FALSE; + _eglPutResource(res); + + /* We always unlink before destroy. The driver still owns a reference */ + assert(res->RefCount); } diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h index f99721e..bcba0548 100644 --- a/src/egl/main/egldisplay.h +++ b/src/egl/main/egldisplay.h @@ -40,6 +40,7 @@ struct _egl_resource /* which display the resource belongs to */ _EGLDisplay *Display; EGLBoolean IsLinked; + EGLint RefCount; /* used to link resources of the same type */ _EGLResource *Next; @@ -162,6 +163,18 @@ _eglGetDisplayHandle(_EGLDisplay *dpy) extern void +_eglInitResource(_EGLResource *res, EGLint size, _EGLDisplay *dpy); + + +PUBLIC void +_eglGetResource(_EGLResource *res); + + +PUBLIC EGLBoolean +_eglPutResource(_EGLResource *res); + + +extern void _eglLinkResource(_EGLResource *res, _EGLResourceType type); diff --git a/src/egl/main/eglimage.c b/src/egl/main/eglimage.c index af4a29f..9625d2a 100644 --- a/src/egl/main/eglimage.c +++ b/src/egl/main/eglimage.c @@ -81,8 +81,7 @@ _eglParseImageAttribList(_EGLImageAttribs *attrs, _EGLDisplay *dpy, EGLBoolean _eglInitImage(_EGLImage *img, _EGLDisplay *dpy) { - memset(img, 0, sizeof(_EGLImage)); - img->Resource.Display = dpy; + _eglInitResource(&img->Resource, sizeof(*img), dpy); return EGL_TRUE; } diff --git a/src/egl/main/eglimage.h b/src/egl/main/eglimage.h index 161230f..bdc325a 100644 --- a/src/egl/main/eglimage.h +++ b/src/egl/main/eglimage.h @@ -43,6 +43,28 @@ _eglInitImage(_EGLImage *img, _EGLDisplay *dpy); /** + * Increment reference count for the image. + */ +static INLINE _EGLImage * +_eglGetImage(_EGLImage *img) +{ + if (img) + _eglGetResource(&img->Resource); + return img; +} + + +/** + * Decrement reference count for the image. + */ +static INLINE EGLBoolean +_eglPutImage(_EGLImage *img) +{ + return (img) ? _eglPutResource(&img->Resource) : EGL_FALSE; +} + + +/** * Link an image to its display and return the handle of the link. * The handle can be passed to client directly. */ diff --git a/src/egl/main/eglsurface.c b/src/egl/main/eglsurface.c index 74f1023..cc50504 100644 --- a/src/egl/main/eglsurface.c +++ b/src/egl/main/eglsurface.c @@ -269,8 +269,7 @@ _eglInitSurface(_EGLSurface *surf, _EGLDisplay *dpy, EGLint type, return EGL_FALSE; } - memset(surf, 0, sizeof(_EGLSurface)); - surf->Resource.Display = dpy; + _eglInitResource(&surf->Resource, sizeof(*surf), dpy); surf->Type = type; surf->Config = conf; diff --git a/src/egl/main/eglsurface.h b/src/egl/main/eglsurface.h index 2812dc3..b833258 100644 --- a/src/egl/main/eglsurface.h +++ b/src/egl/main/eglsurface.h @@ -81,6 +81,28 @@ _eglIsSurfaceBound(_EGLSurface *surf) /** + * Increment reference count for the surface. + */ +static INLINE _EGLSurface * +_eglGetSurface(_EGLSurface *surf) +{ + if (surf) + _eglGetResource(&surf->Resource); + return surf; +} + + +/** + * Decrement reference count for the surface. + */ +static INLINE EGLBoolean +_eglPutSurface(_EGLSurface *surf) +{ + return (surf) ? _eglPutResource(&surf->Resource) : EGL_FALSE; +} + + +/** * Link a surface to its display and return the handle of the link. * The handle can be passed to client directly. */ diff --git a/src/egl/main/eglsync.c b/src/egl/main/eglsync.c index b9cd99a..95e97c7 100644 --- a/src/egl/main/eglsync.c +++ b/src/egl/main/eglsync.c @@ -50,10 +50,7 @@ _eglInitSync(_EGLSync *sync, _EGLDisplay *dpy, EGLenum type, !(type == EGL_SYNC_FENCE_KHR && dpy->Extensions.KHR_fence_sync)) return _eglError(EGL_BAD_ATTRIBUTE, "eglCreateSyncKHR"); - memset(sync, 0, sizeof(*sync)); - - sync->Resource.Display = dpy; - + _eglInitResource(&sync->Resource, sizeof(*sync), dpy); sync->Type = type; sync->SyncStatus = EGL_UNSIGNALED_KHR; sync->SyncCondition = EGL_SYNC_PRIOR_COMMANDS_COMPLETE_KHR; diff --git a/src/egl/main/eglsync.h b/src/egl/main/eglsync.h index 09d799b..97ae67c 100644 --- a/src/egl/main/eglsync.h +++ b/src/egl/main/eglsync.h @@ -34,6 +34,28 @@ _eglGetSyncAttribKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync, /** + * Increment reference count for the sync. + */ +static INLINE _EGLSync * +_eglGetSync(_EGLSync *sync) +{ + if (sync) + _eglGetResource(&sync->Resource); + return sync; +} + + +/** + * Decrement reference count for the sync. + */ +static INLINE EGLBoolean +_eglPutSync(_EGLSync *sync) +{ + return (sync) ? _eglPutResource(&sync->Resource) : EGL_FALSE; +} + + +/** * Link a sync to its display and return the handle of the link. * The handle can be passed to client directly. */ -- 2.7.4