OPENGL: Rework renderer selection code

Add a class to group all renderer related (static) functions.
This allows to have getBestMatchingAvailableType inline in all engines.

The matching code is now shared between all engines but allows
customization for engines needing it (Grim, WME3D).

The new code takes runtime availability of features to select the
best renderer.
It avoid crashes when user choosed OpenGL but GLES2 is used.
This commit is contained in:
Le Philousophe 2022-04-02 18:15:25 +02:00
parent b978cd1caa
commit 1e4696f6d0
14 changed files with 246 additions and 179 deletions

View file

@ -22,6 +22,9 @@
#include "graphics/renderer.h"
#include "common/translation.h"
#include "common/system.h"
#include "graphics/opengl/context.h"
namespace Graphics {
@ -40,12 +43,12 @@ static const RendererTypeDescription rendererTypes[] = {
DECLARE_TRANSLATION_ADDITIONAL_CONTEXT("OpenGL with shaders", "lowres")
const RendererTypeDescription *listRendererTypes() {
const RendererTypeDescription *Renderer::listTypes() {
return rendererTypes;
}
RendererType parseRendererTypeCode(const Common::String &code) {
const RendererTypeDescription *rt = listRendererTypes();
RendererType Renderer::parseTypeCode(const Common::String &code) {
const RendererTypeDescription *rt = listTypes();
while (rt->code) {
if (rt->code == code) {
return rt->id;
@ -56,8 +59,8 @@ RendererType parseRendererTypeCode(const Common::String &code) {
return kRendererTypeDefault;
}
Common::String getRendererTypeCode(RendererType type) {
const RendererTypeDescription *rt = listRendererTypes();
Common::String Renderer::getTypeCode(RendererType type) {
const RendererTypeDescription *rt = listTypes();
while (rt->code) {
if (rt->id == type) {
return rt->code;
@ -68,30 +71,62 @@ Common::String getRendererTypeCode(RendererType type) {
return "";
}
RendererType getBestMatchingAvailableRendererType(RendererType desired) {
if (desired == kRendererTypeDefault) {
desired = kRendererTypeOpenGLShaders;
}
uint32 Renderer::getAvailableTypes() {
uint32 available = 0;
#if !defined(USE_OPENGL_SHADERS)
if (desired == kRendererTypeOpenGLShaders) {
desired = kRendererTypeOpenGL;
}
#if defined(USE_TINYGL)
/* TinyGL doesn't depend on hardware support */
available |= kRendererTypeTinyGL;
#endif
#if (!defined(USE_OPENGL_GAME) && defined(USE_OPENGL_SHADERS))
if (desired == kRendererTypeOpenGL) {
desired = kRendererTypeOpenGLShaders;
}
#endif
#if defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS)
bool backendCapableOpenGL = g_system->hasFeature(OSystem::kFeatureOpenGLForGame);
#if !defined(USE_OPENGL_GAME) && !defined(USE_OPENGL_SHADERS)
if (desired == kRendererTypeOpenGL || desired == kRendererTypeOpenGLShaders) {
desired = kRendererTypeTinyGL;
}
if (backendCapableOpenGL) {
/* Backend either support OpenGL or OpenGL ES(2) */
#if defined(USE_OPENGL_GAME)
/* OpenGL classic is compiled in, check if hardware supports it */
if (g_system->getOpenGLType() == OpenGL::kOGLContextGL) {
available |= kRendererTypeOpenGL;
}
#endif
#if defined(USE_OPENGL_SHADERS)
/* OpenGL with shaders is compiled in, check if hardware supports it */
if (g_system->hasFeature(OSystem::kFeatureShadersForGame)) {
available |= kRendererTypeOpenGLShaders;
}
#endif
}
#endif // defined(USE_OPENGL_GAME) || defined(USE_OPENGL_SHADERS
return available;
}
return desired;
RendererType Renderer::getBestMatchingType(RendererType desired, uint32 available) {
/* What we want is possible */
if (available & desired) {
return desired;
}
/* We apply the same logic when nothing is desired and when what we want is not possible */
if (desired != kRendererTypeDefault) {
warning("Unable to create a '%s' renderer", getTypeCode(desired).c_str());
}
/* Shaders are the best experience */
if (available & kRendererTypeOpenGLShaders) {
return kRendererTypeOpenGLShaders;
}
/* then OpenGL */
if (available & kRendererTypeOpenGL) {
return kRendererTypeOpenGL;
}
/* then TinyGL */
if (available & kRendererTypeTinyGL) {
return kRendererTypeTinyGL;
}
/* Failure is not an option */
error("Unable to create a renderer");
}
} // End of namespace Graphics