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.
This commit is contained in:
Chia-I Wu 2010-10-23 11:59:03 +08:00
parent 662e098b56
commit dc4f845c37
10 changed files with 146 additions and 11 deletions

View 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;

View 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.
*

View 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);
}

View 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);

View 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;
}

View 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.

View 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;

View 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.

View 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;

View 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.