diff --git a/src/citra_qt/externals/duckstation/duckstation_compat.h b/src/citra_qt/externals/duckstation/duckstation_compat.h index fed378056..9c2caf778 100644 --- a/src/citra_qt/externals/duckstation/duckstation_compat.h +++ b/src/citra_qt/externals/duckstation/duckstation_compat.h @@ -7,7 +7,7 @@ #define ALWAYS_INLINE __attribute__((always_inline)) inline -#define AssertMsg(cond, msg) assert(cond && msg) +#define AssertMsg(cond, msg) assert(cond&& msg) #define Assert(cond) assert(cond) #define Panic(msg) assert(false && msg) diff --git a/src/citra_qt/externals/duckstation/gl/context.cpp b/src/citra_qt/externals/duckstation/gl/context.cpp index 308b3c406..56f03466b 100644 --- a/src/citra_qt/externals/duckstation/gl/context.cpp +++ b/src/citra_qt/externals/duckstation/gl/context.cpp @@ -1,9 +1,9 @@ -#include "context.h" -#include "../log.h" -#include "loader.h" #include #include #include +#include "../log.h" +#include "context.h" +#include "loader.h" Log_SetChannel(GL::Context); #if defined(_WIN32) @@ -20,16 +20,15 @@ Log_SetChannel(GL::Context); namespace GL { -static bool ShouldPreferESContext() -{ +static bool ShouldPreferESContext() { #ifndef _MSC_VER - const char* value = std::getenv("PREFER_GLES_CONTEXT"); - return (value && strcmp(value, "1") == 0); + const char* value = std::getenv("PREFER_GLES_CONTEXT"); + return (value && strcmp(value, "1") == 0); #else - char buffer[2] = {}; - size_t buffer_size = sizeof(buffer); - getenv_s(&buffer_size, buffer, "PREFER_GLES_CONTEXT"); - return (std::strcmp(buffer, "1") == 0); + char buffer[2] = {}; + size_t buffer_size = sizeof(buffer); + getenv_s(&buffer_size, buffer, "PREFER_GLES_CONTEXT"); + return (std::strcmp(buffer, "1") == 0); #endif } @@ -37,139 +36,131 @@ Context::Context(const WindowInfo& wi) : m_wi(wi) {} Context::~Context() = default; -std::vector Context::EnumerateFullscreenModes() -{ - return {}; +std::vector Context::EnumerateFullscreenModes() { + return {}; } std::unique_ptr Context::Create(const WindowInfo& wi, const Version* versions_to_try, - size_t num_versions_to_try) -{ - if (ShouldPreferESContext()) - { - // move ES versions to the front - Version* new_versions_to_try = static_cast(alloca(sizeof(Version) * num_versions_to_try)); - size_t count = 0; - for (size_t i = 0; i < num_versions_to_try; i++) - { - if (versions_to_try[i].profile == Profile::ES) - new_versions_to_try[count++] = versions_to_try[i]; + size_t num_versions_to_try) { + if (ShouldPreferESContext()) { + // move ES versions to the front + Version* new_versions_to_try = + static_cast(alloca(sizeof(Version) * num_versions_to_try)); + size_t count = 0; + for (size_t i = 0; i < num_versions_to_try; i++) { + if (versions_to_try[i].profile == Profile::ES) + new_versions_to_try[count++] = versions_to_try[i]; + } + for (size_t i = 0; i < num_versions_to_try; i++) { + if (versions_to_try[i].profile != Profile::ES) + new_versions_to_try[count++] = versions_to_try[i]; + } + versions_to_try = new_versions_to_try; } - for (size_t i = 0; i < num_versions_to_try; i++) - { - if (versions_to_try[i].profile != Profile::ES) - new_versions_to_try[count++] = versions_to_try[i]; - } - versions_to_try = new_versions_to_try; - } - std::unique_ptr context; + std::unique_ptr context; #if defined(_WIN32) - context = ContextWGL::Create(wi, versions_to_try, num_versions_to_try); + context = ContextWGL::Create(wi, versions_to_try, num_versions_to_try); #elif defined(__APPLE__) - context = ContextAGL::Create(wi, versions_to_try, num_versions_to_try); + context = ContextAGL::Create(wi, versions_to_try, num_versions_to_try); #else - if (wi.type == WindowInfo::Type::X11) - { - const char* use_egl_x11 = std::getenv("USE_EGL_X11"); - if (use_egl_x11 && std::strcmp(use_egl_x11, "1") == 0) - context = ContextEGLX11::Create(wi, versions_to_try, num_versions_to_try); - else - context = ContextGLX::Create(wi, versions_to_try, num_versions_to_try); - } + if (wi.type == WindowInfo::Type::X11) { + const char* use_egl_x11 = std::getenv("USE_EGL_X11"); + if (use_egl_x11 && std::strcmp(use_egl_x11, "1") == 0) + context = ContextEGLX11::Create(wi, versions_to_try, num_versions_to_try); + else + context = ContextGLX::Create(wi, versions_to_try, num_versions_to_try); + } #ifdef WAYLAND_ENABLED - if (wi.type == WindowInfo::Type::Wayland) - context = ContextEGLWayland::Create(wi, versions_to_try, num_versions_to_try); + if (wi.type == WindowInfo::Type::Wayland) + context = ContextEGLWayland::Create(wi, versions_to_try, num_versions_to_try); #endif #endif - if (!context) - return nullptr; + if (!context) + return nullptr; - Log_InfoPrintf("Created a %s context", context->IsGLES() ? "OpenGL ES" : "OpenGL"); + Log_InfoPrintf("Created a %s context", context->IsGLES() ? "OpenGL ES" : "OpenGL"); - // TODO: Not thread-safe. - static Context* context_being_created; - context_being_created = context.get(); + // TODO: Not thread-safe. + static Context* context_being_created; + context_being_created = context.get(); - if (!gladLoadGLLoader([](const char* name) { return context_being_created->GetProcAddress(name); })) - { - Log_ErrorPrintf("Failed to load GL functions for GLAD"); - return nullptr; - } + if (!gladLoadGLLoader( + [](const char* name) { return context_being_created->GetProcAddress(name); })) { + Log_ErrorPrintf("Failed to load GL functions for GLAD"); + return nullptr; + } - const char* gl_vendor = reinterpret_cast(glGetString(GL_VENDOR)); - const char* gl_renderer = reinterpret_cast(glGetString(GL_RENDERER)); - const char* gl_version = reinterpret_cast(glGetString(GL_VERSION)); - const char* gl_shading_language_version = reinterpret_cast(glGetString(GL_SHADING_LANGUAGE_VERSION)); - Log_InfoPrintf("GL_VENDOR: %s", gl_vendor); - Log_InfoPrintf("GL_RENDERER: %s", gl_renderer); - Log_InfoPrintf("GL_VERSION: %s", gl_version); - Log_InfoPrintf("GL_SHADING_LANGUAGE_VERSION: %s", gl_shading_language_version); + const char* gl_vendor = reinterpret_cast(glGetString(GL_VENDOR)); + const char* gl_renderer = reinterpret_cast(glGetString(GL_RENDERER)); + const char* gl_version = reinterpret_cast(glGetString(GL_VERSION)); + const char* gl_shading_language_version = + reinterpret_cast(glGetString(GL_SHADING_LANGUAGE_VERSION)); + Log_InfoPrintf("GL_VENDOR: %s", gl_vendor); + Log_InfoPrintf("GL_RENDERER: %s", gl_renderer); + Log_InfoPrintf("GL_VERSION: %s", gl_version); + Log_InfoPrintf("GL_SHADING_LANGUAGE_VERSION: %s", gl_shading_language_version); - return context; + return context; } -const std::array& Context::GetAllDesktopVersionsList() -{ - static constexpr std::array vlist = {{{Profile::Core, 4, 6}, - {Profile::Core, 4, 5}, - {Profile::Core, 4, 4}, - {Profile::Core, 4, 3}, - {Profile::Core, 4, 2}, - {Profile::Core, 4, 1}, - {Profile::Core, 4, 0}, - {Profile::Core, 3, 3}, - {Profile::Core, 3, 2}, - {Profile::Core, 3, 1}, - {Profile::Core, 3, 0}}}; - return vlist; +const std::array& Context::GetAllDesktopVersionsList() { + static constexpr std::array vlist = {{{Profile::Core, 4, 6}, + {Profile::Core, 4, 5}, + {Profile::Core, 4, 4}, + {Profile::Core, 4, 3}, + {Profile::Core, 4, 2}, + {Profile::Core, 4, 1}, + {Profile::Core, 4, 0}, + {Profile::Core, 3, 3}, + {Profile::Core, 3, 2}, + {Profile::Core, 3, 1}, + {Profile::Core, 3, 0}}}; + return vlist; } -const std::array& Context::GetAllDesktopVersionsListWithFallback() -{ - static constexpr std::array vlist = {{{Profile::Core, 4, 6}, - {Profile::Core, 4, 5}, - {Profile::Core, 4, 4}, - {Profile::Core, 4, 3}, - {Profile::Core, 4, 2}, - {Profile::Core, 4, 1}, - {Profile::Core, 4, 0}, - {Profile::Core, 3, 3}, - {Profile::Core, 3, 2}, - {Profile::Core, 3, 1}, - {Profile::Core, 3, 0}, - {Profile::NoProfile, 0, 0}}}; - return vlist; +const std::array& Context::GetAllDesktopVersionsListWithFallback() { + static constexpr std::array vlist = {{{Profile::Core, 4, 6}, + {Profile::Core, 4, 5}, + {Profile::Core, 4, 4}, + {Profile::Core, 4, 3}, + {Profile::Core, 4, 2}, + {Profile::Core, 4, 1}, + {Profile::Core, 4, 0}, + {Profile::Core, 3, 3}, + {Profile::Core, 3, 2}, + {Profile::Core, 3, 1}, + {Profile::Core, 3, 0}, + {Profile::NoProfile, 0, 0}}}; + return vlist; } -const std::array& Context::GetAllESVersionsList() -{ - static constexpr std::array vlist = { - {{Profile::ES, 3, 2}, {Profile::ES, 3, 1}, {Profile::ES, 3, 0}, {Profile::ES, 2, 0}}}; - return vlist; +const std::array& Context::GetAllESVersionsList() { + static constexpr std::array vlist = { + {{Profile::ES, 3, 2}, {Profile::ES, 3, 1}, {Profile::ES, 3, 0}, {Profile::ES, 2, 0}}}; + return vlist; } -const std::array& Context::GetAllVersionsList() -{ - static constexpr std::array vlist = {{{Profile::Core, 4, 6}, - {Profile::Core, 4, 5}, - {Profile::Core, 4, 4}, - {Profile::Core, 4, 3}, - {Profile::Core, 4, 2}, - {Profile::Core, 4, 1}, - {Profile::Core, 4, 0}, - {Profile::Core, 3, 3}, - {Profile::Core, 3, 2}, - {Profile::Core, 3, 1}, - {Profile::Core, 3, 0}, - {Profile::ES, 3, 2}, - {Profile::ES, 3, 1}, - {Profile::ES, 3, 0}, - {Profile::ES, 2, 0}, - {Profile::NoProfile, 0, 0}}}; - return vlist; +const std::array& Context::GetAllVersionsList() { + static constexpr std::array vlist = {{{Profile::Core, 4, 6}, + {Profile::Core, 4, 5}, + {Profile::Core, 4, 4}, + {Profile::Core, 4, 3}, + {Profile::Core, 4, 2}, + {Profile::Core, 4, 1}, + {Profile::Core, 4, 0}, + {Profile::Core, 3, 3}, + {Profile::Core, 3, 2}, + {Profile::Core, 3, 1}, + {Profile::Core, 3, 0}, + {Profile::ES, 3, 2}, + {Profile::ES, 3, 1}, + {Profile::ES, 3, 0}, + {Profile::ES, 2, 0}, + {Profile::NoProfile, 0, 0}}}; + return vlist; } } // namespace GL diff --git a/src/citra_qt/externals/duckstation/gl/context.h b/src/citra_qt/externals/duckstation/gl/context.h index 09c73e660..a77c99e3b 100644 --- a/src/citra_qt/externals/duckstation/gl/context.h +++ b/src/citra_qt/externals/duckstation/gl/context.h @@ -1,77 +1,81 @@ #pragma once -#include "../duckstation_compat.h" -#include "../window_info.h" #include #include #include +#include "../duckstation_compat.h" +#include "../window_info.h" namespace GL { using namespace citra; -class Context -{ +class Context { public: - Context(const WindowInfo& wi); - virtual ~Context(); + Context(const WindowInfo& wi); + virtual ~Context(); - enum class Profile - { - NoProfile, - Core, - ES - }; + enum class Profile { NoProfile, Core, ES }; - struct Version - { - Profile profile; - int major_version; - int minor_version; - }; + struct Version { + Profile profile; + int major_version; + int minor_version; + }; - struct FullscreenModeInfo - { - u32 width; - u32 height; - float refresh_rate; - }; + struct FullscreenModeInfo { + u32 width; + u32 height; + float refresh_rate; + }; - ALWAYS_INLINE const WindowInfo& GetWindowInfo() const { return m_wi; } - ALWAYS_INLINE bool IsGLES() const { return (m_version.profile == Profile::ES); } - ALWAYS_INLINE u32 GetSurfaceWidth() const { return m_wi.surface_width; } - ALWAYS_INLINE u32 GetSurfaceHeight() const { return m_wi.surface_height; } - ALWAYS_INLINE WindowInfo::SurfaceFormat GetSurfaceFormat() const { return m_wi.surface_format; } + ALWAYS_INLINE const WindowInfo& GetWindowInfo() const { + return m_wi; + } + ALWAYS_INLINE bool IsGLES() const { + return (m_version.profile == Profile::ES); + } + ALWAYS_INLINE u32 GetSurfaceWidth() const { + return m_wi.surface_width; + } + ALWAYS_INLINE u32 GetSurfaceHeight() const { + return m_wi.surface_height; + } + ALWAYS_INLINE WindowInfo::SurfaceFormat GetSurfaceFormat() const { + return m_wi.surface_format; + } - virtual void* GetProcAddress(const char* name) = 0; - virtual bool ChangeSurface(const WindowInfo& new_wi) = 0; - virtual void ResizeSurface(u32 new_surface_width = 0, u32 new_surface_height = 0) = 0; - virtual bool SwapBuffers() = 0; - virtual bool MakeCurrent() = 0; - virtual bool DoneCurrent() = 0; - virtual bool SetSwapInterval(s32 interval) = 0; - virtual std::unique_ptr CreateSharedContext(const WindowInfo& wi) = 0; + virtual void* GetProcAddress(const char* name) = 0; + virtual bool ChangeSurface(const WindowInfo& new_wi) = 0; + virtual void ResizeSurface(u32 new_surface_width = 0, u32 new_surface_height = 0) = 0; + virtual bool SwapBuffers() = 0; + virtual bool MakeCurrent() = 0; + virtual bool DoneCurrent() = 0; + virtual bool SetSwapInterval(s32 interval) = 0; + virtual std::unique_ptr CreateSharedContext(const WindowInfo& wi) = 0; - virtual std::vector EnumerateFullscreenModes(); + virtual std::vector EnumerateFullscreenModes(); - static std::unique_ptr Create(const WindowInfo& wi, const Version* versions_to_try, - size_t num_versions_to_try); + static std::unique_ptr Create(const WindowInfo& wi, const Version* versions_to_try, + size_t num_versions_to_try); - template - static std::unique_ptr Create(const WindowInfo& wi, const std::array& versions_to_try) - { - return Create(wi, versions_to_try.data(), versions_to_try.size()); - } + template + static std::unique_ptr Create(const WindowInfo& wi, + const std::array& versions_to_try) { + return Create(wi, versions_to_try.data(), versions_to_try.size()); + } - static std::unique_ptr Create(const WindowInfo& wi) { return Create(wi, GetAllVersionsList()); } + static std::unique_ptr Create(const WindowInfo& wi) { + return Create(wi, GetAllVersionsList()); + } - static const std::array& GetAllDesktopVersionsList(); - static const std::array& GetAllDesktopVersionsListWithFallback(); - static const std::array& GetAllESVersionsList(); - static const std::array& GetAllVersionsList(); + static const std::array& GetAllDesktopVersionsList(); + static const std::array& GetAllDesktopVersionsListWithFallback(); + static const std::array& GetAllESVersionsList(); + static const std::array& GetAllVersionsList(); protected: #ifdef _WIN32 #endif - WindowInfo m_wi; - Version m_version = {}; + WindowInfo m_wi; + Version m_version = {}; }; } // namespace GL diff --git a/src/citra_qt/externals/duckstation/gl/context_agl.h b/src/citra_qt/externals/duckstation/gl/context_agl.h index 4ae5202d8..af36a1234 100644 --- a/src/citra_qt/externals/duckstation/gl/context_agl.h +++ b/src/citra_qt/externals/duckstation/gl/context_agl.h @@ -14,37 +14,38 @@ struct NSView; namespace GL { using namespace melonDS; -class ContextAGL final : public Context -{ +class ContextAGL final : public Context { public: - ContextAGL(const WindowInfo& wi); - ~ContextAGL() override; + ContextAGL(const WindowInfo& wi); + ~ContextAGL() override; - static std::unique_ptr Create(const WindowInfo& wi, const Version* versions_to_try, - size_t num_versions_to_try); + static std::unique_ptr Create(const WindowInfo& wi, const Version* versions_to_try, + size_t num_versions_to_try); - void* GetProcAddress(const char* name) override; - bool ChangeSurface(const WindowInfo& new_wi) override; - void ResizeSurface(u32 new_surface_width = 0, u32 new_surface_height = 0) override; - bool SwapBuffers() override; - bool MakeCurrent() override; - bool DoneCurrent() override; - bool SetSwapInterval(s32 interval) override; - std::unique_ptr CreateSharedContext(const WindowInfo& wi) override; + void* GetProcAddress(const char* name) override; + bool ChangeSurface(const WindowInfo& new_wi) override; + void ResizeSurface(u32 new_surface_width = 0, u32 new_surface_height = 0) override; + bool SwapBuffers() override; + bool MakeCurrent() override; + bool DoneCurrent() override; + bool SetSwapInterval(s32 interval) override; + std::unique_ptr CreateSharedContext(const WindowInfo& wi) override; private: - ALWAYS_INLINE NSView* GetView() const { return static_cast((__bridge NSView*)m_wi.window_handle); } + ALWAYS_INLINE NSView* GetView() const { + return static_cast((__bridge NSView*)m_wi.window_handle); + } - bool Initialize(const Version* versions_to_try, size_t num_versions_to_try); - bool CreateContext(NSOpenGLContext* share_context, int profile, bool make_current); - void BindContextToView(); + bool Initialize(const Version* versions_to_try, size_t num_versions_to_try); + bool CreateContext(NSOpenGLContext* share_context, int profile, bool make_current); + void BindContextToView(); - // returns true if dimensions have changed - bool UpdateDimensions(); + // returns true if dimensions have changed + bool UpdateDimensions(); - NSOpenGLContext* m_context = nullptr; - NSOpenGLPixelFormat* m_pixel_format = nullptr; - void* m_opengl_module_handle = nullptr; + NSOpenGLContext* m_context = nullptr; + NSOpenGLPixelFormat* m_pixel_format = nullptr; + void* m_opengl_module_handle = nullptr; }; } // namespace GL diff --git a/src/citra_qt/externals/duckstation/gl/context_egl.cpp b/src/citra_qt/externals/duckstation/gl/context_egl.cpp index d251a39cd..4d0a9cb3a 100644 --- a/src/citra_qt/externals/duckstation/gl/context_egl.cpp +++ b/src/citra_qt/externals/duckstation/gl/context_egl.cpp @@ -1,432 +1,386 @@ -#include "context_egl.h" -#include "../log.h" -#include "../duckstation_compat.h" +#include #include #include -#include +#include "../duckstation_compat.h" +#include "../log.h" +#include "context_egl.h" Log_SetChannel(GL::ContextEGL); namespace GL { ContextEGL::ContextEGL(const WindowInfo& wi) : Context(wi) {} -ContextEGL::~ContextEGL() -{ - DestroySurface(); - DestroyContext(); +ContextEGL::~ContextEGL() { + DestroySurface(); + DestroyContext(); } std::unique_ptr ContextEGL::Create(const WindowInfo& wi, const Version* versions_to_try, - size_t num_versions_to_try) -{ - std::unique_ptr context = std::make_unique(wi); - if (!context->Initialize(versions_to_try, num_versions_to_try)) - return nullptr; + size_t num_versions_to_try) { + std::unique_ptr context = std::make_unique(wi); + if (!context->Initialize(versions_to_try, num_versions_to_try)) + return nullptr; - return context; + return context; } -bool ContextEGL::Initialize(const Version* versions_to_try, size_t num_versions_to_try) -{ - if (!gladLoadEGL()) - { - Log_ErrorPrintf("Loading GLAD EGL functions failed"); +bool ContextEGL::Initialize(const Version* versions_to_try, size_t num_versions_to_try) { + if (!gladLoadEGL()) { + Log_ErrorPrintf("Loading GLAD EGL functions failed"); + return false; + } + + if (!SetDisplay()) + return false; + + int egl_major, egl_minor; + if (!eglInitialize(m_display, &egl_major, &egl_minor)) { + Log_ErrorPrintf("eglInitialize() failed: %d", eglGetError()); + return false; + } + Log_InfoPrintf("EGL Version: %d.%d", egl_major, egl_minor); + + const char* extensions = eglQueryString(m_display, EGL_EXTENSIONS); + if (extensions) { + Log_InfoPrintf("EGL Extensions: %s", extensions); + m_supports_surfaceless = std::strstr(extensions, "EGL_KHR_surfaceless_context") != nullptr; + } + if (!m_supports_surfaceless) + Log_WarningPrint( + "EGL implementation does not support surfaceless contexts, emulating with pbuffers"); + + for (size_t i = 0; i < num_versions_to_try; i++) { + if (CreateContextAndSurface(versions_to_try[i], nullptr, true)) + return true; + } + return false; - } - - if (!SetDisplay()) - return false; - - int egl_major, egl_minor; - if (!eglInitialize(m_display, &egl_major, &egl_minor)) - { - Log_ErrorPrintf("eglInitialize() failed: %d", eglGetError()); - return false; - } - Log_InfoPrintf("EGL Version: %d.%d", egl_major, egl_minor); - - const char* extensions = eglQueryString(m_display, EGL_EXTENSIONS); - if (extensions) - { - Log_InfoPrintf("EGL Extensions: %s", extensions); - m_supports_surfaceless = std::strstr(extensions, "EGL_KHR_surfaceless_context") != nullptr; - } - if (!m_supports_surfaceless) - Log_WarningPrint("EGL implementation does not support surfaceless contexts, emulating with pbuffers"); - - for (size_t i = 0; i < num_versions_to_try; i++) - { - if (CreateContextAndSurface(versions_to_try[i], nullptr, true)) - return true; - } - - return false; } -bool ContextEGL::SetDisplay() -{ - m_display = eglGetDisplay(static_cast(m_wi.display_connection)); - if (!m_display) - { - Log_ErrorPrintf("eglGetDisplay() failed: %d", eglGetError()); - return false; - } +bool ContextEGL::SetDisplay() { + m_display = eglGetDisplay(static_cast(m_wi.display_connection)); + if (!m_display) { + Log_ErrorPrintf("eglGetDisplay() failed: %d", eglGetError()); + return false; + } - return true; + return true; } -void* ContextEGL::GetProcAddress(const char* name) -{ - return reinterpret_cast(eglGetProcAddress(name)); +void* ContextEGL::GetProcAddress(const char* name) { + return reinterpret_cast(eglGetProcAddress(name)); } -bool ContextEGL::ChangeSurface(const WindowInfo& new_wi) -{ - const bool was_current = (eglGetCurrentContext() == m_context); - if (was_current) - eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); +bool ContextEGL::ChangeSurface(const WindowInfo& new_wi) { + const bool was_current = (eglGetCurrentContext() == m_context); + if (was_current) + eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - if (m_surface != EGL_NO_SURFACE) - { - eglDestroySurface(m_display, m_surface); - m_surface = EGL_NO_SURFACE; - } + if (m_surface != EGL_NO_SURFACE) { + eglDestroySurface(m_display, m_surface); + m_surface = EGL_NO_SURFACE; + } - m_wi = new_wi; - if (!CreateSurface()) - return false; + m_wi = new_wi; + if (!CreateSurface()) + return false; - if (was_current && !eglMakeCurrent(m_display, m_surface, m_surface, m_context)) - { - Log_ErrorPrintf("Failed to make context current again after surface change"); - return false; - } + if (was_current && !eglMakeCurrent(m_display, m_surface, m_surface, m_context)) { + Log_ErrorPrintf("Failed to make context current again after surface change"); + return false; + } - return true; + return true; } -void ContextEGL::ResizeSurface(u32 new_surface_width /*= 0*/, u32 new_surface_height /*= 0*/) -{ - if (new_surface_width == 0 && new_surface_height == 0) - { +void ContextEGL::ResizeSurface(u32 new_surface_width /*= 0*/, u32 new_surface_height /*= 0*/) { + if (new_surface_width == 0 && new_surface_height == 0) { + EGLint surface_width, surface_height; + if (eglQuerySurface(m_display, m_surface, EGL_WIDTH, &surface_width) && + eglQuerySurface(m_display, m_surface, EGL_HEIGHT, &surface_height)) { + m_wi.surface_width = static_cast(surface_width); + m_wi.surface_height = static_cast(surface_height); + return; + } else { + Log_ErrorPrintf("eglQuerySurface() failed: %d", eglGetError()); + } + } + + m_wi.surface_width = new_surface_width; + m_wi.surface_height = new_surface_height; +} + +bool ContextEGL::SwapBuffers() { + return eglSwapBuffers(m_display, m_surface); +} + +bool ContextEGL::MakeCurrent() { + if (!eglMakeCurrent(m_display, m_surface, m_surface, m_context)) { + Log_ErrorPrintf("eglMakeCurrent() failed: %d", eglGetError()); + return false; + } + + return true; +} + +bool ContextEGL::DoneCurrent() { + return eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); +} + +bool ContextEGL::SetSwapInterval(s32 interval) { + return eglSwapInterval(m_display, interval); +} + +std::unique_ptr ContextEGL::CreateSharedContext(const WindowInfo& wi) { + std::unique_ptr context = std::make_unique(wi); + context->m_display = m_display; + context->m_supports_surfaceless = m_supports_surfaceless; + + if (!context->CreateContextAndSurface(m_version, m_context, false)) + return nullptr; + + return context; +} + +EGLNativeWindowType ContextEGL::GetNativeWindow(EGLConfig config) { + return {}; +} + +bool ContextEGL::CreateSurface() { + if (m_wi.type == WindowInfo::Type::Surfaceless) { + if (m_supports_surfaceless) + return true; + else + return CreatePBufferSurface(); + } + + EGLNativeWindowType native_window = GetNativeWindow(m_config); + m_surface = eglCreateWindowSurface(m_display, m_config, native_window, nullptr); + if (!m_surface) { + Log_ErrorPrintf("eglCreateWindowSurface() failed: %d", eglGetError()); + return false; + } + + // Some implementations may require the size to be queried at runtime. EGLint surface_width, surface_height; if (eglQuerySurface(m_display, m_surface, EGL_WIDTH, &surface_width) && - eglQuerySurface(m_display, m_surface, EGL_HEIGHT, &surface_height)) - { - m_wi.surface_width = static_cast(surface_width); - m_wi.surface_height = static_cast(surface_height); - return; + eglQuerySurface(m_display, m_surface, EGL_HEIGHT, &surface_height)) { + m_wi.surface_width = static_cast(surface_width); + m_wi.surface_height = static_cast(surface_height); + } else { + Log_ErrorPrintf("eglQuerySurface() failed: %d", eglGetError()); } - else - { - Log_ErrorPrintf("eglQuerySurface() failed: %d", eglGetError()); + + return true; +} + +bool ContextEGL::CreatePBufferSurface() { + const u32 width = std::max(m_wi.surface_width, 1); + const u32 height = std::max(m_wi.surface_height, 1); + + // TODO: Format + EGLint attrib_list[] = { + EGL_WIDTH, static_cast(width), EGL_HEIGHT, static_cast(height), EGL_NONE, + }; + + m_surface = eglCreatePbufferSurface(m_display, m_config, attrib_list); + if (!m_surface) { + Log_ErrorPrintf("eglCreatePbufferSurface() failed: %d", eglGetError()); + return false; } - } - m_wi.surface_width = new_surface_width; - m_wi.surface_height = new_surface_height; + Log_DevPrintf("Created %ux%u pbuffer surface", width, height); + return true; } -bool ContextEGL::SwapBuffers() -{ - return eglSwapBuffers(m_display, m_surface); -} +bool ContextEGL::CheckConfigSurfaceFormat(EGLConfig config, + WindowInfo::SurfaceFormat format) const { + int red_size, green_size, blue_size, alpha_size; + if (!eglGetConfigAttrib(m_display, config, EGL_RED_SIZE, &red_size) || + !eglGetConfigAttrib(m_display, config, EGL_GREEN_SIZE, &green_size) || + !eglGetConfigAttrib(m_display, config, EGL_BLUE_SIZE, &blue_size) || + !eglGetConfigAttrib(m_display, config, EGL_ALPHA_SIZE, &alpha_size)) { + return false; + } -bool ContextEGL::MakeCurrent() -{ - if (!eglMakeCurrent(m_display, m_surface, m_surface, m_context)) - { - Log_ErrorPrintf("eglMakeCurrent() failed: %d", eglGetError()); - return false; - } - - return true; -} - -bool ContextEGL::DoneCurrent() -{ - return eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); -} - -bool ContextEGL::SetSwapInterval(s32 interval) -{ - return eglSwapInterval(m_display, interval); -} - -std::unique_ptr ContextEGL::CreateSharedContext(const WindowInfo& wi) -{ - std::unique_ptr context = std::make_unique(wi); - context->m_display = m_display; - context->m_supports_surfaceless = m_supports_surfaceless; - - if (!context->CreateContextAndSurface(m_version, m_context, false)) - return nullptr; - - return context; -} - -EGLNativeWindowType ContextEGL::GetNativeWindow(EGLConfig config) -{ - return {}; -} - -bool ContextEGL::CreateSurface() -{ - if (m_wi.type == WindowInfo::Type::Surfaceless) - { - if (m_supports_surfaceless) - return true; - else - return CreatePBufferSurface(); - } - - EGLNativeWindowType native_window = GetNativeWindow(m_config); - m_surface = eglCreateWindowSurface(m_display, m_config, native_window, nullptr); - if (!m_surface) - { - Log_ErrorPrintf("eglCreateWindowSurface() failed: %d", eglGetError()); - return false; - } - - // Some implementations may require the size to be queried at runtime. - EGLint surface_width, surface_height; - if (eglQuerySurface(m_display, m_surface, EGL_WIDTH, &surface_width) && - eglQuerySurface(m_display, m_surface, EGL_HEIGHT, &surface_height)) - { - m_wi.surface_width = static_cast(surface_width); - m_wi.surface_height = static_cast(surface_height); - } - else - { - Log_ErrorPrintf("eglQuerySurface() failed: %d", eglGetError()); - } - - return true; -} - -bool ContextEGL::CreatePBufferSurface() -{ - const u32 width = std::max(m_wi.surface_width, 1); - const u32 height = std::max(m_wi.surface_height, 1); - - // TODO: Format - EGLint attrib_list[] = { - EGL_WIDTH, static_cast(width), EGL_HEIGHT, static_cast(height), EGL_NONE, - }; - - m_surface = eglCreatePbufferSurface(m_display, m_config, attrib_list); - if (!m_surface) - { - Log_ErrorPrintf("eglCreatePbufferSurface() failed: %d", eglGetError()); - return false; - } - - Log_DevPrintf("Created %ux%u pbuffer surface", width, height); - return true; -} - -bool ContextEGL::CheckConfigSurfaceFormat(EGLConfig config, WindowInfo::SurfaceFormat format) const -{ - int red_size, green_size, blue_size, alpha_size; - if (!eglGetConfigAttrib(m_display, config, EGL_RED_SIZE, &red_size) || - !eglGetConfigAttrib(m_display, config, EGL_GREEN_SIZE, &green_size) || - !eglGetConfigAttrib(m_display, config, EGL_BLUE_SIZE, &blue_size) || - !eglGetConfigAttrib(m_display, config, EGL_ALPHA_SIZE, &alpha_size)) - { - return false; - } - - switch (format) - { + switch (format) { case WindowInfo::SurfaceFormat::Auto: - return true; + return true; case WindowInfo::SurfaceFormat::RGB8: - return (red_size == 8 && green_size == 8 && blue_size == 8); + return (red_size == 8 && green_size == 8 && blue_size == 8); case WindowInfo::SurfaceFormat::RGBA8: - return (red_size == 8 && green_size == 8 && blue_size == 8 && alpha_size == 8); + return (red_size == 8 && green_size == 8 && blue_size == 8 && alpha_size == 8); case WindowInfo::SurfaceFormat::RGB565: - return (red_size == 5 && green_size == 6 && blue_size == 5); + return (red_size == 5 && green_size == 6 && blue_size == 5); default: - return false; - } + return false; + } } -void ContextEGL::DestroyContext() -{ - if (eglGetCurrentContext() == m_context) - eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); +void ContextEGL::DestroyContext() { + if (eglGetCurrentContext() == m_context) + eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - if (m_context != EGL_NO_CONTEXT) - { - eglDestroyContext(m_display, m_context); - m_context = EGL_NO_CONTEXT; - } + if (m_context != EGL_NO_CONTEXT) { + eglDestroyContext(m_display, m_context); + m_context = EGL_NO_CONTEXT; + } } -void ContextEGL::DestroySurface() -{ - if (eglGetCurrentSurface(EGL_DRAW) == m_surface) - eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); +void ContextEGL::DestroySurface() { + if (eglGetCurrentSurface(EGL_DRAW) == m_surface) + eglMakeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - if (m_surface != EGL_NO_SURFACE) - { - eglDestroySurface(m_display, m_surface); - m_surface = EGL_NO_SURFACE; - } + if (m_surface != EGL_NO_SURFACE) { + eglDestroySurface(m_display, m_surface); + m_surface = EGL_NO_SURFACE; + } } -bool ContextEGL::CreateContext(const Version& version, EGLContext share_context) -{ - Log_DevPrintf( - "Trying version %u.%u (%s)", version.major_version, version.minor_version, - version.profile == Context::Profile::ES ? "ES" : (version.profile == Context::Profile::Core ? "Core" : "None")); - int surface_attribs[16] = { - EGL_RENDERABLE_TYPE, - (version.profile == Profile::ES) ? - ((version.major_version >= 3) ? EGL_OPENGL_ES3_BIT : - ((version.major_version == 2) ? EGL_OPENGL_ES2_BIT : EGL_OPENGL_ES_BIT)) : - EGL_OPENGL_BIT, - EGL_SURFACE_TYPE, - (m_wi.type != WindowInfo::Type::Surfaceless) ? EGL_WINDOW_BIT : 0, - }; - int nsurface_attribs = 4; +bool ContextEGL::CreateContext(const Version& version, EGLContext share_context) { + Log_DevPrintf("Trying version %u.%u (%s)", version.major_version, version.minor_version, + version.profile == Context::Profile::ES + ? "ES" + : (version.profile == Context::Profile::Core ? "Core" : "None")); + int surface_attribs[16] = { + EGL_RENDERABLE_TYPE, + (version.profile == Profile::ES) + ? ((version.major_version >= 3) + ? EGL_OPENGL_ES3_BIT + : ((version.major_version == 2) ? EGL_OPENGL_ES2_BIT : EGL_OPENGL_ES_BIT)) + : EGL_OPENGL_BIT, + EGL_SURFACE_TYPE, + (m_wi.type != WindowInfo::Type::Surfaceless) ? EGL_WINDOW_BIT : 0, + }; + int nsurface_attribs = 4; - switch (m_wi.surface_format) - { + switch (m_wi.surface_format) { case WindowInfo::SurfaceFormat::RGB8: - surface_attribs[nsurface_attribs++] = EGL_RED_SIZE; - surface_attribs[nsurface_attribs++] = 8; - surface_attribs[nsurface_attribs++] = EGL_GREEN_SIZE; - surface_attribs[nsurface_attribs++] = 8; - surface_attribs[nsurface_attribs++] = EGL_BLUE_SIZE; - surface_attribs[nsurface_attribs++] = 8; - break; + surface_attribs[nsurface_attribs++] = EGL_RED_SIZE; + surface_attribs[nsurface_attribs++] = 8; + surface_attribs[nsurface_attribs++] = EGL_GREEN_SIZE; + surface_attribs[nsurface_attribs++] = 8; + surface_attribs[nsurface_attribs++] = EGL_BLUE_SIZE; + surface_attribs[nsurface_attribs++] = 8; + break; case WindowInfo::SurfaceFormat::RGBA8: - surface_attribs[nsurface_attribs++] = EGL_RED_SIZE; - surface_attribs[nsurface_attribs++] = 8; - surface_attribs[nsurface_attribs++] = EGL_GREEN_SIZE; - surface_attribs[nsurface_attribs++] = 8; - surface_attribs[nsurface_attribs++] = EGL_BLUE_SIZE; - surface_attribs[nsurface_attribs++] = 8; - surface_attribs[nsurface_attribs++] = EGL_ALPHA_SIZE; - surface_attribs[nsurface_attribs++] = 8; - break; + surface_attribs[nsurface_attribs++] = EGL_RED_SIZE; + surface_attribs[nsurface_attribs++] = 8; + surface_attribs[nsurface_attribs++] = EGL_GREEN_SIZE; + surface_attribs[nsurface_attribs++] = 8; + surface_attribs[nsurface_attribs++] = EGL_BLUE_SIZE; + surface_attribs[nsurface_attribs++] = 8; + surface_attribs[nsurface_attribs++] = EGL_ALPHA_SIZE; + surface_attribs[nsurface_attribs++] = 8; + break; case WindowInfo::SurfaceFormat::RGB565: - surface_attribs[nsurface_attribs++] = EGL_RED_SIZE; - surface_attribs[nsurface_attribs++] = 5; - surface_attribs[nsurface_attribs++] = EGL_GREEN_SIZE; - surface_attribs[nsurface_attribs++] = 6; - surface_attribs[nsurface_attribs++] = EGL_BLUE_SIZE; - surface_attribs[nsurface_attribs++] = 5; - break; + surface_attribs[nsurface_attribs++] = EGL_RED_SIZE; + surface_attribs[nsurface_attribs++] = 5; + surface_attribs[nsurface_attribs++] = EGL_GREEN_SIZE; + surface_attribs[nsurface_attribs++] = 6; + surface_attribs[nsurface_attribs++] = EGL_BLUE_SIZE; + surface_attribs[nsurface_attribs++] = 5; + break; case WindowInfo::SurfaceFormat::Auto: - break; + break; default: - UnreachableCode(); - break; - } - - surface_attribs[nsurface_attribs++] = EGL_NONE; - surface_attribs[nsurface_attribs++] = 0; - - EGLint num_configs; - if (!eglChooseConfig(m_display, surface_attribs, nullptr, 0, &num_configs) || num_configs == 0) - { - Log_ErrorPrintf("eglChooseConfig() failed: %d", eglGetError()); - return false; - } - - std::vector configs(static_cast(num_configs)); - if (!eglChooseConfig(m_display, surface_attribs, configs.data(), num_configs, &num_configs)) - { - Log_ErrorPrintf("eglChooseConfig() failed: %d", eglGetError()); - return false; - } - configs.resize(static_cast(num_configs)); - - std::optional config; - for (EGLConfig check_config : configs) - { - if (CheckConfigSurfaceFormat(check_config, m_wi.surface_format)) - { - config = check_config; - break; + UnreachableCode(); + break; } - } - if (!config.has_value()) - { - Log_WarningPrintf("No EGL configs matched exactly, using first."); - config = configs.front(); - } + surface_attribs[nsurface_attribs++] = EGL_NONE; + surface_attribs[nsurface_attribs++] = 0; - int attribs[8]; - int nattribs = 0; - if (version.profile != Profile::NoProfile) - { - attribs[nattribs++] = EGL_CONTEXT_MAJOR_VERSION; - attribs[nattribs++] = version.major_version; - attribs[nattribs++] = EGL_CONTEXT_MINOR_VERSION; - attribs[nattribs++] = version.minor_version; - } - attribs[nattribs++] = EGL_NONE; - attribs[nattribs++] = 0; + EGLint num_configs; + if (!eglChooseConfig(m_display, surface_attribs, nullptr, 0, &num_configs) || + num_configs == 0) { + Log_ErrorPrintf("eglChooseConfig() failed: %d", eglGetError()); + return false; + } - if (!eglBindAPI((version.profile == Profile::ES) ? EGL_OPENGL_ES_API : EGL_OPENGL_API)) - { - Log_ErrorPrintf("eglBindAPI(%s) failed", (version.profile == Profile::ES) ? "EGL_OPENGL_ES_API" : "EGL_OPENGL_API"); - return false; - } + std::vector configs(static_cast(num_configs)); + if (!eglChooseConfig(m_display, surface_attribs, configs.data(), num_configs, &num_configs)) { + Log_ErrorPrintf("eglChooseConfig() failed: %d", eglGetError()); + return false; + } + configs.resize(static_cast(num_configs)); - m_context = eglCreateContext(m_display, config.value(), share_context, attribs); - if (!m_context) - { - Log_ErrorPrintf("eglCreateContext() failed: %d", eglGetError()); - return false; - } + std::optional config; + for (EGLConfig check_config : configs) { + if (CheckConfigSurfaceFormat(check_config, m_wi.surface_format)) { + config = check_config; + break; + } + } - Log_InfoPrintf( - "Got version %u.%u (%s)", version.major_version, version.minor_version, - version.profile == Context::Profile::ES ? "ES" : (version.profile == Context::Profile::Core ? "Core" : "None")); + if (!config.has_value()) { + Log_WarningPrintf("No EGL configs matched exactly, using first."); + config = configs.front(); + } - m_config = config.value(); - m_version = version; - return true; + int attribs[8]; + int nattribs = 0; + if (version.profile != Profile::NoProfile) { + attribs[nattribs++] = EGL_CONTEXT_MAJOR_VERSION; + attribs[nattribs++] = version.major_version; + attribs[nattribs++] = EGL_CONTEXT_MINOR_VERSION; + attribs[nattribs++] = version.minor_version; + } + attribs[nattribs++] = EGL_NONE; + attribs[nattribs++] = 0; + + if (!eglBindAPI((version.profile == Profile::ES) ? EGL_OPENGL_ES_API : EGL_OPENGL_API)) { + Log_ErrorPrintf("eglBindAPI(%s) failed", + (version.profile == Profile::ES) ? "EGL_OPENGL_ES_API" : "EGL_OPENGL_API"); + return false; + } + + m_context = eglCreateContext(m_display, config.value(), share_context, attribs); + if (!m_context) { + Log_ErrorPrintf("eglCreateContext() failed: %d", eglGetError()); + return false; + } + + Log_InfoPrintf("Got version %u.%u (%s)", version.major_version, version.minor_version, + version.profile == Context::Profile::ES + ? "ES" + : (version.profile == Context::Profile::Core ? "Core" : "None")); + + m_config = config.value(); + m_version = version; + return true; } -bool ContextEGL::CreateContextAndSurface(const Version& version, EGLContext share_context, bool make_current) -{ - if (!CreateContext(version, share_context)) - return false; +bool ContextEGL::CreateContextAndSurface(const Version& version, EGLContext share_context, + bool make_current) { + if (!CreateContext(version, share_context)) + return false; - if (!CreateSurface()) - { - Log_ErrorPrintf("Failed to create surface for context"); - eglDestroyContext(m_display, m_context); - m_context = EGL_NO_CONTEXT; - return false; - } - - if (make_current && !eglMakeCurrent(m_display, m_surface, m_surface, m_context)) - { - Log_ErrorPrintf("eglMakeCurrent() failed: %d", eglGetError()); - if (m_surface != EGL_NO_SURFACE) - { - eglDestroySurface(m_display, m_surface); - m_surface = EGL_NO_SURFACE; + if (!CreateSurface()) { + Log_ErrorPrintf("Failed to create surface for context"); + eglDestroyContext(m_display, m_context); + m_context = EGL_NO_CONTEXT; + return false; } - eglDestroyContext(m_display, m_context); - m_context = EGL_NO_CONTEXT; - return false; - } - return true; + if (make_current && !eglMakeCurrent(m_display, m_surface, m_surface, m_context)) { + Log_ErrorPrintf("eglMakeCurrent() failed: %d", eglGetError()); + if (m_surface != EGL_NO_SURFACE) { + eglDestroySurface(m_display, m_surface); + m_surface = EGL_NO_SURFACE; + } + eglDestroyContext(m_display, m_context); + m_context = EGL_NO_CONTEXT; + return false; + } + + return true; } } // namespace GL diff --git a/src/citra_qt/externals/duckstation/gl/context_egl.h b/src/citra_qt/externals/duckstation/gl/context_egl.h index 4462736ac..cf19a8991 100644 --- a/src/citra_qt/externals/duckstation/gl/context_egl.h +++ b/src/citra_qt/externals/duckstation/gl/context_egl.h @@ -1,48 +1,48 @@ #pragma once -#include "context.h" #include "../../../../../externals/glad/src/glad_egl.h" +#include "context.h" namespace GL { -class ContextEGL : public Context -{ +class ContextEGL : public Context { public: - ContextEGL(const WindowInfo& wi); - ~ContextEGL() override; + ContextEGL(const WindowInfo& wi); + ~ContextEGL() override; - static std::unique_ptr Create(const WindowInfo& wi, const Version* versions_to_try, - size_t num_versions_to_try); + static std::unique_ptr Create(const WindowInfo& wi, const Version* versions_to_try, + size_t num_versions_to_try); - void* GetProcAddress(const char* name) override; - virtual bool ChangeSurface(const WindowInfo& new_wi) override; - virtual void ResizeSurface(u32 new_surface_width = 0, u32 new_surface_height = 0) override; - bool SwapBuffers() override; - bool MakeCurrent() override; - bool DoneCurrent() override; - bool SetSwapInterval(s32 interval) override; - virtual std::unique_ptr CreateSharedContext(const WindowInfo& wi) override; + void* GetProcAddress(const char* name) override; + virtual bool ChangeSurface(const WindowInfo& new_wi) override; + virtual void ResizeSurface(u32 new_surface_width = 0, u32 new_surface_height = 0) override; + bool SwapBuffers() override; + bool MakeCurrent() override; + bool DoneCurrent() override; + bool SetSwapInterval(s32 interval) override; + virtual std::unique_ptr CreateSharedContext(const WindowInfo& wi) override; protected: - virtual bool SetDisplay(); - virtual EGLNativeWindowType GetNativeWindow(EGLConfig config); + virtual bool SetDisplay(); + virtual EGLNativeWindowType GetNativeWindow(EGLConfig config); - bool Initialize(const Version* versions_to_try, size_t num_versions_to_try); - bool CreateDisplay(); - bool CreateContext(const Version& version, EGLContext share_context); - bool CreateContextAndSurface(const Version& version, EGLContext share_context, bool make_current); - bool CreateSurface(); - bool CreatePBufferSurface(); - bool CheckConfigSurfaceFormat(EGLConfig config, WindowInfo::SurfaceFormat format) const; - void DestroyContext(); - void DestroySurface(); + bool Initialize(const Version* versions_to_try, size_t num_versions_to_try); + bool CreateDisplay(); + bool CreateContext(const Version& version, EGLContext share_context); + bool CreateContextAndSurface(const Version& version, EGLContext share_context, + bool make_current); + bool CreateSurface(); + bool CreatePBufferSurface(); + bool CheckConfigSurfaceFormat(EGLConfig config, WindowInfo::SurfaceFormat format) const; + void DestroyContext(); + void DestroySurface(); - EGLDisplay m_display = EGL_NO_DISPLAY; - EGLSurface m_surface = EGL_NO_SURFACE; - EGLContext m_context = EGL_NO_CONTEXT; + EGLDisplay m_display = EGL_NO_DISPLAY; + EGLSurface m_surface = EGL_NO_SURFACE; + EGLContext m_context = EGL_NO_CONTEXT; - EGLConfig m_config = {}; + EGLConfig m_config = {}; - bool m_supports_surfaceless = false; + bool m_supports_surfaceless = false; }; } // namespace GL diff --git a/src/citra_qt/externals/duckstation/gl/context_egl_wayland.cpp b/src/citra_qt/externals/duckstation/gl/context_egl_wayland.cpp index 16532e8b1..9f6929aa8 100644 --- a/src/citra_qt/externals/duckstation/gl/context_egl_wayland.cpp +++ b/src/citra_qt/externals/duckstation/gl/context_egl_wayland.cpp @@ -1,86 +1,78 @@ -#include "context_egl_wayland.h" -#include "../log.h" #include +#include "../log.h" +#include "context_egl_wayland.h" Log_SetChannel(ContextEGLWayland); namespace GL { static const char* WAYLAND_EGL_MODNAME = "libwayland-egl.so.1"; ContextEGLWayland::ContextEGLWayland(const WindowInfo& wi) : ContextEGL(wi) {} -ContextEGLWayland::~ContextEGLWayland() -{ - if (m_wl_window) - m_wl_egl_window_destroy(m_wl_window); - if (m_wl_module) - dlclose(m_wl_module); +ContextEGLWayland::~ContextEGLWayland() { + if (m_wl_window) + m_wl_egl_window_destroy(m_wl_window); + if (m_wl_module) + dlclose(m_wl_module); } -std::unique_ptr ContextEGLWayland::Create(const WindowInfo& wi, const Version* versions_to_try, - size_t num_versions_to_try) -{ - std::unique_ptr context = std::make_unique(wi); - if (!context->LoadModule() || !context->Initialize(versions_to_try, num_versions_to_try)) - return nullptr; +std::unique_ptr ContextEGLWayland::Create(const WindowInfo& wi, + const Version* versions_to_try, + size_t num_versions_to_try) { + std::unique_ptr context = std::make_unique(wi); + if (!context->LoadModule() || !context->Initialize(versions_to_try, num_versions_to_try)) + return nullptr; - return context; + return context; } -std::unique_ptr ContextEGLWayland::CreateSharedContext(const WindowInfo& wi) -{ - std::unique_ptr context = std::make_unique(wi); - context->m_display = m_display; +std::unique_ptr ContextEGLWayland::CreateSharedContext(const WindowInfo& wi) { + std::unique_ptr context = std::make_unique(wi); + context->m_display = m_display; - if (!context->LoadModule() || !context->CreateContextAndSurface(m_version, m_context, false)) - return nullptr; + if (!context->LoadModule() || !context->CreateContextAndSurface(m_version, m_context, false)) + return nullptr; - return context; + return context; } -void ContextEGLWayland::ResizeSurface(u32 new_surface_width, u32 new_surface_height) -{ - if (m_wl_window) - m_wl_egl_window_resize(m_wl_window, new_surface_width, new_surface_height, 0, 0); +void ContextEGLWayland::ResizeSurface(u32 new_surface_width, u32 new_surface_height) { + if (m_wl_window) + m_wl_egl_window_resize(m_wl_window, new_surface_width, new_surface_height, 0, 0); - ContextEGL::ResizeSurface(new_surface_width, new_surface_height); + ContextEGL::ResizeSurface(new_surface_width, new_surface_height); } -EGLNativeWindowType ContextEGLWayland::GetNativeWindow(EGLConfig config) -{ - if (m_wl_window) - { - m_wl_egl_window_destroy(m_wl_window); - m_wl_window = nullptr; - } +EGLNativeWindowType ContextEGLWayland::GetNativeWindow(EGLConfig config) { + if (m_wl_window) { + m_wl_egl_window_destroy(m_wl_window); + m_wl_window = nullptr; + } - m_wl_window = - m_wl_egl_window_create(static_cast(m_wi.window_handle), m_wi.surface_width, m_wi.surface_height); - if (!m_wl_window) - return {}; + m_wl_window = m_wl_egl_window_create(static_cast(m_wi.window_handle), + m_wi.surface_width, m_wi.surface_height); + if (!m_wl_window) + return {}; - return reinterpret_cast(m_wl_window); + return reinterpret_cast(m_wl_window); } -bool ContextEGLWayland::LoadModule() -{ - m_wl_module = dlopen(WAYLAND_EGL_MODNAME, RTLD_NOW | RTLD_GLOBAL); - if (!m_wl_module) - { - Log_ErrorPrintf("Failed to load %s.", WAYLAND_EGL_MODNAME); - return false; - } +bool ContextEGLWayland::LoadModule() { + m_wl_module = dlopen(WAYLAND_EGL_MODNAME, RTLD_NOW | RTLD_GLOBAL); + if (!m_wl_module) { + Log_ErrorPrintf("Failed to load %s.", WAYLAND_EGL_MODNAME); + return false; + } - m_wl_egl_window_create = - reinterpret_cast(dlsym(m_wl_module, "wl_egl_window_create")); - m_wl_egl_window_destroy = - reinterpret_cast(dlsym(m_wl_module, "wl_egl_window_destroy")); - m_wl_egl_window_resize = - reinterpret_cast(dlsym(m_wl_module, "wl_egl_window_resize")); - if (!m_wl_egl_window_create || !m_wl_egl_window_destroy || !m_wl_egl_window_resize) - { - Log_ErrorPrintf("Failed to load one or more functions from %s.", WAYLAND_EGL_MODNAME); - return false; - } + m_wl_egl_window_create = reinterpret_cast( + dlsym(m_wl_module, "wl_egl_window_create")); + m_wl_egl_window_destroy = reinterpret_cast( + dlsym(m_wl_module, "wl_egl_window_destroy")); + m_wl_egl_window_resize = reinterpret_cast( + dlsym(m_wl_module, "wl_egl_window_resize")); + if (!m_wl_egl_window_create || !m_wl_egl_window_destroy || !m_wl_egl_window_resize) { + Log_ErrorPrintf("Failed to load one or more functions from %s.", WAYLAND_EGL_MODNAME); + return false; + } - return true; + return true; } } // namespace GL diff --git a/src/citra_qt/externals/duckstation/gl/context_egl_wayland.h b/src/citra_qt/externals/duckstation/gl/context_egl_wayland.h index 4682f4244..b9aaa3e64 100644 --- a/src/citra_qt/externals/duckstation/gl/context_egl_wayland.h +++ b/src/citra_qt/externals/duckstation/gl/context_egl_wayland.h @@ -1,33 +1,33 @@ #pragma once -#include "context_egl.h" #include +#include "context_egl.h" namespace GL { -class ContextEGLWayland final : public ContextEGL -{ +class ContextEGLWayland final : public ContextEGL { public: - ContextEGLWayland(const WindowInfo& wi); - ~ContextEGLWayland() override; + ContextEGLWayland(const WindowInfo& wi); + ~ContextEGLWayland() override; - static std::unique_ptr Create(const WindowInfo& wi, const Version* versions_to_try, - size_t num_versions_to_try); + static std::unique_ptr Create(const WindowInfo& wi, const Version* versions_to_try, + size_t num_versions_to_try); - std::unique_ptr CreateSharedContext(const WindowInfo& wi) override; - void ResizeSurface(u32 new_surface_width = 0, u32 new_surface_height = 0) override; + std::unique_ptr CreateSharedContext(const WindowInfo& wi) override; + void ResizeSurface(u32 new_surface_width = 0, u32 new_surface_height = 0) override; protected: - EGLNativeWindowType GetNativeWindow(EGLConfig config) override; + EGLNativeWindowType GetNativeWindow(EGLConfig config) override; private: - bool LoadModule(); + bool LoadModule(); - wl_egl_window* m_wl_window = nullptr; + wl_egl_window* m_wl_window = nullptr; - void* m_wl_module = nullptr; - wl_egl_window* (*m_wl_egl_window_create)(struct wl_surface* surface, int width, int height); - void (*m_wl_egl_window_destroy)(struct wl_egl_window* egl_window); - void (*m_wl_egl_window_resize)(struct wl_egl_window* egl_window, int width, int height, int dx, int dy); + void* m_wl_module = nullptr; + wl_egl_window* (*m_wl_egl_window_create)(struct wl_surface* surface, int width, int height); + void (*m_wl_egl_window_destroy)(struct wl_egl_window* egl_window); + void (*m_wl_egl_window_resize)(struct wl_egl_window* egl_window, int width, int height, int dx, + int dy); }; } // namespace GL diff --git a/src/citra_qt/externals/duckstation/gl/context_egl_x11.cpp b/src/citra_qt/externals/duckstation/gl/context_egl_x11.cpp index c7310e312..1cf6f5882 100644 --- a/src/citra_qt/externals/duckstation/gl/context_egl_x11.cpp +++ b/src/citra_qt/externals/duckstation/gl/context_egl_x11.cpp @@ -1,5 +1,5 @@ -#include "context_egl_x11.h" #include "../log.h" +#include "context_egl_x11.h" Log_SetChannel(GL::ContextEGLX11); namespace GL { @@ -7,63 +7,59 @@ ContextEGLX11::ContextEGLX11(const WindowInfo& wi) : ContextEGL(wi) {} ContextEGLX11::~ContextEGLX11() = default; std::unique_ptr ContextEGLX11::Create(const WindowInfo& wi, const Version* versions_to_try, - size_t num_versions_to_try) -{ - std::unique_ptr context = std::make_unique(wi); - if (!context->Initialize(versions_to_try, num_versions_to_try)) - return nullptr; + size_t num_versions_to_try) { + std::unique_ptr context = std::make_unique(wi); + if (!context->Initialize(versions_to_try, num_versions_to_try)) + return nullptr; - return context; + return context; } -std::unique_ptr ContextEGLX11::CreateSharedContext(const WindowInfo& wi) -{ - std::unique_ptr context = std::make_unique(wi); - context->m_display = m_display; +std::unique_ptr ContextEGLX11::CreateSharedContext(const WindowInfo& wi) { + std::unique_ptr context = std::make_unique(wi); + context->m_display = m_display; - if (!context->CreateContextAndSurface(m_version, m_context, false)) - return nullptr; + if (!context->CreateContextAndSurface(m_version, m_context, false)) + return nullptr; - return context; + return context; } -void ContextEGLX11::ResizeSurface(u32 new_surface_width, u32 new_surface_height) -{ - m_window.Resize(); - ContextEGL::ResizeSurface(new_surface_width, new_surface_height); +void ContextEGLX11::ResizeSurface(u32 new_surface_width, u32 new_surface_height) { + m_window.Resize(); + ContextEGL::ResizeSurface(new_surface_width, new_surface_height); } -EGLNativeWindowType ContextEGLX11::GetNativeWindow(EGLConfig config) -{ - X11InhibitErrors ei; +EGLNativeWindowType ContextEGLX11::GetNativeWindow(EGLConfig config) { + X11InhibitErrors ei; - EGLint native_visual_id = 0; - if (!eglGetConfigAttrib(m_display, m_config, EGL_NATIVE_VISUAL_ID, &native_visual_id)) - { - Log_ErrorPrintf("Failed to get X11 visual ID"); - return false; - } + EGLint native_visual_id = 0; + if (!eglGetConfigAttrib(m_display, m_config, EGL_NATIVE_VISUAL_ID, &native_visual_id)) { + Log_ErrorPrintf("Failed to get X11 visual ID"); + return false; + } - XVisualInfo vi_query = {}; - vi_query.visualid = native_visual_id; + XVisualInfo vi_query = {}; + vi_query.visualid = native_visual_id; - int num_vis; - XVisualInfo* vi = XGetVisualInfo(static_cast(m_wi.display_connection), VisualIDMask, &vi_query, &num_vis); - if (num_vis <= 0 || !vi) - { - Log_ErrorPrintf("Failed to query visual from X11"); - return false; - } + int num_vis; + XVisualInfo* vi = XGetVisualInfo(static_cast(m_wi.display_connection), VisualIDMask, + &vi_query, &num_vis); + if (num_vis <= 0 || !vi) { + Log_ErrorPrintf("Failed to query visual from X11"); + return false; + } + + m_window.Destroy(); + if (!m_window.Create(GetDisplay(), + static_cast(reinterpret_cast(m_wi.window_handle)), + vi)) { + Log_ErrorPrintf("Faild to create X11 child window"); + XFree(vi); + return false; + } - m_window.Destroy(); - if (!m_window.Create(GetDisplay(), static_cast(reinterpret_cast(m_wi.window_handle)), vi)) - { - Log_ErrorPrintf("Faild to create X11 child window"); XFree(vi); - return false; - } - - XFree(vi); - return static_cast(m_window.GetWindow()); + return static_cast(m_window.GetWindow()); } } // namespace GL diff --git a/src/citra_qt/externals/duckstation/gl/context_egl_x11.h b/src/citra_qt/externals/duckstation/gl/context_egl_x11.h index 7def8bfbc..e0e55fd22 100644 --- a/src/citra_qt/externals/duckstation/gl/context_egl_x11.h +++ b/src/citra_qt/externals/duckstation/gl/context_egl_x11.h @@ -4,25 +4,26 @@ namespace GL { -class ContextEGLX11 final : public ContextEGL -{ +class ContextEGLX11 final : public ContextEGL { public: - ContextEGLX11(const WindowInfo& wi); - ~ContextEGLX11() override; + ContextEGLX11(const WindowInfo& wi); + ~ContextEGLX11() override; - static std::unique_ptr Create(const WindowInfo& wi, const Version* versions_to_try, - size_t num_versions_to_try); + static std::unique_ptr Create(const WindowInfo& wi, const Version* versions_to_try, + size_t num_versions_to_try); - std::unique_ptr CreateSharedContext(const WindowInfo& wi) override; - void ResizeSurface(u32 new_surface_width = 0, u32 new_surface_height = 0) override; + std::unique_ptr CreateSharedContext(const WindowInfo& wi) override; + void ResizeSurface(u32 new_surface_width = 0, u32 new_surface_height = 0) override; protected: - EGLNativeWindowType GetNativeWindow(EGLConfig config) override; + EGLNativeWindowType GetNativeWindow(EGLConfig config) override; private: - ALWAYS_INLINE Display* GetDisplay() const { return static_cast(m_wi.display_connection); } + ALWAYS_INLINE Display* GetDisplay() const { + return static_cast(m_wi.display_connection); + } - X11Window m_window; + X11Window m_window; }; } // namespace GL diff --git a/src/citra_qt/externals/duckstation/gl/context_glx.cpp b/src/citra_qt/externals/duckstation/gl/context_glx.cpp index bd32039ff..34eb16431 100644 --- a/src/citra_qt/externals/duckstation/gl/context_glx.cpp +++ b/src/citra_qt/externals/duckstation/gl/context_glx.cpp @@ -1,328 +1,281 @@ -#include "context_glx.h" +#include #include "../duckstation_compat.h" #include "../log.h" -#include +#include "context_glx.h" Log_SetChannel(GL::ContextGLX); namespace GL { ContextGLX::ContextGLX(const WindowInfo& wi) : Context(wi) {} -ContextGLX::~ContextGLX() -{ - if (glXGetCurrentContext() == m_context) - glXMakeCurrent(GetDisplay(), None, nullptr); +ContextGLX::~ContextGLX() { + if (glXGetCurrentContext() == m_context) + glXMakeCurrent(GetDisplay(), None, nullptr); - if (m_context) - glXDestroyContext(GetDisplay(), m_context); + if (m_context) + glXDestroyContext(GetDisplay(), m_context); - if (m_vi) - XFree(m_vi); + if (m_vi) + XFree(m_vi); - if (m_libGL_handle) - dlclose(m_libGL_handle); + if (m_libGL_handle) + dlclose(m_libGL_handle); } std::unique_ptr ContextGLX::Create(const WindowInfo& wi, const Version* versions_to_try, - size_t num_versions_to_try) -{ - std::unique_ptr context = std::make_unique(wi); - if (!context->Initialize(versions_to_try, num_versions_to_try)) - return nullptr; + size_t num_versions_to_try) { + std::unique_ptr context = std::make_unique(wi); + if (!context->Initialize(versions_to_try, num_versions_to_try)) + return nullptr; - return context; + return context; } -bool ContextGLX::Initialize(const Version* versions_to_try, size_t num_versions_to_try) -{ - // We need libGL loaded, because GLAD loads its own, then releases it. - m_libGL_handle = dlopen("libGL.so.1", RTLD_NOW | RTLD_GLOBAL); - if (!m_libGL_handle) - { - m_libGL_handle = dlopen("libGL.so", RTLD_NOW | RTLD_GLOBAL); - if (!m_libGL_handle) - { - Log_ErrorPrintf("Failed to load libGL.so: %s", dlerror()); - return false; +bool ContextGLX::Initialize(const Version* versions_to_try, size_t num_versions_to_try) { + // We need libGL loaded, because GLAD loads its own, then releases it. + m_libGL_handle = dlopen("libGL.so.1", RTLD_NOW | RTLD_GLOBAL); + if (!m_libGL_handle) { + m_libGL_handle = dlopen("libGL.so", RTLD_NOW | RTLD_GLOBAL); + if (!m_libGL_handle) { + Log_ErrorPrintf("Failed to load libGL.so: %s", dlerror()); + return false; + } } - } - const int screen = DefaultScreen(GetDisplay()); - if (!gladLoadGLX(GetDisplay(), screen)) - { - Log_ErrorPrintf("Loading GLAD GLX functions failed"); - return false; - } - - if (m_wi.type == WindowInfo::Type::X11) - { - if (!CreateWindow(screen)) - return false; - } - else - { - Panic("Create pbuffer"); - } - - for (size_t i = 0; i < num_versions_to_try; i++) - { - const Version& cv = versions_to_try[i]; - if (cv.profile == Profile::NoProfile && CreateAnyContext(nullptr, true)) - { - m_version = cv; - return true; - } - else if (cv.profile != Profile::NoProfile && CreateVersionContext(cv, nullptr, true)) - { - m_version = cv; - return true; - } - } - - return false; -} - -void* ContextGLX::GetProcAddress(const char* name) -{ - return reinterpret_cast(glXGetProcAddress(reinterpret_cast(name))); -} - -bool ContextGLX::ChangeSurface(const WindowInfo& new_wi) -{ - const bool was_current = (glXGetCurrentContext() == m_context); - if (was_current) - glXMakeCurrent(GetDisplay(), None, nullptr); - - m_window.Destroy(); - m_wi = new_wi; - - if (new_wi.type == WindowInfo::Type::X11) - { const int screen = DefaultScreen(GetDisplay()); - if (!CreateWindow(screen)) - return false; - } + if (!gladLoadGLX(GetDisplay(), screen)) { + Log_ErrorPrintf("Loading GLAD GLX functions failed"); + return false; + } + + if (m_wi.type == WindowInfo::Type::X11) { + if (!CreateWindow(screen)) + return false; + } else { + Panic("Create pbuffer"); + } + + for (size_t i = 0; i < num_versions_to_try; i++) { + const Version& cv = versions_to_try[i]; + if (cv.profile == Profile::NoProfile && CreateAnyContext(nullptr, true)) { + m_version = cv; + return true; + } else if (cv.profile != Profile::NoProfile && CreateVersionContext(cv, nullptr, true)) { + m_version = cv; + return true; + } + } - if (was_current && !glXMakeCurrent(GetDisplay(), GetDrawable(), m_context)) - { - Log_ErrorPrintf("Failed to make context current again after surface change"); return false; - } - - return true; } -void ContextGLX::ResizeSurface(u32 new_surface_width /*= 0*/, u32 new_surface_height /*= 0*/) -{ - m_window.Resize(new_surface_width, new_surface_height); - m_wi.surface_width = m_window.GetWidth(); - m_wi.surface_height = m_window.GetHeight(); +void* ContextGLX::GetProcAddress(const char* name) { + return reinterpret_cast(glXGetProcAddress(reinterpret_cast(name))); } -bool ContextGLX::SwapBuffers() -{ - glXSwapBuffers(GetDisplay(), GetDrawable()); - return true; -} +bool ContextGLX::ChangeSurface(const WindowInfo& new_wi) { + const bool was_current = (glXGetCurrentContext() == m_context); + if (was_current) + glXMakeCurrent(GetDisplay(), None, nullptr); -bool ContextGLX::MakeCurrent() -{ - return (glXMakeCurrent(GetDisplay(), GetDrawable(), m_context) == True); -} + m_window.Destroy(); + m_wi = new_wi; -bool ContextGLX::DoneCurrent() -{ - return (glXMakeCurrent(GetDisplay(), None, nullptr) == True); -} + if (new_wi.type == WindowInfo::Type::X11) { + const int screen = DefaultScreen(GetDisplay()); + if (!CreateWindow(screen)) + return false; + } + + if (was_current && !glXMakeCurrent(GetDisplay(), GetDrawable(), m_context)) { + Log_ErrorPrintf("Failed to make context current again after surface change"); + return false; + } -bool ContextGLX::SetSwapInterval(s32 interval) -{ - if (GLAD_GLX_EXT_swap_control) - { - glXSwapIntervalEXT(GetDisplay(), GetDrawable(), interval); return true; - } - else if (GLAD_GLX_MESA_swap_control) - { - return (glXSwapIntervalMESA(static_cast(std::max(interval, 0))) != 0); - } - else if (GLAD_GLX_SGI_swap_control) - { - return (glXSwapIntervalSGI(interval) != 0); - } - else - { - return false; - } } -std::unique_ptr ContextGLX::CreateSharedContext(const WindowInfo& wi) -{ - std::unique_ptr context = std::make_unique(wi); - if (wi.type == WindowInfo::Type::X11) - { - const int screen = DefaultScreen(context->GetDisplay()); - if (!context->CreateWindow(screen)) - return nullptr; - } - else - { - Panic("Create pbuffer"); - } - - if (m_version.profile == Profile::NoProfile) - { - if (!context->CreateAnyContext(m_context, false)) - return nullptr; - } - else - { - if (!context->CreateVersionContext(m_version, m_context, false)) - return nullptr; - } - - context->m_version = m_version; - return context; +void ContextGLX::ResizeSurface(u32 new_surface_width /*= 0*/, u32 new_surface_height /*= 0*/) { + m_window.Resize(new_surface_width, new_surface_height); + m_wi.surface_width = m_window.GetWidth(); + m_wi.surface_height = m_window.GetHeight(); } -bool ContextGLX::CreateWindow(int screen) -{ - int attribs[32] = {GLX_X_RENDERABLE, True, GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, - GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, GLX_DOUBLEBUFFER, True}; - int nattribs = 8; +bool ContextGLX::SwapBuffers() { + glXSwapBuffers(GetDisplay(), GetDrawable()); + return true; +} - switch (m_wi.surface_format) - { +bool ContextGLX::MakeCurrent() { + return (glXMakeCurrent(GetDisplay(), GetDrawable(), m_context) == True); +} + +bool ContextGLX::DoneCurrent() { + return (glXMakeCurrent(GetDisplay(), None, nullptr) == True); +} + +bool ContextGLX::SetSwapInterval(s32 interval) { + if (GLAD_GLX_EXT_swap_control) { + glXSwapIntervalEXT(GetDisplay(), GetDrawable(), interval); + return true; + } else if (GLAD_GLX_MESA_swap_control) { + return (glXSwapIntervalMESA(static_cast(std::max(interval, 0))) != 0); + } else if (GLAD_GLX_SGI_swap_control) { + return (glXSwapIntervalSGI(interval) != 0); + } else { + return false; + } +} + +std::unique_ptr ContextGLX::CreateSharedContext(const WindowInfo& wi) { + std::unique_ptr context = std::make_unique(wi); + if (wi.type == WindowInfo::Type::X11) { + const int screen = DefaultScreen(context->GetDisplay()); + if (!context->CreateWindow(screen)) + return nullptr; + } else { + Panic("Create pbuffer"); + } + + if (m_version.profile == Profile::NoProfile) { + if (!context->CreateAnyContext(m_context, false)) + return nullptr; + } else { + if (!context->CreateVersionContext(m_version, m_context, false)) + return nullptr; + } + + context->m_version = m_version; + return context; +} + +bool ContextGLX::CreateWindow(int screen) { + int attribs[32] = {GLX_X_RENDERABLE, True, GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, + GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, GLX_DOUBLEBUFFER, True}; + int nattribs = 8; + + switch (m_wi.surface_format) { case WindowInfo::SurfaceFormat::RGB8: - attribs[nattribs++] = GLX_RED_SIZE; - attribs[nattribs++] = 8; - attribs[nattribs++] = GLX_GREEN_SIZE; - attribs[nattribs++] = 8; - attribs[nattribs++] = GLX_BLUE_SIZE; - attribs[nattribs++] = 8; - break; + attribs[nattribs++] = GLX_RED_SIZE; + attribs[nattribs++] = 8; + attribs[nattribs++] = GLX_GREEN_SIZE; + attribs[nattribs++] = 8; + attribs[nattribs++] = GLX_BLUE_SIZE; + attribs[nattribs++] = 8; + break; case WindowInfo::SurfaceFormat::RGBA8: - attribs[nattribs++] = GLX_RED_SIZE; - attribs[nattribs++] = 8; - attribs[nattribs++] = GLX_GREEN_SIZE; - attribs[nattribs++] = 8; - attribs[nattribs++] = GLX_BLUE_SIZE; - attribs[nattribs++] = 8; - attribs[nattribs++] = GLX_ALPHA_SIZE; - attribs[nattribs++] = 8; - break; + attribs[nattribs++] = GLX_RED_SIZE; + attribs[nattribs++] = 8; + attribs[nattribs++] = GLX_GREEN_SIZE; + attribs[nattribs++] = 8; + attribs[nattribs++] = GLX_BLUE_SIZE; + attribs[nattribs++] = 8; + attribs[nattribs++] = GLX_ALPHA_SIZE; + attribs[nattribs++] = 8; + break; case WindowInfo::SurfaceFormat::RGB565: - attribs[nattribs++] = GLX_RED_SIZE; - attribs[nattribs++] = 5; - attribs[nattribs++] = GLX_GREEN_SIZE; - attribs[nattribs++] = 6; - attribs[nattribs++] = GLX_BLUE_SIZE; - attribs[nattribs++] = 5; - break; + attribs[nattribs++] = GLX_RED_SIZE; + attribs[nattribs++] = 5; + attribs[nattribs++] = GLX_GREEN_SIZE; + attribs[nattribs++] = 6; + attribs[nattribs++] = GLX_BLUE_SIZE; + attribs[nattribs++] = 5; + break; case WindowInfo::SurfaceFormat::Auto: - break; + break; default: - UnreachableCode(); - break; - } + UnreachableCode(); + break; + } - attribs[nattribs++] = None; - attribs[nattribs++] = 0; + attribs[nattribs++] = None; + attribs[nattribs++] = 0; - int fbcount = 0; - GLXFBConfig* fbc = glXChooseFBConfig(GetDisplay(), screen, attribs, &fbcount); - if (!fbc || !fbcount) - { - Log_ErrorPrintf("glXChooseFBConfig() failed"); - return false; - } - m_fb_config = *fbc; - XFree(fbc); + int fbcount = 0; + GLXFBConfig* fbc = glXChooseFBConfig(GetDisplay(), screen, attribs, &fbcount); + if (!fbc || !fbcount) { + Log_ErrorPrintf("glXChooseFBConfig() failed"); + return false; + } + m_fb_config = *fbc; + XFree(fbc); - if (!GLAD_GLX_VERSION_1_3) - { - Log_ErrorPrintf("GLX Version 1.3 is required"); - return false; - } + if (!GLAD_GLX_VERSION_1_3) { + Log_ErrorPrintf("GLX Version 1.3 is required"); + return false; + } - m_vi = glXGetVisualFromFBConfig(GetDisplay(), m_fb_config); - if (!m_vi) - { - Log_ErrorPrintf("glXGetVisualFromFBConfig() failed"); - return false; - } + m_vi = glXGetVisualFromFBConfig(GetDisplay(), m_fb_config); + if (!m_vi) { + Log_ErrorPrintf("glXGetVisualFromFBConfig() failed"); + return false; + } - return m_window.Create(GetDisplay(), static_cast(reinterpret_cast(m_wi.window_handle)), m_vi); + return m_window.Create( + GetDisplay(), static_cast(reinterpret_cast(m_wi.window_handle)), m_vi); } -bool ContextGLX::CreateAnyContext(GLXContext share_context, bool make_current) -{ - X11InhibitErrors ie; +bool ContextGLX::CreateAnyContext(GLXContext share_context, bool make_current) { + X11InhibitErrors ie; - m_context = glXCreateContext(GetDisplay(), m_vi, share_context, True); - if (!m_context || ie.HadError()) - { - Log_ErrorPrintf("glxCreateContext() failed"); - return false; - } - - if (make_current) - { - if (!glXMakeCurrent(GetDisplay(), GetDrawable(), m_context)) - { - Log_ErrorPrintf("glXMakeCurrent() failed"); - return false; + m_context = glXCreateContext(GetDisplay(), m_vi, share_context, True); + if (!m_context || ie.HadError()) { + Log_ErrorPrintf("glxCreateContext() failed"); + return false; } - } - return true; + if (make_current) { + if (!glXMakeCurrent(GetDisplay(), GetDrawable(), m_context)) { + Log_ErrorPrintf("glXMakeCurrent() failed"); + return false; + } + } + + return true; } -bool ContextGLX::CreateVersionContext(const Version& version, GLXContext share_context, bool make_current) -{ - // we need create context attribs - if (!GLAD_GLX_VERSION_1_3) - { - Log_ErrorPrint("Missing GLX version 1.3."); - return false; - } - - int attribs[32]; - int nattribs = 0; - attribs[nattribs++] = GLX_CONTEXT_PROFILE_MASK_ARB; - attribs[nattribs++] = - ((version.profile == Profile::ES) ? - ((version.major_version >= 2) ? GLX_CONTEXT_ES2_PROFILE_BIT_EXT : GLX_CONTEXT_ES_PROFILE_BIT_EXT) : - GLX_CONTEXT_CORE_PROFILE_BIT_ARB); - attribs[nattribs++] = GLX_CONTEXT_MAJOR_VERSION_ARB; - attribs[nattribs++] = version.major_version; - attribs[nattribs++] = GLX_CONTEXT_MINOR_VERSION_ARB; - attribs[nattribs++] = version.minor_version; - attribs[nattribs++] = None; - attribs[nattribs++] = 0; - - X11InhibitErrors ie; - m_context = glXCreateContextAttribsARB(GetDisplay(), m_fb_config, share_context, True, attribs); - XSync(GetDisplay(), False); - if (ie.HadError()) - m_context = nullptr; - if (!m_context) - return false; - - if (make_current) - { - if (!glXMakeCurrent(GetDisplay(), GetDrawable(), m_context)) - { - Log_ErrorPrint("glXMakeCurrent() failed"); - glXDestroyContext(GetDisplay(), m_context); - m_context = nullptr; - return false; +bool ContextGLX::CreateVersionContext(const Version& version, GLXContext share_context, + bool make_current) { + // we need create context attribs + if (!GLAD_GLX_VERSION_1_3) { + Log_ErrorPrint("Missing GLX version 1.3."); + return false; } - } - return true; + int attribs[32]; + int nattribs = 0; + attribs[nattribs++] = GLX_CONTEXT_PROFILE_MASK_ARB; + attribs[nattribs++] = ((version.profile == Profile::ES) + ? ((version.major_version >= 2) ? GLX_CONTEXT_ES2_PROFILE_BIT_EXT + : GLX_CONTEXT_ES_PROFILE_BIT_EXT) + : GLX_CONTEXT_CORE_PROFILE_BIT_ARB); + attribs[nattribs++] = GLX_CONTEXT_MAJOR_VERSION_ARB; + attribs[nattribs++] = version.major_version; + attribs[nattribs++] = GLX_CONTEXT_MINOR_VERSION_ARB; + attribs[nattribs++] = version.minor_version; + attribs[nattribs++] = None; + attribs[nattribs++] = 0; + + X11InhibitErrors ie; + m_context = glXCreateContextAttribsARB(GetDisplay(), m_fb_config, share_context, True, attribs); + XSync(GetDisplay(), False); + if (ie.HadError()) + m_context = nullptr; + if (!m_context) + return false; + + if (make_current) { + if (!glXMakeCurrent(GetDisplay(), GetDrawable(), m_context)) { + Log_ErrorPrint("glXMakeCurrent() failed"); + glXDestroyContext(GetDisplay(), m_context); + m_context = nullptr; + return false; + } + } + + return true; } } // namespace GL diff --git a/src/citra_qt/externals/duckstation/gl/context_glx.h b/src/citra_qt/externals/duckstation/gl/context_glx.h index 1f386fe9d..f8f2fafab 100644 --- a/src/citra_qt/externals/duckstation/gl/context_glx.h +++ b/src/citra_qt/externals/duckstation/gl/context_glx.h @@ -1,44 +1,47 @@ #pragma once -#include "context.h" #include "../../../../../externals/glad/src/glad_glx.h" +#include "context.h" #include "x11_window.h" namespace GL { -class ContextGLX final : public Context -{ +class ContextGLX final : public Context { public: - ContextGLX(const WindowInfo& wi); - ~ContextGLX() override; + ContextGLX(const WindowInfo& wi); + ~ContextGLX() override; - static std::unique_ptr Create(const WindowInfo& wi, const Version* versions_to_try, - size_t num_versions_to_try); + static std::unique_ptr Create(const WindowInfo& wi, const Version* versions_to_try, + size_t num_versions_to_try); - void* GetProcAddress(const char* name) override; - bool ChangeSurface(const WindowInfo& new_wi) override; - void ResizeSurface(u32 new_surface_width = 0, u32 new_surface_height = 0) override; - bool SwapBuffers() override; - bool MakeCurrent() override; - bool DoneCurrent() override; - bool SetSwapInterval(s32 interval) override; - std::unique_ptr CreateSharedContext(const WindowInfo& wi) override; + void* GetProcAddress(const char* name) override; + bool ChangeSurface(const WindowInfo& new_wi) override; + void ResizeSurface(u32 new_surface_width = 0, u32 new_surface_height = 0) override; + bool SwapBuffers() override; + bool MakeCurrent() override; + bool DoneCurrent() override; + bool SetSwapInterval(s32 interval) override; + std::unique_ptr CreateSharedContext(const WindowInfo& wi) override; private: - ALWAYS_INLINE Display* GetDisplay() const { return static_cast(m_wi.display_connection); } - ALWAYS_INLINE GLXDrawable GetDrawable() const { return static_cast(m_window.GetWindow()); } + ALWAYS_INLINE Display* GetDisplay() const { + return static_cast(m_wi.display_connection); + } + ALWAYS_INLINE GLXDrawable GetDrawable() const { + return static_cast(m_window.GetWindow()); + } - bool Initialize(const Version* versions_to_try, size_t num_versions_to_try); - bool CreateWindow(int screen); - bool CreateAnyContext(GLXContext share_context, bool make_current); - bool CreateVersionContext(const Version& version, GLXContext share_context, bool make_current); + bool Initialize(const Version* versions_to_try, size_t num_versions_to_try); + bool CreateWindow(int screen); + bool CreateAnyContext(GLXContext share_context, bool make_current); + bool CreateVersionContext(const Version& version, GLXContext share_context, bool make_current); - GLXContext m_context = nullptr; - GLXFBConfig m_fb_config = {}; - XVisualInfo* m_vi = nullptr; - X11Window m_window; + GLXContext m_context = nullptr; + GLXFBConfig m_fb_config = {}; + XVisualInfo* m_vi = nullptr; + X11Window m_window; - // GLAD releases its reference to libGL.so, so we need to maintain our own. - void* m_libGL_handle = nullptr; + // GLAD releases its reference to libGL.so, so we need to maintain our own. + void* m_libGL_handle = nullptr; }; } // namespace GL diff --git a/src/citra_qt/externals/duckstation/gl/context_wgl.cpp b/src/citra_qt/externals/duckstation/gl/context_wgl.cpp index 09f994c92..2d79ca71d 100644 --- a/src/citra_qt/externals/duckstation/gl/context_wgl.cpp +++ b/src/citra_qt/externals/duckstation/gl/context_wgl.cpp @@ -1,7 +1,7 @@ -#include "context_wgl.h" #include "../duckstation_compat.h" #include "../log.h" #include "../scoped_guard.h" +#include "context_wgl.h" #include "loader.h" using namespace melonDS; Log_SetChannel(GL::ContextWGL); @@ -9,445 +9,390 @@ Log_SetChannel(GL::ContextWGL); // TODO: get rid of this #pragma comment(lib, "opengl32.lib") -static void* GetProcAddressCallback(const char* name) -{ - void* addr = reinterpret_cast(wglGetProcAddress(name)); - if (addr) - return addr; +static void* GetProcAddressCallback(const char* name) { + void* addr = reinterpret_cast(wglGetProcAddress(name)); + if (addr) + return addr; - // try opengl32.dll - return reinterpret_cast(::GetProcAddress(GetModuleHandleA("opengl32.dll"), name)); + // try opengl32.dll + return reinterpret_cast(::GetProcAddress(GetModuleHandleA("opengl32.dll"), name)); } namespace GL { ContextWGL::ContextWGL(const WindowInfo& wi) : Context(wi) {} -ContextWGL::~ContextWGL() -{ - if (wglGetCurrentContext() == m_rc) - wglMakeCurrent(m_dc, nullptr); +ContextWGL::~ContextWGL() { + if (wglGetCurrentContext() == m_rc) + wglMakeCurrent(m_dc, nullptr); - if (m_rc) - wglDeleteContext(m_rc); + if (m_rc) + wglDeleteContext(m_rc); - ReleaseDC(); + ReleaseDC(); } std::unique_ptr ContextWGL::Create(const WindowInfo& wi, const Version* versions_to_try, - size_t num_versions_to_try) -{ - std::unique_ptr context = std::make_unique(wi); - if (!context->Initialize(versions_to_try, num_versions_to_try)) - return nullptr; + size_t num_versions_to_try) { + std::unique_ptr context = std::make_unique(wi); + if (!context->Initialize(versions_to_try, num_versions_to_try)) + return nullptr; - return context; + return context; } -bool ContextWGL::Initialize(const Version* versions_to_try, size_t num_versions_to_try) -{ - if (m_wi.type == WindowInfo::Type::Win32) - { +bool ContextWGL::Initialize(const Version* versions_to_try, size_t num_versions_to_try) { + if (m_wi.type == WindowInfo::Type::Win32) { + if (!InitializeDC()) + return false; + } else { + Log_ErrorPrint("ContextWGL must always start with a valid surface."); + return false; + } + + // Everything including core/ES requires a dummy profile to load the WGL extensions. + if (!CreateAnyContext(nullptr, true)) + return false; + + for (size_t i = 0; i < num_versions_to_try; i++) { + const Version& cv = versions_to_try[i]; + if (cv.profile == Profile::NoProfile) { + // we already have the dummy context, so just use that + m_version = cv; + return true; + } else if (CreateVersionContext(cv, nullptr, true)) { + m_version = cv; + return true; + } + } + + return false; +} + +void* ContextWGL::GetProcAddress(const char* name) { + return GetProcAddressCallback(name); +} + +bool ContextWGL::ChangeSurface(const WindowInfo& new_wi) { + const bool was_current = (wglGetCurrentContext() == m_rc); + + ReleaseDC(); + + m_wi = new_wi; if (!InitializeDC()) - return false; - } - else - { - Log_ErrorPrint("ContextWGL must always start with a valid surface."); - return false; - } + return false; - // Everything including core/ES requires a dummy profile to load the WGL extensions. - if (!CreateAnyContext(nullptr, true)) - return false; - - for (size_t i = 0; i < num_versions_to_try; i++) - { - const Version& cv = versions_to_try[i]; - if (cv.profile == Profile::NoProfile) - { - // we already have the dummy context, so just use that - m_version = cv; - return true; - } - else if (CreateVersionContext(cv, nullptr, true)) - { - m_version = cv; - return true; - } - } - - return false; -} - -void* ContextWGL::GetProcAddress(const char* name) -{ - return GetProcAddressCallback(name); -} - -bool ContextWGL::ChangeSurface(const WindowInfo& new_wi) -{ - const bool was_current = (wglGetCurrentContext() == m_rc); - - ReleaseDC(); - - m_wi = new_wi; - if (!InitializeDC()) - return false; - - if (was_current && !wglMakeCurrent(m_dc, m_rc)) - { - Log_ErrorPrintf("Failed to make context current again after surface change: 0x%08X", GetLastError()); - return false; - } - - return true; -} - -void ContextWGL::ResizeSurface(u32 new_surface_width /*= 0*/, u32 new_surface_height /*= 0*/) -{ - RECT client_rc = {}; - GetClientRect(GetHWND(), &client_rc); - m_wi.surface_width = static_cast(client_rc.right - client_rc.left); - m_wi.surface_height = static_cast(client_rc.bottom - client_rc.top); -} - -bool ContextWGL::SwapBuffers() -{ - return ::SwapBuffers(m_dc); -} - -bool ContextWGL::MakeCurrent() -{ - if (!wglMakeCurrent(m_dc, m_rc)) - { - Log_ErrorPrintf("wglMakeCurrent() failed: 0x%08X", GetLastError()); - return false; - } - - return true; -} - -bool ContextWGL::DoneCurrent() -{ - return wglMakeCurrent(m_dc, nullptr); -} - -bool ContextWGL::SetSwapInterval(s32 interval) -{ - if (!GLAD_WGL_EXT_swap_control) - return false; - - return wglSwapIntervalEXT(interval); -} - -std::unique_ptr ContextWGL::CreateSharedContext(const WindowInfo& wi) -{ - std::unique_ptr context = std::make_unique(wi); - if (wi.type == WindowInfo::Type::Win32) - { - if (!context->InitializeDC()) - return nullptr; - } - else - { - Log_ErrorPrint("PBuffer not implemented"); - return nullptr; - } - - if (m_version.profile == Profile::NoProfile) - { - if (!context->CreateAnyContext(m_rc, false)) - return nullptr; - } - else - { - if (!context->CreateVersionContext(m_version, m_rc, false)) - return nullptr; - } - - context->m_version = m_version; - return context; -} - -HDC ContextWGL::GetDCAndSetPixelFormat(HWND hwnd) -{ - PIXELFORMATDESCRIPTOR pfd = {}; - pfd.nSize = sizeof(pfd); - pfd.nVersion = 1; - pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; - pfd.iPixelType = PFD_TYPE_RGBA; - pfd.dwLayerMask = PFD_MAIN_PLANE; - pfd.cRedBits = 8; - pfd.cGreenBits = 8; - pfd.cBlueBits = 8; - pfd.cColorBits = 24; - - HDC hDC = ::GetDC(hwnd); - if (!hDC) - { - Log_ErrorPrintf("GetDC() failed: 0x%08X", GetLastError()); - return {}; - } - - if (!m_pixel_format.has_value()) - { - const int pf = ChoosePixelFormat(hDC, &pfd); - if (pf == 0) - { - Log_ErrorPrintf("ChoosePixelFormat() failed: 0x%08X", GetLastError()); - ::ReleaseDC(hwnd, hDC); - return {}; - } - - m_pixel_format = pf; - } - - if (!SetPixelFormat(hDC, m_pixel_format.value(), &pfd)) - { - Log_ErrorPrintf("SetPixelFormat() failed: 0x%08X", GetLastError()); - ::ReleaseDC(hwnd, hDC); - return {}; - } - - return hDC; -} - -bool ContextWGL::InitializeDC() -{ - if (m_wi.type == WindowInfo::Type::Win32) - { - m_dc = GetDCAndSetPixelFormat(GetHWND()); - if (!m_dc) - { - Log_ErrorPrint("Failed to get DC for window"); - return false; + if (was_current && !wglMakeCurrent(m_dc, m_rc)) { + Log_ErrorPrintf("Failed to make context current again after surface change: 0x%08X", + GetLastError()); + return false; } return true; - } - else if (m_wi.type == WindowInfo::Type::Surfaceless) - { - return CreatePBuffer(); - } - else - { - Log_ErrorPrintf("Unknown window info type %u", static_cast(m_wi.type)); - return false; - } } -void ContextWGL::ReleaseDC() -{ - if (m_pbuffer) - { - wglReleasePbufferDCARB(m_pbuffer, m_dc); - m_dc = {}; - - wglDestroyPbufferARB(m_pbuffer); - m_pbuffer = {}; - - ::ReleaseDC(m_dummy_window, m_dummy_dc); - m_dummy_dc = {}; - - DestroyWindow(m_dummy_window); - m_dummy_window = {}; - } - else if (m_dc) - { - ::ReleaseDC(GetHWND(), m_dc); - m_dc = {}; - } +void ContextWGL::ResizeSurface(u32 new_surface_width /*= 0*/, u32 new_surface_height /*= 0*/) { + RECT client_rc = {}; + GetClientRect(GetHWND(), &client_rc); + m_wi.surface_width = static_cast(client_rc.right - client_rc.left); + m_wi.surface_height = static_cast(client_rc.bottom - client_rc.top); } -bool ContextWGL::CreatePBuffer() -{ - static bool window_class_registered = false; - static const wchar_t* window_class_name = L"ContextWGLPBuffer"; +bool ContextWGL::SwapBuffers() { + return ::SwapBuffers(m_dc); +} - if (!window_class_registered) - { - WNDCLASSEXW wc = {}; - wc.cbSize = sizeof(WNDCLASSEXW); - wc.style = 0; - wc.lpfnWndProc = DefWindowProcW; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = GetModuleHandle(nullptr); - wc.hIcon = NULL; - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); - wc.lpszMenuName = NULL; - wc.lpszClassName = window_class_name; - wc.hIconSm = NULL; - - if (!RegisterClassExW(&wc)) - { - Log_ErrorPrint("(ContextWGL::CreatePBuffer) RegisterClassExW() failed"); - return false; +bool ContextWGL::MakeCurrent() { + if (!wglMakeCurrent(m_dc, m_rc)) { + Log_ErrorPrintf("wglMakeCurrent() failed: 0x%08X", GetLastError()); + return false; } - window_class_registered = true; - } - - HWND hwnd = CreateWindowExW(0, window_class_name, window_class_name, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL); - if (!hwnd) - { - Log_ErrorPrint("(ContextWGL::CreatePBuffer) CreateWindowEx() failed"); - return false; - } - - ScopedGuard hwnd_guard([hwnd]() { DestroyWindow(hwnd); }); - - HDC hdc = GetDCAndSetPixelFormat(hwnd); - if (!hdc) - return false; - - ScopedGuard hdc_guard([hdc, hwnd]() { ::ReleaseDC(hwnd, hdc); }); - - static constexpr const int pb_attribs[] = {0, 0}; - - AssertMsg(m_pixel_format.has_value(), "Has pixel format for pbuffer"); - HPBUFFERARB pbuffer = wglCreatePbufferARB(hdc, m_pixel_format.value(), 1, 1, pb_attribs); - if (!pbuffer) - { - Log_ErrorPrint("(ContextWGL::CreatePBuffer) wglCreatePbufferARB() failed"); - return false; - } - - ScopedGuard pbuffer_guard([pbuffer]() { wglDestroyPbufferARB(pbuffer); }); - - m_dc = wglGetPbufferDCARB(pbuffer); - if (!m_dc) - { - Log_ErrorPrint("(ContextWGL::CreatePbuffer) wglGetPbufferDCARB() failed"); - return false; - } - - m_dummy_window = hwnd; - m_dummy_dc = hdc; - m_pbuffer = pbuffer; - - pbuffer_guard.Cancel(); - hdc_guard.Cancel(); - hwnd_guard.Cancel(); - return true; + return true; } -bool ContextWGL::CreateAnyContext(HGLRC share_context, bool make_current) -{ - m_rc = wglCreateContext(m_dc); - if (!m_rc) - { - Log_ErrorPrintf("wglCreateContext() failed: 0x%08X", GetLastError()); - return false; - } - - if (make_current) - { - if (!wglMakeCurrent(m_dc, m_rc)) - { - Log_ErrorPrintf("wglMakeCurrent() failed: 0x%08X", GetLastError()); - return false; - } - - // re-init glad-wgl - if (!gladLoadWGLLoader([](const char* name) -> void* { return reinterpret_cast(wglGetProcAddress(name)); }, m_dc)) - { - Log_ErrorPrint("Loading GLAD WGL functions failed"); - return false; - } - } - - if (share_context && !wglShareLists(share_context, m_rc)) - { - Log_ErrorPrintf("wglShareLists() failed: 0x%08X", GetLastError()); - return false; - } - - return true; +bool ContextWGL::DoneCurrent() { + return wglMakeCurrent(m_dc, nullptr); } -bool ContextWGL::CreateVersionContext(const Version& version, HGLRC share_context, bool make_current) -{ - // we need create context attribs - if (!GLAD_WGL_ARB_create_context) - { - Log_ErrorPrint("Missing GLAD_WGL_ARB_create_context."); - return false; - } +bool ContextWGL::SetSwapInterval(s32 interval) { + if (!GLAD_WGL_EXT_swap_control) + return false; - HGLRC new_rc; - if (version.profile == Profile::Core) - { - const int attribs[] = {WGL_CONTEXT_PROFILE_MASK_ARB, - WGL_CONTEXT_CORE_PROFILE_BIT_ARB, - WGL_CONTEXT_MAJOR_VERSION_ARB, - version.major_version, - WGL_CONTEXT_MINOR_VERSION_ARB, - version.minor_version, + return wglSwapIntervalEXT(interval); +} + +std::unique_ptr ContextWGL::CreateSharedContext(const WindowInfo& wi) { + std::unique_ptr context = std::make_unique(wi); + if (wi.type == WindowInfo::Type::Win32) { + if (!context->InitializeDC()) + return nullptr; + } else { + Log_ErrorPrint("PBuffer not implemented"); + return nullptr; + } + + if (m_version.profile == Profile::NoProfile) { + if (!context->CreateAnyContext(m_rc, false)) + return nullptr; + } else { + if (!context->CreateVersionContext(m_version, m_rc, false)) + return nullptr; + } + + context->m_version = m_version; + return context; +} + +HDC ContextWGL::GetDCAndSetPixelFormat(HWND hwnd) { + PIXELFORMATDESCRIPTOR pfd = {}; + pfd.nSize = sizeof(pfd); + pfd.nVersion = 1; + pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; + pfd.iPixelType = PFD_TYPE_RGBA; + pfd.dwLayerMask = PFD_MAIN_PLANE; + pfd.cRedBits = 8; + pfd.cGreenBits = 8; + pfd.cBlueBits = 8; + pfd.cColorBits = 24; + + HDC hDC = ::GetDC(hwnd); + if (!hDC) { + Log_ErrorPrintf("GetDC() failed: 0x%08X", GetLastError()); + return {}; + } + + if (!m_pixel_format.has_value()) { + const int pf = ChoosePixelFormat(hDC, &pfd); + if (pf == 0) { + Log_ErrorPrintf("ChoosePixelFormat() failed: 0x%08X", GetLastError()); + ::ReleaseDC(hwnd, hDC); + return {}; + } + + m_pixel_format = pf; + } + + if (!SetPixelFormat(hDC, m_pixel_format.value(), &pfd)) { + Log_ErrorPrintf("SetPixelFormat() failed: 0x%08X", GetLastError()); + ::ReleaseDC(hwnd, hDC); + return {}; + } + + return hDC; +} + +bool ContextWGL::InitializeDC() { + if (m_wi.type == WindowInfo::Type::Win32) { + m_dc = GetDCAndSetPixelFormat(GetHWND()); + if (!m_dc) { + Log_ErrorPrint("Failed to get DC for window"); + return false; + } + + return true; + } else if (m_wi.type == WindowInfo::Type::Surfaceless) { + return CreatePBuffer(); + } else { + Log_ErrorPrintf("Unknown window info type %u", static_cast(m_wi.type)); + return false; + } +} + +void ContextWGL::ReleaseDC() { + if (m_pbuffer) { + wglReleasePbufferDCARB(m_pbuffer, m_dc); + m_dc = {}; + + wglDestroyPbufferARB(m_pbuffer); + m_pbuffer = {}; + + ::ReleaseDC(m_dummy_window, m_dummy_dc); + m_dummy_dc = {}; + + DestroyWindow(m_dummy_window); + m_dummy_window = {}; + } else if (m_dc) { + ::ReleaseDC(GetHWND(), m_dc); + m_dc = {}; + } +} + +bool ContextWGL::CreatePBuffer() { + static bool window_class_registered = false; + static const wchar_t* window_class_name = L"ContextWGLPBuffer"; + + if (!window_class_registered) { + WNDCLASSEXW wc = {}; + wc.cbSize = sizeof(WNDCLASSEXW); + wc.style = 0; + wc.lpfnWndProc = DefWindowProcW; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = GetModuleHandle(nullptr); + wc.hIcon = NULL; + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wc.lpszMenuName = NULL; + wc.lpszClassName = window_class_name; + wc.hIconSm = NULL; + + if (!RegisterClassExW(&wc)) { + Log_ErrorPrint("(ContextWGL::CreatePBuffer) RegisterClassExW() failed"); + return false; + } + + window_class_registered = true; + } + + HWND hwnd = CreateWindowExW(0, window_class_name, window_class_name, 0, 0, 0, 0, 0, NULL, NULL, + NULL, NULL); + if (!hwnd) { + Log_ErrorPrint("(ContextWGL::CreatePBuffer) CreateWindowEx() failed"); + return false; + } + + ScopedGuard hwnd_guard([hwnd]() { DestroyWindow(hwnd); }); + + HDC hdc = GetDCAndSetPixelFormat(hwnd); + if (!hdc) + return false; + + ScopedGuard hdc_guard([hdc, hwnd]() { ::ReleaseDC(hwnd, hdc); }); + + static constexpr const int pb_attribs[] = {0, 0}; + + AssertMsg(m_pixel_format.has_value(), "Has pixel format for pbuffer"); + HPBUFFERARB pbuffer = wglCreatePbufferARB(hdc, m_pixel_format.value(), 1, 1, pb_attribs); + if (!pbuffer) { + Log_ErrorPrint("(ContextWGL::CreatePBuffer) wglCreatePbufferARB() failed"); + return false; + } + + ScopedGuard pbuffer_guard([pbuffer]() { wglDestroyPbufferARB(pbuffer); }); + + m_dc = wglGetPbufferDCARB(pbuffer); + if (!m_dc) { + Log_ErrorPrint("(ContextWGL::CreatePbuffer) wglGetPbufferDCARB() failed"); + return false; + } + + m_dummy_window = hwnd; + m_dummy_dc = hdc; + m_pbuffer = pbuffer; + + pbuffer_guard.Cancel(); + hdc_guard.Cancel(); + hwnd_guard.Cancel(); + return true; +} + +bool ContextWGL::CreateAnyContext(HGLRC share_context, bool make_current) { + m_rc = wglCreateContext(m_dc); + if (!m_rc) { + Log_ErrorPrintf("wglCreateContext() failed: 0x%08X", GetLastError()); + return false; + } + + if (make_current) { + if (!wglMakeCurrent(m_dc, m_rc)) { + Log_ErrorPrintf("wglMakeCurrent() failed: 0x%08X", GetLastError()); + return false; + } + + // re-init glad-wgl + if (!gladLoadWGLLoader( + [](const char* name) -> void* { + return reinterpret_cast(wglGetProcAddress(name)); + }, + m_dc)) { + Log_ErrorPrint("Loading GLAD WGL functions failed"); + return false; + } + } + + if (share_context && !wglShareLists(share_context, m_rc)) { + Log_ErrorPrintf("wglShareLists() failed: 0x%08X", GetLastError()); + return false; + } + + return true; +} + +bool ContextWGL::CreateVersionContext(const Version& version, HGLRC share_context, + bool make_current) { + // we need create context attribs + if (!GLAD_WGL_ARB_create_context) { + Log_ErrorPrint("Missing GLAD_WGL_ARB_create_context."); + return false; + } + + HGLRC new_rc; + if (version.profile == Profile::Core) { + const int attribs[] = {WGL_CONTEXT_PROFILE_MASK_ARB, + WGL_CONTEXT_CORE_PROFILE_BIT_ARB, + WGL_CONTEXT_MAJOR_VERSION_ARB, + version.major_version, + WGL_CONTEXT_MINOR_VERSION_ARB, + version.minor_version, #ifdef _DEBUG - WGL_CONTEXT_FLAGS_ARB, - WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB | WGL_CONTEXT_DEBUG_BIT_ARB, + WGL_CONTEXT_FLAGS_ARB, + WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB | WGL_CONTEXT_DEBUG_BIT_ARB, #else - WGL_CONTEXT_FLAGS_ARB, - WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, + WGL_CONTEXT_FLAGS_ARB, + WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, #endif - 0, - 0}; + 0, + 0}; - new_rc = wglCreateContextAttribsARB(m_dc, share_context, attribs); - } - else if (version.profile == Profile::ES) - { - if ((version.major_version >= 2 && !GLAD_WGL_EXT_create_context_es2_profile) || - (version.major_version < 2 && !GLAD_WGL_EXT_create_context_es_profile)) - { - Log_ErrorPrint("WGL_EXT_create_context_es_profile not supported"); - return false; + new_rc = wglCreateContextAttribsARB(m_dc, share_context, attribs); + } else if (version.profile == Profile::ES) { + if ((version.major_version >= 2 && !GLAD_WGL_EXT_create_context_es2_profile) || + (version.major_version < 2 && !GLAD_WGL_EXT_create_context_es_profile)) { + Log_ErrorPrint("WGL_EXT_create_context_es_profile not supported"); + return false; + } + + const int attribs[] = {WGL_CONTEXT_PROFILE_MASK_ARB, + ((version.major_version >= 2) ? WGL_CONTEXT_ES2_PROFILE_BIT_EXT + : WGL_CONTEXT_ES_PROFILE_BIT_EXT), + WGL_CONTEXT_MAJOR_VERSION_ARB, + version.major_version, + WGL_CONTEXT_MINOR_VERSION_ARB, + version.minor_version, + 0, + 0}; + + new_rc = wglCreateContextAttribsARB(m_dc, share_context, attribs); + } else { + Log_ErrorPrint("Unknown profile"); + return false; } - const int attribs[] = { - WGL_CONTEXT_PROFILE_MASK_ARB, - ((version.major_version >= 2) ? WGL_CONTEXT_ES2_PROFILE_BIT_EXT : WGL_CONTEXT_ES_PROFILE_BIT_EXT), - WGL_CONTEXT_MAJOR_VERSION_ARB, - version.major_version, - WGL_CONTEXT_MINOR_VERSION_ARB, - version.minor_version, - 0, - 0}; + if (!new_rc) + return false; - new_rc = wglCreateContextAttribsARB(m_dc, share_context, attribs); - } - else - { - Log_ErrorPrint("Unknown profile"); - return false; - } + // destroy and swap contexts + if (m_rc) { + if (!wglMakeCurrent(m_dc, make_current ? new_rc : nullptr)) { + Log_ErrorPrintf("wglMakeCurrent() failed: 0x%08X", GetLastError()); + wglDeleteContext(new_rc); + return false; + } - if (!new_rc) - return false; + // re-init glad-wgl + if (make_current && !gladLoadWGLLoader( + [](const char* name) -> void* { + return reinterpret_cast(wglGetProcAddress(name)); + }, + m_dc)) { + Log_ErrorPrint("Loading GLAD WGL functions failed"); + return false; + } - // destroy and swap contexts - if (m_rc) - { - if (!wglMakeCurrent(m_dc, make_current ? new_rc : nullptr)) - { - Log_ErrorPrintf("wglMakeCurrent() failed: 0x%08X", GetLastError()); - wglDeleteContext(new_rc); - return false; + wglDeleteContext(m_rc); } - // re-init glad-wgl - if (make_current && !gladLoadWGLLoader([](const char* name) -> void* { return reinterpret_cast(wglGetProcAddress(name)); }, m_dc)) - { - Log_ErrorPrint("Loading GLAD WGL functions failed"); - return false; - } - - wglDeleteContext(m_rc); - } - - m_rc = new_rc; - return true; + m_rc = new_rc; + return true; } } // namespace GL diff --git a/src/citra_qt/externals/duckstation/gl/context_wgl.h b/src/citra_qt/externals/duckstation/gl/context_wgl.h index c90845ebb..1f869e005 100644 --- a/src/citra_qt/externals/duckstation/gl/context_wgl.h +++ b/src/citra_qt/externals/duckstation/gl/context_wgl.h @@ -1,53 +1,54 @@ #pragma once #include "../windows_headers.h" -#include "context.h" -#include "../../../../../externals/glad/src/glad_wgl.h" -#include "loader.h" #include +#include "../../../../../externals/glad/src/glad_wgl.h" +#include "context.h" +#include "loader.h" namespace GL { -class ContextWGL final : public Context -{ +class ContextWGL final : public Context { public: - ContextWGL(const WindowInfo& wi); - ~ContextWGL() override; + ContextWGL(const WindowInfo& wi); + ~ContextWGL() override; - static std::unique_ptr Create(const WindowInfo& wi, const Version* versions_to_try, - size_t num_versions_to_try); + static std::unique_ptr Create(const WindowInfo& wi, const Version* versions_to_try, + size_t num_versions_to_try); - void* GetProcAddress(const char* name) override; - bool ChangeSurface(const WindowInfo& new_wi) override; - void ResizeSurface(u32 new_surface_width = 0, u32 new_surface_height = 0) override; - bool SwapBuffers() override; - bool MakeCurrent() override; - bool DoneCurrent() override; - bool SetSwapInterval(s32 interval) override; - std::unique_ptr CreateSharedContext(const WindowInfo& wi) override; + void* GetProcAddress(const char* name) override; + bool ChangeSurface(const WindowInfo& new_wi) override; + void ResizeSurface(u32 new_surface_width = 0, u32 new_surface_height = 0) override; + bool SwapBuffers() override; + bool MakeCurrent() override; + bool DoneCurrent() override; + bool SetSwapInterval(s32 interval) override; + std::unique_ptr CreateSharedContext(const WindowInfo& wi) override; private: - ALWAYS_INLINE HWND GetHWND() const { return static_cast(m_wi.window_handle); } + ALWAYS_INLINE HWND GetHWND() const { + return static_cast(m_wi.window_handle); + } - HDC GetDCAndSetPixelFormat(HWND hwnd); + HDC GetDCAndSetPixelFormat(HWND hwnd); - bool Initialize(const Version* versions_to_try, size_t num_versions_to_try); - bool InitializeDC(); - void ReleaseDC(); - bool CreatePBuffer(); - bool CreateAnyContext(HGLRC share_context, bool make_current); - bool CreateVersionContext(const Version& version, HGLRC share_context, bool make_current); + bool Initialize(const Version* versions_to_try, size_t num_versions_to_try); + bool InitializeDC(); + void ReleaseDC(); + bool CreatePBuffer(); + bool CreateAnyContext(HGLRC share_context, bool make_current); + bool CreateVersionContext(const Version& version, HGLRC share_context, bool make_current); - HDC m_dc = {}; - HGLRC m_rc = {}; + HDC m_dc = {}; + HGLRC m_rc = {}; - // Can't change pixel format once it's set for a RC. - std::optional m_pixel_format; + // Can't change pixel format once it's set for a RC. + std::optional m_pixel_format; - // Dummy window for creating a PBuffer off when we're surfaceless. - HWND m_dummy_window = {}; - HDC m_dummy_dc = {}; - HPBUFFERARB m_pbuffer = {}; + // Dummy window for creating a PBuffer off when we're surfaceless. + HWND m_dummy_window = {}; + HDC m_dummy_dc = {}; + HPBUFFERARB m_pbuffer = {}; }; } // namespace GL diff --git a/src/citra_qt/externals/duckstation/gl/x11_window.cpp b/src/citra_qt/externals/duckstation/gl/x11_window.cpp index bf09fcc61..6ae766b92 100644 --- a/src/citra_qt/externals/duckstation/gl/x11_window.cpp +++ b/src/citra_qt/externals/duckstation/gl/x11_window.cpp @@ -1,101 +1,89 @@ -#include "x11_window.h" -#include "../log.h" -#include "../duckstation_compat.h" #include +#include "../duckstation_compat.h" +#include "../log.h" +#include "x11_window.h" Log_SetChannel(X11Window); namespace GL { X11Window::X11Window() = default; -X11Window::~X11Window() -{ - Destroy(); +X11Window::~X11Window() { + Destroy(); } -bool X11Window::Create(Display* display, Window parent_window, const XVisualInfo* vi) -{ - m_display = display; - m_parent_window = parent_window; - XSync(m_display, True); +bool X11Window::Create(Display* display, Window parent_window, const XVisualInfo* vi) { + m_display = display; + m_parent_window = parent_window; + XSync(m_display, True); - XWindowAttributes parent_wa = {}; - XGetWindowAttributes(m_display, m_parent_window, &parent_wa); - m_width = static_cast(parent_wa.width); - m_height = static_cast(parent_wa.height); - - // Failed X calls terminate the process so no need to check for errors. - // We could swap the error handler out here as well. - m_colormap = XCreateColormap(m_display, m_parent_window, vi->visual, AllocNone); - - XSetWindowAttributes wa = {}; - wa.colormap = m_colormap; - - m_window = XCreateWindow(m_display, m_parent_window, 0, 0, m_width, m_height, 0, vi->depth, InputOutput, vi->visual, - CWColormap, &wa); - XMapWindow(m_display, m_window); - XSync(m_display, True); - - return true; -} - -void X11Window::Destroy() -{ - if (m_window) - { - XUnmapWindow(m_display, m_window); - XDestroyWindow(m_display, m_window); - m_window = {}; - } - - if (m_colormap) - { - XFreeColormap(m_display, m_colormap); - m_colormap = {}; - } -} - -void X11Window::Resize(u32 width, u32 height) -{ - if (width != 0 && height != 0) - { - m_width = width; - m_height = height; - } - else - { XWindowAttributes parent_wa = {}; XGetWindowAttributes(m_display, m_parent_window, &parent_wa); m_width = static_cast(parent_wa.width); m_height = static_cast(parent_wa.height); - } - XResizeWindow(m_display, m_window, m_width, m_height); + // Failed X calls terminate the process so no need to check for errors. + // We could swap the error handler out here as well. + m_colormap = XCreateColormap(m_display, m_parent_window, vi->visual, AllocNone); + + XSetWindowAttributes wa = {}; + wa.colormap = m_colormap; + + m_window = XCreateWindow(m_display, m_parent_window, 0, 0, m_width, m_height, 0, vi->depth, + InputOutput, vi->visual, CWColormap, &wa); + XMapWindow(m_display, m_window); + XSync(m_display, True); + + return true; +} + +void X11Window::Destroy() { + if (m_window) { + XUnmapWindow(m_display, m_window); + XDestroyWindow(m_display, m_window); + m_window = {}; + } + + if (m_colormap) { + XFreeColormap(m_display, m_colormap); + m_colormap = {}; + } +} + +void X11Window::Resize(u32 width, u32 height) { + if (width != 0 && height != 0) { + m_width = width; + m_height = height; + } else { + XWindowAttributes parent_wa = {}; + XGetWindowAttributes(m_display, m_parent_window, &parent_wa); + m_width = static_cast(parent_wa.width); + m_height = static_cast(parent_wa.height); + } + + XResizeWindow(m_display, m_window, m_width, m_height); } static X11InhibitErrors* s_current_error_inhibiter; -X11InhibitErrors::X11InhibitErrors() -{ - Assert(!s_current_error_inhibiter); - m_old_handler = XSetErrorHandler(ErrorHandler); - s_current_error_inhibiter = this; +X11InhibitErrors::X11InhibitErrors() { + Assert(!s_current_error_inhibiter); + m_old_handler = XSetErrorHandler(ErrorHandler); + s_current_error_inhibiter = this; } -X11InhibitErrors::~X11InhibitErrors() -{ - Assert(s_current_error_inhibiter == this); - s_current_error_inhibiter = nullptr; - XSetErrorHandler(m_old_handler); +X11InhibitErrors::~X11InhibitErrors() { + Assert(s_current_error_inhibiter == this); + s_current_error_inhibiter = nullptr; + XSetErrorHandler(m_old_handler); } -int X11InhibitErrors::ErrorHandler(Display* display, XErrorEvent* ee) -{ - char error_string[256] = {}; - XGetErrorText(display, ee->error_code, error_string, sizeof(error_string)); - Log_WarningPrintf("X11 Error: %s (Error %u Minor %u Request %u)", error_string, ee->error_code, ee->minor_code, - ee->request_code); +int X11InhibitErrors::ErrorHandler(Display* display, XErrorEvent* ee) { + char error_string[256] = {}; + XGetErrorText(display, ee->error_code, error_string, sizeof(error_string)); + Log_WarningPrintf("X11 Error: %s (Error %u Minor %u Request %u)", error_string, ee->error_code, + ee->minor_code, ee->request_code); - s_current_error_inhibiter->m_had_error = true; - return 0; + s_current_error_inhibiter->m_had_error = true; + return 0; } } // namespace GL diff --git a/src/citra_qt/externals/duckstation/gl/x11_window.h b/src/citra_qt/externals/duckstation/gl/x11_window.h index 9fa896f33..a8fa2f6cb 100644 --- a/src/citra_qt/externals/duckstation/gl/x11_window.h +++ b/src/citra_qt/externals/duckstation/gl/x11_window.h @@ -1,49 +1,55 @@ #pragma once -#include "../duckstation_compat.h" #include #include +#include "../duckstation_compat.h" namespace GL { using namespace citra; -class X11Window -{ +class X11Window { public: - X11Window(); - ~X11Window(); + X11Window(); + ~X11Window(); - ALWAYS_INLINE Window GetWindow() const { return m_window; } - ALWAYS_INLINE u32 GetWidth() const { return m_width; } - ALWAYS_INLINE u32 GetHeight() const { return m_height; } + ALWAYS_INLINE Window GetWindow() const { + return m_window; + } + ALWAYS_INLINE u32 GetWidth() const { + return m_width; + } + ALWAYS_INLINE u32 GetHeight() const { + return m_height; + } - bool Create(Display* display, Window parent_window, const XVisualInfo* vi); - void Destroy(); + bool Create(Display* display, Window parent_window, const XVisualInfo* vi); + void Destroy(); - // Setting a width/height of 0 will use parent dimensions. - void Resize(u32 width = 0, u32 height = 0); + // Setting a width/height of 0 will use parent dimensions. + void Resize(u32 width = 0, u32 height = 0); private: - Display* m_display = nullptr; - Window m_parent_window = {}; - Window m_window = {}; - Colormap m_colormap = {}; - u32 m_width = 0; - u32 m_height = 0; + Display* m_display = nullptr; + Window m_parent_window = {}; + Window m_window = {}; + Colormap m_colormap = {}; + u32 m_width = 0; + u32 m_height = 0; }; // Helper class for managing X errors -class X11InhibitErrors -{ +class X11InhibitErrors { public: - X11InhibitErrors(); - ~X11InhibitErrors(); + X11InhibitErrors(); + ~X11InhibitErrors(); - ALWAYS_INLINE bool HadError() const { return m_had_error; } + ALWAYS_INLINE bool HadError() const { + return m_had_error; + } private: - static int ErrorHandler(Display* display, XErrorEvent* ee); + static int ErrorHandler(Display* display, XErrorEvent* ee); - XErrorHandler m_old_handler = {}; - bool m_had_error = false; + XErrorHandler m_old_handler = {}; + bool m_had_error = false; }; } // namespace GL diff --git a/src/citra_qt/externals/duckstation/log.h b/src/citra_qt/externals/duckstation/log.h index a945bb35c..452d13fbf 100644 --- a/src/citra_qt/externals/duckstation/log.h +++ b/src/citra_qt/externals/duckstation/log.h @@ -5,42 +5,74 @@ #define Log_SetChannel(ChannelName) #define Log_ErrorPrint(msg) puts(msg "\n"); -#define Log_ErrorPrintf(...) do { printf(__VA_ARGS__); putchar('\n'); } while (0) +#define Log_ErrorPrintf(...) \ + do { \ + printf(__VA_ARGS__); \ + putchar('\n'); \ + } while (0) #define Log_WarningPrint(msg) puts(msg) -#define Log_WarningPrintf(...) do { printf(__VA_ARGS__); putchar('\n'); } while (0) +#define Log_WarningPrintf(...) \ + do { \ + printf(__VA_ARGS__); \ + putchar('\n'); \ + } while (0) #define Log_PerfPrint(msg) puts(msg) -#define Log_PerfPrintf(...) do { printf(__VA_ARGS__); putchar('\n'); } while (0) +#define Log_PerfPrintf(...) \ + do { \ + printf(__VA_ARGS__); \ + putchar('\n'); \ + } while (0) #define Log_InfoPrint(msg) puts(msg) -#define Log_InfoPrintf(...) do { printf(__VA_ARGS__); putchar('\n'); } while (0) +#define Log_InfoPrintf(...) \ + do { \ + printf(__VA_ARGS__); \ + putchar('\n'); \ + } while (0) #define Log_VerbosePrint(msg) puts(msg) -#define Log_VerbosePrintf(...) do { printf(__VA_ARGS__); putchar('\n'); } while (0) +#define Log_VerbosePrintf(...) \ + do { \ + printf(__VA_ARGS__); \ + putchar('\n'); \ + } while (0) #define Log_DevPrint(msg) puts(msg) -#define Log_DevPrintf(...) do { printf(__VA_ARGS__); putchar('\n'); } while (0) +#define Log_DevPrintf(...) \ + do { \ + printf(__VA_ARGS__); \ + putchar('\n'); \ + } while (0) #define Log_ProfilePrint(msg) puts(msg) -#define Log_ProfilePrintf(...) do { printf(__VA_ARGS__); putchar('\n'); } while (0) +#define Log_ProfilePrintf(...) \ + do { \ + printf(__VA_ARGS__); \ + putchar('\n'); \ + } while (0) #ifdef _DEBUG #define Log_DebugPrint(msg) puts(msg) -#define Log_DebugPrintf(...) do { printf(__VA_ARGS__); putchar('\n'); } while (0) +#define Log_DebugPrintf(...) \ + do { \ + printf(__VA_ARGS__); \ + putchar('\n'); \ + } while (0) #define Log_TracePrint(msg) puts(msg) -#define Log_TracePrintf(...) do { printf(__VA_ARGS__); putchar('\n'); } while (0) +#define Log_TracePrintf(...) \ + do { \ + printf(__VA_ARGS__); \ + putchar('\n'); \ + } while (0) #else -#define Log_DebugPrint(msg) \ - do \ - { \ - } while (0) -#define Log_DebugPrintf(...) \ - do \ - { \ - } while (0) -#define Log_TracePrint(msg) \ - do \ - { \ - } while (0) -#define Log_TracePrintf(...) \ - do \ - { \ - } while (0) +#define Log_DebugPrint(msg) \ + do { \ + } while (0) +#define Log_DebugPrintf(...) \ + do { \ + } while (0) +#define Log_TracePrint(msg) \ + do { \ + } while (0) +#define Log_TracePrintf(...) \ + do { \ + } while (0) #endif #endif \ No newline at end of file diff --git a/src/citra_qt/externals/duckstation/scoped_guard.h b/src/citra_qt/externals/duckstation/scoped_guard.h index 89f35d92f..cca821bba 100644 --- a/src/citra_qt/externals/duckstation/scoped_guard.h +++ b/src/citra_qt/externals/duckstation/scoped_guard.h @@ -5,30 +5,34 @@ /// ScopedGuard provides an object which runs a function (usually a lambda) when /// it goes out of scope. This can be useful for releasing resources or handles /// which do not normally have C++ types to automatically release. -template -class ScopedGuard final -{ +template +class ScopedGuard final { public: - ALWAYS_INLINE ScopedGuard(T&& func) : m_func(std::forward(func)) {} - ALWAYS_INLINE ScopedGuard(ScopedGuard&& other) : m_func(std::move(other.m_func)) { other.m_func = nullptr; } - ALWAYS_INLINE ~ScopedGuard() { Invoke(); } + ALWAYS_INLINE ScopedGuard(T&& func) : m_func(std::forward(func)) {} + ALWAYS_INLINE ScopedGuard(ScopedGuard&& other) : m_func(std::move(other.m_func)) { + other.m_func = nullptr; + } + ALWAYS_INLINE ~ScopedGuard() { + Invoke(); + } - ScopedGuard(const ScopedGuard&) = delete; - void operator=(const ScopedGuard&) = delete; + ScopedGuard(const ScopedGuard&) = delete; + void operator=(const ScopedGuard&) = delete; - /// Prevents the function from being invoked when we go out of scope. - ALWAYS_INLINE void Cancel() { m_func.reset(); } + /// Prevents the function from being invoked when we go out of scope. + ALWAYS_INLINE void Cancel() { + m_func.reset(); + } - /// Explicitly fires the function. - ALWAYS_INLINE void Invoke() - { - if (!m_func.has_value()) - return; + /// Explicitly fires the function. + ALWAYS_INLINE void Invoke() { + if (!m_func.has_value()) + return; - m_func.value()(); - m_func.reset(); - } + m_func.value()(); + m_func.reset(); + } private: - std::optional m_func; + std::optional m_func; }; diff --git a/src/citra_qt/externals/duckstation/window_info.cpp b/src/citra_qt/externals/duckstation/window_info.cpp index 5176dad62..615cd4baf 100644 --- a/src/citra_qt/externals/duckstation/window_info.cpp +++ b/src/citra_qt/externals/duckstation/window_info.cpp @@ -1,191 +1,175 @@ -#include "window_info.h" #include "common/log.h" +#include "window_info.h" Log_SetChannel(WindowInfo); #if defined(_WIN32) -#include "common/windows_headers.h" #include +#include "common/windows_headers.h" -static bool GetRefreshRateFromDWM(HWND hwnd, float* refresh_rate) -{ - static HMODULE dwm_module = nullptr; - static HRESULT(STDAPICALLTYPE * is_composition_enabled)(BOOL * pfEnabled) = nullptr; - static HRESULT(STDAPICALLTYPE * get_timing_info)(HWND hwnd, DWM_TIMING_INFO * pTimingInfo) = nullptr; - static bool load_tried = false; - if (!load_tried) - { - load_tried = true; - dwm_module = LoadLibrary("dwmapi.dll"); - if (dwm_module) - { - std::atexit([]() { - FreeLibrary(dwm_module); - dwm_module = nullptr; - }); - is_composition_enabled = - reinterpret_cast(GetProcAddress(dwm_module, "DwmIsCompositionEnabled")); - get_timing_info = - reinterpret_cast(GetProcAddress(dwm_module, "DwmGetCompositionTimingInfo")); +static bool GetRefreshRateFromDWM(HWND hwnd, float* refresh_rate) { + static HMODULE dwm_module = nullptr; + static HRESULT(STDAPICALLTYPE * is_composition_enabled)(BOOL * pfEnabled) = nullptr; + static HRESULT(STDAPICALLTYPE * get_timing_info)(HWND hwnd, DWM_TIMING_INFO * pTimingInfo) = + nullptr; + static bool load_tried = false; + if (!load_tried) { + load_tried = true; + dwm_module = LoadLibrary("dwmapi.dll"); + if (dwm_module) { + std::atexit([]() { + FreeLibrary(dwm_module); + dwm_module = nullptr; + }); + is_composition_enabled = reinterpret_cast( + GetProcAddress(dwm_module, "DwmIsCompositionEnabled")); + get_timing_info = reinterpret_cast( + GetProcAddress(dwm_module, "DwmGetCompositionTimingInfo")); + } + } + + BOOL composition_enabled; + if (!is_composition_enabled || + FAILED(is_composition_enabled(&composition_enabled) || !get_timing_info)) + return false; + + DWM_TIMING_INFO ti = {}; + ti.cbSize = sizeof(ti); + HRESULT hr = get_timing_info(nullptr, &ti); + if (SUCCEEDED(hr)) { + if (ti.rateRefresh.uiNumerator == 0 || ti.rateRefresh.uiDenominator == 0) + return false; + + *refresh_rate = static_cast(ti.rateRefresh.uiNumerator) / + static_cast(ti.rateRefresh.uiDenominator); + return true; } - } - BOOL composition_enabled; - if (!is_composition_enabled || FAILED(is_composition_enabled(&composition_enabled) || !get_timing_info)) return false; - - DWM_TIMING_INFO ti = {}; - ti.cbSize = sizeof(ti); - HRESULT hr = get_timing_info(nullptr, &ti); - if (SUCCEEDED(hr)) - { - if (ti.rateRefresh.uiNumerator == 0 || ti.rateRefresh.uiDenominator == 0) - return false; - - *refresh_rate = static_cast(ti.rateRefresh.uiNumerator) / static_cast(ti.rateRefresh.uiDenominator); - return true; - } - - return false; } -static bool GetRefreshRateFromMonitor(HWND hwnd, float* refresh_rate) -{ - HMONITOR mon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); - if (!mon) - return false; +static bool GetRefreshRateFromMonitor(HWND hwnd, float* refresh_rate) { + HMONITOR mon = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST); + if (!mon) + return false; - MONITORINFOEXW mi = {}; - mi.cbSize = sizeof(mi); - if (GetMonitorInfoW(mon, &mi)) - { - DEVMODEW dm = {}; - dm.dmSize = sizeof(dm); + MONITORINFOEXW mi = {}; + mi.cbSize = sizeof(mi); + if (GetMonitorInfoW(mon, &mi)) { + DEVMODEW dm = {}; + dm.dmSize = sizeof(dm); - // 0/1 are reserved for "defaults". - if (EnumDisplaySettingsW(mi.szDevice, ENUM_CURRENT_SETTINGS, &dm) && dm.dmDisplayFrequency > 1) - { - *refresh_rate = static_cast(dm.dmDisplayFrequency); - return true; + // 0/1 are reserved for "defaults". + if (EnumDisplaySettingsW(mi.szDevice, ENUM_CURRENT_SETTINGS, &dm) && + dm.dmDisplayFrequency > 1) { + *refresh_rate = static_cast(dm.dmDisplayFrequency); + return true; + } } - } - return false; + return false; } -bool WindowInfo::QueryRefreshRateForWindow(const WindowInfo& wi, float* refresh_rate) -{ - if (wi.type != Type::Win32 || !wi.window_handle) - return false; +bool WindowInfo::QueryRefreshRateForWindow(const WindowInfo& wi, float* refresh_rate) { + if (wi.type != Type::Win32 || !wi.window_handle) + return false; - // Try DWM first, then fall back to integer values. - const HWND hwnd = static_cast(wi.window_handle); - return GetRefreshRateFromDWM(hwnd, refresh_rate) || GetRefreshRateFromMonitor(hwnd, refresh_rate); + // Try DWM first, then fall back to integer values. + const HWND hwnd = static_cast(wi.window_handle); + return GetRefreshRateFromDWM(hwnd, refresh_rate) || + GetRefreshRateFromMonitor(hwnd, refresh_rate); } #else #ifdef USE_X11 +#include #include "common/scoped_guard.h" #include "gl/x11_window.h" -#include -static bool GetRefreshRateFromXRandR(const WindowInfo& wi, float* refresh_rate) -{ - Display* display = static_cast(wi.display_connection); - Window window = static_cast(reinterpret_cast(wi.window_handle)); - if (!display || !window) - return false; +static bool GetRefreshRateFromXRandR(const WindowInfo& wi, float* refresh_rate) { + Display* display = static_cast(wi.display_connection); + Window window = static_cast(reinterpret_cast(wi.window_handle)); + if (!display || !window) + return false; - GL::X11InhibitErrors inhibiter; + GL::X11InhibitErrors inhibiter; - XRRScreenResources* res = XRRGetScreenResources(display, window); - if (!res) - { - Log_ErrorPrint("XRRGetScreenResources() failed"); - return false; - } - - ScopedGuard res_guard([res]() { XRRFreeScreenResources(res); }); - - int num_monitors; - XRRMonitorInfo* mi = XRRGetMonitors(display, window, True, &num_monitors); - if (num_monitors < 0) - { - Log_ErrorPrint("XRRGetMonitors() failed"); - return false; - } - else if (num_monitors > 1) - { - Log_WarningPrintf("XRRGetMonitors() returned %d monitors, using first", num_monitors); - } - - ScopedGuard mi_guard([mi]() { XRRFreeMonitors(mi); }); - if (mi->noutput <= 0) - { - Log_ErrorPrint("Monitor has no outputs"); - return false; - } - else if (mi->noutput > 1) - { - Log_WarningPrintf("Monitor has %d outputs, using first", mi->noutput); - } - - XRROutputInfo* oi = XRRGetOutputInfo(display, res, mi->outputs[0]); - if (!oi) - { - Log_ErrorPrint("XRRGetOutputInfo() failed"); - return false; - } - - ScopedGuard oi_guard([oi]() { XRRFreeOutputInfo(oi); }); - - XRRCrtcInfo* ci = XRRGetCrtcInfo(display, res, oi->crtc); - if (!ci) - { - Log_ErrorPrint("XRRGetCrtcInfo() failed"); - return false; - } - - ScopedGuard ci_guard([ci]() { XRRFreeCrtcInfo(ci); }); - - XRRModeInfo* mode = nullptr; - for (int i = 0; i < res->nmode; i++) - { - if (res->modes[i].id == ci->mode) - { - mode = &res->modes[i]; - break; + XRRScreenResources* res = XRRGetScreenResources(display, window); + if (!res) { + Log_ErrorPrint("XRRGetScreenResources() failed"); + return false; } - } - if (!mode) - { - Log_ErrorPrintf("Failed to look up mode %d (of %d)", static_cast(ci->mode), res->nmode); - return false; - } - if (mode->dotClock == 0 || mode->hTotal == 0 || mode->vTotal == 0) - { - Log_ErrorPrintf("Modeline is invalid: %ld/%d/%d", mode->dotClock, mode->hTotal, mode->vTotal); - return false; - } + ScopedGuard res_guard([res]() { XRRFreeScreenResources(res); }); - *refresh_rate = - static_cast(mode->dotClock) / (static_cast(mode->hTotal) * static_cast(mode->vTotal)); - return true; + int num_monitors; + XRRMonitorInfo* mi = XRRGetMonitors(display, window, True, &num_monitors); + if (num_monitors < 0) { + Log_ErrorPrint("XRRGetMonitors() failed"); + return false; + } else if (num_monitors > 1) { + Log_WarningPrintf("XRRGetMonitors() returned %d monitors, using first", num_monitors); + } + + ScopedGuard mi_guard([mi]() { XRRFreeMonitors(mi); }); + if (mi->noutput <= 0) { + Log_ErrorPrint("Monitor has no outputs"); + return false; + } else if (mi->noutput > 1) { + Log_WarningPrintf("Monitor has %d outputs, using first", mi->noutput); + } + + XRROutputInfo* oi = XRRGetOutputInfo(display, res, mi->outputs[0]); + if (!oi) { + Log_ErrorPrint("XRRGetOutputInfo() failed"); + return false; + } + + ScopedGuard oi_guard([oi]() { XRRFreeOutputInfo(oi); }); + + XRRCrtcInfo* ci = XRRGetCrtcInfo(display, res, oi->crtc); + if (!ci) { + Log_ErrorPrint("XRRGetCrtcInfo() failed"); + return false; + } + + ScopedGuard ci_guard([ci]() { XRRFreeCrtcInfo(ci); }); + + XRRModeInfo* mode = nullptr; + for (int i = 0; i < res->nmode; i++) { + if (res->modes[i].id == ci->mode) { + mode = &res->modes[i]; + break; + } + } + if (!mode) { + Log_ErrorPrintf("Failed to look up mode %d (of %d)", static_cast(ci->mode), + res->nmode); + return false; + } + + if (mode->dotClock == 0 || mode->hTotal == 0 || mode->vTotal == 0) { + Log_ErrorPrintf("Modeline is invalid: %ld/%d/%d", mode->dotClock, mode->hTotal, + mode->vTotal); + return false; + } + + *refresh_rate = static_cast(mode->dotClock) / + (static_cast(mode->hTotal) * static_cast(mode->vTotal)); + return true; } #endif // USE_X11 -bool WindowInfo::QueryRefreshRateForWindow(const WindowInfo& wi, float* refresh_rate) -{ +bool WindowInfo::QueryRefreshRateForWindow(const WindowInfo& wi, float* refresh_rate) { #if defined(USE_X11) - if (wi.type == WindowInfo::Type::X11) - return GetRefreshRateFromXRandR(wi, refresh_rate); + if (wi.type == WindowInfo::Type::X11) + return GetRefreshRateFromXRandR(wi, refresh_rate); #endif - return false; + return false; } #endif \ No newline at end of file diff --git a/src/citra_qt/externals/duckstation/window_info.h b/src/citra_qt/externals/duckstation/window_info.h index 0a92a2dd8..848cc3703 100644 --- a/src/citra_qt/externals/duckstation/window_info.h +++ b/src/citra_qt/externals/duckstation/window_info.h @@ -2,42 +2,32 @@ #include "../types.h" // Contains the information required to create a graphics context in a window. -struct WindowInfo -{ - enum class Type - { - Surfaceless, - Win32, - X11, - Wayland, - MacOS, - Android, - Display, - }; +struct WindowInfo { + enum class Type { + Surfaceless, + Win32, + X11, + Wayland, + MacOS, + Android, + Display, + }; - enum class SurfaceFormat - { - None, - Auto, - RGB8, - RGBA8, - RGB565, - Count - }; + enum class SurfaceFormat { None, Auto, RGB8, RGBA8, RGB565, Count }; - Type type = Type::Surfaceless; - void* display_connection = nullptr; - void* window_handle = nullptr; - citra::u32 surface_width = 0; - citra::u32 surface_height = 0; - float surface_refresh_rate = 0.0f; - float surface_scale = 1.0f; - SurfaceFormat surface_format = SurfaceFormat::RGB8; + Type type = Type::Surfaceless; + void* display_connection = nullptr; + void* window_handle = nullptr; + citra::u32 surface_width = 0; + citra::u32 surface_height = 0; + float surface_refresh_rate = 0.0f; + float surface_scale = 1.0f; + SurfaceFormat surface_format = SurfaceFormat::RGB8; - // Needed for macOS. + // Needed for macOS. #ifdef __APPLE__ - void* surface_handle = nullptr; + void* surface_handle = nullptr; #endif - static bool QueryRefreshRateForWindow(const WindowInfo& wi, float* refresh_rate); + static bool QueryRefreshRateForWindow(const WindowInfo& wi, float* refresh_rate); }; diff --git a/src/citra_qt/externals/types.h b/src/citra_qt/externals/types.h index a6cc1b46c..8d0c3edb9 100644 --- a/src/citra_qt/externals/types.h +++ b/src/citra_qt/externals/types.h @@ -19,21 +19,20 @@ #ifndef TYPES_H #define TYPES_H -#include #include +#include -namespace citra -{ -typedef uint8_t u8; -typedef uint16_t u16; -typedef uint32_t u32; -typedef uint64_t u64; -typedef int8_t s8; -typedef int16_t s16; -typedef int32_t s32; -typedef int64_t s64; +namespace citra { +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; +typedef int8_t s8; +typedef int16_t s16; +typedef int32_t s32; +typedef int64_t s64; -template +template using array2d = std::array, A>; -} +} // namespace citra #endif // TYPES_H