From d19afc57fe49816f3f3290410e0124d326577be2 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Sat, 23 Oct 2010 12:52:26 +0800 Subject: [PATCH] egl: Use reference counting to replace IsLinked or IsBound. Remove all _eglIsLinked and _eglIsBound. Update _eglBindContext and drivers to do reference counting. --- src/egl/drivers/dri2/egl_dri2.c | 35 ++++++--- src/egl/drivers/glx/egl_glx.c | 32 ++++++-- src/egl/main/eglapi.c | 17 +++-- src/egl/main/eglcontext.c | 75 +++++++++++-------- src/egl/main/eglcontext.h | 31 +------- src/egl/main/eglimage.h | 11 --- src/egl/main/eglsurface.h | 27 ------- src/egl/main/eglsync.h | 14 ---- .../state_trackers/egl/common/egl_g3d_api.c | 44 ++++++++--- 9 files changed, 138 insertions(+), 148 deletions(-) diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c index 75aa29f55b9..a5f95b944c5 100644 --- a/src/egl/drivers/dri2/egl_dri2.c +++ b/src/egl/drivers/dri2/egl_dri2.c @@ -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; } diff --git a/src/egl/drivers/glx/egl_glx.c b/src/egl/drivers/glx/egl_glx.c index 256de57ed87..8ec7c48c50e 100644 --- a/src/egl/drivers/glx/egl_glx.c +++ b/src/egl/drivers/glx/egl_glx.c @@ -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; diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c index 913ddd288bd..efa9e97346b 100644 --- a/src/egl/main/eglapi.c +++ b/src/egl/main/eglapi.c @@ -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); diff --git a/src/egl/main/eglcontext.c b/src/egl/main/eglcontext.c index b4cc7439583..3266a758249 100644 --- a/src/egl/main/eglcontext.c +++ b/src/egl/main/eglcontext.c @@ -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; - - newCtx->DrawSurface = newDraw; - newCtx->ReadSurface = newRead; + if (ctx) { + if (draw) + draw->CurrentContext = ctx; + if (read) + read->CurrentContext = ctx; + + 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; } diff --git a/src/egl/main/eglcontext.h b/src/egl/main/eglcontext.h index 9c1e2184c64..8cd0df17313 100644 --- a/src/egl/main/eglcontext.h +++ b/src/egl/main/eglcontext.h @@ -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 */ diff --git a/src/egl/main/eglimage.h b/src/egl/main/eglimage.h index bdc325a7f33..adb939a9e02 100644 --- a/src/egl/main/eglimage.h +++ b/src/egl/main/eglimage.h @@ -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 */ diff --git a/src/egl/main/eglsurface.h b/src/egl/main/eglsurface.h index b833258bf69..ef01b32ede3 100644 --- a/src/egl/main/eglsurface.h +++ b/src/egl/main/eglsurface.h @@ -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 */ diff --git a/src/egl/main/eglsync.h b/src/egl/main/eglsync.h index 97ae67cf866..a0025237e7a 100644 --- a/src/egl/main/eglsync.h +++ b/src/egl/main/eglsync.h @@ -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 */ diff --git a/src/gallium/state_trackers/egl/common/egl_g3d_api.c b/src/gallium/state_trackers/egl/common/egl_g3d_api.c index 3bde39737ba..c10245bb067 100644 --- a/src/gallium/state_trackers/egl/common/egl_g3d_api.c +++ b/src/gallium/state_trackers/egl/common/egl_g3d_api.c @@ -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; } -- 2.30.2