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 113e4e48fb35b3c237b05d108c6663abfd778b34..b4cc7439583e53984f62268a08d7ea088564f5b4 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 c2b8280b6703df16be9076c89c319be678446498..9c1e2184c640d887759ae3a1b0323a4a53b10b43 100644 (file)
@@ -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.
  *
index 47dcc3e05a5e3d3436839c2126eca545918ecfc5..565e44d2d23c8fc98d292aaa77983772042d2bdb 100644 (file)
@@ -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);
 }
index f99721e69825b8a522f76efa0de088b1378ace3b..bcba05480a86676f9599a75e250c049f120a46d2 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;
@@ -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);
 
index af4a29fb0e2463c74a6bcc0688030984ba353550..9625d2ae84b9face437496d5f24a9a3cb8e91cba 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 161230f900900b34d59d5ba255a93fd6706818d6..bdc325a7f33c4a2a15950e5754ff6a23b000d9da 100644 (file)
@@ -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.
index 74f10230eaada4f9c35965cf860818f275d1146e..cc505045e12967a19faeacf2310638cdbdd0dda6 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 2812dc36ab0c59812ce490de9d54b40020dc31e3..b833258bf69d3ec7353092b2ae371f82fbeeaa0e 100644 (file)
@@ -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.
index b9cd99a332cece80a46bd8581dd85a7599b7204a..95e97c735424a0fb07b93227b86cea845e709bf5 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 09d799ba5f183c6ff4f538a2ec04504e8a720f57..97ae67cf866bbc5d36b2d33e1904e42d6c38fc76 100644 (file)
@@ -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.