egl: Use reference counting to replace IsLinked or IsBound.

Remove all _egl<Res>IsLinked and _egl<Res>IsBound.  Update
_eglBindContext and drivers to do reference counting.
This commit is contained in:
Chia-I Wu 2010-10-23 12:52:26 +08:00
parent dc4f845c37
commit d19afc57fe
9 changed files with 137 additions and 147 deletions

View File

@ -1160,7 +1160,7 @@ dri2_destroy_surface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
(void) drv;
if (_eglIsSurfaceBound(surf))
if (!_eglPutSurface(surf))
return EGL_TRUE;
(*dri2_dpy->core->destroyDrawable)(dri2_surf->dri_drawable);
@ -1187,11 +1187,13 @@ dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
struct dri2_egl_surface *dri2_dsurf = dri2_egl_surface(dsurf);
struct dri2_egl_surface *dri2_rsurf = dri2_egl_surface(rsurf);
struct dri2_egl_context *dri2_ctx = dri2_egl_context(ctx);
_EGLContext *old_ctx;
_EGLSurface *old_dsurf, *old_rsurf;
__DRIdrawable *ddraw, *rdraw;
__DRIcontext *cctx;
/* bind the new context and return the "orphaned" one */
if (!_eglBindContext(&ctx, &dsurf, &rsurf))
/* make new bindings */
if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf))
return EGL_FALSE;
/* flush before context switch */
@ -1204,16 +1206,29 @@ dri2_make_current(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
if ((cctx == NULL && ddraw == NULL && rdraw == NULL) ||
dri2_dpy->core->bindContext(cctx, ddraw, rdraw)) {
if (dsurf && !_eglIsSurfaceLinked(dsurf))
dri2_destroy_surface(drv, disp, dsurf);
if (rsurf && rsurf != dsurf && !_eglIsSurfaceLinked(dsurf))
dri2_destroy_surface(drv, disp, rsurf);
if (ctx != NULL && !_eglIsContextLinked(ctx))
dri2_dpy->core->unbindContext(dri2_egl_context(ctx)->dri_context);
dri2_destroy_surface(drv, disp, old_dsurf);
dri2_destroy_surface(drv, disp, old_rsurf);
if (old_ctx) {
dri2_dpy->core->unbindContext(dri2_egl_context(old_ctx)->dri_context);
/* no destroy? */
_eglPutContext(old_ctx);
}
return EGL_TRUE;
} else {
_eglBindContext(&ctx, &dsurf, &rsurf);
/* undo the previous _eglBindContext */
_eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &dsurf, &rsurf);
assert(&dri2_ctx->base == ctx &&
&dri2_dsurf->base == dsurf &&
&dri2_rsurf->base == rsurf);
_eglPutSurface(dsurf);
_eglPutSurface(rsurf);
_eglPutContext(ctx);
_eglPutSurface(old_dsurf);
_eglPutSurface(old_rsurf);
_eglPutContext(old_ctx);
return EGL_FALSE;
}

View File

@ -677,14 +677,16 @@ GLX_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
struct GLX_egl_surface *GLX_dsurf = GLX_egl_surface(dsurf);
struct GLX_egl_surface *GLX_rsurf = GLX_egl_surface(rsurf);
struct GLX_egl_context *GLX_ctx = GLX_egl_context(ctx);
_EGLContext *old_ctx;
_EGLSurface *old_dsurf, *old_rsurf;
GLXDrawable ddraw, rdraw;
GLXContext cctx;
EGLBoolean ret = EGL_FALSE;
(void) drv;
/* bind the new context and return the "orphaned" one */
if (!_eglBindContext(&ctx, &dsurf, &rsurf))
/* make new bindings */
if (!_eglBindContext(ctx, dsurf, rsurf, &old_ctx, &old_dsurf, &old_rsurf))
return EGL_FALSE;
ddraw = (GLX_dsurf) ? GLX_dsurf->glx_drawable : None;
@ -697,13 +699,27 @@ GLX_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
ret = glXMakeCurrent(GLX_dpy->dpy, ddraw, cctx);
if (ret) {
if (dsurf && !_eglIsSurfaceLinked(dsurf))
destroy_surface(disp, dsurf);
if (rsurf && rsurf != dsurf && !_eglIsSurfaceLinked(rsurf))
destroy_surface(disp, rsurf);
if (_eglPutSurface(old_dsurf))
destroy_surface(disp, old_dsurf);
if (_eglPutSurface(old_rsurf))
destroy_surface(disp, old_rsurf);
/* no destroy? */
_eglPutContext(old_ctx);
}
else {
_eglBindContext(&ctx, &dsurf, &rsurf);
/* undo the previous _eglBindContext */
_eglBindContext(old_ctx, old_dsurf, old_rsurf, &ctx, &dsurf, &rsurf);
assert(&GLX_ctx->Base == ctx &&
&GLX_dsurf->Base == dsurf &&
&GLX_rsurf->Base == rsurf);
_eglPutSurface(dsurf);
_eglPutSurface(rsurf);
_eglPutContext(ctx);
_eglPutSurface(old_dsurf);
_eglPutSurface(old_rsurf);
_eglPutContext(old_ctx);
}
return ret;
@ -907,7 +923,7 @@ GLX_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
{
(void) drv;
if (!_eglIsSurfaceBound(surf))
if (_eglPutSurface(surf))
destroy_surface(disp, surf);
return EGL_TRUE;

View File

@ -648,11 +648,12 @@ eglSwapInterval(EGLDisplay dpy, EGLint interval)
_EGL_CHECK_DISPLAY(disp, EGL_FALSE, drv);
if (!ctx || !_eglIsContextLinked(ctx) || ctx->Resource.Display != disp)
if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
ctx->Resource.Display != disp)
RETURN_EGL_ERROR(disp, EGL_BAD_CONTEXT, EGL_FALSE);
surf = ctx->DrawSurface;
if (!_eglIsSurfaceLinked(surf))
if (_eglGetSurfaceHandle(surf) == EGL_NO_SURFACE)
RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
ret = drv->API.SwapInterval(drv, disp, surf, interval);
@ -673,7 +674,8 @@ eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
_EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
/* surface must be bound to current context in EGL 1.4 */
if (!ctx || !_eglIsContextLinked(ctx) || surf != ctx->DrawSurface)
if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
surf != ctx->DrawSurface)
RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
ret = drv->API.SwapBuffers(drv, disp, surf);
@ -714,7 +716,8 @@ eglWaitClient(void)
_eglLockMutex(&disp->Mutex);
/* let bad current context imply bad current surface */
if (!_eglIsContextLinked(ctx) || !_eglIsSurfaceLinked(ctx->DrawSurface))
if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
_eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE)
RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
/* a valid current context implies an initialized current display */
@ -763,7 +766,8 @@ eglWaitNative(EGLint engine)
_eglLockMutex(&disp->Mutex);
/* let bad current context imply bad current surface */
if (!_eglIsContextLinked(ctx) || !_eglIsSurfaceLinked(ctx->DrawSurface))
if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
_eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE)
RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE);
/* a valid current context implies an initialized current display */
@ -1437,7 +1441,8 @@ eglSwapBuffersRegionNOK(EGLDisplay dpy, EGLSurface surface,
RETURN_EGL_EVAL(disp, EGL_FALSE);
/* surface must be bound to current context in EGL 1.4 */
if (!ctx || !_eglIsContextLinked(ctx) || surf != ctx->DrawSurface)
if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT ||
surf != ctx->DrawSurface)
RETURN_EGL_ERROR(disp, EGL_BAD_SURFACE, EGL_FALSE);
ret = drv->API.SwapBuffersRegionNOK(drv, disp, surf, numRects, rects);

View File

@ -300,54 +300,65 @@ _eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read)
/**
* Bind the context to the current thread and given surfaces. Return the
* "orphaned" context and surfaces. Each argument is both input and output.
* previous bound context and surfaces. The caller should unreference the
* returned context and surfaces.
*
* Making a second call with the resources returned by the first call
* unsurprisingly undoes the first call, except for the resouce reference
* counts.
*/
EGLBoolean
_eglBindContext(_EGLContext **ctx, _EGLSurface **draw, _EGLSurface **read)
_eglBindContext(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read,
_EGLContext **old_ctx,
_EGLSurface **old_draw, _EGLSurface **old_read)
{
_EGLThreadInfo *t = _eglGetCurrentThread();
_EGLContext *newCtx = *ctx, *oldCtx;
_EGLSurface *newDraw = *draw, *newRead = *read;
_EGLContext *prev_ctx;
_EGLSurface *prev_draw, *prev_read;
if (!_eglCheckMakeCurrent(newCtx, newDraw, newRead))
if (!_eglCheckMakeCurrent(ctx, draw, read))
return EGL_FALSE;
/* increment refcounts before binding */
_eglGetContext(ctx);
_eglGetSurface(draw);
_eglGetSurface(read);
/* bind the new context */
oldCtx = _eglBindContextToThread(newCtx, t);
prev_ctx = _eglBindContextToThread(ctx, t);
/* break old bindings */
if (oldCtx) {
*ctx = oldCtx;
*draw = oldCtx->DrawSurface;
*read = oldCtx->ReadSurface;
/* break previous bindings */
if (prev_ctx) {
prev_draw = prev_ctx->DrawSurface;
prev_read = prev_ctx->ReadSurface;
if (*draw)
(*draw)->CurrentContext = NULL;
if (*read)
(*read)->CurrentContext = NULL;
if (prev_draw)
prev_draw->CurrentContext = NULL;
if (prev_read)
prev_read->CurrentContext = NULL;
oldCtx->DrawSurface = NULL;
oldCtx->ReadSurface = NULL;
prev_ctx->DrawSurface = NULL;
prev_ctx->ReadSurface = NULL;
}
else {
prev_draw = prev_read = NULL;
}
/* establish new bindings */
if (newCtx) {
if (newDraw)
newDraw->CurrentContext = newCtx;
if (newRead)
newRead->CurrentContext = newCtx;
if (ctx) {
if (draw)
draw->CurrentContext = ctx;
if (read)
read->CurrentContext = ctx;
newCtx->DrawSurface = newDraw;
newCtx->ReadSurface = newRead;
ctx->DrawSurface = draw;
ctx->ReadSurface = read;
}
/* an old context or surface is not orphaned if it is still bound */
if (*ctx == newCtx)
*ctx = NULL;
if (*draw == newDraw || *draw == newRead)
*draw = NULL;
if (*read == newDraw || *read == newRead)
*read = NULL;
assert(old_ctx && old_draw && old_read);
*old_ctx = prev_ctx;
*old_draw = prev_draw;
*old_read = prev_read;
return EGL_TRUE;
}

View File

@ -39,7 +39,9 @@ _eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx, EGLint att
PUBLIC EGLBoolean
_eglBindContext(_EGLContext **ctx, _EGLSurface **draw, _EGLSurface **read);
_eglBindContext(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read,
_EGLContext **old_ctx,
_EGLSurface **old_draw, _EGLSurface **old_read);
/**
@ -64,19 +66,6 @@ _eglPutContext(_EGLContext *ctx)
}
/**
* Return true if the context is bound to a thread.
*
* The binding is considered a reference to the context. Drivers should not
* destroy a context when it is bound.
*/
static INLINE EGLBoolean
_eglIsContextBound(_EGLContext *ctx)
{
return (ctx->Binding != NULL);
}
/**
* Link a context to its display and return the handle of the link.
* The handle can be passed to client directly.
@ -126,18 +115,4 @@ _eglGetContextHandle(_EGLContext *ctx)
}
/**
* Return true if the context is linked to a display.
*
* The link is considered a reference to the context (the display is owning the
* context). Drivers should not destroy a context when it is linked.
*/
static INLINE EGLBoolean
_eglIsContextLinked(_EGLContext *ctx)
{
_EGLResource *res = (_EGLResource *) ctx;
return (res && _eglIsResourceLinked(res));
}
#endif /* EGLCONTEXT_INCLUDED */

View File

@ -113,15 +113,4 @@ _eglGetImageHandle(_EGLImage *img)
}
/**
* Return true if the image is linked to a display.
*/
static INLINE EGLBoolean
_eglIsImageLinked(_EGLImage *img)
{
_EGLResource *res = (_EGLResource *) img;
return (res && _eglIsResourceLinked(res));
}
#endif /* EGLIMAGE_INCLUDED */

View File

@ -67,19 +67,6 @@ extern EGLBoolean
_eglSwapInterval(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLint interval);
/**
* Return true if there is a context bound to the surface.
*
* The binding is considered a reference to the surface. Drivers should not
* destroy a surface when it is bound.
*/
static INLINE EGLBoolean
_eglIsSurfaceBound(_EGLSurface *surf)
{
return (surf->CurrentContext != NULL);
}
/**
* Increment reference count for the surface.
*/
@ -151,18 +138,4 @@ _eglGetSurfaceHandle(_EGLSurface *surf)
}
/**
* Return true if the surface is linked to a display.
*
* The link is considered a reference to the surface (the display is owning the
* surface). Drivers should not destroy a surface when it is linked.
*/
static INLINE EGLBoolean
_eglIsSurfaceLinked(_EGLSurface *surf)
{
_EGLResource *res = (_EGLResource *) surf;
return (res && _eglIsResourceLinked(res));
}
#endif /* EGLSURFACE_INCLUDED */

View File

@ -103,20 +103,6 @@ _eglGetSyncHandle(_EGLSync *sync)
}
/**
* Return true if the sync is linked to a display.
*
* The link is considered a reference to the sync (the display is owning the
* sync). Drivers should not destroy a sync when it is linked.
*/
static INLINE EGLBoolean
_eglIsSyncLinked(_EGLSync *sync)
{
_EGLResource *res = (_EGLResource *) sync;
return (res && _eglIsResourceLinked(res));
}
#endif /* EGL_KHR_reusable_sync */

View File

@ -160,7 +160,7 @@ destroy_context(_EGLDisplay *dpy, _EGLContext *ctx)
static EGLBoolean
egl_g3d_destroy_context(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
{
if (!_eglIsContextBound(ctx))
if (_eglPutContext(ctx))
destroy_context(dpy, ctx);
return EGL_TRUE;
}
@ -433,7 +433,7 @@ destroy_surface(_EGLDisplay *dpy, _EGLSurface *surf)
static EGLBoolean
egl_g3d_destroy_surface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf)
{
if (!_eglIsSurfaceBound(surf))
if (_eglPutSurface(surf))
destroy_surface(dpy, surf);
return EGL_TRUE;
}
@ -446,13 +446,15 @@ egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy,
struct egl_g3d_surface *gdraw = egl_g3d_surface(draw);
struct egl_g3d_surface *gread = egl_g3d_surface(read);
struct egl_g3d_context *old_gctx;
_EGLContext *old_ctx;
_EGLSurface *old_draw, *old_read;
EGLBoolean ok = EGL_TRUE;
/* bind the new context and return the "orphaned" one */
if (!_eglBindContext(&ctx, &draw, &read))
/* make new bindings */
if (!_eglBindContext(ctx, draw, read, &old_ctx, &old_draw, &old_read))
return EGL_FALSE;
old_gctx = egl_g3d_context(ctx);
old_gctx = egl_g3d_context(old_ctx);
if (old_gctx) {
/* flush old context */
old_gctx->stctxi->flush(old_gctx->stctxi,
@ -481,15 +483,33 @@ egl_g3d_make_current(_EGLDriver *drv, _EGLDisplay *dpy,
}
else if (old_gctx) {
ok = old_gctx->stapi->make_current(old_gctx->stapi, NULL, NULL, NULL);
old_gctx->base.WindowRenderBuffer = EGL_NONE;
if (ok)
old_gctx->base.WindowRenderBuffer = EGL_NONE;
}
if (ctx && !_eglIsContextLinked(ctx))
destroy_context(dpy, ctx);
if (draw && !_eglIsSurfaceLinked(draw))
destroy_surface(dpy, draw);
if (read && read != draw && !_eglIsSurfaceLinked(read))
destroy_surface(dpy, read);
if (ok) {
if (_eglPutContext(old_ctx))
destroy_context(dpy, old_ctx);
if (_eglPutSurface(old_draw))
destroy_surface(dpy, old_draw);
if (_eglPutSurface(old_read))
destroy_surface(dpy, old_read);
}
else {
/* undo the previous _eglBindContext */
_eglBindContext(old_ctx, old_draw, old_read, &ctx, &draw, &read);
assert(&gctx->base == ctx &&
&gdraw->base == draw &&
&gread->base == read);
_eglPutSurface(draw);
_eglPutSurface(read);
_eglPutContext(ctx);
_eglPutSurface(old_draw);
_eglPutSurface(old_read);
_eglPutContext(old_ctx);
}
return ok;
}