summaryrefslogtreecommitdiff
path: root/src/egl/main/eglcontext.c
diff options
context:
space:
mode:
authorChia-I Wu <olv@lunarg.com>2010-04-05 21:26:34 +0800
committerChia-I Wu <olv@lunarg.com>2010-04-06 11:37:58 +0800
commitbbe459b14d593bd2d7b6c0f010e165fe815e8396 (patch)
treeb8ba421ebbeb5c60584045b8ab83cae3abaf10e2 /src/egl/main/eglcontext.c
parentffb6a8f55269d99d61eb3dc63dd510141ef817b4 (diff)
egl: Fix eglMakeCurrent with different surfaces.
0a82fadcdd0b6ebbc345c7c302da0e0efce40a98 seems to trigger a bug in _eglBindContext. Rework the logics yet again. It is simpler, and hopefully correct this time.
Diffstat (limited to 'src/egl/main/eglcontext.c')
-rw-r--r--src/egl/main/eglcontext.c75
1 files changed, 45 insertions, 30 deletions
diff --git a/src/egl/main/eglcontext.c b/src/egl/main/eglcontext.c
index 5e831aab33..80e316a10b 100644
--- a/src/egl/main/eglcontext.c
+++ b/src/egl/main/eglcontext.c
@@ -208,39 +208,56 @@ _eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c,
* bound to; when the context is NULL, the same surfaces are returned.
*/
static void
-_eglBindContextToSurfaces(_EGLContext *ctx,
+_eglBindContextToSurfaces(_EGLContext *newCtx,
_EGLSurface **draw, _EGLSurface **read)
{
_EGLSurface *newDraw = *draw, *newRead = *read;
_EGLContext *oldCtx;
+ /*
+ * The goal is to bind a newCtx to newDraw. Since newDraw may already have
+ * a binding context (oldCtx), and newCtx may already be bound to another
+ * surface (oldDraw), the old bindings are broken first and the new one is
+ * created.
+ */
oldCtx = newDraw->CurrentContext;
- if (ctx != oldCtx) {
+ if (newCtx != oldCtx) {
if (oldCtx) {
- assert(*draw == oldCtx->DrawSurface);
+ assert(oldCtx->DrawSurface == newDraw);
oldCtx->DrawSurface = NULL;
}
- if (ctx) {
- *draw = ctx->DrawSurface;
- ctx->DrawSurface = newDraw;
+
+ if (newCtx) {
+ _EGLSurface *oldDraw = newCtx->DrawSurface;
+ if (oldDraw)
+ oldDraw->CurrentContext = NULL;
+
+ newCtx->DrawSurface = newDraw;
+ *draw = oldDraw;
}
- newDraw->CurrentContext = ctx;
+ newDraw->CurrentContext = newCtx;
}
+ /* likewise */
if (newRead != newDraw)
oldCtx = newRead->CurrentContext;
- if (ctx != oldCtx) {
+ if (newCtx != oldCtx) {
if (oldCtx) {
- assert(*read == oldCtx->ReadSurface);
+ assert(oldCtx->ReadSurface == newRead);
oldCtx->ReadSurface = NULL;
}
- if (ctx) {
- *read = ctx->ReadSurface;
- ctx->ReadSurface = newRead;
+
+ if (newCtx) {
+ _EGLSurface *oldRead = newCtx->ReadSurface;
+ if (oldRead)
+ oldRead->CurrentContext = NULL;
+
+ newCtx->ReadSurface = newRead;
+ *read = oldRead;
}
- newRead->CurrentContext = ctx;
+ newRead->CurrentContext = newCtx;
}
}
@@ -360,27 +377,25 @@ _eglBindContext(_EGLContext **ctx, _EGLSurface **draw, _EGLSurface **read)
/* bind the new context */
oldCtx = _eglBindContextToThread(newCtx, t);
- *ctx = oldCtx;
- if (newCtx)
+
+ if (newCtx) {
_eglBindContextToSurfaces(newCtx, draw, read);
+ }
+ else {
+ assert(!*draw && !*read);
+ if (oldCtx) {
+ *draw = oldCtx->DrawSurface;
+ *read = oldCtx->ReadSurface;
+ assert(*draw && *read);
- /* unbind the old context from its binding surfaces */
- if (oldCtx && oldCtx != newCtx) {
- /*
- * If the new context replaces some old context, the new one should not
- * be current before the replacement and it should not be bound to any
- * surface.
- */
- if (newCtx)
- assert(!*draw && !*read);
-
- *draw = oldCtx->DrawSurface;
- *read = oldCtx->ReadSurface;
- assert(*draw && *read);
-
- _eglBindContextToSurfaces(NULL, draw, read);
+ /* unbind the old context from its surfaces */
+ _eglBindContextToSurfaces(NULL, draw, read);
+ }
}
+ *ctx = oldCtx;
+ /* draw and read have been updated in _eglBindContextToSurfaces */
+
return EGL_TRUE;
}