|
@@ -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; i<found_configs; i++ ) {
|
|
|
+ for (i = 0; i < found_configs; i++ ) {
|
|
|
bitdiff = 0;
|
|
|
for (j = 0; j < SDL_arraysize(attribs) - 1; j += 2) {
|
|
|
if (attribs[j] == EGL_NONE) {
|
|
@@ -386,8 +396,10 @@ SDL_EGL_ChooseConfig(_THIS)
|
|
|
|
|
|
best_bitdiff = bitdiff;
|
|
|
}
|
|
|
-
|
|
|
- if (bitdiff == 0) break; /* we found an exact match! */
|
|
|
+
|
|
|
+ if (bitdiff == 0) {
|
|
|
+ break; /* we found an exact match! */
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
@@ -396,82 +408,86 @@ SDL_EGL_ChooseConfig(_THIS)
|
|
|
SDL_GLContext
|
|
|
SDL_EGL_CreateContext(_THIS, EGLSurface egl_surface)
|
|
|
{
|
|
|
- EGLint context_attrib_list[] = {
|
|
|
- EGL_CONTEXT_CLIENT_VERSION,
|
|
|
- 1,
|
|
|
- EGL_NONE,
|
|
|
- EGL_NONE,
|
|
|
- EGL_NONE,
|
|
|
- EGL_NONE,
|
|
|
- EGL_NONE
|
|
|
- };
|
|
|
-
|
|
|
+ /* max 14 values plus terminator. */
|
|
|
+ EGLint attribs[15];
|
|
|
+ int attr = 0;
|
|
|
+
|
|
|
EGLContext egl_context, share_context = EGL_NO_CONTEXT;
|
|
|
-
|
|
|
+ EGLint profile_mask = _this->gl_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");
|