OpenGL: Better handling for activation/desactivation
This commit is contained in:
parent
d62e99091f
commit
f63d045676
|
|
@ -56,17 +56,24 @@ namespace Nz::GL
|
||||||
NAZARA_OPENGLRENDERER_FOREACH_GLES_FUNC(NAZARA_OPENGLRENDERER_FUNC)
|
NAZARA_OPENGLRENDERER_FOREACH_GLES_FUNC(NAZARA_OPENGLRENDERER_FUNC)
|
||||||
#undef NAZARA_OPENGLRENDERER_FUNC
|
#undef NAZARA_OPENGLRENDERER_FUNC
|
||||||
|
|
||||||
|
static const Context* GetCurrentContext();
|
||||||
|
static bool SetCurrentContext(const Context* context);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
virtual bool Activate() const = 0;
|
||||||
|
virtual void Desactivate() const = 0;
|
||||||
virtual const Loader& GetLoader() = 0;
|
virtual const Loader& GetLoader() = 0;
|
||||||
|
|
||||||
virtual bool ImplementFallback(const std::string_view& function);
|
virtual bool ImplementFallback(const std::string_view& function);
|
||||||
|
|
||||||
std::unordered_set<std::string> m_supportedExtensions;
|
static void NotifyContextDestruction(Context* context);
|
||||||
|
|
||||||
ContextParams m_params;
|
ContextParams m_params;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void GL_APIENTRY HandleDebugMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message) const;
|
void GL_APIENTRY HandleDebugMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message) const;
|
||||||
|
|
||||||
|
std::unordered_set<std::string> m_supportedExtensions;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,8 +31,6 @@ namespace Nz::GL
|
||||||
WGLContext(WGLContext&&) = delete;
|
WGLContext(WGLContext&&) = delete;
|
||||||
~WGLContext();
|
~WGLContext();
|
||||||
|
|
||||||
bool Activate() override;
|
|
||||||
|
|
||||||
bool Create(const WGLContext* baseContext, const ContextParams& params, const WGLContext* shareContext = nullptr);
|
bool Create(const WGLContext* baseContext, const ContextParams& params, const WGLContext* shareContext = nullptr);
|
||||||
bool Create(const WGLContext* baseContext, const ContextParams& params, WindowHandle window, const WGLContext* shareContext = nullptr);
|
bool Create(const WGLContext* baseContext, const ContextParams& params, WindowHandle window, const WGLContext* shareContext = nullptr);
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
|
@ -50,7 +48,8 @@ namespace Nz::GL
|
||||||
bool CreateInternal(const WGLContext* baseContext, const ContextParams& params, const WGLContext* shareContext = nullptr);
|
bool CreateInternal(const WGLContext* baseContext, const ContextParams& params, const WGLContext* shareContext = nullptr);
|
||||||
bool ImplementFallback(const std::string_view& function) override;
|
bool ImplementFallback(const std::string_view& function) override;
|
||||||
|
|
||||||
void Desactivate();
|
bool Activate() const override;
|
||||||
|
void Desactivate() const override;
|
||||||
const Loader& GetLoader() override;
|
const Loader& GetLoader() override;
|
||||||
bool LoadWGLExt();
|
bool LoadWGLExt();
|
||||||
bool SetPixelFormat();
|
bool SetPixelFormat();
|
||||||
|
|
|
||||||
|
|
@ -23,10 +23,10 @@ namespace Nz::GL
|
||||||
|
|
||||||
const Loader& loader = GetLoader();
|
const Loader& loader = GetLoader();
|
||||||
|
|
||||||
auto LoadSymbol = [&](auto& func, const char* funcName)
|
auto LoadSymbol = [&](auto& func, const char* funcName, bool mandatory)
|
||||||
{
|
{
|
||||||
func = reinterpret_cast<std::decay_t<decltype(func)>>(loader.LoadFunction(funcName));
|
func = reinterpret_cast<std::decay_t<decltype(func)>>(loader.LoadFunction(funcName));
|
||||||
if (!func && !ImplementFallback(funcName) && !func) //< Not a mistake
|
if (!func && !ImplementFallback(funcName) && !func && mandatory) //< Not a mistake
|
||||||
throw std::runtime_error("failed to load core function " + std::string(funcName));
|
throw std::runtime_error("failed to load core function " + std::string(funcName));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -114,6 +114,34 @@ namespace Nz::GL
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Context* Context::GetCurrentContext()
|
||||||
|
{
|
||||||
|
return s_currentContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Context::SetCurrentContext(const Context* context)
|
||||||
|
{
|
||||||
|
const Context*& currentContext = s_currentContext; //< Pay TLS cost only once
|
||||||
|
if (currentContext == context)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (currentContext)
|
||||||
|
{
|
||||||
|
currentContext->Desactivate();
|
||||||
|
currentContext = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context)
|
||||||
|
{
|
||||||
|
if (!context->Activate())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
currentContext = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool Context::ImplementFallback(const std::string_view& function)
|
bool Context::ImplementFallback(const std::string_view& function)
|
||||||
{
|
{
|
||||||
const Loader& loader = GetLoader();
|
const Loader& loader = GetLoader();
|
||||||
|
|
@ -135,6 +163,13 @@ namespace Nz::GL
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Context::NotifyContextDestruction(Context* context)
|
||||||
|
{
|
||||||
|
const Context*& currentContext = s_currentContext; //< Pay TLS cost only once
|
||||||
|
if (currentContext == context)
|
||||||
|
currentContext = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void Context::HandleDebugMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message) const
|
void Context::HandleDebugMessage(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei length, const GLchar* message) const
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,6 @@
|
||||||
|
|
||||||
namespace Nz::GL
|
namespace Nz::GL
|
||||||
{
|
{
|
||||||
thread_local WGLContext* s_currentContext = nullptr;
|
|
||||||
|
|
||||||
GL::WGLContext::WGLContext(const WGLLoader& loader) :
|
GL::WGLContext::WGLContext(const WGLLoader& loader) :
|
||||||
m_loader(loader)
|
m_loader(loader)
|
||||||
{
|
{
|
||||||
|
|
@ -24,30 +22,6 @@ namespace Nz::GL
|
||||||
Destroy();
|
Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WGLContext::Activate()
|
|
||||||
{
|
|
||||||
WGLContext*& currentContext = s_currentContext; //< Pay TLS cost only once
|
|
||||||
if (currentContext)
|
|
||||||
{
|
|
||||||
if (currentContext == this)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// Only one context can be activated per thread
|
|
||||||
currentContext->Desactivate();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool succeeded = m_loader.wglMakeCurrent(m_deviceContext, m_handle);
|
|
||||||
if (!succeeded)
|
|
||||||
{
|
|
||||||
NazaraError("failed to activate context: " + Error::GetLastSystemError());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
currentContext = this;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WGLContext::Create(const WGLContext* baseContext, const ContextParams& params, const WGLContext* shareContext)
|
bool WGLContext::Create(const WGLContext* baseContext, const ContextParams& params, const WGLContext* shareContext)
|
||||||
{
|
{
|
||||||
// Creating a context requires a device context, create window to get one
|
// Creating a context requires a device context, create window to get one
|
||||||
|
|
@ -79,9 +53,7 @@ namespace Nz::GL
|
||||||
{
|
{
|
||||||
if (m_handle)
|
if (m_handle)
|
||||||
{
|
{
|
||||||
WGLContext*& currentContext = s_currentContext; //< Pay TLS cost only once
|
NotifyContextDestruction(this);
|
||||||
if (currentContext == this)
|
|
||||||
currentContext = nullptr;
|
|
||||||
|
|
||||||
m_loader.wglDeleteContext(m_handle);
|
m_loader.wglDeleteContext(m_handle);
|
||||||
m_handle = nullptr;
|
m_handle = nullptr;
|
||||||
|
|
@ -139,8 +111,8 @@ namespace Nz::GL
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<int, 3 * 2 + 1> attributes = {
|
std::array<int, 3 * 2 + 1> attributes = {
|
||||||
WGL_CONTEXT_MAJOR_VERSION_ARB, version.major,
|
WGL_CONTEXT_MAJOR_VERSION_ARB, int(version.major),
|
||||||
WGL_CONTEXT_MINOR_VERSION_ARB, version.minor,
|
WGL_CONTEXT_MINOR_VERSION_ARB, int(version.minor),
|
||||||
|
|
||||||
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB | WGL_CONTEXT_ES_PROFILE_BIT_EXT
|
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB | WGL_CONTEXT_ES_PROFILE_BIT_EXT
|
||||||
};
|
};
|
||||||
|
|
@ -180,8 +152,8 @@ namespace Nz::GL
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<int, 3 * 2 + 1> attributes = {
|
std::array<int, 3 * 2 + 1> attributes = {
|
||||||
WGL_CONTEXT_MAJOR_VERSION_ARB, version.major,
|
WGL_CONTEXT_MAJOR_VERSION_ARB, int(version.major),
|
||||||
WGL_CONTEXT_MINOR_VERSION_ARB, version.minor,
|
WGL_CONTEXT_MINOR_VERSION_ARB, int(version.minor),
|
||||||
|
|
||||||
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB
|
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB
|
||||||
};
|
};
|
||||||
|
|
@ -243,22 +215,31 @@ namespace Nz::GL
|
||||||
|
|
||||||
glClearDepthf = [](GLfloat depth)
|
glClearDepthf = [](GLfloat depth)
|
||||||
{
|
{
|
||||||
assert(s_currentContext);
|
const WGLContext* context = static_cast<const WGLContext*>(GetCurrentContext());
|
||||||
s_currentContext->fallbacks.glClearDepth(depth);
|
assert(context);
|
||||||
|
context->fallbacks.glClearDepth(depth);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WGLContext::Desactivate()
|
bool WGLContext::Activate() const
|
||||||
{
|
{
|
||||||
WGLContext*& currentContext = s_currentContext; //< Pay TLS cost only once
|
bool succeeded = m_loader.wglMakeCurrent(m_deviceContext, m_handle);
|
||||||
if (currentContext == this)
|
if (!succeeded)
|
||||||
{
|
{
|
||||||
m_loader.wglMakeCurrent(nullptr, nullptr);
|
NazaraError("failed to activate context: " + Error::GetLastSystemError());
|
||||||
currentContext = nullptr;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WGLContext::Desactivate() const
|
||||||
|
{
|
||||||
|
assert(GetCurrentContext() == this);
|
||||||
|
m_loader.wglMakeCurrent(nullptr, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Loader& WGLContext::GetLoader()
|
const Loader& WGLContext::GetLoader()
|
||||||
|
|
@ -308,7 +289,7 @@ namespace Nz::GL
|
||||||
int pixelFormat = 0;
|
int pixelFormat = 0;
|
||||||
if (m_params.sampleCount > 1)
|
if (m_params.sampleCount > 1)
|
||||||
{
|
{
|
||||||
WGLContext* currentContext = s_currentContext; //< Pay TLS cost only once
|
const WGLContext* currentContext = static_cast<const WGLContext*>(GetCurrentContext()); //< Pay TLS cost only once
|
||||||
if (currentContext)
|
if (currentContext)
|
||||||
{
|
{
|
||||||
// WGL_ARB_pixel_format and WGL_EXT_pixel_format are the same, except for the symbol
|
// WGL_ARB_pixel_format and WGL_EXT_pixel_format are the same, except for the symbol
|
||||||
|
|
@ -320,13 +301,13 @@ namespace Nz::GL
|
||||||
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
|
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
|
||||||
WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
|
WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
|
||||||
WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
|
WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
|
||||||
WGL_COLOR_BITS_ARB, (m_params.bitsPerPixel == 32) ? 24 : m_params.bitsPerPixel,
|
WGL_COLOR_BITS_ARB, int((m_params.bitsPerPixel == 32) ? 24 : m_params.bitsPerPixel),
|
||||||
WGL_ALPHA_BITS_ARB, (m_params.bitsPerPixel == 32) ? 8 : 0,
|
WGL_ALPHA_BITS_ARB, int((m_params.bitsPerPixel == 32) ? 8 : 0),
|
||||||
WGL_DEPTH_BITS_ARB, m_params.depthBits,
|
WGL_DEPTH_BITS_ARB, int(m_params.depthBits),
|
||||||
WGL_STENCIL_BITS_ARB, m_params.stencilBits,
|
WGL_STENCIL_BITS_ARB, int(m_params.stencilBits),
|
||||||
WGL_DOUBLE_BUFFER_ARB, (m_params.doubleBuffering) ? GL_TRUE : GL_FALSE,
|
WGL_DOUBLE_BUFFER_ARB, int((m_params.doubleBuffering) ? GL_TRUE : GL_FALSE),
|
||||||
WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
|
WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
|
||||||
WGL_SAMPLES_ARB, m_params.sampleCount
|
WGL_SAMPLES_ARB, int(m_params.sampleCount)
|
||||||
};
|
};
|
||||||
|
|
||||||
int& sampleCount = attributes[attributes.size() - 3];
|
int& sampleCount = attributes[attributes.size() - 3];
|
||||||
|
|
@ -344,7 +325,7 @@ namespace Nz::GL
|
||||||
}
|
}
|
||||||
while (sampleCount > 1);
|
while (sampleCount > 1);
|
||||||
|
|
||||||
if (m_params.sampleCount != sampleCount)
|
if (int(m_params.sampleCount) != sampleCount)
|
||||||
NazaraWarning("couldn't find a pixel format matching " + std::to_string(m_params.sampleCount) + " sample count, using " + std::to_string(sampleCount) + " sample(s) instead");
|
NazaraWarning("couldn't find a pixel format matching " + std::to_string(m_params.sampleCount) + " sample count, using " + std::to_string(sampleCount) + " sample(s) instead");
|
||||||
|
|
||||||
m_params.sampleCount = sampleCount;
|
m_params.sampleCount = sampleCount;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue