OpenGL: Link contexts to device

This commit is contained in:
Lynix 2020-04-19 15:33:36 +02:00
parent bd6924d66d
commit 349e915e10
12 changed files with 78 additions and 21 deletions

View File

@ -12,12 +12,15 @@
#include <Nazara/OpenGLRenderer/Config.hpp> #include <Nazara/OpenGLRenderer/Config.hpp>
#include <Nazara/OpenGLRenderer/Wrapper/Context.hpp> #include <Nazara/OpenGLRenderer/Wrapper/Context.hpp>
#include <Nazara/Renderer/RenderDevice.hpp> #include <Nazara/Renderer/RenderDevice.hpp>
#include <unordered_set>
#include <vector> #include <vector>
namespace Nz namespace Nz
{ {
class NAZARA_OPENGLRENDERER_API OpenGLDevice : public RenderDevice class NAZARA_OPENGLRENDERER_API OpenGLDevice : public RenderDevice
{ {
friend GL::Context;
public: public:
OpenGLDevice(GL::Loader& loader); OpenGLDevice(GL::Loader& loader);
OpenGLDevice(const OpenGLDevice&) = delete; OpenGLDevice(const OpenGLDevice&) = delete;
@ -37,11 +40,16 @@ namespace Nz
std::unique_ptr<Texture> InstantiateTexture(const TextureInfo& params) override; std::unique_ptr<Texture> InstantiateTexture(const TextureInfo& params) override;
std::unique_ptr<TextureSampler> InstantiateTextureSampler(const TextureSamplerInfo& params) override; std::unique_ptr<TextureSampler> InstantiateTextureSampler(const TextureSamplerInfo& params) override;
inline void NotifyTextureDestruction(GLuint texture) const;
OpenGLDevice& operator=(const OpenGLDevice&) = delete; OpenGLDevice& operator=(const OpenGLDevice&) = delete;
OpenGLDevice& operator=(OpenGLDevice&&) = delete; ///TODO? OpenGLDevice& operator=(OpenGLDevice&&) = delete; ///TODO?
private: private:
inline void NotifyContextDestruction(const GL::Context& context) const;
std::unique_ptr<GL::Context> m_referenceContext; std::unique_ptr<GL::Context> m_referenceContext;
mutable std::unordered_set<const GL::Context*> m_contexts;
GL::Loader& m_loader; GL::Loader& m_loader;
}; };
} }

View File

@ -11,6 +11,17 @@ namespace Nz
{ {
return *m_referenceContext; return *m_referenceContext;
} }
inline void OpenGLDevice::NotifyTextureDestruction(GLuint texture) const
{
for (const GL::Context* context : m_contexts)
context->NotifyTextureDestruction(texture);
}
inline void OpenGLDevice::NotifyContextDestruction(const GL::Context& context) const
{
m_contexts.erase(&context);
}
} }
#include <Nazara/OpenGLRenderer/DebugOff.hpp> #include <Nazara/OpenGLRenderer/DebugOff.hpp>

View File

@ -14,6 +14,11 @@
#include <string> #include <string>
#include <unordered_set> #include <unordered_set>
namespace Nz
{
class OpenGLDevice;
}
namespace Nz::GL namespace Nz::GL
{ {
enum class ContextType enum class ContextType
@ -55,13 +60,13 @@ namespace Nz::GL
class Context class Context
{ {
public: public:
Context() = default; inline Context(const OpenGLDevice* device);
virtual ~Context(); virtual ~Context();
virtual bool Activate() = 0;
virtual void EnableVerticalSync(bool enabled) = 0; virtual void EnableVerticalSync(bool enabled) = 0;
inline const OpenGLDevice* GetDevice() const;
inline ExtensionStatus GetExtensionStatus(Extension extension) const; inline ExtensionStatus GetExtensionStatus(Extension extension) const;
inline const ContextParams& GetParams() const; inline const ContextParams& GetParams() const;
@ -95,6 +100,7 @@ namespace Nz::GL
std::array<ExtensionStatus, UnderlyingCast(Extension::Max) + 1> m_extensionStatus; std::array<ExtensionStatus, UnderlyingCast(Extension::Max) + 1> m_extensionStatus;
std::unordered_set<std::string> m_supportedExtensions; std::unordered_set<std::string> m_supportedExtensions;
const OpenGLDevice* m_device;
}; };
} }

View File

@ -7,6 +7,15 @@
namespace Nz::GL namespace Nz::GL
{ {
inline Context::Context(const OpenGLDevice* device) :
m_device(device)
{
}
inline const OpenGLDevice* Context::GetDevice() const
{
return m_device;
}
inline ExtensionStatus Context::GetExtensionStatus(Extension extension) const inline ExtensionStatus Context::GetExtensionStatus(Extension extension) const
{ {

View File

@ -13,6 +13,11 @@
#include <Nazara/OpenGLRenderer/Wrapper/Context.hpp> #include <Nazara/OpenGLRenderer/Wrapper/Context.hpp>
#include <memory> #include <memory>
namespace Nz
{
class OpenGLDevice;
}
namespace Nz::GL namespace Nz::GL
{ {
class Context; class Context;
@ -25,8 +30,8 @@ namespace Nz::GL
Loader() = default; Loader() = default;
virtual ~Loader(); virtual ~Loader();
virtual std::unique_ptr<Context> CreateContext(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 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 GLFunction LoadFunction(const char* name) const = 0; virtual GLFunction LoadFunction(const char* name) const = 0;
}; };

View File

@ -26,7 +26,7 @@ namespace Nz::GL
class WGLContext : public Context class WGLContext : public Context
{ {
public: public:
WGLContext(const WGLLoader& loader); inline WGLContext(const OpenGLDevice* device, const WGLLoader& loader);
WGLContext(const WGLContext&) = delete; WGLContext(const WGLContext&) = delete;
WGLContext(WGLContext&&) = delete; WGLContext(WGLContext&&) = delete;
~WGLContext(); ~WGLContext();

View File

@ -7,6 +7,12 @@
namespace Nz::GL namespace Nz::GL
{ {
inline GL::WGLContext::WGLContext(const OpenGLDevice* device, const WGLLoader& loader) :
Context(device),
m_loader(loader)
{
}
inline bool WGLContext::HasPlatformExtension(const std::string& str) const inline bool WGLContext::HasPlatformExtension(const std::string& str) const
{ {
return m_supportedPlatformExtensions.find(str) != m_supportedPlatformExtensions.end(); return m_supportedPlatformExtensions.find(str) != m_supportedPlatformExtensions.end();

View File

@ -24,8 +24,8 @@ namespace Nz::GL
WGLLoader(DynLib& openglLib); WGLLoader(DynLib& openglLib);
~WGLLoader() = default; ~WGLLoader() = default;
std::unique_ptr<Context> CreateContext(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 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;
GLFunction LoadFunction(const char* name) const override; GLFunction LoadFunction(const char* name) const override;

View File

@ -14,21 +14,29 @@ namespace Nz
OpenGLDevice::OpenGLDevice(GL::Loader& loader) : OpenGLDevice::OpenGLDevice(GL::Loader& loader) :
m_loader(loader) m_loader(loader)
{ {
m_referenceContext = loader.CreateContext({}); m_referenceContext = loader.CreateContext(this, {});
if (!m_referenceContext) if (!m_referenceContext)
throw std::runtime_error("failed to create reference context"); throw std::runtime_error("failed to create reference context");
m_contexts.insert(m_referenceContext.get());
} }
OpenGLDevice::~OpenGLDevice() = default; OpenGLDevice::~OpenGLDevice() = default;
std::unique_ptr<GL::Context> OpenGLDevice::CreateContext(const GL::ContextParams& params) const std::unique_ptr<GL::Context> OpenGLDevice::CreateContext(const GL::ContextParams& params) const
{ {
return m_loader.CreateContext(params, m_referenceContext.get()); auto contextPtr = m_loader.CreateContext(this, params, m_referenceContext.get());
m_contexts.insert(contextPtr.get());
return contextPtr;
} }
std::unique_ptr<GL::Context> OpenGLDevice::CreateContext(const GL::ContextParams& params, WindowHandle handle) const std::unique_ptr<GL::Context> OpenGLDevice::CreateContext(const GL::ContextParams& params, WindowHandle handle) const
{ {
return m_loader.CreateContext(params, handle, m_referenceContext.get()); auto contextPtr = m_loader.CreateContext(this, params, handle, m_referenceContext.get());
m_contexts.insert(contextPtr.get());
return contextPtr;
} }
std::unique_ptr<AbstractBuffer> OpenGLDevice::InstantiateBuffer(BufferType type) std::unique_ptr<AbstractBuffer> OpenGLDevice::InstantiateBuffer(BufferType type)

View File

@ -4,8 +4,11 @@
#include <Nazara/OpenGLRenderer/Wrapper/Context.hpp> #include <Nazara/OpenGLRenderer/Wrapper/Context.hpp>
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Log.hpp>
#include <Nazara/Core/StringExt.hpp> #include <Nazara/Core/StringExt.hpp>
#include <Nazara/OpenGLRenderer/OpenGLDevice.hpp>
#include <Nazara/OpenGLRenderer/Wrapper/Loader.hpp> #include <Nazara/OpenGLRenderer/Wrapper/Loader.hpp>
#include <sstream>
#include <stdexcept> #include <stdexcept>
#include <Nazara/OpenGLRenderer/Debug.hpp> #include <Nazara/OpenGLRenderer/Debug.hpp>
@ -13,6 +16,12 @@ namespace Nz::GL
{ {
thread_local const Context* s_currentContext = nullptr; thread_local const Context* s_currentContext = nullptr;
Context::~Context()
{
if (m_device)
m_device->NotifyContextDestruction(*this);
}
bool Context::Initialize(const ContextParams& params) bool Context::Initialize(const ContextParams& params)
{ {

View File

@ -12,11 +12,6 @@
namespace Nz::GL namespace Nz::GL
{ {
GL::WGLContext::WGLContext(const WGLLoader& loader) :
m_loader(loader)
{
}
WGLContext::~WGLContext() WGLContext::~WGLContext()
{ {
Destroy(); Destroy();

View File

@ -11,7 +11,7 @@ namespace Nz::GL
{ {
WGLLoader::WGLLoader(DynLib& openglLib) : WGLLoader::WGLLoader(DynLib& openglLib) :
m_opengl32Lib(openglLib), m_opengl32Lib(openglLib),
m_baseContext(*this) m_baseContext(nullptr, *this)
{ {
if (!m_gdi32Lib.Load("gdi32.dll")) if (!m_gdi32Lib.Load("gdi32.dll"))
throw std::runtime_error("failed to load gdi32.dll: " + m_gdi32Lib.GetLastError()); throw std::runtime_error("failed to load gdi32.dll: " + m_gdi32Lib.GetLastError());
@ -42,7 +42,7 @@ namespace Nz::GL
#undef NAZARA_OPENGLRENDERER_EXT_FUNC #undef NAZARA_OPENGLRENDERER_EXT_FUNC
// In order to load OpenGL functions, we have to create a context first // In order to load OpenGL functions, we have to create a context first
WGLContext loadContext(*this); WGLContext loadContext(nullptr, *this);
if (!loadContext.Create(nullptr, {})) if (!loadContext.Create(nullptr, {}))
throw std::runtime_error("failed to create load context"); throw std::runtime_error("failed to create load context");
@ -56,9 +56,9 @@ namespace Nz::GL
throw std::runtime_error("failed to load OpenGL functions"); throw std::runtime_error("failed to load OpenGL functions");
} }
std::unique_ptr<Context> WGLLoader::CreateContext(const ContextParams& params, Context* shareContext) const std::unique_ptr<Context> WGLLoader::CreateContext(const OpenGLDevice* device, const ContextParams& params, Context* shareContext) const
{ {
auto context = std::make_unique<WGLContext>(*this); auto context = std::make_unique<WGLContext>(device, *this);
if (!context->Create(&m_baseContext, params, static_cast<WGLContext*>(shareContext))) if (!context->Create(&m_baseContext, params, static_cast<WGLContext*>(shareContext)))
{ {
NazaraError("failed to create context"); NazaraError("failed to create context");
@ -74,9 +74,9 @@ namespace Nz::GL
return context; return context;
} }
std::unique_ptr<Context> WGLLoader::CreateContext(const ContextParams& params, WindowHandle handle, Context* shareContext) const std::unique_ptr<Context> WGLLoader::CreateContext(const OpenGLDevice* device, const ContextParams& params, WindowHandle handle, Context* shareContext) const
{ {
auto context = std::make_unique<WGLContext>(*this); auto context = std::make_unique<WGLContext>(device, *this);
if (!context->Create(&m_baseContext, params, handle, static_cast<WGLContext*>(shareContext))) if (!context->Create(&m_baseContext, params, handle, static_cast<WGLContext*>(shareContext)))
{ {
NazaraError("failed to create context"); NazaraError("failed to create context");