mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2025-03-06 06:17:43 +00:00
OpenGLContextEGL: Fix X11+platform base combination
This commit is contained in:
parent
f936a36c85
commit
edeaaebc7d
|
@ -61,22 +61,6 @@ static bool LoadGLADEGL(EGLDisplay display, Error* error)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<EGLint> EGLAttribToInt(const EGLAttrib* attribs)
|
|
||||||
{
|
|
||||||
std::vector<EGLint> int_attribs;
|
|
||||||
if (attribs)
|
|
||||||
{
|
|
||||||
for (const EGLAttrib* attrib = attribs; *attrib != EGL_NONE;)
|
|
||||||
{
|
|
||||||
int_attribs.push_back(static_cast<EGLint>(*(attrib++))); // key
|
|
||||||
int_attribs.push_back(static_cast<EGLint>(*(attrib++))); // value
|
|
||||||
}
|
|
||||||
int_attribs.push_back(EGL_NONE);
|
|
||||||
int_attribs.push_back(0);
|
|
||||||
}
|
|
||||||
return int_attribs;
|
|
||||||
}
|
|
||||||
|
|
||||||
OpenGLContextEGL::OpenGLContextEGL(const WindowInfo& wi) : OpenGLContext(wi)
|
OpenGLContextEGL::OpenGLContextEGL(const WindowInfo& wi) : OpenGLContext(wi)
|
||||||
{
|
{
|
||||||
LoadEGL();
|
LoadEGL();
|
||||||
|
@ -104,7 +88,7 @@ bool OpenGLContextEGL::Initialize(std::span<const Version> versions_to_try, Erro
|
||||||
if (!LoadGLADEGL(EGL_NO_DISPLAY, error))
|
if (!LoadGLADEGL(EGL_NO_DISPLAY, error))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
m_display = GetPlatformDisplay(nullptr, error);
|
m_display = GetPlatformDisplay(error);
|
||||||
if (m_display == EGL_NO_DISPLAY)
|
if (m_display == EGL_NO_DISPLAY)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -135,16 +119,24 @@ bool OpenGLContextEGL::Initialize(std::span<const Version> versions_to_try, Erro
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
EGLDisplay OpenGLContextEGL::GetPlatformDisplay(const EGLAttrib* attribs, Error* error)
|
EGLDisplay OpenGLContextEGL::GetPlatformDisplay(Error* error)
|
||||||
{
|
{
|
||||||
EGLDisplay dpy = TryGetPlatformDisplay(EGL_PLATFORM_SURFACELESS_MESA, attribs);
|
EGLDisplay dpy = TryGetPlatformDisplay(EGL_PLATFORM_SURFACELESS_MESA, "EGL_MESA_platform_surfaceless");
|
||||||
if (dpy == EGL_NO_DISPLAY)
|
if (dpy == EGL_NO_DISPLAY)
|
||||||
dpy = GetFallbackDisplay(error);
|
dpy = GetFallbackDisplay(error);
|
||||||
|
|
||||||
return dpy;
|
return dpy;
|
||||||
}
|
}
|
||||||
|
|
||||||
EGLDisplay OpenGLContextEGL::TryGetPlatformDisplay(EGLenum platform, const EGLAttrib* attribs)
|
EGLSurface OpenGLContextEGL::CreatePlatformSurface(EGLConfig config, void* win, Error* error)
|
||||||
|
{
|
||||||
|
EGLSurface surface = TryCreatePlatformSurface(config, win, error);
|
||||||
|
if (!surface)
|
||||||
|
surface = CreateFallbackSurface(config, win, error);
|
||||||
|
return surface;
|
||||||
|
}
|
||||||
|
|
||||||
|
EGLDisplay OpenGLContextEGL::TryGetPlatformDisplay(EGLenum platform, const char* platform_ext)
|
||||||
{
|
{
|
||||||
const char* extensions_str = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
|
const char* extensions_str = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
|
||||||
if (!extensions_str)
|
if (!extensions_str)
|
||||||
|
@ -154,36 +146,17 @@ EGLDisplay OpenGLContextEGL::TryGetPlatformDisplay(EGLenum platform, const EGLAt
|
||||||
}
|
}
|
||||||
|
|
||||||
EGLDisplay dpy = EGL_NO_DISPLAY;
|
EGLDisplay dpy = EGL_NO_DISPLAY;
|
||||||
if (std::strstr(extensions_str, "EGL_KHR_platform_base"))
|
if (platform_ext && std::strstr(extensions_str, platform_ext))
|
||||||
{
|
{
|
||||||
Log_DevPrint("Using EGL_KHR_platform_base.");
|
Log_DevFmt("Using EGL platform {}.", platform_ext);
|
||||||
|
|
||||||
PFNEGLGETPLATFORMDISPLAYPROC get_platform_display;
|
|
||||||
if (s_egl_library.GetSymbol("eglGetPlatformDisplay", &get_platform_display))
|
|
||||||
{
|
|
||||||
dpy = get_platform_display(platform, m_wi.display_connection, attribs);
|
|
||||||
if (dpy == EGL_NO_DISPLAY)
|
|
||||||
{
|
|
||||||
const EGLint err = eglGetError();
|
|
||||||
Log_ErrorFmt("eglGetPlatformDisplay() failed: {} (0x{:X})", err, err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log_WarningPrint("eglGetPlatformDisplay() was not found");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (std::strstr(extensions_str, "EGL_EXT_platform_base"))
|
|
||||||
{
|
|
||||||
Log_DevPrint("Using EGL_EXT_platform_base.");
|
|
||||||
|
|
||||||
PFNEGLGETPLATFORMDISPLAYEXTPROC get_platform_display_ext =
|
PFNEGLGETPLATFORMDISPLAYEXTPROC get_platform_display_ext =
|
||||||
(PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT");
|
(PFNEGLGETPLATFORMDISPLAYEXTPROC)eglGetProcAddress("eglGetPlatformDisplayEXT");
|
||||||
if (get_platform_display_ext)
|
if (get_platform_display_ext)
|
||||||
{
|
{
|
||||||
const std::vector<EGLint> int_attribs = EGLAttribToInt(attribs);
|
dpy = get_platform_display_ext(platform, m_wi.display_connection, nullptr);
|
||||||
dpy = get_platform_display_ext(platform, m_wi.display_connection, attribs ? int_attribs.data() : nullptr);
|
m_use_ext_platform_base = (dpy != EGL_NO_DISPLAY);
|
||||||
if (dpy == EGL_NO_DISPLAY)
|
if (!m_use_ext_platform_base)
|
||||||
{
|
{
|
||||||
const EGLint err = eglGetError();
|
const EGLint err = eglGetError();
|
||||||
Log_ErrorFmt("eglGetPlatformDisplayEXT() failed: {} (0x{:X})", err, err);
|
Log_ErrorFmt("eglGetPlatformDisplayEXT() failed: {} (0x{:X})", err, err);
|
||||||
|
@ -196,15 +169,41 @@ EGLDisplay OpenGLContextEGL::TryGetPlatformDisplay(EGLenum platform, const EGLAt
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log_WarningPrint("EGL_EXT_platform_base nor EGL_KHR_platform_base is supported.");
|
Log_WarningFmt("{} is not supported.", platform_ext);
|
||||||
}
|
}
|
||||||
|
|
||||||
return dpy;
|
return dpy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EGLSurface OpenGLContextEGL::TryCreatePlatformSurface(EGLConfig config, void* win, Error* error)
|
||||||
|
{
|
||||||
|
EGLSurface surface = EGL_NO_SURFACE;
|
||||||
|
if (m_use_ext_platform_base)
|
||||||
|
{
|
||||||
|
PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC create_platform_window_surface_ext =
|
||||||
|
(PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC)eglGetProcAddress("eglCreatePlatformWindowSurfaceEXT");
|
||||||
|
if (create_platform_window_surface_ext)
|
||||||
|
{
|
||||||
|
surface = create_platform_window_surface_ext(m_display, config, win, nullptr);
|
||||||
|
if (surface == EGL_NO_SURFACE)
|
||||||
|
{
|
||||||
|
const EGLint err = eglGetError();
|
||||||
|
Error::SetStringFmt(error, "eglCreatePlatformWindowSurfaceEXT() failed: {} (0x{:X})", err, err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log_ErrorPrint("eglCreatePlatformWindowSurfaceEXT() not found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return surface;
|
||||||
|
}
|
||||||
|
|
||||||
EGLDisplay OpenGLContextEGL::GetFallbackDisplay(Error* error)
|
EGLDisplay OpenGLContextEGL::GetFallbackDisplay(Error* error)
|
||||||
{
|
{
|
||||||
Log_WarningPrint("Using fallback eglGetDisplay() path.");
|
Log_WarningPrint("Using fallback eglGetDisplay() path.");
|
||||||
|
|
||||||
EGLDisplay dpy = eglGetDisplay(m_wi.display_connection);
|
EGLDisplay dpy = eglGetDisplay(m_wi.display_connection);
|
||||||
if (dpy == EGL_NO_DISPLAY)
|
if (dpy == EGL_NO_DISPLAY)
|
||||||
{
|
{
|
||||||
|
@ -215,32 +214,11 @@ EGLDisplay OpenGLContextEGL::GetFallbackDisplay(Error* error)
|
||||||
return dpy;
|
return dpy;
|
||||||
}
|
}
|
||||||
|
|
||||||
EGLSurface OpenGLContextEGL::CreatePlatformSurface(EGLConfig config, const EGLAttrib* attribs, Error* error)
|
EGLSurface OpenGLContextEGL::CreateFallbackSurface(EGLConfig config, void* win, Error* error)
|
||||||
{
|
|
||||||
EGLSurface surface = EGL_NO_SURFACE;
|
|
||||||
if (GLAD_EGL_VERSION_1_5)
|
|
||||||
{
|
|
||||||
surface = eglCreatePlatformWindowSurface(m_display, config, m_wi.window_handle, attribs);
|
|
||||||
if (surface == EGL_NO_SURFACE)
|
|
||||||
{
|
|
||||||
const EGLint err = eglGetError();
|
|
||||||
Error::SetStringFmt(error, "eglCreatePlatformWindowSurface() failed: {} (0x{:X})", err, err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (surface == EGL_NO_SURFACE)
|
|
||||||
surface = CreateFallbackSurface(config, attribs, m_wi.window_handle, error);
|
|
||||||
|
|
||||||
return surface;
|
|
||||||
}
|
|
||||||
|
|
||||||
EGLSurface OpenGLContextEGL::CreateFallbackSurface(EGLConfig config, const EGLAttrib* attribs, void* win, Error* error)
|
|
||||||
{
|
{
|
||||||
Log_WarningPrint("Using fallback eglCreateWindowSurface() path.");
|
Log_WarningPrint("Using fallback eglCreateWindowSurface() path.");
|
||||||
|
|
||||||
const std::vector<EGLint> int_attribs = EGLAttribToInt(attribs);
|
EGLSurface surface = eglCreateWindowSurface(m_display, config, (EGLNativeWindowType)win, nullptr);
|
||||||
|
|
||||||
EGLSurface surface =
|
|
||||||
eglCreateWindowSurface(m_display, config, (EGLNativeWindowType)win, attribs ? int_attribs.data() : nullptr);
|
|
||||||
if (surface == EGL_NO_SURFACE)
|
if (surface == EGL_NO_SURFACE)
|
||||||
{
|
{
|
||||||
const EGLint err = eglGetError();
|
const EGLint err = eglGetError();
|
||||||
|
@ -358,7 +336,7 @@ bool OpenGLContextEGL::CreateSurface()
|
||||||
}
|
}
|
||||||
|
|
||||||
Error error;
|
Error error;
|
||||||
m_surface = CreatePlatformSurface(m_config, nullptr, &error);
|
m_surface = CreatePlatformSurface(m_config, m_wi.window_handle, &error);
|
||||||
if (m_surface == EGL_NO_SURFACE)
|
if (m_surface == EGL_NO_SURFACE)
|
||||||
{
|
{
|
||||||
Log_ErrorFmt("Failed to create platform surface: {}", error.GetDescription());
|
Log_ErrorFmt("Failed to create platform surface: {}", error.GetDescription());
|
||||||
|
|
|
@ -27,12 +27,13 @@ public:
|
||||||
virtual std::unique_ptr<OpenGLContext> CreateSharedContext(const WindowInfo& wi, Error* error) override;
|
virtual std::unique_ptr<OpenGLContext> CreateSharedContext(const WindowInfo& wi, Error* error) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual EGLDisplay GetPlatformDisplay(const EGLAttrib* attribs, Error* error);
|
virtual EGLDisplay GetPlatformDisplay(Error* error);
|
||||||
virtual EGLSurface CreatePlatformSurface(EGLConfig config, const EGLAttrib* attribs, Error* error);
|
virtual EGLSurface CreatePlatformSurface(EGLConfig config, void* win, Error* error);
|
||||||
|
|
||||||
EGLDisplay TryGetPlatformDisplay(EGLenum platform, const EGLAttrib* attribs);
|
EGLDisplay TryGetPlatformDisplay(EGLenum platform, const char* platform_ext);
|
||||||
|
EGLSurface TryCreatePlatformSurface(EGLConfig config, void* window, Error* error);
|
||||||
EGLDisplay GetFallbackDisplay(Error* error);
|
EGLDisplay GetFallbackDisplay(Error* error);
|
||||||
EGLSurface CreateFallbackSurface(EGLConfig config, const EGLAttrib* attribs, void* window, Error* error);
|
EGLSurface CreateFallbackSurface(EGLConfig config, void* window, Error* error);
|
||||||
|
|
||||||
bool Initialize(std::span<const Version> versions_to_try, Error* error);
|
bool Initialize(std::span<const Version> versions_to_try, Error* error);
|
||||||
bool CreateContext(const Version& version, EGLContext share_context);
|
bool CreateContext(const Version& version, EGLContext share_context);
|
||||||
|
@ -49,4 +50,6 @@ protected:
|
||||||
EGLContext m_context = EGL_NO_CONTEXT;
|
EGLContext m_context = EGL_NO_CONTEXT;
|
||||||
|
|
||||||
EGLConfig m_config = {};
|
EGLConfig m_config = {};
|
||||||
|
|
||||||
|
bool m_use_ext_platform_base = false;
|
||||||
};
|
};
|
||||||
|
|
|
@ -50,16 +50,16 @@ void OpenGLContextEGLWayland::ResizeSurface(u32 new_surface_width, u32 new_surfa
|
||||||
OpenGLContextEGL::ResizeSurface(new_surface_width, new_surface_height);
|
OpenGLContextEGL::ResizeSurface(new_surface_width, new_surface_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
EGLDisplay OpenGLContextEGLWayland::GetPlatformDisplay(const EGLAttrib* attribs, Error* error)
|
EGLDisplay OpenGLContextEGLWayland::GetPlatformDisplay(Error* error)
|
||||||
{
|
{
|
||||||
EGLDisplay dpy = TryGetPlatformDisplay(EGL_PLATFORM_WAYLAND_KHR, attribs);
|
EGLDisplay dpy = TryGetPlatformDisplay(EGL_PLATFORM_WAYLAND_KHR, "EGL_EXT_platform_wayland");
|
||||||
if (dpy == EGL_NO_DISPLAY)
|
if (dpy == EGL_NO_DISPLAY)
|
||||||
dpy = GetFallbackDisplay(error);
|
dpy = GetFallbackDisplay(error);
|
||||||
|
|
||||||
return dpy;
|
return dpy;
|
||||||
}
|
}
|
||||||
|
|
||||||
EGLSurface OpenGLContextEGLWayland::CreatePlatformSurface(EGLConfig config, const EGLAttrib* attribs, Error* error)
|
EGLSurface OpenGLContextEGLWayland::CreatePlatformSurface(EGLConfig config, void* win, Error* error)
|
||||||
{
|
{
|
||||||
if (m_wl_window)
|
if (m_wl_window)
|
||||||
{
|
{
|
||||||
|
@ -67,32 +67,23 @@ EGLSurface OpenGLContextEGLWayland::CreatePlatformSurface(EGLConfig config, cons
|
||||||
m_wl_window = nullptr;
|
m_wl_window = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_wl_window =
|
m_wl_window = m_wl_egl_window_create(static_cast<wl_surface*>(win), m_wi.surface_width, m_wi.surface_height);
|
||||||
m_wl_egl_window_create(static_cast<wl_surface*>(m_wi.window_handle), m_wi.surface_width, m_wi.surface_height);
|
|
||||||
if (!m_wl_window)
|
if (!m_wl_window)
|
||||||
{
|
{
|
||||||
Error::SetStringView(error, "wl_egl_window_create() failed");
|
Error::SetStringView(error, "wl_egl_window_create() failed");
|
||||||
return EGL_NO_SURFACE;
|
return EGL_NO_SURFACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
EGLSurface surface = EGL_NO_SURFACE;
|
EGLSurface surface = TryCreatePlatformSurface(config, m_wl_window, error);
|
||||||
if (GLAD_EGL_VERSION_1_5)
|
if (surface == EGL_NO_SURFACE)
|
||||||
{
|
{
|
||||||
surface = eglCreatePlatformWindowSurface(m_display, config, m_wl_window, attribs);
|
surface = CreateFallbackSurface(config, m_wl_window, error);
|
||||||
if (surface == EGL_NO_SURFACE)
|
if (surface == EGL_NO_SURFACE)
|
||||||
{
|
{
|
||||||
const EGLint err = eglGetError();
|
m_wl_egl_window_destroy(m_wl_window);
|
||||||
Error::SetStringFmt(error, "eglCreatePlatformWindowSurface() for Wayland failed: {} (0x{:X})", err, err);
|
m_wl_window = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (surface == EGL_NO_SURFACE)
|
|
||||||
surface = CreateFallbackSurface(config, attribs, m_wl_window, error);
|
|
||||||
|
|
||||||
if (surface == EGL_NO_SURFACE)
|
|
||||||
{
|
|
||||||
m_wl_egl_window_destroy(m_wl_window);
|
|
||||||
m_wl_window = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return surface;
|
return surface;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,8 +20,8 @@ public:
|
||||||
void ResizeSurface(u32 new_surface_width = 0, u32 new_surface_height = 0) override;
|
void ResizeSurface(u32 new_surface_width = 0, u32 new_surface_height = 0) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
EGLDisplay GetPlatformDisplay(const EGLAttrib* attribs, Error* error) override;
|
EGLDisplay GetPlatformDisplay(Error* error) override;
|
||||||
EGLSurface CreatePlatformSurface(EGLConfig config, const EGLAttrib* attribs, Error* error) override;
|
EGLSurface CreatePlatformSurface(EGLConfig config, void* win, Error* error) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool LoadModule(Error* error);
|
bool LoadModule(Error* error);
|
||||||
|
|
|
@ -32,11 +32,22 @@ std::unique_ptr<OpenGLContext> OpenGLContextEGLX11::CreateSharedContext(const Wi
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
EGLDisplay OpenGLContextEGLX11::GetPlatformDisplay(const EGLAttrib* attribs, Error* error)
|
EGLDisplay OpenGLContextEGLX11::GetPlatformDisplay(Error* error)
|
||||||
{
|
{
|
||||||
EGLDisplay dpy = TryGetPlatformDisplay(EGL_PLATFORM_X11_KHR, attribs);
|
EGLDisplay dpy = TryGetPlatformDisplay(EGL_PLATFORM_X11_KHR, "EGL_EXT_platform_x11");
|
||||||
if (dpy == EGL_NO_DISPLAY)
|
if (dpy == EGL_NO_DISPLAY)
|
||||||
dpy = GetFallbackDisplay(error);
|
dpy = GetFallbackDisplay(error);
|
||||||
|
|
||||||
return dpy;
|
return dpy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EGLSurface OpenGLContextEGLX11::CreatePlatformSurface(EGLConfig config, void* win, Error* error)
|
||||||
|
{
|
||||||
|
// This is hideous.. the EXT version requires a pointer to the window, whereas the base
|
||||||
|
// version requires the window itself, casted to void*...
|
||||||
|
EGLSurface surface = TryCreatePlatformSurface(config, &win, error);
|
||||||
|
if (surface == EGL_NO_SURFACE)
|
||||||
|
surface = CreateFallbackSurface(config, win, error);
|
||||||
|
|
||||||
|
return surface;
|
||||||
|
}
|
|
@ -17,5 +17,6 @@ public:
|
||||||
std::unique_ptr<OpenGLContext> CreateSharedContext(const WindowInfo& wi, Error* error) override;
|
std::unique_ptr<OpenGLContext> CreateSharedContext(const WindowInfo& wi, Error* error) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
EGLDisplay GetPlatformDisplay(const EGLAttrib* attribs, Error* error) override;
|
EGLDisplay GetPlatformDisplay(Error* error) override;
|
||||||
|
EGLSurface CreatePlatformSurface(EGLConfig config, void* win, Error* error) override;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue