EGL allows multiple current contexts, as long as they are bound to different client APIs.
Signed-off-by: Chia-I Wu <[email protected]> --- src/egl/main/eglapi.c | 11 +++++++---- src/egl/main/eglcontext.c | 40 ++++++++++++++++++++++++++++++++++------ src/egl/main/eglcurrent.c | 12 +++++++----- src/egl/main/eglcurrent.h | 42 ++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 88 insertions(+), 17 deletions(-) diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c index 8f4a489..332b98a 100644 --- a/src/egl/main/eglapi.c +++ b/src/egl/main/eglapi.c @@ -550,11 +550,14 @@ eglBindAPI(EGLenum api) if (_eglIsCurrentThreadDummy()) return _eglError(EGL_BAD_ALLOC, "eglBindAPI"); + if (!_eglIsApiValid(api)) + return _eglError(EGL_BAD_PARAMETER, "eglBindAPI"); + switch (api) { #ifdef EGL_VERSION_1_4 case EGL_OPENGL_API: if (_eglGlobal.ClientAPIsMask & EGL_OPENGL_BIT) { - t->CurrentAPI = api; + t->CurrentAPIIndex = _eglConvertApiToIndex(api); return EGL_TRUE; } _eglError(EGL_BAD_PARAMETER, "eglBindAPI"); @@ -562,14 +565,14 @@ eglBindAPI(EGLenum api) #endif case EGL_OPENGL_ES_API: if (_eglGlobal.ClientAPIsMask & (EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT)) { - t->CurrentAPI = api; + t->CurrentAPIIndex = _eglConvertApiToIndex(api); return EGL_TRUE; } _eglError(EGL_BAD_PARAMETER, "eglBindAPI"); return EGL_FALSE; case EGL_OPENVG_API: if (_eglGlobal.ClientAPIsMask & EGL_OPENVG_BIT) { - t->CurrentAPI = api; + t->CurrentAPIIndex = _eglConvertApiToIndex(api); return EGL_TRUE; } _eglError(EGL_BAD_PARAMETER, "eglBindAPI"); @@ -589,7 +592,7 @@ eglQueryAPI(void) { /* returns one of EGL_OPENGL_API, EGL_OPENGL_ES_API or EGL_OPENVG_API */ _EGLThreadInfo *t = _eglGetCurrentThread(); - return t->CurrentAPI; + return _eglConvertApiFromIndex(t->CurrentAPIIndex); } diff --git a/src/egl/main/eglcontext.c b/src/egl/main/eglcontext.c index 5e24b02..81e69e9 100644 --- a/src/egl/main/eglcontext.c +++ b/src/egl/main/eglcontext.c @@ -203,10 +203,10 @@ _eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d, _EGLContext *ctx = _eglLookupContext(context); _EGLSurface *draw = _eglLookupSurface(d); _EGLSurface *read = _eglLookupSurface(r); - - _EGLContext *oldContext = _eglGetCurrentContext(); - _EGLSurface *oldDrawSurface = _eglGetCurrentSurface(EGL_DRAW); - _EGLSurface *oldReadSurface = _eglGetCurrentSurface(EGL_READ); + _EGLContext *oldContext = NULL; + _EGLSurface *oldDrawSurface = NULL; + _EGLSurface *oldReadSurface = NULL; + EGLint apiIndex; if (_eglIsCurrentThreadDummy()) return _eglError(EGL_BAD_ALLOC, "eglMakeCurrent"); @@ -225,6 +225,32 @@ _eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d, _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); return EGL_FALSE; } + +#ifdef EGL_VERSION_1_4 + /* OpenGL and OpenGL ES are conflicting */ + switch (ctx->ClientAPI) { + case EGL_OPENGL_ES_API: + if (t->CurrentContexts[_eglConvertApiToIndex(EGL_OPENGL_API)]) + return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); + break; + case EGL_OPENGL_API: + if (t->CurrentContexts[_eglConvertApiToIndex(EGL_OPENGL_ES_API)]) + return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); + break; + default: + break; + } +#endif + apiIndex = _eglConvertApiToIndex(ctx->ClientAPI); + } + else { + apiIndex = t->CurrentAPIIndex; + } + + oldContext = t->CurrentContexts[apiIndex]; + if (oldContext) { + oldDrawSurface = oldContext->DrawSurface; + oldReadSurface = oldContext->ReadSurface; } /* @@ -275,9 +301,11 @@ _eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d, ctx->IsBound = EGL_TRUE; draw->IsBound = EGL_TRUE; read->IsBound = EGL_TRUE; + t->CurrentContexts[apiIndex] = ctx; + } + else { + t->CurrentContexts[apiIndex] = NULL; } - - t->CurrentContext = ctx; return EGL_TRUE; } diff --git a/src/egl/main/eglcurrent.c b/src/egl/main/eglcurrent.c index 2071a33..96152db 100644 --- a/src/egl/main/eglcurrent.c +++ b/src/egl/main/eglcurrent.c @@ -1,4 +1,5 @@ #include <stdlib.h> +#include <string.h> #include "eglcurrent.h" #include "eglcontext.h" #include "egllog.h" @@ -63,9 +64,10 @@ static INLINE _EGLThreadInfo *_eglGetTSD(void) static void _eglInitThreadInfo(_EGLThreadInfo *t) { - t->CurrentContext = NULL; + memset(t, 0, sizeof(*t)); t->LastError = EGL_SUCCESS; - t->CurrentAPI = EGL_OPENGL_ES_API; /* default, per EGL spec */ + /* default, per EGL spec */ + t->CurrentAPIIndex = _eglConvertApiToIndex(EGL_OPENGL_ES_API); } @@ -172,7 +174,7 @@ _EGLContext * _eglGetCurrentContext(void) { _EGLThreadInfo *t = _eglGetCurrentThread(); - return t->CurrentContext; + return t->CurrentContexts[t->CurrentAPIIndex]; } @@ -183,7 +185,7 @@ _EGLDisplay * _eglGetCurrentDisplay(void) { _EGLThreadInfo *t = _eglGetCurrentThread(); - _EGLContext *ctx = t->CurrentContext; + _EGLContext *ctx = t->CurrentContexts[t->CurrentAPIIndex]; if (ctx) return ctx->Display; else @@ -198,7 +200,7 @@ _EGLSurface * _eglGetCurrentSurface(EGLint readdraw) { _EGLThreadInfo *t = _eglGetCurrentThread(); - _EGLContext *ctx = t->CurrentContext; + _EGLContext *ctx = t->CurrentContexts[t->CurrentAPIIndex]; if (ctx) { switch (readdraw) { case EGL_DRAW: diff --git a/src/egl/main/eglcurrent.h b/src/egl/main/eglcurrent.h index 9f0575f..f9fdf7b 100644 --- a/src/egl/main/eglcurrent.h +++ b/src/egl/main/eglcurrent.h @@ -4,14 +4,19 @@ #include "egltypedefs.h" +#define _EGL_API_NUM_INDICES \ + (EGL_OPENGL_API - EGL_OPENGL_ES_API + 2) /* idx 0 is for EGL_NONE */ + + /** * Per-thread info */ struct _egl_thread_info { EGLint LastError; - _EGLContext *CurrentContext; - EGLenum CurrentAPI; + _EGLContext *CurrentContexts[_EGL_API_NUM_INDICES]; + /* use index for fast access to current context */ + EGLint CurrentAPIIndex; }; @@ -23,6 +28,39 @@ extern void _eglFiniCurrent(void); +/** + * Return true if a client API enum can be converted to an index. + */ +static INLINE EGLBoolean +_eglIsApiValid(EGLenum api) +{ + return ((api >= EGL_OPENGL_ES_API && api <= EGL_OPENGL_API) || + api == EGL_NONE); +} + + +/** + * Convert a client API enum to an index, for use by thread info. + * The client API enum is assumed to be valid. + */ +static INLINE EGLint +_eglConvertApiToIndex(EGLenum api) +{ + return (api != EGL_NONE) ? api - EGL_OPENGL_ES_API + 1 : 0; +} + + +/** + * Convert an index, used by thread info, to a client API enum. + * The index is assumed to be valid. + */ +static INLINE EGLenum +_eglConvertApiFromIndex(EGLint idx) +{ + return (idx) ? EGL_OPENGL_ES_API + idx - 1 : EGL_NONE; +} + + extern _EGLThreadInfo * _eglGetCurrentThread(void); -- 1.6.2.4 ------------------------------------------------------------------------------ Enter the BlackBerry Developer Challenge This is your chance to win up to $100,000 in prizes! For a limited time, vendors submitting new applications to BlackBerry App World(TM) will have the opportunity to enter the BlackBerry Developer Challenge. See full prize details at: http://p.sf.net/sfu/Challenge _______________________________________________ Mesa3d-dev mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/mesa3d-dev
