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 113e4e48fb3..b4cc7439583 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 c2b8280b670..9c1e2184c64 100644 --- a/src/egl/main/eglcontext.h +++ b/src/egl/main/eglcontext.h @@ -42,6 +42,28 @@ PUBLIC EGLBoolean _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. * diff --git a/src/egl/main/egldisplay.c b/src/egl/main/egldisplay.c index 47dcc3e05a5..565e44d2d23 100644 --- a/src/egl/main/egldisplay.c +++ b/src/egl/main/egldisplay.c @@ -232,6 +232,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. */ @@ -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 f99721e6982..bcba05480a8 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; @@ -161,6 +162,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 af4a29fb0e2..9625d2ae84b 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 161230f9009..bdc325a7f33 100644 --- a/src/egl/main/eglimage.h +++ b/src/egl/main/eglimage.h @@ -42,6 +42,28 @@ PUBLIC EGLBoolean _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 74f10230eaa..cc505045e12 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 2812dc36ab0..b833258bf69 100644 --- a/src/egl/main/eglsurface.h +++ b/src/egl/main/eglsurface.h @@ -80,6 +80,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 b9cd99a332c..95e97c73542 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 09d799ba5f1..97ae67cf866 100644 --- a/src/egl/main/eglsync.h +++ b/src/egl/main/eglsync.h @@ -33,6 +33,28 @@ _eglGetSyncAttribKHR(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSync *sync, EGLint attribute, EGLint *value); +/** + * 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.30.2