OpenGLRenderer: Use a single context with WebGL

This commit is contained in:
SirLynix
2022-12-06 09:06:38 +01:00
committed by Jérôme Leclercq
parent ea5c5240fc
commit 5b3703347f
16 changed files with 68 additions and 136 deletions

View File

@@ -136,10 +136,7 @@ namespace Nz
std::strcpy(m_cpuBrandString.data(), "CPU from unknown vendor - cpuid not supported");
if (!HardwareInfoImpl::IsCpuidSupported())
{
NazaraWarning("Cpuid is not supported");
return;
}
// To begin, we get the id of the constructor and the id of maximal functions supported by the CPUID
std::array<UInt32, 4> registers;

View File

@@ -147,14 +147,11 @@ namespace Nz::GL
GLenum Context::BindFramebuffer(GLuint fbo) const
{
// it looks like emscripten wants us to rebind the FBO everytime
#ifndef NAZARA_PLATFORM_WEB
if (m_state.boundDrawFBO == fbo)
return GL_DRAW_FRAMEBUFFER;
else if (m_state.boundReadFBO == fbo)
return GL_READ_FRAMEBUFFER;
else
#endif
{
if (!SetCurrentContext(this))
throw std::runtime_error("failed to activate context");
@@ -169,10 +166,7 @@ namespace Nz::GL
void Context::BindFramebuffer(FramebufferTarget target, GLuint fbo) const
{
auto& currentFbo = (target == FramebufferTarget::Draw) ? m_state.boundDrawFBO : m_state.boundReadFBO;
// it looks like emscripten wants us to rebind the FBO everytime
#ifndef NAZARA_PLATFORM_WEB
if (currentFbo != fbo)
#endif
{
if (!SetCurrentContext(this))
throw std::runtime_error("failed to activate context");

View File

@@ -133,14 +133,14 @@ namespace Nz::GL
eglTerminate(m_defaultDisplay);
}
std::unique_ptr<Context> EGLLoader::CreateContext(const OpenGLDevice* device, const ContextParams& params, Context* shareContext) const
std::shared_ptr<Context> EGLLoader::CreateContext(const OpenGLDevice* device, const ContextParams& params, Context* shareContext) const
{
std::unique_ptr<EGLContextBase> context;
std::shared_ptr<EGLContextBase> context;
#ifdef NAZARA_PLATFORM_WINDOWS
// On Windows context sharing seems to work only with window contexts
context = std::make_unique<EGLContextWin32>(device, *this);
context = std::make_shared<EGLContextWin32>(device, *this);
#else
context = std::make_unique<EGLContextBase>(device, *this);
context = std::make_shared<EGLContextBase>(device, *this);
#endif
if (!context->Create(params, static_cast<EGLContextBase*>(shareContext)))
@@ -158,9 +158,9 @@ namespace Nz::GL
return context;
}
std::unique_ptr<Context> EGLLoader::CreateContext([[maybe_unused]] const OpenGLDevice* device, const ContextParams& params, WindowHandle handle, Context* shareContext) const
std::shared_ptr<Context> EGLLoader::CreateContext([[maybe_unused]] const OpenGLDevice* device, const ContextParams& params, WindowHandle handle, Context* shareContext) const
{
std::unique_ptr<EGLContextBase> context;
std::shared_ptr<EGLContextBase> context;
switch (handle.type)
{
case WindowBackend::Invalid:
@@ -169,19 +169,19 @@ namespace Nz::GL
case WindowBackend::X11:
#ifdef NAZARA_PLATFORM_LINUX
context = std::make_unique<EGLContextX11>(device, *this);
context = std::make_shared<EGLContextX11>(device, *this);
#endif
break;
case WindowBackend::Windows:
#ifdef NAZARA_PLATFORM_WINDOWS
context = std::make_unique<EGLContextWin32>(device, *this);
context = std::make_shared<EGLContextWin32>(device, *this);
#endif
break;
case WindowBackend::Wayland:
#ifdef NAZARA_PLATFORM_LINUX
context = std::make_unique<EGLContextWayland>(device, *this);
context = std::make_shared<EGLContextWayland>(device, *this);
#endif
break;
}

View File

@@ -93,9 +93,9 @@ namespace Nz::GL
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::shared_ptr<Context> WGLLoader::CreateContext(const OpenGLDevice* device, const ContextParams& params, Context* shareContext) const
{
auto context = std::make_unique<WGLContext>(device, *this);
auto context = std::make_shared<WGLContext>(device, *this);
if (!context->Create(&m_baseContext, params, static_cast<WGLContext*>(shareContext)))
{
NazaraError("failed to create context");
@@ -111,9 +111,9 @@ namespace Nz::GL
return context;
}
std::unique_ptr<Context> WGLLoader::CreateContext(const OpenGLDevice* device, const ContextParams& params, WindowHandle handle, Context* shareContext) const
std::shared_ptr<Context> WGLLoader::CreateContext(const OpenGLDevice* device, const ContextParams& params, WindowHandle handle, Context* shareContext) const
{
auto context = std::make_unique<WGLContext>(device, *this);
auto context = std::make_shared<WGLContext>(device, *this);
if (!context->Create(&m_baseContext, params, handle, static_cast<WGLContext*>(shareContext)))
{
NazaraError("failed to create context");

View File

@@ -25,55 +25,6 @@ namespace Nz::GL
m_params = params;
std::size_t configCount;
std::array<EmscriptenWebGLContextAttributes, 0xFF> configs;
if (!ChooseConfig(configs.data(), configs.size(), &configCount))
return false;
std::size_t configIndex = 0;
return CreateInternal(configs[configIndex], shareContext);
}
bool WebContext::Create(const ContextParams& params, WindowHandle /*window*/, const WebContext* /*shareContext*/)
{
/*NazaraError("Unexpected context creation call");
return false;*/
return Create(params, nullptr);
}
void WebContext::Destroy()
{
if (s_handle > 0)
{
assert(s_handle > 0);
OnContextRelease();
NotifyContextDestruction(this);
s_handleCounter--;
if(s_handleCounter == 0)
{
emscripten_webgl_destroy_context(s_handle);
s_handle = 0;
}
}
}
void WebContext::EnableVerticalSync(bool /*enabled*/)
{
// TODO
}
void WebContext::SwapBuffers()
{
emscripten_webgl_commit_frame();
}
bool WebContext::ChooseConfig(EmscriptenWebGLContextAttributes* configs, std::size_t maxConfigCount, std::size_t* configCount)
{
EmscriptenWebGLContextAttributes configAttributes;
emscripten_webgl_init_context_attributes(&configAttributes);
@@ -93,23 +44,38 @@ namespace Nz::GL
configAttributes.renderViaOffscreenBackBuffer = false; // todo
configAttributes.proxyContextToMainThread = false; // todo
size_t numConfig = 1;
return CreateInternal(configAttributes, shareContext);
}
configs[0] = configAttributes;
bool WebContext::Create(const ContextParams& params, WindowHandle /*window*/, const WebContext* /*shareContext*/)
{
return Create(params, nullptr);
}
*configCount = numConfig;
void WebContext::Destroy()
{
if (m_handle != 0)
{
OnContextRelease();
NotifyContextDestruction(this);
return true;
emscripten_webgl_destroy_context(m_handle);
m_handle = 0;
}
}
void WebContext::EnableVerticalSync(bool /*enabled*/)
{
// TODO
}
void WebContext::SwapBuffers()
{
emscripten_webgl_commit_frame();
}
bool WebContext::CreateInternal(EmscriptenWebGLContextAttributes config, const WebContext* shareContext)
{
if(s_handleCounter > 0)
{
s_handleCounter++;
return true;
}
if (shareContext)
{
NazaraWarning(std::string("shared contexes are not supported by WebGL but shareContext is not null"));
@@ -145,8 +111,8 @@ namespace Nz::GL
config.majorVersion = version.major;
config.minorVersion = version.minor;
s_handle = emscripten_webgl_create_context("canvas", &config);
if (s_handle > 0)
m_handle = emscripten_webgl_create_context("canvas", &config);
if (m_handle > 0)
{
break;
}
@@ -158,15 +124,13 @@ namespace Nz::GL
return false;
}
if (s_handle <= 0)
if (m_handle <= 0)
{
NazaraError(std::string("failed to create Web context: ") + WebLoader::TranslateError(static_cast<EMSCRIPTEN_RESULT>(s_handle)));
NazaraError(std::string("failed to create Web context: ") + WebLoader::TranslateError(static_cast<EMSCRIPTEN_RESULT>(m_handle)));
return false;
}
LoadExt();
s_handleCounter++;
return true;
}
@@ -197,7 +161,7 @@ namespace Nz::GL
bool WebContext::Activate() const
{
EMSCRIPTEN_RESULT succeeded = emscripten_webgl_make_context_current(s_handle);
EMSCRIPTEN_RESULT succeeded = emscripten_webgl_make_context_current(m_handle);
if (succeeded != EMSCRIPTEN_RESULT_SUCCESS)
{
NazaraError("failed to activate context");
@@ -226,6 +190,8 @@ namespace Nz::GL
return false;
char* extensionString = emscripten_webgl_get_supported_extensions();
CallOnExit releaseStr([&] { free(extensionString); });
if (extensionString)
{
SplitString(extensionString, " ", [&](std::string_view extension)
@@ -234,20 +200,14 @@ namespace Nz::GL
std::string ext(extension);
emscripten_webgl_enable_extension(s_handle, ext.c_str());
emscripten_webgl_enable_extension(m_handle, ext.c_str());
return true;
});
}
free(extensionString);
return true;
}
EMSCRIPTEN_WEBGL_CONTEXT_HANDLE WebContext::s_handle = 0;
size_t WebContext::s_handleCounter = 0;
}
#if defined(NAZARA_PLATFORM_WINDOWS)

View File

@@ -43,9 +43,9 @@ namespace Nz::GL
WebLoader& loader;
};
std::unique_ptr<Context> WebLoader::CreateContext(const OpenGLDevice* device, const ContextParams& params, Context* shareContext) const
std::shared_ptr<Context> WebLoader::CreateContext(const OpenGLDevice* device, const ContextParams& params, Context* shareContext) const
{
std::unique_ptr<WebContext> context = std::make_unique<WebContext>(device, *this);
std::shared_ptr<WebContext> context = std::make_shared<WebContext>(device, *this);
if (!context->Create(params, static_cast<WebContext*>(shareContext)))
{
@@ -62,25 +62,15 @@ namespace Nz::GL
return context;
}
std::unique_ptr<Context> WebLoader::CreateContext(const OpenGLDevice* device, const ContextParams& params, WindowHandle handle, Context* shareContext) const
std::shared_ptr<Context> WebLoader::CreateContext(const OpenGLDevice* device, const ContextParams& params, WindowHandle handle, Context* shareContext) const
{
std::unique_ptr<WebContext> context;
switch (handle.type)
{
case WindowBackend::Invalid:
break;
case WindowBackend::Web:
context = std::make_unique<WebContext>(device, *this);
break;
}
if (!context)
if (handle.type != WindowBackend::Web)
{
NazaraError("unsupported window type");
return {};
}
std::shared_ptr<WebContext> context = std::make_shared<WebContext>(device, *this);
if (!context->Create(params, handle, static_cast<WebContext*>(shareContext)))
{
NazaraError("failed to create context");
@@ -103,15 +93,7 @@ namespace Nz::GL
GLFunction WebLoader::LoadFunction(const char* name) const
{
/*GLFunction func = reinterpret_cast<GLFunction>(m_WebLib.GetSymbol(name));
if (!func && WebGetProcAddress)
func = reinterpret_cast<GLFunction>(WebGetProcAddress(name));
return func;*/
return reinterpret_cast<GLFunction>(emscripten_webgl_get_proc_address(name));
//return nullptr;
}
const char* WebLoader::TranslateError(EMSCRIPTEN_RESULT errorId)

View File

@@ -196,6 +196,8 @@ namespace Nz
{
#ifdef NAZARA_PLATFORM_WEB
WindowHandle handle;
handle.type = WindowBackend::Web;
return handle;
#else
SDL_SysWMinfo wmInfo;