| | |
| | | #endif |
| | | |
| | | #include "SDL_sysvideo.h" |
| | | #include "SDL_log.h" |
| | | #include "SDL_egl_c.h" |
| | | #include "SDL_loadso.h" |
| | | #include "SDL_hints.h" |
| | |
| | | #define DEFAULT_OGL_ES_PVR "libGLES_CM.dylib" //??? |
| | | #define DEFAULT_OGL_ES "libGLESv1_CM.dylib" //??? |
| | | |
| | | #elif defined(__OpenBSD__) |
| | | #define DEFAULT_OGL "libGL.so" |
| | | #define DEFAULT_EGL "libEGL.so" |
| | | #define DEFAULT_OGL_ES2 "libGLESv2.so" |
| | | #define DEFAULT_OGL_ES_PVR "libGLES_CM.so" |
| | | #define DEFAULT_OGL_ES "libGLESv1_CM.so" |
| | | |
| | | #else |
| | | /* Desktop Linux */ |
| | | #define DEFAULT_OGL "libGL.so.1" |
| | |
| | | #define DEFAULT_OGL_ES_PVR "libGLES_CM.so.1" |
| | | #define DEFAULT_OGL_ES "libGLESv1_CM.so.1" |
| | | #endif /* SDL_VIDEO_DRIVER_RPI */ |
| | | |
| | | #if SDL_VIDEO_OPENGL |
| | | #include "SDL_opengl.h" |
| | | #endif |
| | | |
| | | /** If we happen to not have this defined because of an older EGL version, just define it 0x0 |
| | | as eglGetPlatformDisplayEXT will most likely be NULL if this is missing |
| | |
| | | } |
| | | |
| | | /* EGL implementation of SDL OpenGL ES support */ |
| | | typedef enum { |
| | | SDL_EGL_DISPLAY_EXTENSION, |
| | | SDL_EGL_CLIENT_EXTENSION |
| | | } SDL_EGL_ExtensionType; |
| | | |
| | | static SDL_bool SDL_EGL_HasExtension(_THIS, SDL_EGL_ExtensionType type, const char *ext) |
| | | SDL_bool SDL_EGL_HasExtension(_THIS, SDL_EGL_ExtensionType type, const char *ext) |
| | | { |
| | | size_t ext_len; |
| | | const char *ext_override; |
| | |
| | | retval = _this->egl_data->eglGetProcAddress(proc); |
| | | } |
| | | |
| | | #ifndef __EMSCRIPTEN__ /* LoadFunction isn't needed on Emscripten and will call dlsym(), causing other problems. */ |
| | | /* Try SDL_LoadFunction() first for EGL <= 1.4, or as a fallback for >= 1.5. */ |
| | | if (!retval) { |
| | | static char procname[64]; |
| | |
| | | retval = SDL_LoadFunction(_this->egl_data->egl_dll_handle, procname); |
| | | } |
| | | } |
| | | #endif |
| | | |
| | | /* Try eglGetProcAddress if we on <= 1.4 and still searching... */ |
| | | /* Try eglGetProcAddress if we're on <= 1.4 and still searching... */ |
| | | if (!retval && !is_egl_15_or_later && _this->egl_data->eglGetProcAddress) { |
| | | retval = _this->egl_data->eglGetProcAddress(proc); |
| | | if (retval) { |
| | |
| | | LOAD_FUNC(eglGetError); |
| | | LOAD_FUNC_EGLEXT(eglQueryDevicesEXT); |
| | | LOAD_FUNC_EGLEXT(eglGetPlatformDisplayEXT); |
| | | |
| | | _this->gl_config.driver_loaded = 1; |
| | | /* Atomic functions */ |
| | | LOAD_FUNC_EGLEXT(eglCreateSyncKHR); |
| | | LOAD_FUNC_EGLEXT(eglDestroySyncKHR); |
| | | LOAD_FUNC_EGLEXT(eglDupNativeFenceFDANDROID); |
| | | LOAD_FUNC_EGLEXT(eglWaitSyncKHR); |
| | | LOAD_FUNC_EGLEXT(eglClientWaitSyncKHR); |
| | | /* Atomic functions end */ |
| | | |
| | | if (path) { |
| | | SDL_strlcpy(_this->gl_config.driver_path, path, sizeof(_this->gl_config.driver_path) - 1); |
| | |
| | | EGLint found_configs = 0, value; |
| | | /* 128 seems even nicer here */ |
| | | EGLConfig configs[128]; |
| | | SDL_bool has_matching_format = SDL_FALSE; |
| | | int i, j, best_bitdiff = -1, bitdiff; |
| | | |
| | | if (!_this->egl_data) { |
| | |
| | | return SDL_EGL_SetError("Couldn't find matching EGL config", "eglChooseConfig"); |
| | | } |
| | | |
| | | /* first ensure that a found config has a matching format, or the function will fall through. */ |
| | | for (i = 0; i < found_configs; i++ ) { |
| | | if (_this->egl_data->egl_required_visual_id) |
| | | { |
| | | EGLint format; |
| | | _this->egl_data->eglGetConfigAttrib(_this->egl_data->egl_display, |
| | | configs[i], |
| | | EGL_NATIVE_VISUAL_ID, &format); |
| | | if (_this->egl_data->egl_required_visual_id == format) |
| | | has_matching_format = SDL_TRUE; |
| | | } |
| | | } |
| | | |
| | | /* 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++ ) { |
| | | if (_this->egl_data->egl_required_visual_id) |
| | | if (has_matching_format && _this->egl_data->egl_required_visual_id) |
| | | { |
| | | EGLint format; |
| | | _this->egl_data->eglGetConfigAttrib(_this->egl_data->egl_display, |
| | |
| | | return NULL; |
| | | } |
| | | |
| | | /* Check whether making contexts current without a surface is supported. |
| | | * First condition: EGL must support it. That's the case for EGL 1.5 |
| | | * or later, or if the EGL_KHR_surfaceless_context extension is present. */ |
| | | if ((_this->egl_data->egl_version_major > 1) || |
| | | ((_this->egl_data->egl_version_major == 1) && (_this->egl_data->egl_version_minor >= 5)) || |
| | | SDL_EGL_HasExtension(_this, SDL_EGL_DISPLAY_EXTENSION, "EGL_KHR_surfaceless_context")) |
| | | { |
| | | /* Secondary condition: The client API must support it. */ |
| | | if (profile_es) { |
| | | /* On OpenGL ES, the GL_OES_surfaceless_context extension must be |
| | | * present. */ |
| | | if (SDL_GL_ExtensionSupported("GL_OES_surfaceless_context")) { |
| | | _this->gl_allow_no_surface = SDL_TRUE; |
| | | } |
| | | #if SDL_VIDEO_OPENGL |
| | | } else { |
| | | /* Desktop OpenGL supports it by default from version 3.0 on. */ |
| | | void (APIENTRY * glGetIntegervFunc) (GLenum pname, GLint * params); |
| | | glGetIntegervFunc = SDL_GL_GetProcAddress("glGetIntegerv"); |
| | | if (glGetIntegervFunc) { |
| | | GLint v = 0; |
| | | glGetIntegervFunc(GL_MAJOR_VERSION, &v); |
| | | if (v >= 3) { |
| | | _this->gl_allow_no_surface = SDL_TRUE; |
| | | } |
| | | } |
| | | #endif |
| | | } |
| | | } |
| | | |
| | | return (SDL_GLContext) egl_context; |
| | | } |
| | | |
| | |
| | | /* 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. |
| | | */ |
| | | if (!egl_context || !egl_surface) { |
| | | if (!egl_context || (!egl_surface && !_this->gl_allow_no_surface)) { |
| | | _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, |