21 #include "../SDL_internal.h"
23 #if SDL_VIDEO_OPENGL_EGL
25 #if SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_WINRT
26 #include "../core/windows/SDL_windows.h"
28 #if SDL_VIDEO_DRIVER_ANDROID
29 #include <android/native_window.h>
30 #include "../core/android/SDL_android.h"
39 #ifdef EGL_KHR_create_context
41 #ifndef EGL_OPENGL_ES3_BIT_KHR
42 #define EGL_OPENGL_ES3_BIT_KHR 0x00000040
46 #if SDL_VIDEO_DRIVER_RPI
48 #define DEFAULT_EGL ( vc4 ? "libEGL.so.1" : "libbrcmEGL.so" )
49 #define DEFAULT_OGL_ES2 ( vc4 ? "libGLESv2.so.2" : "libbrcmGLESv2.so" )
50 #define ALT_EGL "libEGL.so"
51 #define ALT_OGL_ES2 "libGLESv2.so"
52 #define DEFAULT_OGL_ES_PVR ( vc4 ? "libGLES_CM.so.1" : "libbrcmGLESv2.so" )
53 #define DEFAULT_OGL_ES ( vc4 ? "libGLESv1_CM.so.1" : "libbrcmGLESv2.so" )
55 #elif SDL_VIDEO_DRIVER_ANDROID || SDL_VIDEO_DRIVER_VIVANTE
57 #define DEFAULT_EGL "libEGL.so"
58 #define DEFAULT_OGL_ES2 "libGLESv2.so"
59 #define DEFAULT_OGL_ES_PVR "libGLES_CM.so"
60 #define DEFAULT_OGL_ES "libGLESv1_CM.so"
62 #elif SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_WINRT
64 #define DEFAULT_EGL "libEGL.dll"
65 #define DEFAULT_OGL_ES2 "libGLESv2.dll"
66 #define DEFAULT_OGL_ES_PVR "libGLES_CM.dll"
67 #define DEFAULT_OGL_ES "libGLESv1_CM.dll"
69 #elif SDL_VIDEO_DRIVER_COCOA
71 #define DEFAULT_EGL "libEGL.dylib"
72 #define DEFAULT_OGL_ES2 "libGLESv2.dylib"
73 #define DEFAULT_OGL_ES_PVR "libGLES_CM.dylib" //???
74 #define DEFAULT_OGL_ES "libGLESv1_CM.dylib" //???
78 #define DEFAULT_OGL "libGL.so.1"
79 #define DEFAULT_EGL "libEGL.so.1"
80 #define DEFAULT_OGL_ES2 "libGLESv2.so.2"
81 #define DEFAULT_OGL_ES_PVR "libGLES_CM.so.1"
82 #define DEFAULT_OGL_ES "libGLESv1_CM.so.1"
88 #ifndef EGL_PLATFORM_DEVICE_EXT
89 #define EGL_PLATFORM_DEVICE_EXT 0x0
92 #ifdef SDL_VIDEO_STATIC_ANGLE
93 #define LOAD_FUNC(NAME) \
94 _this->egl_data->NAME = (void *)NAME;
96 #define LOAD_FUNC(NAME) \
97 _this->egl_data->NAME = SDL_LoadFunction(_this->egl_data->dll_handle, #NAME); \
98 if (!_this->egl_data->NAME) \
100 return SDL_SetError("Could not retrieve EGL function " #NAME); \
105 #define LOAD_FUNC_EGLEXT(NAME) \
106 _this->egl_data->NAME = _this->egl_data->eglGetProcAddress(#NAME);
109 static const char * SDL_EGL_GetErrorName(
EGLint eglErrorCode)
111 #define SDL_EGL_ERROR_TRANSLATE(e) case e: return #e;
112 switch (eglErrorCode) {
132 int SDL_EGL_SetErrorEx(
const char *
message,
const char * eglFunctionName,
EGLint eglErrorCode)
134 const char * errorText = SDL_EGL_GetErrorName(eglErrorCode);
135 char altErrorText[32];
136 if (errorText[0] ==
'\0') {
139 errorText = altErrorText;
141 return SDL_SetError(
"%s (call to %s failed, reporting an error of %s)",
message, eglFunctionName, errorText);
146 SDL_EGL_DISPLAY_EXTENSION,
147 SDL_EGL_CLIENT_EXTENSION
148 } SDL_EGL_ExtensionType;
150 static SDL_bool SDL_EGL_HasExtension(
_THIS, SDL_EGL_ExtensionType
type,
const char *ext)
153 const char *ext_override;
154 const char *egl_extstr;
155 const char *ext_start;
171 if (ext_override !=
NULL) {
172 int disable_ext =
SDL_atoi(ext_override);
173 if (disable_ext & 0x01 &&
type == SDL_EGL_DISPLAY_EXTENSION) {
175 }
else if (disable_ext & 0x02 &&
type == SDL_EGL_CLIENT_EXTENSION) {
182 case SDL_EGL_DISPLAY_EXTENSION:
185 case SDL_EGL_CLIENT_EXTENSION:
197 if (egl_extstr !=
NULL) {
198 ext_start = egl_extstr;
202 if (ext_start ==
NULL) {
206 if (ext_start == egl_extstr || *(ext_start - 1) ==
' ') {
207 if (ext_start[ext_len] ==
' ' || ext_start[ext_len] == 0) {
212 ext_start += ext_len;
213 while (*ext_start !=
' ' && *ext_start != 0) {
223 SDL_EGL_GetProcAddress(
_THIS,
const char *proc)
226 const SDL_bool is_egl_15_or_later = eglver >= ((((
Uint32) 1) << 16) | 5);
230 if (!
retval && is_egl_15_or_later &&
_this->egl_data->eglGetProcAddress) {
236 static char procname[64];
241 SDL_strlcpy(procname + 1, proc,
sizeof (procname) - 1);
247 if (!
retval && !is_egl_15_or_later &&
_this->egl_data->eglGetProcAddress) {
258 SDL_EGL_UnloadLibrary(
_THIS)
260 if (
_this->egl_data) {
261 if (
_this->egl_data->egl_display) {
262 _this->egl_data->eglTerminate(
_this->egl_data->egl_display);
270 if (
_this->egl_data->egl_dll_handle) {
281 SDL_EGL_LoadLibraryOnly(
_THIS,
const char *egl_path)
283 void *dll_handle =
NULL, *egl_dll_handle =
NULL;
285 #if SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_WINRT
286 const char *d3dcompiler;
288 #if SDL_VIDEO_DRIVER_RPI
292 if (
_this->egl_data) {
296 _this->egl_data = (
struct SDL_EGL_VideoData *)
SDL_calloc(1,
sizeof(SDL_EGL_VideoData));
297 if (!
_this->egl_data) {
301 #if SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_WINRT
312 const char *d3dcompiler_list[] = {
313 "d3dcompiler_47.dll",
"d3dcompiler_46.dll",
331 #ifndef SDL_VIDEO_STATIC_ANGLE
338 if (egl_dll_handle ==
NULL) {
341 path = DEFAULT_OGL_ES2;
344 if (egl_dll_handle ==
NULL && !vc4) {
351 path = DEFAULT_OGL_ES;
353 if (egl_dll_handle ==
NULL) {
354 path = DEFAULT_OGL_ES_PVR;
358 if (egl_dll_handle ==
NULL && !vc4) {
372 _this->egl_data->egl_dll_handle = egl_dll_handle;
374 if (egl_dll_handle ==
NULL) {
375 return SDL_SetError(
"Could not initialize OpenGL / GLES library");
379 if (egl_path !=
NULL) {
384 if (dll_handle !=
NULL) {
394 if (dll_handle ==
NULL && !vc4) {
401 if (dll_handle !=
NULL) {
433 LOAD_FUNC_EGLEXT(eglQueryDevicesEXT);
434 LOAD_FUNC_EGLEXT(eglGetPlatformDisplayEXT);
448 SDL_EGL_GetVersion(
_THIS) {
449 if (
_this->egl_data->eglQueryString) {
450 const char *egl_version =
_this->egl_data->eglQueryString(
_this->egl_data->egl_display,
EGL_VERSION);
452 int major = 0, minor = 0;
453 if (
SDL_sscanf(egl_version,
"%d.%d", &major, &minor) == 2) {
454 _this->egl_data->egl_version_major = major;
455 _this->egl_data->egl_version_minor = minor;
466 int egl_version_major, egl_version_minor;
467 int library_load_retcode = SDL_EGL_LoadLibraryOnly(
_this, egl_path);
468 if (library_load_retcode != 0) {
469 return library_load_retcode;
473 SDL_EGL_GetVersion(
_this);
475 egl_version_major =
_this->egl_data->egl_version_major;
476 egl_version_minor =
_this->egl_data->egl_version_minor;
478 if (egl_version_major == 1 && egl_version_minor == 5) {
483 #if !defined(__WINRT__)
485 if (egl_version_major == 1 && egl_version_minor == 5) {
488 if (SDL_EGL_HasExtension(
_this, SDL_EGL_CLIENT_EXTENSION,
"EGL_EXT_platform_base")) {
489 _this->egl_data->eglGetPlatformDisplayEXT = SDL_EGL_GetProcAddress(
_this,
"eglGetPlatformDisplayEXT");
490 if (
_this->egl_data->eglGetPlatformDisplayEXT) {
514 SDL_EGL_GetVersion(
_this);
516 _this->egl_data->is_offscreen = 0;
532 void *egl_devices[SDL_EGL_MAX_DEVICES];
533 EGLint num_egl_devices = 0;
534 const char *egl_device_hint;
537 return SDL_SetError(
"SDL_EGL_LoadLibraryOnly() has not been called or has failed.");
541 if (
_this->egl_data->eglQueryDevicesEXT ==
NULL) {
542 return SDL_SetError(
"eglQueryDevicesEXT is missing (EXT_device_enumeration not supported by the drivers?)");
545 if (
_this->egl_data->eglGetPlatformDisplayEXT ==
NULL) {
546 return SDL_SetError(
"eglGetPlatformDisplayEXT is missing (EXT_platform_base not supported by the drivers?)");
549 if (
_this->egl_data->eglQueryDevicesEXT(SDL_EGL_MAX_DEVICES, egl_devices, &num_egl_devices) !=
EGL_TRUE) {
553 egl_device_hint =
SDL_GetHint(
"SDL_HINT_EGL_DEVICE");
554 if (egl_device_hint) {
557 if (
device >= num_egl_devices) {
558 return SDL_SetError(
"Invalid EGL device is requested.");
564 return SDL_SetError(
"eglGetPlatformDisplayEXT() failed.");
577 for (
i = 0;
i < num_egl_devices;
i++) {
585 _this->egl_data->eglTerminate(attempted_egl_display);
590 _this->egl_data->egl_display = attempted_egl_display;
597 return SDL_SetError(
"Could not find a valid EGL device to initialize");
602 SDL_EGL_GetVersion(
_this);
604 _this->egl_data->is_offscreen = 1;
610 SDL_EGL_SetRequiredVisualId(
_THIS,
int visual_id)
612 _this->egl_data->egl_required_visual_id=visual_id;
615 #ifdef DUMP_EGL_CONFIG
617 #define ATTRIBUTE(_attr) { _attr, #_attr }
624 Attribute attributes[] = {
664 for (attr = 0 ; attr<
sizeof(attributes)/
sizeof(Attribute) ; attr++) {
666 _this->egl_data->eglGetConfigAttrib(
_this->egl_data->egl_display,
config, attributes[attr].attribute, &
value);
674 SDL_EGL_ChooseConfig(
_THIS)
681 int i,
j, best_bitdiff = -1, bitdiff;
683 if (!
_this->egl_data) {
725 if (
_this->egl_data->is_offscreen) {
732 #ifdef EGL_KHR_create_context
734 SDL_EGL_HasExtension(
_this, SDL_EGL_DISPLAY_EXTENSION,
"EGL_KHR_create_context")) {
749 if (
_this->egl_data->egl_surfacetype) {
756 if (
_this->egl_data->eglChooseConfig(
_this->egl_data->egl_display,
760 found_configs == 0) {
761 return SDL_EGL_SetError(
"Couldn't find matching EGL config",
"eglChooseConfig");
767 for (
i = 0;
i < found_configs;
i++ ) {
768 if (
_this->egl_data->egl_required_visual_id)
771 _this->egl_data->eglGetConfigAttrib(
_this->egl_data->egl_display,
774 if (
_this->egl_data->egl_required_visual_id !=
format)
796 if (bitdiff < best_bitdiff || best_bitdiff == -1) {
797 _this->egl_data->egl_config = configs[
i];
799 best_bitdiff = bitdiff;
807 #ifdef DUMP_EGL_CONFIG
808 dumpconfig(
_this,
_this->egl_data->egl_config);
827 if (!
_this->egl_data) {
836 #if SDL_VIDEO_DRIVER_ANDROID
844 int egl_version_major =
_this->egl_data->egl_version_major;
845 int egl_version_minor =
_this->egl_data->egl_version_minor;
846 if (((egl_version_major < 1) || (egl_version_major == 1 && egl_version_minor < 5)) &&
847 !SDL_EGL_HasExtension(
_this, SDL_EGL_DISPLAY_EXTENSION,
"EGL_KHR_debug")) {
855 if ((major_version < 3 || (minor_version == 0 && profile_es)) &&
857 (profile_mask == 0 || profile_es)) {
869 #ifdef EGL_KHR_create_context
873 if (SDL_EGL_HasExtension(
_this, SDL_EGL_DISPLAY_EXTENSION,
"EGL_KHR_create_context")) {
875 attribs[attr++] = major_version;
877 attribs[attr++] = minor_version;
882 attribs[attr++] = profile_mask;
893 SDL_SetError(
"Could not create EGL context (context attributes are not supported)");
899 #ifdef EGL_KHR_create_context_no_error
900 if (SDL_EGL_HasExtension(
_this, SDL_EGL_DISPLAY_EXTENSION,
"EGL_KHR_create_context_no_error")) {
906 SDL_SetError(
"EGL implementation does not support no_error contexts");
920 egl_context =
_this->egl_data->eglCreateContext(
_this->egl_data->egl_display,
921 _this->egl_data->egl_config,
925 SDL_EGL_SetError(
"Could not create EGL context",
"eglCreateContext");
929 _this->egl_data->egl_swapinterval = 0;
931 if (SDL_EGL_MakeCurrent(
_this, egl_surface, egl_context) < 0) {
933 char errorText[1024];
937 SDL_EGL_DeleteContext(
_this, egl_context);
953 if (!
_this->egl_data) {
960 if (!egl_context || !egl_surface) {
963 if (!
_this->egl_data->eglMakeCurrent(
_this->egl_data->egl_display,
964 egl_surface, egl_surface, egl_context)) {
965 return SDL_EGL_SetError(
"Unable to make EGL context current",
"eglMakeCurrent");
973 SDL_EGL_SetSwapInterval(
_THIS,
int interval)
977 if (!
_this->egl_data) {
981 status =
_this->egl_data->eglSwapInterval(
_this->egl_data->egl_display, interval);
983 _this->egl_data->egl_swapinterval = interval;
987 return SDL_EGL_SetError(
"Unable to set the EGL swap interval",
"eglSwapInterval");
991 SDL_EGL_GetSwapInterval(
_THIS)
993 if (!
_this->egl_data) {
998 return _this->egl_data->egl_swapinterval;
1004 if (!
_this->egl_data->eglSwapBuffers(
_this->egl_data->egl_display, egl_surface)) {
1005 return SDL_EGL_SetError(
"unable to show color buffer in an OS-native window",
"eglSwapBuffers");
1016 if (!
_this->egl_data) {
1021 _this->egl_data->eglDestroyContext(
_this->egl_data->egl_display, egl_context);
1035 if (SDL_EGL_ChooseConfig(
_this) != 0) {
1039 #if SDL_VIDEO_DRIVER_ANDROID
1045 _this->egl_data->eglGetConfigAttrib(
_this->egl_data->egl_display,
1046 _this->egl_data->egl_config,
1049 ANativeWindow_setBuffersGeometry(nw, 0, 0,
format);
1057 #ifdef EGL_KHR_gl_colorspace
1058 if (SDL_EGL_HasExtension(
_this, SDL_EGL_DISPLAY_EXTENSION,
"EGL_KHR_gl_colorspace")) {
1064 SDL_SetError(
"EGL implementation does not support sRGB system framebuffers");
1072 _this->egl_data->egl_display,
1073 _this->egl_data->egl_config,
1076 SDL_EGL_SetError(
"unable to create an EGL window surface",
"eglCreateWindowSurface");
1090 if (SDL_EGL_ChooseConfig(
_this) != 0) {
1094 return _this->egl_data->eglCreatePbufferSurface(
1095 _this->egl_data->egl_display,
1096 _this->egl_data->egl_config,
1103 if (!
_this->egl_data) {
1108 _this->egl_data->eglDestroySurface(
_this->egl_data->egl_display, egl_surface);