OpenGL: Fix contexts & loaders
This commit is contained in:
parent
4dc8920a73
commit
9dd208c3cf
|
|
@ -8,12 +8,14 @@
|
|||
#define NAZARA_OPENGLRENDERER_LOADER_HPP
|
||||
|
||||
#include <Nazara/Prerequisites.hpp>
|
||||
#include <Nazara/Platform/WindowHandle.hpp>
|
||||
#include <Nazara/OpenGLRenderer/Config.hpp>
|
||||
#include <Nazara/OpenGLRenderer/Wrapper/Context.hpp>
|
||||
#include <memory>
|
||||
|
||||
namespace Nz::GL
|
||||
{
|
||||
class GLContext;
|
||||
class Context;
|
||||
|
||||
using GLFunction = int(*)();
|
||||
|
||||
|
|
@ -23,9 +25,10 @@ namespace Nz::GL
|
|||
Loader() = default;
|
||||
virtual ~Loader();
|
||||
|
||||
virtual std::unique_ptr<GLContext> CreateContext() = 0;
|
||||
virtual std::unique_ptr<Context> CreateContext(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 GLFunction LoadFunction(const char* name) = 0;
|
||||
virtual GLFunction LoadFunction(const char* name) const = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,96 @@
|
|||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/OpenGLRenderer/Wrapper/Context.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/StringExt.hpp>
|
||||
#include <Nazara/OpenGLRenderer/Wrapper/Loader.hpp>
|
||||
#include <stdexcept>
|
||||
#include <Nazara/OpenGLRenderer/Debug.hpp>
|
||||
|
||||
namespace Nz::GL
|
||||
{
|
||||
Context::~Context() = default;
|
||||
|
||||
bool Context::Initialize(const ContextParams& params)
|
||||
{
|
||||
if (!Activate())
|
||||
{
|
||||
NazaraError("failed to activate context");
|
||||
return false;
|
||||
}
|
||||
|
||||
const Loader& loader = GetLoader();
|
||||
|
||||
auto LoadSymbol = [&](auto& func, const char* funcName)
|
||||
{
|
||||
func = reinterpret_cast<std::decay_t<decltype(func)>>(loader.LoadFunction(funcName));
|
||||
if (!func && !ImplementFallback(funcName) && !func) //< Not a mistake
|
||||
throw std::runtime_error("failed to load core function " + std::string(funcName));
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
#define NAZARA_OPENGLRENDERER_FUNC(name, sig) LoadSymbol(name, #name);
|
||||
NAZARA_OPENGLRENDERER_FOREACH_GLES_FUNC(NAZARA_OPENGLRENDERER_FUNC)
|
||||
#undef NAZARA_OPENGLRENDERER_FUNC
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
NazaraError(e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Retrieve OpenGL version
|
||||
auto DecodeDigit = [](char c) -> int
|
||||
{
|
||||
if (c >= '0' && c <= '9')
|
||||
return c - '0';
|
||||
else
|
||||
return -1;
|
||||
};
|
||||
|
||||
std::string_view versionString = reinterpret_cast<const char*>(glGetString(GL_VERSION));
|
||||
if (versionString.size() > 2 && DecodeDigit(versionString[0]) >= 0 && versionString[1] == '.' && DecodeDigit(versionString[2]) >= 0)
|
||||
{
|
||||
m_params.glMajorVersion = DecodeDigit(versionString[0]);
|
||||
m_params.glMinorVersion = DecodeDigit(versionString[2]);
|
||||
}
|
||||
else
|
||||
NazaraWarning("Failed to decode OpenGL version: " + std::string(versionString));
|
||||
|
||||
// Load extensions
|
||||
std::string_view extensionList = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS));
|
||||
SplitString(extensionList, " ", [&](std::string_view extension)
|
||||
{
|
||||
m_supportedExtensions.emplace(extension);
|
||||
return true;
|
||||
});
|
||||
|
||||
// If we requested an OpenGL ES context but cannot create one, check for some compatibility extensions
|
||||
if (params.type == ContextType::OpenGL_ES && m_params.type != params.type)
|
||||
{
|
||||
if (m_supportedExtensions.count("GL_ARB_ES3_2_compatibility"))
|
||||
{
|
||||
m_params.type = ContextType::OpenGL_ES;
|
||||
m_params.glMajorVersion = 3;
|
||||
m_params.glMinorVersion = 2;
|
||||
}
|
||||
else if (m_supportedExtensions.count("GL_ARB_ES3_1_compatibility"))
|
||||
{
|
||||
m_params.type = ContextType::OpenGL_ES;
|
||||
m_params.glMajorVersion = 3;
|
||||
m_params.glMinorVersion = 1;
|
||||
}
|
||||
else if (m_supportedExtensions.count("GL_ARB_ES3_compatibility"))
|
||||
{
|
||||
m_params.type = ContextType::OpenGL_ES;
|
||||
m_params.glMajorVersion = 3;
|
||||
m_params.glMinorVersion = 0;
|
||||
}
|
||||
else
|
||||
NazaraWarning("desktop support for OpenGL ES is missing, falling back to OpenGL...");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,44 +0,0 @@
|
|||
// Copyright (C) 2020 Jérôme Leclercq
|
||||
// This file is part of the "Nazara Engine - OpenGL Renderer"
|
||||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/OpenGLRenderer/Wrapper/GLContext.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/OpenGLRenderer/Wrapper/Loader.hpp>
|
||||
#include <stdexcept>
|
||||
#include <Nazara/OpenGLRenderer/Debug.hpp>
|
||||
|
||||
namespace Nz::GL
|
||||
{
|
||||
GLContext::~GLContext() = default;
|
||||
|
||||
bool GLContext::LoadCoreFunctions(Loader& loader)
|
||||
{
|
||||
if (!Activate())
|
||||
{
|
||||
NazaraError("failed to activate context");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto LoadSymbol = [&](auto& func, const char* funcName)
|
||||
{
|
||||
func = reinterpret_cast<std::decay_t<decltype(func)>>(loader.LoadFunction(funcName));
|
||||
if (!func)
|
||||
throw std::runtime_error("failed to load core function " + std::string(funcName));
|
||||
};
|
||||
|
||||
try
|
||||
{
|
||||
#define NAZARA_OPENGLRENDERER_FUNC(name, sig) LoadSymbol(name, #name);
|
||||
NAZARA_OPENGLRENDERER_FOREACH_GLES_FUNC(NAZARA_OPENGLRENDERER_FUNC)
|
||||
#undef NAZARA_OPENGLRENDERER_FUNC
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
NazaraError(e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -14,7 +14,7 @@ namespace Nz::GL
|
|||
{
|
||||
thread_local WGLContext* s_currentContext = nullptr;
|
||||
|
||||
GL::WGLContext::WGLContext(WGLLoader& loader) :
|
||||
GL::WGLContext::WGLContext(const WGLLoader& loader) :
|
||||
m_loader(loader)
|
||||
{
|
||||
}
|
||||
|
|
@ -48,11 +48,9 @@ namespace Nz::GL
|
|||
return true;
|
||||
}
|
||||
|
||||
bool WGLContext::Create(const ContextParams& params)
|
||||
bool WGLContext::Create(const WGLContext* baseContext, const ContextParams& params, const WGLContext* shareContext)
|
||||
{
|
||||
Destroy();
|
||||
|
||||
// Creating a context requires a Window
|
||||
// Creating a context requires a device context, create window to get one
|
||||
m_window.reset(::CreateWindowA("STATIC", nullptr, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, nullptr, nullptr, GetModuleHandle(nullptr), nullptr));
|
||||
if (!m_window)
|
||||
{
|
||||
|
|
@ -62,71 +60,19 @@ namespace Nz::GL
|
|||
|
||||
::ShowWindow(m_window.get(), FALSE);
|
||||
|
||||
m_deviceContext = ::GetDC(m_window.get());
|
||||
return Create(baseContext, params, m_window.get(), shareContext);
|
||||
}
|
||||
|
||||
bool WGLContext::Create(const WGLContext* baseContext, const ContextParams& params, WindowHandle window, const WGLContext* shareContext)
|
||||
{
|
||||
m_deviceContext = ::GetDC(static_cast<HWND>(window));
|
||||
if (!m_deviceContext)
|
||||
{
|
||||
NazaraError("failed to retrieve dummy window device context: " + Error::GetLastSystemError());
|
||||
NazaraError("failed to retrieve window device context: " + Error::GetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SetPixelFormat(params))
|
||||
return false;
|
||||
|
||||
WGLContext* currentContext = s_currentContext; //< Pay TLS cost only once
|
||||
if (currentContext && currentContext->wglCreateContextAttribsARB)
|
||||
{
|
||||
struct OpenGLVersion
|
||||
{
|
||||
int major;
|
||||
int minor;
|
||||
};
|
||||
|
||||
std::array<OpenGLVersion, 8> supportedVersions = {
|
||||
{
|
||||
{ 4, 6 },
|
||||
{ 4, 5 },
|
||||
{ 4, 4 },
|
||||
{ 4, 3 },
|
||||
{ 4, 2 },
|
||||
{ 4, 1 },
|
||||
{ 4, 0 },
|
||||
{ 3, 3 }
|
||||
}
|
||||
};
|
||||
|
||||
for (const OpenGLVersion& version : supportedVersions)
|
||||
{
|
||||
std::array<int, 3 * 2 + 1> attributes = {
|
||||
WGL_CONTEXT_MAJOR_VERSION_ARB, version.major,
|
||||
WGL_CONTEXT_MINOR_VERSION_ARB, version.minor,
|
||||
|
||||
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB
|
||||
};
|
||||
|
||||
m_handle = currentContext->wglCreateContextAttribsARB(m_deviceContext, nullptr, attributes.data());
|
||||
if (m_handle)
|
||||
break;
|
||||
}
|
||||
|
||||
if (!m_handle)
|
||||
{
|
||||
NazaraError("failed to create WGL context: " + Error::GetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_handle = m_loader.wglCreateContext(m_deviceContext);
|
||||
if (!m_handle)
|
||||
{
|
||||
NazaraError("failed to create WGL context: " + Error::GetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
LoadWGLExt();
|
||||
|
||||
return true;
|
||||
return CreateInternal(baseContext, params, shareContext);
|
||||
}
|
||||
|
||||
void WGLContext::Destroy()
|
||||
|
|
@ -151,6 +97,157 @@ namespace Nz::GL
|
|||
m_loader.SwapBuffers(m_deviceContext);
|
||||
}
|
||||
|
||||
bool WGLContext::CreateInternal(const WGLContext* baseContext, const ContextParams& params, const WGLContext* shareContext)
|
||||
{
|
||||
Destroy();
|
||||
|
||||
m_params = params;
|
||||
|
||||
if (!SetPixelFormat())
|
||||
return false;
|
||||
|
||||
if (baseContext && baseContext->wglCreateContextAttribsARB)
|
||||
{
|
||||
struct Version
|
||||
{
|
||||
unsigned int major;
|
||||
unsigned int minor;
|
||||
};
|
||||
|
||||
if (params.type == ContextType::OpenGL_ES)
|
||||
{
|
||||
if (baseContext->HasPlatformExtension("WGL_EXT_create_context_es_profile"))
|
||||
{
|
||||
// Create OpenGL ES context
|
||||
std::array<Version, 3> supportedGL_ESVersions = {
|
||||
{
|
||||
{ 3, 2 },
|
||||
{ 3, 1 },
|
||||
{ 3, 0 }
|
||||
}
|
||||
};
|
||||
|
||||
for (const Version& version : supportedGL_ESVersions)
|
||||
{
|
||||
if (params.glMajorVersion != 0)
|
||||
{
|
||||
if (version.major > params.glMajorVersion)
|
||||
continue;
|
||||
|
||||
if (params.glMinorVersion != 0 && version.minor > params.glMinorVersion)
|
||||
continue;
|
||||
}
|
||||
|
||||
std::array<int, 3 * 2 + 1> attributes = {
|
||||
WGL_CONTEXT_MAJOR_VERSION_ARB, version.major,
|
||||
WGL_CONTEXT_MINOR_VERSION_ARB, version.minor,
|
||||
|
||||
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB | WGL_CONTEXT_ES_PROFILE_BIT_EXT
|
||||
};
|
||||
|
||||
m_handle = baseContext->wglCreateContextAttribsARB(m_deviceContext, nullptr, attributes.data());
|
||||
if (m_handle)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_handle)
|
||||
{
|
||||
// Create OpenGL context
|
||||
std::array<Version, 8> supportedGLVersions = {
|
||||
{
|
||||
{ 4, 6 },
|
||||
{ 4, 5 },
|
||||
{ 4, 4 },
|
||||
{ 4, 3 },
|
||||
{ 4, 2 },
|
||||
{ 4, 1 },
|
||||
{ 4, 0 },
|
||||
{ 3, 3 }
|
||||
}
|
||||
};
|
||||
|
||||
for (const Version& version : supportedGLVersions)
|
||||
{
|
||||
if (params.glMajorVersion != 0)
|
||||
{
|
||||
if (version.major > params.glMajorVersion)
|
||||
continue;
|
||||
|
||||
if (params.glMinorVersion != 0 && version.minor > params.glMinorVersion)
|
||||
continue;
|
||||
}
|
||||
|
||||
std::array<int, 3 * 2 + 1> attributes = {
|
||||
WGL_CONTEXT_MAJOR_VERSION_ARB, version.major,
|
||||
WGL_CONTEXT_MINOR_VERSION_ARB, version.minor,
|
||||
|
||||
WGL_CONTEXT_PROFILE_MASK_ARB, WGL_CONTEXT_CORE_PROFILE_BIT_ARB
|
||||
};
|
||||
|
||||
m_handle = baseContext->wglCreateContextAttribsARB(m_deviceContext, nullptr, attributes.data());
|
||||
if (m_handle)
|
||||
{
|
||||
m_params.type = ContextType::OpenGL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!m_handle)
|
||||
{
|
||||
NazaraError("failed to create WGL context: " + Error::GetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_handle = m_loader.wglCreateContext(m_deviceContext);
|
||||
if (!m_handle)
|
||||
{
|
||||
NazaraError("failed to create WGL context: " + Error::GetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
|
||||
m_params.type = ContextType::OpenGL;
|
||||
}
|
||||
|
||||
if (shareContext)
|
||||
{
|
||||
if (!m_loader.wglShareLists(shareContext->m_handle, m_handle))
|
||||
{
|
||||
NazaraError("failed to share context objects: " + Error::GetLastSystemError());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
LoadWGLExt();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WGLContext::ImplementFallback(const std::string_view& function)
|
||||
{
|
||||
if (m_params.type == ContextType::OpenGL_ES)
|
||||
return false; //< Implement fallback only for OpenGL (when emulating OpenGL ES)
|
||||
|
||||
if (function == "glClearDepthf")
|
||||
{
|
||||
fallbacks.glClearDepth = reinterpret_cast<Fallback::glClearDepthProc>(m_loader.LoadFunction("glClearDepth"));
|
||||
if (!fallbacks.glClearDepth)
|
||||
return false;
|
||||
|
||||
glClearDepthf = [](GLfloat depth)
|
||||
{
|
||||
assert(s_currentContext);
|
||||
s_currentContext->fallbacks.glClearDepth(depth);
|
||||
};
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void WGLContext::Desactivate()
|
||||
{
|
||||
WGLContext*& currentContext = s_currentContext; //< Pay TLS cost only once
|
||||
|
|
@ -161,6 +258,11 @@ namespace Nz::GL
|
|||
}
|
||||
}
|
||||
|
||||
const Loader& WGLContext::GetLoader()
|
||||
{
|
||||
return m_loader;
|
||||
}
|
||||
|
||||
bool WGLContext::LoadWGLExt()
|
||||
{
|
||||
if (!Activate())
|
||||
|
|
@ -186,7 +288,7 @@ namespace Nz::GL
|
|||
{
|
||||
SplitString(extensionString, " ", [&](std::string_view extension)
|
||||
{
|
||||
m_supportedExtensions.emplace(extension);
|
||||
m_supportedPlatformExtensions.emplace(extension);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
|
@ -194,14 +296,14 @@ namespace Nz::GL
|
|||
return true;
|
||||
}
|
||||
|
||||
bool WGLContext::SetPixelFormat(const ContextParams& params)
|
||||
bool WGLContext::SetPixelFormat()
|
||||
{
|
||||
PIXELFORMATDESCRIPTOR descriptor = {};
|
||||
descriptor.nSize = sizeof(PIXELFORMATDESCRIPTOR);
|
||||
descriptor.nVersion = 1;
|
||||
|
||||
int pixelFormat = 0;
|
||||
if (params.sampleCount > 1)
|
||||
if (m_params.sampleCount > 1)
|
||||
{
|
||||
WGLContext* currentContext = s_currentContext; //< Pay TLS cost only once
|
||||
if (currentContext)
|
||||
|
|
@ -215,13 +317,13 @@ namespace Nz::GL
|
|||
WGL_DRAW_TO_WINDOW_ARB, GL_TRUE,
|
||||
WGL_SUPPORT_OPENGL_ARB, GL_TRUE,
|
||||
WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB,
|
||||
WGL_COLOR_BITS_ARB, (params.bitsPerPixel == 32) ? 24 : params.bitsPerPixel,
|
||||
WGL_ALPHA_BITS_ARB, (params.bitsPerPixel == 32) ? 8 : 0,
|
||||
WGL_DEPTH_BITS_ARB, params.depthBits,
|
||||
WGL_STENCIL_BITS_ARB, params.stencilBits,
|
||||
WGL_DOUBLE_BUFFER_ARB, (params.doubleBuffering) ? GL_TRUE : GL_FALSE,
|
||||
WGL_COLOR_BITS_ARB, (m_params.bitsPerPixel == 32) ? 24 : m_params.bitsPerPixel,
|
||||
WGL_ALPHA_BITS_ARB, (m_params.bitsPerPixel == 32) ? 8 : 0,
|
||||
WGL_DEPTH_BITS_ARB, m_params.depthBits,
|
||||
WGL_STENCIL_BITS_ARB, m_params.stencilBits,
|
||||
WGL_DOUBLE_BUFFER_ARB, (m_params.doubleBuffering) ? GL_TRUE : GL_FALSE,
|
||||
WGL_SAMPLE_BUFFERS_ARB, GL_TRUE,
|
||||
WGL_SAMPLES_ARB, params.sampleCount
|
||||
WGL_SAMPLES_ARB, m_params.sampleCount
|
||||
};
|
||||
|
||||
int& sampleCount = attributes[attributes.size() - 3];
|
||||
|
|
@ -239,24 +341,26 @@ namespace Nz::GL
|
|||
}
|
||||
while (sampleCount > 1);
|
||||
|
||||
if (params.sampleCount != sampleCount)
|
||||
NazaraWarning("couldn't find a pixel format matching " + std::to_string(params.sampleCount) + " sample count, using " + std::to_string(sampleCount) + " sample(s) instead");
|
||||
if (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");
|
||||
|
||||
m_params.sampleCount = sampleCount;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pixelFormat == 0)
|
||||
{
|
||||
descriptor.cColorBits = BYTE((params.bitsPerPixel == 32) ? 24 : params.bitsPerPixel);
|
||||
descriptor.cDepthBits = BYTE(params.depthBits);
|
||||
descriptor.cStencilBits = BYTE(params.stencilBits);
|
||||
descriptor.cColorBits = BYTE((m_params.bitsPerPixel == 32) ? 24 : m_params.bitsPerPixel);
|
||||
descriptor.cDepthBits = BYTE(m_params.depthBits);
|
||||
descriptor.cStencilBits = BYTE(m_params.stencilBits);
|
||||
descriptor.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL;
|
||||
descriptor.iPixelType = PFD_TYPE_RGBA;
|
||||
|
||||
if (params.bitsPerPixel == 32)
|
||||
if (m_params.bitsPerPixel == 32)
|
||||
descriptor.cAlphaBits = 8;
|
||||
|
||||
if (params.doubleBuffering)
|
||||
if (m_params.doubleBuffering)
|
||||
descriptor.dwFlags |= PFD_DOUBLEBUFFER;
|
||||
|
||||
pixelFormat = m_loader.ChoosePixelFormat(m_deviceContext, &descriptor);
|
||||
|
|
@ -273,6 +377,13 @@ namespace Nz::GL
|
|||
return false;
|
||||
}
|
||||
|
||||
if (DescribePixelFormat(m_deviceContext, pixelFormat, sizeof(PIXELFORMATDESCRIPTOR), &descriptor) != 0)
|
||||
{
|
||||
m_params.bitsPerPixel = descriptor.cColorBits + descriptor.cAlphaBits;
|
||||
m_params.depthBits = descriptor.cDepthBits;
|
||||
m_params.stencilBits = descriptor.cStencilBits;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,13 +3,15 @@
|
|||
// For conditions of distribution and use, see copyright notice in Config.hpp
|
||||
|
||||
#include <Nazara/OpenGLRenderer/Wrapper/Win32/WGLLoader.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/OpenGLRenderer/Wrapper/Win32/WGLContext.hpp>
|
||||
#include <Nazara/OpenGLRenderer/Debug.hpp>
|
||||
|
||||
namespace Nz::GL
|
||||
{
|
||||
WGLLoader::WGLLoader(DynLib& openglLib) :
|
||||
m_opengl32Lib(openglLib)
|
||||
m_opengl32Lib(openglLib),
|
||||
m_baseContext(*this)
|
||||
{
|
||||
if (!m_gdi32Lib.Load("gdi32.dll"))
|
||||
throw std::runtime_error("failed to load gdi32.dll: " + m_gdi32Lib.GetLastError());
|
||||
|
|
@ -35,31 +37,62 @@ namespace Nz::GL
|
|||
NAZARA_OPENGLRENDERER_FOREACH_WGL_FUNC(NAZARA_OPENGLRENDERER_FUNC, NAZARA_OPENGLRENDERER_EXT_BEGIN, NAZARA_OPENGLRENDERER_EXT_END, NAZARA_OPENGLRENDERER_EXT_FUNC)
|
||||
#undef NAZARA_OPENGLRENDERER_FUNC
|
||||
|
||||
// In order to load OpenGL functions, we have to create a context first
|
||||
WGLContext dummyContext(*this);
|
||||
|
||||
if (!dummyContext.Create({}))
|
||||
throw std::runtime_error("failed to create load context");
|
||||
|
||||
WGLContext loadContext(*this);
|
||||
|
||||
if (!loadContext.Create({}))
|
||||
throw std::runtime_error("failed to create load context");
|
||||
|
||||
if (!loadContext.LoadCoreFunctions(*this))
|
||||
throw std::runtime_error("failed to load OpenGL functions");
|
||||
|
||||
#undef NAZARA_OPENGLRENDERER_EXT_BEGIN
|
||||
#undef NAZARA_OPENGLRENDERER_EXT_END
|
||||
#undef NAZARA_OPENGLRENDERER_EXT_FUNC
|
||||
|
||||
// In order to load OpenGL functions, we have to create a context first
|
||||
WGLContext loadContext(*this);
|
||||
|
||||
if (!loadContext.Create(nullptr, {}))
|
||||
throw std::runtime_error("failed to create load context");
|
||||
|
||||
ContextParams params;
|
||||
|
||||
if (!m_baseContext.Create(&loadContext, params))
|
||||
throw std::runtime_error("failed to create load context");
|
||||
|
||||
if (!m_baseContext.Initialize(params))
|
||||
throw std::runtime_error("failed to load OpenGL functions");
|
||||
}
|
||||
|
||||
std::unique_ptr<GLContext> WGLLoader::CreateContext()
|
||||
std::unique_ptr<Context> WGLLoader::CreateContext(const ContextParams& params, Context* shareContext) const
|
||||
{
|
||||
return {}; //< TODO
|
||||
auto context = std::make_unique<WGLContext>(*this);
|
||||
if (!context->Create(&m_baseContext, params, static_cast<WGLContext*>(shareContext)))
|
||||
{
|
||||
NazaraError("failed to create context");
|
||||
return {};
|
||||
}
|
||||
|
||||
GLFunction WGLLoader::LoadFunction(const char* name)
|
||||
if (!context->Initialize(params))
|
||||
{
|
||||
NazaraError("failed to initialize context");
|
||||
return {};
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
std::unique_ptr<Context> WGLLoader::CreateContext(const ContextParams& params, WindowHandle handle, Context* shareContext) const
|
||||
{
|
||||
auto context = std::make_unique<WGLContext>(*this);
|
||||
if (!context->Create(&m_baseContext, params, handle, static_cast<WGLContext*>(shareContext)))
|
||||
{
|
||||
NazaraError("failed to create context");
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!context->Initialize(params))
|
||||
{
|
||||
NazaraError("failed to initialize context");
|
||||
return {};
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
GLFunction WGLLoader::LoadFunction(const char* name) const
|
||||
{
|
||||
GLFunction func = reinterpret_cast<GLFunction>(wglGetProcAddress(name));
|
||||
if (!func) //< wglGetProcAddress doesn't work for OpenGL 1.1 functions
|
||||
|
|
|
|||
Loading…
Reference in New Issue