summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChia-I Wu <olv@lunarg.com>2010-10-23 12:52:26 +0800
committerChia-I Wu <olv@lunarg.com>2010-10-23 15:26:28 +0800
commitd19afc57fe49816f3f3290410e0124d326577be2 (patch)
tree8d90c500c91f8c2e703a05259c85406d4261c3ed
parentdc4f845c37a8446de19036e24fd397a0aa864c02 (diff)
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.
-rw-r--r--src/egl/drivers/dri2/egl_dri2.c35
-rw-r--r--src/egl/drivers/glx/egl_glx.c32
-rw-r--r--src/egl/main/eglapi.c17
-rw-r--r--src/egl/main/eglcontext.c75
-rw-r--r--src/egl/main/eglcontext.h31
-rw-r--r--src/egl/main/eglimage.h11
-rw-r--r--src/egl/main/eglsurface.h27
-rw-r--r--src/egl/main/eglsync.h14
-rw-r--r--src/gallium/state_trackers/egl/common/egl_g3d_api.c44
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 75aa29f55b..a5f95b944c 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 256de57ed8..8ec7c48c50 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 913ddd288b..efa9e97346 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 b4cc743958..3266a75824 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 9c1e2184c6..8cd0df1731 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 bdc325a7f3..adb939a9e0 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 b833258bf6..ef01b32ede 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 97ae67cf86..a0025237e7 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 3bde39737b..c10245bb06 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;
}