From 3b8a8476546f988e87f084448afdaa3b49316a21 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 9 Jun 2018 12:27:00 -0700 Subject: [PATCH 1/3] SDL: Allow more EGL configs. This attempts to choose the "best" config using weights. --- SDL/SDLGLGraphicsContext.cpp | 105 +++++++++++++++++++++++++++-------- 1 file changed, 83 insertions(+), 22 deletions(-) diff --git a/SDL/SDLGLGraphicsContext.cpp b/SDL/SDLGLGraphicsContext.cpp index a225831a60..3466fe1bea 100644 --- a/SDL/SDLGLGraphicsContext.cpp +++ b/SDL/SDLGLGraphicsContext.cpp @@ -1,3 +1,4 @@ +#include #include "SDLGLGraphicsContext.h" #include "Core/Config.h" #include "Core/System.h" @@ -72,34 +73,94 @@ int8_t EGL_Open() { return 0; } -int8_t EGL_Init() { - EGLConfig g_eglConfig; - EGLint g_numConfigs = 0; - EGLint attrib_list[]= { - // TODO: Should cycle through fallbacks, like on Android -#ifdef USING_FBDEV - EGL_RED_SIZE, 5, - EGL_GREEN_SIZE, 6, - EGL_BLUE_SIZE, 5, +#ifndef EGL_OPENGL_ES3_BIT_KHR +#define EGL_OPENGL_ES3_BIT_KHR (1 << 6) #endif - EGL_DEPTH_SIZE, 16, - EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + +EGLConfig EGL_FindConfig(int &contextVersion) { + std::vector configs; + EGLint numConfigs = 0; + + EGLBoolean result = eglGetConfigs(g_eglDisplay, nullptr, 0, &numConfigs); + if (result != EGL_TRUE || numConfigs == 0) { + return nullptr; + } + + configs.resize(numConfigs); + EGLBoolean result = eglGetConfigs(g_eglDisplay, &configs[0], numConfigs, &numConfigs); + if (result != EGL_TRUE || numConfigs == 0) { + return nullptr; + } + + EGLConfig best = nullptr; + int bestScore = 0; + int bestContextVersion = 0; + for (const EGLConfig &config : configs) { + auto readConfig = [&](EGLint attr) -> EGLint { + EGLint val = 0; + eglGetConfigAttrib(g_eglDisplay, config, attr, &val); + return val; + }; + + int colorScore = readConfig(EGL_RED_SIZE) + readConfig(EGL_BLUE_SIZE) + readConfig(EGL_GREEN_SIZE); + int alphaScore = readConfig(EGL_ALPHA_SIZE); + int depthScore = readConfig(EGL_DEPTH_SIZE); + int levelScore = readConfig(EGL_LEVEL) == 0 ? 100 : 0; + int samplesScore = readConfig(EGL_SAMPLES) == 0 ? 100 : 0; + int sampleBufferScore = readConfig(EGL_SAMPLE_BUFFERS) == 0 ? 100 : 0; + int stencilScore = readConfig(EGL_STENCIL_SIZE); + int transparentScore = readConfig(EGL_TRANSPARENT_TYPE) == EGL_NONE ? 50 : 0; + + EGLint caveat = readConfig(EGL_CONFIG_CAVEAT); + int caveatScore = caveat == EGL_NONE ? 100 : (caveat == EGL_NON_CONFORMANT ? 50 : 0); + + EGLint renderable = readConfig(EGL_RENDERABLE_TYPE); + bool renderableGLES3 = (renderable & EGL_OPENGL_ES3_BIT_KHR) != 0; + bool renderableGLES2 = (renderable & EGL_OPENGL_ES2_BIT) != 0; + bool renderableGL = (renderable & EGL_OPENGL_BIT) != 0; #ifdef USING_GLES2 - EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + int renderableScore = renderableGLES3 ? 100 : (renderableGLES2 ? 80 : 0); #else - EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, + int renderableScore = renderableGL ? 100 : (renderableGLES3 ? 80 : 0); #endif - EGL_SAMPLE_BUFFERS, 0, - EGL_SAMPLES, 0, - EGL_NONE}; - const EGLint attributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE }; + int score = 0; + // Here's a good place to play with the weights to pick a better config. + score += (colorScore + alphaScore) * 10; + score += depthScore * 5 + stencilScore; + score += levelScore + samplesScore + sampleBufferScore + transparentScore; + score += caveatScore + renderableScore; - EGLBoolean result = eglChooseConfig(g_eglDisplay, attrib_list, &g_eglConfig, 1, &g_numConfigs); - if (result != EGL_TRUE || g_numConfigs == 0) EGL_ERROR("Unable to query for available configs.", true); + if (score > bestScore) { + bestScore = score; + best = config; + bestContextVersion = renderableGLES3 ? 3 : (renderableGLES2 ? 2 : 0); + } + } - g_eglContext = eglCreateContext(g_eglDisplay, g_eglConfig, NULL, attributes ); - if (g_eglContext == EGL_NO_CONTEXT) EGL_ERROR("Unable to create GLES context!", true); + contextVersion = bestContextVersion; + return best; +} + +int8_t EGL_Init() { + int contextVersion = 0; + EGLConfig eglConfig = EGL_FindConfig(); + if (!eglConfig) { + EGL_ERROR("Unable to find a usable EGL config.", true); + } + + EGLint contextAttributes[] = { + EGL_CONTEXT_CLIENT_VERSION, contextVersion, + EGL_NONE, + }; + if (contextVersion == 0) { + ctx_attributes[0] = EGL_NONE; + } + + g_eglContext = eglCreateContext(g_eglDisplay, eglConfig, nullptr, contextAttributes); + if (g_eglContext == EGL_NO_CONTEXT) { + EGL_ERROR("Unable to create GLES context!", true); + } #if !defined(USING_FBDEV) && !defined(__APPLE__) //Get the SDL window handle @@ -109,7 +170,7 @@ int8_t EGL_Init() { #else g_Window = (NativeWindowType)NULL; #endif - g_eglSurface = eglCreateWindowSurface(g_eglDisplay, g_eglConfig, g_Window, 0); + g_eglSurface = eglCreateWindowSurface(g_eglDisplay, eglConfig, g_Window, nullptr); if (g_eglSurface == EGL_NO_SURFACE) EGL_ERROR("Unable to create EGL surface!", true); From 84273ff5eb717e040f762d69c64a6d2971baedc9 Mon Sep 17 00:00:00 2001 From: hissingshark Date: Sun, 10 Jun 2018 00:32:05 -0700 Subject: [PATCH 2/3] SDL: Buildfixes for EGL lookup. --- SDL/SDLGLGraphicsContext.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/SDL/SDLGLGraphicsContext.cpp b/SDL/SDLGLGraphicsContext.cpp index 3466fe1bea..2884534e61 100644 --- a/SDL/SDLGLGraphicsContext.cpp +++ b/SDL/SDLGLGraphicsContext.cpp @@ -77,7 +77,7 @@ int8_t EGL_Open() { #define EGL_OPENGL_ES3_BIT_KHR (1 << 6) #endif -EGLConfig EGL_FindConfig(int &contextVersion) { +EGLConfig EGL_FindConfig(int *contextVersion) { std::vector configs; EGLint numConfigs = 0; @@ -87,7 +87,7 @@ EGLConfig EGL_FindConfig(int &contextVersion) { } configs.resize(numConfigs); - EGLBoolean result = eglGetConfigs(g_eglDisplay, &configs[0], numConfigs, &numConfigs); + result = eglGetConfigs(g_eglDisplay, &configs[0], numConfigs, &numConfigs); if (result != EGL_TRUE || numConfigs == 0) { return nullptr; } @@ -112,7 +112,7 @@ EGLConfig EGL_FindConfig(int &contextVersion) { int transparentScore = readConfig(EGL_TRANSPARENT_TYPE) == EGL_NONE ? 50 : 0; EGLint caveat = readConfig(EGL_CONFIG_CAVEAT); - int caveatScore = caveat == EGL_NONE ? 100 : (caveat == EGL_NON_CONFORMANT ? 50 : 0); + int caveatScore = caveat == EGL_NONE ? 100 : (caveat == EGL_NON_CONFORMANT_CONFIG ? 50 : 0); EGLint renderable = readConfig(EGL_RENDERABLE_TYPE); bool renderableGLES3 = (renderable & EGL_OPENGL_ES3_BIT_KHR) != 0; @@ -138,13 +138,13 @@ EGLConfig EGL_FindConfig(int &contextVersion) { } } - contextVersion = bestContextVersion; + *contextVersion = bestContextVersion; return best; } int8_t EGL_Init() { int contextVersion = 0; - EGLConfig eglConfig = EGL_FindConfig(); + EGLConfig eglConfig = EGL_FindConfig(&contextVersion); if (!eglConfig) { EGL_ERROR("Unable to find a usable EGL config.", true); } @@ -154,7 +154,7 @@ int8_t EGL_Init() { EGL_NONE, }; if (contextVersion == 0) { - ctx_attributes[0] = EGL_NONE; + contextAttributes[0] = EGL_NONE; } g_eglContext = eglCreateContext(g_eglDisplay, eglConfig, nullptr, contextAttributes); From 1b417590514ac4e45f2ac3333e842f3d1ab20ba8 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sat, 16 Jun 2018 16:19:17 -0700 Subject: [PATCH 3/3] SDL: Avoid alpha on Mali/ARM devices using GLES. See #10534. --- SDL/SDLGLGraphicsContext.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/SDL/SDLGLGraphicsContext.cpp b/SDL/SDLGLGraphicsContext.cpp index 2884534e61..e3dc209e3f 100644 --- a/SDL/SDLGLGraphicsContext.cpp +++ b/SDL/SDLGLGraphicsContext.cpp @@ -92,6 +92,11 @@ EGLConfig EGL_FindConfig(int *contextVersion) { return nullptr; } + // Mali (ARM) seems to have compositing issues with alpha backbuffers. + // EGL_TRANSPARENT_TYPE doesn't help. + const char *vendorName = eglQueryString(g_eglDisplay, EGL_VENDOR); + const bool avoidAlphaGLES = vendorName && !strcmp(vendorName, "ARM"); + EGLConfig best = nullptr; int bestScore = 0; int bestContextVersion = 0; @@ -119,17 +124,23 @@ EGLConfig EGL_FindConfig(int *contextVersion) { bool renderableGLES2 = (renderable & EGL_OPENGL_ES2_BIT) != 0; bool renderableGL = (renderable & EGL_OPENGL_BIT) != 0; #ifdef USING_GLES2 - int renderableScore = renderableGLES3 ? 100 : (renderableGLES2 ? 80 : 0); + int renderableScoreGLES = renderableGLES3 ? 100 : (renderableGLES2 ? 80 : 0); + int renderableScoreGL = 0; #else - int renderableScore = renderableGL ? 100 : (renderableGLES3 ? 80 : 0); + int renderableScoreGLES = 0; + int renderableScoreGL = renderableGL ? 100 : (renderableGLES3 ? 80 : 0); #endif + if (avoidAlphaGLES && renderableScoreGLES > 0) { + alphaScore = 8 - alphaScore; + } + int score = 0; // Here's a good place to play with the weights to pick a better config. score += (colorScore + alphaScore) * 10; score += depthScore * 5 + stencilScore; score += levelScore + samplesScore + sampleBufferScore + transparentScore; - score += caveatScore + renderableScore; + score += caveatScore + renderableScoreGLES + renderableScoreGL; if (score > bestScore) { bestScore = score;