diff options
author | Chia-I Wu <[email protected]> | 2010-04-05 21:26:34 +0800 |
---|---|---|
committer | Chia-I Wu <[email protected]> | 2010-04-06 11:37:58 +0800 |
commit | bbe459b14d593bd2d7b6c0f010e165fe815e8396 (patch) | |
tree | b8ba421ebbeb5c60584045b8ab83cae3abaf10e2 /src/egl | |
parent | ffb6a8f55269d99d61eb3dc63dd510141ef817b4 (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')
-rw-r--r-- | src/egl/main/eglcontext.c | 75 |
1 files changed, 45 insertions, 30 deletions
diff --git a/src/egl/main/eglcontext.c b/src/egl/main/eglcontext.c index 5e831aab332..80e316a10b1 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; } |