Drop Host_GetRenderSurface and pass display to backend

This commit is contained in:
Stenzek 2018-10-03 23:03:13 +10:00
parent 134d967be2
commit a3961750a7
35 changed files with 129 additions and 124 deletions

View File

@ -89,11 +89,6 @@ void Host_Message(HostMessageID id)
} }
} }
void* Host_GetRenderHandle()
{
return s_surf;
}
void Host_UpdateTitle(const std::string& title) void Host_UpdateTitle(const std::string& title)
{ {
__android_log_write(ANDROID_LOG_INFO, DOLPHIN_TAG, title.c_str()); __android_log_write(ANDROID_LOG_INFO, DOLPHIN_TAG, title.c_str());

View File

@ -78,6 +78,14 @@ struct BootParameters
Parameters parameters; Parameters parameters;
std::optional<std::string> savestate_path; std::optional<std::string> savestate_path;
bool delete_savestate = false; 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 class CBoot

View File

@ -89,7 +89,6 @@ static bool s_is_stopping = false;
static bool s_hardware_initialized = false; static bool s_hardware_initialized = false;
static bool s_is_started = false; static bool s_is_started = false;
static Common::Flag s_is_booting; static Common::Flag s_is_booting;
static void* s_window_handle = nullptr;
static std::thread s_emu_thread; static std::thread s_emu_thread;
static StateChangedCallbackFunc s_on_state_changed_callback; static StateChangedCallbackFunc s_on_state_changed_callback;
@ -215,8 +214,6 @@ bool Init(std::unique_ptr<BootParameters> boot)
Host_UpdateMainFrame(); // Disable any menus or buttons at boot Host_UpdateMainFrame(); // Disable any menus or buttons at boot
s_window_handle = Host_GetRenderHandle();
// Start the emu thread // Start the emu thread
s_emu_thread = std::thread(EmuThread, std::move(boot)); s_emu_thread = std::thread(EmuThread, std::move(boot));
return true; return true;
@ -441,7 +438,7 @@ static void EmuThread(std::unique_ptr<BootParameters> boot)
g_video_backend->InitBackendInfo(); g_video_backend->InitBackendInfo();
g_Config.Refresh(); 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!"); PanicAlert("Failed to initialize video backend!");
return; return;
@ -462,7 +459,7 @@ static void EmuThread(std::unique_ptr<BootParameters> boot)
bool init_controllers = false; bool init_controllers = false;
if (!g_controller_interface.IsInit()) if (!g_controller_interface.IsInit())
{ {
g_controller_interface.Initialize(s_window_handle); g_controller_interface.Initialize(boot->render_surface);
Pad::Initialize(); Pad::Initialize();
Keyboard::Initialize(); Keyboard::Initialize();
init_controllers = true; init_controllers = true;
@ -958,4 +955,4 @@ void DoFrameStep()
} }
} }
} // Core } // namespace Core

View File

@ -44,6 +44,3 @@ void Host_UpdateMainFrame();
void Host_UpdateTitle(const std::string& title); void Host_UpdateTitle(const std::string& title);
void Host_YieldToUI(); void Host_YieldToUI();
void Host_UpdateProgressDialog(const char* caption, int position, int total); void Host_UpdateProgressDialog(const char* caption, int position, int total);
// TODO (neobrain): Remove this from host!
void* Host_GetRenderHandle();

View File

@ -71,6 +71,9 @@ public:
} }
virtual void Shutdown() {} virtual void Shutdown() {}
virtual ~Platform() {} virtual ~Platform() {}
virtual void* GetDisplayHandle() { return nullptr; }
virtual void* GetWindowHandle() { return nullptr; }
}; };
static Platform* platform; static Platform* platform;
@ -91,12 +94,6 @@ void Host_Message(HostMessageID id)
updateMainFrameEvent.Set(); updateMainFrameEvent.Set();
} }
static void* s_window_handle = nullptr;
void* Host_GetRenderHandle()
{
return s_window_handle;
}
void Host_UpdateTitle(const std::string& title) void Host_UpdateTitle(const std::string& title)
{ {
platform->SetTitle(title); platform->SetTitle(title);
@ -187,7 +184,6 @@ class PlatformX11 : public Platform
} }
XMapRaised(dpy, win); XMapRaised(dpy, win);
XFlush(dpy); XFlush(dpy);
s_window_handle = (void*)win;
if (SConfig::GetInstance().bDisableScreenSaver) if (SConfig::GetInstance().bDisableScreenSaver)
X11Utils::InhibitScreensaver(win, true); X11Utils::InhibitScreensaver(win, true);
@ -354,6 +350,10 @@ class PlatformX11 : public Platform
XCloseDisplay(dpy); XCloseDisplay(dpy);
} }
void* GetDisplayHandle() override { return static_cast<void*>(dpy); }
void* GetWindowHandle() override { return reinterpret_cast<void*>(win); }
}; };
#endif #endif
@ -433,6 +433,9 @@ int main(int argc, char* argv[])
DolphinAnalytics::Instance()->ReportDolphinStart("nogui"); DolphinAnalytics::Instance()->ReportDolphinStart("nogui");
boot->display_connection = platform->GetDisplayHandle();
boot->render_surface = platform->GetWindowHandle();
if (!BootManager::BootCore(std::move(boot))) if (!BootManager::BootCore(std::move(boot)))
{ {
fprintf(stderr, "Could not boot the specified file\n"); fprintf(stderr, "Could not boot the specified file\n");

View File

@ -30,14 +30,10 @@ Host* Host::GetInstance()
return s_instance; return s_instance;
} }
void* Host::GetRenderHandle()
{
return m_render_handle;
}
void Host::SetRenderHandle(void* handle) void Host::SetRenderHandle(void* handle)
{ {
m_render_handle = handle; if (g_renderer)
g_renderer->ChangeSurface(handle);
} }
bool Host::GetRenderFocus() bool Host::GetRenderFocus()
@ -94,11 +90,6 @@ void Host_UpdateTitle(const std::string& title)
emit Host::GetInstance()->RequestTitle(QString::fromStdString(title)); emit Host::GetInstance()->RequestTitle(QString::fromStdString(title));
} }
void* Host_GetRenderHandle()
{
return Host::GetInstance()->GetRenderHandle();
}
bool Host_RendererHasFocus() bool Host_RendererHasFocus()
{ {
return Host::GetInstance()->GetRenderFocus(); return Host::GetInstance()->GetRenderFocus();

View File

@ -20,7 +20,6 @@ class Host final : public QObject
public: public:
static Host* GetInstance(); static Host* GetInstance();
void* GetRenderHandle();
bool GetRenderFocus(); bool GetRenderFocus();
bool GetRenderFullscreen(); bool GetRenderFullscreen();

View File

@ -26,6 +26,10 @@
#include "QtUtils/SignalDaemon.h" #include "QtUtils/SignalDaemon.h"
#endif #endif
#ifndef WIN32
#include <qpa/qplatformnativeinterface.h>
#endif
#include "Common/Version.h" #include "Common/Version.h"
#include "Core/Boot/Boot.h" #include "Core/Boot/Boot.h"
@ -98,7 +102,6 @@
#include "VideoCommon/VideoConfig.h" #include "VideoCommon/VideoConfig.h"
#if defined(HAVE_XRANDR) && HAVE_XRANDR #if defined(HAVE_XRANDR) && HAVE_XRANDR
#include <qpa/qplatformnativeinterface.h>
#include "UICommon/X11Utils.h" #include "UICommon/X11Utils.h"
#endif #endif
@ -797,14 +800,26 @@ void MainWindow::StartGame(std::unique_ptr<BootParameters>&& parameters)
m_pending_boot = std::move(parameters); m_pending_boot = std::move(parameters);
return; return;
} }
// We need the render widget before booting.
ShowRenderWidget();
// Populate the video backend fields of the boot parameters.
parameters->render_surface = reinterpret_cast<void*>(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. // Boot up, show an error if it fails to load the game.
if (!BootManager::BootCore(std::move(parameters))) if (!BootManager::BootCore(std::move(parameters)))
{ {
QMessageBox::critical(this, tr("Error"), tr("Failed to init core"), QMessageBox::Ok); QMessageBox::critical(this, tr("Error"), tr("Failed to init core"), QMessageBox::Ok);
HideRenderWidget();
return; return;
} }
ShowRenderWidget();
#ifdef USE_DISCORD_PRESENCE #ifdef USE_DISCORD_PRESENCE
if (!NetPlay::IsNetPlayRunning()) if (!NetPlay::IsNetPlayRunning())
Discord::UpdateDiscordPresence(); Discord::UpdateDiscordPresence();

View File

@ -55,8 +55,6 @@ RenderWidget::RenderWidget(QWidget* parent) : QWidget(parent)
connect(this, &RenderWidget::FocusChanged, Host::GetInstance(), &Host::SetRenderFocus, connect(this, &RenderWidget::FocusChanged, Host::GetInstance(), &Host::SetRenderFocus,
Qt::DirectConnection); Qt::DirectConnection);
emit HandleChanged((void*)winId());
m_mouse_timer = new QTimer(this); m_mouse_timer = new QTimer(this);
connect(m_mouse_timer, &QTimer::timeout, this, &RenderWidget::HandleCursorTimer); connect(m_mouse_timer, &QTimer::timeout, this, &RenderWidget::HandleCursorTimer);
m_mouse_timer->setSingleShot(true); m_mouse_timer->setSingleShot(true);
@ -144,7 +142,7 @@ bool RenderWidget::event(QEvent* event)
} }
break; break;
case QEvent::WinIdChange: case QEvent::WinIdChange:
emit HandleChanged((void*)winId()); emit HandleChanged(reinterpret_cast<void*>(winId()));
break; break;
case QEvent::WindowActivate: case QEvent::WindowActivate:
if (SConfig::GetInstance().m_PauseOnFocusLost && Core::GetState() == Core::State::Paused) if (SConfig::GetInstance().m_PauseOnFocusLost && Core::GetState() == Core::State::Paused)

View File

@ -225,6 +225,11 @@ void Renderer::Create3DVisionTexture(int width, int height)
DXGI_FORMAT_R8G8B8A8_UNORM, 1, 1, &sys_data); DXGI_FORMAT_R8G8B8A8_UNORM, 1, 1, &sys_data);
} }
bool Renderer::IsHeadless() const
{
return D3D::swapchain == nullptr;
}
std::unique_ptr<AbstractTexture> Renderer::CreateTexture(const TextureConfig& config) std::unique_ptr<AbstractTexture> Renderer::CreateTexture(const TextureConfig& config)
{ {
return std::make_unique<DXTexture>(config); return std::make_unique<DXTexture>(config);
@ -698,12 +703,12 @@ void Renderer::CheckForSurfaceChange()
if (!m_surface_changed.TestAndClear()) if (!m_surface_changed.TestAndClear())
return; return;
m_surface_handle = m_new_surface_handle;
m_new_surface_handle = nullptr;
SAFE_RELEASE(m_screenshot_texture); SAFE_RELEASE(m_screenshot_texture);
SAFE_RELEASE(m_3d_vision_texture); SAFE_RELEASE(m_3d_vision_texture);
D3D::Reset(reinterpret_cast<HWND>(m_new_surface_handle)); D3D::Reset(reinterpret_cast<HWND>(m_new_surface_handle));
m_new_surface_handle = nullptr;
UpdateBackbufferSize(); UpdateBackbufferSize();
} }

View File

@ -22,6 +22,9 @@ public:
~Renderer() override; ~Renderer() override;
StateCache& GetStateCache() { return m_state_cache; } StateCache& GetStateCache() { return m_state_cache; }
bool IsHeadless() const override;
std::unique_ptr<AbstractTexture> CreateTexture(const TextureConfig& config) override; std::unique_ptr<AbstractTexture> CreateTexture(const TextureConfig& config) override;
std::unique_ptr<AbstractStagingTexture> std::unique_ptr<AbstractStagingTexture>
CreateStagingTexture(StagingTextureType type, const TextureConfig& config) override; CreateStagingTexture(StagingTextureType type, const TextureConfig& config) override;

View File

@ -11,7 +11,7 @@ namespace DX11
{ {
class VideoBackend : public VideoBackendBase class VideoBackend : public VideoBackendBase
{ {
bool Initialize(void*) override; bool Initialize(void* display_handle, void* window_handle) override;
void Shutdown() override; void Shutdown() override;
std::string GetName() const override; std::string GetName() const override;
@ -19,4 +19,4 @@ class VideoBackend : public VideoBackendBase
void InitBackendInfo() override; void InitBackendInfo() override;
}; };
} } // namespace DX11

View File

@ -127,7 +127,7 @@ void VideoBackend::InitBackendInfo()
DX11::D3D::UnloadD3D(); DX11::D3D::UnloadD3D();
} }
bool VideoBackend::Initialize(void* window_handle) bool VideoBackend::Initialize(void* display_handle, void* window_handle)
{ {
if (window_handle == nullptr) if (window_handle == nullptr)
return false; return false;
@ -188,4 +188,4 @@ void VideoBackend::Shutdown()
D3D::Close(); D3D::Close();
} }
} } // namespace DX11

View File

@ -54,7 +54,7 @@ void VideoBackend::InitBackendInfo()
g_Config.backend_info.AAModes = {1}; g_Config.backend_info.AAModes = {1};
} }
bool VideoBackend::Initialize(void* window_handle) bool VideoBackend::Initialize(void* display_handle, void* window_handle)
{ {
InitializeShared(); InitializeShared();
@ -80,4 +80,4 @@ void VideoBackend::Shutdown()
ShutdownShared(); ShutdownShared();
} }
} } // namespace Null

View File

@ -24,6 +24,11 @@ Renderer::~Renderer()
UpdateActiveConfig(); UpdateActiveConfig();
} }
bool Renderer::IsHeadless() const
{
return true;
}
std::unique_ptr<AbstractTexture> Renderer::CreateTexture(const TextureConfig& config) std::unique_ptr<AbstractTexture> Renderer::CreateTexture(const TextureConfig& config)
{ {
return std::make_unique<NullTexture>(config); return std::make_unique<NullTexture>(config);

View File

@ -14,6 +14,8 @@ public:
Renderer(); Renderer();
~Renderer() override; ~Renderer() override;
bool IsHeadless() const override;
std::unique_ptr<AbstractTexture> CreateTexture(const TextureConfig& config) override; std::unique_ptr<AbstractTexture> CreateTexture(const TextureConfig& config) override;
std::unique_ptr<AbstractStagingTexture> std::unique_ptr<AbstractStagingTexture>
CreateStagingTexture(StagingTextureType type, const TextureConfig& config) override; CreateStagingTexture(StagingTextureType type, const TextureConfig& config) override;

View File

@ -11,7 +11,7 @@ namespace Null
{ {
class VideoBackend : public VideoBackendBase class VideoBackend : public VideoBackendBase
{ {
bool Initialize(void* window_handle) override; bool Initialize(void* display_handle, void* window_handle) override;
void Shutdown() override; void Shutdown() override;
std::string GetName() const override { return "Null"; } std::string GetName() const override { return "Null"; }
@ -22,4 +22,4 @@ class VideoBackend : public VideoBackendBase
} }
void InitBackendInfo() override; void InitBackendInfo() override;
}; };
} } // namespace Null

View File

@ -804,6 +804,11 @@ Renderer::Renderer()
Renderer::~Renderer() = default; Renderer::~Renderer() = default;
bool Renderer::IsHeadless() const
{
return g_main_gl_context->IsHeadless();
}
void Renderer::Shutdown() void Renderer::Shutdown()
{ {
::Renderer::Shutdown(); ::Renderer::Shutdown();
@ -1499,9 +1504,8 @@ void Renderer::CheckForSurfaceChange()
if (!m_surface_changed.TestAndClear()) if (!m_surface_changed.TestAndClear())
return; return;
m_surface_handle = m_new_surface_handle; g_main_gl_context->UpdateSurface(m_new_surface_handle);
m_new_surface_handle = nullptr; m_new_surface_handle = nullptr;
g_main_gl_context->UpdateSurface(m_surface_handle);
// With a surface change, the window likely has new dimensions. // With a surface change, the window likely has new dimensions.
m_backbuffer_width = g_main_gl_context->GetBackBufferWidth(); m_backbuffer_width = g_main_gl_context->GetBackBufferWidth();

View File

@ -84,6 +84,8 @@ public:
Renderer(); Renderer();
~Renderer() override; ~Renderer() override;
bool IsHeadless() const override;
void Init(); void Init();
void Shutdown() override; void Shutdown() override;

View File

@ -11,7 +11,7 @@ namespace OGL
{ {
class VideoBackend : public VideoBackendBase class VideoBackend : public VideoBackendBase
{ {
bool Initialize(void*) override; bool Initialize(void* display_handle, void* window_handle) override;
void Shutdown() override; void Shutdown() override;
std::string GetName() const override; std::string GetName() const override;
@ -23,4 +23,4 @@ private:
bool InitializeGLExtensions(); bool InitializeGLExtensions();
bool FillBackendInfo(); bool FillBackendInfo();
}; };
} } // namespace OGL

View File

@ -157,7 +157,7 @@ bool VideoBackend::FillBackendInfo()
return true; return true;
} }
bool VideoBackend::Initialize(void* window_handle) bool VideoBackend::Initialize(void* display_handle, void* window_handle)
{ {
InitializeShared(); InitializeShared();

View File

@ -7,6 +7,7 @@
#include <string> #include <string>
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/GL/GLContext.h"
#include "Core/Config/GraphicsSettings.h" #include "Core/Config/GraphicsSettings.h"
#include "Core/HW/Memmap.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<AbstractTexture> SWRenderer::CreateTexture(const TextureConfig& config) std::unique_ptr<AbstractTexture> SWRenderer::CreateTexture(const TextureConfig& config)
{ {
return std::make_unique<SW::SWTexture>(config); return std::make_unique<SW::SWTexture>(config);

View File

@ -13,6 +13,8 @@ class SWRenderer : public Renderer
public: public:
SWRenderer(); SWRenderer();
bool IsHeadless() const override;
std::unique_ptr<AbstractTexture> CreateTexture(const TextureConfig& config) override; std::unique_ptr<AbstractTexture> CreateTexture(const TextureConfig& config) override;
std::unique_ptr<AbstractStagingTexture> std::unique_ptr<AbstractStagingTexture>
CreateStagingTexture(StagingTextureType type, const TextureConfig& config) override; CreateStagingTexture(StagingTextureType type, const TextureConfig& config) override;

View File

@ -78,7 +78,7 @@ void VideoSoftware::InitBackendInfo()
g_Config.backend_info.AAModes = {1}; g_Config.backend_info.AAModes = {1};
} }
bool VideoSoftware::Initialize(void* window_handle) bool VideoSoftware::Initialize(void* display_handle, void* window_handle)
{ {
InitializeShared(); InitializeShared();

View File

@ -11,7 +11,7 @@ namespace SW
{ {
class VideoSoftware : public VideoBackendBase class VideoSoftware : public VideoBackendBase
{ {
bool Initialize(void* window_handle) override; bool Initialize(void* display_handle, void* window_handle) override;
void Shutdown() override; void Shutdown() override;
std::string GetName() const override; std::string GetName() const override;
@ -19,4 +19,4 @@ class VideoSoftware : public VideoBackendBase
void InitBackendInfo() override; void InitBackendInfo() override;
}; };
} } // namespace SW

View File

@ -70,6 +70,11 @@ Renderer* Renderer::GetInstance()
return static_cast<Renderer*>(g_renderer.get()); return static_cast<Renderer*>(g_renderer.get());
} }
bool Renderer::IsHeadless() const
{
return m_swap_chain == nullptr;
}
bool Renderer::Initialize() bool Renderer::Initialize()
{ {
BindEFBToStateTracker(); BindEFBToStateTracker();
@ -860,12 +865,9 @@ void Renderer::BlitScreen(VkRenderPass render_pass, const TargetRectangle& dst_r
void Renderer::CheckForSurfaceChange() void Renderer::CheckForSurfaceChange()
{ {
if (!m_surface_changed.TestAndClear()) if (!m_surface_changed.TestAndClear() || !m_swap_chain)
return; return;
m_surface_handle = m_new_surface_handle;
m_new_surface_handle = nullptr;
// Submit the current draws up until rendering the XFB. // Submit the current draws up until rendering the XFB.
g_command_buffer_mgr->ExecuteCommandBuffer(false, false); g_command_buffer_mgr->ExecuteCommandBuffer(false, false);
g_command_buffer_mgr->WaitForGPUIdle(); 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. // Clear the present failed flag, since we don't want to resize after recreating.
g_command_buffer_mgr->CheckLastPresentFail(); g_command_buffer_mgr->CheckLastPresentFail();
// Did we previously have a swap chain? // Recreate the surface. If this fails we're in trouble.
if (m_swap_chain) if (!m_swap_chain->RecreateSurface(m_new_surface_handle))
{ PanicAlert("Failed to recreate Vulkan surface. Cannot continue.");
if (!m_surface_handle) m_new_surface_handle = nullptr;
{
// 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.");
}
}
// Handle case where the dimensions are now different. // Handle case where the dimensions are now different.
OnSwapChainResized(); OnSwapChainResized();

View File

@ -35,6 +35,8 @@ public:
static Renderer* GetInstance(); static Renderer* GetInstance();
bool IsHeadless() const override;
std::unique_ptr<AbstractTexture> CreateTexture(const TextureConfig& config) override; std::unique_ptr<AbstractTexture> CreateTexture(const TextureConfig& config) override;
std::unique_ptr<AbstractStagingTexture> std::unique_ptr<AbstractStagingTexture>
CreateStagingTexture(StagingTextureType type, const TextureConfig& config) override; CreateStagingTexture(StagingTextureType type, const TextureConfig& config) override;

View File

@ -25,8 +25,9 @@
namespace Vulkan namespace Vulkan
{ {
SwapChain::SwapChain(void* native_handle, VkSurfaceKHR surface, bool vsync) SwapChain::SwapChain(void* display_handle, void* native_handle, VkSurfaceKHR surface, bool vsync)
: m_native_handle(native_handle), m_surface(surface), m_vsync_enabled(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(); 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) #if defined(VK_USE_PLATFORM_WIN32_KHR)
VkWin32SurfaceCreateInfoKHR surface_create_info = { VkWin32SurfaceCreateInfoKHR surface_create_info = {
@ -59,15 +60,11 @@ VkSurfaceKHR SwapChain::CreateVulkanSurface(VkInstance instance, void* hwnd)
return surface; return surface;
#elif defined(VK_USE_PLATFORM_XLIB_KHR) #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 = { VkXlibSurfaceCreateInfoKHR surface_create_info = {
VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, // VkStructureType sType VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR, // VkStructureType sType
nullptr, // const void* pNext nullptr, // const void* pNext
0, // VkXlibSurfaceCreateFlagsKHR flags 0, // VkXlibSurfaceCreateFlagsKHR flags
display, // Display* dpy static_cast<Display*>(display_handle), // Display* dpy
reinterpret_cast<Window>(hwnd) // Window window reinterpret_cast<Window>(hwnd) // Window window
}; };
@ -83,8 +80,7 @@ VkSurfaceKHR SwapChain::CreateVulkanSurface(VkInstance instance, void* hwnd)
#elif defined(VK_USE_PLATFORM_XCB_KHR) #elif defined(VK_USE_PLATFORM_XCB_KHR)
// If we ever switch to using xcb, we should pass the display handle as well. // 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_handle);
xcb_connection_t* connection = XGetXCBConnection(display);
VkXcbSurfaceCreateInfoKHR surface_create_info = { VkXcbSurfaceCreateInfoKHR surface_create_info = {
VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR, // VkStructureType sType VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR, // VkStructureType sType
@ -127,10 +123,11 @@ VkSurfaceKHR SwapChain::CreateVulkanSurface(VkInstance instance, void* hwnd)
#endif #endif
} }
std::unique_ptr<SwapChain> SwapChain::Create(void* native_handle, VkSurfaceKHR surface, bool vsync) std::unique_ptr<SwapChain> SwapChain::Create(void* display_handle, void* native_handle,
VkSurfaceKHR surface, bool vsync)
{ {
std::unique_ptr<SwapChain> swap_chain = std::unique_ptr<SwapChain> swap_chain =
std::make_unique<SwapChain>(native_handle, surface, vsync); std::make_unique<SwapChain>(display_handle, native_handle, surface, vsync);
if (!swap_chain->CreateSwapChain() || !swap_chain->CreateRenderPass() || if (!swap_chain->CreateSwapChain() || !swap_chain->CreateRenderPass() ||
!swap_chain->SetupSwapChainImages()) !swap_chain->SetupSwapChainImages())
@ -467,7 +464,8 @@ bool SwapChain::RecreateSurface(void* native_handle)
// Re-create the surface with the new native handle // Re-create the surface with the new native handle
m_native_handle = 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) if (m_surface == VK_NULL_HANDLE)
return false; return false;
@ -499,4 +497,4 @@ void SwapChain::DestroySurface()
vkDestroySurfaceKHR(g_vulkan_context->GetVulkanInstance(), m_surface, nullptr); vkDestroySurfaceKHR(g_vulkan_context->GetVulkanInstance(), m_surface, nullptr);
m_surface = VK_NULL_HANDLE; m_surface = VK_NULL_HANDLE;
} }
} } // namespace Vulkan

View File

@ -19,15 +19,17 @@ class ObjectCache;
class SwapChain class SwapChain
{ {
public: public:
SwapChain(void* native_handle, VkSurfaceKHR surface, bool vsync); SwapChain(void* display_handle, void* native_handle, VkSurfaceKHR surface, bool vsync);
~SwapChain(); ~SwapChain();
// Creates a vulkan-renderable surface for the specified window handle. // 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. // Create a new swap chain from a pre-existing surface.
static std::unique_ptr<SwapChain> Create(void* native_handle, VkSurfaceKHR surface, bool vsync); static std::unique_ptr<SwapChain> 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; } void* GetNativeHandle() const { return m_native_handle; }
VkSurfaceKHR GetSurface() const { return m_surface; } VkSurfaceKHR GetSurface() const { return m_surface; }
VkSurfaceFormatKHR GetSurfaceFormat() const { return m_surface_format; } VkSurfaceFormatKHR GetSurfaceFormat() const { return m_surface_format; }
@ -81,6 +83,7 @@ private:
VkFramebuffer framebuffer; VkFramebuffer framebuffer;
}; };
void* m_display_handle;
void* m_native_handle; void* m_native_handle;
VkSurfaceKHR m_surface = VK_NULL_HANDLE; VkSurfaceKHR m_surface = VK_NULL_HANDLE;
VkSurfaceFormatKHR m_surface_format = {}; VkSurfaceFormatKHR m_surface_format = {};

View File

@ -12,11 +12,11 @@ namespace Vulkan
class VideoBackend : public VideoBackendBase class VideoBackend : public VideoBackendBase
{ {
public: public:
bool Initialize(void* window_handle) override; bool Initialize(void* display_handle, void* window_handle) override;
void Shutdown() override; void Shutdown() override;
std::string GetName() const override { return "Vulkan"; } std::string GetName() const override { return "Vulkan"; }
std::string GetDisplayName() const override { return _trans("Vulkan"); } std::string GetDisplayName() const override { return _trans("Vulkan"); }
void InitBackendInfo() override; void InitBackendInfo() override;
}; };
} } // namespace Vulkan

View File

@ -89,7 +89,7 @@ static bool ShouldEnableDebugReports(bool enable_validation_layers)
return enable_validation_layers || IsHostGPULoggingEnabled(); return enable_validation_layers || IsHostGPULoggingEnabled();
} }
bool VideoBackend::Initialize(void* window_handle) bool VideoBackend::Initialize(void* display_handle, void* window_handle)
{ {
if (!LoadVulkanLibrary()) if (!LoadVulkanLibrary())
{ {
@ -146,7 +146,7 @@ bool VideoBackend::Initialize(void* window_handle)
VkSurfaceKHR surface = VK_NULL_HANDLE; VkSurfaceKHR surface = VK_NULL_HANDLE;
if (enable_surface) if (enable_surface)
{ {
surface = SwapChain::CreateVulkanSurface(instance, window_handle); surface = SwapChain::CreateVulkanSurface(instance, display_handle, window_handle);
if (surface == VK_NULL_HANDLE) if (surface == VK_NULL_HANDLE)
{ {
PanicAlert("Failed to create Vulkan surface."); PanicAlert("Failed to create Vulkan surface.");
@ -209,7 +209,7 @@ bool VideoBackend::Initialize(void* window_handle)
std::unique_ptr<SwapChain> swap_chain; std::unique_ptr<SwapChain> swap_chain;
if (surface != VK_NULL_HANDLE) 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) if (!swap_chain)
{ {
PanicAlert("Failed to create Vulkan swap chain."); PanicAlert("Failed to create Vulkan swap chain.");
@ -271,4 +271,4 @@ void VideoBackend::Shutdown()
ShutdownShared(); ShutdownShared();
UnloadVulkanLibrary(); UnloadVulkanLibrary();
} }
} } // namespace Vulkan

View File

@ -86,7 +86,6 @@ Renderer::Renderer(int backbuffer_width, int backbuffer_height)
if (SConfig::GetInstance().bWii) if (SConfig::GetInstance().bWii)
m_aspect_wide = Config::Get(Config::SYSCONF_WIDESCREEN); m_aspect_wide = Config::Get(Config::SYSCONF_WIDESCREEN);
m_surface_handle = Host_GetRenderHandle();
m_last_host_config_bits = ShaderHostConfig::GetCurrent().bits; m_last_host_config_bits = ShaderHostConfig::GetCurrent().bits;
m_last_efb_multisamples = g_ActiveConfig.iMultisamples; m_last_efb_multisamples = g_ActiveConfig.iMultisamples;
} }
@ -408,7 +407,7 @@ float Renderer::CalculateDrawAspectRatio() const
bool Renderer::IsHeadless() const bool Renderer::IsHeadless() const
{ {
return !m_surface_handle; return true;
} }
void Renderer::ChangeSurface(void* new_surface_handle) void Renderer::ChangeSurface(void* new_surface_handle)

View File

@ -77,6 +77,8 @@ public:
using ClearColor = std::array<float, 4>; using ClearColor = std::array<float, 4>;
virtual bool IsHeadless() const = 0;
virtual void SetPipeline(const AbstractPipeline* pipeline) {} virtual void SetPipeline(const AbstractPipeline* pipeline) {}
virtual void SetScissorRect(const MathUtil::Rectangle<int>& rc) {} virtual void SetScissorRect(const MathUtil::Rectangle<int>& rc) {}
virtual void SetTexture(u32 index, const AbstractTexture* texture) {} virtual void SetTexture(u32 index, const AbstractTexture* texture) {}
@ -134,7 +136,6 @@ public:
const TargetRectangle& GetTargetRectangle() const { return m_target_rectangle; } const TargetRectangle& GetTargetRectangle() const { return m_target_rectangle; }
float CalculateDrawAspectRatio() const; float CalculateDrawAspectRatio() const;
bool IsHeadless() const;
std::tuple<float, float> ScaleToDisplayAspectRatio(int width, int height) const; std::tuple<float, float> ScaleToDisplayAspectRatio(int width, int height) const;
void UpdateDrawRectangle(); void UpdateDrawRectangle();
@ -236,7 +237,6 @@ protected:
std::unique_ptr<PostProcessingShaderImplementation> m_post_processor; std::unique_ptr<PostProcessingShaderImplementation> m_post_processor;
void* m_surface_handle = nullptr;
void* m_new_surface_handle = nullptr; void* m_new_surface_handle = nullptr;
Common::Flag m_surface_changed; Common::Flag m_surface_changed;
Common::Flag m_surface_resized; Common::Flag m_surface_resized;

View File

@ -35,7 +35,7 @@ class VideoBackendBase
{ {
public: public:
virtual ~VideoBackendBase() {} virtual ~VideoBackendBase() {}
virtual bool Initialize(void* window_handle) = 0; virtual bool Initialize(void* display_handle, void* window_handle) = 0;
virtual void Shutdown() = 0; virtual void Shutdown() = 0;
virtual std::string GetName() const = 0; virtual std::string GetName() const = 0;

View File

@ -19,10 +19,6 @@ void Host_RefreshDSPDebuggerWindow()
void Host_Message(HostMessageID) void Host_Message(HostMessageID)
{ {
} }
void* Host_GetRenderHandle()
{
return nullptr;
}
void Host_UpdateTitle(const std::string&) void Host_UpdateTitle(const std::string&)
{ {
} }