From 74b82bab3b6e4e8a1799bbcbdc5244f20f4d2826 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Wed, 3 Oct 2018 22:28:38 +1000 Subject: [PATCH 01/12] GLInterface: Drop Haiku support --- CMakeLists.txt | 15 +--- Source/Core/Common/CMakeLists.txt | 6 -- Source/Core/Common/GL/GLInterface/BGL.cpp | 70 ------------------- Source/Core/Common/GL/GLInterface/BGL.h | 27 ------- .../Core/Common/GL/GLInterface/EGLHaiku.cpp | 30 -------- Source/Core/Common/GL/GLInterface/EGLHaiku.h | 16 ----- .../Common/GL/GLInterface/GLInterface.cpp | 5 -- Source/Core/VideoCommon/DriverDetails.cpp | 2 - Source/Core/VideoCommon/DriverDetails.h | 1 - 9 files changed, 3 insertions(+), 169 deletions(-) delete mode 100644 Source/Core/Common/GL/GLInterface/BGL.cpp delete mode 100644 Source/Core/Common/GL/GLInterface/BGL.h delete mode 100644 Source/Core/Common/GL/GLInterface/EGLHaiku.cpp delete mode 100644 Source/Core/Common/GL/GLInterface/EGLHaiku.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 1466e27810..3b336a88cb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -87,13 +87,8 @@ set_property(GLOBAL PROPERTY USE_FOLDERS ON) # Set up paths set(bindir ${CMAKE_INSTALL_PREFIX}/bin CACHE PATH "bindir") -if(HAIKU) - set(datadir ${CMAKE_INSTALL_PREFIX}/data/dolphin-emu CACHE PATH "datadir") - set(mandir ${CMAKE_INSTALL_PREFIX}/documentation/man CACHE PATH "mandir") -else() - set(datadir ${CMAKE_INSTALL_PREFIX}/share/dolphin-emu CACHE PATH "datadir") - set(mandir ${CMAKE_INSTALL_PREFIX}/share/man CACHE PATH "mandir") -endif() +set(datadir ${CMAKE_INSTALL_PREFIX}/share/dolphin-emu CACHE PATH "datadir") +set(mandir ${CMAKE_INSTALL_PREFIX}/share/man CACHE PATH "mandir") add_definitions(-DDATA_DIR="${datadir}/") if(CMAKE_SYSROOT) @@ -381,10 +376,6 @@ if(ANDROID) SET(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) SET(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) SET(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) -elseif(HAIKU) - set(USE_X11 0) - set(USE_UPNP 0) - set(USE_EGL 0) endif() if(ENABLE_HEADLESS) @@ -427,7 +418,7 @@ endif() set(USE_X11 0) -if(UNIX AND NOT APPLE AND NOT ANDROID AND NOT HAIKU AND NOT ENABLE_HEADLESS) +if(UNIX AND NOT APPLE AND NOT ANDROID AND NOT ENABLE_HEADLESS) find_package(X11) if(TRY_X11 AND X11_FOUND) set(USE_X11 1) diff --git a/Source/Core/Common/CMakeLists.txt b/Source/Core/Common/CMakeLists.txt index 507e08662e..d0ac4a48cd 100644 --- a/Source/Core/Common/CMakeLists.txt +++ b/Source/Core/Common/CMakeLists.txt @@ -130,9 +130,6 @@ if(WIN32) ) elseif(APPLE) target_sources(common PRIVATE GL/GLInterface/AGL.mm) -elseif(HAIKU) - target_sources(common PRIVATE GL/GLInterface/BGL.cpp) - target_link_libraries(common PUBLIC be GL) elseif(USE_X11) if (NOT USE_EGL) target_sources(common PRIVATE GL/GLInterface/GLX.cpp) @@ -163,9 +160,6 @@ if(UNIX) if(SYSTEMD_FOUND) target_link_libraries(traversal_server PRIVATE ${SYSTEMD_LIBRARIES}) endif() - if(HAIKU) - target_link_libraries(traversal_server PRIVATE network) - endif() elseif(WIN32) target_link_libraries(common PRIVATE "-INCLUDE:enableCompatPatches") endif() diff --git a/Source/Core/Common/GL/GLInterface/BGL.cpp b/Source/Core/Common/GL/GLInterface/BGL.cpp deleted file mode 100644 index ed2670efc5..0000000000 --- a/Source/Core/Common/GL/GLInterface/BGL.cpp +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2017 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -#include "Common/GL/GLInterface/BGL.h" - -#include -#include -#include - -void cInterfaceBGL::Swap() -{ - m_gl->SwapBuffers(); -} - -bool cInterfaceBGL::Create(void* window_handle, bool stereo, bool core) -{ - m_window = static_cast(window_handle); - - m_gl = new BGLView(m_window->Bounds(), "cInterfaceBGL", B_FOLLOW_ALL_SIDES, 0, - BGL_RGB | BGL_DOUBLE | BGL_ALPHA); - m_window->AddChild(m_gl); - - s_opengl_mode = GLInterfaceMode::MODE_OPENGL; - - // Control m_window size and picture scaling - BRect size = m_gl->Frame(); - s_backbuffer_width = size.IntegerWidth(); - s_backbuffer_height = size.IntegerHeight(); - - return true; -} - -bool cInterfaceBGL::MakeCurrent() -{ - m_gl->LockGL(); - return true; -} - -bool cInterfaceBGL::ClearCurrent() -{ - m_gl->UnlockGL(); - return true; -} - -void cInterfaceBGL::Shutdown() -{ - // We don't need to delete m_gl, it's owned by the BWindow. - m_gl = nullptr; -} - -void cInterfaceBGL::Update() -{ - BRect size = m_gl->Frame(); - - if (s_backbuffer_width == size.IntegerWidth() && s_backbuffer_height == size.IntegerHeight()) - return; - - s_backbuffer_width = size.IntegerWidth(); - s_backbuffer_height = size.IntegerHeight(); -} - -void cInterfaceBGL::SwapInterval(int interval) -{ -} - -void* cInterfaceBGL::GetFuncAddress(const std::string& name) -{ - return m_gl->GetGLProcAddress(name.c_str()); -} diff --git a/Source/Core/Common/GL/GLInterface/BGL.h b/Source/Core/Common/GL/GLInterface/BGL.h deleted file mode 100644 index b26e5e3fc8..0000000000 --- a/Source/Core/Common/GL/GLInterface/BGL.h +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2017 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -#pragma once - -#include "Common/GL/GLInterfaceBase.h" - -class BWindow; -class BGLView; - -class cInterfaceBGL final : public cInterfaceBase -{ -public: - void Swap() override; - void* GetFuncAddress(const std::string& name) override; - bool Create(void* window_handle, bool stereo, bool core) override; - bool MakeCurrent() override; - bool ClearCurrent() override; - void Shutdown() override; - void Update() override; - void SwapInterval(int interval) override; - -private: - BWindow* m_window; - BGLView* m_gl; -}; diff --git a/Source/Core/Common/GL/GLInterface/EGLHaiku.cpp b/Source/Core/Common/GL/GLInterface/EGLHaiku.cpp deleted file mode 100644 index 253b9c8c98..0000000000 --- a/Source/Core/Common/GL/GLInterface/EGLHaiku.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2017 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -#include "Common/GL/GLInterface/EGLHaiku.h" - -#include - -EGLDisplay cInterfaceEGLHaiku::OpenDisplay() -{ - return eglGetDisplay(EGL_DEFAULT_DISPLAY); -} - -EGLNativeWindowType cInterfaceEGLHaiku::InitializePlatform(EGLNativeWindowType host_window, - EGLConfig config) -{ - EGLint format; - eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &format); - - BWindow* window = reinterpret_cast(host_window); - const int width = window->Size().width; - const int height = window->Size().height; - GLInterface->SetBackBufferDimensions(width, height); - - return host_window; -} - -void cInterfaceEGLHaiku::ShutdownPlatform() -{ -} diff --git a/Source/Core/Common/GL/GLInterface/EGLHaiku.h b/Source/Core/Common/GL/GLInterface/EGLHaiku.h deleted file mode 100644 index fc755963df..0000000000 --- a/Source/Core/Common/GL/GLInterface/EGLHaiku.h +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2017 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -#pragma once - -#include "Common/GL/GLInterface/EGL.h" - -class cInterfaceEGLHaiku final : public cInterfaceEGL -{ -protected: - EGLDisplay OpenDisplay() override; - EGLNativeWindowType InitializePlatform(EGLNativeWindowType host_window, - EGLConfig config) override; - void ShutdownPlatform() override; -}; diff --git a/Source/Core/Common/GL/GLInterface/GLInterface.cpp b/Source/Core/Common/GL/GLInterface/GLInterface.cpp index edd84cc2ab..a6ae0c0991 100644 --- a/Source/Core/Common/GL/GLInterface/GLInterface.cpp +++ b/Source/Core/Common/GL/GLInterface/GLInterface.cpp @@ -20,9 +20,6 @@ #include "Common/GL/GLInterface/EGL.h" #elif ANDROID #include "Common/GL/GLInterface/EGLAndroid.h" -#elif defined(__HAIKU__) -#include "Common/GL/GLInterface/BGL.h" -#else #error Platform doesnt have a GLInterface #endif @@ -42,8 +39,6 @@ std::unique_ptr HostGL_CreateGLInterface() #endif #elif ANDROID return std::make_unique(); -#elif defined(__HAIKU__) - return std::make_unique(); #else return nullptr; #endif diff --git a/Source/Core/VideoCommon/DriverDetails.cpp b/Source/Core/VideoCommon/DriverDetails.cpp index 301c73d89f..fd52d3dd6b 100644 --- a/Source/Core/VideoCommon/DriverDetails.cpp +++ b/Source/Core/VideoCommon/DriverDetails.cpp @@ -35,8 +35,6 @@ const u32 m_os = OS_ALL | OS_LINUX; const u32 m_os = OS_ALL | OS_FREEBSD; #elif __OpenBSD__ const u32 m_os = OS_ALL | OS_OPENBSD; -#elif __HAIKU__ -const u32 m_os = OS_ALL | OS_HAIKU; #endif static API m_api = API_OPENGL; diff --git a/Source/Core/VideoCommon/DriverDetails.h b/Source/Core/VideoCommon/DriverDetails.h index 9ace5f83b4..7d60b0e168 100644 --- a/Source/Core/VideoCommon/DriverDetails.h +++ b/Source/Core/VideoCommon/DriverDetails.h @@ -27,7 +27,6 @@ enum OS OS_ANDROID = (1 << 4), OS_FREEBSD = (1 << 5), OS_OPENBSD = (1 << 6), - OS_HAIKU = (1 << 7), }; // Enum of known vendors // Tegra and Nvidia are separated out due to such substantial differences From 134d967be2dd4ba9531abb8ba8494c3ac423ca72 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Wed, 3 Oct 2018 23:02:45 +1000 Subject: [PATCH 02/12] Refactoring and cleanup of GLInterface (now GLContext) --- Source/Android/jni/MainAndroid.cpp | 1 - Source/Core/Common/CMakeLists.txt | 4 +- Source/Core/Common/Common.vcxproj | 6 +- Source/Core/Common/Common.vcxproj.filters | 14 +- Source/Core/Common/GL/GLContext.cpp | 115 ++++++++++ Source/Core/Common/GL/GLContext.h | 64 ++++++ .../Common/GL/GLExtensions/GLExtensions.cpp | 8 +- Source/Core/Common/GL/GLInterface/AGL.h | 26 ++- Source/Core/Common/GL/GLInterface/AGL.mm | 47 ++-- Source/Core/Common/GL/GLInterface/EGL.cpp | 217 +++++++++--------- Source/Core/Common/GL/GLInterface/EGL.h | 66 +++--- .../Core/Common/GL/GLInterface/EGLAndroid.cpp | 23 +- .../Core/Common/GL/GLInterface/EGLAndroid.h | 9 +- Source/Core/Common/GL/GLInterface/EGLX11.cpp | 48 ++-- Source/Core/Common/GL/GLInterface/EGLX11.h | 18 +- .../Common/GL/GLInterface/GLInterface.cpp | 45 ---- Source/Core/Common/GL/GLInterface/GLX.cpp | 142 ++++++------ Source/Core/Common/GL/GLInterface/GLX.h | 52 +++-- Source/Core/Common/GL/GLInterface/WGL.cpp | 75 +++--- Source/Core/Common/GL/GLInterface/WGL.h | 24 +- .../Core/Common/GL/GLInterface/X11_Util.cpp | 72 ------ Source/Core/Common/GL/GLInterface/X11_Util.h | 27 --- Source/Core/Common/GL/GLInterfaceBase.h | 61 ----- Source/Core/Common/GL/GLUtil.cpp | 13 +- Source/Core/Common/GL/GLUtil.h | 3 +- Source/Core/Common/GL/GLX11Window.cpp | 77 +++++++ Source/Core/Common/GL/GLX11Window.h | 41 ++++ .../VideoBackends/OGL/FramebufferManager.cpp | 4 +- Source/Core/VideoBackends/OGL/OGLTexture.cpp | 1 - Source/Core/VideoBackends/OGL/PerfQuery.cpp | 9 +- .../VideoBackends/OGL/ProgramShaderCache.cpp | 8 +- Source/Core/VideoBackends/OGL/Render.cpp | 40 ++-- .../Core/VideoBackends/OGL/SamplerCache.cpp | 6 +- .../Core/VideoBackends/OGL/TextureCache.cpp | 1 - Source/Core/VideoBackends/OGL/main.cpp | 20 +- .../VideoBackends/Software/SWOGLWindow.cpp | 31 +-- .../Core/VideoBackends/Software/SWOGLWindow.h | 2 - Source/Core/VideoBackends/Software/SWmain.cpp | 6 +- Source/UnitTests/StubHost.cpp | 5 - 39 files changed, 741 insertions(+), 690 deletions(-) create mode 100644 Source/Core/Common/GL/GLContext.cpp create mode 100644 Source/Core/Common/GL/GLContext.h delete mode 100644 Source/Core/Common/GL/GLInterface/GLInterface.cpp delete mode 100644 Source/Core/Common/GL/GLInterface/X11_Util.cpp delete mode 100644 Source/Core/Common/GL/GLInterface/X11_Util.h delete mode 100644 Source/Core/Common/GL/GLInterfaceBase.h create mode 100644 Source/Core/Common/GL/GLX11Window.cpp create mode 100644 Source/Core/Common/GL/GLX11Window.h diff --git a/Source/Android/jni/MainAndroid.cpp b/Source/Android/jni/MainAndroid.cpp index 4d230fca60..34a19f6426 100644 --- a/Source/Android/jni/MainAndroid.cpp +++ b/Source/Android/jni/MainAndroid.cpp @@ -22,7 +22,6 @@ #include "Common/CommonTypes.h" #include "Common/Event.h" #include "Common/FileUtil.h" -#include "Common/GL/GLInterfaceBase.h" #include "Common/Logging/LogManager.h" #include "Common/MsgHandler.h" #include "Common/Version.h" diff --git a/Source/Core/Common/CMakeLists.txt b/Source/Core/Common/CMakeLists.txt index d0ac4a48cd..f6430c04f3 100644 --- a/Source/Core/Common/CMakeLists.txt +++ b/Source/Core/Common/CMakeLists.txt @@ -110,7 +110,7 @@ endif() target_sources(common PRIVATE GL/GLUtil.cpp GL/GLExtensions/GLExtensions.cpp - GL/GLInterface/GLInterface.cpp + GL/GLContext.cpp ) if(USE_EGL) @@ -137,7 +137,7 @@ elseif(USE_X11) # Make sure to link to it if using GLX. target_link_libraries(common PUBLIC ${OPENGL_LIBRARIES}) endif() - target_sources(common PRIVATE GL/GLInterface/X11_Util.cpp) + target_sources(common PRIVATE GL/GLX11Window.cpp) target_link_libraries(common PUBLIC ${XRANDR_LIBRARIES}) endif() diff --git a/Source/Core/Common/Common.vcxproj b/Source/Core/Common/Common.vcxproj index d0751f8c3f..23752002cf 100644 --- a/Source/Core/Common/Common.vcxproj +++ b/Source/Core/Common/Common.vcxproj @@ -121,7 +121,7 @@ - + @@ -189,7 +189,7 @@ - + @@ -255,4 +255,4 @@ - + \ No newline at end of file diff --git a/Source/Core/Common/Common.vcxproj.filters b/Source/Core/Common/Common.vcxproj.filters index 3737a5a1ff..63a131a8dc 100644 --- a/Source/Core/Common/Common.vcxproj.filters +++ b/Source/Core/Common/Common.vcxproj.filters @@ -243,9 +243,6 @@ GL\GLInterface - - GL\GLInterface - @@ -275,6 +272,9 @@ Debug + + GL\GLInterface + @@ -339,9 +339,6 @@ GL\GLInterface - - GL\GLInterface - @@ -355,6 +352,9 @@ Debug + + GL\GLInterface + @@ -362,4 +362,4 @@ - + \ No newline at end of file diff --git a/Source/Core/Common/GL/GLContext.cpp b/Source/Core/Common/GL/GLContext.cpp new file mode 100644 index 0000000000..da22f45c3b --- /dev/null +++ b/Source/Core/Common/GL/GLContext.cpp @@ -0,0 +1,115 @@ +// Copyright 2014 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include + +#include "Common/GL/GLContext.h" + +#if defined(__APPLE__) +#include "Common/GL/GLInterface/AGL.h" +#elif defined(_WIN32) +#include "Common/GL/GLInterface/WGL.h" +#elif HAVE_X11 +#if defined(USE_EGL) && USE_EGL +#include "Common/GL/GLInterface/EGLX11.h" +#else +#include "Common/GL/GLInterface/GLX.h" +#endif +#elif defined(USE_EGL) && USE_EGL && defined(USE_HEADLESS) +#include "Common/GL/GLInterface/EGL.h" +#elif ANDROID +#include "Common/GL/GLInterface/EGLAndroid.h" +#error Platform doesnt have a GLInterface +#endif + +std::unique_ptr g_main_gl_context; + +GLContext::~GLContext() = default; + +bool GLContext::Initialize(void* window_handle, bool stereo, bool core) +{ + return false; +} + +bool GLContext::Initialize(GLContext* main_context) +{ + return false; +} + +void GLContext::SetBackBufferDimensions(u32 w, u32 h) +{ + m_backbuffer_width = w; + m_backbuffer_height = h; +} + +bool GLContext::IsHeadless() const +{ + return true; +} + +std::unique_ptr GLContext::CreateSharedContext() +{ + return nullptr; +} + +bool GLContext::MakeCurrent() +{ + return false; +} + +bool GLContext::ClearCurrent() +{ + return false; +} + +void GLContext::Shutdown() +{ +} + +void GLContext::Update() +{ +} + +void GLContext::UpdateSurface(void* window_handle) +{ +} + +void GLContext::Swap() +{ +} + +void GLContext::SwapInterval(int interval) +{ +} + +void* GLContext::GetFuncAddress(const std::string& name) +{ + return nullptr; +} + +std::unique_ptr GLContext::Create(void* window_handle, bool stereo, bool core) +{ + std::unique_ptr context; +#if defined(__APPLE__) + context = std::make_unique(); +#elif defined(_WIN32) + context = std::make_unique(); +#elif defined(USE_EGL) && defined(USE_HEADLESS) + context = std::make_unique(); +#elif defined(HAVE_X11) && HAVE_X11 +#if defined(USE_EGL) && USE_EGL + context = std::make_unique(); +#else + context = std::make_unique(); +#endif +#elif ANDROID + context = std::make_unique(); +#else + return nullptr; +#endif + if (!context->Initialize(window_handle, stereo, core)) + return nullptr; + + return context; +} diff --git a/Source/Core/Common/GL/GLContext.h b/Source/Core/Common/GL/GLContext.h new file mode 100644 index 0000000000..990883ca90 --- /dev/null +++ b/Source/Core/Common/GL/GLContext.h @@ -0,0 +1,64 @@ +// Copyright 2008 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include +#include + +#include "Common/CommonTypes.h" + +class GLContext +{ +public: + enum class Mode + { + Detect, + OpenGL, + OpenGLES + }; + + virtual ~GLContext(); + + Mode GetMode() { return m_opengl_mode; } + bool IsGLES() const { return m_opengl_mode == Mode::OpenGLES; } + + u32 GetBackBufferWidth() { return m_backbuffer_width; } + u32 GetBackBufferHeight() { return m_backbuffer_height; } + void SetBackBufferDimensions(u32 w, u32 h); + + virtual bool IsHeadless() const; + + virtual std::unique_ptr CreateSharedContext(); + virtual void Shutdown(); + + virtual bool MakeCurrent(); + virtual bool ClearCurrent(); + + virtual void Update(); + virtual void UpdateSurface(void* window_handle); + + virtual void Swap(); + virtual void SwapInterval(int interval); + + virtual void* GetFuncAddress(const std::string& name); + + // Creates an instance of GLInterface specific to the platform we are running on. + static std::unique_ptr Create(void* window_handle, bool stereo = false, + bool core = true); + +protected: + virtual bool Initialize(void* window_handle, bool stereo, bool core); + virtual bool Initialize(GLContext* main_context); + + Mode m_opengl_mode = Mode::Detect; + + // Window dimensions. + u32 m_backbuffer_width = 0; + u32 m_backbuffer_height = 0; + bool m_is_core_context = false; + bool m_is_shared = false; +}; + +extern std::unique_ptr g_main_gl_context; diff --git a/Source/Core/Common/GL/GLExtensions/GLExtensions.cpp b/Source/Core/Common/GL/GLExtensions/GLExtensions.cpp index 9252a7bed3..18c4dc2f39 100644 --- a/Source/Core/Common/GL/GLExtensions/GLExtensions.cpp +++ b/Source/Core/Common/GL/GLExtensions/GLExtensions.cpp @@ -5,8 +5,8 @@ #include #include +#include "Common/GL/GLContext.h" #include "Common/GL/GLExtensions/GLExtensions.h" -#include "Common/GL/GLInterfaceBase.h" #include "Common/Logging/Log.h" #if defined(__linux__) || defined(__APPLE__) @@ -2432,7 +2432,7 @@ static void InitVersion() static void* GetFuncAddress(const std::string& name, void** func) { - *func = GLInterface->GetFuncAddress(name); + *func = g_main_gl_context->GetFuncAddress(name); if (*func == nullptr) { #if defined(__linux__) || defined(__APPLE__) @@ -2457,7 +2457,7 @@ bool Supports(const std::string& name) bool Init() { - _isES = GLInterface->GetMode() != GLInterfaceMode::MODE_OPENGL; + _isES = g_main_gl_context->GetMode() == GLContext::Mode::OpenGLES; // Grab a few functions for initial checking // We need them to grab the extension list @@ -2507,4 +2507,4 @@ bool InitFunctionPointers() result &= !!GetFuncAddress(it.function_name, it.function_ptr); return result; } -} +} // namespace GLExtensions diff --git a/Source/Core/Common/GL/GLInterface/AGL.h b/Source/Core/Common/GL/GLInterface/AGL.h index 8d62086954..3032fe573d 100644 --- a/Source/Core/Common/GL/GLInterface/AGL.h +++ b/Source/Core/Common/GL/GLInterface/AGL.h @@ -12,22 +12,28 @@ struct NSOpenGLPixelFormat; struct NSView; #endif -#include "Common/GL/GLInterfaceBase.h" +#include "Common/GL/GLContext.h" -class cInterfaceAGL : public cInterfaceBase +class GLContextAGL : public GLContext { public: - void Swap() override; - bool Create(void* window_handle, bool stereo, bool core) override; - bool Create(cInterfaceBase* main_context) override; + bool IsHeadless() const override; + + std::unique_ptr CreateSharedContext() override; + void Shutdown() override; + bool MakeCurrent() override; bool ClearCurrent() override; - void Shutdown() override; - void Update() override; - void SwapInterval(int interval) override; - std::unique_ptr CreateSharedContext() override; -private: + void Update() override; + + void Swap() override; + void SwapInterval(int interval) override; + +protected: + bool Initialize(void* window_handle, bool stereo, bool core) override; + bool Initialize(GLContext* main_context) override; + NSView* m_view = nullptr; NSOpenGLContext* m_context = nullptr; NSOpenGLPixelFormat* m_pixel_format = nullptr; diff --git a/Source/Core/Common/GL/GLInterface/AGL.mm b/Source/Core/Common/GL/GLInterface/AGL.mm index 07502475f7..80b82f917e 100644 --- a/Source/Core/Common/GL/GLInterface/AGL.mm +++ b/Source/Core/Common/GL/GLInterface/AGL.mm @@ -10,16 +10,15 @@ static bool UpdateCachedDimensions(NSView* view, u32* width, u32* height) NSWindow* window = [view window]; NSSize size = [view frame].size; - float scale = [window backingScaleFactor]; - size.width *= scale; - size.height *= scale; + const CGFloat scale = [window backingScaleFactor]; + u32 new_width = static_cast(size.width * scale); + u32 new_height = static_cast(size.height * scale); - if (*width == size.width && *height == size.height) + if (*width == new_width && *height == new_height) return false; - *width = size.width; - *height = size.height; - + *width = new_width; + *height = new_height; return true; } @@ -44,14 +43,19 @@ static bool AttachContextToView(NSOpenGLContext* context, NSView* view, u32* wid return true; } -void cInterfaceAGL::Swap() +bool GLContextAGL::IsHeadless() const +{ + return !m_view; +} + +void GLContextAGL::Swap() { [m_context flushBuffer]; } // Create rendering window. // Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize() -bool cInterfaceAGL::Create(void* window_handle, bool stereo, bool core) +bool GLContextAGL::Initialize(void* window_handle, bool stereo, bool core) { NSOpenGLPixelFormatAttribute attr[] = { NSOpenGLPFADoubleBuffer, @@ -78,12 +82,13 @@ bool cInterfaceAGL::Create(void* window_handle, bool stereo, bool core) return true; m_view = static_cast(window_handle); - return AttachContextToView(m_context, m_view, &s_backbuffer_width, &s_backbuffer_height); + m_opengl_mode = Mode::OpenGL; + return AttachContextToView(m_context, m_view, &m_backbuffer_width, &m_backbuffer_height); } -bool cInterfaceAGL::Create(cInterfaceBase* main_context) +bool GLContextAGL::Initialize(GLContext* main_context) { - cInterfaceAGL* agl_context = static_cast(main_context); + GLContextAGL* agl_context = static_cast(main_context); NSOpenGLPixelFormat* pixel_format = agl_context->m_pixel_format; NSOpenGLContext* share_context = agl_context->m_context; @@ -97,28 +102,28 @@ bool cInterfaceAGL::Create(cInterfaceBase* main_context) return true; } -std::unique_ptr cInterfaceAGL::CreateSharedContext() +std::unique_ptr GLContextAGL::CreateSharedContext() { - std::unique_ptr context = std::make_unique(); - if (!context->Create(this)) + std::unique_ptr context = std::make_unique(); + if (!context->Initialize(this)) return nullptr; return context; } -bool cInterfaceAGL::MakeCurrent() +bool GLContextAGL::MakeCurrent() { [m_context makeCurrentContext]; return true; } -bool cInterfaceAGL::ClearCurrent() +bool GLContextAGL::ClearCurrent() { [NSOpenGLContext clearCurrentContext]; return true; } // Close backend -void cInterfaceAGL::Shutdown() +void GLContextAGL::Shutdown() { [m_context clearDrawable]; [m_context release]; @@ -127,16 +132,16 @@ void cInterfaceAGL::Shutdown() m_pixel_format = nil; } -void cInterfaceAGL::Update() +void GLContextAGL::Update() { if (!m_view) return; - if (UpdateCachedDimensions(m_view, &s_backbuffer_width, &s_backbuffer_height)) + if (UpdateCachedDimensions(m_view, &m_backbuffer_width, &m_backbuffer_height)) [m_context update]; } -void cInterfaceAGL::SwapInterval(int interval) +void GLContextAGL::SwapInterval(int interval) { [m_context setValues:static_cast(&interval) forParameter:NSOpenGLCPSwapInterval]; } diff --git a/Source/Core/Common/GL/GLInterface/EGL.cpp b/Source/Core/Common/GL/GLInterface/EGL.cpp index e71b365928..46073fe074 100644 --- a/Source/Core/Common/GL/GLInterface/EGL.cpp +++ b/Source/Core/Common/GL/GLInterface/EGL.cpp @@ -28,35 +28,35 @@ #define EGL_OPENGL_ES3_BIT_KHR 0x00000040 #endif /* EGL_KHR_create_context */ -// Show the current FPS -void cInterfaceEGL::Swap() +GLContextEGL::~GLContextEGL() = default; + +bool GLContextEGL::IsHeadless() const { - if (egl_surf != EGL_NO_SURFACE) - eglSwapBuffers(egl_dpy, egl_surf); -} -void cInterfaceEGL::SwapInterval(int Interval) -{ - eglSwapInterval(egl_dpy, Interval); + return m_host_window == nullptr; } -void* cInterfaceEGL::GetFuncAddress(const std::string& name) +void GLContextEGL::Swap() +{ + if (m_egl_surface != EGL_NO_SURFACE) + eglSwapBuffers(m_egl_display, m_egl_surface); +} +void GLContextEGL::SwapInterval(int interval) +{ + eglSwapInterval(m_egl_display, interval); +} + +void* GLContextEGL::GetFuncAddress(const std::string& name) { return (void*)eglGetProcAddress(name.c_str()); } -void cInterfaceEGL::DetectMode() +void GLContextEGL::DetectMode(bool has_handle) { - if (s_opengl_mode != GLInterfaceMode::MODE_DETECT) - return; bool preferGLES = Config::Get(Config::GFX_PREFER_GLES); EGLint num_configs; - bool supportsGL = false, supportsGLES2 = false, supportsGLES3 = false; - std::array renderable_types{{ - EGL_OPENGL_BIT, - (1 << 6), /* EGL_OPENGL_ES3_BIT_KHR */ - EGL_OPENGL_ES2_BIT, - }}; + bool supportsGL = false, supportsGLES3 = false; + std::array renderable_types{{EGL_OPENGL_BIT, EGL_OPENGL_ES3_BIT_KHR}}; for (auto renderable_type : renderable_types) { @@ -71,11 +71,11 @@ void cInterfaceEGL::DetectMode() EGL_RENDERABLE_TYPE, renderable_type, EGL_SURFACE_TYPE, - m_has_handle ? EGL_WINDOW_BIT : 0, + has_handle ? EGL_WINDOW_BIT : 0, EGL_NONE}; // Get how many configs there are - if (!eglChooseConfig(egl_dpy, attribs, nullptr, 0, &num_configs)) + if (!eglChooseConfig(m_egl_display, attribs, nullptr, 0, &num_configs)) { INFO_LOG(VIDEO, "Error: couldn't get an EGL visual config"); continue; @@ -84,7 +84,7 @@ void cInterfaceEGL::DetectMode() EGLConfig* config = new EGLConfig[num_configs]; // Get all the configurations - if (!eglChooseConfig(egl_dpy, attribs, config, num_configs, &num_configs)) + if (!eglChooseConfig(m_egl_display, attribs, config, num_configs, &num_configs)) { INFO_LOG(VIDEO, "Error: couldn't get an EGL visual config"); delete[] config; @@ -95,15 +95,13 @@ void cInterfaceEGL::DetectMode() { EGLint attribVal; bool ret; - ret = eglGetConfigAttrib(egl_dpy, config[i], EGL_RENDERABLE_TYPE, &attribVal); + ret = eglGetConfigAttrib(m_egl_display, config[i], EGL_RENDERABLE_TYPE, &attribVal); if (ret) { if (attribVal & EGL_OPENGL_BIT) supportsGL = true; - if (attribVal & (1 << 6)) /* EGL_OPENGL_ES3_BIT_KHR */ + if (attribVal & EGL_OPENGL_ES3_BIT_KHR) supportsGLES3 = true; - if (attribVal & EGL_OPENGL_ES2_BIT) - supportsGLES2 = true; } } delete[] config; @@ -112,63 +110,66 @@ void cInterfaceEGL::DetectMode() if (preferGLES) { if (supportsGLES3) - s_opengl_mode = GLInterfaceMode::MODE_OPENGLES3; - else if (supportsGLES2) - s_opengl_mode = GLInterfaceMode::MODE_OPENGLES2; + m_opengl_mode = Mode::OpenGLES; else if (supportsGL) - s_opengl_mode = GLInterfaceMode::MODE_OPENGL; + m_opengl_mode = Mode::OpenGL; } else { if (supportsGL) - s_opengl_mode = GLInterfaceMode::MODE_OPENGL; + m_opengl_mode = Mode::OpenGL; else if (supportsGLES3) - s_opengl_mode = GLInterfaceMode::MODE_OPENGLES3; - else if (supportsGLES2) - s_opengl_mode = GLInterfaceMode::MODE_OPENGLES2; + m_opengl_mode = Mode::OpenGLES; } - if (s_opengl_mode == GLInterfaceMode::MODE_OPENGL) + if (m_opengl_mode == Mode::OpenGL) { INFO_LOG(VIDEO, "Using OpenGL"); } - else if (s_opengl_mode == GLInterfaceMode::MODE_OPENGLES3) + else if (m_opengl_mode == Mode::OpenGLES) { - INFO_LOG(VIDEO, "Using OpenGL|ES 3"); + INFO_LOG(VIDEO, "Using OpenGL|ES"); } - else if (s_opengl_mode == GLInterfaceMode::MODE_OPENGLES2) - { - INFO_LOG(VIDEO, "Using OpenGL|ES 2"); - } - else if (s_opengl_mode == GLInterfaceMode::MODE_DETECT) + else if (m_opengl_mode == Mode::Detect) { // Errored before we found a mode ERROR_LOG(VIDEO, "Error: Failed to detect OpenGL flavour, falling back to OpenGL"); // This will fail to create a context, as it'll try to use the same attribs we just failed to // find a matching config with - s_opengl_mode = GLInterfaceMode::MODE_OPENGL; + m_opengl_mode = Mode::OpenGL; } } +EGLDisplay GLContextEGL::OpenEGLDisplay() +{ + return eglGetDisplay(EGL_DEFAULT_DISPLAY); +} + +EGLNativeWindowType GLContextEGL::GetEGLNativeWindow(EGLConfig config) +{ + return reinterpret_cast(EGL_DEFAULT_DISPLAY); +} + // Create rendering window. // Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize() -bool cInterfaceEGL::Create(void* window_handle, bool stereo, bool core) +bool GLContextEGL::Initialize(void* window_handle, bool stereo, bool core) { + const bool has_handle = !!window_handle; + EGLint egl_major, egl_minor; bool supports_core_profile = false; - egl_dpy = OpenDisplay(); - m_host_window = (EGLNativeWindowType)window_handle; - m_has_handle = !!window_handle; - m_core = core; + m_egl_display = OpenEGLDisplay(); + m_host_window = window_handle; + m_is_core_context = core; - if (!egl_dpy) + if (!m_egl_display) { INFO_LOG(VIDEO, "Error: eglGetDisplay() failed"); return false; } - if (!eglInitialize(egl_dpy, &egl_major, &egl_minor)) + if (!eglInitialize(m_egl_display, &egl_major, &egl_minor)) { INFO_LOG(VIDEO, "Error: eglInitialize() failed"); return false; @@ -177,12 +178,13 @@ bool cInterfaceEGL::Create(void* window_handle, bool stereo, bool core) /* Detection code */ EGLint num_configs; - DetectMode(); + if (m_opengl_mode == Mode::Detect) + DetectMode(has_handle); // attributes for a visual in RGBA format with at least // 8 bits per color int attribs[] = {EGL_RENDERABLE_TYPE, - EGL_OPENGL_ES2_BIT, + 0, EGL_RED_SIZE, 8, EGL_GREEN_SIZE, @@ -190,43 +192,38 @@ bool cInterfaceEGL::Create(void* window_handle, bool stereo, bool core) EGL_BLUE_SIZE, 8, EGL_SURFACE_TYPE, - m_has_handle ? EGL_WINDOW_BIT : 0, + has_handle ? EGL_WINDOW_BIT : 0, EGL_NONE}; std::vector ctx_attribs; - switch (s_opengl_mode) + switch (m_opengl_mode) { - case GLInterfaceMode::MODE_OPENGL: + case Mode::OpenGL: attribs[1] = EGL_OPENGL_BIT; ctx_attribs = {EGL_NONE}; break; - case GLInterfaceMode::MODE_OPENGLES2: - attribs[1] = EGL_OPENGL_ES2_BIT; - ctx_attribs = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}; - break; - case GLInterfaceMode::MODE_OPENGLES3: - attribs[1] = (1 << 6); /* EGL_OPENGL_ES3_BIT_KHR */ + case Mode::OpenGLES: + attribs[1] = EGL_OPENGL_ES3_BIT_KHR; ctx_attribs = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE}; break; default: ERROR_LOG(VIDEO, "Unknown opengl mode set"); return false; - break; } - if (!eglChooseConfig(egl_dpy, attribs, &m_config, 1, &num_configs)) + if (!eglChooseConfig(m_egl_display, attribs, &m_config, 1, &num_configs)) { INFO_LOG(VIDEO, "Error: couldn't get an EGL visual config"); return false; } - if (s_opengl_mode == GLInterfaceMode::MODE_OPENGL) + if (m_opengl_mode == Mode::OpenGL) eglBindAPI(EGL_OPENGL_API); else eglBindAPI(EGL_OPENGL_ES_API); std::string tmp; - std::istringstream buffer(eglQueryString(egl_dpy, EGL_EXTENSIONS)); + std::istringstream buffer(eglQueryString(m_egl_display, EGL_EXTENSIONS)); while (buffer >> tmp) { if (tmp == "EGL_KHR_surfaceless_context") @@ -235,7 +232,7 @@ bool cInterfaceEGL::Create(void* window_handle, bool stereo, bool core) supports_core_profile = true; } - if (supports_core_profile && core && s_opengl_mode == GLInterfaceMode::MODE_OPENGL) + if (supports_core_profile && core && m_opengl_mode == Mode::OpenGL) { std::array, 7> versions_to_try = {{ {4, 5}, @@ -259,8 +256,8 @@ bool cInterfaceEGL::Create(void* window_handle, bool stereo, bool core) EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR, EGL_NONE}; - egl_ctx = eglCreateContext(egl_dpy, m_config, EGL_NO_CONTEXT, &core_attribs[0]); - if (egl_ctx) + m_egl_context = eglCreateContext(m_egl_display, m_config, EGL_NO_CONTEXT, &core_attribs[0]); + if (m_egl_context) { m_attribs = std::move(core_attribs); break; @@ -268,14 +265,14 @@ bool cInterfaceEGL::Create(void* window_handle, bool stereo, bool core) } } - if (!egl_ctx) + if (!m_egl_context) { - m_core = false; - egl_ctx = eglCreateContext(egl_dpy, m_config, EGL_NO_CONTEXT, &ctx_attribs[0]); + m_is_core_context = false; + m_egl_context = eglCreateContext(m_egl_display, m_config, EGL_NO_CONTEXT, &ctx_attribs[0]); m_attribs = std::move(ctx_attribs); } - if (!egl_ctx) + if (!m_egl_context) { INFO_LOG(VIDEO, "Error: eglCreateContext failed"); return false; @@ -289,33 +286,33 @@ bool cInterfaceEGL::Create(void* window_handle, bool stereo, bool core) return true; } -std::unique_ptr cInterfaceEGL::CreateSharedContext() +std::unique_ptr GLContextEGL::CreateSharedContext() { - std::unique_ptr context = std::make_unique(); - if (!context->Create(this)) + std::unique_ptr context = std::make_unique(); + if (!context->Initialize(this)) return nullptr; return context; } -bool cInterfaceEGL::Create(cInterfaceBase* main_context) +bool GLContextEGL::Initialize(GLContext* main_context) { - cInterfaceEGL* egl_context = static_cast(main_context); + GLContextEGL* egl_context = static_cast(main_context); - egl_dpy = egl_context->egl_dpy; - m_core = egl_context->m_core; + m_opengl_mode = egl_context->m_opengl_mode; + m_egl_display = egl_context->m_egl_display; + m_is_core_context = egl_context->m_is_core_context; m_config = egl_context->m_config; m_supports_surfaceless = egl_context->m_supports_surfaceless; m_is_shared = true; - m_has_handle = false; - if (egl_context->GetMode() == GLInterfaceMode::MODE_OPENGL) + if (egl_context->GetMode() == Mode::OpenGL) eglBindAPI(EGL_OPENGL_API); else eglBindAPI(EGL_OPENGL_ES_API); - egl_ctx = - eglCreateContext(egl_dpy, m_config, egl_context->egl_ctx, egl_context->m_attribs.data()); - if (!egl_ctx) + m_egl_context = eglCreateContext(m_egl_display, m_config, egl_context->m_egl_context, + egl_context->m_attribs.data()); + if (!m_egl_context) { INFO_LOG(VIDEO, "Error: eglCreateContext failed 0x%04x", eglGetError()); return false; @@ -329,13 +326,13 @@ bool cInterfaceEGL::Create(cInterfaceBase* main_context) return true; } -bool cInterfaceEGL::CreateWindowSurface() +bool GLContextEGL::CreateWindowSurface() { - if (m_has_handle) + if (m_host_window) { - EGLNativeWindowType native_window = InitializePlatform(m_host_window, m_config); - egl_surf = eglCreateWindowSurface(egl_dpy, m_config, native_window, nullptr); - if (!egl_surf) + EGLNativeWindowType native_window = GetEGLNativeWindow(m_config); + m_egl_surface = eglCreateWindowSurface(m_egl_display, m_config, native_window, nullptr); + if (!m_egl_surface) { INFO_LOG(VIDEO, "Error: eglCreateWindowSurface failed"); return false; @@ -346,8 +343,8 @@ bool cInterfaceEGL::CreateWindowSurface() EGLint attrib_list[] = { EGL_NONE, }; - egl_surf = eglCreatePbufferSurface(egl_dpy, m_config, attrib_list); - if (!egl_surf) + m_egl_surface = eglCreatePbufferSurface(m_egl_display, m_config, attrib_list); + if (!m_egl_surface) { INFO_LOG(VIDEO, "Error: eglCreatePbufferSurface failed"); return false; @@ -355,56 +352,50 @@ bool cInterfaceEGL::CreateWindowSurface() } else { - egl_surf = EGL_NO_SURFACE; + m_egl_surface = EGL_NO_SURFACE; } return true; } -void cInterfaceEGL::DestroyWindowSurface() +void GLContextEGL::DestroyWindowSurface() { - if (egl_surf != EGL_NO_SURFACE && !eglDestroySurface(egl_dpy, egl_surf)) + if (m_egl_surface != EGL_NO_SURFACE && !eglDestroySurface(m_egl_display, m_egl_surface)) NOTICE_LOG(VIDEO, "Could not destroy window surface."); - egl_surf = EGL_NO_SURFACE; + m_egl_surface = EGL_NO_SURFACE; } -bool cInterfaceEGL::MakeCurrent() +bool GLContextEGL::MakeCurrent() { - return eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx); + return eglMakeCurrent(m_egl_display, m_egl_surface, m_egl_surface, m_egl_context); } -void cInterfaceEGL::UpdateHandle(void* window_handle) -{ - m_host_window = (EGLNativeWindowType)window_handle; - m_has_handle = !!window_handle; -} - -void cInterfaceEGL::UpdateSurface() +void GLContextEGL::UpdateSurface(void* window_handle) { + m_host_window = window_handle; ClearCurrent(); DestroyWindowSurface(); CreateWindowSurface(); MakeCurrent(); } -bool cInterfaceEGL::ClearCurrent() +bool GLContextEGL::ClearCurrent() { - return eglMakeCurrent(egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + return eglMakeCurrent(m_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); } // Close backend -void cInterfaceEGL::Shutdown() +void GLContextEGL::Shutdown() { - ShutdownPlatform(); - if (egl_ctx) + if (m_egl_context) { - if (!eglMakeCurrent(egl_dpy, egl_surf, egl_surf, egl_ctx)) + if (!eglMakeCurrent(m_egl_display, m_egl_surface, m_egl_surface, m_egl_context)) NOTICE_LOG(VIDEO, "Could not release drawing context."); - eglMakeCurrent(egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - if (!eglDestroyContext(egl_dpy, egl_ctx)) + eglMakeCurrent(m_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + if (!eglDestroyContext(m_egl_display, m_egl_context)) NOTICE_LOG(VIDEO, "Could not destroy drawing context."); DestroyWindowSurface(); - if (!m_is_shared && !eglTerminate(egl_dpy)) + if (!m_is_shared && !eglTerminate(m_egl_display)) NOTICE_LOG(VIDEO, "Could not destroy display connection."); - egl_ctx = nullptr; + m_egl_context = nullptr; } } diff --git a/Source/Core/Common/GL/GLInterface/EGL.h b/Source/Core/Common/GL/GLInterface/EGL.h index 79c623c942..49abd63cc1 100644 --- a/Source/Core/Common/GL/GLInterface/EGL.h +++ b/Source/Core/Common/GL/GLInterface/EGL.h @@ -9,44 +9,46 @@ #include #include -#include "Common/GL/GLInterfaceBase.h" +#include "Common/GL/GLContext.h" -class cInterfaceEGL : public cInterfaceBase +class GLContextEGL : public GLContext { -private: - EGLConfig m_config; - bool m_has_handle; - EGLNativeWindowType m_host_window; - bool m_supports_surfaceless = false; - std::vector m_attribs; +public: + virtual ~GLContextEGL(); + + bool IsHeadless() const override; + + std::unique_ptr CreateSharedContext() override; + virtual void Shutdown() override; + + bool MakeCurrent() override; + bool ClearCurrent() override; + + void UpdateSurface(void* window_handle) override; + + void Swap() override; + void SwapInterval(int interval) override; + + void* GetFuncAddress(const std::string& name) override; + +protected: + virtual EGLDisplay OpenEGLDisplay(); + virtual EGLNativeWindowType GetEGLNativeWindow(EGLConfig config); + + bool Initialize(void* window_handle, bool stereo, bool core) override; + bool Initialize(GLContext* main_context) override; bool CreateWindowSurface(); void DestroyWindowSurface(); + void DetectMode(bool has_handle); -protected: - void DetectMode(); - EGLSurface egl_surf; - EGLContext egl_ctx; - EGLDisplay egl_dpy; + void* m_host_window = nullptr; - virtual EGLDisplay OpenDisplay() { return eglGetDisplay(EGL_DEFAULT_DISPLAY); } - virtual EGLNativeWindowType InitializePlatform(EGLNativeWindowType host_window, EGLConfig config) - { - return (EGLNativeWindowType)EGL_DEFAULT_DISPLAY; - } - virtual void ShutdownPlatform() {} + EGLConfig m_config; + bool m_supports_surfaceless = false; + std::vector m_attribs; -public: - void Swap() override; - void SwapInterval(int interval) override; - void SetMode(GLInterfaceMode mode) override { s_opengl_mode = mode; } - void* GetFuncAddress(const std::string& name) override; - bool Create(void* window_handle, bool stereo, bool core) override; - bool Create(cInterfaceBase* main_context) override; - bool MakeCurrent() override; - bool ClearCurrent() override; - void Shutdown() override; - void UpdateHandle(void* window_handle) override; - void UpdateSurface() override; - std::unique_ptr CreateSharedContext() override; + EGLSurface m_egl_surface; + EGLContext m_egl_context; + EGLDisplay m_egl_display; }; diff --git a/Source/Core/Common/GL/GLInterface/EGLAndroid.cpp b/Source/Core/Common/GL/GLInterface/EGLAndroid.cpp index 44fb41f1d2..2a5123b21f 100644 --- a/Source/Core/Common/GL/GLInterface/EGLAndroid.cpp +++ b/Source/Core/Common/GL/GLInterface/EGLAndroid.cpp @@ -3,26 +3,19 @@ // Refer to the license.txt file included. #include "Common/GL/GLInterface/EGLAndroid.h" +#include -EGLDisplay cInterfaceEGLAndroid::OpenDisplay() +EGLDisplay GLContextEGLAndroid::OpenEGLDisplay() { return eglGetDisplay(EGL_DEFAULT_DISPLAY); } -EGLNativeWindowType cInterfaceEGLAndroid::InitializePlatform(EGLNativeWindowType host_window, - EGLConfig config) +EGLNativeWindowType GLContextEGLAndroid::GetEGLNativeWindow(EGLConfig config) { EGLint format; - eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &format); - ANativeWindow_setBuffersGeometry(host_window, 0, 0, format); - - const int width = ANativeWindow_getWidth(host_window); - const int height = ANativeWindow_getHeight(host_window); - GLInterface->SetBackBufferDimensions(width, height); - - return host_window; -} - -void cInterfaceEGLAndroid::ShutdownPlatform() -{ + eglGetConfigAttrib(m_egl_display, config, EGL_NATIVE_VISUAL_ID, &format); + ANativeWindow_setBuffersGeometry(static_cast(m_host_window), 0, 0, format); + m_backbuffer_width = ANativeWindow_getWidth(static_cast(m_host_window)); + m_backbuffer_height = ANativeWindow_getHeight(static_cast(m_host_window)); + return static_cast(m_host_window); } diff --git a/Source/Core/Common/GL/GLInterface/EGLAndroid.h b/Source/Core/Common/GL/GLInterface/EGLAndroid.h index 8a43f261c9..0139bae91c 100644 --- a/Source/Core/Common/GL/GLInterface/EGLAndroid.h +++ b/Source/Core/Common/GL/GLInterface/EGLAndroid.h @@ -4,14 +4,11 @@ #pragma once -#include #include "Common/GL/GLInterface/EGL.h" -class cInterfaceEGLAndroid : public cInterfaceEGL +class GLContextEGLAndroid : public GLContextEGL { protected: - EGLDisplay OpenDisplay() override; - EGLNativeWindowType InitializePlatform(EGLNativeWindowType host_window, - EGLConfig config) override; - void ShutdownPlatform() override; + EGLDisplay OpenEGLDisplay() override; + EGLNativeWindowType GetEGLNativeWindow(EGLConfig config) override; }; diff --git a/Source/Core/Common/GL/GLInterface/EGLX11.cpp b/Source/Core/Common/GL/GLInterface/EGLX11.cpp index 432f0aa601..58bf3133a8 100644 --- a/Source/Core/Common/GL/GLInterface/EGLX11.cpp +++ b/Source/Core/Common/GL/GLInterface/EGLX11.cpp @@ -5,41 +5,39 @@ #include "Common/GL/GLInterface/EGLX11.h" #include "Common/Logging/Log.h" -EGLDisplay cInterfaceEGLX11::OpenDisplay() +GLContextEGLX11::~GLContextEGLX11() { - dpy = XOpenDisplay(nullptr); - XWindow.Initialize(dpy); - return eglGetDisplay(dpy); + if (m_display) + XCloseDisplay(m_display); } -EGLNativeWindowType cInterfaceEGLX11::InitializePlatform(EGLNativeWindowType host_window, - EGLConfig config) +EGLDisplay GLContextEGLX11::OpenEGLDisplay() +{ + if (!m_display) + m_display = XOpenDisplay(nullptr); + + return eglGetDisplay(m_display); +} + +EGLNativeWindowType GLContextEGLX11::GetEGLNativeWindow(EGLConfig config) { EGLint vid; - eglGetConfigAttrib(egl_dpy, config, EGL_NATIVE_VISUAL_ID, &vid); + eglGetConfigAttrib(m_egl_display, config, EGL_NATIVE_VISUAL_ID, &vid); - XVisualInfo visTemplate; + XVisualInfo visTemplate = {}; visTemplate.visualid = vid; - XVisualInfo* vi; int nVisuals; - vi = XGetVisualInfo(dpy, VisualIDMask, &visTemplate, &nVisuals); + XVisualInfo* vi = XGetVisualInfo(m_display, VisualIDMask, &visTemplate, &nVisuals); - XWindowAttributes attribs; - if (!XGetWindowAttributes(dpy, (Window)host_window, &attribs)) - { - ERROR_LOG(VIDEO, "Window attribute retrieval failed"); - return 0; - } + if (m_x_window) + m_x_window.reset(); - s_backbuffer_width = attribs.width; - s_backbuffer_height = attribs.height; + m_x_window = GLX11Window::Create(m_display, reinterpret_cast(m_host_window), vi); + m_backbuffer_width = m_x_window->GetWidth(); + m_backbuffer_height = m_x_window->GetHeight(); - return (EGLNativeWindowType)XWindow.CreateXWindow((Window)host_window, vi); -} - -void cInterfaceEGLX11::ShutdownPlatform() -{ - XWindow.DestroyXWindow(); - XCloseDisplay(dpy); + XFree(vi); + + return reinterpret_cast(m_x_window->GetWindow()); } diff --git a/Source/Core/Common/GL/GLInterface/EGLX11.h b/Source/Core/Common/GL/GLInterface/EGLX11.h index dab5a38d8e..ec0e933ef7 100644 --- a/Source/Core/Common/GL/GLInterface/EGLX11.h +++ b/Source/Core/Common/GL/GLInterface/EGLX11.h @@ -7,17 +7,17 @@ #include #include "Common/GL/GLInterface/EGL.h" -#include "Common/GL/GLInterface/X11_Util.h" +#include "Common/GL/GLX11Window.h" -class cInterfaceEGLX11 : public cInterfaceEGL +class GLContextEGLX11 : public GLContextEGL { -private: - cX11Window XWindow; - Display* dpy; +public: + ~GLContextEGLX11() override; protected: - EGLDisplay OpenDisplay() override; - EGLNativeWindowType InitializePlatform(EGLNativeWindowType host_window, - EGLConfig config) override; - void ShutdownPlatform() override; + EGLDisplay OpenEGLDisplay() override; + EGLNativeWindowType GetEGLNativeWindow(EGLConfig config) override; + + Display* m_display = nullptr; + std::unique_ptr m_x_window; }; diff --git a/Source/Core/Common/GL/GLInterface/GLInterface.cpp b/Source/Core/Common/GL/GLInterface/GLInterface.cpp deleted file mode 100644 index a6ae0c0991..0000000000 --- a/Source/Core/Common/GL/GLInterface/GLInterface.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright 2014 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -#include - -#include "Common/GL/GLInterfaceBase.h" - -#if defined(__APPLE__) -#include "Common/GL/GLInterface/AGL.h" -#elif defined(_WIN32) -#include "Common/GL/GLInterface/WGL.h" -#elif HAVE_X11 -#if defined(USE_EGL) && USE_EGL -#include "Common/GL/GLInterface/EGLX11.h" -#else -#include "Common/GL/GLInterface/GLX.h" -#endif -#elif defined(USE_EGL) && USE_EGL && defined(USE_HEADLESS) -#include "Common/GL/GLInterface/EGL.h" -#elif ANDROID -#include "Common/GL/GLInterface/EGLAndroid.h" -#error Platform doesnt have a GLInterface -#endif - -std::unique_ptr HostGL_CreateGLInterface() -{ -#if defined(__APPLE__) - return std::make_unique(); -#elif defined(_WIN32) - return std::make_unique(); -#elif defined(USE_EGL) && defined(USE_HEADLESS) - return std::make_unique(); -#elif defined(HAVE_X11) && HAVE_X11 -#if defined(USE_EGL) && USE_EGL - return std::make_unique(); -#else - return std::make_unique(); -#endif -#elif ANDROID - return std::make_unique(); -#else - return nullptr; -#endif -} diff --git a/Source/Core/Common/GL/GLInterface/GLX.cpp b/Source/Core/Common/GL/GLInterface/GLX.cpp index 28714fd20c..173127fc5b 100644 --- a/Source/Core/Common/GL/GLInterface/GLX.cpp +++ b/Source/Core/Common/GL/GLInterface/GLX.cpp @@ -30,43 +30,40 @@ static int ctxErrorHandler(Display* dpy, XErrorEvent* ev) return 0; } -void cInterfaceGLX::SwapInterval(int Interval) +void GLContextGLX::SwapInterval(int Interval) { - if (!m_has_handle) + if (!m_drawable) return; // Try EXT_swap_control, then MESA_swap_control. if (glXSwapIntervalEXTPtr) - glXSwapIntervalEXTPtr(dpy, win, Interval); + glXSwapIntervalEXTPtr(m_display, m_drawable, Interval); else if (glXSwapIntervalMESAPtr) glXSwapIntervalMESAPtr(static_cast(Interval)); else ERROR_LOG(VIDEO, "No support for SwapInterval (framerate clamped to monitor refresh rate)."); } -void* cInterfaceGLX::GetFuncAddress(const std::string& name) +void* GLContextGLX::GetFuncAddress(const std::string& name) { - return (void*)glXGetProcAddress((const GLubyte*)name.c_str()); + return reinterpret_cast(glXGetProcAddress(reinterpret_cast(name.c_str()))); } -void cInterfaceGLX::Swap() +void GLContextGLX::Swap() { - glXSwapBuffers(dpy, win); + glXSwapBuffers(m_display, m_drawable); } // Create rendering window. // Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize() -bool cInterfaceGLX::Create(void* window_handle, bool stereo, bool core) +bool GLContextGLX::Initialize(void* window_handle, bool stereo, bool core) { - m_has_handle = !!window_handle; - m_host_window = (Window)window_handle; - - dpy = XOpenDisplay(nullptr); - int screen = DefaultScreen(dpy); + m_display = XOpenDisplay(nullptr); + int screen = DefaultScreen(m_display); // checking glx version int glxMajorVersion, glxMinorVersion; - glXQueryVersion(dpy, &glxMajorVersion, &glxMinorVersion); + glXQueryVersion(m_display, &glxMajorVersion, &glxMinorVersion); if (glxMajorVersion < 1 || (glxMajorVersion == 1 && glxMinorVersion < 4)) { ERROR_LOG(VIDEO, "glX-Version %d.%d detected, but need at least 1.4", glxMajorVersion, @@ -107,13 +104,13 @@ bool cInterfaceGLX::Create(void* window_handle, bool stereo, bool core) stereo ? True : False, None}; int fbcount = 0; - GLXFBConfig* fbc = glXChooseFBConfig(dpy, screen, visual_attribs, &fbcount); + GLXFBConfig* fbc = glXChooseFBConfig(m_display, screen, visual_attribs, &fbcount); if (!fbc || !fbcount) { ERROR_LOG(VIDEO, "Failed to retrieve a framebuffer config"); return false; } - fbconfig = *fbc; + m_fbconfig = *fbc; XFree(fbc); s_glxError = false; @@ -125,36 +122,36 @@ bool cInterfaceGLX::Create(void* window_handle, bool stereo, bool core) {GLX_CONTEXT_MAJOR_VERSION_ARB, 4, GLX_CONTEXT_MINOR_VERSION_ARB, 0, GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, None}}; - ctx = nullptr; + m_context = nullptr; if (core) { - ctx = glXCreateContextAttribs(dpy, fbconfig, 0, True, &context_attribs[0]); - XSync(dpy, False); + m_context = glXCreateContextAttribs(m_display, m_fbconfig, 0, True, &context_attribs[0]); + XSync(m_display, False); m_attribs.insert(m_attribs.end(), context_attribs.begin(), context_attribs.end()); } - if (core && (!ctx || s_glxError)) + if (core && (!m_context || s_glxError)) { std::array context_attribs_33 = { {GLX_CONTEXT_MAJOR_VERSION_ARB, 3, GLX_CONTEXT_MINOR_VERSION_ARB, 3, GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, None}}; s_glxError = false; - ctx = glXCreateContextAttribs(dpy, fbconfig, 0, True, &context_attribs_33[0]); - XSync(dpy, False); + m_context = glXCreateContextAttribs(m_display, m_fbconfig, 0, True, &context_attribs_33[0]); + XSync(m_display, False); m_attribs.clear(); m_attribs.insert(m_attribs.end(), context_attribs_33.begin(), context_attribs_33.end()); } - if (!ctx || s_glxError) + if (!m_context || s_glxError) { std::array context_attribs_legacy = { {GLX_CONTEXT_MAJOR_VERSION_ARB, 1, GLX_CONTEXT_MINOR_VERSION_ARB, 0, None}}; s_glxError = false; - ctx = glXCreateContextAttribs(dpy, fbconfig, 0, True, &context_attribs_legacy[0]); - XSync(dpy, False); + m_context = glXCreateContextAttribs(m_display, m_fbconfig, 0, True, &context_attribs_legacy[0]); + XSync(m_display, False); m_attribs.clear(); m_attribs.insert(m_attribs.end(), context_attribs_legacy.begin(), context_attribs_legacy.end()); } - if (!ctx || s_glxError) + if (!m_context || s_glxError) { ERROR_LOG(VIDEO, "Unable to create GL context."); XSetErrorHandler(oldHandler); @@ -168,7 +165,7 @@ bool cInterfaceGLX::Create(void* window_handle, bool stereo, bool core) m_supports_pbuffer = false; std::string tmp; - std::istringstream buffer(glXQueryExtensionsString(dpy, screen)); + std::istringstream buffer(glXQueryExtensionsString(m_display, screen)); while (buffer >> tmp) { if (tmp == "GLX_SGIX_pbuffer") @@ -191,7 +188,7 @@ bool cInterfaceGLX::Create(void* window_handle, bool stereo, bool core) } } - if (!CreateWindowSurface()) + if (!CreateWindowSurface(reinterpret_cast(window_handle))) { ERROR_LOG(VIDEO, "Error: CreateWindowSurface failed\n"); XSetErrorHandler(oldHandler); @@ -199,31 +196,33 @@ bool cInterfaceGLX::Create(void* window_handle, bool stereo, bool core) } XSetErrorHandler(oldHandler); + m_opengl_mode = Mode::OpenGL; return true; } -bool cInterfaceGLX::Create(cInterfaceBase* main_context) +bool GLContextGLX::Initialize(GLContext* main_context) { - cInterfaceGLX* glx_context = static_cast(main_context); + GLContextGLX* glx_context = static_cast(main_context); - m_has_handle = false; + m_opengl_mode = glx_context->m_opengl_mode; m_supports_pbuffer = glx_context->m_supports_pbuffer; - dpy = glx_context->dpy; - fbconfig = glx_context->fbconfig; + m_display = glx_context->m_display; + m_fbconfig = glx_context->m_fbconfig; s_glxError = false; XErrorHandler oldHandler = XSetErrorHandler(&ctxErrorHandler); - ctx = glXCreateContextAttribs(dpy, fbconfig, glx_context->ctx, True, &glx_context->m_attribs[0]); - XSync(dpy, False); + m_context = glXCreateContextAttribs(m_display, m_fbconfig, glx_context->m_context, True, + &glx_context->m_attribs[0]); + XSync(m_display, False); - if (!ctx || s_glxError) + if (!m_context || s_glxError) { ERROR_LOG(VIDEO, "Unable to create GL context."); XSetErrorHandler(oldHandler); return false; } - if (m_supports_pbuffer && !CreateWindowSurface()) + if (m_supports_pbuffer && !CreateWindowSurface(None)) { ERROR_LOG(VIDEO, "Error: CreateWindowSurface failed\n"); XSetErrorHandler(oldHandler); @@ -234,84 +233,81 @@ bool cInterfaceGLX::Create(cInterfaceBase* main_context) return true; } -std::unique_ptr cInterfaceGLX::CreateSharedContext() +bool GLContextGLX::IsHeadless() const { - std::unique_ptr context = std::make_unique(); - if (!context->Create(this)) + return m_render_window == nullptr; +} + +std::unique_ptr GLContextGLX::CreateSharedContext() +{ + std::unique_ptr context = std::make_unique(); + if (!context->Initialize(this)) return nullptr; return context; } -bool cInterfaceGLX::CreateWindowSurface() +bool GLContextGLX::CreateWindowSurface(Window window_handle) { - if (m_has_handle) + if (window_handle) { // Get an appropriate visual - XVisualInfo* vi = glXGetVisualFromFBConfig(dpy, fbconfig); - - XWindow.Initialize(dpy); - - XWindowAttributes attribs; - if (!XGetWindowAttributes(dpy, m_host_window, &attribs)) - { - ERROR_LOG(VIDEO, "Window attribute retrieval failed"); + XVisualInfo* vi = glXGetVisualFromFBConfig(m_display, m_fbconfig); + m_render_window = GLX11Window::Create(m_display, window_handle, vi); + if (!m_render_window) return false; - } - s_backbuffer_width = attribs.width; - s_backbuffer_height = attribs.height; - - win = XWindow.CreateXWindow(m_host_window, vi); + m_backbuffer_width = m_render_window->GetWidth(); + m_backbuffer_height = m_render_window->GetHeight(); + m_drawable = static_cast(m_render_window->GetWindow()); XFree(vi); } else if (m_supports_pbuffer) { - win = m_pbuffer = glXCreateGLXPbufferSGIX(dpy, fbconfig, 1, 1, nullptr); + m_pbuffer = glXCreateGLXPbufferSGIX(m_display, m_fbconfig, 1, 1, nullptr); if (!m_pbuffer) return false; + + m_drawable = static_cast(m_pbuffer); } return true; } -void cInterfaceGLX::DestroyWindowSurface() +void GLContextGLX::DestroyWindowSurface() { - if (m_has_handle) + m_render_window.reset(); + if (m_supports_pbuffer && m_pbuffer) { - XWindow.DestroyXWindow(); - } - else if (m_supports_pbuffer && m_pbuffer) - { - glXDestroyGLXPbufferSGIX(dpy, m_pbuffer); + glXDestroyGLXPbufferSGIX(m_display, m_pbuffer); m_pbuffer = 0; } } -bool cInterfaceGLX::MakeCurrent() +bool GLContextGLX::MakeCurrent() { - return glXMakeCurrent(dpy, win, ctx); + return glXMakeCurrent(m_display, m_drawable, m_context); } -bool cInterfaceGLX::ClearCurrent() +bool GLContextGLX::ClearCurrent() { - return glXMakeCurrent(dpy, None, nullptr); + return glXMakeCurrent(m_display, None, nullptr); } // Close backend -void cInterfaceGLX::Shutdown() +void GLContextGLX::Shutdown() { DestroyWindowSurface(); - if (ctx) + if (m_context) { - glXDestroyContext(dpy, ctx); + glXDestroyContext(m_display, m_context); // Don't close the display connection if we are a shared context. // Saves doing reference counting on this object, and the main context will always // be shut down last anyway. - if (m_has_handle) + if (m_render_window) { - XCloseDisplay(dpy); - ctx = nullptr; + XCloseDisplay(m_display); + m_context = nullptr; } } } diff --git a/Source/Core/Common/GL/GLInterface/GLX.h b/Source/Core/Common/GL/GLInterface/GLX.h index 724dca5141..42e36f863f 100644 --- a/Source/Core/Common/GL/GLInterface/GLX.h +++ b/Source/Core/Common/GL/GLInterface/GLX.h @@ -10,35 +10,39 @@ #include #include -#include "Common/GL/GLInterface/X11_Util.h" -#include "Common/GL/GLInterfaceBase.h" +#include "Common/GL/GLContext.h" +#include "Common/GL/GLX11Window.h" -class cInterfaceGLX : public cInterfaceBase +class GLContextGLX : public GLContext { -private: - Window m_host_window; - cX11Window XWindow; - Display* dpy; - Window win; - GLXContext ctx; - GLXFBConfig fbconfig; - bool m_has_handle; +public: + bool IsHeadless() const override; + + std::unique_ptr CreateSharedContext() override; + void Shutdown() override; + + bool MakeCurrent() override; + bool ClearCurrent() override; + + void SwapInterval(int Interval) override; + void Swap() override; + + void* GetFuncAddress(const std::string& name) override; + +protected: + bool Initialize(void* window_handle, bool stereo, bool core) override; + bool Initialize(GLContext* main_context) override; + + Display* m_display = nullptr; + std::unique_ptr m_render_window; + + GLXDrawable m_drawable = {}; + GLXContext m_context = {}; + GLXFBConfig m_fbconfig = {}; bool m_supports_pbuffer = false; GLXPbufferSGIX m_pbuffer = 0; std::vector m_attribs; - bool CreateWindowSurface(); + bool CreateWindowSurface(Window window_handle); void DestroyWindowSurface(); - -public: - friend class cX11Window; - void SwapInterval(int Interval) override; - void Swap() override; - void* GetFuncAddress(const std::string& name) override; - bool Create(void* window_handle, bool stereo, bool core) override; - bool Create(cInterfaceBase* main_context) override; - bool MakeCurrent() override; - bool ClearCurrent() override; - void Shutdown() override; - std::unique_ptr CreateSharedContext() override; }; diff --git a/Source/Core/Common/GL/GLInterface/WGL.cpp b/Source/Core/Common/GL/GLInterface/WGL.cpp index 48f4b8c96c..d7c8c87c4f 100644 --- a/Source/Core/Common/GL/GLInterface/WGL.cpp +++ b/Source/Core/Common/GL/GLInterface/WGL.cpp @@ -130,8 +130,8 @@ static PFNWGLDESTROYPBUFFERARBPROC wglDestroyPbufferARB = nullptr; static void LoadWGLExtensions() { - wglSwapIntervalEXT = reinterpret_cast( - GLInterface->GetFuncAddress("wglSwapIntervalEXT")); + wglSwapIntervalEXT = + reinterpret_cast(wglGetProcAddress("wglSwapIntervalEXT")); wglCreateContextAttribsARB = reinterpret_cast( wglGetProcAddress("wglCreateContextAttribsARB")); wglChoosePixelFormatARB = reinterpret_cast( @@ -157,19 +157,24 @@ static void ClearWGLExtensionPointers() wglDestroyPbufferARB = nullptr; } -void cInterfaceWGL::SwapInterval(int Interval) +bool GLContextWGL::IsHeadless() const +{ + return !m_window_handle; +} + +void GLContextWGL::SwapInterval(int interval) { if (wglSwapIntervalEXT) - wglSwapIntervalEXT(Interval); + wglSwapIntervalEXT(interval); else ERROR_LOG(VIDEO, "No support for SwapInterval (framerate clamped to monitor refresh rate)."); } -void cInterfaceWGL::Swap() +void GLContextWGL::Swap() { SwapBuffers(m_dc); } -void* cInterfaceWGL::GetFuncAddress(const std::string& name) +void* GLContextWGL::GetFuncAddress(const std::string& name) { FARPROC func = wglGetProcAddress(name.c_str()); if (func == nullptr) @@ -183,24 +188,9 @@ void* cInterfaceWGL::GetFuncAddress(const std::string& name) return func; } -// Draw messages on top of the screen -bool cInterfaceWGL::PeekMessages() -{ - // TODO: peekmessage - MSG msg; - while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) - { - if (msg.message == WM_QUIT) - return FALSE; - TranslateMessage(&msg); - DispatchMessage(&msg); - } - return TRUE; -} - // Create rendering window. // Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize() -bool cInterfaceWGL::Create(void* window_handle, bool stereo, bool core) +bool GLContextWGL::Initialize(void* window_handle, bool stereo, bool core) { if (!window_handle) return false; @@ -216,8 +206,8 @@ bool cInterfaceWGL::Create(void* window_handle, bool stereo, bool core) // Control window size and picture scaling int twidth = window_rect.right - window_rect.left; int theight = window_rect.bottom - window_rect.top; - s_backbuffer_width = twidth; - s_backbuffer_height = theight; + m_backbuffer_width = twidth; + m_backbuffer_height = theight; const DWORD stereo_flag = stereo ? PFD_STEREO : 0; @@ -274,8 +264,7 @@ bool cInterfaceWGL::Create(void* window_handle, bool stereo, bool core) } // WGL only supports desktop GL, for now. - if (s_opengl_mode == GLInterfaceMode::MODE_DETECT) - s_opengl_mode = GLInterfaceMode::MODE_OPENGL; + m_opengl_mode = Mode::OpenGL; if (core) { @@ -306,7 +295,7 @@ bool cInterfaceWGL::Create(void* window_handle, bool stereo, bool core) { wglDeleteContext(m_rc); m_rc = core_context; - m_core = true; + m_is_core_context = true; } else { @@ -317,9 +306,11 @@ bool cInterfaceWGL::Create(void* window_handle, bool stereo, bool core) return true; } -bool cInterfaceWGL::Create(cInterfaceBase* main_context) +bool GLContextWGL::Initialize(GLContext* main_context) { - cInterfaceWGL* wgl_main_context = static_cast(main_context); + GLContextWGL* wgl_main_context = static_cast(main_context); + + m_opengl_mode = wgl_main_context->m_opengl_mode; // WGL does not support surfaceless contexts, so we use a 1x1 pbuffer instead. if (!CreatePBuffer(wgl_main_context->m_dc, 1, 1, &m_pbuffer_handle, &m_dc)) @@ -329,14 +320,14 @@ bool cInterfaceWGL::Create(cInterfaceBase* main_context) if (!m_rc) return false; - m_core = true; + m_is_core_context = true; return true; } -std::unique_ptr cInterfaceWGL::CreateSharedContext() +std::unique_ptr GLContextWGL::CreateSharedContext() { - std::unique_ptr context = std::make_unique(); - if (!context->Create(this)) + std::unique_ptr context = std::make_unique(); + if (!context->Initialize(this)) { context->Shutdown(); return nullptr; @@ -345,7 +336,7 @@ std::unique_ptr cInterfaceWGL::CreateSharedContext() return std::move(context); } -HGLRC cInterfaceWGL::CreateCoreContext(HDC dc, HGLRC share_context) +HGLRC GLContextWGL::CreateCoreContext(HDC dc, HGLRC share_context) { if (!wglCreateContextAttribsARB) { @@ -402,8 +393,8 @@ HGLRC cInterfaceWGL::CreateCoreContext(HDC dc, HGLRC share_context) return nullptr; } -bool cInterfaceWGL::CreatePBuffer(HDC onscreen_dc, int width, int height, HANDLE* pbuffer_handle, - HDC* pbuffer_dc) +bool GLContextWGL::CreatePBuffer(HDC onscreen_dc, int width, int height, HANDLE* pbuffer_handle, + HDC* pbuffer_dc) { if (!wglChoosePixelFormatARB || !wglCreatePbufferARB || !wglGetPbufferDCARB || !wglReleasePbufferDCARB || !wglDestroyPbufferARB) @@ -462,29 +453,29 @@ bool cInterfaceWGL::CreatePBuffer(HDC onscreen_dc, int width, int height, HANDLE return true; } -bool cInterfaceWGL::MakeCurrent() +bool GLContextWGL::MakeCurrent() { return wglMakeCurrent(m_dc, m_rc) == TRUE; } -bool cInterfaceWGL::ClearCurrent() +bool GLContextWGL::ClearCurrent() { return wglMakeCurrent(m_dc, nullptr) == TRUE; } // Update window width, size and etc. Called from Render.cpp -void cInterfaceWGL::Update() +void GLContextWGL::Update() { RECT rcWindow; GetClientRect(m_window_handle, &rcWindow); // Get the new window width and height - s_backbuffer_width = rcWindow.right - rcWindow.left; - s_backbuffer_height = rcWindow.bottom - rcWindow.top; + m_backbuffer_width = rcWindow.right - rcWindow.left; + m_backbuffer_height = rcWindow.bottom - rcWindow.top; } // Close backend -void cInterfaceWGL::Shutdown() +void GLContextWGL::Shutdown() { if (m_rc) { diff --git a/Source/Core/Common/GL/GLInterface/WGL.h b/Source/Core/Common/GL/GLInterface/WGL.h index efa9655713..7e74470866 100644 --- a/Source/Core/Common/GL/GLInterface/WGL.h +++ b/Source/Core/Common/GL/GLInterface/WGL.h @@ -6,26 +6,30 @@ #include #include -#include "Common/GL/GLInterfaceBase.h" +#include "Common/GL/GLContext.h" -class cInterfaceWGL : public cInterfaceBase +class GLContextWGL : public GLContext { public: - void SwapInterval(int interval) override; - void Swap() override; - void* GetFuncAddress(const std::string& name) override; - bool Create(void* window_handle, bool stereo, bool core) override; - bool Create(cInterfaceBase* main_context) override; + bool IsHeadless() const; + + std::unique_ptr CreateSharedContext() override; + bool MakeCurrent() override; bool ClearCurrent() override; void Shutdown() override; void Update() override; - bool PeekMessages() override; - std::unique_ptr CreateSharedContext() override; + void Swap() override; + void SwapInterval(int interval) override; + + void* GetFuncAddress(const std::string& name) override; + +protected: + bool Initialize(void* window_handle, bool stereo, bool core) override; + bool Initialize(GLContext* main_context) override; -private: static HGLRC CreateCoreContext(HDC dc, HGLRC share_context); static bool CreatePBuffer(HDC onscreen_dc, int width, int height, HANDLE* pbuffer_handle, HDC* pbuffer_dc); diff --git a/Source/Core/Common/GL/GLInterface/X11_Util.cpp b/Source/Core/Common/GL/GLInterface/X11_Util.cpp deleted file mode 100644 index ed884a9ffd..0000000000 --- a/Source/Core/Common/GL/GLInterface/X11_Util.cpp +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright 2012 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -#include "Common/GL/GLInterface/X11_Util.h" -#include "Common/GL/GLInterfaceBase.h" -#include "Common/Logging/Log.h" -#include "Common/Thread.h" - -void cX11Window::Initialize(Display* _dpy) -{ - dpy = _dpy; -} - -Window cX11Window::CreateXWindow(Window parent, XVisualInfo* vi) -{ - XSetWindowAttributes attr; - - colormap = XCreateColormap(dpy, parent, vi->visual, AllocNone); - - // Setup window attributes - attr.colormap = colormap; - - XWindowAttributes attribs; - if (!XGetWindowAttributes(dpy, parent, &attribs)) - { - ERROR_LOG(VIDEO, "Window attribute retrieval failed"); - return 0; - } - - // Create the window - win = XCreateWindow(dpy, parent, 0, 0, attribs.width, attribs.height, 0, vi->depth, InputOutput, - vi->visual, CWColormap, &attr); - XSelectInput(dpy, parent, StructureNotifyMask); - XMapWindow(dpy, win); - XSync(dpy, True); - - xEventThread = std::thread(&cX11Window::XEventThread, this); - - return win; -} - -void cX11Window::DestroyXWindow(void) -{ - XUnmapWindow(dpy, win); - win = 0; - if (xEventThread.joinable()) - xEventThread.join(); - XFreeColormap(dpy, colormap); -} - -void cX11Window::XEventThread() -{ - while (win) - { - XEvent event; - for (int num_events = XPending(dpy); num_events > 0; num_events--) - { - XNextEvent(dpy, &event); - switch (event.type) - { - case ConfigureNotify: - XResizeWindow(dpy, win, event.xconfigure.width, event.xconfigure.height); - GLInterface->SetBackBufferDimensions(event.xconfigure.width, event.xconfigure.height); - break; - default: - break; - } - } - Common::SleepCurrentThread(20); - } -} diff --git a/Source/Core/Common/GL/GLInterface/X11_Util.h b/Source/Core/Common/GL/GLInterface/X11_Util.h deleted file mode 100644 index e79a6fe1df..0000000000 --- a/Source/Core/Common/GL/GLInterface/X11_Util.h +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2008 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -#pragma once - -#include -#include -#include -#include -#include - -class cX11Window -{ -private: - void XEventThread(); - std::thread xEventThread; - Colormap colormap; - -public: - void Initialize(Display* dpy); - Window CreateXWindow(Window parent, XVisualInfo* vi); - void DestroyXWindow(); - - Display* dpy; - Window win; -}; diff --git a/Source/Core/Common/GL/GLInterfaceBase.h b/Source/Core/Common/GL/GLInterfaceBase.h deleted file mode 100644 index 4ffb7f5f53..0000000000 --- a/Source/Core/Common/GL/GLInterfaceBase.h +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2008 Dolphin Emulator Project -// Licensed under GPLv2+ -// Refer to the license.txt file included. - -#pragma once - -#include -#include - -#include "Common/CommonTypes.h" - -enum class GLInterfaceMode -{ - MODE_DETECT, - MODE_OPENGL, - MODE_OPENGLES2, - MODE_OPENGLES3, -}; - -class cInterfaceBase -{ -protected: - // Window dimensions. - u32 s_backbuffer_width = 0; - u32 s_backbuffer_height = 0; - bool m_core = false; - bool m_is_shared = false; - - GLInterfaceMode s_opengl_mode = GLInterfaceMode::MODE_DETECT; - -public: - virtual ~cInterfaceBase() {} - virtual void Swap() {} - virtual void SetMode(GLInterfaceMode mode) { s_opengl_mode = GLInterfaceMode::MODE_OPENGL; } - virtual GLInterfaceMode GetMode() { return s_opengl_mode; } - virtual void* GetFuncAddress(const std::string& name) { return nullptr; } - virtual bool Create(void* window_handle, bool stereo = false, bool core = true) { return true; } - virtual bool Create(cInterfaceBase* main_context) { return true; } - virtual bool MakeCurrent() { return true; } - virtual bool ClearCurrent() { return true; } - virtual void Shutdown() {} - virtual void SwapInterval(int Interval) {} - virtual u32 GetBackBufferWidth() { return s_backbuffer_width; } - virtual u32 GetBackBufferHeight() { return s_backbuffer_height; } - virtual void SetBackBufferDimensions(u32 W, u32 H) - { - s_backbuffer_width = W; - s_backbuffer_height = H; - } - virtual void Update() {} - virtual bool PeekMessages() { return false; } - virtual void UpdateHandle(void* window_handle) {} - virtual void UpdateSurface() {} - virtual std::unique_ptr CreateSharedContext() { return nullptr; } -}; - -extern std::unique_ptr GLInterface; - -// This function has to be defined along the Host_ functions from Core/Host.h. -// Current canonical implementation: DolphinWX/GLInterface/GLInterface.cpp. -std::unique_ptr HostGL_CreateGLInterface(); diff --git a/Source/Core/Common/GL/GLUtil.cpp b/Source/Core/Common/GL/GLUtil.cpp index 02a38d8654..729cc2c25d 100644 --- a/Source/Core/Common/GL/GLUtil.cpp +++ b/Source/Core/Common/GL/GLUtil.cpp @@ -5,19 +5,12 @@ #include #include "Common/Assert.h" -#include "Common/GL/GLInterfaceBase.h" +#include "Common/GL/GLContext.h" #include "Common/GL/GLUtil.h" #include "Common/Logging/Log.h" -std::unique_ptr GLInterface; - namespace GLUtil { -void InitInterface() -{ - GLInterface = HostGL_CreateGLInterface(); -} - GLuint CompileProgram(const std::string& vertexShader, const std::string& fragmentShader) { // generate objects @@ -107,7 +100,7 @@ void EnablePrimitiveRestart() { constexpr GLuint PRIMITIVE_RESTART_INDEX = 65535; - if (GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGLES3) + if (g_main_gl_context->GetMode() == GLContext::Mode::OpenGLES) { glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX); } @@ -125,4 +118,4 @@ void EnablePrimitiveRestart() } } } -} +} // namespace GLUtil diff --git a/Source/Core/Common/GL/GLUtil.h b/Source/Core/Common/GL/GLUtil.h index d4714026f0..62605585f3 100644 --- a/Source/Core/Common/GL/GLUtil.h +++ b/Source/Core/Common/GL/GLUtil.h @@ -10,7 +10,6 @@ namespace GLUtil { -void InitInterface(); GLuint CompileProgram(const std::string& vertexShader, const std::string& fragmentShader); void EnablePrimitiveRestart(); -} +} // namespace GLUtil diff --git a/Source/Core/Common/GL/GLX11Window.cpp b/Source/Core/Common/GL/GLX11Window.cpp new file mode 100644 index 0000000000..793939377d --- /dev/null +++ b/Source/Core/Common/GL/GLX11Window.cpp @@ -0,0 +1,77 @@ +// Copyright 2012 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "Common/GL/GLX11Window.h" +#include "Common/GL/GLContext.h" +#include "Common/Thread.h" + +GLX11Window::GLX11Window(Display* display, Window parent_window, Colormap color_map, Window window, + int width, int height) + : m_display(display), m_parent_window(parent_window), m_color_map(color_map), m_window(window), + m_width(width), m_height(height), + m_event_thread(std::thread(&GLX11Window::XEventThread, this)) +{ +} + +GLX11Window::~GLX11Window() +{ + Window window = m_window; + m_window = None; + if (m_event_thread.joinable()) + m_event_thread.join(); + XUnmapWindow(m_display, window); + XDestroyWindow(m_display, window); + XFreeColormap(m_display, m_color_map); +} + +std::unique_ptr GLX11Window::Create(Display* display, Window parent_window, + XVisualInfo* vi) +{ + // Set color map for the new window based on the visual. + Colormap color_map = XCreateColormap(display, parent_window, vi->visual, AllocNone); + XSetWindowAttributes attribs = {}; + attribs.colormap = color_map; + + // Get the dimensions from the parent window. + XWindowAttributes parent_attribs = {}; + XGetWindowAttributes(display, parent_window, &parent_attribs); + + // Create the window + Window window = + XCreateWindow(display, parent_window, 0, 0, parent_attribs.width, parent_attribs.height, 0, + vi->depth, InputOutput, vi->visual, CWColormap, &attribs); + XSelectInput(display, parent_window, StructureNotifyMask); + XMapWindow(display, window); + XSync(display, True); + + return std::make_unique(display, parent_window, color_map, window, + parent_attribs.width, parent_attribs.height); +} + +void GLX11Window::XEventThread() +{ + // There's a potential race here on m_window. But this thread will disappear soon. + while (m_window) + { + XEvent event; + for (int num_events = XPending(m_display); num_events > 0; num_events--) + { + XNextEvent(m_display, &event); + switch (event.type) + { + case ConfigureNotify: + { + m_width = event.xconfigure.width; + m_height = event.xconfigure.height; + XResizeWindow(m_display, m_window, m_width, m_height); + g_main_gl_context->SetBackBufferDimensions(m_width, m_height); + } + break; + default: + break; + } + } + Common::SleepCurrentThread(20); + } +} diff --git a/Source/Core/Common/GL/GLX11Window.h b/Source/Core/Common/GL/GLX11Window.h new file mode 100644 index 0000000000..15c183c7cf --- /dev/null +++ b/Source/Core/Common/GL/GLX11Window.h @@ -0,0 +1,41 @@ +// Copyright 2008 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include +#include +#include + +class GLX11Window +{ +public: + GLX11Window(Display* display, Window parent_window, Colormap color_map, Window window, int width, + int height); + ~GLX11Window(); + + Display* GetDisplay() const { return m_display; } + Window GetParentWindow() const { return m_parent_window; } + Window GetWindow() const { return m_window; } + int GetWidth() const { return m_width; } + int GetHeight() const { return m_height; } + + static std::unique_ptr Create(Display* display, Window parent_window, + XVisualInfo* vi); + +private: + void XEventThread(); + + Display* m_display; + Window m_parent_window; + Colormap m_color_map; + Window m_window; + + int m_width; + int m_height; + + std::thread m_event_thread; +}; diff --git a/Source/Core/VideoBackends/OGL/FramebufferManager.cpp b/Source/Core/VideoBackends/OGL/FramebufferManager.cpp index a6cccdaaa2..1c1c976f70 100644 --- a/Source/Core/VideoBackends/OGL/FramebufferManager.cpp +++ b/Source/Core/VideoBackends/OGL/FramebufferManager.cpp @@ -9,7 +9,7 @@ #include "Common/Common.h" #include "Common/CommonTypes.h" -#include "Common/GL/GLInterfaceBase.h" +#include "Common/GL/GLContext.h" #include "Common/Logging/Log.h" #include "Common/MsgHandler.h" @@ -414,7 +414,7 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms glBindBuffer(GL_ARRAY_BUFFER, static_cast(g_vertex_manager.get())->GetVertexBufferHandle()); - if (GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGL) + if (!g_main_gl_context->IsGLES()) glEnable(GL_PROGRAM_POINT_SIZE); } diff --git a/Source/Core/VideoBackends/OGL/OGLTexture.cpp b/Source/Core/VideoBackends/OGL/OGLTexture.cpp index 1efb650eeb..fbe7f576c7 100644 --- a/Source/Core/VideoBackends/OGL/OGLTexture.cpp +++ b/Source/Core/VideoBackends/OGL/OGLTexture.cpp @@ -4,7 +4,6 @@ #include "Common/Assert.h" #include "Common/CommonTypes.h" -#include "Common/GL/GLInterfaceBase.h" #include "Common/MsgHandler.h" #include "VideoBackends/OGL/FramebufferManager.h" diff --git a/Source/Core/VideoBackends/OGL/PerfQuery.cpp b/Source/Core/VideoBackends/OGL/PerfQuery.cpp index b3b5df2265..30a6e1781b 100644 --- a/Source/Core/VideoBackends/OGL/PerfQuery.cpp +++ b/Source/Core/VideoBackends/OGL/PerfQuery.cpp @@ -6,7 +6,7 @@ #include "Common/CommonFuncs.h" #include "Common/CommonTypes.h" -#include "Common/GL/GLInterfaceBase.h" +#include "Common/GL/GLContext.h" #include "Common/GL/GLUtil.h" #include "VideoBackends/OGL/PerfQuery.h" @@ -17,11 +17,10 @@ namespace OGL { std::unique_ptr GetPerfQuery() { - if (GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGLES3 && - GLExtensions::Supports("GL_NV_occlusion_query_samples")) + if (g_main_gl_context->IsGLES() && GLExtensions::Supports("GL_NV_occlusion_query_samples")) return std::make_unique(); - if (GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGLES3) + if (g_main_gl_context->IsGLES()) return std::make_unique(GL_ANY_SAMPLES_PASSED); return std::make_unique(GL_SAMPLES_PASSED); @@ -266,4 +265,4 @@ void PerfQueryGLESNV::FlushResults() FlushOne(); } -} // namespace +} // namespace OGL diff --git a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp index 2d284ae4ef..ae930dddab 100644 --- a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp +++ b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp @@ -12,7 +12,7 @@ #include "Common/Assert.h" #include "Common/CommonTypes.h" #include "Common/FileUtil.h" -#include "Common/GL/GLInterfaceBase.h" +#include "Common/GL/GLContext.h" #include "Common/Logging/Log.h" #include "Common/MsgHandler.h" #include "Common/StringUtil.h" @@ -805,7 +805,7 @@ void ProgramShaderCache::CreateHeader() bool SharedContextAsyncShaderCompiler::WorkerThreadInitMainThread(void** param) { - std::unique_ptr context = GLInterface->CreateSharedContext(); + std::unique_ptr context = g_main_gl_context->CreateSharedContext(); if (!context) { PanicAlert("Failed to create shared context for shader compiling."); @@ -818,7 +818,7 @@ bool SharedContextAsyncShaderCompiler::WorkerThreadInitMainThread(void** param) bool SharedContextAsyncShaderCompiler::WorkerThreadInitWorkerThread(void* param) { - cInterfaceBase* context = static_cast(param); + GLContext* context = static_cast(param); if (!context->MakeCurrent()) return false; @@ -831,7 +831,7 @@ bool SharedContextAsyncShaderCompiler::WorkerThreadInitWorkerThread(void* param) void SharedContextAsyncShaderCompiler::WorkerThreadExit(void* param) { - cInterfaceBase* context = static_cast(param); + GLContext* context = static_cast(param); context->ClearCurrent(); delete context; } diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index 27113a6b8b..18f9fbf322 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -16,7 +16,7 @@ #include "Common/Assert.h" #include "Common/Atomic.h" #include "Common/CommonTypes.h" -#include "Common/GL/GLInterfaceBase.h" +#include "Common/GL/GLContext.h" #include "Common/GL/GLUtil.h" #include "Common/Logging/LogManager.h" #include "Common/MathUtil.h" @@ -354,8 +354,8 @@ static void InitDriverInfo() // Init functions Renderer::Renderer() - : ::Renderer(static_cast(std::max(GLInterface->GetBackBufferWidth(), 1u)), - static_cast(std::max(GLInterface->GetBackBufferHeight(), 1u))) + : ::Renderer(static_cast(std::max(g_main_gl_context->GetBackBufferWidth(), 1u)), + static_cast(std::max(g_main_gl_context->GetBackBufferHeight(), 1u))) { bool bSuccess = true; @@ -365,7 +365,7 @@ Renderer::Renderer() InitDriverInfo(); - if (GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGL) + if (!g_main_gl_context->IsGLES()) { if (!GLExtensions::Supports("GL_ARB_framebuffer_object")) { @@ -500,7 +500,7 @@ Renderer::Renderer() g_Config.backend_info.bSupportsBPTCTextures = GLExtensions::Supports("GL_ARB_texture_compression_bptc"); - if (GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGLES3) + if (g_main_gl_context->IsGLES()) { g_ogl_config.SupportedESPointSize = GLExtensions::Supports("GL_OES_geometry_point_size") ? @@ -730,10 +730,9 @@ Renderer::Renderer() if (!g_ogl_config.bSupportsGLBufferStorage && !g_ogl_config.bSupportsGLPinnedMemory) { - OSD::AddMessage( - StringFromFormat("Your OpenGL driver does not support %s_buffer_storage.", - GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGLES3 ? "EXT" : "ARB"), - 60000); + OSD::AddMessage(StringFromFormat("Your OpenGL driver does not support %s_buffer_storage.", + g_main_gl_context->IsGLES() ? "EXT" : "ARB"), + 60000); OSD::AddMessage("This device's performance will be terrible.", 60000); OSD::AddMessage("Please ask your device vendor for an updated OpenGL driver.", 60000); } @@ -761,7 +760,7 @@ Renderer::Renderer() // Handle VSync on/off s_vsync = g_ActiveConfig.IsVSync(); if (!DriverDetails::HasBug(DriverDetails::BUG_BROKEN_VSYNC)) - GLInterface->SwapInterval(s_vsync); + g_main_gl_context->SwapInterval(s_vsync); // Because of the fixed framebuffer size we need to disable the resolution // options while running @@ -1044,7 +1043,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) std::unique_ptr colorMap(new u32[targetPixelRcWidth * targetPixelRcHeight]); - if (GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGLES3) + if (g_main_gl_context->IsGLES()) // XXX: Swap colours glReadPixels(targetPixelRc.left, targetPixelRc.bottom, targetPixelRcWidth, targetPixelRcHeight, GL_RGBA, GL_UNSIGNED_BYTE, colorMap.get()); @@ -1351,7 +1350,7 @@ void Renderer::ApplyBlendingState(const BlendingState state, bool force) GL_XOR, GL_OR, GL_NOR, GL_EQUIV, GL_INVERT, GL_OR_REVERSE, GL_COPY_INVERTED, GL_OR_INVERTED, GL_NAND, GL_SET}; - if (GLInterface->GetMode() != GLInterfaceMode::MODE_OPENGL) + if (g_main_gl_context->IsGLES()) { // Logic ops aren't available in GLES3 } @@ -1421,7 +1420,7 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region OSD::DrawMessages(); // Swap the back and front buffers, presenting the image. - GLInterface->Swap(); + g_main_gl_context->Swap(); } else { @@ -1466,7 +1465,7 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region { s_vsync = g_ActiveConfig.IsVSync(); if (!DriverDetails::HasBug(DriverDetails::BUG_BROKEN_VSYNC)) - GLInterface->SwapInterval(s_vsync); + g_main_gl_context->SwapInterval(s_vsync); } // Clean out old stuff from caches. It's not worth it to clean out the shader caches. @@ -1502,12 +1501,11 @@ void Renderer::CheckForSurfaceChange() m_surface_handle = m_new_surface_handle; m_new_surface_handle = nullptr; - GLInterface->UpdateHandle(m_surface_handle); - GLInterface->UpdateSurface(); + g_main_gl_context->UpdateSurface(m_surface_handle); // With a surface change, the window likely has new dimensions. - m_backbuffer_width = GLInterface->GetBackBufferWidth(); - m_backbuffer_height = GLInterface->GetBackBufferHeight(); + m_backbuffer_width = g_main_gl_context->GetBackBufferWidth(); + m_backbuffer_height = g_main_gl_context->GetBackBufferHeight(); } void Renderer::CheckForSurfaceResize() @@ -1515,7 +1513,7 @@ void Renderer::CheckForSurfaceResize() if (!m_surface_resized.TestAndClear()) return; - GLInterface->Update(); + g_main_gl_context->Update(); m_backbuffer_width = m_new_backbuffer_width; m_backbuffer_height = m_new_backbuffer_height; } @@ -1538,7 +1536,7 @@ void Renderer::ResetAPIState() glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); glDisable(GL_BLEND); - if (GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGL) + if (!g_main_gl_context->IsGLES()) glDisable(GL_COLOR_LOGIC_OP); if (g_ActiveConfig.backend_info.bSupportsDepthClamp) { @@ -1717,4 +1715,4 @@ std::unique_ptr Renderer::CreateAsyncShaderCom { return std::make_unique(); } -} +} // namespace OGL diff --git a/Source/Core/VideoBackends/OGL/SamplerCache.cpp b/Source/Core/VideoBackends/OGL/SamplerCache.cpp index 32be0ac4d9..ae848e8d29 100644 --- a/Source/Core/VideoBackends/OGL/SamplerCache.cpp +++ b/Source/Core/VideoBackends/OGL/SamplerCache.cpp @@ -7,7 +7,7 @@ #include #include "Common/CommonTypes.h" -#include "Common/GL/GLInterfaceBase.h" +#include "Common/GL/GLContext.h" #include "VideoCommon/SamplerCommon.h" #include "VideoCommon/VideoConfig.h" @@ -99,7 +99,7 @@ void SamplerCache::SetParameters(GLuint sampler_id, const SamplerState& params) glSamplerParameterf(sampler_id, GL_TEXTURE_MIN_LOD, params.min_lod / 16.f); glSamplerParameterf(sampler_id, GL_TEXTURE_MAX_LOD, params.max_lod / 16.f); - if (GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGL) + if (!g_main_gl_context->IsGLES()) glSamplerParameterf(sampler_id, GL_TEXTURE_LOD_BIAS, params.lod_bias / 256.f); if (params.anisotropic_filtering && g_ogl_config.bSupportsAniso) @@ -117,4 +117,4 @@ void SamplerCache::Clear() p.second = 0; m_cache.clear(); } -} +} // namespace OGL diff --git a/Source/Core/VideoBackends/OGL/TextureCache.cpp b/Source/Core/VideoBackends/OGL/TextureCache.cpp index 95a3d30e1a..10f191448e 100644 --- a/Source/Core/VideoBackends/OGL/TextureCache.cpp +++ b/Source/Core/VideoBackends/OGL/TextureCache.cpp @@ -10,7 +10,6 @@ #include #include "Common/Assert.h" -#include "Common/GL/GLInterfaceBase.h" #include "Common/MsgHandler.h" #include "Common/StringUtil.h" diff --git a/Source/Core/VideoBackends/OGL/main.cpp b/Source/Core/VideoBackends/OGL/main.cpp index d2e37f07a9..130669c28e 100644 --- a/Source/Core/VideoBackends/OGL/main.cpp +++ b/Source/Core/VideoBackends/OGL/main.cpp @@ -39,7 +39,7 @@ Make AA apply instantly during gameplay if possible #include #include "Common/Common.h" -#include "Common/GL/GLInterfaceBase.h" +#include "Common/GL/GLContext.h" #include "Common/GL/GLUtil.h" #include "Common/MsgHandler.h" @@ -66,7 +66,7 @@ std::string VideoBackend::GetName() const std::string VideoBackend::GetDisplayName() const { - if (GLInterface != nullptr && GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGLES3) + if (g_main_gl_context && g_main_gl_context->GetMode() == GLContext::Mode::OpenGLES) return _trans("OpenGL ES"); else return _trans("OpenGL"); @@ -161,12 +161,12 @@ bool VideoBackend::Initialize(void* window_handle) { InitializeShared(); - GLUtil::InitInterface(); - GLInterface->SetMode(GLInterfaceMode::MODE_DETECT); - if (!GLInterface->Create(window_handle, g_ActiveConfig.stereo_mode == StereoMode::QuadBuffer)) + g_main_gl_context = + GLContext::Create(window_handle, g_ActiveConfig.stereo_mode == StereoMode::QuadBuffer); + if (!g_main_gl_context) return false; - GLInterface->MakeCurrent(); + g_main_gl_context->MakeCurrent(); if (!InitializeGLExtensions() || !FillBackendInfo()) return false; @@ -196,9 +196,9 @@ void VideoBackend::Shutdown() g_perf_query.reset(); g_vertex_manager.reset(); g_renderer.reset(); - GLInterface->ClearCurrent(); - GLInterface->Shutdown(); - GLInterface.reset(); + g_main_gl_context->ClearCurrent(); + g_main_gl_context->Shutdown(); + g_main_gl_context.reset(); ShutdownShared(); } -} +} // namespace OGL diff --git a/Source/Core/VideoBackends/Software/SWOGLWindow.cpp b/Source/Core/VideoBackends/Software/SWOGLWindow.cpp index 695f58cc1d..dd390bc6dc 100644 --- a/Source/Core/VideoBackends/Software/SWOGLWindow.cpp +++ b/Source/Core/VideoBackends/Software/SWOGLWindow.cpp @@ -4,7 +4,7 @@ #include -#include "Common/GL/GLInterfaceBase.h" +#include "Common/GL/GLContext.h" #include "Common/GL/GLUtil.h" #include "Common/Logging/Log.h" @@ -15,9 +15,8 @@ std::unique_ptr SWOGLWindow::s_instance; void SWOGLWindow::Init(void* window_handle) { - GLUtil::InitInterface(); - GLInterface->SetMode(GLInterfaceMode::MODE_DETECT); - if (!GLInterface->Create(window_handle)) + g_main_gl_context = GLContext::Create(window_handle); + if (!g_main_gl_context) { ERROR_LOG(VIDEO, "GLInterface::Create failed."); } @@ -27,8 +26,8 @@ void SWOGLWindow::Init(void* window_handle) void SWOGLWindow::Shutdown() { - GLInterface->Shutdown(); - GLInterface.reset(); + g_main_gl_context->Shutdown(); + g_main_gl_context.reset(); s_instance.reset(); } @@ -66,10 +65,9 @@ void SWOGLWindow::Prepare() " TexCoord = vec2(rawpos.x, -rawpos.y);\n" "}\n"; - std::string header = GLInterface->GetMode() == GLInterfaceMode::MODE_OPENGL ? - "#version 140\n" : - "#version 300 es\n" - "precision highp float;\n"; + std::string header = g_main_gl_context->IsGLES() ? "#version 300 es\n" + "precision highp float;\n" : + "#version 140\n"; m_image_program = GLUtil::CompileProgram(header + vertex_shader, header + frag_shader); @@ -93,10 +91,10 @@ void SWOGLWindow::PrintText(const std::string& text, int x, int y, u32 color) void SWOGLWindow::ShowImage(AbstractTexture* image, const EFBRectangle& xfb_region) { SW::SWTexture* sw_image = static_cast(image); - GLInterface->Update(); // just updates the render window position and the backbuffer size + g_main_gl_context->Update(); // just updates the render window position and the backbuffer size - GLsizei glWidth = (GLsizei)GLInterface->GetBackBufferWidth(); - GLsizei glHeight = (GLsizei)GLInterface->GetBackBufferHeight(); + GLsizei glWidth = (GLsizei)g_main_gl_context->GetBackBufferWidth(); + GLsizei glHeight = (GLsizei)g_main_gl_context->GetBackBufferHeight(); glViewport(0, 0, glWidth, glHeight); @@ -123,10 +121,5 @@ void SWOGLWindow::ShowImage(AbstractTexture* image, const EFBRectangle& xfb_regi // } m_text.clear(); - GLInterface->Swap(); -} - -int SWOGLWindow::PeekMessages() -{ - return GLInterface->PeekMessages(); + g_main_gl_context->Swap(); } diff --git a/Source/Core/VideoBackends/Software/SWOGLWindow.h b/Source/Core/VideoBackends/Software/SWOGLWindow.h index 64ee2414bc..eadf3171cb 100644 --- a/Source/Core/VideoBackends/Software/SWOGLWindow.h +++ b/Source/Core/VideoBackends/Software/SWOGLWindow.h @@ -26,8 +26,6 @@ public: // Image to show, will be swapped immediately void ShowImage(AbstractTexture* image, const EFBRectangle& xfb_region); - int PeekMessages(); - static std::unique_ptr s_instance; private: diff --git a/Source/Core/VideoBackends/Software/SWmain.cpp b/Source/Core/VideoBackends/Software/SWmain.cpp index 6ca183b57c..8781a2da9b 100644 --- a/Source/Core/VideoBackends/Software/SWmain.cpp +++ b/Source/Core/VideoBackends/Software/SWmain.cpp @@ -9,7 +9,7 @@ #include "Common/Common.h" #include "Common/CommonTypes.h" -#include "Common/GL/GLInterfaceBase.h" +#include "Common/GL/GLContext.h" #include "VideoBackends/Software/Clipper.h" #include "VideoBackends/Software/DebugUtil.h" @@ -88,7 +88,7 @@ bool VideoSoftware::Initialize(void* window_handle) Rasterizer::Init(); DebugUtil::Init(); - GLInterface->MakeCurrent(); + g_main_gl_context->MakeCurrent(); SWOGLWindow::s_instance->Prepare(); g_renderer = std::make_unique(); @@ -116,4 +116,4 @@ void VideoSoftware::Shutdown() g_renderer.reset(); ShutdownShared(); } -} +} // namespace SW diff --git a/Source/UnitTests/StubHost.cpp b/Source/UnitTests/StubHost.cpp index a2ba02c20b..78c81c38f2 100644 --- a/Source/UnitTests/StubHost.cpp +++ b/Source/UnitTests/StubHost.cpp @@ -8,7 +8,6 @@ #include #include -#include "Common/GL/GLInterfaceBase.h" #include "Core/Host.h" void Host_NotifyMapLoaded() @@ -54,7 +53,3 @@ void Host_YieldToUI() void Host_UpdateProgressDialog(const char* caption, int position, int total) { } -std::unique_ptr HostGL_CreateGLInterface() -{ - return nullptr; -} From a3961750a7174be7402fc492367f017d845b8e1f Mon Sep 17 00:00:00 2001 From: Stenzek Date: Wed, 3 Oct 2018 23:03:13 +1000 Subject: [PATCH 03/12] Drop Host_GetRenderSurface and pass display to backend --- Source/Android/jni/MainAndroid.cpp | 5 --- Source/Core/Core/Boot/Boot.h | 8 ++++ Source/Core/Core/Core.cpp | 9 ++-- Source/Core/Core/Host.h | 3 -- Source/Core/DolphinNoGUI/MainNoGUI.cpp | 17 ++++--- Source/Core/DolphinQt/Host.cpp | 13 +----- Source/Core/DolphinQt/Host.h | 1 - Source/Core/DolphinQt/MainWindow.cpp | 19 +++++++- Source/Core/DolphinQt/RenderWidget.cpp | 4 +- Source/Core/VideoBackends/D3D/Render.cpp | 11 +++-- Source/Core/VideoBackends/D3D/Render.h | 3 ++ Source/Core/VideoBackends/D3D/VideoBackend.h | 4 +- Source/Core/VideoBackends/D3D/main.cpp | 4 +- .../Core/VideoBackends/Null/NullBackend.cpp | 4 +- Source/Core/VideoBackends/Null/Render.cpp | 5 +++ Source/Core/VideoBackends/Null/Render.h | 2 + Source/Core/VideoBackends/Null/VideoBackend.h | 4 +- Source/Core/VideoBackends/OGL/Render.cpp | 8 +++- Source/Core/VideoBackends/OGL/Render.h | 2 + Source/Core/VideoBackends/OGL/VideoBackend.h | 4 +- Source/Core/VideoBackends/OGL/main.cpp | 2 +- .../VideoBackends/Software/SWRenderer.cpp | 6 +++ .../Core/VideoBackends/Software/SWRenderer.h | 2 + Source/Core/VideoBackends/Software/SWmain.cpp | 2 +- .../VideoBackends/Software/VideoBackend.h | 4 +- Source/Core/VideoBackends/Vulkan/Renderer.cpp | 45 +++++-------------- Source/Core/VideoBackends/Vulkan/Renderer.h | 2 + .../Core/VideoBackends/Vulkan/SwapChain.cpp | 26 +++++------ Source/Core/VideoBackends/Vulkan/SwapChain.h | 9 ++-- .../Core/VideoBackends/Vulkan/VideoBackend.h | 4 +- Source/Core/VideoBackends/Vulkan/main.cpp | 8 ++-- Source/Core/VideoCommon/RenderBase.cpp | 3 +- Source/Core/VideoCommon/RenderBase.h | 4 +- Source/Core/VideoCommon/VideoBackendBase.h | 2 +- Source/UnitTests/StubHost.cpp | 4 -- 35 files changed, 129 insertions(+), 124 deletions(-) diff --git a/Source/Android/jni/MainAndroid.cpp b/Source/Android/jni/MainAndroid.cpp index 34a19f6426..83fefce338 100644 --- a/Source/Android/jni/MainAndroid.cpp +++ b/Source/Android/jni/MainAndroid.cpp @@ -89,11 +89,6 @@ void Host_Message(HostMessageID id) } } -void* Host_GetRenderHandle() -{ - return s_surf; -} - void Host_UpdateTitle(const std::string& title) { __android_log_write(ANDROID_LOG_INFO, DOLPHIN_TAG, title.c_str()); diff --git a/Source/Core/Core/Boot/Boot.h b/Source/Core/Core/Boot/Boot.h index 589b9b2056..f229c7d560 100644 --- a/Source/Core/Core/Boot/Boot.h +++ b/Source/Core/Core/Boot/Boot.h @@ -78,6 +78,14 @@ struct BootParameters Parameters parameters; std::optional savestate_path; bool delete_savestate = false; + + // Connection to a display server. This is used on X11 and Wayland platforms. + void* display_connection = nullptr; + + // Render surface. This is a pointer to the native window handle, which depends + // on the platform. e.g. HWND for Windows, Window for X11. If the surface is + // set to nullptr, the video backend will run in headless mode. + void* render_surface = nullptr; }; class CBoot diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp index 7ebb070d2b..8831db5908 100644 --- a/Source/Core/Core/Core.cpp +++ b/Source/Core/Core/Core.cpp @@ -89,7 +89,6 @@ static bool s_is_stopping = false; static bool s_hardware_initialized = false; static bool s_is_started = false; static Common::Flag s_is_booting; -static void* s_window_handle = nullptr; static std::thread s_emu_thread; static StateChangedCallbackFunc s_on_state_changed_callback; @@ -215,8 +214,6 @@ bool Init(std::unique_ptr boot) Host_UpdateMainFrame(); // Disable any menus or buttons at boot - s_window_handle = Host_GetRenderHandle(); - // Start the emu thread s_emu_thread = std::thread(EmuThread, std::move(boot)); return true; @@ -441,7 +438,7 @@ static void EmuThread(std::unique_ptr boot) g_video_backend->InitBackendInfo(); g_Config.Refresh(); - if (!g_video_backend->Initialize(s_window_handle)) + if (!g_video_backend->Initialize(boot->display_connection, boot->render_surface)) { PanicAlert("Failed to initialize video backend!"); return; @@ -462,7 +459,7 @@ static void EmuThread(std::unique_ptr boot) bool init_controllers = false; if (!g_controller_interface.IsInit()) { - g_controller_interface.Initialize(s_window_handle); + g_controller_interface.Initialize(boot->render_surface); Pad::Initialize(); Keyboard::Initialize(); init_controllers = true; @@ -958,4 +955,4 @@ void DoFrameStep() } } -} // Core +} // namespace Core diff --git a/Source/Core/Core/Host.h b/Source/Core/Core/Host.h index 72e9c3d8a0..3777d375f5 100644 --- a/Source/Core/Core/Host.h +++ b/Source/Core/Core/Host.h @@ -44,6 +44,3 @@ void Host_UpdateMainFrame(); void Host_UpdateTitle(const std::string& title); void Host_YieldToUI(); void Host_UpdateProgressDialog(const char* caption, int position, int total); - -// TODO (neobrain): Remove this from host! -void* Host_GetRenderHandle(); diff --git a/Source/Core/DolphinNoGUI/MainNoGUI.cpp b/Source/Core/DolphinNoGUI/MainNoGUI.cpp index 5097b1b8f9..60c037e005 100644 --- a/Source/Core/DolphinNoGUI/MainNoGUI.cpp +++ b/Source/Core/DolphinNoGUI/MainNoGUI.cpp @@ -71,6 +71,9 @@ public: } virtual void Shutdown() {} virtual ~Platform() {} + + virtual void* GetDisplayHandle() { return nullptr; } + virtual void* GetWindowHandle() { return nullptr; } }; static Platform* platform; @@ -91,12 +94,6 @@ void Host_Message(HostMessageID id) updateMainFrameEvent.Set(); } -static void* s_window_handle = nullptr; -void* Host_GetRenderHandle() -{ - return s_window_handle; -} - void Host_UpdateTitle(const std::string& title) { platform->SetTitle(title); @@ -187,7 +184,6 @@ class PlatformX11 : public Platform } XMapRaised(dpy, win); XFlush(dpy); - s_window_handle = (void*)win; if (SConfig::GetInstance().bDisableScreenSaver) X11Utils::InhibitScreensaver(win, true); @@ -354,6 +350,10 @@ class PlatformX11 : public Platform XCloseDisplay(dpy); } + + void* GetDisplayHandle() override { return static_cast(dpy); } + + void* GetWindowHandle() override { return reinterpret_cast(win); } }; #endif @@ -433,6 +433,9 @@ int main(int argc, char* argv[]) DolphinAnalytics::Instance()->ReportDolphinStart("nogui"); + boot->display_connection = platform->GetDisplayHandle(); + boot->render_surface = platform->GetWindowHandle(); + if (!BootManager::BootCore(std::move(boot))) { fprintf(stderr, "Could not boot the specified file\n"); diff --git a/Source/Core/DolphinQt/Host.cpp b/Source/Core/DolphinQt/Host.cpp index 975091eac5..0470c008b5 100644 --- a/Source/Core/DolphinQt/Host.cpp +++ b/Source/Core/DolphinQt/Host.cpp @@ -30,14 +30,10 @@ Host* Host::GetInstance() return s_instance; } -void* Host::GetRenderHandle() -{ - return m_render_handle; -} - void Host::SetRenderHandle(void* handle) { - m_render_handle = handle; + if (g_renderer) + g_renderer->ChangeSurface(handle); } bool Host::GetRenderFocus() @@ -94,11 +90,6 @@ void Host_UpdateTitle(const std::string& title) emit Host::GetInstance()->RequestTitle(QString::fromStdString(title)); } -void* Host_GetRenderHandle() -{ - return Host::GetInstance()->GetRenderHandle(); -} - bool Host_RendererHasFocus() { return Host::GetInstance()->GetRenderFocus(); diff --git a/Source/Core/DolphinQt/Host.h b/Source/Core/DolphinQt/Host.h index cd5e5d5c3e..9a25d217a9 100644 --- a/Source/Core/DolphinQt/Host.h +++ b/Source/Core/DolphinQt/Host.h @@ -20,7 +20,6 @@ class Host final : public QObject public: static Host* GetInstance(); - void* GetRenderHandle(); bool GetRenderFocus(); bool GetRenderFullscreen(); diff --git a/Source/Core/DolphinQt/MainWindow.cpp b/Source/Core/DolphinQt/MainWindow.cpp index 6330fb7fcf..0a2ebfe101 100644 --- a/Source/Core/DolphinQt/MainWindow.cpp +++ b/Source/Core/DolphinQt/MainWindow.cpp @@ -26,6 +26,10 @@ #include "QtUtils/SignalDaemon.h" #endif +#ifndef WIN32 +#include +#endif + #include "Common/Version.h" #include "Core/Boot/Boot.h" @@ -98,7 +102,6 @@ #include "VideoCommon/VideoConfig.h" #if defined(HAVE_XRANDR) && HAVE_XRANDR -#include #include "UICommon/X11Utils.h" #endif @@ -797,14 +800,26 @@ void MainWindow::StartGame(std::unique_ptr&& parameters) m_pending_boot = std::move(parameters); return; } + + // We need the render widget before booting. + ShowRenderWidget(); + + // Populate the video backend fields of the boot parameters. + parameters->render_surface = reinterpret_cast(m_render_widget->winId()); +#ifndef WIN32 + parameters->display_connection = + QGuiApplication::platformNativeInterface()->nativeResourceForWindow("display", + windowHandle()); +#endif + // Boot up, show an error if it fails to load the game. if (!BootManager::BootCore(std::move(parameters))) { QMessageBox::critical(this, tr("Error"), tr("Failed to init core"), QMessageBox::Ok); + HideRenderWidget(); return; } - ShowRenderWidget(); #ifdef USE_DISCORD_PRESENCE if (!NetPlay::IsNetPlayRunning()) Discord::UpdateDiscordPresence(); diff --git a/Source/Core/DolphinQt/RenderWidget.cpp b/Source/Core/DolphinQt/RenderWidget.cpp index d37872dcdf..6846de5dd5 100644 --- a/Source/Core/DolphinQt/RenderWidget.cpp +++ b/Source/Core/DolphinQt/RenderWidget.cpp @@ -55,8 +55,6 @@ RenderWidget::RenderWidget(QWidget* parent) : QWidget(parent) connect(this, &RenderWidget::FocusChanged, Host::GetInstance(), &Host::SetRenderFocus, Qt::DirectConnection); - emit HandleChanged((void*)winId()); - m_mouse_timer = new QTimer(this); connect(m_mouse_timer, &QTimer::timeout, this, &RenderWidget::HandleCursorTimer); m_mouse_timer->setSingleShot(true); @@ -144,7 +142,7 @@ bool RenderWidget::event(QEvent* event) } break; case QEvent::WinIdChange: - emit HandleChanged((void*)winId()); + emit HandleChanged(reinterpret_cast(winId())); break; case QEvent::WindowActivate: if (SConfig::GetInstance().m_PauseOnFocusLost && Core::GetState() == Core::State::Paused) diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index b179597204..fc413673da 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -225,6 +225,11 @@ void Renderer::Create3DVisionTexture(int width, int height) DXGI_FORMAT_R8G8B8A8_UNORM, 1, 1, &sys_data); } +bool Renderer::IsHeadless() const +{ + return D3D::swapchain == nullptr; +} + std::unique_ptr Renderer::CreateTexture(const TextureConfig& config) { return std::make_unique(config); @@ -698,12 +703,12 @@ void Renderer::CheckForSurfaceChange() if (!m_surface_changed.TestAndClear()) return; - m_surface_handle = m_new_surface_handle; - m_new_surface_handle = nullptr; - SAFE_RELEASE(m_screenshot_texture); SAFE_RELEASE(m_3d_vision_texture); + D3D::Reset(reinterpret_cast(m_new_surface_handle)); + m_new_surface_handle = nullptr; + UpdateBackbufferSize(); } diff --git a/Source/Core/VideoBackends/D3D/Render.h b/Source/Core/VideoBackends/D3D/Render.h index 0927f6c934..24b02af672 100644 --- a/Source/Core/VideoBackends/D3D/Render.h +++ b/Source/Core/VideoBackends/D3D/Render.h @@ -22,6 +22,9 @@ public: ~Renderer() override; StateCache& GetStateCache() { return m_state_cache; } + + bool IsHeadless() const override; + std::unique_ptr CreateTexture(const TextureConfig& config) override; std::unique_ptr CreateStagingTexture(StagingTextureType type, const TextureConfig& config) override; diff --git a/Source/Core/VideoBackends/D3D/VideoBackend.h b/Source/Core/VideoBackends/D3D/VideoBackend.h index 59bd8d9b73..2470401dd3 100644 --- a/Source/Core/VideoBackends/D3D/VideoBackend.h +++ b/Source/Core/VideoBackends/D3D/VideoBackend.h @@ -11,7 +11,7 @@ namespace DX11 { class VideoBackend : public VideoBackendBase { - bool Initialize(void*) override; + bool Initialize(void* display_handle, void* window_handle) override; void Shutdown() override; std::string GetName() const override; @@ -19,4 +19,4 @@ class VideoBackend : public VideoBackendBase void InitBackendInfo() override; }; -} +} // namespace DX11 diff --git a/Source/Core/VideoBackends/D3D/main.cpp b/Source/Core/VideoBackends/D3D/main.cpp index 69b6f47804..36c5558435 100644 --- a/Source/Core/VideoBackends/D3D/main.cpp +++ b/Source/Core/VideoBackends/D3D/main.cpp @@ -127,7 +127,7 @@ void VideoBackend::InitBackendInfo() DX11::D3D::UnloadD3D(); } -bool VideoBackend::Initialize(void* window_handle) +bool VideoBackend::Initialize(void* display_handle, void* window_handle) { if (window_handle == nullptr) return false; @@ -188,4 +188,4 @@ void VideoBackend::Shutdown() D3D::Close(); } -} +} // namespace DX11 diff --git a/Source/Core/VideoBackends/Null/NullBackend.cpp b/Source/Core/VideoBackends/Null/NullBackend.cpp index f3743773c5..6d2edb79b5 100644 --- a/Source/Core/VideoBackends/Null/NullBackend.cpp +++ b/Source/Core/VideoBackends/Null/NullBackend.cpp @@ -54,7 +54,7 @@ void VideoBackend::InitBackendInfo() g_Config.backend_info.AAModes = {1}; } -bool VideoBackend::Initialize(void* window_handle) +bool VideoBackend::Initialize(void* display_handle, void* window_handle) { InitializeShared(); @@ -80,4 +80,4 @@ void VideoBackend::Shutdown() ShutdownShared(); } -} +} // namespace Null diff --git a/Source/Core/VideoBackends/Null/Render.cpp b/Source/Core/VideoBackends/Null/Render.cpp index c9c0e62325..c80506c15b 100644 --- a/Source/Core/VideoBackends/Null/Render.cpp +++ b/Source/Core/VideoBackends/Null/Render.cpp @@ -24,6 +24,11 @@ Renderer::~Renderer() UpdateActiveConfig(); } +bool Renderer::IsHeadless() const +{ + return true; +} + std::unique_ptr Renderer::CreateTexture(const TextureConfig& config) { return std::make_unique(config); diff --git a/Source/Core/VideoBackends/Null/Render.h b/Source/Core/VideoBackends/Null/Render.h index c1bf9c122e..10f15f0304 100644 --- a/Source/Core/VideoBackends/Null/Render.h +++ b/Source/Core/VideoBackends/Null/Render.h @@ -14,6 +14,8 @@ public: Renderer(); ~Renderer() override; + bool IsHeadless() const override; + std::unique_ptr CreateTexture(const TextureConfig& config) override; std::unique_ptr CreateStagingTexture(StagingTextureType type, const TextureConfig& config) override; diff --git a/Source/Core/VideoBackends/Null/VideoBackend.h b/Source/Core/VideoBackends/Null/VideoBackend.h index 2f5f0dc057..3d0353f073 100644 --- a/Source/Core/VideoBackends/Null/VideoBackend.h +++ b/Source/Core/VideoBackends/Null/VideoBackend.h @@ -11,7 +11,7 @@ namespace Null { class VideoBackend : public VideoBackendBase { - bool Initialize(void* window_handle) override; + bool Initialize(void* display_handle, void* window_handle) override; void Shutdown() override; std::string GetName() const override { return "Null"; } @@ -22,4 +22,4 @@ class VideoBackend : public VideoBackendBase } void InitBackendInfo() override; }; -} +} // namespace Null diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index 18f9fbf322..5ee01701f2 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -804,6 +804,11 @@ Renderer::Renderer() Renderer::~Renderer() = default; +bool Renderer::IsHeadless() const +{ + return g_main_gl_context->IsHeadless(); +} + void Renderer::Shutdown() { ::Renderer::Shutdown(); @@ -1499,9 +1504,8 @@ void Renderer::CheckForSurfaceChange() if (!m_surface_changed.TestAndClear()) return; - m_surface_handle = m_new_surface_handle; + g_main_gl_context->UpdateSurface(m_new_surface_handle); m_new_surface_handle = nullptr; - g_main_gl_context->UpdateSurface(m_surface_handle); // With a surface change, the window likely has new dimensions. m_backbuffer_width = g_main_gl_context->GetBackBufferWidth(); diff --git a/Source/Core/VideoBackends/OGL/Render.h b/Source/Core/VideoBackends/OGL/Render.h index c27c06308c..7662900624 100644 --- a/Source/Core/VideoBackends/OGL/Render.h +++ b/Source/Core/VideoBackends/OGL/Render.h @@ -84,6 +84,8 @@ public: Renderer(); ~Renderer() override; + bool IsHeadless() const override; + void Init(); void Shutdown() override; diff --git a/Source/Core/VideoBackends/OGL/VideoBackend.h b/Source/Core/VideoBackends/OGL/VideoBackend.h index 1bb4cb3af1..96864f3ecc 100644 --- a/Source/Core/VideoBackends/OGL/VideoBackend.h +++ b/Source/Core/VideoBackends/OGL/VideoBackend.h @@ -11,7 +11,7 @@ namespace OGL { class VideoBackend : public VideoBackendBase { - bool Initialize(void*) override; + bool Initialize(void* display_handle, void* window_handle) override; void Shutdown() override; std::string GetName() const override; @@ -23,4 +23,4 @@ private: bool InitializeGLExtensions(); bool FillBackendInfo(); }; -} +} // namespace OGL diff --git a/Source/Core/VideoBackends/OGL/main.cpp b/Source/Core/VideoBackends/OGL/main.cpp index 130669c28e..27a0192b2c 100644 --- a/Source/Core/VideoBackends/OGL/main.cpp +++ b/Source/Core/VideoBackends/OGL/main.cpp @@ -157,7 +157,7 @@ bool VideoBackend::FillBackendInfo() return true; } -bool VideoBackend::Initialize(void* window_handle) +bool VideoBackend::Initialize(void* display_handle, void* window_handle) { InitializeShared(); diff --git a/Source/Core/VideoBackends/Software/SWRenderer.cpp b/Source/Core/VideoBackends/Software/SWRenderer.cpp index f4e322619d..5e76cdd296 100644 --- a/Source/Core/VideoBackends/Software/SWRenderer.cpp +++ b/Source/Core/VideoBackends/Software/SWRenderer.cpp @@ -7,6 +7,7 @@ #include #include "Common/CommonTypes.h" +#include "Common/GL/GLContext.h" #include "Core/Config/GraphicsSettings.h" #include "Core/HW/Memmap.h" @@ -28,6 +29,11 @@ SWRenderer::SWRenderer() { } +bool SWRenderer::IsHeadless() const +{ + return g_main_gl_context->IsHeadless(); +} + std::unique_ptr SWRenderer::CreateTexture(const TextureConfig& config) { return std::make_unique(config); diff --git a/Source/Core/VideoBackends/Software/SWRenderer.h b/Source/Core/VideoBackends/Software/SWRenderer.h index 3c274edda7..6b2a3f0795 100644 --- a/Source/Core/VideoBackends/Software/SWRenderer.h +++ b/Source/Core/VideoBackends/Software/SWRenderer.h @@ -13,6 +13,8 @@ class SWRenderer : public Renderer public: SWRenderer(); + bool IsHeadless() const override; + std::unique_ptr CreateTexture(const TextureConfig& config) override; std::unique_ptr CreateStagingTexture(StagingTextureType type, const TextureConfig& config) override; diff --git a/Source/Core/VideoBackends/Software/SWmain.cpp b/Source/Core/VideoBackends/Software/SWmain.cpp index 8781a2da9b..f4c0aaa641 100644 --- a/Source/Core/VideoBackends/Software/SWmain.cpp +++ b/Source/Core/VideoBackends/Software/SWmain.cpp @@ -78,7 +78,7 @@ void VideoSoftware::InitBackendInfo() g_Config.backend_info.AAModes = {1}; } -bool VideoSoftware::Initialize(void* window_handle) +bool VideoSoftware::Initialize(void* display_handle, void* window_handle) { InitializeShared(); diff --git a/Source/Core/VideoBackends/Software/VideoBackend.h b/Source/Core/VideoBackends/Software/VideoBackend.h index f618ea44ab..336a96325b 100644 --- a/Source/Core/VideoBackends/Software/VideoBackend.h +++ b/Source/Core/VideoBackends/Software/VideoBackend.h @@ -11,7 +11,7 @@ namespace SW { class VideoSoftware : public VideoBackendBase { - bool Initialize(void* window_handle) override; + bool Initialize(void* display_handle, void* window_handle) override; void Shutdown() override; std::string GetName() const override; @@ -19,4 +19,4 @@ class VideoSoftware : public VideoBackendBase void InitBackendInfo() override; }; -} +} // namespace SW diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.cpp b/Source/Core/VideoBackends/Vulkan/Renderer.cpp index 38d7bd0992..371b9033a8 100644 --- a/Source/Core/VideoBackends/Vulkan/Renderer.cpp +++ b/Source/Core/VideoBackends/Vulkan/Renderer.cpp @@ -70,6 +70,11 @@ Renderer* Renderer::GetInstance() return static_cast(g_renderer.get()); } +bool Renderer::IsHeadless() const +{ + return m_swap_chain == nullptr; +} + bool Renderer::Initialize() { BindEFBToStateTracker(); @@ -860,12 +865,9 @@ void Renderer::BlitScreen(VkRenderPass render_pass, const TargetRectangle& dst_r void Renderer::CheckForSurfaceChange() { - if (!m_surface_changed.TestAndClear()) + if (!m_surface_changed.TestAndClear() || !m_swap_chain) return; - m_surface_handle = m_new_surface_handle; - m_new_surface_handle = nullptr; - // Submit the current draws up until rendering the XFB. g_command_buffer_mgr->ExecuteCommandBuffer(false, false); g_command_buffer_mgr->WaitForGPUIdle(); @@ -873,37 +875,10 @@ void Renderer::CheckForSurfaceChange() // Clear the present failed flag, since we don't want to resize after recreating. g_command_buffer_mgr->CheckLastPresentFail(); - // Did we previously have a swap chain? - if (m_swap_chain) - { - if (!m_surface_handle) - { - // If there is no surface now, destroy the swap chain. - m_swap_chain.reset(); - } - else - { - // Recreate the surface. If this fails we're in trouble. - if (!m_swap_chain->RecreateSurface(m_surface_handle)) - PanicAlert("Failed to recreate Vulkan surface. Cannot continue."); - } - } - else - { - // Previously had no swap chain. So create one. - VkSurfaceKHR surface = - SwapChain::CreateVulkanSurface(g_vulkan_context->GetVulkanInstance(), m_surface_handle); - if (surface != VK_NULL_HANDLE) - { - m_swap_chain = SwapChain::Create(m_surface_handle, surface, g_ActiveConfig.IsVSync()); - if (!m_swap_chain) - PanicAlert("Failed to create swap chain."); - } - else - { - PanicAlert("Failed to create surface."); - } - } + // Recreate the surface. If this fails we're in trouble. + if (!m_swap_chain->RecreateSurface(m_new_surface_handle)) + PanicAlert("Failed to recreate Vulkan surface. Cannot continue."); + m_new_surface_handle = nullptr; // Handle case where the dimensions are now different. OnSwapChainResized(); diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.h b/Source/Core/VideoBackends/Vulkan/Renderer.h index ce15d12592..ba8fd889bd 100644 --- a/Source/Core/VideoBackends/Vulkan/Renderer.h +++ b/Source/Core/VideoBackends/Vulkan/Renderer.h @@ -35,6 +35,8 @@ public: static Renderer* GetInstance(); + bool IsHeadless() const override; + std::unique_ptr CreateTexture(const TextureConfig& config) override; std::unique_ptr CreateStagingTexture(StagingTextureType type, const TextureConfig& config) override; diff --git a/Source/Core/VideoBackends/Vulkan/SwapChain.cpp b/Source/Core/VideoBackends/Vulkan/SwapChain.cpp index 3294b944ef..5222d88114 100644 --- a/Source/Core/VideoBackends/Vulkan/SwapChain.cpp +++ b/Source/Core/VideoBackends/Vulkan/SwapChain.cpp @@ -25,8 +25,9 @@ namespace Vulkan { -SwapChain::SwapChain(void* native_handle, VkSurfaceKHR surface, bool vsync) - : m_native_handle(native_handle), m_surface(surface), m_vsync_enabled(vsync) +SwapChain::SwapChain(void* display_handle, void* native_handle, VkSurfaceKHR surface, bool vsync) + : m_display_handle(display_handle), m_native_handle(native_handle), m_surface(surface), + m_vsync_enabled(vsync) { } @@ -37,7 +38,7 @@ SwapChain::~SwapChain() DestroySurface(); } -VkSurfaceKHR SwapChain::CreateVulkanSurface(VkInstance instance, void* hwnd) +VkSurfaceKHR SwapChain::CreateVulkanSurface(VkInstance instance, void* display_handle, void* hwnd) { #if defined(VK_USE_PLATFORM_WIN32_KHR) VkWin32SurfaceCreateInfoKHR surface_create_info = { @@ -59,15 +60,11 @@ VkSurfaceKHR SwapChain::CreateVulkanSurface(VkInstance instance, void* hwnd) return surface; #elif defined(VK_USE_PLATFORM_XLIB_KHR) - // Assuming the display handles are compatible, or shared. This matches what we do in the - // GL backend, but it's not ideal. - Display* display = XOpenDisplay(nullptr); - VkXlibSurfaceCreateInfoKHR surface_create_info = { VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, // VkStructureType sType nullptr, // const void* pNext 0, // VkXlibSurfaceCreateFlagsKHR flags - display, // Display* dpy + static_cast(display_handle), // Display* dpy reinterpret_cast(hwnd) // Window window }; @@ -83,8 +80,7 @@ VkSurfaceKHR SwapChain::CreateVulkanSurface(VkInstance instance, void* hwnd) #elif defined(VK_USE_PLATFORM_XCB_KHR) // If we ever switch to using xcb, we should pass the display handle as well. - Display* display = XOpenDisplay(nullptr); - xcb_connection_t* connection = XGetXCBConnection(display); + xcb_connection_t* connection = XGetXCBConnection(display_handle); VkXcbSurfaceCreateInfoKHR surface_create_info = { VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR, // VkStructureType sType @@ -127,10 +123,11 @@ VkSurfaceKHR SwapChain::CreateVulkanSurface(VkInstance instance, void* hwnd) #endif } -std::unique_ptr SwapChain::Create(void* native_handle, VkSurfaceKHR surface, bool vsync) +std::unique_ptr SwapChain::Create(void* display_handle, void* native_handle, + VkSurfaceKHR surface, bool vsync) { std::unique_ptr swap_chain = - std::make_unique(native_handle, surface, vsync); + std::make_unique(display_handle, native_handle, surface, vsync); if (!swap_chain->CreateSwapChain() || !swap_chain->CreateRenderPass() || !swap_chain->SetupSwapChainImages()) @@ -467,7 +464,8 @@ bool SwapChain::RecreateSurface(void* native_handle) // Re-create the surface with the new native handle m_native_handle = native_handle; - m_surface = CreateVulkanSurface(g_vulkan_context->GetVulkanInstance(), native_handle); + m_surface = + CreateVulkanSurface(g_vulkan_context->GetVulkanInstance(), m_display_handle, native_handle); if (m_surface == VK_NULL_HANDLE) return false; @@ -499,4 +497,4 @@ void SwapChain::DestroySurface() vkDestroySurfaceKHR(g_vulkan_context->GetVulkanInstance(), m_surface, nullptr); m_surface = VK_NULL_HANDLE; } -} +} // namespace Vulkan diff --git a/Source/Core/VideoBackends/Vulkan/SwapChain.h b/Source/Core/VideoBackends/Vulkan/SwapChain.h index 1561103cb8..8cf2776a36 100644 --- a/Source/Core/VideoBackends/Vulkan/SwapChain.h +++ b/Source/Core/VideoBackends/Vulkan/SwapChain.h @@ -19,15 +19,17 @@ class ObjectCache; class SwapChain { public: - SwapChain(void* native_handle, VkSurfaceKHR surface, bool vsync); + SwapChain(void* display_handle, void* native_handle, VkSurfaceKHR surface, bool vsync); ~SwapChain(); // Creates a vulkan-renderable surface for the specified window handle. - static VkSurfaceKHR CreateVulkanSurface(VkInstance instance, void* hwnd); + static VkSurfaceKHR CreateVulkanSurface(VkInstance instance, void* display_handle, void* hwnd); // Create a new swap chain from a pre-existing surface. - static std::unique_ptr Create(void* native_handle, VkSurfaceKHR surface, bool vsync); + static std::unique_ptr Create(void* display_handle, void* native_handle, + VkSurfaceKHR surface, bool vsync); + void* GetDisplayHandle() const { return m_display_handle; } void* GetNativeHandle() const { return m_native_handle; } VkSurfaceKHR GetSurface() const { return m_surface; } VkSurfaceFormatKHR GetSurfaceFormat() const { return m_surface_format; } @@ -81,6 +83,7 @@ private: VkFramebuffer framebuffer; }; + void* m_display_handle; void* m_native_handle; VkSurfaceKHR m_surface = VK_NULL_HANDLE; VkSurfaceFormatKHR m_surface_format = {}; diff --git a/Source/Core/VideoBackends/Vulkan/VideoBackend.h b/Source/Core/VideoBackends/Vulkan/VideoBackend.h index d4f284962b..ddf0ab4342 100644 --- a/Source/Core/VideoBackends/Vulkan/VideoBackend.h +++ b/Source/Core/VideoBackends/Vulkan/VideoBackend.h @@ -12,11 +12,11 @@ namespace Vulkan class VideoBackend : public VideoBackendBase { public: - bool Initialize(void* window_handle) override; + bool Initialize(void* display_handle, void* window_handle) override; void Shutdown() override; std::string GetName() const override { return "Vulkan"; } std::string GetDisplayName() const override { return _trans("Vulkan"); } void InitBackendInfo() override; }; -} +} // namespace Vulkan diff --git a/Source/Core/VideoBackends/Vulkan/main.cpp b/Source/Core/VideoBackends/Vulkan/main.cpp index 9bd4039138..2617de2191 100644 --- a/Source/Core/VideoBackends/Vulkan/main.cpp +++ b/Source/Core/VideoBackends/Vulkan/main.cpp @@ -89,7 +89,7 @@ static bool ShouldEnableDebugReports(bool enable_validation_layers) return enable_validation_layers || IsHostGPULoggingEnabled(); } -bool VideoBackend::Initialize(void* window_handle) +bool VideoBackend::Initialize(void* display_handle, void* window_handle) { if (!LoadVulkanLibrary()) { @@ -146,7 +146,7 @@ bool VideoBackend::Initialize(void* window_handle) VkSurfaceKHR surface = VK_NULL_HANDLE; if (enable_surface) { - surface = SwapChain::CreateVulkanSurface(instance, window_handle); + surface = SwapChain::CreateVulkanSurface(instance, display_handle, window_handle); if (surface == VK_NULL_HANDLE) { PanicAlert("Failed to create Vulkan surface."); @@ -209,7 +209,7 @@ bool VideoBackend::Initialize(void* window_handle) std::unique_ptr swap_chain; if (surface != VK_NULL_HANDLE) { - swap_chain = SwapChain::Create(window_handle, surface, g_Config.IsVSync()); + swap_chain = SwapChain::Create(display_handle, window_handle, surface, g_Config.IsVSync()); if (!swap_chain) { PanicAlert("Failed to create Vulkan swap chain."); @@ -271,4 +271,4 @@ void VideoBackend::Shutdown() ShutdownShared(); UnloadVulkanLibrary(); } -} +} // namespace Vulkan diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index 317f876aa7..3c7eec10f1 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -86,7 +86,6 @@ Renderer::Renderer(int backbuffer_width, int backbuffer_height) if (SConfig::GetInstance().bWii) m_aspect_wide = Config::Get(Config::SYSCONF_WIDESCREEN); - m_surface_handle = Host_GetRenderHandle(); m_last_host_config_bits = ShaderHostConfig::GetCurrent().bits; m_last_efb_multisamples = g_ActiveConfig.iMultisamples; } @@ -408,7 +407,7 @@ float Renderer::CalculateDrawAspectRatio() const bool Renderer::IsHeadless() const { - return !m_surface_handle; + return true; } void Renderer::ChangeSurface(void* new_surface_handle) diff --git a/Source/Core/VideoCommon/RenderBase.h b/Source/Core/VideoCommon/RenderBase.h index e5861d00c9..07f7ea7bae 100644 --- a/Source/Core/VideoCommon/RenderBase.h +++ b/Source/Core/VideoCommon/RenderBase.h @@ -77,6 +77,8 @@ public: using ClearColor = std::array; + virtual bool IsHeadless() const = 0; + virtual void SetPipeline(const AbstractPipeline* pipeline) {} virtual void SetScissorRect(const MathUtil::Rectangle& rc) {} virtual void SetTexture(u32 index, const AbstractTexture* texture) {} @@ -134,7 +136,6 @@ public: const TargetRectangle& GetTargetRectangle() const { return m_target_rectangle; } float CalculateDrawAspectRatio() const; - bool IsHeadless() const; std::tuple ScaleToDisplayAspectRatio(int width, int height) const; void UpdateDrawRectangle(); @@ -236,7 +237,6 @@ protected: std::unique_ptr m_post_processor; - void* m_surface_handle = nullptr; void* m_new_surface_handle = nullptr; Common::Flag m_surface_changed; Common::Flag m_surface_resized; diff --git a/Source/Core/VideoCommon/VideoBackendBase.h b/Source/Core/VideoCommon/VideoBackendBase.h index 5f43b904d4..3b106bff98 100644 --- a/Source/Core/VideoCommon/VideoBackendBase.h +++ b/Source/Core/VideoCommon/VideoBackendBase.h @@ -35,7 +35,7 @@ class VideoBackendBase { public: virtual ~VideoBackendBase() {} - virtual bool Initialize(void* window_handle) = 0; + virtual bool Initialize(void* display_handle, void* window_handle) = 0; virtual void Shutdown() = 0; virtual std::string GetName() const = 0; diff --git a/Source/UnitTests/StubHost.cpp b/Source/UnitTests/StubHost.cpp index 78c81c38f2..62a332e59b 100644 --- a/Source/UnitTests/StubHost.cpp +++ b/Source/UnitTests/StubHost.cpp @@ -19,10 +19,6 @@ void Host_RefreshDSPDebuggerWindow() void Host_Message(HostMessageID) { } -void* Host_GetRenderHandle() -{ - return nullptr; -} void Host_UpdateTitle(const std::string&) { } From 1d827a52234974f308e71e86cdd6f61293e0523f Mon Sep 17 00:00:00 2001 From: Stenzek Date: Wed, 3 Oct 2018 23:03:16 +1000 Subject: [PATCH 04/12] Renderer: Pull dimensions from GLInterface/Swapchain --- Source/Core/DolphinNoGUI/MainNoGUI.cpp | 13 ++----------- Source/Core/DolphinQt/Host.cpp | 2 +- Source/Core/VideoBackends/D3D/Render.cpp | 3 --- Source/Core/VideoBackends/OGL/Render.cpp | 4 ++-- Source/Core/VideoBackends/Vulkan/Renderer.cpp | 3 --- Source/Core/VideoCommon/RenderBase.cpp | 4 +--- Source/Core/VideoCommon/RenderBase.h | 4 +--- 7 files changed, 7 insertions(+), 26 deletions(-) diff --git a/Source/Core/DolphinNoGUI/MainNoGUI.cpp b/Source/Core/DolphinNoGUI/MainNoGUI.cpp index 60c037e005..6447f6948b 100644 --- a/Source/Core/DolphinNoGUI/MainNoGUI.cpp +++ b/Source/Core/DolphinNoGUI/MainNoGUI.cpp @@ -209,9 +209,6 @@ class PlatformX11 : public Platform void MainLoop() override { bool fullscreen = SConfig::GetInstance().bFullscreen; - int last_window_width = SConfig::GetInstance().iRenderWindowWidth; - int last_window_height = SConfig::GetInstance().iRenderWindowHeight; - if (fullscreen) { rendererIsFullscreen = X11Utils::ToggleFullscreen(dpy, win); @@ -311,14 +308,8 @@ class PlatformX11 : public Platform break; case ConfigureNotify: { - if (last_window_width != event.xconfigure.width || - last_window_height != event.xconfigure.height) - { - last_window_width = event.xconfigure.width; - last_window_height = event.xconfigure.height; - if (g_renderer) - g_renderer->ResizeSurface(last_window_width, last_window_height); - } + if (g_renderer) + g_renderer->ResizeSurface(); } break; } diff --git a/Source/Core/DolphinQt/Host.cpp b/Source/Core/DolphinQt/Host.cpp index 0470c008b5..daaaee14b0 100644 --- a/Source/Core/DolphinQt/Host.cpp +++ b/Source/Core/DolphinQt/Host.cpp @@ -68,7 +68,7 @@ void Host::SetRenderFullscreen(bool fullscreen) void Host::ResizeSurface(int new_width, int new_height) { if (g_renderer) - g_renderer->ResizeSurface(new_width, new_height); + g_renderer->ResizeSurface(); } void Host_Message(HostMessageID id) diff --git a/Source/Core/VideoBackends/D3D/Render.cpp b/Source/Core/VideoBackends/D3D/Render.cpp index fc413673da..bfaa5763ba 100644 --- a/Source/Core/VideoBackends/D3D/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Render.cpp @@ -719,9 +719,6 @@ void Renderer::CheckForSurfaceResize() if (!m_surface_resized.TestAndClear() && !exclusive_fullscreen_changed) return; - m_backbuffer_width = m_new_backbuffer_width; - m_backbuffer_height = m_new_backbuffer_height; - SAFE_RELEASE(m_screenshot_texture); SAFE_RELEASE(m_3d_vision_texture); m_last_fullscreen_state = fullscreen_state; diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index 5ee01701f2..be08541f97 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -1518,8 +1518,8 @@ void Renderer::CheckForSurfaceResize() return; g_main_gl_context->Update(); - m_backbuffer_width = m_new_backbuffer_width; - m_backbuffer_height = m_new_backbuffer_height; + m_backbuffer_width = g_main_gl_context->GetBackBufferWidth(); + m_backbuffer_height = g_main_gl_context->GetBackBufferHeight(); } void Renderer::DrawEFB(GLuint framebuffer, const TargetRectangle& target_rc, diff --git a/Source/Core/VideoBackends/Vulkan/Renderer.cpp b/Source/Core/VideoBackends/Vulkan/Renderer.cpp index 371b9033a8..ce52b0718d 100644 --- a/Source/Core/VideoBackends/Vulkan/Renderer.cpp +++ b/Source/Core/VideoBackends/Vulkan/Renderer.cpp @@ -889,9 +889,6 @@ void Renderer::CheckForSurfaceResize() if (!m_surface_resized.TestAndClear()) return; - m_backbuffer_width = m_new_backbuffer_width; - m_backbuffer_height = m_new_backbuffer_height; - // If we don't have a surface, how can we resize the swap chain? // CheckForSurfaceChange should handle this case. if (!m_swap_chain) diff --git a/Source/Core/VideoCommon/RenderBase.cpp b/Source/Core/VideoCommon/RenderBase.cpp index 3c7eec10f1..5aa6989615 100644 --- a/Source/Core/VideoCommon/RenderBase.cpp +++ b/Source/Core/VideoCommon/RenderBase.cpp @@ -417,11 +417,9 @@ void Renderer::ChangeSurface(void* new_surface_handle) m_surface_changed.Set(); } -void Renderer::ResizeSurface(int new_width, int new_height) +void Renderer::ResizeSurface() { std::lock_guard lock(m_swap_mutex); - m_new_backbuffer_width = new_width; - m_new_backbuffer_height = new_height; m_surface_resized.Set(); } diff --git a/Source/Core/VideoCommon/RenderBase.h b/Source/Core/VideoCommon/RenderBase.h index 07f7ea7bae..d5dd761c40 100644 --- a/Source/Core/VideoCommon/RenderBase.h +++ b/Source/Core/VideoCommon/RenderBase.h @@ -183,7 +183,7 @@ public: // Final surface changing // This is called when the surface is resized (WX) or the window changes (Android). void ChangeSurface(void* new_surface_handle); - void ResizeSurface(int new_width, int new_height); + void ResizeSurface(); bool UseVertexDepthRange() const; virtual std::unique_ptr CreateAsyncShaderCompiler(); @@ -229,8 +229,6 @@ protected: // Backbuffer (window) size and render area int m_backbuffer_width = 0; int m_backbuffer_height = 0; - int m_new_backbuffer_width = 0; - int m_new_backbuffer_height = 0; TargetRectangle m_target_rectangle = {}; FPSCounter m_fps_counter; From 9c57a98723997736adea94383668fbdf8a993fd8 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Wed, 3 Oct 2018 23:03:19 +1000 Subject: [PATCH 05/12] GLContext: Use host connection This also removes the need for a sleeping event thread. --- Source/Core/Common/GL/GLContext.cpp | 13 ++--- Source/Core/Common/GL/GLContext.h | 7 ++- Source/Core/Common/GL/GLInterface/AGL.h | 2 +- Source/Core/Common/GL/GLInterface/AGL.mm | 2 +- Source/Core/Common/GL/GLInterface/EGL.cpp | 6 ++- Source/Core/Common/GL/GLInterface/EGL.h | 3 +- Source/Core/Common/GL/GLInterface/EGLX11.cpp | 31 ++++++------ Source/Core/Common/GL/GLInterface/EGLX11.h | 5 +- Source/Core/Common/GL/GLInterface/GLX.cpp | 22 ++++----- Source/Core/Common/GL/GLInterface/GLX.h | 4 +- Source/Core/Common/GL/GLInterface/WGL.cpp | 2 +- Source/Core/Common/GL/GLInterface/WGL.h | 2 +- Source/Core/Common/GL/GLX11Window.cpp | 48 +++++-------------- Source/Core/Common/GL/GLX11Window.h | 6 +-- Source/Core/VideoBackends/OGL/main.cpp | 4 +- .../VideoBackends/Software/SWOGLWindow.cpp | 4 +- .../Core/VideoBackends/Software/SWOGLWindow.h | 2 +- Source/Core/VideoBackends/Software/SWmain.cpp | 2 +- 18 files changed, 68 insertions(+), 97 deletions(-) diff --git a/Source/Core/Common/GL/GLContext.cpp b/Source/Core/Common/GL/GLContext.cpp index da22f45c3b..0b7f0238c1 100644 --- a/Source/Core/Common/GL/GLContext.cpp +++ b/Source/Core/Common/GL/GLContext.cpp @@ -27,7 +27,7 @@ std::unique_ptr g_main_gl_context; GLContext::~GLContext() = default; -bool GLContext::Initialize(void* window_handle, bool stereo, bool core) +bool GLContext::Initialize(void* display_handle, void* window_handle, bool stereo, bool core) { return false; } @@ -37,12 +37,6 @@ bool GLContext::Initialize(GLContext* main_context) return false; } -void GLContext::SetBackBufferDimensions(u32 w, u32 h) -{ - m_backbuffer_width = w; - m_backbuffer_height = h; -} - bool GLContext::IsHeadless() const { return true; @@ -88,7 +82,8 @@ void* GLContext::GetFuncAddress(const std::string& name) return nullptr; } -std::unique_ptr GLContext::Create(void* window_handle, bool stereo, bool core) +std::unique_ptr GLContext::Create(void* display_handle, void* window_handle, bool stereo, + bool core) { std::unique_ptr context; #if defined(__APPLE__) @@ -108,7 +103,7 @@ std::unique_ptr GLContext::Create(void* window_handle, bool stereo, b #else return nullptr; #endif - if (!context->Initialize(window_handle, stereo, core)) + if (!context->Initialize(display_handle, window_handle, stereo, core)) return nullptr; return context; diff --git a/Source/Core/Common/GL/GLContext.h b/Source/Core/Common/GL/GLContext.h index 990883ca90..46df03dba8 100644 --- a/Source/Core/Common/GL/GLContext.h +++ b/Source/Core/Common/GL/GLContext.h @@ -26,7 +26,6 @@ public: u32 GetBackBufferWidth() { return m_backbuffer_width; } u32 GetBackBufferHeight() { return m_backbuffer_height; } - void SetBackBufferDimensions(u32 w, u32 h); virtual bool IsHeadless() const; @@ -45,11 +44,11 @@ public: virtual void* GetFuncAddress(const std::string& name); // Creates an instance of GLInterface specific to the platform we are running on. - static std::unique_ptr Create(void* window_handle, bool stereo = false, - bool core = true); + static std::unique_ptr Create(void* display_handle, void* window_handle, + bool stereo = false, bool core = true); protected: - virtual bool Initialize(void* window_handle, bool stereo, bool core); + virtual bool Initialize(void* display_handle, void* window_handle, bool stereo, bool core); virtual bool Initialize(GLContext* main_context); Mode m_opengl_mode = Mode::Detect; diff --git a/Source/Core/Common/GL/GLInterface/AGL.h b/Source/Core/Common/GL/GLInterface/AGL.h index 3032fe573d..00978535f8 100644 --- a/Source/Core/Common/GL/GLInterface/AGL.h +++ b/Source/Core/Common/GL/GLInterface/AGL.h @@ -31,7 +31,7 @@ public: void SwapInterval(int interval) override; protected: - bool Initialize(void* window_handle, bool stereo, bool core) override; + bool Initialize(void* display_handle, void* window_handle, bool stereo, bool core) override; bool Initialize(GLContext* main_context) override; NSView* m_view = nullptr; diff --git a/Source/Core/Common/GL/GLInterface/AGL.mm b/Source/Core/Common/GL/GLInterface/AGL.mm index 80b82f917e..4998fab40e 100644 --- a/Source/Core/Common/GL/GLInterface/AGL.mm +++ b/Source/Core/Common/GL/GLInterface/AGL.mm @@ -55,7 +55,7 @@ void GLContextAGL::Swap() // Create rendering window. // Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize() -bool GLContextAGL::Initialize(void* window_handle, bool stereo, bool core) +bool GLContextAGL::Initialize(void* display_handle, void* window_handle, bool stereo, bool core) { NSOpenGLPixelFormatAttribute attr[] = { NSOpenGLPFADoubleBuffer, diff --git a/Source/Core/Common/GL/GLInterface/EGL.cpp b/Source/Core/Common/GL/GLInterface/EGL.cpp index 46073fe074..eebe5e2e0e 100644 --- a/Source/Core/Common/GL/GLInterface/EGL.cpp +++ b/Source/Core/Common/GL/GLInterface/EGL.cpp @@ -152,15 +152,16 @@ EGLNativeWindowType GLContextEGL::GetEGLNativeWindow(EGLConfig config) // Create rendering window. // Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize() -bool GLContextEGL::Initialize(void* window_handle, bool stereo, bool core) +bool GLContextEGL::Initialize(void* display_handle, void* window_handle, bool stereo, bool core) { const bool has_handle = !!window_handle; EGLint egl_major, egl_minor; bool supports_core_profile = false; - m_egl_display = OpenEGLDisplay(); + m_host_display = display_handle; m_host_window = window_handle; + m_egl_display = OpenEGLDisplay(); m_is_core_context = core; if (!m_egl_display) @@ -299,6 +300,7 @@ bool GLContextEGL::Initialize(GLContext* main_context) GLContextEGL* egl_context = static_cast(main_context); m_opengl_mode = egl_context->m_opengl_mode; + m_host_display = egl_context->m_host_display; m_egl_display = egl_context->m_egl_display; m_is_core_context = egl_context->m_is_core_context; m_config = egl_context->m_config; diff --git a/Source/Core/Common/GL/GLInterface/EGL.h b/Source/Core/Common/GL/GLInterface/EGL.h index 49abd63cc1..52c183e21c 100644 --- a/Source/Core/Common/GL/GLInterface/EGL.h +++ b/Source/Core/Common/GL/GLInterface/EGL.h @@ -35,13 +35,14 @@ protected: virtual EGLDisplay OpenEGLDisplay(); virtual EGLNativeWindowType GetEGLNativeWindow(EGLConfig config); - bool Initialize(void* window_handle, bool stereo, bool core) override; + bool Initialize(void* display_handle, void* window_handle, bool stereo, bool core) override; bool Initialize(GLContext* main_context) override; bool CreateWindowSurface(); void DestroyWindowSurface(); void DetectMode(bool has_handle); + void* m_host_display = nullptr; void* m_host_window = nullptr; EGLConfig m_config; diff --git a/Source/Core/Common/GL/GLInterface/EGLX11.cpp b/Source/Core/Common/GL/GLInterface/EGLX11.cpp index 58bf3133a8..bc87769440 100644 --- a/Source/Core/Common/GL/GLInterface/EGLX11.cpp +++ b/Source/Core/Common/GL/GLInterface/EGLX11.cpp @@ -3,20 +3,19 @@ // Refer to the license.txt file included. #include "Common/GL/GLInterface/EGLX11.h" -#include "Common/Logging/Log.h" -GLContextEGLX11::~GLContextEGLX11() +GLContextEGLX11::~GLContextEGLX11() = default; + +void GLContextEGLX11::Update() { - if (m_display) - XCloseDisplay(m_display); + m_render_window->UpdateDimensions(); + m_backbuffer_width = m_render_window->GetWidth(); + m_backbuffer_height = m_render_window->GetHeight(); } EGLDisplay GLContextEGLX11::OpenEGLDisplay() { - if (!m_display) - m_display = XOpenDisplay(nullptr); - - return eglGetDisplay(m_display); + return eglGetDisplay(static_cast(m_host_display)); } EGLNativeWindowType GLContextEGLX11::GetEGLNativeWindow(EGLConfig config) @@ -28,16 +27,18 @@ EGLNativeWindowType GLContextEGLX11::GetEGLNativeWindow(EGLConfig config) visTemplate.visualid = vid; int nVisuals; - XVisualInfo* vi = XGetVisualInfo(m_display, VisualIDMask, &visTemplate, &nVisuals); + XVisualInfo* vi = + XGetVisualInfo(static_cast(m_host_display), VisualIDMask, &visTemplate, &nVisuals); - if (m_x_window) - m_x_window.reset(); + if (m_render_window) + m_render_window.reset(); - m_x_window = GLX11Window::Create(m_display, reinterpret_cast(m_host_window), vi); - m_backbuffer_width = m_x_window->GetWidth(); - m_backbuffer_height = m_x_window->GetHeight(); + m_render_window = GLX11Window::Create(static_cast(m_host_display), + reinterpret_cast(m_host_window), vi); + m_backbuffer_width = m_render_window->GetWidth(); + m_backbuffer_height = m_render_window->GetHeight(); XFree(vi); - return reinterpret_cast(m_x_window->GetWindow()); + return reinterpret_cast(m_render_window->GetWindow()); } diff --git a/Source/Core/Common/GL/GLInterface/EGLX11.h b/Source/Core/Common/GL/GLInterface/EGLX11.h index ec0e933ef7..6254d7ca0a 100644 --- a/Source/Core/Common/GL/GLInterface/EGLX11.h +++ b/Source/Core/Common/GL/GLInterface/EGLX11.h @@ -14,10 +14,11 @@ class GLContextEGLX11 : public GLContextEGL public: ~GLContextEGLX11() override; + void Update() override; + protected: EGLDisplay OpenEGLDisplay() override; EGLNativeWindowType GetEGLNativeWindow(EGLConfig config) override; - Display* m_display = nullptr; - std::unique_ptr m_x_window; + std::unique_ptr m_render_window; }; diff --git a/Source/Core/Common/GL/GLInterface/GLX.cpp b/Source/Core/Common/GL/GLInterface/GLX.cpp index 173127fc5b..c2569bd153 100644 --- a/Source/Core/Common/GL/GLInterface/GLX.cpp +++ b/Source/Core/Common/GL/GLInterface/GLX.cpp @@ -56,9 +56,9 @@ void GLContextGLX::Swap() // Create rendering window. // Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize() -bool GLContextGLX::Initialize(void* window_handle, bool stereo, bool core) +bool GLContextGLX::Initialize(void* display_handle, void* window_handle, bool stereo, bool core) { - m_display = XOpenDisplay(nullptr); + m_display = static_cast(display_handle); int screen = DefaultScreen(m_display); // checking glx version @@ -298,16 +298,12 @@ void GLContextGLX::Shutdown() { DestroyWindowSurface(); if (m_context) - { glXDestroyContext(m_display, m_context); - - // Don't close the display connection if we are a shared context. - // Saves doing reference counting on this object, and the main context will always - // be shut down last anyway. - if (m_render_window) - { - XCloseDisplay(m_display); - m_context = nullptr; - } - } +} + +void GLContextGLX::Update() +{ + m_render_window->UpdateDimensions(); + m_backbuffer_width = m_render_window->GetWidth(); + m_backbuffer_height = m_render_window->GetHeight(); } diff --git a/Source/Core/Common/GL/GLInterface/GLX.h b/Source/Core/Common/GL/GLInterface/GLX.h index 42e36f863f..ef90e0ba5e 100644 --- a/Source/Core/Common/GL/GLInterface/GLX.h +++ b/Source/Core/Common/GL/GLInterface/GLX.h @@ -24,13 +24,15 @@ public: bool MakeCurrent() override; bool ClearCurrent() override; + void Update() override; + void SwapInterval(int Interval) override; void Swap() override; void* GetFuncAddress(const std::string& name) override; protected: - bool Initialize(void* window_handle, bool stereo, bool core) override; + bool Initialize(void* display_handle, void* window_handle, bool stereo, bool core) override; bool Initialize(GLContext* main_context) override; Display* m_display = nullptr; diff --git a/Source/Core/Common/GL/GLInterface/WGL.cpp b/Source/Core/Common/GL/GLInterface/WGL.cpp index d7c8c87c4f..6d1f072aee 100644 --- a/Source/Core/Common/GL/GLInterface/WGL.cpp +++ b/Source/Core/Common/GL/GLInterface/WGL.cpp @@ -190,7 +190,7 @@ void* GLContextWGL::GetFuncAddress(const std::string& name) // Create rendering window. // Call browser: Core.cpp:EmuThread() > main.cpp:Video_Initialize() -bool GLContextWGL::Initialize(void* window_handle, bool stereo, bool core) +bool GLContextWGL::Initialize(void* display_handle, void* window_handle, bool stereo, bool core) { if (!window_handle) return false; diff --git a/Source/Core/Common/GL/GLInterface/WGL.h b/Source/Core/Common/GL/GLInterface/WGL.h index 7e74470866..e253a1accd 100644 --- a/Source/Core/Common/GL/GLInterface/WGL.h +++ b/Source/Core/Common/GL/GLInterface/WGL.h @@ -27,7 +27,7 @@ public: void* GetFuncAddress(const std::string& name) override; protected: - bool Initialize(void* window_handle, bool stereo, bool core) override; + bool Initialize(void* display_handle, void* window_handle, bool stereo, bool core) override; bool Initialize(GLContext* main_context) override; static HGLRC CreateCoreContext(HDC dc, HGLRC share_context); diff --git a/Source/Core/Common/GL/GLX11Window.cpp b/Source/Core/Common/GL/GLX11Window.cpp index 793939377d..681adaa099 100644 --- a/Source/Core/Common/GL/GLX11Window.cpp +++ b/Source/Core/Common/GL/GLX11Window.cpp @@ -4,27 +4,30 @@ #include "Common/GL/GLX11Window.h" #include "Common/GL/GLContext.h" -#include "Common/Thread.h" GLX11Window::GLX11Window(Display* display, Window parent_window, Colormap color_map, Window window, int width, int height) : m_display(display), m_parent_window(parent_window), m_color_map(color_map), m_window(window), - m_width(width), m_height(height), - m_event_thread(std::thread(&GLX11Window::XEventThread, this)) + m_width(width), m_height(height) { } GLX11Window::~GLX11Window() { - Window window = m_window; - m_window = None; - if (m_event_thread.joinable()) - m_event_thread.join(); - XUnmapWindow(m_display, window); - XDestroyWindow(m_display, window); + XUnmapWindow(m_display, m_window); + XDestroyWindow(m_display, m_window); XFreeColormap(m_display, m_color_map); } +void GLX11Window::UpdateDimensions() +{ + XWindowAttributes attribs; + XGetWindowAttributes(m_display, m_parent_window, &attribs); + XResizeWindow(m_display, m_window, attribs.width, attribs.height); + m_width = attribs.width; + m_height = attribs.height; +} + std::unique_ptr GLX11Window::Create(Display* display, Window parent_window, XVisualInfo* vi) { @@ -48,30 +51,3 @@ std::unique_ptr GLX11Window::Create(Display* display, Window parent return std::make_unique(display, parent_window, color_map, window, parent_attribs.width, parent_attribs.height); } - -void GLX11Window::XEventThread() -{ - // There's a potential race here on m_window. But this thread will disappear soon. - while (m_window) - { - XEvent event; - for (int num_events = XPending(m_display); num_events > 0; num_events--) - { - XNextEvent(m_display, &event); - switch (event.type) - { - case ConfigureNotify: - { - m_width = event.xconfigure.width; - m_height = event.xconfigure.height; - XResizeWindow(m_display, m_window, m_width, m_height); - g_main_gl_context->SetBackBufferDimensions(m_width, m_height); - } - break; - default: - break; - } - } - Common::SleepCurrentThread(20); - } -} diff --git a/Source/Core/Common/GL/GLX11Window.h b/Source/Core/Common/GL/GLX11Window.h index 15c183c7cf..fd3020d1d8 100644 --- a/Source/Core/Common/GL/GLX11Window.h +++ b/Source/Core/Common/GL/GLX11Window.h @@ -23,12 +23,12 @@ public: int GetWidth() const { return m_width; } int GetHeight() const { return m_height; } + void UpdateDimensions(); + static std::unique_ptr Create(Display* display, Window parent_window, XVisualInfo* vi); private: - void XEventThread(); - Display* m_display; Window m_parent_window; Colormap m_color_map; @@ -36,6 +36,4 @@ private: int m_width; int m_height; - - std::thread m_event_thread; }; diff --git a/Source/Core/VideoBackends/OGL/main.cpp b/Source/Core/VideoBackends/OGL/main.cpp index 27a0192b2c..edfb861eea 100644 --- a/Source/Core/VideoBackends/OGL/main.cpp +++ b/Source/Core/VideoBackends/OGL/main.cpp @@ -161,8 +161,8 @@ bool VideoBackend::Initialize(void* display_handle, void* window_handle) { InitializeShared(); - g_main_gl_context = - GLContext::Create(window_handle, g_ActiveConfig.stereo_mode == StereoMode::QuadBuffer); + g_main_gl_context = GLContext::Create(display_handle, window_handle, + g_ActiveConfig.stereo_mode == StereoMode::QuadBuffer); if (!g_main_gl_context) return false; diff --git a/Source/Core/VideoBackends/Software/SWOGLWindow.cpp b/Source/Core/VideoBackends/Software/SWOGLWindow.cpp index dd390bc6dc..fb6731b4b7 100644 --- a/Source/Core/VideoBackends/Software/SWOGLWindow.cpp +++ b/Source/Core/VideoBackends/Software/SWOGLWindow.cpp @@ -13,9 +13,9 @@ std::unique_ptr SWOGLWindow::s_instance; -void SWOGLWindow::Init(void* window_handle) +void SWOGLWindow::Init(void* display_handle, void* window_handle) { - g_main_gl_context = GLContext::Create(window_handle); + g_main_gl_context = GLContext::Create(display_handle, window_handle); if (!g_main_gl_context) { ERROR_LOG(VIDEO, "GLInterface::Create failed."); diff --git a/Source/Core/VideoBackends/Software/SWOGLWindow.h b/Source/Core/VideoBackends/Software/SWOGLWindow.h index eadf3171cb..a393194ed7 100644 --- a/Source/Core/VideoBackends/Software/SWOGLWindow.h +++ b/Source/Core/VideoBackends/Software/SWOGLWindow.h @@ -16,7 +16,7 @@ class AbstractTexture; class SWOGLWindow { public: - static void Init(void* window_handle); + static void Init(void* display_handle, void* window_handle); static void Shutdown(); void Prepare(); diff --git a/Source/Core/VideoBackends/Software/SWmain.cpp b/Source/Core/VideoBackends/Software/SWmain.cpp index f4c0aaa641..2aa099e9e9 100644 --- a/Source/Core/VideoBackends/Software/SWmain.cpp +++ b/Source/Core/VideoBackends/Software/SWmain.cpp @@ -82,7 +82,7 @@ bool VideoSoftware::Initialize(void* display_handle, void* window_handle) { InitializeShared(); - SWOGLWindow::Init(window_handle); + SWOGLWindow::Init(display_handle, window_handle); Clipper::Init(); Rasterizer::Init(); From eb284b5d661cab6aed770e0e51b790917249ef21 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Wed, 3 Oct 2018 23:03:22 +1000 Subject: [PATCH 06/12] VideoBackends: Pass window system info from host on creation --- Source/Android/jni/MainAndroid.cpp | 4 +- Source/Core/Common/GL/GLContext.cpp | 5 +- Source/Core/Common/GL/GLContext.h | 5 +- Source/Core/Common/WindowSystemInfo.h | 35 +++++++++++++ Source/Core/Core/Boot/Boot.h | 8 --- Source/Core/Core/BootManager.cpp | 14 ++--- Source/Core/Core/BootManager.h | 5 +- Source/Core/Core/Core.cpp | 12 ++--- Source/Core/Core/Core.h | 5 +- Source/Core/DolphinNoGUI/MainNoGUI.cpp | 17 +++--- Source/Core/DolphinQt/MainWindow.cpp | 52 +++++++++++++++---- Source/Core/DolphinQt/RenderWidget.cpp | 3 ++ Source/Core/VideoBackends/D3D/D3DBase.cpp | 11 ++-- Source/Core/VideoBackends/D3D/VideoBackend.h | 2 +- Source/Core/VideoBackends/D3D/main.cpp | 7 +-- .../Core/VideoBackends/Null/NullBackend.cpp | 2 +- Source/Core/VideoBackends/Null/VideoBackend.h | 2 +- Source/Core/VideoBackends/OGL/VideoBackend.h | 2 +- Source/Core/VideoBackends/OGL/main.cpp | 5 +- .../VideoBackends/Software/SWOGLWindow.cpp | 4 +- .../Core/VideoBackends/Software/SWOGLWindow.h | 3 +- Source/Core/VideoBackends/Software/SWmain.cpp | 4 +- .../VideoBackends/Software/VideoBackend.h | 2 +- .../Core/VideoBackends/Vulkan/VideoBackend.h | 2 +- Source/Core/VideoBackends/Vulkan/main.cpp | 9 ++-- Source/Core/VideoCommon/VideoBackendBase.h | 3 +- 26 files changed, 148 insertions(+), 75 deletions(-) create mode 100644 Source/Core/Common/WindowSystemInfo.h diff --git a/Source/Android/jni/MainAndroid.cpp b/Source/Android/jni/MainAndroid.cpp index 83fefce338..5d3c03e767 100644 --- a/Source/Android/jni/MainAndroid.cpp +++ b/Source/Android/jni/MainAndroid.cpp @@ -25,6 +25,7 @@ #include "Common/Logging/LogManager.h" #include "Common/MsgHandler.h" #include "Common/Version.h" +#include "Common/WindowSystemInfo.h" #include "Core/Analytics.h" #include "Core/Boot/Boot.h" @@ -560,7 +561,8 @@ static void Run(const std::string& path, bool first_open, s_have_wm_user_stop = false; std::unique_ptr boot = BootParameters::GenerateFromFile(path, savestate_path); boot->delete_savestate = delete_savestate; - if (BootManager::BootCore(std::move(boot))) + WindowSystemInfo wsi(WindowSystemType::Android, nullptr, s_surf); + if (BootManager::BootCore(std::move(boot), wsi)) { static constexpr int TIMEOUT = 10000; static constexpr int WAIT_STEP = 25; diff --git a/Source/Core/Common/GL/GLContext.cpp b/Source/Core/Common/GL/GLContext.cpp index 0b7f0238c1..da3e47aa26 100644 --- a/Source/Core/Common/GL/GLContext.cpp +++ b/Source/Core/Common/GL/GLContext.cpp @@ -82,8 +82,7 @@ void* GLContext::GetFuncAddress(const std::string& name) return nullptr; } -std::unique_ptr GLContext::Create(void* display_handle, void* window_handle, bool stereo, - bool core) +std::unique_ptr GLContext::Create(const WindowSystemInfo& wsi, bool stereo, bool core) { std::unique_ptr context; #if defined(__APPLE__) @@ -103,7 +102,7 @@ std::unique_ptr GLContext::Create(void* display_handle, void* window_ #else return nullptr; #endif - if (!context->Initialize(display_handle, window_handle, stereo, core)) + if (!context->Initialize(wsi.display_connection, wsi.render_surface, stereo, core)) return nullptr; return context; diff --git a/Source/Core/Common/GL/GLContext.h b/Source/Core/Common/GL/GLContext.h index 46df03dba8..c9e1d8c457 100644 --- a/Source/Core/Common/GL/GLContext.h +++ b/Source/Core/Common/GL/GLContext.h @@ -8,6 +8,7 @@ #include #include "Common/CommonTypes.h" +#include "Common/WindowSystemInfo.h" class GLContext { @@ -44,8 +45,8 @@ public: virtual void* GetFuncAddress(const std::string& name); // Creates an instance of GLInterface specific to the platform we are running on. - static std::unique_ptr Create(void* display_handle, void* window_handle, - bool stereo = false, bool core = true); + static std::unique_ptr Create(const WindowSystemInfo& wsi, bool stereo = false, + bool core = true); protected: virtual bool Initialize(void* display_handle, void* window_handle, bool stereo, bool core); diff --git a/Source/Core/Common/WindowSystemInfo.h b/Source/Core/Common/WindowSystemInfo.h new file mode 100644 index 0000000000..897d034c2c --- /dev/null +++ b/Source/Core/Common/WindowSystemInfo.h @@ -0,0 +1,35 @@ +// Copyright 2018 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +enum class WindowSystemType +{ + Headless, + Windows, + MacOS, + Android, + X11, + Wayland +}; + +struct WindowSystemInfo +{ + WindowSystemInfo() = default; + WindowSystemInfo(WindowSystemType type_, void* display_connection_, void* render_surface_) + : type(type_), display_connection(display_connection_), render_surface(render_surface_) + { + } + + // Window system type. Determines which GL context or Vulkan WSI is used. + WindowSystemType type = WindowSystemType::Headless; + + // Connection to a display server. This is used on X11 and Wayland platforms. + void* display_connection = nullptr; + + // Render surface. This is a pointer to the native window handle, which depends + // on the platform. e.g. HWND for Windows, Window for X11. If the surface is + // set to nullptr, the video backend will run in headless mode. + void* render_surface = nullptr; +}; diff --git a/Source/Core/Core/Boot/Boot.h b/Source/Core/Core/Boot/Boot.h index f229c7d560..589b9b2056 100644 --- a/Source/Core/Core/Boot/Boot.h +++ b/Source/Core/Core/Boot/Boot.h @@ -78,14 +78,6 @@ struct BootParameters Parameters parameters; std::optional savestate_path; bool delete_savestate = false; - - // Connection to a display server. This is used on X11 and Wayland platforms. - void* display_connection = nullptr; - - // Render surface. This is a pointer to the native window handle, which depends - // on the platform. e.g. HWND for Windows, Window for X11. If the surface is - // set to nullptr, the video backend will run in headless mode. - void* render_surface = nullptr; }; class CBoot diff --git a/Source/Core/Core/BootManager.cpp b/Source/Core/Core/BootManager.cpp index 7f7130ce66..9e5f205113 100644 --- a/Source/Core/Core/BootManager.cpp +++ b/Source/Core/Core/BootManager.cpp @@ -222,7 +222,7 @@ static GPUDeterminismMode ParseGPUDeterminismMode(const std::string& mode) } // Boot the ISO or file -bool BootCore(std::unique_ptr boot) +bool BootCore(std::unique_ptr boot, const WindowSystemInfo& wsi) { if (!boot) return false; @@ -403,12 +403,14 @@ bool BootCore(std::unique_ptr boot) std::holds_alternative(boot->parameters); if (load_ipl) { - return Core::Init(std::make_unique( - BootParameters::IPL{StartUp.m_region, - std::move(std::get(boot->parameters))}, - boot->savestate_path)); + return Core::Init( + std::make_unique( + BootParameters::IPL{StartUp.m_region, + std::move(std::get(boot->parameters))}, + boot->savestate_path), + wsi); } - return Core::Init(std::move(boot)); + return Core::Init(std::move(boot), wsi); } // SYSCONF can be modified during emulation by the user and internally, which makes it diff --git a/Source/Core/Core/BootManager.h b/Source/Core/Core/BootManager.h index 7f236c6ea0..d9c66c370c 100644 --- a/Source/Core/Core/BootManager.h +++ b/Source/Core/Core/BootManager.h @@ -7,12 +7,13 @@ #include struct BootParameters; +struct WindowSystemInfo; namespace BootManager { -bool BootCore(std::unique_ptr parameters); +bool BootCore(std::unique_ptr parameters, const WindowSystemInfo& wsi); // Synchronise Dolphin's configuration with the SYSCONF (which may have changed during emulation), // and restore settings that were overriden by per-game INIs or for some other reason. void RestoreConfig(); -} +} // namespace BootManager diff --git a/Source/Core/Core/Core.cpp b/Source/Core/Core/Core.cpp index 8831db5908..93d4cd4491 100644 --- a/Source/Core/Core/Core.cpp +++ b/Source/Core/Core/Core.cpp @@ -107,7 +107,7 @@ static std::queue s_host_jobs_queue; static thread_local bool tls_is_cpu_thread = false; -static void EmuThread(std::unique_ptr boot); +static void EmuThread(std::unique_ptr boot, WindowSystemInfo wsi); bool GetIsThrottlerTempDisabled() { @@ -190,7 +190,7 @@ bool WantsDeterminism() // This is called from the GUI thread. See the booting call schedule in // BootManager.cpp -bool Init(std::unique_ptr boot) +bool Init(std::unique_ptr boot, const WindowSystemInfo& wsi) { if (s_emu_thread.joinable()) { @@ -215,7 +215,7 @@ bool Init(std::unique_ptr boot) Host_UpdateMainFrame(); // Disable any menus or buttons at boot // Start the emu thread - s_emu_thread = std::thread(EmuThread, std::move(boot)); + s_emu_thread = std::thread(EmuThread, std::move(boot), wsi); return true; } @@ -386,7 +386,7 @@ static void FifoPlayerThread(const std::optional& savestate_path, // Initialize and create emulation thread // Call browser: Init():s_emu_thread(). // See the BootManager.cpp file description for a complete call schedule. -static void EmuThread(std::unique_ptr boot) +static void EmuThread(std::unique_ptr boot, WindowSystemInfo wsi) { const SConfig& core_parameter = SConfig::GetInstance(); s_is_booting.Set(); @@ -438,7 +438,7 @@ static void EmuThread(std::unique_ptr boot) g_video_backend->InitBackendInfo(); g_Config.Refresh(); - if (!g_video_backend->Initialize(boot->display_connection, boot->render_surface)) + if (!g_video_backend->Initialize(wsi)) { PanicAlert("Failed to initialize video backend!"); return; @@ -459,7 +459,7 @@ static void EmuThread(std::unique_ptr boot) bool init_controllers = false; if (!g_controller_interface.IsInit()) { - g_controller_interface.Initialize(boot->render_surface); + g_controller_interface.Initialize(wsi.display_connection); Pad::Initialize(); Keyboard::Initialize(); init_controllers = true; diff --git a/Source/Core/Core/Core.h b/Source/Core/Core/Core.h index 708d2d234f..056e5ed3a1 100644 --- a/Source/Core/Core/Core.h +++ b/Source/Core/Core/Core.h @@ -18,6 +18,7 @@ #include "Common/CommonTypes.h" struct BootParameters; +struct WindowSystemInfo; namespace Core { @@ -35,7 +36,7 @@ enum class State Starting, }; -bool Init(std::unique_ptr boot); +bool Init(std::unique_ptr boot, const WindowSystemInfo& wsi); void Stop(); void Shutdown(); @@ -104,4 +105,4 @@ void HostDispatchJobs(); void DoFrameStep(); -} // namespace +} // namespace Core diff --git a/Source/Core/DolphinNoGUI/MainNoGUI.cpp b/Source/Core/DolphinNoGUI/MainNoGUI.cpp index 6447f6948b..6cd71bd353 100644 --- a/Source/Core/DolphinNoGUI/MainNoGUI.cpp +++ b/Source/Core/DolphinNoGUI/MainNoGUI.cpp @@ -72,8 +72,9 @@ public: virtual void Shutdown() {} virtual ~Platform() {} - virtual void* GetDisplayHandle() { return nullptr; } - virtual void* GetWindowHandle() { return nullptr; } + virtual WindowSystemType GetWindowSystem() const { return WindowSystemType::Headless; } + virtual void* GetDisplayHandle() const { return nullptr; } + virtual void* GetWindowHandle() const { return nullptr; } }; static Platform* platform; @@ -342,9 +343,9 @@ class PlatformX11 : public Platform XCloseDisplay(dpy); } - void* GetDisplayHandle() override { return static_cast(dpy); } - - void* GetWindowHandle() override { return reinterpret_cast(win); } + WindowSystemType GetWindowSystem() const override { return WindowSystemType::X11; } + void* GetDisplayHandle() const override { return static_cast(dpy); } + void* GetWindowHandle() const override { return reinterpret_cast(win); } }; #endif @@ -424,10 +425,10 @@ int main(int argc, char* argv[]) DolphinAnalytics::Instance()->ReportDolphinStart("nogui"); - boot->display_connection = platform->GetDisplayHandle(); - boot->render_surface = platform->GetWindowHandle(); + WindowSystemInfo wsi(platform->GetWindowSystem(), platform->GetDisplayHandle(), + platform->GetWindowHandle()); - if (!BootManager::BootCore(std::move(boot))) + if (!BootManager::BootCore(std::move(boot), wsi)) { fprintf(stderr, "Could not boot the specified file\n"); return 1; diff --git a/Source/Core/DolphinQt/MainWindow.cpp b/Source/Core/DolphinQt/MainWindow.cpp index 0a2ebfe101..b80a0bd2ab 100644 --- a/Source/Core/DolphinQt/MainWindow.cpp +++ b/Source/Core/DolphinQt/MainWindow.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -31,6 +32,7 @@ #endif #include "Common/Version.h" +#include "Common/WindowSystemInfo.h" #include "Core/Boot/Boot.h" #include "Core/BootManager.h" @@ -122,6 +124,45 @@ static void InstallSignalHandler() } #endif +static WindowSystemType GetWindowSystemType() +{ + // Determine WSI type based on Qt platform. + QString platform_name = QGuiApplication::platformName(); + if (platform_name == QStringLiteral("windows")) + return WindowSystemType::Windows; + else if (platform_name == QStringLiteral("cocoa")) + return WindowSystemType::MacOS; + else if (platform_name == QStringLiteral("xcb")) + return WindowSystemType::X11; + else if (platform_name == QStringLiteral("wayland")) + return WindowSystemType::Wayland; + + QMessageBox::critical( + nullptr, QStringLiteral("Error"), + QString::asprintf("Unknown Qt platform: %s", platform_name.toStdString().c_str())); + return WindowSystemType::Headless; +} + +static WindowSystemInfo GetWindowSystemInfo(QWindow* window) +{ + WindowSystemInfo wsi; + wsi.type = GetWindowSystemType(); + + // Our Win32 Qt external doesn't have the private API. +#if defined(WIN32) || defined(__APPLE__) + wsi.render_surface = window ? reinterpret_cast(window->winId()) : nullptr; +#else + QPlatformNativeInterface* pni = QGuiApplication::platformNativeInterface(); + wsi.display_connection = pni->nativeResourceForWindow("display", window); + if (wsi.type == WindowSystemType::Wayland) + wsi.render_surface = window ? pni->nativeResourceForWindow("surface", window) : nullptr; + else + wsi.render_surface = window ? reinterpret_cast(window->winId()) : nullptr; +#endif + + return wsi; +} + MainWindow::MainWindow(std::unique_ptr boot_parameters) : QMainWindow(nullptr) { setWindowTitle(QString::fromStdString(Common::scm_rev_str)); @@ -804,16 +845,9 @@ void MainWindow::StartGame(std::unique_ptr&& parameters) // We need the render widget before booting. ShowRenderWidget(); - // Populate the video backend fields of the boot parameters. - parameters->render_surface = reinterpret_cast(m_render_widget->winId()); -#ifndef WIN32 - parameters->display_connection = - QGuiApplication::platformNativeInterface()->nativeResourceForWindow("display", - windowHandle()); -#endif - // Boot up, show an error if it fails to load the game. - if (!BootManager::BootCore(std::move(parameters))) + if (!BootManager::BootCore(std::move(parameters), + GetWindowSystemInfo(m_render_widget->windowHandle()))) { QMessageBox::critical(this, tr("Error"), tr("Failed to init core"), QMessageBox::Ok); HideRenderWidget(); diff --git a/Source/Core/DolphinQt/RenderWidget.cpp b/Source/Core/DolphinQt/RenderWidget.cpp index 6846de5dd5..1581782e5c 100644 --- a/Source/Core/DolphinQt/RenderWidget.cpp +++ b/Source/Core/DolphinQt/RenderWidget.cpp @@ -68,6 +68,9 @@ RenderWidget::RenderWidget(QWidget* parent) : QWidget(parent) OnKeepOnTopChanged(Settings::Instance().IsKeepWindowOnTopEnabled()); m_mouse_timer->start(MOUSE_HIDE_DELAY); + // We need a native window to render into. + setAttribute(Qt::WA_NativeWindow); + SetFillBackground(true); } diff --git a/Source/Core/VideoBackends/D3D/D3DBase.cpp b/Source/Core/VideoBackends/D3D/D3DBase.cpp index 6c4478c492..333fd969f5 100644 --- a/Source/Core/VideoBackends/D3D/D3DBase.cpp +++ b/Source/Core/VideoBackends/D3D/D3DBase.cpp @@ -429,10 +429,13 @@ HRESULT Create(HWND wnd) // prevent DXGI from responding to Alt+Enter, unfortunately DXGI_MWA_NO_ALT_ENTER // does not work so we disable all monitoring of window messages. However this // may make it more difficult for DXGI to handle display mode changes. - hr = s_dxgi_factory->MakeWindowAssociation(wnd, DXGI_MWA_NO_WINDOW_CHANGES); - if (FAILED(hr)) - MessageBox(wnd, _T("Failed to associate the window"), _T("Dolphin Direct3D 11 backend"), - MB_OK | MB_ICONERROR); + if (wnd) + { + hr = s_dxgi_factory->MakeWindowAssociation(wnd, DXGI_MWA_NO_WINDOW_CHANGES); + if (FAILED(hr)) + MessageBox(wnd, _T("Failed to associate the window"), _T("Dolphin Direct3D 11 backend"), + MB_OK | MB_ICONERROR); + } SetDebugObjectName(context, "device context"); diff --git a/Source/Core/VideoBackends/D3D/VideoBackend.h b/Source/Core/VideoBackends/D3D/VideoBackend.h index 2470401dd3..e288dddb9a 100644 --- a/Source/Core/VideoBackends/D3D/VideoBackend.h +++ b/Source/Core/VideoBackends/D3D/VideoBackend.h @@ -11,7 +11,7 @@ namespace DX11 { class VideoBackend : public VideoBackendBase { - bool Initialize(void* display_handle, void* window_handle) override; + bool Initialize(const WindowSystemInfo& wsi) override; void Shutdown() override; std::string GetName() const override; diff --git a/Source/Core/VideoBackends/D3D/main.cpp b/Source/Core/VideoBackends/D3D/main.cpp index 36c5558435..7df5358b16 100644 --- a/Source/Core/VideoBackends/D3D/main.cpp +++ b/Source/Core/VideoBackends/D3D/main.cpp @@ -127,14 +127,11 @@ void VideoBackend::InitBackendInfo() DX11::D3D::UnloadD3D(); } -bool VideoBackend::Initialize(void* display_handle, void* window_handle) +bool VideoBackend::Initialize(const WindowSystemInfo& wsi) { - if (window_handle == nullptr) - return false; - InitializeShared(); - if (FAILED(D3D::Create(reinterpret_cast(window_handle)))) + if (FAILED(D3D::Create(reinterpret_cast(wsi.render_surface)))) { PanicAlert("Failed to create D3D device."); return false; diff --git a/Source/Core/VideoBackends/Null/NullBackend.cpp b/Source/Core/VideoBackends/Null/NullBackend.cpp index 6d2edb79b5..147d5916ff 100644 --- a/Source/Core/VideoBackends/Null/NullBackend.cpp +++ b/Source/Core/VideoBackends/Null/NullBackend.cpp @@ -54,7 +54,7 @@ void VideoBackend::InitBackendInfo() g_Config.backend_info.AAModes = {1}; } -bool VideoBackend::Initialize(void* display_handle, void* window_handle) +bool VideoBackend::Initialize(const WindowSystemInfo& wsi) { InitializeShared(); diff --git a/Source/Core/VideoBackends/Null/VideoBackend.h b/Source/Core/VideoBackends/Null/VideoBackend.h index 3d0353f073..3076f7aed0 100644 --- a/Source/Core/VideoBackends/Null/VideoBackend.h +++ b/Source/Core/VideoBackends/Null/VideoBackend.h @@ -11,7 +11,7 @@ namespace Null { class VideoBackend : public VideoBackendBase { - bool Initialize(void* display_handle, void* window_handle) override; + bool Initialize(const WindowSystemInfo& wsi) override; void Shutdown() override; std::string GetName() const override { return "Null"; } diff --git a/Source/Core/VideoBackends/OGL/VideoBackend.h b/Source/Core/VideoBackends/OGL/VideoBackend.h index 96864f3ecc..2a1360542f 100644 --- a/Source/Core/VideoBackends/OGL/VideoBackend.h +++ b/Source/Core/VideoBackends/OGL/VideoBackend.h @@ -11,7 +11,7 @@ namespace OGL { class VideoBackend : public VideoBackendBase { - bool Initialize(void* display_handle, void* window_handle) override; + bool Initialize(const WindowSystemInfo& wsi) override; void Shutdown() override; std::string GetName() const override; diff --git a/Source/Core/VideoBackends/OGL/main.cpp b/Source/Core/VideoBackends/OGL/main.cpp index edfb861eea..56cd60fc47 100644 --- a/Source/Core/VideoBackends/OGL/main.cpp +++ b/Source/Core/VideoBackends/OGL/main.cpp @@ -157,12 +157,11 @@ bool VideoBackend::FillBackendInfo() return true; } -bool VideoBackend::Initialize(void* display_handle, void* window_handle) +bool VideoBackend::Initialize(const WindowSystemInfo& wsi) { InitializeShared(); - g_main_gl_context = GLContext::Create(display_handle, window_handle, - g_ActiveConfig.stereo_mode == StereoMode::QuadBuffer); + g_main_gl_context = GLContext::Create(wsi, g_ActiveConfig.stereo_mode == StereoMode::QuadBuffer); if (!g_main_gl_context) return false; diff --git a/Source/Core/VideoBackends/Software/SWOGLWindow.cpp b/Source/Core/VideoBackends/Software/SWOGLWindow.cpp index fb6731b4b7..d9694c17aa 100644 --- a/Source/Core/VideoBackends/Software/SWOGLWindow.cpp +++ b/Source/Core/VideoBackends/Software/SWOGLWindow.cpp @@ -13,9 +13,9 @@ std::unique_ptr SWOGLWindow::s_instance; -void SWOGLWindow::Init(void* display_handle, void* window_handle) +void SWOGLWindow::Init(const WindowSystemInfo& wsi) { - g_main_gl_context = GLContext::Create(display_handle, window_handle); + g_main_gl_context = GLContext::Create(wsi); if (!g_main_gl_context) { ERROR_LOG(VIDEO, "GLInterface::Create failed."); diff --git a/Source/Core/VideoBackends/Software/SWOGLWindow.h b/Source/Core/VideoBackends/Software/SWOGLWindow.h index a393194ed7..2d85770e61 100644 --- a/Source/Core/VideoBackends/Software/SWOGLWindow.h +++ b/Source/Core/VideoBackends/Software/SWOGLWindow.h @@ -12,11 +12,12 @@ #include "VideoCommon/VideoCommon.h" class AbstractTexture; +struct WindowSystemInfo; class SWOGLWindow { public: - static void Init(void* display_handle, void* window_handle); + static void Init(const WindowSystemInfo& wsi); static void Shutdown(); void Prepare(); diff --git a/Source/Core/VideoBackends/Software/SWmain.cpp b/Source/Core/VideoBackends/Software/SWmain.cpp index 2aa099e9e9..070cf74b69 100644 --- a/Source/Core/VideoBackends/Software/SWmain.cpp +++ b/Source/Core/VideoBackends/Software/SWmain.cpp @@ -78,11 +78,11 @@ void VideoSoftware::InitBackendInfo() g_Config.backend_info.AAModes = {1}; } -bool VideoSoftware::Initialize(void* display_handle, void* window_handle) +bool VideoSoftware::Initialize(const WindowSystemInfo& wsi) { InitializeShared(); - SWOGLWindow::Init(display_handle, window_handle); + SWOGLWindow::Init(wsi); Clipper::Init(); Rasterizer::Init(); diff --git a/Source/Core/VideoBackends/Software/VideoBackend.h b/Source/Core/VideoBackends/Software/VideoBackend.h index 336a96325b..bad120d6a1 100644 --- a/Source/Core/VideoBackends/Software/VideoBackend.h +++ b/Source/Core/VideoBackends/Software/VideoBackend.h @@ -11,7 +11,7 @@ namespace SW { class VideoSoftware : public VideoBackendBase { - bool Initialize(void* display_handle, void* window_handle) override; + bool Initialize(const WindowSystemInfo& wsi) override; void Shutdown() override; std::string GetName() const override; diff --git a/Source/Core/VideoBackends/Vulkan/VideoBackend.h b/Source/Core/VideoBackends/Vulkan/VideoBackend.h index ddf0ab4342..83d960330e 100644 --- a/Source/Core/VideoBackends/Vulkan/VideoBackend.h +++ b/Source/Core/VideoBackends/Vulkan/VideoBackend.h @@ -12,7 +12,7 @@ namespace Vulkan class VideoBackend : public VideoBackendBase { public: - bool Initialize(void* display_handle, void* window_handle) override; + bool Initialize(const WindowSystemInfo& wsi) override; void Shutdown() override; std::string GetName() const override { return "Vulkan"; } diff --git a/Source/Core/VideoBackends/Vulkan/main.cpp b/Source/Core/VideoBackends/Vulkan/main.cpp index 2617de2191..40798934e7 100644 --- a/Source/Core/VideoBackends/Vulkan/main.cpp +++ b/Source/Core/VideoBackends/Vulkan/main.cpp @@ -89,7 +89,7 @@ static bool ShouldEnableDebugReports(bool enable_validation_layers) return enable_validation_layers || IsHostGPULoggingEnabled(); } -bool VideoBackend::Initialize(void* display_handle, void* window_handle) +bool VideoBackend::Initialize(const WindowSystemInfo& wsi) { if (!LoadVulkanLibrary()) { @@ -107,7 +107,7 @@ bool VideoBackend::Initialize(void* display_handle, void* window_handle) // Create Vulkan instance, needed before we can create a surface, or enumerate devices. // We use this instance to fill in backend info, then re-use it for the actual device. - bool enable_surface = window_handle != nullptr; + bool enable_surface = wsi.render_surface != nullptr; bool enable_debug_reports = ShouldEnableDebugReports(enable_validation_layer); VkInstance instance = VulkanContext::CreateVulkanInstance(enable_surface, enable_debug_reports, enable_validation_layer); @@ -146,7 +146,7 @@ bool VideoBackend::Initialize(void* display_handle, void* window_handle) VkSurfaceKHR surface = VK_NULL_HANDLE; if (enable_surface) { - surface = SwapChain::CreateVulkanSurface(instance, display_handle, window_handle); + surface = SwapChain::CreateVulkanSurface(instance, wsi.display_connection, wsi.render_surface); if (surface == VK_NULL_HANDLE) { PanicAlert("Failed to create Vulkan surface."); @@ -209,7 +209,8 @@ bool VideoBackend::Initialize(void* display_handle, void* window_handle) std::unique_ptr swap_chain; if (surface != VK_NULL_HANDLE) { - swap_chain = SwapChain::Create(display_handle, window_handle, surface, g_Config.IsVSync()); + swap_chain = + SwapChain::Create(wsi.display_connection, wsi.render_surface, surface, g_Config.IsVSync()); if (!swap_chain) { PanicAlert("Failed to create Vulkan swap chain."); diff --git a/Source/Core/VideoCommon/VideoBackendBase.h b/Source/Core/VideoCommon/VideoBackendBase.h index 3b106bff98..83a74b0608 100644 --- a/Source/Core/VideoCommon/VideoBackendBase.h +++ b/Source/Core/VideoCommon/VideoBackendBase.h @@ -9,6 +9,7 @@ #include #include "Common/CommonTypes.h" +#include "Common/WindowSystemInfo.h" #include "VideoCommon/PerfQueryBase.h" namespace MMIO @@ -35,7 +36,7 @@ class VideoBackendBase { public: virtual ~VideoBackendBase() {} - virtual bool Initialize(void* display_handle, void* window_handle) = 0; + virtual bool Initialize(const WindowSystemInfo& wsi) = 0; virtual void Shutdown() = 0; virtual std::string GetName() const = 0; From dcdd02d646230e7903520a41dc9f86e57ae16dbe Mon Sep 17 00:00:00 2001 From: Stenzek Date: Wed, 3 Oct 2018 23:03:26 +1000 Subject: [PATCH 07/12] GLContext: Remove global context pointer --- Source/Core/Common/GL/GLContext.cpp | 2 - Source/Core/Common/GL/GLContext.h | 2 - .../Common/GL/GLExtensions/GLExtensions.cpp | 92 +++++++++---------- .../Common/GL/GLExtensions/GLExtensions.h | 6 +- Source/Core/Common/GL/GLUtil.cpp | 4 +- Source/Core/Common/GL/GLUtil.h | 4 +- .../VideoBackends/OGL/FramebufferManager.cpp | 3 +- Source/Core/VideoBackends/OGL/PerfQuery.cpp | 15 ++- .../VideoBackends/OGL/ProgramShaderCache.cpp | 5 +- Source/Core/VideoBackends/OGL/Render.cpp | 47 +++++----- Source/Core/VideoBackends/OGL/Render.h | 12 ++- .../Core/VideoBackends/OGL/SamplerCache.cpp | 4 +- Source/Core/VideoBackends/OGL/VideoBackend.h | 4 +- Source/Core/VideoBackends/OGL/main.cpp | 20 ++-- .../VideoBackends/Software/SWOGLWindow.cpp | 61 +++++++----- .../Core/VideoBackends/Software/SWOGLWindow.h | 22 +++-- .../VideoBackends/Software/SWRenderer.cpp | 11 ++- .../Core/VideoBackends/Software/SWRenderer.h | 9 +- Source/Core/VideoBackends/Software/SWmain.cpp | 10 +- 19 files changed, 183 insertions(+), 150 deletions(-) diff --git a/Source/Core/Common/GL/GLContext.cpp b/Source/Core/Common/GL/GLContext.cpp index da3e47aa26..d56d048d1b 100644 --- a/Source/Core/Common/GL/GLContext.cpp +++ b/Source/Core/Common/GL/GLContext.cpp @@ -23,8 +23,6 @@ #error Platform doesnt have a GLInterface #endif -std::unique_ptr g_main_gl_context; - GLContext::~GLContext() = default; bool GLContext::Initialize(void* display_handle, void* window_handle, bool stereo, bool core) diff --git a/Source/Core/Common/GL/GLContext.h b/Source/Core/Common/GL/GLContext.h index c9e1d8c457..89dba55286 100644 --- a/Source/Core/Common/GL/GLContext.h +++ b/Source/Core/Common/GL/GLContext.h @@ -60,5 +60,3 @@ protected: bool m_is_core_context = false; bool m_is_shared = false; }; - -extern std::unique_ptr g_main_gl_context; diff --git a/Source/Core/Common/GL/GLExtensions/GLExtensions.cpp b/Source/Core/Common/GL/GLExtensions/GLExtensions.cpp index 18c4dc2f39..641559a29a 100644 --- a/Source/Core/Common/GL/GLExtensions/GLExtensions.cpp +++ b/Source/Core/Common/GL/GLExtensions/GLExtensions.cpp @@ -2148,12 +2148,11 @@ const GLFunc gl_function_array[] = { namespace GLExtensions { // Private members and functions -static bool _isES; -static u32 _GLVersion; -static std::unordered_map m_extension_list; +static u32 s_gl_version; +static std::unordered_map s_extension_list; // Private initialization functions -bool InitFunctionPointers(); +bool InitFunctionPointers(GLContext* context); // Initializes the extension list the old way static void InitExtensionList21() @@ -2163,28 +2162,28 @@ static void InitExtensionList21() std::istringstream buffer(tmp); while (buffer >> tmp) - m_extension_list[tmp] = true; + s_extension_list[tmp] = true; } -static void InitExtensionList() +static void InitExtensionList(GLContext* context) { - m_extension_list.clear(); - if (_isES) + s_extension_list.clear(); + if (context->IsGLES()) { - switch (_GLVersion) + switch (s_gl_version) { default: case 320: - m_extension_list["VERSION_GLES_3_2"] = true; + s_extension_list["VERSION_GLES_3_2"] = true; case 310: - m_extension_list["VERSION_GLES_3_1"] = true; + s_extension_list["VERSION_GLES_3_1"] = true; case 300: - m_extension_list["VERSION_GLES_3"] = true; + s_extension_list["VERSION_GLES_3"] = true; break; } // We always have ES 2.0 - m_extension_list["VERSION_GLES_2"] = true; + s_extension_list["VERSION_GLES_2"] = true; } else { @@ -2194,7 +2193,7 @@ static void InitExtensionList() // When an extension got merged in to core, the naming may have changed // This has intentional fall through - switch (_GLVersion) + switch (s_gl_version) { default: case 450: @@ -2213,7 +2212,7 @@ static void InitExtensionList() "VERSION_4_5", }; for (auto it : gl450exts) - m_extension_list[it] = true; + s_extension_list[it] = true; } case 440: { @@ -2229,7 +2228,7 @@ static void InitExtensionList() "VERSION_4_4", }; for (auto it : gl440exts) - m_extension_list[it] = true; + s_extension_list[it] = true; } case 430: { @@ -2257,7 +2256,7 @@ static void InitExtensionList() "VERSION_4_3", }; for (auto it : gl430exts) - m_extension_list[it] = true; + s_extension_list[it] = true; } case 420: { @@ -2277,7 +2276,7 @@ static void InitExtensionList() "VERSION_4_2", }; for (auto it : gl420exts) - m_extension_list[it] = true; + s_extension_list[it] = true; } case 410: { @@ -2291,7 +2290,7 @@ static void InitExtensionList() "VERSION_4_1", }; for (auto it : gl410exts) - m_extension_list[it] = true; + s_extension_list[it] = true; } case 400: { @@ -2311,7 +2310,7 @@ static void InitExtensionList() "VERSION_4_0", }; for (auto it : gl400exts) - m_extension_list[it] = true; + s_extension_list[it] = true; } case 330: { @@ -2329,7 +2328,7 @@ static void InitExtensionList() "VERSION_3_3", }; for (auto it : gl330exts) - m_extension_list[it] = true; + s_extension_list[it] = true; } case 320: { @@ -2346,7 +2345,7 @@ static void InitExtensionList() "VERSION_3_2", }; for (auto it : gl320exts) - m_extension_list[it] = true; + s_extension_list[it] = true; } case 310: { @@ -2361,7 +2360,7 @@ static void InitExtensionList() "VERSION_3_1", }; for (auto it : gl310exts) - m_extension_list[it] = true; + s_extension_list[it] = true; } case 300: { @@ -2392,7 +2391,7 @@ static void InitExtensionList() "VERSION_3_0", }; for (auto it : gl300exts) - m_extension_list[it] = true; + s_extension_list[it] = true; } case 210: case 200: @@ -2406,10 +2405,10 @@ static void InitExtensionList() break; } // So we can easily determine if we are running dekstop GL - m_extension_list["VERSION_GL"] = true; + s_extension_list["VERSION_GL"] = true; } - if (_GLVersion < 300) + if (s_gl_version < 300) { InitExtensionList21(); return; @@ -2417,7 +2416,7 @@ static void InitExtensionList() GLint NumExtension = 0; glGetIntegerv(GL_NUM_EXTENSIONS, &NumExtension); for (GLint i = 0; i < NumExtension; ++i) - m_extension_list[std::string((const char*)glGetStringi(GL_EXTENSIONS, i))] = true; + s_extension_list[std::string((const char*)glGetStringi(GL_EXTENSIONS, i))] = true; } static void InitVersion() { @@ -2425,14 +2424,14 @@ static void InitVersion() glGetIntegerv(GL_MAJOR_VERSION, &major); glGetIntegerv(GL_MINOR_VERSION, &minor); if (glGetError() == GL_NO_ERROR) - _GLVersion = major * 100 + minor * 10; + s_gl_version = major * 100 + minor * 10; else - _GLVersion = 210; + s_gl_version = 210; } -static void* GetFuncAddress(const std::string& name, void** func) +static void* GetFuncAddress(GLContext* context, const std::string& name, void** func) { - *func = g_main_gl_context->GetFuncAddress(name); + *func = context->GetFuncAddress(name); if (*func == nullptr) { #if defined(__linux__) || defined(__APPLE__) @@ -2448,37 +2447,36 @@ static void* GetFuncAddress(const std::string& name, void** func) // Public members u32 Version() { - return _GLVersion; + return s_gl_version; } bool Supports(const std::string& name) { - return m_extension_list[name]; + return s_extension_list[name]; } -bool Init() +bool Init(GLContext* context) { - _isES = g_main_gl_context->GetMode() == GLContext::Mode::OpenGLES; - // Grab a few functions for initial checking // We need them to grab the extension list // Also to check if there is an error grabbing the version - if (GetFuncAddress("glGetIntegerv", (void**)&glGetIntegerv) == nullptr) + if (GetFuncAddress(context, "glGetIntegerv", (void**)&glGetIntegerv) == nullptr) return false; - if (GetFuncAddress("glGetString", (void**)&glGetString) == nullptr) + if (GetFuncAddress(context, "glGetString", (void**)&glGetString) == nullptr) return false; - if (GetFuncAddress("glGetError", (void**)&glGetError) == nullptr) + if (GetFuncAddress(context, "glGetError", (void**)&glGetError) == nullptr) return false; InitVersion(); // We need to use glGetStringi to get the extension list // if we are using GLES3 or a GL version greater than 2.1 - if (_GLVersion > 210 && GetFuncAddress("glGetStringi", (void**)&glGetStringi) == nullptr) + if (s_gl_version > 210 && + GetFuncAddress(context, "glGetStringi", (void**)&glGetStringi) == nullptr) return false; - InitExtensionList(); + InitExtensionList(context); - return InitFunctionPointers(); + return InitFunctionPointers(context); } // Private initialization functions @@ -2491,20 +2489,20 @@ static bool HasFeatures(const std::string& extensions) while (buffer >> tmp) { if (tmp[0] == '!') - result &= !m_extension_list[tmp.erase(0, 1)]; + result &= !s_extension_list[tmp.erase(0, 1)]; else if (tmp[0] == '|') - result |= m_extension_list[tmp.erase(0, 1)]; + result |= s_extension_list[tmp.erase(0, 1)]; else - result &= m_extension_list[tmp]; + result &= s_extension_list[tmp]; } return result; } -bool InitFunctionPointers() +bool InitFunctionPointers(GLContext* context) { bool result = true; for (const auto& it : gl_function_array) if (HasFeatures(it.requirements)) - result &= !!GetFuncAddress(it.function_name, it.function_ptr); + result &= !!GetFuncAddress(context, it.function_name, it.function_ptr); return result; } } // namespace GLExtensions diff --git a/Source/Core/Common/GL/GLExtensions/GLExtensions.h b/Source/Core/Common/GL/GLExtensions/GLExtensions.h index 2c0364da48..f1e258f98e 100644 --- a/Source/Core/Common/GL/GLExtensions/GLExtensions.h +++ b/Source/Core/Common/GL/GLExtensions/GLExtensions.h @@ -54,10 +54,12 @@ #include "Common/GL/GLExtensions/gl_4_4.h" #include "Common/GL/GLExtensions/gl_4_5.h" +class GLContext; + namespace GLExtensions { // Initializes the interface -bool Init(); +bool Init(GLContext* context); // Function for checking if the hardware supports an extension // example: if (GLExtensions::Supports("GL_ARB_multi_map")) @@ -65,4 +67,4 @@ bool Supports(const std::string& name); // Returns OpenGL version in format 430 u32 Version(); -} +} // namespace GLExtensions diff --git a/Source/Core/Common/GL/GLUtil.cpp b/Source/Core/Common/GL/GLUtil.cpp index 729cc2c25d..ba0f76b9b0 100644 --- a/Source/Core/Common/GL/GLUtil.cpp +++ b/Source/Core/Common/GL/GLUtil.cpp @@ -96,11 +96,11 @@ GLuint CompileProgram(const std::string& vertexShader, const std::string& fragme return programID; } -void EnablePrimitiveRestart() +void EnablePrimitiveRestart(const GLContext* context) { constexpr GLuint PRIMITIVE_RESTART_INDEX = 65535; - if (g_main_gl_context->GetMode() == GLContext::Mode::OpenGLES) + if (context->IsGLES()) { glEnable(GL_PRIMITIVE_RESTART_FIXED_INDEX); } diff --git a/Source/Core/Common/GL/GLUtil.h b/Source/Core/Common/GL/GLUtil.h index 62605585f3..1ec63ebad0 100644 --- a/Source/Core/Common/GL/GLUtil.h +++ b/Source/Core/Common/GL/GLUtil.h @@ -8,8 +8,10 @@ #include "Common/GL/GLExtensions/GLExtensions.h" +class GLContext; + namespace GLUtil { GLuint CompileProgram(const std::string& vertexShader, const std::string& fragmentShader); -void EnablePrimitiveRestart(); +void EnablePrimitiveRestart(const GLContext* context); } // namespace GLUtil diff --git a/Source/Core/VideoBackends/OGL/FramebufferManager.cpp b/Source/Core/VideoBackends/OGL/FramebufferManager.cpp index 1c1c976f70..12de898ff5 100644 --- a/Source/Core/VideoBackends/OGL/FramebufferManager.cpp +++ b/Source/Core/VideoBackends/OGL/FramebufferManager.cpp @@ -9,7 +9,6 @@ #include "Common/Common.h" #include "Common/CommonTypes.h" -#include "Common/GL/GLContext.h" #include "Common/Logging/Log.h" #include "Common/MsgHandler.h" @@ -414,7 +413,7 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms glBindBuffer(GL_ARRAY_BUFFER, static_cast(g_vertex_manager.get())->GetVertexBufferHandle()); - if (!g_main_gl_context->IsGLES()) + if (!static_cast(g_renderer.get())->IsGLES()) glEnable(GL_PROGRAM_POINT_SIZE); } diff --git a/Source/Core/VideoBackends/OGL/PerfQuery.cpp b/Source/Core/VideoBackends/OGL/PerfQuery.cpp index 30a6e1781b..77471cee19 100644 --- a/Source/Core/VideoBackends/OGL/PerfQuery.cpp +++ b/Source/Core/VideoBackends/OGL/PerfQuery.cpp @@ -6,24 +6,23 @@ #include "Common/CommonFuncs.h" #include "Common/CommonTypes.h" -#include "Common/GL/GLContext.h" -#include "Common/GL/GLUtil.h" +#include "Common/GL/GLExtensions/GLExtensions.h" #include "VideoBackends/OGL/PerfQuery.h" -#include "VideoCommon/RenderBase.h" +#include "VideoBackends/OGL/Render.h" #include "VideoCommon/VideoConfig.h" namespace OGL { std::unique_ptr GetPerfQuery() { - if (g_main_gl_context->IsGLES() && GLExtensions::Supports("GL_NV_occlusion_query_samples")) + const bool is_gles = static_cast(g_renderer.get())->IsGLES(); + if (is_gles && GLExtensions::Supports("GL_NV_occlusion_query_samples")) return std::make_unique(); - - if (g_main_gl_context->IsGLES()) + else if (is_gles) return std::make_unique(GL_ANY_SAMPLES_PASSED); - - return std::make_unique(GL_SAMPLES_PASSED); + else + return std::make_unique(GL_SAMPLES_PASSED); } PerfQuery::PerfQuery() : m_query_read_pos() diff --git a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp index ae930dddab..78458aa3fe 100644 --- a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp +++ b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp @@ -805,7 +805,8 @@ void ProgramShaderCache::CreateHeader() bool SharedContextAsyncShaderCompiler::WorkerThreadInitMainThread(void** param) { - std::unique_ptr context = g_main_gl_context->CreateSharedContext(); + std::unique_ptr context = + static_cast(g_renderer.get())->GetMainGLContext()->CreateSharedContext(); if (!context) { PanicAlert("Failed to create shared context for shader compiling."); @@ -824,7 +825,7 @@ bool SharedContextAsyncShaderCompiler::WorkerThreadInitWorkerThread(void* param) s_is_shared_context = true; if (g_ActiveConfig.backend_info.bSupportsPrimitiveRestart) - GLUtil::EnablePrimitiveRestart(); + GLUtil::EnablePrimitiveRestart(context); return true; } diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index be08541f97..b28df12c6a 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -353,9 +353,10 @@ static void InitDriverInfo() } // Init functions -Renderer::Renderer() - : ::Renderer(static_cast(std::max(g_main_gl_context->GetBackBufferWidth(), 1u)), - static_cast(std::max(g_main_gl_context->GetBackBufferHeight(), 1u))) +Renderer::Renderer(std::unique_ptr main_gl_context) + : ::Renderer(static_cast(std::max(main_gl_context->GetBackBufferWidth(), 1u)), + static_cast(std::max(main_gl_context->GetBackBufferHeight(), 1u))), + m_main_gl_context(std::move(main_gl_context)) { bool bSuccess = true; @@ -365,7 +366,7 @@ Renderer::Renderer() InitDriverInfo(); - if (!g_main_gl_context->IsGLES()) + if (!m_main_gl_context->IsGLES()) { if (!GLExtensions::Supports("GL_ARB_framebuffer_object")) { @@ -500,7 +501,7 @@ Renderer::Renderer() g_Config.backend_info.bSupportsBPTCTextures = GLExtensions::Supports("GL_ARB_texture_compression_bptc"); - if (g_main_gl_context->IsGLES()) + if (m_main_gl_context->IsGLES()) { g_ogl_config.SupportedESPointSize = GLExtensions::Supports("GL_OES_geometry_point_size") ? @@ -731,7 +732,7 @@ Renderer::Renderer() if (!g_ogl_config.bSupportsGLBufferStorage && !g_ogl_config.bSupportsGLPinnedMemory) { OSD::AddMessage(StringFromFormat("Your OpenGL driver does not support %s_buffer_storage.", - g_main_gl_context->IsGLES() ? "EXT" : "ARB"), + m_main_gl_context->IsGLES() ? "EXT" : "ARB"), 60000); OSD::AddMessage("This device's performance will be terrible.", 60000); OSD::AddMessage("Please ask your device vendor for an updated OpenGL driver.", 60000); @@ -760,7 +761,7 @@ Renderer::Renderer() // Handle VSync on/off s_vsync = g_ActiveConfig.IsVSync(); if (!DriverDetails::HasBug(DriverDetails::BUG_BROKEN_VSYNC)) - g_main_gl_context->SwapInterval(s_vsync); + m_main_gl_context->SwapInterval(s_vsync); // Because of the fixed framebuffer size we need to disable the resolution // options while running @@ -795,18 +796,22 @@ Renderer::Renderer() glClearDepthf(1.0f); if (g_ActiveConfig.backend_info.bSupportsPrimitiveRestart) - GLUtil::EnablePrimitiveRestart(); + GLUtil::EnablePrimitiveRestart(m_main_gl_context.get()); IndexGenerator::Init(); UpdateActiveConfig(); ClearEFBCache(); } -Renderer::~Renderer() = default; +Renderer::~Renderer() +{ + m_main_gl_context->ClearCurrent(); + m_main_gl_context->Shutdown(); +} bool Renderer::IsHeadless() const { - return g_main_gl_context->IsHeadless(); + return m_main_gl_context->IsHeadless(); } void Renderer::Shutdown() @@ -1048,7 +1053,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) std::unique_ptr colorMap(new u32[targetPixelRcWidth * targetPixelRcHeight]); - if (g_main_gl_context->IsGLES()) + if (IsGLES()) // XXX: Swap colours glReadPixels(targetPixelRc.left, targetPixelRc.bottom, targetPixelRcWidth, targetPixelRcHeight, GL_RGBA, GL_UNSIGNED_BYTE, colorMap.get()); @@ -1355,7 +1360,7 @@ void Renderer::ApplyBlendingState(const BlendingState state, bool force) GL_XOR, GL_OR, GL_NOR, GL_EQUIV, GL_INVERT, GL_OR_REVERSE, GL_COPY_INVERTED, GL_OR_INVERTED, GL_NAND, GL_SET}; - if (g_main_gl_context->IsGLES()) + if (IsGLES()) { // Logic ops aren't available in GLES3 } @@ -1425,7 +1430,7 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region OSD::DrawMessages(); // Swap the back and front buffers, presenting the image. - g_main_gl_context->Swap(); + m_main_gl_context->Swap(); } else { @@ -1470,7 +1475,7 @@ void Renderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_region { s_vsync = g_ActiveConfig.IsVSync(); if (!DriverDetails::HasBug(DriverDetails::BUG_BROKEN_VSYNC)) - g_main_gl_context->SwapInterval(s_vsync); + m_main_gl_context->SwapInterval(s_vsync); } // Clean out old stuff from caches. It's not worth it to clean out the shader caches. @@ -1504,12 +1509,12 @@ void Renderer::CheckForSurfaceChange() if (!m_surface_changed.TestAndClear()) return; - g_main_gl_context->UpdateSurface(m_new_surface_handle); + m_main_gl_context->UpdateSurface(m_new_surface_handle); m_new_surface_handle = nullptr; // With a surface change, the window likely has new dimensions. - m_backbuffer_width = g_main_gl_context->GetBackBufferWidth(); - m_backbuffer_height = g_main_gl_context->GetBackBufferHeight(); + m_backbuffer_width = m_main_gl_context->GetBackBufferWidth(); + m_backbuffer_height = m_main_gl_context->GetBackBufferHeight(); } void Renderer::CheckForSurfaceResize() @@ -1517,9 +1522,9 @@ void Renderer::CheckForSurfaceResize() if (!m_surface_resized.TestAndClear()) return; - g_main_gl_context->Update(); - m_backbuffer_width = g_main_gl_context->GetBackBufferWidth(); - m_backbuffer_height = g_main_gl_context->GetBackBufferHeight(); + m_main_gl_context->Update(); + m_backbuffer_width = m_main_gl_context->GetBackBufferWidth(); + m_backbuffer_height = m_main_gl_context->GetBackBufferHeight(); } void Renderer::DrawEFB(GLuint framebuffer, const TargetRectangle& target_rc, @@ -1540,7 +1545,7 @@ void Renderer::ResetAPIState() glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); glDisable(GL_BLEND); - if (!g_main_gl_context->IsGLES()) + if (!IsGLES()) glDisable(GL_COLOR_LOGIC_OP); if (g_ActiveConfig.backend_info.bSupportsDepthClamp) { diff --git a/Source/Core/VideoBackends/OGL/Render.h b/Source/Core/VideoBackends/OGL/Render.h index 7662900624..5beb4ecd75 100644 --- a/Source/Core/VideoBackends/OGL/Render.h +++ b/Source/Core/VideoBackends/OGL/Render.h @@ -7,7 +7,8 @@ #include #include -#include "Common/GL/GLUtil.h" +#include "Common/GL/GLContext.h" +#include "Common/GL/GLExtensions/GLExtensions.h" #include "VideoCommon/RenderBase.h" struct XFBSourceBase; @@ -81,7 +82,7 @@ extern VideoConfig g_ogl_config; class Renderer : public ::Renderer { public: - Renderer(); + Renderer(std::unique_ptr main_gl_context); ~Renderer() override; bool IsHeadless() const override; @@ -143,6 +144,10 @@ public: std::unique_ptr CreateAsyncShaderCompiler() override; + // Only call methods from this on the GPU thread. + GLContext* GetMainGLContext() const { return m_main_gl_context.get(); } + bool IsGLES() const { return m_main_gl_context->IsGLES(); } + private: void UpdateEFBCache(EFBAccessType type, u32 cacheRectIdx, const EFBRectangle& efbPixelRc, const TargetRectangle& targetPixelRc, const void* data); @@ -161,10 +166,11 @@ private: void ApplyDepthState(const DepthState state, bool force = false); void UploadUtilityUniforms(const void* uniforms, u32 uniforms_size); + std::unique_ptr m_main_gl_context; std::array m_bound_textures{}; const OGLPipeline* m_graphics_pipeline = nullptr; RasterizationState m_current_rasterization_state = {}; DepthState m_current_depth_state = {}; BlendingState m_current_blend_state = {}; }; -} +} // namespace OGL diff --git a/Source/Core/VideoBackends/OGL/SamplerCache.cpp b/Source/Core/VideoBackends/OGL/SamplerCache.cpp index ae848e8d29..364ec51c99 100644 --- a/Source/Core/VideoBackends/OGL/SamplerCache.cpp +++ b/Source/Core/VideoBackends/OGL/SamplerCache.cpp @@ -3,11 +3,11 @@ // Refer to the license.txt file included. #include "VideoBackends/OGL/SamplerCache.h" +#include "VideoBackends/OGL/Render.h" #include #include "Common/CommonTypes.h" -#include "Common/GL/GLContext.h" #include "VideoCommon/SamplerCommon.h" #include "VideoCommon/VideoConfig.h" @@ -99,7 +99,7 @@ void SamplerCache::SetParameters(GLuint sampler_id, const SamplerState& params) glSamplerParameterf(sampler_id, GL_TEXTURE_MIN_LOD, params.min_lod / 16.f); glSamplerParameterf(sampler_id, GL_TEXTURE_MAX_LOD, params.max_lod / 16.f); - if (!g_main_gl_context->IsGLES()) + if (!static_cast(g_renderer.get())->IsGLES()) glSamplerParameterf(sampler_id, GL_TEXTURE_LOD_BIAS, params.lod_bias / 256.f); if (params.anisotropic_filtering && g_ogl_config.bSupportsAniso) diff --git a/Source/Core/VideoBackends/OGL/VideoBackend.h b/Source/Core/VideoBackends/OGL/VideoBackend.h index 2a1360542f..74bc929e85 100644 --- a/Source/Core/VideoBackends/OGL/VideoBackend.h +++ b/Source/Core/VideoBackends/OGL/VideoBackend.h @@ -7,6 +7,8 @@ #include #include "VideoCommon/VideoBackendBase.h" +class GLContext; + namespace OGL { class VideoBackend : public VideoBackendBase @@ -20,7 +22,7 @@ class VideoBackend : public VideoBackendBase void InitBackendInfo() override; private: - bool InitializeGLExtensions(); + bool InitializeGLExtensions(GLContext* context); bool FillBackendInfo(); }; } // namespace OGL diff --git a/Source/Core/VideoBackends/OGL/main.cpp b/Source/Core/VideoBackends/OGL/main.cpp index 56cd60fc47..2c38986aa9 100644 --- a/Source/Core/VideoBackends/OGL/main.cpp +++ b/Source/Core/VideoBackends/OGL/main.cpp @@ -66,7 +66,7 @@ std::string VideoBackend::GetName() const std::string VideoBackend::GetDisplayName() const { - if (g_main_gl_context && g_main_gl_context->GetMode() == GLContext::Mode::OpenGLES) + if (g_renderer && static_cast(g_renderer.get())->IsGLES()) return _trans("OpenGL ES"); else return _trans("OpenGL"); @@ -108,10 +108,10 @@ void VideoBackend::InitBackendInfo() g_Config.backend_info.AAModes = {1, 2, 4, 8}; } -bool VideoBackend::InitializeGLExtensions() +bool VideoBackend::InitializeGLExtensions(GLContext* context) { // Init extension support. - if (!GLExtensions::Init()) + if (!GLExtensions::Init(context)) { // OpenGL 2.0 is required for all shader based drawings. There is no way to get this by // extensions @@ -161,15 +161,16 @@ bool VideoBackend::Initialize(const WindowSystemInfo& wsi) { InitializeShared(); - g_main_gl_context = GLContext::Create(wsi, g_ActiveConfig.stereo_mode == StereoMode::QuadBuffer); - if (!g_main_gl_context) + std::unique_ptr main_gl_context = + GLContext::Create(wsi, g_ActiveConfig.stereo_mode == StereoMode::QuadBuffer); + if (!main_gl_context) return false; - g_main_gl_context->MakeCurrent(); - if (!InitializeGLExtensions() || !FillBackendInfo()) + main_gl_context->MakeCurrent(); + if (!InitializeGLExtensions(main_gl_context.get()) || !FillBackendInfo()) return false; - g_renderer = std::make_unique(); + g_renderer = std::make_unique(std::move(main_gl_context)); g_vertex_manager = std::make_unique(); g_perf_query = GetPerfQuery(); ProgramShaderCache::Init(); @@ -195,9 +196,6 @@ void VideoBackend::Shutdown() g_perf_query.reset(); g_vertex_manager.reset(); g_renderer.reset(); - g_main_gl_context->ClearCurrent(); - g_main_gl_context->Shutdown(); - g_main_gl_context.reset(); ShutdownShared(); } } // namespace OGL diff --git a/Source/Core/VideoBackends/Software/SWOGLWindow.cpp b/Source/Core/VideoBackends/Software/SWOGLWindow.cpp index d9694c17aa..4936d1a13c 100644 --- a/Source/Core/VideoBackends/Software/SWOGLWindow.cpp +++ b/Source/Core/VideoBackends/Software/SWOGLWindow.cpp @@ -7,48 +7,58 @@ #include "Common/GL/GLContext.h" #include "Common/GL/GLUtil.h" #include "Common/Logging/Log.h" +#include "Common/MsgHandler.h" #include "VideoBackends/Software/SWOGLWindow.h" #include "VideoBackends/Software/SWTexture.h" -std::unique_ptr SWOGLWindow::s_instance; +SWOGLWindow::SWOGLWindow() = default; -void SWOGLWindow::Init(const WindowSystemInfo& wsi) +SWOGLWindow::~SWOGLWindow() { - g_main_gl_context = GLContext::Create(wsi); - if (!g_main_gl_context) + if (m_gl_context) { - ERROR_LOG(VIDEO, "GLInterface::Create failed."); + m_gl_context->ClearCurrent(); + m_gl_context->Shutdown(); + } +} + +std::unique_ptr SWOGLWindow::Create(const WindowSystemInfo& wsi) +{ + std::unique_ptr window = std::unique_ptr(new SWOGLWindow()); + if (!window->Initialize(wsi)) + { + PanicAlert("Failed to create OpenGL window"); + return nullptr; } - s_instance.reset(new SWOGLWindow()); + return window; } -void SWOGLWindow::Shutdown() +bool SWOGLWindow::IsHeadless() const { - g_main_gl_context->Shutdown(); - g_main_gl_context.reset(); - - s_instance.reset(); + return m_gl_context->IsHeadless(); } -void SWOGLWindow::Prepare() +bool SWOGLWindow::Initialize(const WindowSystemInfo& wsi) { - if (m_init) - return; - m_init = true; + m_gl_context = GLContext::Create(wsi); + if (!m_gl_context) + return false; + + m_gl_context->MakeCurrent(); // Init extension support. - if (!GLExtensions::Init()) + if (!GLExtensions::Init(m_gl_context.get())) { ERROR_LOG(VIDEO, "GLExtensions::Init failed!Does your video card support OpenGL 2.0?"); - return; + return false; } else if (GLExtensions::Version() < 310) { ERROR_LOG(VIDEO, "OpenGL Version %d detected, but at least 3.1 is required.", GLExtensions::Version()); - return; + return false; } std::string frag_shader = "in vec2 TexCoord;\n" @@ -65,9 +75,9 @@ void SWOGLWindow::Prepare() " TexCoord = vec2(rawpos.x, -rawpos.y);\n" "}\n"; - std::string header = g_main_gl_context->IsGLES() ? "#version 300 es\n" - "precision highp float;\n" : - "#version 140\n"; + std::string header = m_gl_context->IsGLES() ? "#version 300 es\n" + "precision highp float;\n" : + "#version 140\n"; m_image_program = GLUtil::CompileProgram(header + vertex_shader, header + frag_shader); @@ -81,6 +91,7 @@ void SWOGLWindow::Prepare() glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glGenVertexArrays(1, &m_image_vao); + return true; } void SWOGLWindow::PrintText(const std::string& text, int x, int y, u32 color) @@ -91,10 +102,10 @@ void SWOGLWindow::PrintText(const std::string& text, int x, int y, u32 color) void SWOGLWindow::ShowImage(AbstractTexture* image, const EFBRectangle& xfb_region) { SW::SWTexture* sw_image = static_cast(image); - g_main_gl_context->Update(); // just updates the render window position and the backbuffer size + m_gl_context->Update(); // just updates the render window position and the backbuffer size - GLsizei glWidth = (GLsizei)g_main_gl_context->GetBackBufferWidth(); - GLsizei glHeight = (GLsizei)g_main_gl_context->GetBackBufferHeight(); + GLsizei glWidth = (GLsizei)m_gl_context->GetBackBufferWidth(); + GLsizei glHeight = (GLsizei)m_gl_context->GetBackBufferHeight(); glViewport(0, 0, glWidth, glHeight); @@ -121,5 +132,5 @@ void SWOGLWindow::ShowImage(AbstractTexture* image, const EFBRectangle& xfb_regi // } m_text.clear(); - g_main_gl_context->Swap(); + m_gl_context->Swap(); } diff --git a/Source/Core/VideoBackends/Software/SWOGLWindow.h b/Source/Core/VideoBackends/Software/SWOGLWindow.h index 2d85770e61..38ae316d07 100644 --- a/Source/Core/VideoBackends/Software/SWOGLWindow.h +++ b/Source/Core/VideoBackends/Software/SWOGLWindow.h @@ -11,15 +11,18 @@ #include "Common/CommonTypes.h" #include "VideoCommon/VideoCommon.h" +class GLContext; + class AbstractTexture; struct WindowSystemInfo; class SWOGLWindow { public: - static void Init(const WindowSystemInfo& wsi); - static void Shutdown(); - void Prepare(); + ~SWOGLWindow(); + + GLContext* GetContext() const { return m_gl_context.get(); } + bool IsHeadless() const; // Will be printed on the *next* image void PrintText(const std::string& text, int x, int y, u32 color); @@ -27,10 +30,13 @@ public: // Image to show, will be swapped immediately void ShowImage(AbstractTexture* image, const EFBRectangle& xfb_region); - static std::unique_ptr s_instance; + static std::unique_ptr Create(const WindowSystemInfo& wsi); private: - SWOGLWindow() {} + SWOGLWindow(); + + bool Initialize(const WindowSystemInfo& wsi); + struct TextData { std::string text; @@ -39,7 +45,9 @@ private: }; std::vector m_text; - bool m_init{false}; + u32 m_image_program = 0; + u32 m_image_texture = 0; + u32 m_image_vao = 0; - u32 m_image_program, m_image_texture, m_image_vao; + std::unique_ptr m_gl_context; }; diff --git a/Source/Core/VideoBackends/Software/SWRenderer.cpp b/Source/Core/VideoBackends/Software/SWRenderer.cpp index 5e76cdd296..2c6a97027b 100644 --- a/Source/Core/VideoBackends/Software/SWRenderer.cpp +++ b/Source/Core/VideoBackends/Software/SWRenderer.cpp @@ -24,14 +24,15 @@ #include "VideoCommon/VideoBackendBase.h" #include "VideoCommon/VideoConfig.h" -SWRenderer::SWRenderer() - : ::Renderer(static_cast(MAX_XFB_WIDTH), static_cast(MAX_XFB_HEIGHT)) +SWRenderer::SWRenderer(std::unique_ptr window) + : ::Renderer(static_cast(MAX_XFB_WIDTH), static_cast(MAX_XFB_HEIGHT)), + m_window(std::move(window)) { } bool SWRenderer::IsHeadless() const { - return g_main_gl_context->IsHeadless(); + return m_window->IsHeadless(); } std::unique_ptr SWRenderer::CreateTexture(const TextureConfig& config) @@ -55,7 +56,7 @@ SWRenderer::CreateFramebuffer(const AbstractTexture* color_attachment, void SWRenderer::RenderText(const std::string& pstr, int left, int top, u32 color) { - SWOGLWindow::s_instance->PrintText(pstr, left, top, color); + m_window->PrintText(pstr, left, top, color); } class SWShader final : public AbstractShader @@ -100,7 +101,7 @@ void SWRenderer::SwapImpl(AbstractTexture* texture, const EFBRectangle& xfb_regi if (!IsHeadless()) { DrawDebugText(); - SWOGLWindow::s_instance->ShowImage(texture, xfb_region); + m_window->ShowImage(texture, xfb_region); } UpdateActiveConfig(); diff --git a/Source/Core/VideoBackends/Software/SWRenderer.h b/Source/Core/VideoBackends/Software/SWRenderer.h index 6b2a3f0795..936139516f 100644 --- a/Source/Core/VideoBackends/Software/SWRenderer.h +++ b/Source/Core/VideoBackends/Software/SWRenderer.h @@ -4,14 +4,18 @@ #pragma once +#include + #include "Common/CommonTypes.h" #include "VideoCommon/RenderBase.h" +class SWOGLWindow; + class SWRenderer : public Renderer { public: - SWRenderer(); + SWRenderer(std::unique_ptr window); bool IsHeadless() const override; @@ -42,4 +46,7 @@ public: u32 color, u32 z) override; void ReinterpretPixelData(unsigned int convtype) override {} + +private: + std::unique_ptr m_window; }; diff --git a/Source/Core/VideoBackends/Software/SWmain.cpp b/Source/Core/VideoBackends/Software/SWmain.cpp index 070cf74b69..a0ad349849 100644 --- a/Source/Core/VideoBackends/Software/SWmain.cpp +++ b/Source/Core/VideoBackends/Software/SWmain.cpp @@ -82,16 +82,15 @@ bool VideoSoftware::Initialize(const WindowSystemInfo& wsi) { InitializeShared(); - SWOGLWindow::Init(wsi); + std::unique_ptr window = SWOGLWindow::Create(wsi); + if (!window) + return false; Clipper::Init(); Rasterizer::Init(); DebugUtil::Init(); - g_main_gl_context->MakeCurrent(); - SWOGLWindow::s_instance->Prepare(); - - g_renderer = std::make_unique(); + g_renderer = std::make_unique(std::move(window)); g_vertex_manager = std::make_unique(); g_perf_query = std::make_unique(); g_texture_cache = std::make_unique(); @@ -108,7 +107,6 @@ void VideoSoftware::Shutdown() g_renderer->Shutdown(); DebugUtil::Shutdown(); - SWOGLWindow::Shutdown(); g_framebuffer_manager.reset(); g_texture_cache.reset(); g_perf_query.reset(); From 4b8d1c2b429485d54d7dad2fdc142ed43b34b992 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Wed, 3 Oct 2018 23:03:30 +1000 Subject: [PATCH 08/12] GLContext: Combine shared context initialization and creation --- Source/Core/Common/GL/GLContext.cpp | 5 --- Source/Core/Common/GL/GLContext.h | 1 - Source/Core/Common/GL/GLInterface/AGL.h | 1 - Source/Core/Common/GL/GLInterface/AGL.mm | 31 ++++++-------- Source/Core/Common/GL/GLInterface/EGL.cpp | 48 +++++++++------------- Source/Core/Common/GL/GLInterface/EGL.h | 1 - Source/Core/Common/GL/GLInterface/GLX.cpp | 49 ++++++++++------------- Source/Core/Common/GL/GLInterface/GLX.h | 1 - Source/Core/Common/GL/GLInterface/WGL.cpp | 39 ++++++++---------- Source/Core/Common/GL/GLInterface/WGL.h | 1 - 10 files changed, 68 insertions(+), 109 deletions(-) diff --git a/Source/Core/Common/GL/GLContext.cpp b/Source/Core/Common/GL/GLContext.cpp index d56d048d1b..90cb833302 100644 --- a/Source/Core/Common/GL/GLContext.cpp +++ b/Source/Core/Common/GL/GLContext.cpp @@ -30,11 +30,6 @@ bool GLContext::Initialize(void* display_handle, void* window_handle, bool stere return false; } -bool GLContext::Initialize(GLContext* main_context) -{ - return false; -} - bool GLContext::IsHeadless() const { return true; diff --git a/Source/Core/Common/GL/GLContext.h b/Source/Core/Common/GL/GLContext.h index 89dba55286..48e261bae7 100644 --- a/Source/Core/Common/GL/GLContext.h +++ b/Source/Core/Common/GL/GLContext.h @@ -50,7 +50,6 @@ public: protected: virtual bool Initialize(void* display_handle, void* window_handle, bool stereo, bool core); - virtual bool Initialize(GLContext* main_context); Mode m_opengl_mode = Mode::Detect; diff --git a/Source/Core/Common/GL/GLInterface/AGL.h b/Source/Core/Common/GL/GLInterface/AGL.h index 00978535f8..5e4052caa8 100644 --- a/Source/Core/Common/GL/GLInterface/AGL.h +++ b/Source/Core/Common/GL/GLInterface/AGL.h @@ -32,7 +32,6 @@ public: protected: bool Initialize(void* display_handle, void* window_handle, bool stereo, bool core) override; - bool Initialize(GLContext* main_context) override; NSView* m_view = nullptr; NSOpenGLContext* m_context = nullptr; diff --git a/Source/Core/Common/GL/GLInterface/AGL.mm b/Source/Core/Common/GL/GLInterface/AGL.mm index 4998fab40e..2cd0cb7f60 100644 --- a/Source/Core/Common/GL/GLInterface/AGL.mm +++ b/Source/Core/Common/GL/GLInterface/AGL.mm @@ -86,28 +86,21 @@ bool GLContextAGL::Initialize(void* display_handle, void* window_handle, bool st return AttachContextToView(m_context, m_view, &m_backbuffer_width, &m_backbuffer_height); } -bool GLContextAGL::Initialize(GLContext* main_context) -{ - GLContextAGL* agl_context = static_cast(main_context); - NSOpenGLPixelFormat* pixel_format = agl_context->m_pixel_format; - NSOpenGLContext* share_context = agl_context->m_context; - - m_context = [[NSOpenGLContext alloc] initWithFormat:pixel_format shareContext:share_context]; - if (m_context == nil) - { - ERROR_LOG(VIDEO, "failed to create shared context"); - return false; - } - - return true; -} - std::unique_ptr GLContextAGL::CreateSharedContext() { - std::unique_ptr context = std::make_unique(); - if (!context->Initialize(this)) + NSOpenGLContext* new_agl_context = + [[NSOpenGLContext alloc] initWithFormat:m_pixel_format shareContext:m_context]; + if (new_agl_context == nil) + { + ERROR_LOG(VIDEO, "failed to create shared context"); return nullptr; - return context; + } + + std::unique_ptr new_context = std::make_unique(); + new_context->m_context = new_agl_context; + new_context->m_pixel_format = m_pixel_format; + [new_context->m_pixel_format retain]; + return new_context; } bool GLContextAGL::MakeCurrent() diff --git a/Source/Core/Common/GL/GLInterface/EGL.cpp b/Source/Core/Common/GL/GLInterface/EGL.cpp index eebe5e2e0e..534bf82ec5 100644 --- a/Source/Core/Common/GL/GLInterface/EGL.cpp +++ b/Source/Core/Common/GL/GLInterface/EGL.cpp @@ -289,43 +289,31 @@ bool GLContextEGL::Initialize(void* display_handle, void* window_handle, bool st std::unique_ptr GLContextEGL::CreateSharedContext() { - std::unique_ptr context = std::make_unique(); - if (!context->Initialize(this)) - return nullptr; - return context; -} - -bool GLContextEGL::Initialize(GLContext* main_context) -{ - GLContextEGL* egl_context = static_cast(main_context); - - m_opengl_mode = egl_context->m_opengl_mode; - m_host_display = egl_context->m_host_display; - m_egl_display = egl_context->m_egl_display; - m_is_core_context = egl_context->m_is_core_context; - m_config = egl_context->m_config; - m_supports_surfaceless = egl_context->m_supports_surfaceless; - m_is_shared = true; - - if (egl_context->GetMode() == Mode::OpenGL) - eglBindAPI(EGL_OPENGL_API); - else - eglBindAPI(EGL_OPENGL_ES_API); - - m_egl_context = eglCreateContext(m_egl_display, m_config, egl_context->m_egl_context, - egl_context->m_attribs.data()); - if (!m_egl_context) + eglBindAPI(m_opengl_mode == Mode::OpenGL ? EGL_OPENGL_API : EGL_OPENGL_ES_API); + EGLContext new_egl_context = + eglCreateContext(m_egl_display, m_config, m_egl_context, m_attribs.data()); + if (!new_egl_context) { INFO_LOG(VIDEO, "Error: eglCreateContext failed 0x%04x", eglGetError()); - return false; + return nullptr; } - if (!CreateWindowSurface()) + std::unique_ptr new_context = std::make_unique(); + new_context->m_opengl_mode = m_opengl_mode; + new_context->m_egl_context = new_egl_context; + new_context->m_host_display = m_host_display; + new_context->m_egl_display = m_egl_display; + new_context->m_is_core_context = m_is_core_context; + new_context->m_config = m_config; + new_context->m_supports_surfaceless = m_supports_surfaceless; + new_context->m_is_shared = true; + if (!new_context->CreateWindowSurface()) { ERROR_LOG(VIDEO, "Error: CreateWindowSurface failed 0x%04x", eglGetError()); - return false; + return nullptr; } - return true; + + return new_context; } bool GLContextEGL::CreateWindowSurface() diff --git a/Source/Core/Common/GL/GLInterface/EGL.h b/Source/Core/Common/GL/GLInterface/EGL.h index 52c183e21c..c20552f126 100644 --- a/Source/Core/Common/GL/GLInterface/EGL.h +++ b/Source/Core/Common/GL/GLInterface/EGL.h @@ -36,7 +36,6 @@ protected: virtual EGLNativeWindowType GetEGLNativeWindow(EGLConfig config); bool Initialize(void* display_handle, void* window_handle, bool stereo, bool core) override; - bool Initialize(GLContext* main_context) override; bool CreateWindowSurface(); void DestroyWindowSurface(); diff --git a/Source/Core/Common/GL/GLInterface/GLX.cpp b/Source/Core/Common/GL/GLInterface/GLX.cpp index c2569bd153..7a8e67f109 100644 --- a/Source/Core/Common/GL/GLInterface/GLX.cpp +++ b/Source/Core/Common/GL/GLInterface/GLX.cpp @@ -30,6 +30,11 @@ static int ctxErrorHandler(Display* dpy, XErrorEvent* ev) return 0; } +bool GLContextGLX::IsHeadless() const +{ + return m_render_window == nullptr; +} + void GLContextGLX::SwapInterval(int Interval) { if (!m_drawable) @@ -200,50 +205,38 @@ bool GLContextGLX::Initialize(void* display_handle, void* window_handle, bool st return true; } -bool GLContextGLX::Initialize(GLContext* main_context) +std::unique_ptr GLContextGLX::CreateSharedContext() { - GLContextGLX* glx_context = static_cast(main_context); - - m_opengl_mode = glx_context->m_opengl_mode; - m_supports_pbuffer = glx_context->m_supports_pbuffer; - m_display = glx_context->m_display; - m_fbconfig = glx_context->m_fbconfig; s_glxError = false; XErrorHandler oldHandler = XSetErrorHandler(&ctxErrorHandler); - m_context = glXCreateContextAttribs(m_display, m_fbconfig, glx_context->m_context, True, - &glx_context->m_attribs[0]); + GLXContext new_glx_context = + glXCreateContextAttribs(m_display, m_fbconfig, m_context, True, &m_attribs[0]); XSync(m_display, False); - if (!m_context || s_glxError) + if (!new_glx_context || s_glxError) { ERROR_LOG(VIDEO, "Unable to create GL context."); XSetErrorHandler(oldHandler); - return false; + return nullptr; } - if (m_supports_pbuffer && !CreateWindowSurface(None)) + std::unique_ptr new_context = std::make_unique(); + new_context->m_context = new_glx_context; + new_context->m_opengl_mode = m_opengl_mode; + new_context->m_supports_pbuffer = m_supports_pbuffer; + new_context->m_display = m_display; + new_context->m_fbconfig = m_fbconfig; + + if (m_supports_pbuffer && !new_context->CreateWindowSurface(None)) { - ERROR_LOG(VIDEO, "Error: CreateWindowSurface failed\n"); + ERROR_LOG(VIDEO, "Error: CreateWindowSurface failed"); XSetErrorHandler(oldHandler); - return false; + return nullptr; } XSetErrorHandler(oldHandler); - return true; -} - -bool GLContextGLX::IsHeadless() const -{ - return m_render_window == nullptr; -} - -std::unique_ptr GLContextGLX::CreateSharedContext() -{ - std::unique_ptr context = std::make_unique(); - if (!context->Initialize(this)) - return nullptr; - return context; + return new_context; } bool GLContextGLX::CreateWindowSurface(Window window_handle) diff --git a/Source/Core/Common/GL/GLInterface/GLX.h b/Source/Core/Common/GL/GLInterface/GLX.h index ef90e0ba5e..16443b706a 100644 --- a/Source/Core/Common/GL/GLInterface/GLX.h +++ b/Source/Core/Common/GL/GLInterface/GLX.h @@ -33,7 +33,6 @@ public: protected: bool Initialize(void* display_handle, void* window_handle, bool stereo, bool core) override; - bool Initialize(GLContext* main_context) override; Display* m_display = nullptr; std::unique_ptr m_render_window; diff --git a/Source/Core/Common/GL/GLInterface/WGL.cpp b/Source/Core/Common/GL/GLInterface/WGL.cpp index 6d1f072aee..032657cf69 100644 --- a/Source/Core/Common/GL/GLInterface/WGL.cpp +++ b/Source/Core/Common/GL/GLInterface/WGL.cpp @@ -306,34 +306,29 @@ bool GLContextWGL::Initialize(void* display_handle, void* window_handle, bool st return true; } -bool GLContextWGL::Initialize(GLContext* main_context) -{ - GLContextWGL* wgl_main_context = static_cast(main_context); - - m_opengl_mode = wgl_main_context->m_opengl_mode; - - // WGL does not support surfaceless contexts, so we use a 1x1 pbuffer instead. - if (!CreatePBuffer(wgl_main_context->m_dc, 1, 1, &m_pbuffer_handle, &m_dc)) - return false; - - m_rc = CreateCoreContext(m_dc, wgl_main_context->m_rc); - if (!m_rc) - return false; - - m_is_core_context = true; - return true; -} - std::unique_ptr GLContextWGL::CreateSharedContext() { - std::unique_ptr context = std::make_unique(); - if (!context->Initialize(this)) + // WGL does not support surfaceless contexts, so we use a 1x1 pbuffer instead. + HANDLE pbuffer; + HDC dc; + if (!CreatePBuffer(m_dc, 1, 1, &pbuffer, &dc)) + return nullptr; + + HGLRC rc = CreateCoreContext(dc, m_rc); + if (!rc) { - context->Shutdown(); + wglReleasePbufferDCARB(static_cast(pbuffer), dc); + wglDestroyPbufferARB(static_cast(pbuffer)); return nullptr; } - return std::move(context); + std::unique_ptr context = std::make_unique(); + context->m_pbuffer_handle = pbuffer; + context->m_dc = dc; + context->m_rc = rc; + context->m_opengl_mode = m_opengl_mode; + context->m_is_core_context = m_is_core_context; + return context; } HGLRC GLContextWGL::CreateCoreContext(HDC dc, HGLRC share_context) diff --git a/Source/Core/Common/GL/GLInterface/WGL.h b/Source/Core/Common/GL/GLInterface/WGL.h index e253a1accd..40d86ee6d0 100644 --- a/Source/Core/Common/GL/GLInterface/WGL.h +++ b/Source/Core/Common/GL/GLInterface/WGL.h @@ -28,7 +28,6 @@ public: protected: bool Initialize(void* display_handle, void* window_handle, bool stereo, bool core) override; - bool Initialize(GLContext* main_context) override; static HGLRC CreateCoreContext(HDC dc, HGLRC share_context); static bool CreatePBuffer(HDC onscreen_dc, int width, int height, HANDLE* pbuffer_handle, From 025e909773a2761cad8a3954498fe800f6f94963 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Wed, 3 Oct 2018 23:03:33 +1000 Subject: [PATCH 09/12] GLContext: Use destructor instead of Shutdown() to cleanup Also uses the Initialize() method to make the context current. --- Source/Core/Common/GL/GLContext.cpp | 4 -- Source/Core/Common/GL/GLContext.h | 5 +- Source/Core/Common/GL/GLInterface/AGL.h | 5 +- Source/Core/Common/GL/GLInterface/AGL.mm | 31 +++++--- Source/Core/Common/GL/GLInterface/EGL.cpp | 42 ++++++----- Source/Core/Common/GL/GLInterface/EGL.h | 10 +-- .../Core/Common/GL/GLInterface/EGLAndroid.h | 2 +- Source/Core/Common/GL/GLInterface/EGLX11.cpp | 8 ++- Source/Core/Common/GL/GLInterface/EGLX11.h | 2 +- Source/Core/Common/GL/GLInterface/GLX.cpp | 25 ++++--- Source/Core/Common/GL/GLInterface/GLX.h | 7 +- Source/Core/Common/GL/GLInterface/WGL.cpp | 72 +++++++++---------- Source/Core/Common/GL/GLInterface/WGL.h | 5 +- Source/Core/VideoBackends/OGL/Render.cpp | 6 +- Source/Core/VideoBackends/OGL/main.cpp | 1 - .../VideoBackends/Software/SWOGLWindow.cpp | 12 +--- 16 files changed, 122 insertions(+), 115 deletions(-) diff --git a/Source/Core/Common/GL/GLContext.cpp b/Source/Core/Common/GL/GLContext.cpp index 90cb833302..23f0255cd3 100644 --- a/Source/Core/Common/GL/GLContext.cpp +++ b/Source/Core/Common/GL/GLContext.cpp @@ -50,10 +50,6 @@ bool GLContext::ClearCurrent() return false; } -void GLContext::Shutdown() -{ -} - void GLContext::Update() { } diff --git a/Source/Core/Common/GL/GLContext.h b/Source/Core/Common/GL/GLContext.h index 48e261bae7..376999e0ac 100644 --- a/Source/Core/Common/GL/GLContext.h +++ b/Source/Core/Common/GL/GLContext.h @@ -31,7 +31,6 @@ public: virtual bool IsHeadless() const; virtual std::unique_ptr CreateSharedContext(); - virtual void Shutdown(); virtual bool MakeCurrent(); virtual bool ClearCurrent(); @@ -44,7 +43,8 @@ public: virtual void* GetFuncAddress(const std::string& name); - // Creates an instance of GLInterface specific to the platform we are running on. + // Creates an instance of GLContext specific to the platform we are running on. + // If successful, the context is made current on the calling thread. static std::unique_ptr Create(const WindowSystemInfo& wsi, bool stereo = false, bool core = true); @@ -56,6 +56,5 @@ protected: // Window dimensions. u32 m_backbuffer_width = 0; u32 m_backbuffer_height = 0; - bool m_is_core_context = false; bool m_is_shared = false; }; diff --git a/Source/Core/Common/GL/GLInterface/AGL.h b/Source/Core/Common/GL/GLInterface/AGL.h index 5e4052caa8..59d0116954 100644 --- a/Source/Core/Common/GL/GLInterface/AGL.h +++ b/Source/Core/Common/GL/GLInterface/AGL.h @@ -14,13 +14,14 @@ struct NSView; #include "Common/GL/GLContext.h" -class GLContextAGL : public GLContext +class GLContextAGL final : public GLContext { public: + ~GLContextAGL() override; + bool IsHeadless() const override; std::unique_ptr CreateSharedContext() override; - void Shutdown() override; bool MakeCurrent() override; bool ClearCurrent() override; diff --git a/Source/Core/Common/GL/GLInterface/AGL.mm b/Source/Core/Common/GL/GLInterface/AGL.mm index 2cd0cb7f60..7216946dae 100644 --- a/Source/Core/Common/GL/GLInterface/AGL.mm +++ b/Source/Core/Common/GL/GLInterface/AGL.mm @@ -43,6 +43,20 @@ static bool AttachContextToView(NSOpenGLContext* context, NSView* view, u32* wid return true; } +GLContextAGL::~GLContextAGL() +{ + if ([NSOpenGLContext currentContext] == m_context) + [NSOpenGLContext clearCurrentContext]; + + if (m_context) + { + [m_context clearDrawable]; + [m_context release]; + } + if (m_pixel_format) + [m_pixel_format release]; +} + bool GLContextAGL::IsHeadless() const { return !m_view; @@ -83,7 +97,11 @@ bool GLContextAGL::Initialize(void* display_handle, void* window_handle, bool st m_view = static_cast(window_handle); m_opengl_mode = Mode::OpenGL; - return AttachContextToView(m_context, m_view, &m_backbuffer_width, &m_backbuffer_height); + if (!AttachContextToView(m_context, m_view, &m_backbuffer_width, &m_backbuffer_height)) + return false; + + [m_context makeCurrentContext]; + return true; } std::unique_ptr GLContextAGL::CreateSharedContext() @@ -100,6 +118,7 @@ std::unique_ptr GLContextAGL::CreateSharedContext() new_context->m_context = new_agl_context; new_context->m_pixel_format = m_pixel_format; [new_context->m_pixel_format retain]; + new_context->m_is_shared = true; return new_context; } @@ -115,16 +134,6 @@ bool GLContextAGL::ClearCurrent() return true; } -// Close backend -void GLContextAGL::Shutdown() -{ - [m_context clearDrawable]; - [m_context release]; - m_context = nil; - [m_pixel_format release]; - m_pixel_format = nil; -} - void GLContextAGL::Update() { if (!m_view) diff --git a/Source/Core/Common/GL/GLInterface/EGL.cpp b/Source/Core/Common/GL/GLInterface/EGL.cpp index 534bf82ec5..4af719de40 100644 --- a/Source/Core/Common/GL/GLInterface/EGL.cpp +++ b/Source/Core/Common/GL/GLInterface/EGL.cpp @@ -28,7 +28,11 @@ #define EGL_OPENGL_ES3_BIT_KHR 0x00000040 #endif /* EGL_KHR_create_context */ -GLContextEGL::~GLContextEGL() = default; +GLContextEGL::~GLContextEGL() +{ + DestroyWindowSurface(); + DestroyContext(); +} bool GLContextEGL::IsHeadless() const { @@ -162,7 +166,6 @@ bool GLContextEGL::Initialize(void* display_handle, void* window_handle, bool st m_host_display = display_handle; m_host_window = window_handle; m_egl_display = OpenEGLDisplay(); - m_is_core_context = core; if (!m_egl_display) { @@ -268,7 +271,6 @@ bool GLContextEGL::Initialize(void* display_handle, void* window_handle, bool st if (!m_egl_context) { - m_is_core_context = false; m_egl_context = eglCreateContext(m_egl_display, m_config, EGL_NO_CONTEXT, &ctx_attribs[0]); m_attribs = std::move(ctx_attribs); } @@ -284,7 +286,8 @@ bool GLContextEGL::Initialize(void* display_handle, void* window_handle, bool st ERROR_LOG(VIDEO, "Error: CreateWindowSurface failed 0x%04x", eglGetError()); return false; } - return true; + + return MakeCurrent(); } std::unique_ptr GLContextEGL::CreateSharedContext() @@ -303,7 +306,6 @@ std::unique_ptr GLContextEGL::CreateSharedContext() new_context->m_egl_context = new_egl_context; new_context->m_host_display = m_host_display; new_context->m_egl_display = m_egl_display; - new_context->m_is_core_context = m_is_core_context; new_context->m_config = m_config; new_context->m_supports_surfaceless = m_supports_surfaceless; new_context->m_is_shared = true; @@ -349,7 +351,12 @@ bool GLContextEGL::CreateWindowSurface() void GLContextEGL::DestroyWindowSurface() { - if (m_egl_surface != EGL_NO_SURFACE && !eglDestroySurface(m_egl_display, m_egl_surface)) + if (m_egl_surface == EGL_NO_SURFACE) + return; + + if (eglGetCurrentSurface(EGL_DRAW) == m_egl_surface) + eglMakeCurrent(m_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + if (!eglDestroySurface(m_egl_display, m_egl_surface)) NOTICE_LOG(VIDEO, "Could not destroy window surface."); m_egl_surface = EGL_NO_SURFACE; } @@ -374,18 +381,17 @@ bool GLContextEGL::ClearCurrent() } // Close backend -void GLContextEGL::Shutdown() +void GLContextEGL::DestroyContext() { - if (m_egl_context) - { - if (!eglMakeCurrent(m_egl_display, m_egl_surface, m_egl_surface, m_egl_context)) - NOTICE_LOG(VIDEO, "Could not release drawing context."); + if (!m_egl_context) + return; + + if (eglGetCurrentContext() == m_egl_context) eglMakeCurrent(m_egl_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - if (!eglDestroyContext(m_egl_display, m_egl_context)) - NOTICE_LOG(VIDEO, "Could not destroy drawing context."); - DestroyWindowSurface(); - if (!m_is_shared && !eglTerminate(m_egl_display)) - NOTICE_LOG(VIDEO, "Could not destroy display connection."); - m_egl_context = nullptr; - } + if (!eglDestroyContext(m_egl_display, m_egl_context)) + NOTICE_LOG(VIDEO, "Could not destroy drawing context."); + if (!m_is_shared && !eglTerminate(m_egl_display)) + NOTICE_LOG(VIDEO, "Could not destroy display connection."); + m_egl_context = EGL_NO_CONTEXT; + m_egl_display = EGL_NO_DISPLAY; } diff --git a/Source/Core/Common/GL/GLInterface/EGL.h b/Source/Core/Common/GL/GLInterface/EGL.h index c20552f126..51dd3fda35 100644 --- a/Source/Core/Common/GL/GLInterface/EGL.h +++ b/Source/Core/Common/GL/GLInterface/EGL.h @@ -14,12 +14,11 @@ class GLContextEGL : public GLContext { public: - virtual ~GLContextEGL(); + virtual ~GLContextEGL() override; bool IsHeadless() const override; std::unique_ptr CreateSharedContext() override; - virtual void Shutdown() override; bool MakeCurrent() override; bool ClearCurrent() override; @@ -40,6 +39,7 @@ protected: bool CreateWindowSurface(); void DestroyWindowSurface(); void DetectMode(bool has_handle); + void DestroyContext(); void* m_host_display = nullptr; void* m_host_window = nullptr; @@ -48,7 +48,7 @@ protected: bool m_supports_surfaceless = false; std::vector m_attribs; - EGLSurface m_egl_surface; - EGLContext m_egl_context; - EGLDisplay m_egl_display; + EGLSurface m_egl_surface = EGL_NO_SURFACE; + EGLContext m_egl_context = EGL_NO_CONTEXT; + EGLDisplay m_egl_display = EGL_NO_DISPLAY; }; diff --git a/Source/Core/Common/GL/GLInterface/EGLAndroid.h b/Source/Core/Common/GL/GLInterface/EGLAndroid.h index 0139bae91c..f743f2fb32 100644 --- a/Source/Core/Common/GL/GLInterface/EGLAndroid.h +++ b/Source/Core/Common/GL/GLInterface/EGLAndroid.h @@ -6,7 +6,7 @@ #include "Common/GL/GLInterface/EGL.h" -class GLContextEGLAndroid : public GLContextEGL +class GLContextEGLAndroid final : public GLContextEGL { protected: EGLDisplay OpenEGLDisplay() override; diff --git a/Source/Core/Common/GL/GLInterface/EGLX11.cpp b/Source/Core/Common/GL/GLInterface/EGLX11.cpp index bc87769440..bd59033738 100644 --- a/Source/Core/Common/GL/GLInterface/EGLX11.cpp +++ b/Source/Core/Common/GL/GLInterface/EGLX11.cpp @@ -4,7 +4,13 @@ #include "Common/GL/GLInterface/EGLX11.h" -GLContextEGLX11::~GLContextEGLX11() = default; +GLContextEGLX11::~GLContextEGLX11() +{ + // The context must be destroyed before the window. + DestroyWindowSurface(); + DestroyContext(); + m_render_window.reset(); +} void GLContextEGLX11::Update() { diff --git a/Source/Core/Common/GL/GLInterface/EGLX11.h b/Source/Core/Common/GL/GLInterface/EGLX11.h index 6254d7ca0a..f4be040fae 100644 --- a/Source/Core/Common/GL/GLInterface/EGLX11.h +++ b/Source/Core/Common/GL/GLInterface/EGLX11.h @@ -9,7 +9,7 @@ #include "Common/GL/GLInterface/EGL.h" #include "Common/GL/GLX11Window.h" -class GLContextEGLX11 : public GLContextEGL +class GLContextEGLX11 final : public GLContextEGL { public: ~GLContextEGLX11() override; diff --git a/Source/Core/Common/GL/GLInterface/GLX.cpp b/Source/Core/Common/GL/GLInterface/GLX.cpp index 7a8e67f109..d74bccf8a4 100644 --- a/Source/Core/Common/GL/GLInterface/GLX.cpp +++ b/Source/Core/Common/GL/GLInterface/GLX.cpp @@ -30,9 +30,21 @@ static int ctxErrorHandler(Display* dpy, XErrorEvent* ev) return 0; } +GLContextGLX::~GLContextGLX() +{ + DestroyWindowSurface(); + if (m_context) + { + if (glXGetCurrentContext() == m_context) + glXMakeCurrent(m_display, None, nullptr); + + glXDestroyContext(m_display, m_context); + } +} + bool GLContextGLX::IsHeadless() const { - return m_render_window == nullptr; + return !m_render_window; } void GLContextGLX::SwapInterval(int Interval) @@ -202,7 +214,7 @@ bool GLContextGLX::Initialize(void* display_handle, void* window_handle, bool st XSetErrorHandler(oldHandler); m_opengl_mode = Mode::OpenGL; - return true; + return MakeCurrent(); } std::unique_ptr GLContextGLX::CreateSharedContext() @@ -227,6 +239,7 @@ std::unique_ptr GLContextGLX::CreateSharedContext() new_context->m_supports_pbuffer = m_supports_pbuffer; new_context->m_display = m_display; new_context->m_fbconfig = m_fbconfig; + new_context->m_is_shared = true; if (m_supports_pbuffer && !new_context->CreateWindowSurface(None)) { @@ -286,14 +299,6 @@ bool GLContextGLX::ClearCurrent() return glXMakeCurrent(m_display, None, nullptr); } -// Close backend -void GLContextGLX::Shutdown() -{ - DestroyWindowSurface(); - if (m_context) - glXDestroyContext(m_display, m_context); -} - void GLContextGLX::Update() { m_render_window->UpdateDimensions(); diff --git a/Source/Core/Common/GL/GLInterface/GLX.h b/Source/Core/Common/GL/GLInterface/GLX.h index 16443b706a..1b74e53f60 100644 --- a/Source/Core/Common/GL/GLInterface/GLX.h +++ b/Source/Core/Common/GL/GLInterface/GLX.h @@ -13,13 +13,14 @@ #include "Common/GL/GLContext.h" #include "Common/GL/GLX11Window.h" -class GLContextGLX : public GLContext +class GLContextGLX final : public GLContext { public: + ~GLContextGLX() override; + bool IsHeadless() const override; std::unique_ptr CreateSharedContext() override; - void Shutdown() override; bool MakeCurrent() override; bool ClearCurrent() override; @@ -38,7 +39,7 @@ protected: std::unique_ptr m_render_window; GLXDrawable m_drawable = {}; - GLXContext m_context = {}; + GLXContext m_context = nullptr; GLXFBConfig m_fbconfig = {}; bool m_supports_pbuffer = false; GLXPbufferSGIX m_pbuffer = 0; diff --git a/Source/Core/Common/GL/GLInterface/WGL.cpp b/Source/Core/Common/GL/GLInterface/WGL.cpp index 032657cf69..98b6bd5a3a 100644 --- a/Source/Core/Common/GL/GLInterface/WGL.cpp +++ b/Source/Core/Common/GL/GLInterface/WGL.cpp @@ -157,6 +157,39 @@ static void ClearWGLExtensionPointers() wglDestroyPbufferARB = nullptr; } +GLContextWGL::~GLContextWGL() +{ + if (m_rc) + { + if (wglGetCurrentContext() == m_rc && !wglMakeCurrent(m_dc, nullptr)) + NOTICE_LOG(VIDEO, "Could not release drawing context."); + + if (!wglDeleteContext(m_rc)) + ERROR_LOG(VIDEO, "Attempt to release rendering context failed."); + + m_rc = nullptr; + } + + if (m_dc) + { + if (m_pbuffer_handle) + { + wglReleasePbufferDCARB(static_cast(m_pbuffer_handle), m_dc); + m_dc = nullptr; + + wglDestroyPbufferARB(static_cast(m_pbuffer_handle)); + m_pbuffer_handle = nullptr; + } + else + { + if (!ReleaseDC(m_window_handle, m_dc)) + ERROR_LOG(VIDEO, "Attempt to release device context failed."); + + m_dc = nullptr; + } + } +} + bool GLContextWGL::IsHeadless() const { return !m_window_handle; @@ -295,7 +328,6 @@ bool GLContextWGL::Initialize(void* display_handle, void* window_handle, bool st { wglDeleteContext(m_rc); m_rc = core_context; - m_is_core_context = true; } else { @@ -303,7 +335,7 @@ bool GLContextWGL::Initialize(void* display_handle, void* window_handle, bool st } } - return true; + return MakeCurrent(); } std::unique_ptr GLContextWGL::CreateSharedContext() @@ -327,7 +359,7 @@ std::unique_ptr GLContextWGL::CreateSharedContext() context->m_dc = dc; context->m_rc = rc; context->m_opengl_mode = m_opengl_mode; - context->m_is_core_context = m_is_core_context; + context->m_is_shared = true; return context; } @@ -468,37 +500,3 @@ void GLContextWGL::Update() m_backbuffer_width = rcWindow.right - rcWindow.left; m_backbuffer_height = rcWindow.bottom - rcWindow.top; } - -// Close backend -void GLContextWGL::Shutdown() -{ - if (m_rc) - { - if (!wglMakeCurrent(m_dc, nullptr)) - NOTICE_LOG(VIDEO, "Could not release drawing context."); - - if (!wglDeleteContext(m_rc)) - ERROR_LOG(VIDEO, "Attempt to release rendering context failed."); - - m_rc = nullptr; - } - - if (m_dc) - { - if (m_pbuffer_handle) - { - wglReleasePbufferDCARB(static_cast(m_pbuffer_handle), m_dc); - m_dc = nullptr; - - wglDestroyPbufferARB(static_cast(m_pbuffer_handle)); - m_pbuffer_handle = nullptr; - } - else - { - if (!ReleaseDC(m_window_handle, m_dc)) - ERROR_LOG(VIDEO, "Attempt to release device context failed."); - - m_dc = nullptr; - } - } -} diff --git a/Source/Core/Common/GL/GLInterface/WGL.h b/Source/Core/Common/GL/GLInterface/WGL.h index 40d86ee6d0..9e3f9d86ef 100644 --- a/Source/Core/Common/GL/GLInterface/WGL.h +++ b/Source/Core/Common/GL/GLInterface/WGL.h @@ -8,16 +8,17 @@ #include #include "Common/GL/GLContext.h" -class GLContextWGL : public GLContext +class GLContextWGL final : public GLContext { public: + ~GLContextWGL(); + bool IsHeadless() const; std::unique_ptr CreateSharedContext() override; bool MakeCurrent() override; bool ClearCurrent() override; - void Shutdown() override; void Update() override; diff --git a/Source/Core/VideoBackends/OGL/Render.cpp b/Source/Core/VideoBackends/OGL/Render.cpp index b28df12c6a..360d4c2dcc 100644 --- a/Source/Core/VideoBackends/OGL/Render.cpp +++ b/Source/Core/VideoBackends/OGL/Render.cpp @@ -803,11 +803,7 @@ Renderer::Renderer(std::unique_ptr main_gl_context) ClearEFBCache(); } -Renderer::~Renderer() -{ - m_main_gl_context->ClearCurrent(); - m_main_gl_context->Shutdown(); -} +Renderer::~Renderer() = default; bool Renderer::IsHeadless() const { diff --git a/Source/Core/VideoBackends/OGL/main.cpp b/Source/Core/VideoBackends/OGL/main.cpp index 2c38986aa9..e087c39462 100644 --- a/Source/Core/VideoBackends/OGL/main.cpp +++ b/Source/Core/VideoBackends/OGL/main.cpp @@ -166,7 +166,6 @@ bool VideoBackend::Initialize(const WindowSystemInfo& wsi) if (!main_gl_context) return false; - main_gl_context->MakeCurrent(); if (!InitializeGLExtensions(main_gl_context.get()) || !FillBackendInfo()) return false; diff --git a/Source/Core/VideoBackends/Software/SWOGLWindow.cpp b/Source/Core/VideoBackends/Software/SWOGLWindow.cpp index 4936d1a13c..81216ff7ef 100644 --- a/Source/Core/VideoBackends/Software/SWOGLWindow.cpp +++ b/Source/Core/VideoBackends/Software/SWOGLWindow.cpp @@ -13,15 +13,7 @@ #include "VideoBackends/Software/SWTexture.h" SWOGLWindow::SWOGLWindow() = default; - -SWOGLWindow::~SWOGLWindow() -{ - if (m_gl_context) - { - m_gl_context->ClearCurrent(); - m_gl_context->Shutdown(); - } -} +SWOGLWindow::~SWOGLWindow() = default; std::unique_ptr SWOGLWindow::Create(const WindowSystemInfo& wsi) { @@ -46,8 +38,6 @@ bool SWOGLWindow::Initialize(const WindowSystemInfo& wsi) if (!m_gl_context) return false; - m_gl_context->MakeCurrent(); - // Init extension support. if (!GLExtensions::Init(m_gl_context.get())) { From 0559311f929d62904c6f14c67d3944fb4142aaaf Mon Sep 17 00:00:00 2001 From: Stenzek Date: Wed, 3 Oct 2018 23:03:36 +1000 Subject: [PATCH 10/12] GLContext: Runtime selection of EGL/GLX on Linux --- CMakeLists.txt | 48 ++++++----------------- Source/Core/Common/CMakeLists.txt | 23 +++++------ Source/Core/Common/GL/GLContext.cpp | 42 ++++++++++---------- Source/Core/Common/GL/GLContext.h | 3 +- Source/Core/Common/GL/GLInterface/EGL.cpp | 26 +++--------- Source/Core/UICommon/CMakeLists.txt | 4 +- Source/Core/VideoBackends/OGL/main.cpp | 5 ++- 7 files changed, 61 insertions(+), 90 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3b336a88cb..69440d0c52 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,8 +16,13 @@ project(dolphin-emu) # unique name here. set(DISTRIBUTOR "None" CACHE STRING "Name of the distributor.") -option(USE_EGL "Enables EGL OpenGL Interface" OFF) -option(TRY_X11 "Enables X11 Support" ON) +if(UNIX AND NOT APPLE AND NOT ANDROID) + option(ENABLE_X11 "Enables X11 Support" ON) +endif() +if(NOT WIN32 AND NOT APPLE) + option(ENABLE_EGL "Enables EGL OpenGL Interface" ON) +endif() + option(USE_SHARED_ENET "Use shared libenet if found rather than Dolphin's soon-to-compatibly-diverge version" OFF) option(USE_UPNP "Enables UPnP port mapping support" ON) option(ENABLE_QT "Enable Qt (Default)" ON) @@ -365,9 +370,7 @@ if(ANDROID) # but not as a shared library. We want an executable. set(ANDROID 0) endif() - set(USE_X11 0) set(USE_UPNP 0) - set(USE_EGL 1) set(ENABLE_QT 0) set(USE_DISCORD_PRESENCE 0) @@ -379,13 +382,7 @@ if(ANDROID) endif() if(ENABLE_HEADLESS) - if(APPLE) - message(STATUS "Enabling Headless! Disabling GUI.") - else() - message(STATUS "Enabling Headless! Disabling GUI, force enabling EGL!") - set(USE_EGL 1) - endif() - set(USE_X11 0) + message(STATUS "Enabling Headless! Disabling GUI.") set(ENABLE_QT 0) set(USE_DISCORD_PRESENCE 0) add_definitions(-DUSE_HEADLESS) @@ -416,30 +413,11 @@ if (OPENGL_GL) include_directories(${OPENGL_INCLUDE_DIR}) endif() -set(USE_X11 0) +if(ENABLE_X11) + find_package(X11 REQUIRED) + add_definitions(-DHAVE_X11=1) + message(STATUS "X11 support enabled") -if(UNIX AND NOT APPLE AND NOT ANDROID AND NOT ENABLE_HEADLESS) - find_package(X11) - if(TRY_X11 AND X11_FOUND) - set(USE_X11 1) - add_definitions(-DHAVE_X11=1) - include_directories(${X11_INCLUDE_DIR}) - message(STATUS "X11 support enabled") - else() - set(USE_X11 0) - SET(X11_FOUND "") - message(STATUS "X11 support disabled") - add_definitions(-DHAVE_X11=0) - endif() - - if (NOT USE_X11) - message(FATAL_ERROR "\n" - "No suitable display platform found\n" - "Requires x11 to run") - endif() -endif() - -if(USE_X11) check_lib(XRANDR xrandr Xrandr) if(XRANDR_FOUND) add_definitions(-DHAVE_XRANDR=1) @@ -473,7 +451,7 @@ if(OPROFILING) endif() endif() -if(USE_EGL) +if(ENABLE_EGL) message(STATUS "EGL OpenGL interface enabled") add_definitions(-DUSE_EGL=1) endif() diff --git a/Source/Core/Common/CMakeLists.txt b/Source/Core/Common/CMakeLists.txt index f6430c04f3..62fbb9d0d3 100644 --- a/Source/Core/Common/CMakeLists.txt +++ b/Source/Core/Common/CMakeLists.txt @@ -113,12 +113,10 @@ target_sources(common PRIVATE GL/GLContext.cpp ) -if(USE_EGL) +if(ENABLE_EGL) target_sources(common PRIVATE GL/GLInterface/EGL.cpp) if(ANDROID) target_sources(common PRIVATE GL/GLInterface/EGLAndroid.cpp) - elseif(USE_X11) - target_sources(common PRIVATE GL/GLInterface/EGLX11.cpp) endif() target_link_libraries(common PUBLIC EGL) endif() @@ -130,15 +128,18 @@ if(WIN32) ) elseif(APPLE) target_sources(common PRIVATE GL/GLInterface/AGL.mm) -elseif(USE_X11) - if (NOT USE_EGL) - target_sources(common PRIVATE GL/GLInterface/GLX.cpp) - # GLX has a hard dependency on libGL. - # Make sure to link to it if using GLX. - target_link_libraries(common PUBLIC ${OPENGL_LIBRARIES}) +elseif(ENABLE_X11) + target_sources(common PRIVATE + GL/GLX11Window.cpp + GL/GLInterface/GLX.cpp) + + # GLX has a hard dependency on libGL. + # Make sure to link to it if using GLX. + target_link_libraries(common PUBLIC ${OPENGL_LIBRARIES}) + + if (ENABLE_EGL) + target_sources(common PRIVATE GL/GLInterface/EGLX11.cpp) endif() - target_sources(common PRIVATE GL/GLX11Window.cpp) - target_link_libraries(common PUBLIC ${XRANDR_LIBRARIES}) endif() if(CMAKE_SYSTEM_NAME STREQUAL "Linux") diff --git a/Source/Core/Common/GL/GLContext.cpp b/Source/Core/Common/GL/GLContext.cpp index 23f0255cd3..81bf4e12b6 100644 --- a/Source/Core/Common/GL/GLContext.cpp +++ b/Source/Core/Common/GL/GLContext.cpp @@ -10,17 +10,13 @@ #include "Common/GL/GLInterface/AGL.h" #elif defined(_WIN32) #include "Common/GL/GLInterface/WGL.h" -#elif HAVE_X11 -#if defined(USE_EGL) && USE_EGL -#include "Common/GL/GLInterface/EGLX11.h" -#else -#include "Common/GL/GLInterface/GLX.h" -#endif -#elif defined(USE_EGL) && USE_EGL && defined(USE_HEADLESS) -#include "Common/GL/GLInterface/EGL.h" -#elif ANDROID +#elif defined(ANDROID) #include "Common/GL/GLInterface/EGLAndroid.h" -#error Platform doesnt have a GLInterface +#elif HAVE_X11 +#include "Common/GL/GLInterface/EGLX11.h" +#include "Common/GL/GLInterface/GLX.h" +#elif HAVE_EGL +#include "Common/GL/GLInterface/EGL.h" #endif GLContext::~GLContext() = default; @@ -71,26 +67,32 @@ void* GLContext::GetFuncAddress(const std::string& name) return nullptr; } -std::unique_ptr GLContext::Create(const WindowSystemInfo& wsi, bool stereo, bool core) +std::unique_ptr GLContext::Create(const WindowSystemInfo& wsi, bool stereo, bool core, + bool prefer_egl, bool prefer_gles) { std::unique_ptr context; #if defined(__APPLE__) context = std::make_unique(); #elif defined(_WIN32) context = std::make_unique(); -#elif defined(USE_EGL) && defined(USE_HEADLESS) - context = std::make_unique(); -#elif defined(HAVE_X11) && HAVE_X11 -#if defined(USE_EGL) && USE_EGL - context = std::make_unique(); -#else - context = std::make_unique(); -#endif -#elif ANDROID +#elif defined(ANDROID) context = std::make_unique(); +#elif HAVE_X11 + // GLES is not supported via GLX? + if (prefer_egl || prefer_gles) + context = std::make_unique(); + else + context = std::make_unique(); +#elif HAVE_EGL + context = std::make_unique(); #else return nullptr; #endif + + // Option to prefer GLES on desktop platforms, useful for testing. + if (prefer_gles) + context->m_opengl_mode = Mode::OpenGLES; + if (!context->Initialize(wsi.display_connection, wsi.render_surface, stereo, core)) return nullptr; diff --git a/Source/Core/Common/GL/GLContext.h b/Source/Core/Common/GL/GLContext.h index 376999e0ac..d4854a21cf 100644 --- a/Source/Core/Common/GL/GLContext.h +++ b/Source/Core/Common/GL/GLContext.h @@ -46,7 +46,8 @@ public: // Creates an instance of GLContext specific to the platform we are running on. // If successful, the context is made current on the calling thread. static std::unique_ptr Create(const WindowSystemInfo& wsi, bool stereo = false, - bool core = true); + bool core = true, bool prefer_egl = false, + bool prefer_gles = false); protected: virtual bool Initialize(void* display_handle, void* window_handle, bool stereo, bool core); diff --git a/Source/Core/Common/GL/GLInterface/EGL.cpp b/Source/Core/Common/GL/GLInterface/EGL.cpp index 4af719de40..b472d2b984 100644 --- a/Source/Core/Common/GL/GLInterface/EGL.cpp +++ b/Source/Core/Common/GL/GLInterface/EGL.cpp @@ -9,7 +9,6 @@ #include "Common/GL/GLInterface/EGL.h" #include "Common/Logging/Log.h" -#include "Core/Config/GraphicsSettings.h" #ifndef EGL_KHR_create_context #define EGL_KHR_create_context 1 @@ -56,8 +55,6 @@ void* GLContextEGL::GetFuncAddress(const std::string& name) void GLContextEGL::DetectMode(bool has_handle) { - bool preferGLES = Config::Get(Config::GFX_PREFER_GLES); - EGLint num_configs; bool supportsGL = false, supportsGLES3 = false; std::array renderable_types{{EGL_OPENGL_BIT, EGL_OPENGL_ES3_BIT_KHR}}; @@ -111,30 +108,17 @@ void GLContextEGL::DetectMode(bool has_handle) delete[] config; } - if (preferGLES) - { - if (supportsGLES3) - m_opengl_mode = Mode::OpenGLES; - else if (supportsGL) - m_opengl_mode = Mode::OpenGL; - } - else - { - if (supportsGL) - m_opengl_mode = Mode::OpenGL; - else if (supportsGLES3) - m_opengl_mode = Mode::OpenGLES; - } - - if (m_opengl_mode == Mode::OpenGL) + if (supportsGL) { INFO_LOG(VIDEO, "Using OpenGL"); + m_opengl_mode = Mode::OpenGL; } - else if (m_opengl_mode == Mode::OpenGLES) + else if (supportsGLES3) { INFO_LOG(VIDEO, "Using OpenGL|ES"); + m_opengl_mode = Mode::OpenGLES; } - else if (m_opengl_mode == Mode::Detect) + else { // Errored before we found a mode ERROR_LOG(VIDEO, "Error: Failed to detect OpenGL flavour, falling back to OpenGL"); diff --git a/Source/Core/UICommon/CMakeLists.txt b/Source/Core/UICommon/CMakeLists.txt index 6e5efecaff..5956031531 100644 --- a/Source/Core/UICommon/CMakeLists.txt +++ b/Source/Core/UICommon/CMakeLists.txt @@ -24,8 +24,10 @@ if ((DEFINED CMAKE_ANDROID_ARCH_ABI AND CMAKE_ANDROID_ARCH_ABI MATCHES "x86|x86_ target_link_libraries(uicommon PRIVATE bdisasm) endif() -if(USE_X11) +if(ENABLE_X11) + target_include_directories(uicommon PRIVATE ${X11_INCLUDE_DIR}) target_sources(uicommon PRIVATE X11Utils.cpp) + target_link_libraries(uicommon PUBLIC ${XRANDR_LIBRARIES}) endif() if(LIBUSB_FOUND) diff --git a/Source/Core/VideoBackends/OGL/main.cpp b/Source/Core/VideoBackends/OGL/main.cpp index e087c39462..bc67b716cc 100644 --- a/Source/Core/VideoBackends/OGL/main.cpp +++ b/Source/Core/VideoBackends/OGL/main.cpp @@ -43,6 +43,8 @@ Make AA apply instantly during gameplay if possible #include "Common/GL/GLUtil.h" #include "Common/MsgHandler.h" +#include "Core/Config/GraphicsSettings.h" + #include "VideoBackends/OGL/BoundingBox.h" #include "VideoBackends/OGL/PerfQuery.h" #include "VideoBackends/OGL/ProgramShaderCache.h" @@ -162,7 +164,8 @@ bool VideoBackend::Initialize(const WindowSystemInfo& wsi) InitializeShared(); std::unique_ptr main_gl_context = - GLContext::Create(wsi, g_ActiveConfig.stereo_mode == StereoMode::QuadBuffer); + GLContext::Create(wsi, g_ActiveConfig.stereo_mode == StereoMode::QuadBuffer, true, false, + Config::Get(Config::GFX_PREFER_GLES)); if (!main_gl_context) return false; From c95802afeb2ebc702bed61a9437f6e85e4f833e0 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sun, 14 Oct 2018 23:17:31 +1000 Subject: [PATCH 11/12] CMake: Make X11 and EGL optional --- CMake/FindEGL.cmake | 54 ++++++++++++++++++++++++ CMakeLists.txt | 35 +++++++++------- Source/Core/Common/CMakeLists.txt | 13 +++--- Source/Core/Common/GL/GLContext.cpp | 65 +++++++++++++++++++---------- Source/Core/UICommon/CMakeLists.txt | 2 +- 5 files changed, 126 insertions(+), 43 deletions(-) create mode 100644 CMake/FindEGL.cmake diff --git a/CMake/FindEGL.cmake b/CMake/FindEGL.cmake new file mode 100644 index 0000000000..dd7a8bcff0 --- /dev/null +++ b/CMake/FindEGL.cmake @@ -0,0 +1,54 @@ +# from https://raw.githubusercontent.com/WebKit/webkit/master/Source/cmake/FindEGL.cmake +# - Try to Find EGL +# Once done, this will define +# +# EGL_FOUND - system has EGL installed. +# EGL_INCLUDE_DIRS - directories which contain the EGL headers. +# EGL_LIBRARIES - libraries required to link against EGL. +# EGL_DEFINITIONS - Compiler switches required for using EGL. +# +# Copyright (C) 2012 Intel Corporation. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND ITS CONTRIBUTORS ``AS +# IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR ITS +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +find_package(PkgConfig) + +pkg_check_modules(PC_EGL egl) + +if (PC_EGL_FOUND) + set(EGL_DEFINITIONS ${PC_EGL_CFLAGS_OTHER}) +endif () + +find_path(EGL_INCLUDE_DIRS NAMES EGL/egl.h + HINTS ${PC_EGL_INCLUDEDIR} ${PC_EGL_INCLUDE_DIRS} +) + +set(EGL_NAMES ${EGL_NAMES} egl EGL) +find_library(EGL_LIBRARIES NAMES ${EGL_NAMES} + HINTS ${PC_EGL_LIBDIR} ${PC_EGL_LIBRARY_DIRS} +) + +include(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(EGL DEFAULT_MSG EGL_INCLUDE_DIRS EGL_LIBRARIES) + +mark_as_advanced(EGL_INCLUDE_DIRS EGL_LIBRARIES) diff --git a/CMakeLists.txt b/CMakeLists.txt index 69440d0c52..e69edabddc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -414,18 +414,30 @@ if (OPENGL_GL) endif() if(ENABLE_X11) - find_package(X11 REQUIRED) - add_definitions(-DHAVE_X11=1) - message(STATUS "X11 support enabled") - - check_lib(XRANDR xrandr Xrandr) - if(XRANDR_FOUND) - add_definitions(-DHAVE_XRANDR=1) + find_package(X11) + if(X11_FOUND) + add_definitions(-DHAVE_X11=1) + check_lib(XRANDR xrandr Xrandr) + if(XRANDR_FOUND) + add_definitions(-DHAVE_XRANDR=1) + else() + add_definitions(-DHAVE_XRANDR=0) + endif() + pkg_check_modules(X11_INPUT REQUIRED xi>=1.5.0) + message(STATUS "X11 support enabled") else() - add_definitions(-DHAVE_XRANDR=0) + message(WARNING "X11 support enabled but not found. This build will not support X11.") endif() +endif() - pkg_check_modules(X11_INPUT REQUIRED xi>=1.5.0) +if(ENABLE_EGL) + find_package(EGL) + if(EGL_FOUND) + add_definitions(-DHAVE_EGL=1) + message(STATUS "EGL OpenGL interface enabled") + else() + message(WARNING "EGL support enabled but not found. This build will not support EGL.") + endif() endif() if(ENCODE_FRAMEDUMPS) @@ -451,11 +463,6 @@ if(OPROFILING) endif() endif() -if(ENABLE_EGL) - message(STATUS "EGL OpenGL interface enabled") - add_definitions(-DUSE_EGL=1) -endif() - if(ENABLE_EVDEV) find_package(Libudev REQUIRED) find_package(Libevdev REQUIRED) diff --git a/Source/Core/Common/CMakeLists.txt b/Source/Core/Common/CMakeLists.txt index 62fbb9d0d3..b75c88d013 100644 --- a/Source/Core/Common/CMakeLists.txt +++ b/Source/Core/Common/CMakeLists.txt @@ -113,12 +113,15 @@ target_sources(common PRIVATE GL/GLContext.cpp ) -if(ENABLE_EGL) +if(ENABLE_EGL AND EGL_FOUND) target_sources(common PRIVATE GL/GLInterface/EGL.cpp) if(ANDROID) target_sources(common PRIVATE GL/GLInterface/EGLAndroid.cpp) + elseif(ENABLE_X11 AND X11_FOUND) + target_sources(common PRIVATE GL/GLInterface/EGLX11.cpp) endif() - target_link_libraries(common PUBLIC EGL) + target_include_directories(common PRIVATE ${EGL_INCLUDE_DIRS}) + target_link_libraries(common PUBLIC ${EGL_LIBRARIES}) endif() if(WIN32) @@ -128,7 +131,7 @@ if(WIN32) ) elseif(APPLE) target_sources(common PRIVATE GL/GLInterface/AGL.mm) -elseif(ENABLE_X11) +elseif(ENABLE_X11 AND X11_FOUND) target_sources(common PRIVATE GL/GLX11Window.cpp GL/GLInterface/GLX.cpp) @@ -136,10 +139,6 @@ elseif(ENABLE_X11) # GLX has a hard dependency on libGL. # Make sure to link to it if using GLX. target_link_libraries(common PUBLIC ${OPENGL_LIBRARIES}) - - if (ENABLE_EGL) - target_sources(common PRIVATE GL/GLInterface/EGLX11.cpp) - endif() endif() if(CMAKE_SYSTEM_NAME STREQUAL "Linux") diff --git a/Source/Core/Common/GL/GLContext.cpp b/Source/Core/Common/GL/GLContext.cpp index 81bf4e12b6..d4a9ed2e7a 100644 --- a/Source/Core/Common/GL/GLContext.cpp +++ b/Source/Core/Common/GL/GLContext.cpp @@ -8,15 +8,21 @@ #if defined(__APPLE__) #include "Common/GL/GLInterface/AGL.h" -#elif defined(_WIN32) +#endif +#if defined(WIN32) #include "Common/GL/GLInterface/WGL.h" -#elif defined(ANDROID) -#include "Common/GL/GLInterface/EGLAndroid.h" -#elif HAVE_X11 -#include "Common/GL/GLInterface/EGLX11.h" +#endif +#if HAVE_X11 #include "Common/GL/GLInterface/GLX.h" -#elif HAVE_EGL +#endif +#if HAVE_EGL #include "Common/GL/GLInterface/EGL.h" +#if HAVE_X11 +#include "Common/GL/GLInterface/EGLX11.h" +#endif +#if defined(ANDROID) +#include "Common/GL/GLInterface/EGLAndroid.h" +#endif #endif GLContext::~GLContext() = default; @@ -72,22 +78,39 @@ std::unique_ptr GLContext::Create(const WindowSystemInfo& wsi, bool s { std::unique_ptr context; #if defined(__APPLE__) - context = std::make_unique(); -#elif defined(_WIN32) - context = std::make_unique(); -#elif defined(ANDROID) - context = std::make_unique(); -#elif HAVE_X11 - // GLES is not supported via GLX? - if (prefer_egl || prefer_gles) - context = std::make_unique(); - else - context = std::make_unique(); -#elif HAVE_EGL - context = std::make_unique(); -#else - return nullptr; + if (wsi.type == WindowSystemType::MacOS || wsi.type == WindowSystemType::Headless) + context = std::make_unique(); #endif +#if defined(_WIN32) + if (wsi.type == WindowSystemType::Windows) + context = std::make_unique(); +#endif +#if defined(ANDROID) + if (wsi.type == WindowSystemType::Android) + context = std::make_unique(); +#endif +#if HAVE_X11 + if (wsi.type == WindowSystemType::X11) + { + // GLES 3 is not supported via GLX. + const bool use_egl = prefer_egl || prefer_gles; +#if defined(HAVE_EGL) + if (use_egl) + context = std::make_unique(); + else + context = std::make_unique(); +#else + context = std::make_unique(); +#endif + } +#endif +#if HAVE_EGL + if (wsi.type == WindowSystemType::Headless) + context = std::make_unique(); +#endif + + if (!context) + return nullptr; // Option to prefer GLES on desktop platforms, useful for testing. if (prefer_gles) diff --git a/Source/Core/UICommon/CMakeLists.txt b/Source/Core/UICommon/CMakeLists.txt index 5956031531..f5ef5d6f11 100644 --- a/Source/Core/UICommon/CMakeLists.txt +++ b/Source/Core/UICommon/CMakeLists.txt @@ -24,7 +24,7 @@ if ((DEFINED CMAKE_ANDROID_ARCH_ABI AND CMAKE_ANDROID_ARCH_ABI MATCHES "x86|x86_ target_link_libraries(uicommon PRIVATE bdisasm) endif() -if(ENABLE_X11) +if(ENABLE_X11 AND X11_FOUND) target_include_directories(uicommon PRIVATE ${X11_INCLUDE_DIR}) target_sources(uicommon PRIVATE X11Utils.cpp) target_link_libraries(uicommon PUBLIC ${XRANDR_LIBRARIES}) From 2c6d96433c322b50470705d43005fd6308506d49 Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sun, 14 Oct 2018 23:32:50 +1000 Subject: [PATCH 12/12] GLContext: Try GL versions 3.2-4.6 when getting a context GLX previously was only creating a 4.0 context. --- Source/Core/Common/GL/GLContext.cpp | 3 ++ Source/Core/Common/GL/GLContext.h | 6 ++++ Source/Core/Common/GL/GLInterface/EGL.cpp | 12 +------ Source/Core/Common/GL/GLInterface/GLX.cpp | 41 +++++++++++------------ Source/Core/Common/GL/GLInterface/WGL.cpp | 7 +--- 5 files changed, 31 insertions(+), 38 deletions(-) diff --git a/Source/Core/Common/GL/GLContext.cpp b/Source/Core/Common/GL/GLContext.cpp index d4a9ed2e7a..b02e27778f 100644 --- a/Source/Core/Common/GL/GLContext.cpp +++ b/Source/Core/Common/GL/GLContext.cpp @@ -25,6 +25,9 @@ #endif #endif +const std::array, 9> GLContext::s_desktop_opengl_versions = { + {{4, 6}, {4, 5}, {4, 4}, {4, 3}, {4, 2}, {4, 1}, {4, 0}, {3, 3}, {3, 2}}}; + GLContext::~GLContext() = default; bool GLContext::Initialize(void* display_handle, void* window_handle, bool stereo, bool core) diff --git a/Source/Core/Common/GL/GLContext.h b/Source/Core/Common/GL/GLContext.h index d4854a21cf..074ea3cc6d 100644 --- a/Source/Core/Common/GL/GLContext.h +++ b/Source/Core/Common/GL/GLContext.h @@ -4,8 +4,10 @@ #pragma once +#include #include #include +#include #include "Common/CommonTypes.h" #include "Common/WindowSystemInfo.h" @@ -58,4 +60,8 @@ protected: u32 m_backbuffer_width = 0; u32 m_backbuffer_height = 0; bool m_is_shared = false; + + // A list of desktop OpenGL versions to attempt to create a context for. + // (4.6-3.2, geometry shaders is a minimum requirement since we're using core profile). + static const std::array, 9> s_desktop_opengl_versions; }; diff --git a/Source/Core/Common/GL/GLInterface/EGL.cpp b/Source/Core/Common/GL/GLInterface/EGL.cpp index b472d2b984..93a60ca9d8 100644 --- a/Source/Core/Common/GL/GLInterface/EGL.cpp +++ b/Source/Core/Common/GL/GLInterface/EGL.cpp @@ -222,17 +222,7 @@ bool GLContextEGL::Initialize(void* display_handle, void* window_handle, bool st if (supports_core_profile && core && m_opengl_mode == Mode::OpenGL) { - std::array, 7> versions_to_try = {{ - {4, 5}, - {4, 4}, - {4, 3}, - {4, 2}, - {4, 1}, - {4, 0}, - {3, 3}, - }}; - - for (const auto& version : versions_to_try) + for (const auto& version : s_desktop_opengl_versions) { std::vector core_attribs = {EGL_CONTEXT_MAJOR_VERSION_KHR, version.first, diff --git a/Source/Core/Common/GL/GLInterface/GLX.cpp b/Source/Core/Common/GL/GLInterface/GLX.cpp index d74bccf8a4..c2e4491ff5 100644 --- a/Source/Core/Common/GL/GLInterface/GLX.cpp +++ b/Source/Core/Common/GL/GLInterface/GLX.cpp @@ -134,30 +134,29 @@ bool GLContextGLX::Initialize(void* display_handle, void* window_handle, bool st XErrorHandler oldHandler = XSetErrorHandler(&ctxErrorHandler); // Create a GLX context. - // We try to get a 4.0 core profile, else we try 3.3, else try it with anything we get. - std::array context_attribs = { - {GLX_CONTEXT_MAJOR_VERSION_ARB, 4, GLX_CONTEXT_MINOR_VERSION_ARB, 0, - GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, GLX_CONTEXT_FLAGS_ARB, - GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, None}}; - m_context = nullptr; if (core) { - m_context = glXCreateContextAttribs(m_display, m_fbconfig, 0, True, &context_attribs[0]); - XSync(m_display, False); - m_attribs.insert(m_attribs.end(), context_attribs.begin(), context_attribs.end()); - } - if (core && (!m_context || s_glxError)) - { - std::array context_attribs_33 = { - {GLX_CONTEXT_MAJOR_VERSION_ARB, 3, GLX_CONTEXT_MINOR_VERSION_ARB, 3, - GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, GLX_CONTEXT_FLAGS_ARB, - GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, None}}; - s_glxError = false; - m_context = glXCreateContextAttribs(m_display, m_fbconfig, 0, True, &context_attribs_33[0]); - XSync(m_display, False); - m_attribs.clear(); - m_attribs.insert(m_attribs.end(), context_attribs_33.begin(), context_attribs_33.end()); + for (const auto& version : s_desktop_opengl_versions) + { + std::array context_attribs = { + {GLX_CONTEXT_MAJOR_VERSION_ARB, version.first, GLX_CONTEXT_MINOR_VERSION_ARB, + version.second, GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB, + GLX_CONTEXT_FLAGS_ARB, GLX_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB, None}}; + + s_glxError = false; + m_context = glXCreateContextAttribs(m_display, m_fbconfig, 0, True, &context_attribs[0]); + XSync(m_display, False); + m_attribs.insert(m_attribs.end(), context_attribs.begin(), context_attribs.end()); + if (!m_context || s_glxError) + continue; + + // Got a context. + INFO_LOG(VIDEO, "Created a GLX context with version %d.%d", version.first, version.second); + break; + } } + + // Failed to create any core contexts, try for anything. if (!m_context || s_glxError) { std::array context_attribs_legacy = { diff --git a/Source/Core/Common/GL/GLInterface/WGL.cpp b/Source/Core/Common/GL/GLInterface/WGL.cpp index 98b6bd5a3a..e168f94e51 100644 --- a/Source/Core/Common/GL/GLInterface/WGL.cpp +++ b/Source/Core/Common/GL/GLInterface/WGL.cpp @@ -371,12 +371,7 @@ HGLRC GLContextWGL::CreateCoreContext(HDC dc, HGLRC share_context) return nullptr; } - // List of versions to attempt context creation for. (4.5-3.2, geometry shaders is a minimum - // requirement since we're using core profile) - static constexpr std::array, 8> try_versions = { - {{4, 5}, {4, 4}, {4, 3}, {4, 2}, {4, 1}, {4, 0}, {3, 3}, {3, 2}}}; - - for (const auto& version : try_versions) + for (const auto& version : s_desktop_opengl_versions) { // Construct list of attributes. Prefer a forward-compatible, core context. std::array attribs = {WGL_CONTEXT_PROFILE_MASK_ARB,