diff -r cf8fab52e33b src/video/SDL_egl.c --- a/src/video/SDL_egl.c Thu Apr 09 22:28:37 2015 -0400 +++ b/src/video/SDL_egl.c Fri Apr 10 21:33:03 2015 +0900 @@ -259,6 +259,7 @@ LOAD_FUNC(eglWaitNative); LOAD_FUNC(eglWaitGL); LOAD_FUNC(eglBindAPI); + LOAD_FUNC(eglQueryAPI); LOAD_FUNC(eglQueryString); #if !defined(__WINRT__) @@ -283,6 +284,23 @@ return 0; } +int +SDL_EGL_BindAPI(_THIS, EGLenum eglapi) +{ + if (!_this->egl_data) { + return SDL_SetError("EGL not initialized"); + } + + /* TODO: Does this need to use TLS for the current API? */ + if (_this->egl_data->eglQueryAPI() != eglapi) { + if (!_this->egl_data->eglBindAPI(eglapi)) { + return SDL_SetError("Unable to bind EGL api"); + } + } + + return 0; +} + int SDL_EGL_ChooseConfig(_THIS) { @@ -342,11 +360,11 @@ } else { attribs[i++] = EGL_OPENGL_ES_BIT; } - _this->egl_data->eglBindAPI(EGL_OPENGL_ES_API); + SDL_EGL_BindAPI(_this, EGL_OPENGL_ES_API); } else { attribs[i++] = EGL_OPENGL_BIT; - _this->egl_data->eglBindAPI(EGL_OPENGL_API); + SDL_EGL_BindAPI(_this, EGL_OPENGL_API); } attribs[i++] = EGL_NONE; @@ -407,19 +425,27 @@ }; EGLContext egl_context, share_context = EGL_NO_CONTEXT; - + EGLenum context_api = EGL_NONE; + if (!_this->egl_data) { /* The EGL library wasn't loaded, SDL_GetError() should have info */ return NULL; } if (_this->gl_config.share_with_current_context) { - share_context = (EGLContext)SDL_GL_GetCurrentContext(); + SDL_EGLContext sdl_egl_context = + (SDL_EGLContext)SDL_GL_GetCurrentContext(); + + if (sdl_egl_context != NULL) { + /* TODO: What if current context is from a different API */ + share_context = sdl_egl_context->context; + } } /* Bind the API */ if(_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) { - _this->egl_data->eglBindAPI(EGL_OPENGL_ES_API); + context_api = EGL_OPENGL_ES_API; + SDL_EGL_BindAPI(_this, context_api); if (_this->gl_config.major_version) { context_attrib_list[1] = _this->gl_config.major_version; } @@ -429,7 +455,8 @@ share_context, context_attrib_list); } else { - _this->egl_data->eglBindAPI(EGL_OPENGL_API); + context_api = EGL_OPENGL_ES_API; + SDL_EGL_BindAPI(_this, context_api); #ifdef EGL_KHR_create_context if(SDL_EGL_HasExtension(_this, "EGL_KHR_create_context")) { context_attrib_list[0] = EGL_CONTEXT_MAJOR_VERSION_KHR; @@ -465,36 +492,61 @@ } _this->egl_data->egl_swapinterval = 0; - - if (SDL_EGL_MakeCurrent(_this, egl_surface, egl_context) < 0) { - SDL_EGL_DeleteContext(_this, egl_context); + + /* Encapsulate the api into the egl context */ + SDL_EGLContext sdl_egl_context = SDL_malloc(sizeof *sdl_egl_context); + + if (sdl_egl_context == NULL) { + SDL_OutOfMemory(); + return NULL; + } + + sdl_egl_context->context = egl_context; + sdl_egl_context->api = context_api; + + if (SDL_EGL_MakeCurrent(_this, egl_surface, sdl_egl_context) < 0) { + SDL_EGL_DeleteContext(_this, sdl_egl_context); SDL_SetError("Could not make EGL context current"); return NULL; } - return (SDL_GLContext) egl_context; + return (SDL_GLContext) sdl_egl_context; } int SDL_EGL_MakeCurrent(_THIS, EGLSurface egl_surface, SDL_GLContext context) { - EGLContext egl_context = (EGLContext) context; + SDL_EGLContext egl_context = (SDL_EGLContext) context; + EGLBoolean status; if (!_this->egl_data) { - return SDL_SetError("OpenGL not initialized"); + return SDL_SetError("EGL not initialized"); } /* The android emulator crashes badly if you try to eglMakeCurrent * with a valid context and invalid surface, so we have to check for both here. + * EGL could still fail here for whatever reason. If so the previous context + * will be made current so also check the status. */ - if (!egl_context || !egl_surface) { - _this->egl_data->eglMakeCurrent(_this->egl_data->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + if (!egl_context || egl_context->context == EGL_NO_CONTEXT || !egl_surface) { + status = _this->egl_data->eglMakeCurrent(_this->egl_data->egl_display, + EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); } else { - if (!_this->egl_data->eglMakeCurrent(_this->egl_data->egl_display, - egl_surface, egl_surface, egl_context)) { - return SDL_SetError("Unable to make EGL context current"); + /* EGL API must be bound per thread. If the Context was created on another thread + * or with a different API to the current then it needs to be changed. + * EGL_BindAPI will checking if the API is bound or not. + */ + if (SDL_EGL_BindAPI(_this, egl_context->api) != 0) { + return SDL_SetError("Unable to bind EGL api for context"); } + + status = _this->egl_data->eglMakeCurrent(_this->egl_data->egl_display, + egl_surface, egl_surface, egl_context->context); + } + + if (!status) { + return SDL_SetError("Unable to make EGL context current"); } return 0; @@ -537,18 +589,20 @@ void SDL_EGL_DeleteContext(_THIS, SDL_GLContext context) { - EGLContext egl_context = (EGLContext) context; + SDL_EGLContext egl_context = (SDL_EGLContext) context; /* Clean up GLES and EGL */ if (!_this->egl_data) { return; } - if (egl_context != NULL && egl_context != EGL_NO_CONTEXT) { - SDL_EGL_MakeCurrent(_this, NULL, NULL); - _this->egl_data->eglDestroyContext(_this->egl_data->egl_display, egl_context); + if (egl_context != NULL) { + if (egl_context->context != EGL_NO_CONTEXT) { + _this->egl_data->eglDestroyContext(_this->egl_data->egl_display, egl_context->context); + } + + SDL_free(egl_context); } - } EGLSurface * diff -r cf8fab52e33b src/video/SDL_egl_c.h --- a/src/video/SDL_egl_c.h Thu Apr 09 22:28:37 2015 -0400 +++ b/src/video/SDL_egl_c.h Fri Apr 10 21:33:03 2015 +0900 @@ -78,9 +78,19 @@ EGLBoolean(EGLAPIENTRY *eglWaitGL)(void); EGLBoolean(EGLAPIENTRY *eglBindAPI)(EGLenum); + + EGLenum(EGLAPIENTRY *eglQueryAPI)(void); } SDL_EGL_VideoData; +typedef struct SDL_EGL_Context +{ + EGLContext context; + EGLenum api; +} SDL_EGL_Context; + +typedef SDL_EGL_Context* SDL_EGLContext; + /* OpenGLES functions */ extern int SDL_EGL_GetAttribute(_THIS, SDL_GLattr attrib, int *value); extern int SDL_EGL_LoadLibrary(_THIS, const char *path, NativeDisplayType native_display);