From 03f8528315fa46c95991a34f3325d7b33ae5538c Mon Sep 17 00:00:00 2001
From: Edward Rudd <urkle@outoforder.cc>
Date: Sat, 02 May 2020 21:48:36 +0000
Subject: [PATCH] Update source to SDL2 2.0.12
---
source/src/video/SDL_egl.c | 287 ++++++++++++++++++++++++++++++++++++++++++++++++---------
1 files changed, 241 insertions(+), 46 deletions(-)
diff --git a/source/src/video/SDL_egl.c b/source/src/video/SDL_egl.c
index 78abc03..a8a1485 100644
--- a/source/src/video/SDL_egl.c
+++ b/source/src/video/SDL_egl.c
@@ -1,6 +1,6 @@
/*
* Simple DirectMedia Layer
- * Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
+ * Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
@@ -27,6 +27,7 @@
#endif
#if SDL_VIDEO_DRIVER_ANDROID
#include <android/native_window.h>
+#include "../core/android/SDL_android.h"
#endif
#include "SDL_sysvideo.h"
@@ -81,6 +82,13 @@
#define DEFAULT_OGL_ES "libGLESv1_CM.so.1"
#endif /* SDL_VIDEO_DRIVER_RPI */
+/** 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
+*/
+#ifndef EGL_PLATFORM_DEVICE_EXT
+#define EGL_PLATFORM_DEVICE_EXT 0x0
+#endif
+
#ifdef SDL_VIDEO_STATIC_ANGLE
#define LOAD_FUNC(NAME) \
_this->egl_data->NAME = (void *)NAME;
@@ -92,6 +100,11 @@
return SDL_SetError("Could not retrieve EGL function " #NAME); \
}
#endif
+
+/* it is allowed to not have some of the EGL extensions on start - attempts to use them will fail later. */
+#define LOAD_FUNC_EGLEXT(NAME) \
+ _this->egl_data->NAME = _this->egl_data->eglGetProcAddress(#NAME);
+
static const char * SDL_EGL_GetErrorName(EGLint eglErrorCode)
{
@@ -209,25 +222,35 @@
void *
SDL_EGL_GetProcAddress(_THIS, const char *proc)
{
- static char procname[1024];
- void *retval;
-
- /* eglGetProcAddress is busted on Android http://code.google.com/p/android/issues/detail?id=7681 */
-#if !defined(SDL_VIDEO_DRIVER_ANDROID)
- if (_this->egl_data->eglGetProcAddress) {
+ const Uint32 eglver = (((Uint32) _this->egl_data->egl_version_major) << 16) | ((Uint32) _this->egl_data->egl_version_minor);
+ const SDL_bool is_egl_15_or_later = eglver >= ((((Uint32) 1) << 16) | 5);
+ void *retval = NULL;
+
+ /* EGL 1.5 can use eglGetProcAddress() for any symbol. 1.4 and earlier can't use it for core entry points. */
+ if (!retval && is_egl_15_or_later && _this->egl_data->eglGetProcAddress) {
+ retval = _this->egl_data->eglGetProcAddress(proc);
+ }
+
+ /* 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, proc);
+ /* just in case you need an underscore prepended... */
+ if (!retval && (SDL_strlen(proc) < (sizeof (procname) - 1))) {
+ procname[0] = '_';
+ SDL_strlcpy(procname + 1, proc, sizeof (procname) - 1);
+ retval = SDL_LoadFunction(_this->egl_data->egl_dll_handle, procname);
+ }
+ }
+
+ /* Try eglGetProcAddress if we 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) {
return retval;
}
}
-#endif
-
- retval = SDL_LoadFunction(_this->egl_data->egl_dll_handle, proc);
- if (!retval && SDL_strlen(proc) <= 1022) {
- procname[0] = '_';
- SDL_strlcpy(procname + 1, proc, 1022);
- retval = SDL_LoadFunction(_this->egl_data->egl_dll_handle, procname);
- }
+
return retval;
}
@@ -255,11 +278,10 @@
}
int
-SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_display, EGLenum platform)
+SDL_EGL_LoadLibraryOnly(_THIS, const char *egl_path)
{
void *dll_handle = NULL, *egl_dll_handle = NULL; /* The naming is counter intuitive, but hey, I just work here -- Gabriel */
const char *path = NULL;
- int egl_version_major = 0, egl_version_minor = 0;
#if SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_WINRT
const char *d3dcompiler;
#endif
@@ -278,16 +300,30 @@
#if SDL_VIDEO_DRIVER_WINDOWS || SDL_VIDEO_DRIVER_WINRT
d3dcompiler = SDL_GetHint(SDL_HINT_VIDEO_WIN_D3DCOMPILER);
- if (!d3dcompiler) {
- if (WIN_IsWindowsVistaOrGreater()) {
- d3dcompiler = "d3dcompiler_46.dll";
- } else {
- d3dcompiler = "d3dcompiler_43.dll";
+ if (d3dcompiler) {
+ if (SDL_strcasecmp(d3dcompiler, "none") != 0) {
+ if (SDL_LoadObject(d3dcompiler) == NULL) {
+ SDL_ClearError();
+ }
}
- }
- if (SDL_strcasecmp(d3dcompiler, "none") != 0) {
- if (SDL_LoadObject(d3dcompiler) == NULL) {
- SDL_ClearError();
+ } else {
+ if (WIN_IsWindowsVistaOrGreater()) {
+ /* Try the newer d3d compilers first */
+ const char *d3dcompiler_list[] = {
+ "d3dcompiler_47.dll", "d3dcompiler_46.dll",
+ };
+ int i;
+
+ for (i = 0; i < SDL_arraysize(d3dcompiler_list); ++i) {
+ if (SDL_LoadObject(d3dcompiler_list[i]) != NULL) {
+ break;
+ }
+ SDL_ClearError();
+ }
+ } else {
+ if (SDL_LoadObject("d3dcompiler_43.dll") == NULL) {
+ SDL_ClearError();
+ }
}
}
#endif
@@ -391,23 +427,53 @@
LOAD_FUNC(eglWaitNative);
LOAD_FUNC(eglWaitGL);
LOAD_FUNC(eglBindAPI);
+ LOAD_FUNC(eglQueryAPI);
LOAD_FUNC(eglQueryString);
LOAD_FUNC(eglGetError);
+ LOAD_FUNC_EGLEXT(eglQueryDevicesEXT);
+ LOAD_FUNC_EGLEXT(eglGetPlatformDisplayEXT);
+ _this->gl_config.driver_loaded = 1;
+
+ if (path) {
+ SDL_strlcpy(_this->gl_config.driver_path, path, sizeof(_this->gl_config.driver_path) - 1);
+ } else {
+ *_this->gl_config.driver_path = '\0';
+ }
+
+ return 0;
+}
+
+static void
+SDL_EGL_GetVersion(_THIS) {
if (_this->egl_data->eglQueryString) {
- /* EGL 1.5 allows querying for client version */
- const char *egl_version = _this->egl_data->eglQueryString(EGL_NO_DISPLAY, EGL_VERSION);
- if (egl_version != NULL) {
- if (SDL_sscanf(egl_version, "%d.%d", &egl_version_major, &egl_version_minor) != 2) {
- egl_version_major = 0;
- egl_version_minor = 0;
+ const char *egl_version = _this->egl_data->eglQueryString(_this->egl_data->egl_display, EGL_VERSION);
+ if (egl_version) {
+ int major = 0, minor = 0;
+ if (SDL_sscanf(egl_version, "%d.%d", &major, &minor) == 2) {
+ _this->egl_data->egl_version_major = major;
+ _this->egl_data->egl_version_minor = minor;
+ } else {
SDL_LogWarn(SDL_LOG_CATEGORY_VIDEO, "Could not parse EGL version string: %s", egl_version);
}
}
}
+}
- _this->egl_data->egl_version_major = egl_version_major;
- _this->egl_data->egl_version_minor = egl_version_minor;
+int
+SDL_EGL_LoadLibrary(_THIS, const char *egl_path, NativeDisplayType native_display, EGLenum platform)
+{
+ int egl_version_major, egl_version_minor;
+ int library_load_retcode = SDL_EGL_LoadLibraryOnly(_this, egl_path);
+ if (library_load_retcode != 0) {
+ return library_load_retcode;
+ }
+
+ /* EGL 1.5 allows querying for client version with EGL_NO_DISPLAY */
+ SDL_EGL_GetVersion(_this);
+
+ egl_version_major = _this->egl_data->egl_version_major;
+ egl_version_minor = _this->egl_data->egl_version_minor;
if (egl_version_major == 1 && egl_version_minor == 5) {
LOAD_FUNC(eglGetPlatformDisplay);
@@ -432,21 +498,118 @@
_this->egl_data->egl_display = _this->egl_data->eglGetDisplay(native_display);
}
if (_this->egl_data->egl_display == EGL_NO_DISPLAY) {
+ _this->gl_config.driver_loaded = 0;
+ *_this->gl_config.driver_path = '\0';
return SDL_SetError("Could not get EGL display");
}
if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
+ _this->gl_config.driver_loaded = 0;
+ *_this->gl_config.driver_path = '\0';
return SDL_SetError("Could not initialize EGL");
}
#endif
- if (path) {
- SDL_strlcpy(_this->gl_config.driver_path, path, sizeof(_this->gl_config.driver_path) - 1);
- } else {
- *_this->gl_config.driver_path = '\0';
- }
-
+ /* Get the EGL version with a valid egl_display, for EGL <= 1.4 */
+ SDL_EGL_GetVersion(_this);
+
+ _this->egl_data->is_offscreen = 0;
+
return 0;
+}
+
+/**
+ On multi GPU machines EGL device 0 is not always the first valid GPU.
+ Container environments can restrict access to some GPUs that are still listed in the EGL
+ device list. If the requested device is a restricted GPU and cannot be used
+ (eglInitialize() will fail) then attempt to automatically and silently select the next
+ valid available GPU for EGL to use.
+*/
+
+int
+SDL_EGL_InitializeOffscreen(_THIS, int device)
+{
+ void *egl_devices[SDL_EGL_MAX_DEVICES];
+ EGLint num_egl_devices = 0;
+ const char *egl_device_hint;
+
+ if (_this->gl_config.driver_loaded != 1) {
+ return SDL_SetError("SDL_EGL_LoadLibraryOnly() has not been called or has failed.");
+ }
+
+ /* Check for all extensions that are optional until used and fail if any is missing */
+ if (_this->egl_data->eglQueryDevicesEXT == NULL) {
+ return SDL_SetError("eglQueryDevicesEXT is missing (EXT_device_enumeration not supported by the drivers?)");
+ }
+
+ if (_this->egl_data->eglGetPlatformDisplayEXT == NULL) {
+ return SDL_SetError("eglGetPlatformDisplayEXT is missing (EXT_platform_base not supported by the drivers?)");
+ }
+
+ if (_this->egl_data->eglQueryDevicesEXT(SDL_EGL_MAX_DEVICES, egl_devices, &num_egl_devices) != EGL_TRUE) {
+ return SDL_SetError("eglQueryDevicesEXT() failed");
+ }
+
+ egl_device_hint = SDL_GetHint("SDL_HINT_EGL_DEVICE");
+ if (egl_device_hint) {
+ device = SDL_atoi(egl_device_hint);
+
+ if (device >= num_egl_devices) {
+ return SDL_SetError("Invalid EGL device is requested.");
+ }
+
+ _this->egl_data->egl_display = _this->egl_data->eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT, egl_devices[device], NULL);
+
+ if (_this->egl_data->egl_display == EGL_NO_DISPLAY) {
+ return SDL_SetError("eglGetPlatformDisplayEXT() failed.");
+ }
+
+ if (_this->egl_data->eglInitialize(_this->egl_data->egl_display, NULL, NULL) != EGL_TRUE) {
+ return SDL_SetError("Could not initialize EGL");
+ }
+ }
+ else {
+ int i;
+ SDL_bool found = SDL_FALSE;
+ EGLDisplay attempted_egl_display;
+
+ /* If no hint is provided lets look for the first device/display that will allow us to eglInit */
+ for (i = 0; i < num_egl_devices; i++) {
+ attempted_egl_display = _this->egl_data->eglGetPlatformDisplayEXT(EGL_PLATFORM_DEVICE_EXT, egl_devices[i], NULL);
+
+ if (attempted_egl_display == EGL_NO_DISPLAY) {
+ continue;
+ }
+
+ if (_this->egl_data->eglInitialize(attempted_egl_display, NULL, NULL) != EGL_TRUE) {
+ _this->egl_data->eglTerminate(attempted_egl_display);
+ continue;
+ }
+
+ /* We did not fail, we'll pick this one! */
+ _this->egl_data->egl_display = attempted_egl_display;
+ found = SDL_TRUE;
+
+ break;
+ }
+
+ if (!found) {
+ return SDL_SetError("Could not find a valid EGL device to initialize");
+ }
+ }
+
+ /* Get the EGL version with a valid egl_display, for EGL <= 1.4 */
+ SDL_EGL_GetVersion(_this);
+
+ _this->egl_data->is_offscreen = 1;
+
+ return 0;
+}
+
+void
+SDL_EGL_SetRequiredVisualId(_THIS, int visual_id)
+{
+ _this->egl_data->egl_required_visual_id=visual_id;
}
#ifdef DUMP_EGL_CONFIG
@@ -513,14 +676,8 @@
/* 64 seems nice. */
EGLint attribs[64];
EGLint found_configs = 0, value;
-#ifdef SDL_VIDEO_DRIVER_KMSDRM
- /* Intel EGL on KMS/DRM (al least) returns invalid configs that confuse the bitdiff search used */
- /* later in this function, so we simply use the first one when using the KMSDRM driver for now. */
- EGLConfig configs[1];
-#else
/* 128 seems even nicer here */
EGLConfig configs[128];
-#endif
int i, j, best_bitdiff = -1, bitdiff;
if (!_this->egl_data) {
@@ -565,6 +722,11 @@
attribs[i++] = _this->gl_config.multisamplesamples;
}
+ if (_this->egl_data->is_offscreen) {
+ attribs[i++] = EGL_SURFACE_TYPE;
+ attribs[i++] = EGL_PBUFFER_BIT;
+ }
+
attribs[i++] = EGL_RENDERABLE_TYPE;
if (_this->gl_config.profile_mask == SDL_GL_CONTEXT_PROFILE_ES) {
#ifdef EGL_KHR_create_context
@@ -603,6 +765,16 @@
/* 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)
+ {
+ 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)
+ continue;
+ }
+
bitdiff = 0;
for (j = 0; j < SDL_arraysize(attribs) - 1; j += 2) {
if (attribs[j] == EGL_NONE) {
@@ -875,6 +1047,10 @@
EGL_NATIVE_VISUAL_ID, &format);
ANativeWindow_setBuffersGeometry(nw, 0, 0, format);
+
+ /* Update SurfaceView holder format.
+ * May triggers a sequence surfaceDestroyed(), surfaceCreated(), surfaceChanged(). */
+ Android_JNI_SetSurfaceViewFormat(format);
}
#endif
if (_this->gl_config.framebuffer_srgb_capable) {
@@ -902,6 +1078,25 @@
return surface;
}
+EGLSurface
+SDL_EGL_CreateOffscreenSurface(_THIS, int width, int height)
+{
+ EGLint attributes[] = {
+ EGL_WIDTH, width,
+ EGL_HEIGHT, height,
+ EGL_NONE
+ };
+
+ if (SDL_EGL_ChooseConfig(_this) != 0) {
+ return EGL_NO_SURFACE;
+ }
+
+ return _this->egl_data->eglCreatePbufferSurface(
+ _this->egl_data->egl_display,
+ _this->egl_data->egl_config,
+ attributes);
+}
+
void
SDL_EGL_DestroySurface(_THIS, EGLSurface egl_surface)
{
--
Gitblit v1.9.3