From a3961750a7174be7402fc492367f017d845b8e1f Mon Sep 17 00:00:00 2001 From: Stenzek Date: Wed, 3 Oct 2018 23:03:13 +1000 Subject: [PATCH] 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&) { }