From f1a7c00d062c7775784fc61a0ed5a15fc75c4ca9 Mon Sep 17 00:00:00 2001 From: Alex Szpakowski Date: Mon, 11 May 2015 21:03:36 -0300 Subject: [PATCH] Refactored SDL_EGL_CreateContext: It now supports context flags and OpenGL ES 3+ contexts, and its behavior more closely matches the GLX and WGL context creation code. Improved the code style consistency of SDL_egl.c. Fixes bugzilla #2865. --- src/video/SDL_egl.c | 159 ++++++++++++++++++++++++-------------------- 1 file changed, 87 insertions(+), 72 deletions(-) mode change 100644 => 100755 src/video/SDL_egl.c diff --git a/src/video/SDL_egl.c b/src/video/SDL_egl.c old mode 100644 new mode 100755 index a93b7b71f5c79..74266840ef6e7 --- a/src/video/SDL_egl.c +++ b/src/video/SDL_egl.c @@ -31,6 +31,13 @@ #include "SDL_loadso.h" #include "SDL_hints.h" +#ifdef EGL_KHR_create_context +/* EGL_OPENGL_ES3_BIT_KHR was added in version 13 of the extension. */ +#ifndef EGL_OPENGL_ES3_BIT_KHR +#define EGL_OPENGL_ES3_BIT_KHR 0x00000040 +#endif +#endif /* EGL_KHR_create_context */ + #if SDL_VIDEO_DRIVER_RPI /* Raspbian places the OpenGL ES/EGL binaries in a non standard path */ #define DEFAULT_EGL "/opt/vc/lib/libEGL.so" @@ -81,19 +88,18 @@ static int SDL_EGL_HasExtension(_THIS, const char *ext) ext_len = SDL_strlen(ext); exts = _this->egl_data->eglQueryString(_this->egl_data->egl_display, EGL_EXTENSIONS); - if(exts) { + if (exts) { ext_word = exts; - for(i = 0; exts[i] != 0; i++) { - if(exts[i] == ' ') { - if(ext_len == len && !SDL_strncmp(ext_word, ext, len)) { + for (i = 0; exts[i] != 0; i++) { + if (exts[i] == ' ') { + if (ext_len == len && !SDL_strncmp(ext_word, ext, len)) { return 1; } len = 0; ext_word = &exts[i + 1]; - } - else { + } else { len++; } } @@ -190,12 +196,11 @@ SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_displa } if (egl_dll_handle == NULL) { - if(_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) { + if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) { if (_this->gl_config.major_version > 1) { path = DEFAULT_OGL_ES2; egl_dll_handle = SDL_LoadObject(path); - } - else { + } else { path = DEFAULT_OGL_ES; egl_dll_handle = SDL_LoadObject(path); if (egl_dll_handle == NULL) { @@ -334,17 +339,22 @@ SDL_EGL_ChooseConfig(_THIS) attribs[i++] = EGL_SAMPLES; attribs[i++] = _this->gl_config.multisamplesamples; } - + attribs[i++] = EGL_RENDERABLE_TYPE; - if(_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) { - if (_this->gl_config.major_version == 2) { + if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) { +#ifdef EGL_KHR_create_context + if (_this->gl_config.major_version >= 3 && + SDL_EGL_HasExtension(_this, "EGL_KHR_create_context")) { + attribs[i++] = EGL_OPENGL_ES3_BIT_KHR; + } else +#endif + if (_this->gl_config.major_version >= 2) { attribs[i++] = EGL_OPENGL_ES2_BIT; } else { attribs[i++] = EGL_OPENGL_ES_BIT; } _this->egl_data->eglBindAPI(EGL_OPENGL_ES_API); - } - else { + } else { attribs[i++] = EGL_OPENGL_BIT; _this->egl_data->eglBindAPI(EGL_OPENGL_API); } @@ -362,7 +372,7 @@ SDL_EGL_ChooseConfig(_THIS) /* eglChooseConfig returns a number of configurations that match or exceed the requested attribs. */ /* From those, we select the one that matches our requirements more closely via a makeshift algorithm */ - for ( i=0; igl_config.profile_mask; + 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(); } - - /* Bind the API */ - if(_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) { - _this->egl_data->eglBindAPI(EGL_OPENGL_ES_API); - if (_this->gl_config.major_version) { - context_attrib_list[1] = _this->gl_config.major_version; + + /* Set the context version and other attributes. */ + if (_this->gl_config.major_version < 3 && _this->gl_config.flags == 0 && + (profile_mask == 0 || profile_mask == SDL_GL_CONTEXT_PROFILE_ES)) { + /* Create a context without using EGL_KHR_create_context attribs. */ + if (profile_mask == SDL_GL_CONTEXT_PROFILE_ES) { + attribs[attr++] = EGL_CONTEXT_CLIENT_VERSION; + attribs[attr++] = SDL_max(_this->gl_config.major_version, 1); } + } else { +#ifdef EGL_KHR_create_context + /* The Major/minor version, context profiles, and context flags can + * only be specified when this extension is available. + */ + if (SDL_EGL_HasExtension(_this, "EGL_KHR_create_context")) { + attribs[attr++] = EGL_CONTEXT_MAJOR_VERSION_KHR; + attribs[attr++] = _this->gl_config.major_version; + attribs[attr++] = EGL_CONTEXT_MINOR_VERSION_KHR; + attribs[attr++] = _this->gl_config.minor_version; + + /* SDL profile bits match EGL profile bits. */ + if (profile_mask != 0 && profile_mask != SDL_GL_CONTEXT_PROFILE_ES) { + attribs[attr++] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR; + attribs[attr++] = profile_mask; + } - egl_context = _this->egl_data->eglCreateContext(_this->egl_data->egl_display, - _this->egl_data->egl_config, - share_context, context_attrib_list); - } - else { - _this->egl_data->eglBindAPI(EGL_OPENGL_API); -#ifdef EGL_KHR_create_context - if(SDL_EGL_HasExtension(_this, "EGL_KHR_create_context")) { - context_attrib_list[0] = EGL_CONTEXT_MAJOR_VERSION_KHR; - context_attrib_list[1] = _this->gl_config.major_version; - context_attrib_list[2] = EGL_CONTEXT_MINOR_VERSION_KHR; - context_attrib_list[3] = _this->gl_config.minor_version; - context_attrib_list[4] = EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR; - switch(_this->gl_config.profile_mask) { - case SDL_GL_CONTEXT_PROFILE_COMPATIBILITY: - context_attrib_list[5] = EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT_KHR; - break; - - case SDL_GL_CONTEXT_PROFILE_CORE: - default: - context_attrib_list[5] = EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT_KHR; - break; + /* SDL flags match EGL flags. */ + if (_this->gl_config.flags != 0) { + attribs[attr++] = EGL_CONTEXT_FLAGS_KHR; + attribs[attr++] = _this->gl_config.flags; } - } - else { - context_attrib_list[0] = EGL_NONE; - } -#else /* EGL_KHR_create_context */ - context_attrib_list[0] = EGL_NONE; + } else #endif /* EGL_KHR_create_context */ - egl_context = _this->egl_data->eglCreateContext(_this->egl_data->egl_display, - _this->egl_data->egl_config, - share_context, context_attrib_list); + { + SDL_SetError("Could not create EGL context (context attributes are not supported)"); + return NULL; + } } - + + attribs[attr++] = EGL_NONE; + + /* Bind the API */ + if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) { + _this->egl_data->eglBindAPI(EGL_OPENGL_ES_API); + } else { + _this->egl_data->eglBindAPI(EGL_OPENGL_API); + } + + egl_context = _this->egl_data->eglCreateContext(_this->egl_data->egl_display, + _this->egl_data->egl_config, + share_context, attribs); + if (egl_context == EGL_NO_CONTEXT) { SDL_SetError("Could not create EGL context"); return NULL; } - + _this->egl_data->egl_swapinterval = 0; - + if (SDL_EGL_MakeCurrent(_this, egl_surface, egl_context) < 0) { SDL_EGL_DeleteContext(_this, egl_context); SDL_SetError("Could not make EGL context current"); return NULL; } - + return (SDL_GLContext) egl_context; } @@ -489,8 +505,7 @@ SDL_EGL_MakeCurrent(_THIS, EGLSurface egl_surface, SDL_GLContext context) */ if (!egl_context || !egl_surface) { _this->egl_data->eglMakeCurrent(_this->egl_data->egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - } - else { + } 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");