Fix EGL context sharing

It seems contexts must be part of the same display to be shared, and that using default display with window isn't an issue on Windows/X11
This commit is contained in:
Jérôme Leclercq 2020-09-02 15:40:57 +02:00
parent bc2f18c852
commit d05df45cb6
8 changed files with 60 additions and 46 deletions

View File

@ -71,6 +71,7 @@ namespace Nz::GL
std::unordered_set<std::string> m_supportedPlatformExtensions; std::unordered_set<std::string> m_supportedPlatformExtensions;
EGLContext m_handle; EGLContext m_handle;
bool m_ownsDisplay;
}; };
} }

View File

@ -12,7 +12,8 @@ namespace Nz::GL
m_loader(loader), m_loader(loader),
m_display(EGL_NO_DISPLAY), m_display(EGL_NO_DISPLAY),
m_surface(EGL_NO_SURFACE), m_surface(EGL_NO_SURFACE),
m_handle(EGL_NO_CONTEXT) m_handle(EGL_NO_CONTEXT),
m_ownsDisplay(false)
{ {
} }

View File

@ -20,11 +20,13 @@ namespace Nz::GL
{ {
public: public:
EGLLoader(); EGLLoader();
~EGLLoader() = default; ~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, Context* shareContext) const override;
std::unique_ptr<Context> CreateContext(const OpenGLDevice* device, 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;
inline EGLDisplay GetDefaultDisplay() const;
GLFunction LoadFunction(const char* name) const override; GLFunction LoadFunction(const char* name) const override;
#define NAZARA_OPENGLRENDERER_FUNC(name, sig) sig name = nullptr; #define NAZARA_OPENGLRENDERER_FUNC(name, sig) sig name = nullptr;
@ -40,6 +42,7 @@ namespace Nz::GL
static const char* TranslateError(EGLint errorId); static const char* TranslateError(EGLint errorId);
private: private:
EGLDisplay m_defaultDisplay;
DynLib m_eglLib; DynLib m_eglLib;
}; };
} }

View File

@ -5,8 +5,12 @@
#include <Nazara/OpenGLRenderer/Wrapper/EGL/EGLLoader.hpp> #include <Nazara/OpenGLRenderer/Wrapper/EGL/EGLLoader.hpp>
#include <Nazara/OpenGLRenderer/Debug.hpp> #include <Nazara/OpenGLRenderer/Debug.hpp>
namespace Nz::Vk namespace Nz::GL
{ {
inline EGLDisplay EGLLoader::GetDefaultDisplay() const
{
return m_defaultDisplay;
}
} }
#include <Nazara/OpenGLRenderer/DebugOff.hpp> #include <Nazara/OpenGLRenderer/DebugOff.hpp>

View File

@ -27,15 +27,7 @@ namespace Nz::GL
if (!BindAPI()) if (!BindAPI())
return false; return false;
m_display = m_loader.eglGetDisplay(EGL_DEFAULT_DISPLAY); m_display = m_loader.GetDefaultDisplay();
if (!m_display)
{
NazaraError("failed to retrieve default EGL display");
return false;
}
if (!InitDisplay())
return false;
std::size_t configCount; std::size_t configCount;
std::array<EGLConfig, 0xFF> configs; std::array<EGLConfig, 0xFF> configs;
@ -67,26 +59,32 @@ namespace Nz::GL
void EGLContextBase::Destroy() void EGLContextBase::Destroy()
{ {
if (m_handle) if (m_handle != EGL_NO_CONTEXT)
{ {
assert(m_display); assert(m_display != EGL_NO_DISPLAY);
OnContextRelease(); OnContextRelease();
NotifyContextDestruction(this); NotifyContextDestruction(this);
m_loader.eglDestroyContext(m_display, m_handle); m_loader.eglDestroyContext(m_display, m_handle);
m_handle = nullptr; m_handle = EGL_NO_CONTEXT;
} }
if (m_surface) if (m_surface != EGL_NO_SURFACE)
{ {
assert(m_display); assert(m_display != EGL_NO_DISPLAY);
m_loader.eglDestroySurface(m_display, m_surface); m_loader.eglDestroySurface(m_display, m_surface);
m_surface = nullptr; m_surface = EGL_NO_SURFACE;
} }
if (m_display) if (m_display)
m_loader.eglTerminate(m_display); {
if (m_ownsDisplay)
m_loader.eglTerminate(m_display);
m_display = EGL_NO_DISPLAY;
m_ownsDisplay = false;
}
} }
void EGLContextBase::EnableVerticalSync(bool enabled) void EGLContextBase::EnableVerticalSync(bool enabled)
@ -97,7 +95,6 @@ namespace Nz::GL
void EGLContextBase::SwapBuffers() void EGLContextBase::SwapBuffers()
{ {
m_loader.eglSwapBuffers(m_display, m_surface); m_loader.eglSwapBuffers(m_display, m_surface);
// TODO
} }
bool EGLContextBase::BindAPI() bool EGLContextBase::BindAPI()
@ -133,7 +130,7 @@ namespace Nz::GL
EGLint configAttributes[] = EGLint configAttributes[] =
{ {
EGL_BUFFER_SIZE, EGLint(m_params.bitsPerPixel), EGL_BUFFER_SIZE, EGLint(m_params.bitsPerPixel),
EGL_DEPTH_SIZE, m_params.depthBits, EGL_DEPTH_SIZE, EGLint(m_params.depthBits),
EGL_RENDERABLE_TYPE, (m_params.type == ContextType::OpenGL_ES) ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_BIT, EGL_RENDERABLE_TYPE, (m_params.type == ContextType::OpenGL_ES) ? EGL_OPENGL_ES3_BIT : EGL_OPENGL_BIT,
EGL_SAMPLE_BUFFERS, EGLint((m_params.sampleCount > 1) ? 1 : 0), EGL_SAMPLE_BUFFERS, EGLint((m_params.sampleCount > 1) ? 1 : 0),
EGL_SAMPLES, EGLint((m_params.sampleCount > 1) ? m_params.sampleCount : 0), EGL_SAMPLES, EGLint((m_params.sampleCount > 1) ? m_params.sampleCount : 0),
@ -264,6 +261,8 @@ namespace Nz::GL
return false; return false;
} }
m_ownsDisplay = true;
const char* vendor = m_loader.eglQueryString(m_display, EGL_VENDOR); const char* vendor = m_loader.eglQueryString(m_display, EGL_VENDOR);
NazaraNotice("Initialized EGL " + std::to_string(major) + "." + std::to_string(minor) + " display (" + vendor + ")"); NazaraNotice("Initialized EGL " + std::to_string(major) + "." + std::to_string(minor) + " display (" + vendor + ")");

View File

@ -4,6 +4,7 @@
#include <Nazara/OpenGLRenderer/Wrapper/EGL/EGLLoader.hpp> #include <Nazara/OpenGLRenderer/Wrapper/EGL/EGLLoader.hpp>
#include <Nazara/Core/Error.hpp> #include <Nazara/Core/Error.hpp>
#include <Nazara/Core/Log.hpp>
#include <Nazara/OpenGLRenderer/Wrapper/EGL/EGLContextBase.hpp> #include <Nazara/OpenGLRenderer/Wrapper/EGL/EGLContextBase.hpp>
#ifdef NAZARA_PLATFORM_LINUX #ifdef NAZARA_PLATFORM_LINUX
@ -19,7 +20,8 @@
namespace Nz::GL namespace Nz::GL
{ {
EGLLoader::EGLLoader() EGLLoader::EGLLoader() :
m_defaultDisplay(nullptr)
{ {
if (!m_eglLib.Load("libEGL")) if (!m_eglLib.Load("libEGL"))
throw std::runtime_error("failed to load gdi32.dll: " + m_eglLib.GetLastError()); throw std::runtime_error("failed to load gdi32.dll: " + m_eglLib.GetLastError());
@ -45,14 +47,33 @@ namespace Nz::GL
#undef NAZARA_OPENGLRENDERER_EXT_END #undef NAZARA_OPENGLRENDERER_EXT_END
#undef NAZARA_OPENGLRENDERER_EXT_FUNC #undef NAZARA_OPENGLRENDERER_EXT_FUNC
EGLDisplay defaultDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (!defaultDisplay)
throw std::runtime_error("failed to retrieve default EGL display");
EGLint major, minor;
if (eglInitialize(defaultDisplay, &major, &minor) != EGL_TRUE)
throw std::runtime_error("failed to initialize default EGL display");
m_defaultDisplay = defaultDisplay;
const char* vendor = eglQueryString(m_defaultDisplay, EGL_VENDOR);
NazaraNotice("Initialized EGL " + std::to_string(major) + "." + std::to_string(minor) + " display (" + vendor + ")");
// Try to create a dummy context in order to check EGL support (FIXME: is this really necessary?) // Try to create a dummy context in order to check EGL support (FIXME: is this really necessary?)
ContextParams params; /*ContextParams params;
EGLContextBase baseContext(nullptr, *this); EGLContextBase baseContext(nullptr, *this);
if (!baseContext.Create(params)) if (!baseContext.Create(params))
throw std::runtime_error("failed to create load context"); throw std::runtime_error("failed to create load context");
if (!baseContext.Initialize(params)) if (!baseContext.Initialize(params))
throw std::runtime_error("failed to load OpenGL functions"); throw std::runtime_error("failed to load OpenGL functions");*/
}
EGLLoader::~EGLLoader()
{
if (m_defaultDisplay)
eglTerminate(m_defaultDisplay);
} }
std::unique_ptr<Context> EGLLoader::CreateContext(const OpenGLDevice* device, const ContextParams& params, Context* shareContext) const std::unique_ptr<Context> EGLLoader::CreateContext(const OpenGLDevice* device, const ContextParams& params, Context* shareContext) const

View File

@ -17,22 +17,7 @@ namespace Nz::GL
if (!BindAPI()) if (!BindAPI())
return false; return false;
m_xdisplay = XOpenDisplay(nullptr); m_display = m_loader.GetDefaultDisplay();
if (!m_xdisplay)
{
NazaraError("failed to connect to X server");
return false;
}
m_display = m_loader.eglGetDisplay(m_xdisplay);
if (!m_display)
{
NazaraError("failed to retrieve default EGL display");
return false;
}
if (!InitDisplay())
return false;
std::size_t configCount; std::size_t configCount;
std::array<EGLConfig, 0xFF> configs; std::array<EGLConfig, 0xFF> configs;
@ -67,9 +52,7 @@ namespace Nz::GL
if (!BindAPI()) if (!BindAPI())
return false; return false;
m_display = m_loader.eglGetDisplay(static_cast<Display*>(window.x11.display)); m_display = m_loader.GetDefaultDisplay();
if (!InitDisplay())
return false;
std::size_t configCount; std::size_t configCount;
std::array<EGLConfig, 0xFF> configs; std::array<EGLConfig, 0xFF> configs;

View File

@ -44,16 +44,18 @@ namespace Nz::GL
return false; return false;
HWND windowHandle = static_cast<HWND>(window.windows.window); HWND windowHandle = static_cast<HWND>(window.windows.window);
HDC deviceContext = ::GetDC(windowHandle); /*HDC deviceContext = ::GetDC(windowHandle);
if (!deviceContext) if (!deviceContext)
{ {
NazaraError("failed to retrieve window device context: " + Error::GetLastSystemError()); NazaraError("failed to retrieve window device context: " + Error::GetLastSystemError());
return false; return false;
} }
m_display = m_loader.eglGetDisplay(deviceContext); m_display = m_loader.GetDefaultDisplay();
if (!InitDisplay()) if (!InitDisplay())
return false; return false;*/
m_display = m_loader.GetDefaultDisplay();
std::size_t configCount; std::size_t configCount;
std::array<EGLConfig, 0xFF> configs; std::array<EGLConfig, 0xFF> configs;