OpenGLRenderer: Choose between OpenGL/OpenGL ES at loading
This commit is contained in:
parent
d872428658
commit
9946c17a23
|
|
@ -28,6 +28,7 @@ namespace Nz::GL
|
||||||
std::unique_ptr<Context> CreateContext(const OpenGLDevice* device, const ContextParams& params, WindowHandle handle, Context* shareContext) const override;
|
std::unique_ptr<Context> CreateContext(const OpenGLDevice* device, const ContextParams& params, WindowHandle handle, Context* shareContext) const override;
|
||||||
|
|
||||||
inline EGLDisplay GetDefaultDisplay() const;
|
inline EGLDisplay GetDefaultDisplay() const;
|
||||||
|
ContextType GetPreferredContextType() const override;
|
||||||
|
|
||||||
GLFunction LoadFunction(const char* name) const override;
|
GLFunction LoadFunction(const char* name) const override;
|
||||||
|
|
||||||
|
|
@ -41,6 +42,7 @@ namespace Nz::GL
|
||||||
private:
|
private:
|
||||||
bool ImplementFallback(const std::string_view& function);
|
bool ImplementFallback(const std::string_view& function);
|
||||||
|
|
||||||
|
ContextType m_preferredContextType;
|
||||||
EGLDisplay m_defaultDisplay;
|
EGLDisplay m_defaultDisplay;
|
||||||
DynLib m_eglLib;
|
DynLib m_eglLib;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ namespace Nz::GL
|
||||||
using GLFunction = void(*)(void);
|
using GLFunction = void(*)(void);
|
||||||
|
|
||||||
class Context;
|
class Context;
|
||||||
|
enum class ContextType;
|
||||||
struct ContextParams;
|
struct ContextParams;
|
||||||
|
|
||||||
class NAZARA_OPENGLRENDERER_API Loader
|
class NAZARA_OPENGLRENDERER_API Loader
|
||||||
|
|
@ -33,6 +34,8 @@ namespace Nz::GL
|
||||||
virtual std::unique_ptr<Context> CreateContext(const OpenGLDevice* device, const ContextParams& params, Context* shareContext = nullptr) const = 0;
|
virtual std::unique_ptr<Context> CreateContext(const OpenGLDevice* device, const ContextParams& params, Context* shareContext = nullptr) const = 0;
|
||||||
virtual std::unique_ptr<Context> CreateContext(const OpenGLDevice* device, const ContextParams& params, WindowHandle handle, Context* shareContext = nullptr) const = 0;
|
virtual std::unique_ptr<Context> 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;
|
virtual GLFunction LoadFunction(const char* name) const = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,8 @@ namespace Nz::GL
|
||||||
std::unique_ptr<Context> CreateContext(const OpenGLDevice* device, const ContextParams& params, Context* shareContext) const override;
|
std::unique_ptr<Context> CreateContext(const OpenGLDevice* device, const ContextParams& params, Context* shareContext) const override;
|
||||||
std::unique_ptr<Context> CreateContext(const OpenGLDevice* device, const ContextParams& params, WindowHandle handle, Context* shareContext) const override;
|
std::unique_ptr<Context> CreateContext(const OpenGLDevice* device, const ContextParams& params, WindowHandle handle, Context* shareContext) const override;
|
||||||
|
|
||||||
|
ContextType GetPreferredContextType() const override;
|
||||||
|
|
||||||
GLFunction LoadFunction(const char* name) const override;
|
GLFunction LoadFunction(const char* name) const override;
|
||||||
|
|
||||||
#define NAZARA_OPENGLRENDERER_FUNC(name, sig) sig name = nullptr;
|
#define NAZARA_OPENGLRENDERER_FUNC(name, sig) sig name = nullptr;
|
||||||
|
|
|
||||||
|
|
@ -23,25 +23,11 @@ namespace Nz
|
||||||
OpenGLDevice::OpenGLDevice(GL::Loader& loader) :
|
OpenGLDevice::OpenGLDevice(GL::Loader& loader) :
|
||||||
m_loader(loader)
|
m_loader(loader)
|
||||||
{
|
{
|
||||||
// Favor OpenGL on desktop and OpenGL ES on mobile
|
GL::ContextParams params;
|
||||||
std::array<GL::ContextType, 2> contextTypes = {
|
params.type = loader.GetPreferredContextType();
|
||||||
#if defined(NAZARA_PLATFORM_DESKTOP)
|
|
||||||
GL::ContextType::OpenGL, GL::ContextType::OpenGL_ES
|
|
||||||
#else
|
|
||||||
GL::ContextType::OpenGL_ES, GL::ContextType::OpenGL
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
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)
|
if (!m_referenceContext)
|
||||||
throw std::runtime_error("failed to create reference context");
|
throw std::runtime_error("failed to create reference context");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,14 +81,38 @@ namespace Nz::GL
|
||||||
const char* vendor = eglQueryString(m_defaultDisplay, EGL_VENDOR);
|
const char* vendor = eglQueryString(m_defaultDisplay, EGL_VENDOR);
|
||||||
NazaraNotice("Initialized EGL " + std::to_string(major) + "." + std::to_string(minor) + " display (" + 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?)
|
// Try to create a dummy context in order to check OpenGL / OpenGL ES support
|
||||||
/*ContextParams params;
|
|
||||||
EGLContextBase baseContext(nullptr, *this);
|
|
||||||
if (!baseContext.Create(params))
|
|
||||||
throw std::runtime_error("failed to create load context");
|
|
||||||
|
|
||||||
if (!baseContext.Initialize(params))
|
// Favor OpenGL on desktop and OpenGL ES on mobile
|
||||||
throw std::runtime_error("failed to load OpenGL functions");*/
|
std::array<GL::ContextType, 2> 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()
|
EGLLoader::~EGLLoader()
|
||||||
|
|
@ -170,6 +194,11 @@ namespace Nz::GL
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ContextType EGLLoader::GetPreferredContextType() const
|
||||||
|
{
|
||||||
|
return m_preferredContextType;
|
||||||
|
}
|
||||||
|
|
||||||
GLFunction EGLLoader::LoadFunction(const char* name) const
|
GLFunction EGLLoader::LoadFunction(const char* name) const
|
||||||
{
|
{
|
||||||
GLFunction func = reinterpret_cast<GLFunction>(m_eglLib.GetSymbol(name));
|
GLFunction func = reinterpret_cast<GLFunction>(m_eglLib.GetSymbol(name));
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@ namespace Nz::GL
|
||||||
|
|
||||||
bool WGLContext::Create(const WGLContext* baseContext, const ContextParams& params, const WGLContext* shareContext)
|
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
|
// 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));
|
HWNDHandle window(::CreateWindowA("STATIC", nullptr, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, nullptr, nullptr, GetModuleHandle(nullptr), nullptr));
|
||||||
if (!window)
|
if (!window)
|
||||||
|
|
@ -47,6 +49,8 @@ namespace Nz::GL
|
||||||
{
|
{
|
||||||
NazaraAssert(window.type == WindowManager::Windows, "expected Windows window");
|
NazaraAssert(window.type == WindowManager::Windows, "expected Windows window");
|
||||||
|
|
||||||
|
Destroy();
|
||||||
|
|
||||||
m_deviceContext = ::GetDC(static_cast<HWND>(window.windows.window));
|
m_deviceContext = ::GetDC(static_cast<HWND>(window.windows.window));
|
||||||
if (!m_deviceContext)
|
if (!m_deviceContext)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -50,12 +50,32 @@ namespace Nz::GL
|
||||||
throw std::runtime_error("failed to create load context");
|
throw std::runtime_error("failed to create load context");
|
||||||
|
|
||||||
ContextParams params;
|
ContextParams params;
|
||||||
|
// Favor OpenGL on desktop and OpenGL ES on mobile
|
||||||
|
std::array<GL::ContextType, 2> 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))
|
bool created = false;
|
||||||
throw std::runtime_error("failed to create load context");
|
for (GL::ContextType contextType : contextTypes)
|
||||||
|
{
|
||||||
|
params.type = contextType;
|
||||||
|
|
||||||
if (!m_baseContext.Initialize(params))
|
if (!m_baseContext.Create(&loadContext, params) || m_baseContext.GetParams().type != contextType)
|
||||||
throw std::runtime_error("failed to load OpenGL functions");
|
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<Context> WGLLoader::CreateContext(const OpenGLDevice* device, const ContextParams& params, Context* shareContext) const
|
std::unique_ptr<Context> WGLLoader::CreateContext(const OpenGLDevice* device, const ContextParams& params, Context* shareContext) const
|
||||||
|
|
@ -94,6 +114,11 @@ namespace Nz::GL
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ContextType WGLLoader::GetPreferredContextType() const
|
||||||
|
{
|
||||||
|
return m_baseContext.GetParams().type;
|
||||||
|
}
|
||||||
|
|
||||||
GLFunction WGLLoader::LoadFunction(const char* name) const
|
GLFunction WGLLoader::LoadFunction(const char* name) const
|
||||||
{
|
{
|
||||||
GLFunction func = reinterpret_cast<GLFunction>(wglGetProcAddress(name));
|
GLFunction func = reinterpret_cast<GLFunction>(wglGetProcAddress(name));
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue