From 354cabd4a7ae73121a527980d7cef9dae41e9d3a Mon Sep 17 00:00:00 2001 From: "Ryan C. Gordon" Date: Sat, 3 Apr 2021 18:15:50 -0400 Subject: [PATCH] egl: favor truecolor configurations. If app requested <= 16 color depth and there is a 24-bit config available, favor that. This fixes things that quietly expect to get truecolor output but don't request it (...like SDL's render api...) and things that are probably requesting 16-bit color as a fallback but expecting reasonable systems to give them full depth. Specifically, this fixes Life is Strange on Wayland, which uses the latter approach, and anything using SDL_Render on Wayland, which uses the former. Fixes #4056. Fixes #4132. --- src/video/SDL_egl.c | 53 +++++++++++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 9 deletions(-) diff --git a/src/video/SDL_egl.c b/src/video/SDL_egl.c index 3716da750..0eb4c85fc 100644 --- a/src/video/SDL_egl.c +++ b/src/video/SDL_egl.c @@ -700,7 +700,8 @@ SDL_EGL_ChooseConfig(_THIS) /* 128 seems even nicer here */ EGLConfig configs[128]; SDL_bool has_matching_format = SDL_FALSE; - int i, j, best_bitdiff = -1, bitdiff; + int i, j, best_bitdiff = -1, best_truecolor_bitdiff = -1; + int truecolor_config_idx = -1; if (!_this->egl_data) { /* The EGL library wasn't loaded, SDL_GetError() should have info */ @@ -804,17 +805,30 @@ SDL_EGL_ChooseConfig(_THIS) /* From those, we select the one that matches our requirements more closely via a makeshift algorithm */ for (i = 0; i < found_configs; i++ ) { - if (has_matching_format && _this->egl_data->egl_required_visual_id) - { + SDL_bool is_truecolor = SDL_FALSE; + int bitdiff = 0; + + if (has_matching_format && _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) + if (_this->egl_data->egl_required_visual_id != format) { continue; + } + } + + _this->egl_data->eglGetConfigAttrib(_this->egl_data->egl_display, configs[i], EGL_RED_SIZE, &value); + if (value == 8) { + _this->egl_data->eglGetConfigAttrib(_this->egl_data->egl_display, configs[i], EGL_GREEN_SIZE, &value); + if (value == 8) { + _this->egl_data->eglGetConfigAttrib(_this->egl_data->egl_display, configs[i], EGL_BLUE_SIZE, &value); + if (value == 8) { + is_truecolor = SDL_TRUE; + } + } } - bitdiff = 0; for (j = 0; j < SDL_arraysize(attribs) - 1; j += 2) { if (attribs[j] == EGL_NONE) { break; @@ -832,17 +846,38 @@ SDL_EGL_ChooseConfig(_THIS) } } - if (bitdiff < best_bitdiff || best_bitdiff == -1) { + if ((bitdiff < best_bitdiff) || (best_bitdiff == -1)) { _this->egl_data->egl_config = configs[i]; - best_bitdiff = bitdiff; } - if (bitdiff == 0) { - break; /* we found an exact match! */ + if (is_truecolor && ((bitdiff < best_truecolor_bitdiff) || (best_truecolor_bitdiff == -1))) { + truecolor_config_idx = i; + best_truecolor_bitdiff = bitdiff; } } + #define FAVOR_TRUECOLOR 1 + #if FAVOR_TRUECOLOR + /* Some apps request a low color depth, either because they _assume_ + they'll get a larger one but don't want to fail if only smaller ones + are available, or they just never called SDL_GL_SetAttribute at all and + got a tiny default. For these cases, a game that would otherwise run + at 24-bit color might get dithered down to something smaller, which is + worth avoiding. If the app requested <= 16 bit color and an exact 24-bit + match is available, favor that. Otherwise, we look for the closest + match. Note that while the API promises what you request _or better_, + it's feasible this can be disastrous for performance for custom software + on small hardware that all expected to actually get 16-bit color. In this + case, turn off FAVOR_TRUECOLOR (and maybe send a patch to make this more + flexible). */ + if ( ((_this->gl_config.red_size + _this->gl_config.blue_size + _this->gl_config.green_size) <= 16) ) { + if (truecolor_config_idx != -1) { + _this->egl_data->egl_config = configs[truecolor_config_idx]; + } + } + #endif + #ifdef DUMP_EGL_CONFIG dumpconfig(_this, _this->egl_data->egl_config); #endif