From 9946c17a23fcd4e9245dc00ad2d2c20c608435bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Leclercq?= Date: Tue, 2 Nov 2021 09:13:12 +0100 Subject: [PATCH] OpenGLRenderer: Choose between OpenGL/OpenGL ES at loading --- .../OpenGLRenderer/Wrapper/EGL/EGLLoader.hpp | 2 + .../Nazara/OpenGLRenderer/Wrapper/Loader.hpp | 3 ++ .../OpenGLRenderer/Wrapper/WGL/WGLLoader.hpp | 2 + src/Nazara/OpenGLRenderer/OpenGLDevice.cpp | 20 ++------- .../OpenGLRenderer/Wrapper/EGL/EGLLoader.cpp | 43 ++++++++++++++++--- .../OpenGLRenderer/Wrapper/WGL/WGLContext.cpp | 4 ++ .../OpenGLRenderer/Wrapper/WGL/WGLLoader.cpp | 33 ++++++++++++-- 7 files changed, 79 insertions(+), 28 deletions(-) diff --git a/include/Nazara/OpenGLRenderer/Wrapper/EGL/EGLLoader.hpp b/include/Nazara/OpenGLRenderer/Wrapper/EGL/EGLLoader.hpp index d815008d6..fa3edee35 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/EGL/EGLLoader.hpp +++ b/include/Nazara/OpenGLRenderer/Wrapper/EGL/EGLLoader.hpp @@ -28,6 +28,7 @@ namespace Nz::GL std::unique_ptr CreateContext(const OpenGLDevice* device, const ContextParams& params, WindowHandle handle, Context* shareContext) const override; inline EGLDisplay GetDefaultDisplay() const; + ContextType GetPreferredContextType() const override; GLFunction LoadFunction(const char* name) const override; @@ -41,6 +42,7 @@ namespace Nz::GL private: bool ImplementFallback(const std::string_view& function); + ContextType m_preferredContextType; EGLDisplay m_defaultDisplay; DynLib m_eglLib; }; diff --git a/include/Nazara/OpenGLRenderer/Wrapper/Loader.hpp b/include/Nazara/OpenGLRenderer/Wrapper/Loader.hpp index 024e4f2d6..ee4a6766e 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/Loader.hpp +++ b/include/Nazara/OpenGLRenderer/Wrapper/Loader.hpp @@ -22,6 +22,7 @@ namespace Nz::GL using GLFunction = void(*)(void); class Context; + enum class ContextType; struct ContextParams; class NAZARA_OPENGLRENDERER_API Loader @@ -33,6 +34,8 @@ namespace Nz::GL virtual std::unique_ptr CreateContext(const OpenGLDevice* device, const ContextParams& params, Context* shareContext = nullptr) const = 0; virtual std::unique_ptr CreateContext(const OpenGLDevice* device, const ContextParams& params, WindowHandle handle, Context* shareContext = nullptr) const = 0; + virtual ContextType GetPreferredContextType() const = 0; + virtual GLFunction LoadFunction(const char* name) const = 0; }; } diff --git a/include/Nazara/OpenGLRenderer/Wrapper/WGL/WGLLoader.hpp b/include/Nazara/OpenGLRenderer/Wrapper/WGL/WGLLoader.hpp index fc614110c..9426491a4 100644 --- a/include/Nazara/OpenGLRenderer/Wrapper/WGL/WGLLoader.hpp +++ b/include/Nazara/OpenGLRenderer/Wrapper/WGL/WGLLoader.hpp @@ -26,6 +26,8 @@ namespace Nz::GL std::unique_ptr CreateContext(const OpenGLDevice* device, const ContextParams& params, Context* shareContext) const override; std::unique_ptr CreateContext(const OpenGLDevice* device, const ContextParams& params, WindowHandle handle, Context* shareContext) const override; + ContextType GetPreferredContextType() const override; + GLFunction LoadFunction(const char* name) const override; #define NAZARA_OPENGLRENDERER_FUNC(name, sig) sig name = nullptr; diff --git a/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp b/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp index 921cb2ebf..2a43943ac 100644 --- a/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp +++ b/src/Nazara/OpenGLRenderer/OpenGLDevice.cpp @@ -23,25 +23,11 @@ namespace Nz OpenGLDevice::OpenGLDevice(GL::Loader& loader) : m_loader(loader) { - // Favor OpenGL on desktop and OpenGL ES on mobile - std::array contextTypes = { -#if defined(NAZARA_PLATFORM_DESKTOP) - GL::ContextType::OpenGL, GL::ContextType::OpenGL_ES -#else - GL::ContextType::OpenGL_ES, GL::ContextType::OpenGL -#endif - }; + GL::ContextParams params; + params.type = loader.GetPreferredContextType(); - for (GL::ContextType contextType : contextTypes) - { - GL::ContextParams params; - params.type = contextType; - - m_referenceContext = loader.CreateContext(this, params); - if (m_referenceContext) - break; - } + m_referenceContext = loader.CreateContext(this, params); if (!m_referenceContext) throw std::runtime_error("failed to create reference context"); diff --git a/src/Nazara/OpenGLRenderer/Wrapper/EGL/EGLLoader.cpp b/src/Nazara/OpenGLRenderer/Wrapper/EGL/EGLLoader.cpp index 86ad6fd3d..a4b1a0f79 100644 --- a/src/Nazara/OpenGLRenderer/Wrapper/EGL/EGLLoader.cpp +++ b/src/Nazara/OpenGLRenderer/Wrapper/EGL/EGLLoader.cpp @@ -81,14 +81,38 @@ namespace Nz::GL const char* vendor = eglQueryString(m_defaultDisplay, EGL_VENDOR); NazaraNotice("Initialized EGL " + std::to_string(major) + "." + std::to_string(minor) + " display (" + vendor + ")"); - // Try to create a dummy context in order to check EGL support (FIXME: is this really necessary?) - /*ContextParams params; - EGLContextBase baseContext(nullptr, *this); - if (!baseContext.Create(params)) - throw std::runtime_error("failed to create load context"); + // Try to create a dummy context in order to check OpenGL / OpenGL ES support - if (!baseContext.Initialize(params)) - throw std::runtime_error("failed to load OpenGL functions");*/ + // Favor OpenGL on desktop and OpenGL ES on mobile + std::array contextTypes = { +#if defined(NAZARA_PLATFORM_DESKTOP) + GL::ContextType::OpenGL, GL::ContextType::OpenGL_ES +#else + GL::ContextType::OpenGL_ES, GL::ContextType::OpenGL +#endif + }; + + ContextParams params; + + bool created = false; + for (GL::ContextType contextType : contextTypes) + { + params.type = contextType; + + EGLContextBase baseContext(nullptr, *this); + if (!baseContext.Create(params) || baseContext.GetParams().type != contextType) + continue; + + if (!baseContext.Initialize(params)) //< Is this really necessary? + continue; + + created = true; + m_preferredContextType = contextType; + break; + } + + if (!created) + throw std::runtime_error("failed to create or initialize base context"); } EGLLoader::~EGLLoader() @@ -170,6 +194,11 @@ namespace Nz::GL return context; } + ContextType EGLLoader::GetPreferredContextType() const + { + return m_preferredContextType; + } + GLFunction EGLLoader::LoadFunction(const char* name) const { GLFunction func = reinterpret_cast(m_eglLib.GetSymbol(name)); diff --git a/src/Nazara/OpenGLRenderer/Wrapper/WGL/WGLContext.cpp b/src/Nazara/OpenGLRenderer/Wrapper/WGL/WGLContext.cpp index 8e0c28e23..70ecd01df 100644 --- a/src/Nazara/OpenGLRenderer/Wrapper/WGL/WGLContext.cpp +++ b/src/Nazara/OpenGLRenderer/Wrapper/WGL/WGLContext.cpp @@ -19,6 +19,8 @@ namespace Nz::GL bool WGLContext::Create(const WGLContext* baseContext, const ContextParams& params, const WGLContext* shareContext) { + Destroy(); + // Creating a context requires a device context, create window to get one HWNDHandle window(::CreateWindowA("STATIC", nullptr, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, nullptr, nullptr, GetModuleHandle(nullptr), nullptr)); if (!window) @@ -47,6 +49,8 @@ namespace Nz::GL { NazaraAssert(window.type == WindowManager::Windows, "expected Windows window"); + Destroy(); + m_deviceContext = ::GetDC(static_cast(window.windows.window)); if (!m_deviceContext) { diff --git a/src/Nazara/OpenGLRenderer/Wrapper/WGL/WGLLoader.cpp b/src/Nazara/OpenGLRenderer/Wrapper/WGL/WGLLoader.cpp index f172d81cb..48a20fe7a 100644 --- a/src/Nazara/OpenGLRenderer/Wrapper/WGL/WGLLoader.cpp +++ b/src/Nazara/OpenGLRenderer/Wrapper/WGL/WGLLoader.cpp @@ -50,12 +50,32 @@ namespace Nz::GL throw std::runtime_error("failed to create load context"); ContextParams params; + // Favor OpenGL on desktop and OpenGL ES on mobile + std::array contextTypes = { +#if defined(NAZARA_PLATFORM_DESKTOP) + GL::ContextType::OpenGL, GL::ContextType::OpenGL_ES +#else + GL::ContextType::OpenGL_ES, GL::ContextType::OpenGL +#endif + }; - if (!m_baseContext.Create(&loadContext, params)) - throw std::runtime_error("failed to create load context"); + bool created = false; + for (GL::ContextType contextType : contextTypes) + { + params.type = contextType; - if (!m_baseContext.Initialize(params)) - throw std::runtime_error("failed to load OpenGL functions"); + if (!m_baseContext.Create(&loadContext, params) || m_baseContext.GetParams().type != contextType) + continue; + + if (!m_baseContext.Initialize(params)) + continue; + + created = true; + break; + } + + if (!created) + throw std::runtime_error("failed to create or initialize base context"); } std::unique_ptr WGLLoader::CreateContext(const OpenGLDevice* device, const ContextParams& params, Context* shareContext) const @@ -94,6 +114,11 @@ namespace Nz::GL return context; } + ContextType WGLLoader::GetPreferredContextType() const + { + return m_baseContext.GetParams().type; + } + GLFunction WGLLoader::LoadFunction(const char* name) const { GLFunction func = reinterpret_cast(wglGetProcAddress(name));