OpenGLRenderer: Use a single context with WebGL
This commit is contained in:
parent
ea5c5240fc
commit
5b3703347f
|
|
@ -29,8 +29,8 @@ namespace Nz
|
|||
OpenGLDevice(OpenGLDevice&&) = delete; ///TODO?
|
||||
~OpenGLDevice();
|
||||
|
||||
std::unique_ptr<GL::Context> CreateContext(GL::ContextParams params) const;
|
||||
std::unique_ptr<GL::Context> CreateContext(GL::ContextParams params, WindowHandle handle) const;
|
||||
std::shared_ptr<GL::Context> CreateContext(GL::ContextParams params) const;
|
||||
std::shared_ptr<GL::Context> CreateContext(GL::ContextParams params, WindowHandle handle) const;
|
||||
|
||||
const RenderDeviceInfo& GetDeviceInfo() const override;
|
||||
const RenderDeviceFeatures& GetEnabledFeatures() const override;
|
||||
|
|
@ -62,7 +62,7 @@ namespace Nz
|
|||
private:
|
||||
inline void NotifyContextDestruction(const GL::Context& context) const;
|
||||
|
||||
std::unique_ptr<GL::Context> m_referenceContext;
|
||||
std::shared_ptr<GL::Context> m_referenceContext;
|
||||
mutable std::unordered_set<const GL::Context*> m_contexts;
|
||||
RenderDeviceInfo m_deviceInfo;
|
||||
GL::Loader& m_loader;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ namespace Nz
|
|||
std::optional<OpenGLRenderPass> m_renderPass;
|
||||
std::size_t m_currentFrame;
|
||||
std::vector<std::unique_ptr<OpenGLRenderImage>> m_renderImage;
|
||||
std::unique_ptr<GL::Context> m_context;
|
||||
std::shared_ptr<GL::Context> m_context;
|
||||
OpenGLWindowFramebuffer m_framebuffer;
|
||||
Vector2ui m_size;
|
||||
bool m_sizeInvalidated;
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ namespace Nz::GL
|
|||
EGLLoader(const Renderer::Config& config);
|
||||
~EGLLoader();
|
||||
|
||||
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::shared_ptr<Context> CreateContext(const OpenGLDevice* device, const ContextParams& params, Context* shareContext) const override;
|
||||
std::shared_ptr<Context> CreateContext(const OpenGLDevice* device, const ContextParams& params, WindowHandle handle, Context* shareContext) const override;
|
||||
|
||||
inline EGLDisplay GetDefaultDisplay() const;
|
||||
ContextType GetPreferredContextType() const override;
|
||||
|
|
|
|||
|
|
@ -31,8 +31,8 @@ namespace Nz::GL
|
|||
Loader() = default;
|
||||
virtual ~Loader();
|
||||
|
||||
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::shared_ptr<Context> CreateContext(const OpenGLDevice* device, const ContextParams& params, Context* shareContext = nullptr) const = 0;
|
||||
virtual std::shared_ptr<Context> CreateContext(const OpenGLDevice* device, const ContextParams& params, WindowHandle handle, Context* shareContext = nullptr) const = 0;
|
||||
|
||||
virtual ContextType GetPreferredContextType() const = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ namespace Nz::GL
|
|||
|
||||
inline void Shader::DestroyHelper(OpenGLDevice& /*device*/, const Context& context, GLuint objectId)
|
||||
{
|
||||
// context.glDeleteShader(objectId);
|
||||
context.glDeleteShader(objectId);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,8 +24,8 @@ namespace Nz::GL
|
|||
WGLLoader(const Renderer::Config& config);
|
||||
~WGLLoader() = default;
|
||||
|
||||
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::shared_ptr<Context> CreateContext(const OpenGLDevice* device, const ContextParams& params, Context* shareContext) const override;
|
||||
std::shared_ptr<Context> CreateContext(const OpenGLDevice* device, const ContextParams& params, WindowHandle handle, Context* shareContext) const override;
|
||||
|
||||
ContextType GetPreferredContextType() const override;
|
||||
|
||||
|
|
|
|||
|
|
@ -65,9 +65,7 @@ namespace Nz::GL
|
|||
Fallback fallbacks; //< m_ omitted
|
||||
|
||||
std::unordered_set<std::string> m_supportedPlatformExtensions;
|
||||
static EMSCRIPTEN_WEBGL_CONTEXT_HANDLE s_handle;
|
||||
static size_t s_handleCounter;
|
||||
bool m_ownsDisplay;
|
||||
EMSCRIPTEN_WEBGL_CONTEXT_HANDLE m_handle;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,8 +10,7 @@ namespace Nz::GL
|
|||
inline WebContext::WebContext(const OpenGLDevice* device, const WebLoader& loader) :
|
||||
Context(device),
|
||||
m_loader(loader),
|
||||
//m_handle(0),
|
||||
m_ownsDisplay(false)
|
||||
m_handle(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,8 +21,8 @@ namespace Nz::GL
|
|||
friend SymbolLoader;
|
||||
|
||||
public:
|
||||
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::shared_ptr<Context> CreateContext(const OpenGLDevice* device, const ContextParams& params, Context* shareContext) const override;
|
||||
std::shared_ptr<Context> CreateContext(const OpenGLDevice* device, const ContextParams& params, WindowHandle handle, Context* shareContext) const override;
|
||||
|
||||
ContextType GetPreferredContextType() const override;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -196,6 +196,8 @@ namespace Nz
|
|||
{
|
||||
#ifdef NAZARA_PLATFORM_WEB
|
||||
WindowHandle handle;
|
||||
handle.type = WindowBackend::Web;
|
||||
|
||||
return handle;
|
||||
#else
|
||||
SDL_SysWMinfo wmInfo;
|
||||
|
|
|
|||
Loading…
Reference in New Issue