Skip to content

Commit

Permalink
VideoBackends: Pass window system info from host on creation
Browse files Browse the repository at this point in the history
  • Loading branch information
stenzek committed Oct 20, 2018
1 parent 9c57a98 commit eb284b5
Show file tree
Hide file tree
Showing 26 changed files with 148 additions and 75 deletions.
4 changes: 3 additions & 1 deletion Source/Android/jni/MainAndroid.cpp
Expand Up @@ -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"
Expand Down Expand Up @@ -560,7 +561,8 @@ static void Run(const std::string& path, bool first_open,
s_have_wm_user_stop = false;
std::unique_ptr<BootParameters> 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;
Expand Down
5 changes: 2 additions & 3 deletions Source/Core/Common/GL/GLContext.cpp
Expand Up @@ -82,8 +82,7 @@ void* GLContext::GetFuncAddress(const std::string& name)
return nullptr;
}

std::unique_ptr<GLContext> GLContext::Create(void* display_handle, void* window_handle, bool stereo,
bool core)
std::unique_ptr<GLContext> GLContext::Create(const WindowSystemInfo& wsi, bool stereo, bool core)
{
std::unique_ptr<GLContext> context;
#if defined(__APPLE__)
Expand All @@ -103,7 +102,7 @@ std::unique_ptr<GLContext> 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;
Expand Down
5 changes: 3 additions & 2 deletions Source/Core/Common/GL/GLContext.h
Expand Up @@ -8,6 +8,7 @@
#include <string>

#include "Common/CommonTypes.h"
#include "Common/WindowSystemInfo.h"

class GLContext
{
Expand Down Expand Up @@ -44,8 +45,8 @@ class GLContext
virtual void* GetFuncAddress(const std::string& name);

// Creates an instance of GLInterface specific to the platform we are running on.
static std::unique_ptr<GLContext> Create(void* display_handle, void* window_handle,
bool stereo = false, bool core = true);
static std::unique_ptr<GLContext> Create(const WindowSystemInfo& wsi, bool stereo = false,
bool core = true);

protected:
virtual bool Initialize(void* display_handle, void* window_handle, bool stereo, bool core);
Expand Down
35 changes: 35 additions & 0 deletions 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;
};
8 changes: 0 additions & 8 deletions Source/Core/Core/Boot/Boot.h
Expand Up @@ -78,14 +78,6 @@ struct BootParameters
Parameters parameters;
std::optional<std::string> 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
Expand Down
14 changes: 8 additions & 6 deletions Source/Core/Core/BootManager.cpp
Expand Up @@ -222,7 +222,7 @@ static GPUDeterminismMode ParseGPUDeterminismMode(const std::string& mode)
}

// Boot the ISO or file
bool BootCore(std::unique_ptr<BootParameters> boot)
bool BootCore(std::unique_ptr<BootParameters> boot, const WindowSystemInfo& wsi)
{
if (!boot)
return false;
Expand Down Expand Up @@ -403,12 +403,14 @@ bool BootCore(std::unique_ptr<BootParameters> boot)
std::holds_alternative<BootParameters::Disc>(boot->parameters);
if (load_ipl)
{
return Core::Init(std::make_unique<BootParameters>(
BootParameters::IPL{StartUp.m_region,
std::move(std::get<BootParameters::Disc>(boot->parameters))},
boot->savestate_path));
return Core::Init(
std::make_unique<BootParameters>(
BootParameters::IPL{StartUp.m_region,
std::move(std::get<BootParameters::Disc>(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
Expand Down
5 changes: 3 additions & 2 deletions Source/Core/Core/BootManager.h
Expand Up @@ -7,12 +7,13 @@
#include <memory>

struct BootParameters;
struct WindowSystemInfo;

namespace BootManager
{
bool BootCore(std::unique_ptr<BootParameters> parameters);
bool BootCore(std::unique_ptr<BootParameters> 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
12 changes: 6 additions & 6 deletions Source/Core/Core/Core.cpp
Expand Up @@ -107,7 +107,7 @@ static std::queue<HostJob> s_host_jobs_queue;

static thread_local bool tls_is_cpu_thread = false;

static void EmuThread(std::unique_ptr<BootParameters> boot);
static void EmuThread(std::unique_ptr<BootParameters> boot, WindowSystemInfo wsi);

bool GetIsThrottlerTempDisabled()
{
Expand Down Expand Up @@ -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<BootParameters> boot)
bool Init(std::unique_ptr<BootParameters> boot, const WindowSystemInfo& wsi)
{
if (s_emu_thread.joinable())
{
Expand All @@ -215,7 +215,7 @@ bool Init(std::unique_ptr<BootParameters> 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;
}

Expand Down Expand Up @@ -386,7 +386,7 @@ static void FifoPlayerThread(const std::optional<std::string>& 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<BootParameters> boot)
static void EmuThread(std::unique_ptr<BootParameters> boot, WindowSystemInfo wsi)
{
const SConfig& core_parameter = SConfig::GetInstance();
s_is_booting.Set();
Expand Down Expand Up @@ -438,7 +438,7 @@ static void EmuThread(std::unique_ptr<BootParameters> 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;
Expand All @@ -459,7 +459,7 @@ static void EmuThread(std::unique_ptr<BootParameters> 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;
Expand Down
5 changes: 3 additions & 2 deletions Source/Core/Core/Core.h
Expand Up @@ -18,6 +18,7 @@
#include "Common/CommonTypes.h"

struct BootParameters;
struct WindowSystemInfo;

namespace Core
{
Expand All @@ -35,7 +36,7 @@ enum class State
Starting,
};

bool Init(std::unique_ptr<BootParameters> boot);
bool Init(std::unique_ptr<BootParameters> boot, const WindowSystemInfo& wsi);
void Stop();
void Shutdown();

Expand Down Expand Up @@ -104,4 +105,4 @@ void HostDispatchJobs();

void DoFrameStep();

} // namespace
} // namespace Core
17 changes: 9 additions & 8 deletions Source/Core/DolphinNoGUI/MainNoGUI.cpp
Expand Up @@ -72,8 +72,9 @@ class Platform
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;
Expand Down Expand Up @@ -342,9 +343,9 @@ class PlatformX11 : public Platform
XCloseDisplay(dpy);
}

void* GetDisplayHandle() override { return static_cast<void*>(dpy); }

void* GetWindowHandle() override { return reinterpret_cast<void*>(win); }
WindowSystemType GetWindowSystem() const override { return WindowSystemType::X11; }
void* GetDisplayHandle() const override { return static_cast<void*>(dpy); }
void* GetWindowHandle() const override { return reinterpret_cast<void*>(win); }
};
#endif

Expand Down Expand Up @@ -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;
Expand Down
52 changes: 43 additions & 9 deletions Source/Core/DolphinQt/MainWindow.cpp
Expand Up @@ -16,6 +16,7 @@
#include <QProgressDialog>
#include <QStackedWidget>
#include <QVBoxLayout>
#include <QWindow>

#include <future>
#include <optional>
Expand All @@ -31,6 +32,7 @@
#endif

#include "Common/Version.h"
#include "Common/WindowSystemInfo.h"

#include "Core/Boot/Boot.h"
#include "Core/BootManager.h"
Expand Down Expand Up @@ -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<void*>(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<void*>(window->winId()) : nullptr;
#endif

return wsi;
}

MainWindow::MainWindow(std::unique_ptr<BootParameters> boot_parameters) : QMainWindow(nullptr)
{
setWindowTitle(QString::fromStdString(Common::scm_rev_str));
Expand Down Expand Up @@ -804,16 +845,9 @@ void MainWindow::StartGame(std::unique_ptr<BootParameters>&& parameters)
// 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.
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();
Expand Down
3 changes: 3 additions & 0 deletions Source/Core/DolphinQt/RenderWidget.cpp
Expand Up @@ -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);
}

Expand Down
11 changes: 7 additions & 4 deletions Source/Core/VideoBackends/D3D/D3DBase.cpp
Expand Up @@ -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");

Expand Down
2 changes: 1 addition & 1 deletion Source/Core/VideoBackends/D3D/VideoBackend.h
Expand Up @@ -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;
Expand Down

0 comments on commit eb284b5

Please sign in to comment.