Mesa (master): egl: Use reference counting to replace IsLinked or IsBound.

Chia-I Wu olv at kemper.freedesktop.org
Sat Oct 23 08:59:02 UTC 2010


Module: Mesa
Branch: master
Commit: d19afc57fe49816f3f3290410e0124d326577be2
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=d19afc57fe49816f3f3290410e0124d326577be2

Author: Chia-I Wu <olv at lunarg.com>
Date:   Sat Oct 23 12:52:26 2010 +0800

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.

---

 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 75aa29f..a5f95b9 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 256de57..8ec7c48 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 913ddd2..efa9e97 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 b4cc743..3266a75 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 9c1e218..8cd0df1 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);
 
 
 /**
@@ -65,19 +67,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 bdc325a..adb939a 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 b833258..ef01b32 100644
--- a/src/egl/main/eglsurface.h
+++ b/src/egl/main/eglsurface.h
@@ -68,19 +68,6 @@ _eglSwapInterval(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLint in
 
 
 /**
- * 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.
  */
 static INLINE _EGLSurface *
@@ -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 97ae67c..a002523 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 3bde397..c10245b 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;
 }




More information about the mesa-commit mailing list