X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fegl%2Fmain%2Feglcontext.c;h=588f48921f2d28c177bec9e8bc4a826e0efb1910;hb=c59ad265df655a19285d813144f6b76d7f49d7fd;hp=d5a1e79a9948926a8a1d3f07f7db90a2983e9dbc;hpb=848945e5d63ff8327f5a1a6e61e66fcdab3ac8fc;p=mesa.git diff --git a/src/egl/main/eglcontext.c b/src/egl/main/eglcontext.c index d5a1e79a994..588f48921f2 100644 --- a/src/egl/main/eglcontext.c +++ b/src/egl/main/eglcontext.c @@ -1,3 +1,33 @@ +/************************************************************************** + * + * Copyright 2008 VMware, Inc. + * Copyright 2009-2010 Chia-I Wu + * Copyright 2010-2011 LunarG, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + #include #include #include @@ -19,13 +49,16 @@ _eglGetContextAPIBit(_EGLContext *ctx) switch (ctx->ClientAPI) { case EGL_OPENGL_ES_API: - switch (ctx->ClientVersion) { + switch (ctx->ClientMajorVersion) { case 1: bit = EGL_OPENGL_ES_BIT; break; case 2: bit = EGL_OPENGL_ES2_BIT; break; + case 3: + bit = EGL_OPENGL_ES3_BIT_KHR; + break; default: break; } @@ -48,7 +81,8 @@ _eglGetContextAPIBit(_EGLContext *ctx) * Parse the list of context attributes and return the proper error code. */ static EGLint -_eglParseContextAttribList(_EGLContext *ctx, const EGLint *attrib_list) +_eglParseContextAttribList(_EGLContext *ctx, _EGLDisplay *dpy, + const EGLint *attrib_list) { EGLenum api = ctx->ClientAPI; EGLint i, err = EGL_SUCCESS; @@ -56,22 +90,175 @@ _eglParseContextAttribList(_EGLContext *ctx, const EGLint *attrib_list) if (!attrib_list) return EGL_SUCCESS; + if (api == EGL_OPENVG_API && attrib_list[0] != EGL_NONE) { + _eglLog(_EGL_DEBUG, "bad context attribute 0x%04x", attrib_list[0]); + return EGL_BAD_ATTRIBUTE; + } + for (i = 0; attrib_list[i] != EGL_NONE; i++) { EGLint attr = attrib_list[i++]; EGLint val = attrib_list[i]; switch (attr) { case EGL_CONTEXT_CLIENT_VERSION: - if (api != EGL_OPENGL_ES_API) { + /* The EGL 1.4 spec says: + * + * "attribute EGL_CONTEXT_CLIENT_VERSION is only valid when the + * current rendering API is EGL_OPENGL_ES_API" + * + * The EGL_KHR_create_context spec says: + * + * "EGL_CONTEXT_MAJOR_VERSION_KHR 0x3098 + * (this token is an alias for EGL_CONTEXT_CLIENT_VERSION)" + * + * "The values for attributes EGL_CONTEXT_MAJOR_VERSION_KHR and + * EGL_CONTEXT_MINOR_VERSION_KHR specify the requested client API + * version. They are only meaningful for OpenGL and OpenGL ES + * contexts, and specifying them for other types of contexts will + * generate an error." + */ + if ((api != EGL_OPENGL_ES_API && + (!dpy->Extensions.KHR_create_context || api != EGL_OPENGL_API))) { + err = EGL_BAD_ATTRIBUTE; + break; + } + + ctx->ClientMajorVersion = val; + break; + + case EGL_CONTEXT_MINOR_VERSION_KHR: + /* The EGL_KHR_create_context spec says: + * + * "The values for attributes EGL_CONTEXT_MAJOR_VERSION_KHR and + * EGL_CONTEXT_MINOR_VERSION_KHR specify the requested client API + * version. They are only meaningful for OpenGL and OpenGL ES + * contexts, and specifying them for other types of contexts will + * generate an error." + */ + if (!dpy->Extensions.KHR_create_context || + (api != EGL_OPENGL_ES_API && api != EGL_OPENGL_API)) { + err = EGL_BAD_ATTRIBUTE; + break; + } + + ctx->ClientMinorVersion = val; + break; + + case EGL_CONTEXT_FLAGS_KHR: + if (!dpy->Extensions.KHR_create_context) { + err = EGL_BAD_ATTRIBUTE; + break; + } + + /* The EGL_KHR_create_context spec says: + * + * "Flags are only defined for OpenGL context creation, and + * specifying a flags value other than zero for other types of + * contexts, including OpenGL ES contexts, will generate an + * error." + */ + if (api != EGL_OPENGL_API && val != 0) { + err = EGL_BAD_ATTRIBUTE; + break; + } + + ctx->Flags |= val; + break; + + case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR: + if (!dpy->Extensions.KHR_create_context) { + err = EGL_BAD_ATTRIBUTE; + break; + } + + /* The EGL_KHR_create_context spec says: + * + * "[EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR] is only meaningful for + * OpenGL contexts, and specifying it for other types of + * contexts, including OpenGL ES contexts, will generate an + * error." + */ + if (api != EGL_OPENGL_API) { + err = EGL_BAD_ATTRIBUTE; + break; + } + + ctx->Profile = val; + break; + + case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR: + /* The EGL_KHR_create_context spec says: + * + * "[EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR] is only + * meaningful for OpenGL contexts, and specifying it for other + * types of contexts, including OpenGL ES contexts, will generate + * an error." + */ + if (!dpy->Extensions.KHR_create_context + || api != EGL_OPENGL_API) { + err = EGL_BAD_ATTRIBUTE; + break; + } + + ctx->ResetNotificationStrategy = val; + break; + + case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT: + /* The EGL_EXT_create_context_robustness spec says: + * + * "[EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT] is only + * meaningful for OpenGL ES contexts, and specifying it for other + * types of contexts will generate an EGL_BAD_ATTRIBUTE error." + */ + if (!dpy->Extensions.EXT_create_context_robustness + || api != EGL_OPENGL_ES_API) { + err = EGL_BAD_ATTRIBUTE; + break; + } + + ctx->ResetNotificationStrategy = val; + break; + + case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT: + if (!dpy->Extensions.EXT_create_context_robustness) { err = EGL_BAD_ATTRIBUTE; break; } - if (val != 1 && val != 2) { + + if (val == EGL_TRUE) + ctx->Flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR; + break; + + case EGL_CONTEXT_OPENGL_ROBUST_ACCESS: + if (dpy->Version < 15) { err = EGL_BAD_ATTRIBUTE; break; } - ctx->ClientVersion = val; + + if (val == EGL_TRUE) + ctx->Flags |= EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR; + break; + + case EGL_CONTEXT_OPENGL_DEBUG: + if (dpy->Version < 15) { + err = EGL_BAD_ATTRIBUTE; + break; + } + + if (val == EGL_TRUE) + ctx->Flags |= EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR; + break; + + case EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE: + if (dpy->Version < 15) { + err = EGL_BAD_ATTRIBUTE; + break; + } + + if (val == EGL_TRUE) + ctx->Flags |= EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR; break; + default: err = EGL_BAD_ATTRIBUTE; break; @@ -83,13 +270,145 @@ _eglParseContextAttribList(_EGLContext *ctx, const EGLint *attrib_list) } } - if (err == EGL_SUCCESS) { - EGLint renderable_type, api_bit; + if (api == EGL_OPENGL_API) { + /* The EGL_KHR_create_context spec says: + * + * "If the requested OpenGL version is less than 3.2, + * EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR is ignored and the + * functionality of the context is determined solely by the + * requested version." + * + * Since the value is ignored, only validate the setting if the version + * is >= 3.2. + */ + if (ctx->ClientMajorVersion >= 4 + || (ctx->ClientMajorVersion == 3 && ctx->ClientMinorVersion >= 2)) { + switch (ctx->Profile) { + case EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR: + case EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR: + break; - renderable_type = GET_CONFIG_ATTRIB(ctx->Config, EGL_RENDERABLE_TYPE); - api_bit = _eglGetContextAPIBit(ctx); - if (!(renderable_type & api_bit)) - err = EGL_BAD_CONFIG; + default: + /* The EGL_KHR_create_context spec says: + * + * "* If an OpenGL context is requested, the requested version + * is greater than 3.2, and the value for attribute + * EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR has no bits set; has + * any bits set other than EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR + * and EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; has + * more than one of these bits set; or if the implementation does + * not support the requested profile, then an EGL_BAD_MATCH error + * is generated." + */ + err = EGL_BAD_MATCH; + break; + } + } + + /* The EGL_KHR_create_context spec says: + * + * "* If an OpenGL context is requested and the values for + * attributes EGL_CONTEXT_MAJOR_VERSION_KHR and + * EGL_CONTEXT_MINOR_VERSION_KHR, when considered together with + * the value for attribute + * EGL_CONTEXT_FORWARD_COMPATIBLE_BIT_KHR, specify an OpenGL + * version and feature set that are not defined, than an + * EGL_BAD_MATCH error is generated. + * + * ... Thus, examples of invalid combinations of attributes + * include: + * + * - Major version < 1 or > 4 + * - Major version == 1 and minor version < 0 or > 5 + * - Major version == 2 and minor version < 0 or > 1 + * - Major version == 3 and minor version < 0 or > 2 + * - Major version == 4 and minor version < 0 or > 2 + * - Forward-compatible flag set and major version < 3" + */ + if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0) + err = EGL_BAD_MATCH; + + switch (ctx->ClientMajorVersion) { + case 1: + if (ctx->ClientMinorVersion > 5 + || (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0) + err = EGL_BAD_MATCH; + break; + + case 2: + if (ctx->ClientMinorVersion > 1 + || (ctx->Flags & EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR) != 0) + err = EGL_BAD_MATCH; + break; + + case 3: + /* Note: The text above is incorrect. There *is* an OpenGL 3.3! + */ + if (ctx->ClientMinorVersion > 3) + err = EGL_BAD_MATCH; + break; + + case 4: + default: + /* Don't put additional version checks here. We don't know that + * there won't be versions > 4.2. + */ + break; + } + } else if (api == EGL_OPENGL_ES_API) { + /* The EGL_KHR_create_context spec says: + * + * "* If an OpenGL ES context is requested and the values for + * attributes EGL_CONTEXT_MAJOR_VERSION_KHR and + * EGL_CONTEXT_MINOR_VERSION_KHR specify an OpenGL ES version that + * is not defined, than an EGL_BAD_MATCH error is generated. + * + * ... Examples of invalid combinations of attributes include: + * + * - Major version < 1 or > 2 + * - Major version == 1 and minor version < 0 or > 1 + * - Major version == 2 and minor version != 0 + */ + if (ctx->ClientMajorVersion < 1 || ctx->ClientMinorVersion < 0) + err = EGL_BAD_MATCH; + + switch (ctx->ClientMajorVersion) { + case 1: + if (ctx->ClientMinorVersion > 1) + err = EGL_BAD_MATCH; + break; + + case 2: + if (ctx->ClientMinorVersion > 0) + err = EGL_BAD_MATCH; + break; + + case 3: + /* Don't put additional version checks here. We don't know that + * there won't be versions > 3.0. + */ + break; + + default: + err = EGL_BAD_MATCH; + break; + } + } + + switch (ctx->ResetNotificationStrategy) { + case EGL_NO_RESET_NOTIFICATION_KHR: + case EGL_LOSE_CONTEXT_ON_RESET_KHR: + break; + + default: + err = EGL_BAD_ATTRIBUTE; + break; + } + + if ((ctx->Flags & ~(EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR + | EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR + | EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR)) != 0) { + err = EGL_BAD_ATTRIBUTE; } return err; @@ -112,15 +431,29 @@ _eglInitContext(_EGLContext *ctx, _EGLDisplay *dpy, _EGLConfig *conf, return EGL_FALSE; } - memset(ctx, 0, sizeof(_EGLContext)); - ctx->Resource.Display = dpy; + _eglInitResource(&ctx->Resource, sizeof(*ctx), dpy); ctx->ClientAPI = api; ctx->Config = conf; ctx->WindowRenderBuffer = EGL_NONE; + ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; + + ctx->ClientMajorVersion = 1; /* the default, per EGL spec */ + ctx->ClientMinorVersion = 0; + ctx->Flags = 0; + ctx->Profile = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; + ctx->ResetNotificationStrategy = EGL_NO_RESET_NOTIFICATION_KHR; - ctx->ClientVersion = 1; /* the default, per EGL spec */ + err = _eglParseContextAttribList(ctx, dpy, attrib_list); + if (err == EGL_SUCCESS && ctx->Config) { + EGLint api_bit; - err = _eglParseContextAttribList(ctx, attrib_list); + api_bit = _eglGetContextAPIBit(ctx); + if (!(ctx->Config->RenderableType & api_bit)) { + _eglLog(_EGL_DEBUG, "context api is 0x%x while config supports 0x%x", + api_bit, ctx->Config->RenderableType); + err = EGL_BAD_CONFIG; + } + } if (err != EGL_SUCCESS) return _eglError(err, "eglCreateContext"); @@ -128,30 +461,6 @@ _eglInitContext(_EGLContext *ctx, _EGLDisplay *dpy, _EGLConfig *conf, } -/** - * Just a placeholder/demo function. Real driver will never use this! - */ -_EGLContext * -_eglCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, - _EGLContext *share_list, const EGLint *attrib_list) -{ - return NULL; -} - - -/** - * Default fallback routine - drivers should usually override this. - */ -EGLBoolean -_eglDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx) -{ - if (!_eglIsContextBound(ctx)) - free(ctx); - return EGL_TRUE; -} - - -#ifdef EGL_VERSION_1_2 static EGLint _eglQueryContextRenderBuffer(_EGLContext *ctx) { @@ -166,7 +475,6 @@ _eglQueryContextRenderBuffer(_EGLContext *ctx) rb = surf->RenderBuffer; return rb; } -#endif /* EGL_VERSION_1_2 */ EGLBoolean @@ -181,19 +489,19 @@ _eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c, switch (attribute) { case EGL_CONFIG_ID: - *value = GET_CONFIG_ATTRIB(c->Config, EGL_CONFIG_ID); + if (!c->Config) + return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext"); + *value = c->Config->ConfigID; break; case EGL_CONTEXT_CLIENT_VERSION: - *value = c->ClientVersion; + *value = c->ClientMajorVersion; break; -#ifdef EGL_VERSION_1_2 case EGL_CONTEXT_CLIENT_TYPE: *value = c->ClientAPI; break; case EGL_RENDER_BUFFER: *value = _eglQueryContextRenderBuffer(c); break; -#endif /* EGL_VERSION_1_2 */ default: return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext"); } @@ -202,66 +510,6 @@ _eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c, } -/** - * Bind the context to the surfaces. Return the surfaces that are "orphaned". - * That is, when the context is not NULL, return the surfaces it previously - * bound to; when the context is NULL, the same surfaces are returned. - */ -static void -_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 (newCtx != oldCtx) { - if (oldCtx) { - assert(oldCtx->DrawSurface == newDraw); - oldCtx->DrawSurface = NULL; - } - - if (newCtx) { - _EGLSurface *oldDraw = newCtx->DrawSurface; - if (oldDraw) - oldDraw->CurrentContext = NULL; - - newCtx->DrawSurface = newDraw; - *draw = oldDraw; - } - - newDraw->CurrentContext = newCtx; - } - - /* likewise */ - if (newRead != newDraw) - oldCtx = newRead->CurrentContext; - if (newCtx != oldCtx) { - if (oldCtx) { - assert(oldCtx->ReadSurface == newRead); - oldCtx->ReadSurface = NULL; - } - - if (newCtx) { - _EGLSurface *oldRead = newCtx->ReadSurface; - if (oldRead) - oldRead->CurrentContext = NULL; - - newCtx->ReadSurface = newRead; - *read = oldRead; - } - - newRead->CurrentContext = newCtx; - } -} - - /** * Bind the context to the thread and return the previous context. * @@ -297,6 +545,7 @@ static EGLBoolean _eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read) { _EGLThreadInfo *t = _eglGetCurrentThread(); + _EGLDisplay *dpy; EGLint conflict_api; if (_eglIsCurrentThreadDummy()) @@ -309,14 +558,11 @@ _eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read) return EGL_TRUE; } - /* ctx/draw/read must be all given */ - if (draw == NULL || read == NULL) + dpy = ctx->Resource.Display; + if (!dpy->Extensions.KHR_surfaceless_context + && (draw == NULL || read == NULL)) return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); - /* context stealing from another thread is not allowed */ - if (ctx->Binding && ctx->Binding != t) - return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); - /* * The spec says * @@ -324,23 +570,42 @@ _eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read) * bound to contexts in another thread, an EGL_BAD_ACCESS error is * generated." * - * But it also says + * and * * "at most one context may be bound to a particular surface at a given * time" - * - * The latter is more restrictive so we can check only the latter case. */ - if ((draw->CurrentContext && draw->CurrentContext != ctx) || - (read->CurrentContext && read->CurrentContext != ctx)) + if (ctx->Binding && ctx->Binding != t) return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); + if (draw && draw->CurrentContext && draw->CurrentContext != ctx) { + if (draw->CurrentContext->Binding != t || + draw->CurrentContext->ClientAPI != ctx->ClientAPI) + return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); + } + if (read && read->CurrentContext && read->CurrentContext != ctx) { + if (read->CurrentContext->Binding != t || + read->CurrentContext->ClientAPI != ctx->ClientAPI) + return _eglError(EGL_BAD_ACCESS, "eglMakeCurrent"); + } - /* simply require the configs to be equal */ - if (draw->Config != ctx->Config || read->Config != ctx->Config) - return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); + /* If the context has a config then it must match that of the two + * surfaces */ + if (ctx->Config) { + if ((draw && draw->Config != ctx->Config) || + (read && read->Config != ctx->Config)) + return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); + } else { + /* Otherwise we must be using the EGL_MESA_configless_context + * extension */ + assert(dpy->Extensions.MESA_configless_context); + + /* The extension doesn't permit binding draw and read buffers with + * differing contexts */ + if (draw && read && draw->Config != read->Config) + return _eglError(EGL_BAD_MATCH, "eglMakeCurrent"); + } switch (ctx->ClientAPI) { -#ifdef EGL_VERSION_1_4 /* OpenGL and OpenGL ES are conflicting */ case EGL_OPENGL_ES_API: conflict_api = EGL_OPENGL_API; @@ -348,7 +613,6 @@ _eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read) case EGL_OPENGL_API: conflict_api = EGL_OPENGL_ES_API; break; -#endif default: conflict_api = -1; break; @@ -363,62 +627,65 @@ _eglCheckMakeCurrent(_EGLContext *ctx, _EGLSurface *draw, _EGLSurface *read) /** * Bind the context to the current thread and given surfaces. Return the - * previously bound context and the surfaces it bound to. 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; + _EGLContext *prev_ctx; + _EGLSurface *prev_draw, *prev_read; - if (!_eglCheckMakeCurrent(newCtx, *draw, *read)) + if (!_eglCheckMakeCurrent(ctx, draw, read)) return EGL_FALSE; - /* bind the new context */ - oldCtx = _eglBindContextToThread(newCtx, t); + /* increment refcounts before binding */ + _eglGetContext(ctx); + _eglGetSurface(draw); + _eglGetSurface(read); - if (newCtx) - _eglBindContextToSurfaces(newCtx, draw, read); + /* bind the new context */ + prev_ctx = _eglBindContextToThread(ctx, t); - /* unbind the old context from its binding surfaces */ - if (oldCtx && oldCtx != newCtx) { - assert(!*draw && !*read); + /* break previous bindings */ + if (prev_ctx) { + prev_draw = prev_ctx->DrawSurface; + prev_read = prev_ctx->ReadSurface; - *draw = oldCtx->DrawSurface; - *read = oldCtx->ReadSurface; - assert(*draw && *read); + if (prev_draw) + prev_draw->CurrentContext = NULL; + if (prev_read) + prev_read->CurrentContext = NULL; - _eglBindContextToSurfaces(NULL, draw, read); + prev_ctx->DrawSurface = NULL; + prev_ctx->ReadSurface = NULL; + } + else { + prev_draw = prev_read = NULL; } - *ctx = oldCtx; - /* draw and read have been updated in _eglBindContextToSurfaces */ - - return EGL_TRUE; -} - + /* establish new bindings */ + if (ctx) { + if (draw) + draw->CurrentContext = ctx; + if (read) + read->CurrentContext = ctx; -/** - * Just a placeholder/demo function. Drivers should override this. - */ -EGLBoolean -_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw, - _EGLSurface *read, _EGLContext *ctx) -{ - return EGL_FALSE; -} + ctx->DrawSurface = draw; + ctx->ReadSurface = read; + } + assert(old_ctx && old_draw && old_read); + *old_ctx = prev_ctx; + *old_draw = prev_draw; + *old_read = prev_read; -/** - * This is defined by the EGL_MESA_copy_context extension. - */ -EGLBoolean -_eglCopyContextMESA(_EGLDriver *drv, EGLDisplay dpy, EGLContext source, - EGLContext dest, EGLint mask) -{ - /* This function will always have to be overridden/implemented in the - * device driver. If the driver is based on Mesa, use _mesa_copy_context(). - */ - return EGL_FALSE; + return EGL_TRUE; }