egl: Add reference count for resources.
authorChia-I Wu <olv@lunarg.com>
Sat, 23 Oct 2010 03:59:03 +0000 (11:59 +0800)
committerChia-I Wu <olv@lunarg.com>
Sat, 23 Oct 2010 07:19:34 +0000 (15:19 +0800)
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
src/egl/main/eglcontext.h
src/egl/main/egldisplay.c
src/egl/main/egldisplay.h
src/egl/main/eglimage.c
src/egl/main/eglimage.h
src/egl/main/eglsurface.c
src/egl/main/eglsurface.h
src/egl/main/eglsync.c
src/egl/main/eglsync.h

index 113e4e4..b4cc743 100644 (file)
@@ -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;
index c2b8280..9c1e218 100644 (file)
@@ -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
index 47dcc3e..565e44d 100644 (file)
@@ -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);
 }
index f99721e..bcba054 100644 (file)
@@ -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);
 
 
index af4a29f..9625d2a 100644 (file)
@@ -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;
 }
index 161230f..bdc325a 100644 (file)
@@ -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.
  */
index 74f1023..cc50504 100644 (file)
@@ -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;
 
index 2812dc3..b833258 100644 (file)
@@ -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.
  */
index b9cd99a..95e97c7 100644 (file)
@@ -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;
index 09d799b..97ae67c 100644 (file)
@@ -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.
  */