HostDisplay: Make global pointer instead of function

This commit is contained in:
Connor McLaughlin 2022-09-07 20:19:40 +10:00 committed by refractionpcsx2
parent b667236c92
commit e064e96c96
26 changed files with 143 additions and 175 deletions

View File

@ -956,11 +956,10 @@ bool MainWindow::isShowingGameList() const
bool MainWindow::isRenderingFullscreen() const
{
HostDisplay* display = Host::GetHostDisplay();
if (!display || !m_display_widget)
if (!g_host_display || !m_display_widget)
return false;
return getDisplayContainer()->isFullScreen() || display->IsFullscreen();
return getDisplayContainer()->isFullScreen() || g_host_display->IsFullscreen();
}
bool MainWindow::isRenderingToMain() const
@ -1755,12 +1754,11 @@ DisplayWidget* MainWindow::createDisplay(bool fullscreen, bool render_to_main)
{
DevCon.WriteLn("createDisplay(%u, %u)", static_cast<u32>(fullscreen), static_cast<u32>(render_to_main));
HostDisplay* host_display = Host::GetHostDisplay();
if (!host_display)
if (!g_host_display)
return nullptr;
const std::string fullscreen_mode(Host::GetBaseStringSettingValue("EmuCore/GS", "FullscreenMode", ""));
const bool is_exclusive_fullscreen = (fullscreen && !fullscreen_mode.empty() && host_display->SupportsFullscreen());
const bool is_exclusive_fullscreen = (fullscreen && !fullscreen_mode.empty() && g_host_display->SupportsFullscreen());
createDisplayWidget(fullscreen, render_to_main, is_exclusive_fullscreen);
@ -1777,7 +1775,7 @@ DisplayWidget* MainWindow::createDisplay(bool fullscreen, bool render_to_main)
g_emu_thread->connectDisplaySignals(m_display_widget);
if (!host_display->CreateRenderDevice(wi.value(), Host::GetStringSettingValue("EmuCore/GS", "Adapter", ""), EmuConfig.GetEffectiveVsyncMode(),
if (!g_host_display->CreateRenderDevice(wi.value(), Host::GetStringSettingValue("EmuCore/GS", "Adapter", ""), EmuConfig.GetEffectiveVsyncMode(),
Host::GetBoolSettingValue("EmuCore/GS", "ThreadedPresentation", false), Host::GetBoolSettingValue("EmuCore/GS", "UseDebugDevice", false)))
{
QMessageBox::critical(this, tr("Error"), tr("Failed to create host display device context."));
@ -1803,7 +1801,7 @@ DisplayWidget* MainWindow::createDisplay(bool fullscreen, bool render_to_main)
m_display_widget->updateCursor(s_vm_valid && !s_vm_paused);
m_display_widget->setFocus();
host_display->DoneRenderContextCurrent();
g_host_display->DoneRenderContextCurrent();
return m_display_widget;
}
@ -1812,12 +1810,11 @@ DisplayWidget* MainWindow::updateDisplay(bool fullscreen, bool render_to_main, b
DevCon.WriteLn("updateDisplay() fullscreen=%s render_to_main=%s surfaceless=%s",
fullscreen ? "true" : "false", render_to_main ? "true" : "false", surfaceless ? "true" : "false");
HostDisplay* host_display = Host::GetHostDisplay();
QWidget* container = m_display_container ? static_cast<QWidget*>(m_display_container) : static_cast<QWidget*>(m_display_widget);
const bool is_fullscreen = isRenderingFullscreen();
const bool is_rendering_to_main = isRenderingToMain();
const std::string fullscreen_mode(Host::GetBaseStringSettingValue("EmuCore/GS", "FullscreenMode", ""));
const bool is_exclusive_fullscreen = (fullscreen && !fullscreen_mode.empty() && host_display->SupportsFullscreen());
const bool is_exclusive_fullscreen = (fullscreen && !fullscreen_mode.empty() && g_host_display->SupportsFullscreen());
const bool changing_surfaceless = (!m_display_widget != surfaceless);
if (fullscreen == is_fullscreen && is_rendering_to_main == render_to_main && !changing_surfaceless)
return m_display_widget;
@ -1829,8 +1826,8 @@ DisplayWidget* MainWindow::updateDisplay(bool fullscreen, bool render_to_main, b
if (!is_rendering_to_main && !render_to_main && !is_exclusive_fullscreen && has_container == needs_container && !needs_container && !changing_surfaceless)
{
DevCon.WriteLn("Toggling to %s without recreating surface", (fullscreen ? "fullscreen" : "windowed"));
if (host_display->IsFullscreen())
host_display->SetFullscreen(false, 0, 0, 0.0f);
if (g_host_display->IsFullscreen())
g_host_display->SetFullscreen(false, 0, 0, 0.0f);
// since we don't destroy the display widget, we need to save it here
if (!is_fullscreen && !is_rendering_to_main)
@ -1855,7 +1852,7 @@ DisplayWidget* MainWindow::updateDisplay(bool fullscreen, bool render_to_main, b
return m_display_widget;
}
host_display->DestroyRenderSurface();
g_host_display->DestroyRenderSurface();
destroyDisplayWidget(surfaceless);
@ -1875,7 +1872,7 @@ DisplayWidget* MainWindow::updateDisplay(bool fullscreen, bool render_to_main, b
g_emu_thread->connectDisplaySignals(m_display_widget);
if (!host_display->ChangeRenderWindow(wi.value()))
if (!g_host_display->ChangeRenderWindow(wi.value()))
pxFailRel("Failed to recreate surface on new widget.");
if (is_exclusive_fullscreen)
@ -2101,7 +2098,7 @@ void MainWindow::setDisplayFullscreen(const std::string& fullscreen_mode)
float refresh_rate;
if (HostDisplay::ParseFullscreenMode(fullscreen_mode, &width, &height, &refresh_rate))
{
if (Host::GetHostDisplay()->SetFullscreen(true, width, height, refresh_rate))
if (g_host_display->SetFullscreen(true, width, height, refresh_rate))
{
Host::AddOSDMessage("Acquired exclusive fullscreen.", 10.0f);
}

View File

@ -83,7 +83,6 @@ static void HookSignals();
const IConsoleWriter* PatchesCon = &Console;
static std::unique_ptr<QTimer> s_settings_save_timer;
static std::unique_ptr<INISettingsInterface> s_base_settings_interface;
static std::unique_ptr<HostDisplay> s_host_display;
static bool s_batch_mode = false;
static bool s_nogui_mode = false;
static bool s_start_fullscreen_ui = false;
@ -206,13 +205,13 @@ void EmuThread::stopFullscreenUI()
QMetaObject::invokeMethod(this, &EmuThread::stopFullscreenUI, Qt::QueuedConnection);
// wait until the host display is gone
while (s_host_display)
while (g_host_display)
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents, 1);
return;
}
if (!s_host_display)
if (!g_host_display)
return;
pxAssertRel(!VMManager::HasValidVM(), "VM is not valid at FSUI shutdown time");
@ -595,7 +594,7 @@ void EmuThread::checkForSettingChanges()
{
QMetaObject::invokeMethod(g_main_window, &MainWindow::checkForSettingChanges, Qt::QueuedConnection);
if (s_host_display)
if (g_host_display)
{
const bool render_to_main = shouldRenderToMain();
if (!m_is_fullscreen && m_is_rendering_to_main != render_to_main)
@ -769,7 +768,7 @@ void EmuThread::connectDisplaySignals(DisplayWidget* widget)
void EmuThread::onDisplayWindowResized(int width, int height, float scale)
{
if (!s_host_display)
if (!g_host_display)
return;
GetMTGS().ResizeDisplayWindow(width, height, scale);
@ -842,76 +841,72 @@ void EmuThread::updateDisplay()
pxAssertRel(!isOnEmuThread(), "Not on emu thread");
// finished with the display for now
HostDisplay* display = Host::GetHostDisplay();
display->DoneRenderContextCurrent();
g_host_display->DoneRenderContextCurrent();
// but we should get it back after this call
onUpdateDisplayRequested(m_is_fullscreen, !m_is_fullscreen && m_is_rendering_to_main, m_is_surfaceless);
if (!display->MakeRenderContextCurrent())
if (!g_host_display->MakeRenderContextCurrent())
{
pxFailRel("Failed to recreate context after updating");
return;
}
}
HostDisplay* EmuThread::acquireHostDisplay(HostDisplay::RenderAPI api)
bool EmuThread::acquireHostDisplay(HostDisplay::RenderAPI api)
{
s_host_display = HostDisplay::CreateDisplayForAPI(api);
if (!s_host_display)
return nullptr;
pxAssertRel(!g_host_display, "Host display does not exist on create");
g_host_display = HostDisplay::CreateDisplayForAPI(api);
if (!g_host_display)
return false;
DisplayWidget* widget = emit onCreateDisplayRequested(m_is_fullscreen, m_is_rendering_to_main);
if (!widget)
{
s_host_display.reset();
return nullptr;
g_host_display.reset();
return false;
}
connectDisplaySignals(widget);
if (!s_host_display->MakeRenderContextCurrent())
if (!g_host_display->MakeRenderContextCurrent())
{
Console.Error("Failed to make render context current");
releaseHostDisplay();
return nullptr;
return false;
}
if (!s_host_display->InitializeRenderDevice(EmuFolders::Cache, false) ||
if (!g_host_display->InitializeRenderDevice(EmuFolders::Cache, false) ||
!ImGuiManager::Initialize())
{
Console.Error("Failed to initialize device/imgui");
releaseHostDisplay();
return nullptr;
return false;
}
Console.WriteLn(Color_StrongGreen, "%s Graphics Driver Info:", HostDisplay::RenderAPIToString(s_host_display->GetRenderAPI()));
Console.Indent().WriteLn(s_host_display->GetDriverInfo());
Console.WriteLn(Color_StrongGreen, "%s Graphics Driver Info:", HostDisplay::RenderAPIToString(g_host_display->GetRenderAPI()));
Console.Indent().WriteLn(g_host_display->GetDriverInfo());
if (m_run_fullscreen_ui && !FullscreenUI::Initialize())
{
Console.Error("Failed to initialize fullscreen UI");
releaseHostDisplay();
m_run_fullscreen_ui = false;
return nullptr;
return false;
}
return s_host_display.get();
return true;
}
void EmuThread::releaseHostDisplay()
{
ImGuiManager::Shutdown();
s_host_display.reset();
g_host_display.reset();
emit onDestroyDisplayRequested();
}
HostDisplay* Host::GetHostDisplay()
{
return s_host_display.get();
}
HostDisplay* Host::AcquireHostDisplay(HostDisplay::RenderAPI api)
bool Host::AcquireHostDisplay(HostDisplay::RenderAPI api)
{
return g_emu_thread->acquireHostDisplay(api);
}
@ -923,7 +918,7 @@ void Host::ReleaseHostDisplay()
bool Host::BeginPresentFrame(bool frame_skip)
{
if (!s_host_display->BeginPresent(frame_skip))
if (!g_host_display->BeginPresent(frame_skip))
{
// if we're skipping a frame, we need to reset imgui's state, since
// we won't be calling EndPresentFrame().
@ -941,13 +936,13 @@ void Host::EndPresentFrame()
FullscreenUI::Render();
ImGuiManager::RenderOSD();
s_host_display->EndPresent();
g_host_display->EndPresent();
ImGuiManager::NewFrame();
}
void Host::ResizeHostDisplay(u32 new_window_width, u32 new_window_height, float new_window_scale)
{
s_host_display->ResizeRenderWindow(new_window_width, new_window_height, new_window_scale);
g_host_display->ResizeRenderWindow(new_window_width, new_window_height, new_window_scale);
ImGuiManager::WindowResized();
// if we're paused, re-present the current frame at the new window size.

View File

@ -69,7 +69,7 @@ public:
bool isOnEmuThread() const;
/// Called back from the GS thread when the display state changes (e.g. fullscreen, render to main).
HostDisplay* acquireHostDisplay(HostDisplay::RenderAPI api);
bool acquireHostDisplay(HostDisplay::RenderAPI api);
void connectDisplaySignals(DisplayWidget* widget);
void releaseHostDisplay();
void updateDisplay();

View File

@ -361,7 +361,7 @@ static double AdjustToHostRefreshRate(double vertical_frequency, double frame_li
}
float host_refresh_rate;
if (!Host::GetHostDisplay()->GetHostRefreshRate(&host_refresh_rate))
if (!g_host_display->GetHostRefreshRate(&host_refresh_rate))
{
Console.Warning("Cannot sync to host refresh since the query failed.");
SPU2SetDeviceSampleRateMultiplier(1.0);

View File

@ -465,7 +465,7 @@ void FullscreenUI::UpdateForcedVsync(bool should_force)
const VsyncMode mode = EmuConfig.GetEffectiveVsyncMode();
// toss it through regardless of the mode, because options can change it
Host::GetHostDisplay()->SetVSync((should_force && mode == VsyncMode::Off) ? VsyncMode::On : mode);
g_host_display->SetVSync((should_force && mode == VsyncMode::Off) ? VsyncMode::On : mode);
}
void FullscreenUI::OnVMStarted()
@ -1707,8 +1707,7 @@ void FullscreenUI::SwitchToGameSettings(const GameList::Entry* entry)
void FullscreenUI::PopulateGraphicsAdapterList()
{
HostDisplay* display = Host::GetHostDisplay();
HostDisplay::AdapterAndModeList ml(display->GetAdapterAndModeList());
HostDisplay::AdapterAndModeList ml(g_host_display->GetAdapterAndModeList());
s_graphics_adapter_list_cache = std::move(ml.adapter_names);
s_fullscreen_mode_list_cache = std::move(ml.fullscreen_modes);
s_fullscreen_mode_list_cache.insert(s_fullscreen_mode_list_cache.begin(), "Borderless Fullscreen");
@ -3600,7 +3599,7 @@ bool FullscreenUI::InitializeSaveStateListEntry(
std::vector<u32> screenshot_pixels;
if (SaveState_ReadScreenshot(li->path, &screenshot_width, &screenshot_height, &screenshot_pixels))
{
li->preview_texture = Host::GetHostDisplay()->CreateTexture(
li->preview_texture = g_host_display->CreateTexture(
screenshot_width, screenshot_height, screenshot_pixels.data(), sizeof(u32) * screenshot_width, false);
if (!li->preview_texture)
Console.Error("Failed to upload save state image to GPU");

View File

@ -278,7 +278,7 @@ std::optional<Common::RGBA8Image> ImGuiFullscreen::LoadTextureImage(const char*
std::shared_ptr<HostDisplayTexture> ImGuiFullscreen::UploadTexture(const char* path, const Common::RGBA8Image& image)
{
std::unique_ptr<HostDisplayTexture> texture =
Host::GetHostDisplay()->CreateTexture(image.GetWidth(), image.GetHeight(), image.GetPixels(), image.GetByteStride());
g_host_display->CreateTexture(image.GetWidth(), image.GetHeight(), image.GetPixels(), image.GetByteStride());
if (!texture)
{
Console.Error("failed to create %ux%u texture for resource", image.GetWidth(), image.GetHeight());

View File

@ -95,8 +95,7 @@ bool ImGuiManager::Initialize()
return false;
}
HostDisplay* display = Host::GetHostDisplay();
s_global_scale = std::max(1.0f, display->GetWindowScale() * static_cast<float>(EmuConfig.GS.OsdScale / 100.0));
s_global_scale = std::max(1.0f, g_host_display->GetWindowScale() * static_cast<float>(EmuConfig.GS.OsdScale / 100.0));
ImGui::CreateContext();
@ -110,8 +109,8 @@ bool ImGuiManager::Initialize()
#endif
io.DisplayFramebufferScale = ImVec2(1, 1); // We already scale things ourselves, this would double-apply scaling
io.DisplaySize.x = static_cast<float>(display->GetWindowWidth());
io.DisplaySize.y = static_cast<float>(display->GetWindowHeight());
io.DisplaySize.x = static_cast<float>(g_host_display->GetWindowWidth());
io.DisplaySize.y = static_cast<float>(g_host_display->GetWindowHeight());
SetKeyMap();
SetStyle();
@ -120,19 +119,19 @@ bool ImGuiManager::Initialize()
pxAssertRel(!FullscreenUI::IsInitialized(), "Fullscreen UI is not initialized on ImGui init");
#endif
if (!display->CreateImGuiContext())
if (!g_host_display->CreateImGuiContext())
{
pxFailRel("Failed to create ImGui device context");
display->DestroyImGuiContext();
g_host_display->DestroyImGuiContext();
ImGui::DestroyContext();
UnloadFontData();
return false;
}
if (!AddImGuiFonts(false) || !display->UpdateImGuiFontTexture())
if (!AddImGuiFonts(false) || !g_host_display->UpdateImGuiFontTexture())
{
pxFailRel("Failed to create ImGui font text");
display->DestroyImGuiContext();
g_host_display->DestroyImGuiContext();
ImGui::DestroyContext();
UnloadFontData();
return false;
@ -151,9 +150,8 @@ void ImGuiManager::Shutdown()
FullscreenUI::Shutdown();
#endif
HostDisplay* display = Host::GetHostDisplay();
if (display)
display->DestroyImGuiContext();
if (g_host_display)
g_host_display->DestroyImGuiContext();
if (ImGui::GetCurrentContext())
ImGui::DestroyContext();
@ -170,10 +168,8 @@ void ImGuiManager::Shutdown()
void ImGuiManager::WindowResized()
{
HostDisplay* display = Host::GetHostDisplay();
const u32 new_width = display ? display->GetWindowWidth() : 0;
const u32 new_height = display ? display->GetWindowHeight() : 0;
const u32 new_width = g_host_display ? g_host_display->GetWindowWidth() : 0;
const u32 new_height = g_host_display ? g_host_display->GetWindowHeight() : 0;
ImGui::GetIO().DisplaySize = ImVec2(static_cast<float>(new_width), static_cast<float>(new_height));
@ -186,8 +182,7 @@ void ImGuiManager::WindowResized()
void ImGuiManager::UpdateScale()
{
HostDisplay* display = Host::GetHostDisplay();
const float window_scale = display ? display->GetWindowScale() : 1.0f;
const float window_scale = g_host_display ? g_host_display->GetWindowScale() : 1.0f;
const float scale = std::max(window_scale * static_cast<float>(EmuConfig.GS.OsdScale / 100.0), 1.0f);
#ifdef PCSX2_CORE
@ -211,7 +206,7 @@ void ImGuiManager::UpdateScale()
if (!AddImGuiFonts(HasFullscreenFonts()))
pxFailRel("Failed to create ImGui font text");
if (!display->UpdateImGuiFontTexture())
if (!g_host_display->UpdateImGuiFontTexture())
pxFailRel("Failed to recreate font texture after scale+resize");
NewFrame();
@ -483,7 +478,7 @@ bool ImGuiManager::AddFullscreenFontsIfMissing()
AddImGuiFonts(false);
}
Host::GetHostDisplay()->UpdateImGuiFontTexture();
g_host_display->UpdateImGuiFontTexture();
NewFrame();
return HasFullscreenFonts();

View File

@ -158,8 +158,8 @@ void GSclose()
g_gs_device.reset();
}
if (HostDisplay* display = Host::GetHostDisplay(); display)
display->SetGPUTimingEnabled(false);
if (g_host_display)
g_host_display->SetGPUTimingEnabled(false);
Host::ReleaseHostDisplay();
}
@ -212,12 +212,9 @@ static HostDisplay::RenderAPI GetAPIForRenderer(GSRendererType renderer)
static bool DoGSOpen(GSRendererType renderer, u8* basemem)
{
HostDisplay* display = Host::GetHostDisplay();
pxAssert(display);
s_render_api = g_host_display->GetRenderAPI();
s_render_api = Host::GetHostDisplay()->GetRenderAPI();
switch (display->GetRenderAPI())
switch (g_host_display->GetRenderAPI())
{
#ifdef _WIN32
case HostDisplay::RenderAPI::D3D11:
@ -246,13 +243,13 @@ static bool DoGSOpen(GSRendererType renderer, u8* basemem)
#endif
default:
Console.Error("Unknown render API %u", static_cast<unsigned>(display->GetRenderAPI()));
Console.Error("Unknown render API %u", static_cast<unsigned>(g_host_display->GetRenderAPI()));
return false;
}
try
{
if (!g_gs_device->Create(display))
if (!g_gs_device->Create())
{
g_gs_device->Destroy();
g_gs_device.reset();
@ -285,11 +282,11 @@ static bool DoGSOpen(GSRendererType renderer, u8* basemem)
#ifdef PCSX2_CORE
// Don't override the fullscreen UI's vsync choice.
if (!FullscreenUI::IsInitialized())
display->SetVSync(EmuConfig.GetEffectiveVsyncMode());
g_host_display->SetVSync(EmuConfig.GetEffectiveVsyncMode());
#else
display->SetVSync(EmuConfig.GetEffectiveVsyncMode());
g_host_display->SetVSync(EmuConfig.GetEffectiveVsyncMode());
#endif
GSConfig.OsdShowGPU = EmuConfig.GS.OsdShowGPU && display->SetGPUTimingEnabled(true);
GSConfig.OsdShowGPU = EmuConfig.GS.OsdShowGPU && g_host_display->SetGPUTimingEnabled(true);
g_gs_renderer->SetRegsMem(basemem);
g_perfmon.Reset();
@ -765,20 +762,19 @@ void GSUpdateConfig(const Pcsx2Config::GSOptions& new_config)
if (!g_gs_renderer)
return;
HostDisplay* display = Host::GetHostDisplay();
// Handle OSD scale changes by pushing a window resize through.
if (new_config.OsdScale != old_config.OsdScale)
{
g_gs_device->ResetAPIState();
Host::ResizeHostDisplay(display->GetWindowWidth(), display->GetWindowHeight(), display->GetWindowScale());
Host::ResizeHostDisplay(g_host_display->GetWindowWidth(), g_host_display->GetWindowHeight(), g_host_display->GetWindowScale());
g_gs_device->RestoreAPIState();
}
// Options which need a full teardown/recreate.
if (!GSConfig.RestartOptionsAreEqual(old_config))
{
HostDisplay::RenderAPI existing_api = Host::GetHostDisplay()->GetRenderAPI();
HostDisplay::RenderAPI existing_api = g_host_display->GetRenderAPI();
if (existing_api == HostDisplay::RenderAPI::OpenGLES)
existing_api = HostDisplay::RenderAPI::OpenGL;
@ -868,11 +864,8 @@ void GSUpdateConfig(const Pcsx2Config::GSOptions& new_config)
if (GSConfig.OsdShowGPU != old_config.OsdShowGPU)
{
if (HostDisplay* display = Host::GetHostDisplay(); display)
{
if (!display->SetGPUTimingEnabled(GSConfig.OsdShowGPU))
GSConfig.OsdShowGPU = false;
}
if (!g_host_display->SetGPUTimingEnabled(GSConfig.OsdShowGPU))
GSConfig.OsdShowGPU = false;
}
}
@ -884,7 +877,7 @@ void GSSwitchRenderer(GSRendererType new_renderer)
if (!g_gs_renderer || GSConfig.Renderer == new_renderer)
return;
HostDisplay::RenderAPI existing_api = Host::GetHostDisplay()->GetRenderAPI();
HostDisplay::RenderAPI existing_api = g_host_display->GetRenderAPI();
if (existing_api == HostDisplay::RenderAPI::OpenGLES)
existing_api = HostDisplay::RenderAPI::OpenGL;

View File

@ -88,9 +88,8 @@ GSDevice::~GSDevice()
delete m_target_tmp;
}
bool GSDevice::Create(HostDisplay* display)
bool GSDevice::Create()
{
m_display = display;
return true;
}

View File

@ -740,8 +740,6 @@ private:
protected:
static constexpr u32 MAX_POOLED_TEXTURES = 300;
HostDisplay* m_display = nullptr;
GSTexture* m_merge = nullptr;
GSTexture* m_weavebob = nullptr;
GSTexture* m_blend = nullptr;
@ -772,7 +770,6 @@ public:
GSDevice();
virtual ~GSDevice();
__fi HostDisplay* GetDisplay() const { return m_display; }
__fi unsigned int GetFrameNumber() const { return m_frame; }
void Recycle(GSTexture* t);
@ -793,7 +790,7 @@ public:
Performance
};
virtual bool Create(HostDisplay* display);
virtual bool Create();
virtual void Destroy();
virtual void ResetAPIState();

View File

@ -619,11 +619,10 @@ void GSRenderer::VSync(u32 field, bool registers_written)
GSTexture* current = g_gs_device->GetCurrent();
if (current && !blank_frame)
{
HostDisplay* const display = g_gs_device->GetDisplay();
const GSVector4i src_rect(CalculateDrawSrcRect(current));
const GSVector4 src_uv(GSVector4(src_rect) / GSVector4(current->GetSize()).xyxy());
const GSVector4 draw_rect(CalculateDrawDstRect(display->GetWindowWidth(), display->GetWindowHeight(),
src_rect, current->GetSize(), display->GetDisplayAlignment(), display->UsesLowerLeftOrigin(),
const GSVector4 draw_rect(CalculateDrawDstRect(g_host_display->GetWindowWidth(), g_host_display->GetWindowHeight(),
src_rect, current->GetSize(), g_host_display->GetDisplayAlignment(), g_host_display->UsesLowerLeftOrigin(),
GetVideoMode() == GSVideoMode::SDTV_480P || (GSConfig.PCRTCOverscan && GSConfig.PCRTCOffsets)));
const u64 current_time = Common::Timer::GetCurrentValue();
@ -636,7 +635,7 @@ void GSRenderer::VSync(u32 field, bool registers_written)
Host::EndPresentFrame();
if (GSConfig.OsdShowGPU)
PerformanceMetrics::OnGPUPresent(Host::GetHostDisplay()->GetAndResetAccumulatedGPUTime());
PerformanceMetrics::OnGPUPresent(g_host_display->GetAndResetAccumulatedGPUTime());
}
g_gs_device->RestoreAPIState();
PerformanceMetrics::Update(registers_written, fb_sprite_frame);
@ -827,11 +826,10 @@ void GSRenderer::PresentCurrentFrame()
GSTexture* current = g_gs_device->GetCurrent();
if (current)
{
HostDisplay* const display = g_gs_device->GetDisplay();
const GSVector4i src_rect(CalculateDrawSrcRect(current));
const GSVector4 src_uv(GSVector4(src_rect) / GSVector4(current->GetSize()).xyxy());
const GSVector4 draw_rect(CalculateDrawDstRect(display->GetWindowWidth(), display->GetWindowHeight(),
src_rect, current->GetSize(), display->GetDisplayAlignment(), display->UsesLowerLeftOrigin(),
const GSVector4 draw_rect(CalculateDrawDstRect(g_host_display->GetWindowWidth(), g_host_display->GetWindowHeight(),
src_rect, current->GetSize(), g_host_display->GetDisplayAlignment(), g_host_display->UsesLowerLeftOrigin(),
GetVideoMode() == GSVideoMode::SDTV_480P || (GSConfig.PCRTCOverscan && GSConfig.PCRTCOffsets)));
const u64 current_time = Common::Timer::GetCurrentValue();

View File

@ -66,9 +66,9 @@ GSDevice11::~GSDevice11()
m_state.dsv->Release();
}
bool GSDevice11::Create(HostDisplay* display)
bool GSDevice11::Create()
{
if (!__super::Create(display))
if (!GSDevice::Create())
return false;
D3D11_BUFFER_DESC bd;
@ -79,14 +79,14 @@ bool GSDevice11::Create(HostDisplay* display)
D3D_FEATURE_LEVEL level;
if (display->GetRenderAPI() != HostDisplay::RenderAPI::D3D11)
if (g_host_display->GetRenderAPI() != HostDisplay::RenderAPI::D3D11)
{
fprintf(stderr, "Render API is incompatible with D3D11\n");
return false;
}
m_dev = static_cast<ID3D11Device*>(display->GetRenderDevice());
m_ctx = static_cast<ID3D11DeviceContext*>(display->GetRenderContext());
m_dev = static_cast<ID3D11Device*>(g_host_display->GetRenderDevice());
m_ctx = static_cast<ID3D11DeviceContext*>(g_host_display->GetRenderContext());
level = m_dev->GetFeatureLevel();
if (!GSConfig.DisableShaderCache)
@ -633,7 +633,7 @@ void GSDevice11::StretchRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
}
else
{
ds = GSVector2i(m_display->GetWindowWidth(), m_display->GetWindowHeight());
ds = GSVector2i(g_host_display->GetWindowWidth(), g_host_display->GetWindowHeight());
}
@ -709,7 +709,7 @@ void GSDevice11::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
}
else
{
ds = GSVector2i(m_display->GetWindowWidth(), m_display->GetWindowHeight());
ds = GSVector2i(g_host_display->GetWindowWidth(), g_host_display->GetWindowHeight());
}
DisplayConstantBuffer cb;

View File

@ -241,7 +241,7 @@ public:
__fi ID3D11Device* GetD3DDevice() const { return m_dev.get(); }
__fi ID3D11DeviceContext* GetD3DContext() const { return m_ctx.get(); }
bool Create(HostDisplay* display);
bool Create() override;
void ResetAPIState() override;
void RestoreAPIState() override;

View File

@ -95,9 +95,9 @@ GSDevice12::GSDevice12()
GSDevice12::~GSDevice12() {}
bool GSDevice12::Create(HostDisplay* display)
bool GSDevice12::Create()
{
if (!GSDevice::Create(display) || !CheckFeatures())
if (!GSDevice::Create() || !CheckFeatures())
return false;
{
@ -491,7 +491,7 @@ void GSDevice12::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
{
DisplayConstantBuffer cb;
cb.SetSource(sRect, sTex->GetSize());
cb.SetTarget(dRect, dTex ? dTex->GetSize() : GSVector2i(m_display->GetWindowWidth(), m_display->GetWindowHeight()));
cb.SetTarget(dRect, dTex ? dTex->GetSize() : GSVector2i(g_host_display->GetWindowWidth(), g_host_display->GetWindowHeight()));
cb.SetTime(shaderTime);
SetUtilityRootSignature();
SetUtilityPushConstants(&cb, sizeof(cb));
@ -540,7 +540,7 @@ void GSDevice12::DoStretchRect(GSTexture12* sTex, const GSVector4& sRect, GSText
const bool is_present = (!dTex);
const bool depth = (dTex && dTex->GetType() == GSTexture::Type::DepthStencil);
const GSVector2i size(
is_present ? GSVector2i(m_display->GetWindowWidth(), m_display->GetWindowHeight()) : dTex->GetSize());
is_present ? GSVector2i(g_host_display->GetWindowWidth(), g_host_display->GetWindowHeight()) : dTex->GetSize());
const GSVector4i dtex_rc(0, 0, size.x, size.y);
const GSVector4i dst_rc(GSVector4i(dRect).rintersect(dtex_rc));

View File

@ -223,7 +223,7 @@ public:
__fi static GSDevice12* GetInstance() { return static_cast<GSDevice12*>(g_gs_device.get()); }
bool Create(HostDisplay* display) override;
bool Create() override;
void Destroy() override;
void ResetAPIState() override;

View File

@ -343,7 +343,7 @@ public:
MRCOwned<id<MTLFunction>> LoadShader(NSString* name);
MRCOwned<id<MTLRenderPipelineState>> MakePipeline(MTLRenderPipelineDescriptor* desc, id<MTLFunction> vertex, id<MTLFunction> fragment, NSString* name);
bool Create(HostDisplay* display) override;
bool Create() override;
void ClearRenderTarget(GSTexture* t, const GSVector4& c) override;
void ClearRenderTarget(GSTexture* t, u32 c) override;

View File

@ -226,7 +226,7 @@ void GSDeviceMTL::DrawCommandBufferFinished(u64 draw, id<MTLCommandBuffer> buffe
// We can do the update non-atomically because we only ever update under the lock
u64 newval = std::max(draw, m_last_finished_draw.load(std::memory_order_relaxed));
m_last_finished_draw.store(newval, std::memory_order_release);
static_cast<MetalHostDisplay*>(m_display)->AccumulateCommandBufferTime(buffer);
static_cast<MetalHostDisplay*>(g_host_display.get())->AccumulateCommandBufferTime(buffer);
}
void GSDeviceMTL::FlushEncoders()
@ -576,19 +576,19 @@ static void setFnConstantI(MTLFunctionConstantValues* fc, unsigned int value, GS
[fc setConstantValue:&value type:MTLDataTypeUInt atIndex:constant];
}
bool GSDeviceMTL::Create(HostDisplay* display)
bool GSDeviceMTL::Create()
{ @autoreleasepool {
if (!GSDevice::Create(display))
if (!GSDevice::Create())
return false;
if (display->GetRenderAPI() != HostDisplay::RenderAPI::Metal)
if (g_host_display->GetRenderAPI() != HostDisplay::RenderAPI::Metal)
return false;
if (!m_display->HasRenderDevice() || !m_display->HasRenderSurface())
if (!g_host_display->HasRenderDevice() || !g_host_display->HasRenderSurface())
return false;
m_dev = *static_cast<const GSMTLDevice*>(m_display->GetRenderDevice());
m_queue = MRCRetain((__bridge id<MTLCommandQueue>)m_display->GetRenderContext());
MTLPixelFormat layer_px_fmt = [(__bridge CAMetalLayer*)m_display->GetRenderSurface() pixelFormat];
m_dev = *static_cast<const GSMTLDevice*>(g_host_display->GetRenderDevice());
m_queue = MRCRetain((__bridge id<MTLCommandQueue>)g_host_display->GetRenderContext());
MTLPixelFormat layer_px_fmt = [(__bridge CAMetalLayer*)g_host_display->GetRenderSurface() pixelFormat];
m_features.broken_point_sampler = [[m_dev.dev name] containsString:@"AMD"];
m_features.geometry_shader = false;
@ -1109,7 +1109,7 @@ static_assert(offsetof(DisplayConstantBuffer, TimeAndPad.x) == offsetof(G
void GSDeviceMTL::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture* dTex, const GSVector4& dRect, PresentShader shader, float shaderTime, bool linear)
{ @autoreleasepool {
GSVector2i ds = dTex ? dTex->GetSize() : GSVector2i(m_display->GetWindowWidth(), m_display->GetWindowHeight());
GSVector2i ds = dTex ? dTex->GetSize() : GSVector2i(g_host_display->GetWindowWidth(), g_host_display->GetWindowHeight());
DisplayConstantBuffer cb;
cb.SetSource(sRect, sTex->GetSize());
cb.SetTarget(dRect, ds);
@ -1806,7 +1806,7 @@ void GSDeviceMTL::RenderImGui(ImDrawData* data)
[enc setVertexBuffer:map.gpu_buffer offset:map.gpu_offset atIndex:GSMTLBufferIndexVertices];
[enc setVertexBytes:&transform length:sizeof(transform) atIndex:GSMTLBufferIndexUniforms];
simd::uint4 last_scissor = simd::make_uint4(0, 0, m_display->GetWindowWidth(), m_display->GetWindowHeight());
simd::uint4 last_scissor = simd::make_uint4(0, 0, g_host_display->GetWindowWidth(), g_host_display->GetWindowHeight());
simd::float2 fb_size = simd_float(last_scissor.zw);
simd::float2 clip_off = ToSimd(data->DisplayPos); // (0,0) unless using multi-viewports
simd::float2 clip_scale = ToSimd(data->FramebufferScale); // (1,1) unless using retina display which are often (2,2)

View File

@ -191,12 +191,12 @@ GSTexture* GSDeviceOGL::CreateSurface(GSTexture::Type type, int width, int heigh
return new GSTextureOGL(type, width, height, levels, format, m_fbo_read);
}
bool GSDeviceOGL::Create(HostDisplay* display)
bool GSDeviceOGL::Create()
{
if (!GSDevice::Create(display))
if (!GSDevice::Create())
return false;
if (display->GetRenderAPI() != HostDisplay::RenderAPI::OpenGL)
if (g_host_display->GetRenderAPI() != HostDisplay::RenderAPI::OpenGL)
return false;
// Check openGL requirement as soon as possible so we can switch to another
@ -1250,7 +1250,7 @@ void GSDeviceOGL::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture
BeginScene();
const GSVector2i ds(dTex ? dTex->GetSize() : GSVector2i(m_display->GetWindowWidth(), m_display->GetWindowHeight()));
const GSVector2i ds(dTex ? dTex->GetSize() : GSVector2i(g_host_display->GetWindowWidth(), g_host_display->GetWindowHeight()));
DisplayConstantBuffer cb;
cb.SetSource(sRect, sTex->GetSize());
cb.SetTarget(dRect, ds);

View File

@ -323,7 +323,7 @@ public:
// Used by OpenGL, so the same calling convention is required.
static void APIENTRY DebugOutputToFile(GLenum gl_source, GLenum gl_type, GLuint id, GLenum gl_severity, GLsizei gl_length, const GLchar* gl_message, const void* userParam);
bool Create(HostDisplay* display) override;
bool Create() override;
void ResetAPIState() override;
void RestoreAPIState() override;

View File

@ -65,9 +65,9 @@ GSDeviceVK::GSDeviceVK()
GSDeviceVK::~GSDeviceVK() {}
bool GSDeviceVK::Create(HostDisplay* display)
bool GSDeviceVK::Create()
{
if (!GSDevice::Create(display) || !CheckFeatures())
if (!GSDevice::Create() || !CheckFeatures())
return false;
{
@ -590,7 +590,7 @@ void GSDeviceVK::PresentRect(GSTexture* sTex, const GSVector4& sRect, GSTexture*
{
DisplayConstantBuffer cb;
cb.SetSource(sRect, sTex->GetSize());
cb.SetTarget(dRect, dTex ? dTex->GetSize() : GSVector2i(m_display->GetWindowWidth(), m_display->GetWindowHeight()));
cb.SetTarget(dRect, dTex ? dTex->GetSize() : GSVector2i(g_host_display->GetWindowWidth(), g_host_display->GetWindowHeight()));
cb.SetTime(shaderTime);
SetUtilityPushConstants(&cb, sizeof(cb));
@ -655,7 +655,7 @@ void GSDeviceVK::DoStretchRect(GSTextureVK* sTex, const GSVector4& sRect, GSText
const bool is_present = (!dTex);
const bool depth = (dTex && dTex->GetType() == GSTexture::Type::DepthStencil);
const GSVector2i size(
is_present ? GSVector2i(m_display->GetWindowWidth(), m_display->GetWindowHeight()) : dTex->GetSize());
is_present ? GSVector2i(g_host_display->GetWindowWidth(), g_host_display->GetWindowHeight()) : dTex->GetSize());
const GSVector4i dtex_rc(0, 0, size.x, size.y);
const GSVector4i dst_rc(GSVector4i(dRect).rintersect(dtex_rc));
@ -1307,7 +1307,7 @@ bool GSDeviceVK::CreateRenderPasses()
bool GSDeviceVK::CompileConvertPipelines()
{
// we may not have a swap chain if running in headless mode.
Vulkan::SwapChain* swapchain = static_cast<Vulkan::SwapChain*>(m_display->GetRenderSurface());
Vulkan::SwapChain* swapchain = static_cast<Vulkan::SwapChain*>(g_host_display->GetRenderSurface());
if (swapchain)
{
m_swap_chain_render_pass =
@ -1523,7 +1523,7 @@ bool GSDeviceVK::CompileConvertPipelines()
bool GSDeviceVK::CompilePresentPipelines()
{
// we may not have a swap chain if running in headless mode.
Vulkan::SwapChain* swapchain = static_cast<Vulkan::SwapChain*>(m_display->GetRenderSurface());
Vulkan::SwapChain* swapchain = static_cast<Vulkan::SwapChain*>(g_host_display->GetRenderSurface());
if (swapchain)
{
m_swap_chain_render_pass =

View File

@ -201,7 +201,7 @@ public:
__fi VkSampler GetPointSampler() const { return m_point_sampler; }
__fi VkSampler GetLinearSampler() const { return m_linear_sampler; }
bool Create(HostDisplay* display) override;
bool Create() override;
void Destroy() override;
void ResetAPIState() override;

View File

@ -26,6 +26,8 @@
#include <thread>
#include <vector>
std::unique_ptr<HostDisplay> g_host_display;
HostDisplayTexture::~HostDisplayTexture() = default;
HostDisplay::~HostDisplay() = default;

View File

@ -149,17 +149,17 @@ protected:
VsyncMode m_vsync_mode = VsyncMode::Off;
};
/// Returns a pointer to the current host display abstraction. Assumes AcquireHostDisplay() has been caled.
extern std::unique_ptr<HostDisplay> g_host_display;
namespace Host
{
/// Creates the host display. This may create a new window. The API used depends on the current configuration.
HostDisplay* AcquireHostDisplay(HostDisplay::RenderAPI api);
bool AcquireHostDisplay(HostDisplay::RenderAPI api);
/// Destroys the host display. This may close the display window.
void ReleaseHostDisplay();
/// Returns a pointer to the current host display abstraction. Assumes AcquireHostDisplay() has been caled.
HostDisplay* GetHostDisplay();
/// Returns false if the window was completely occluded. If frame_skip is set, the frame won't be
/// displayed, but the GPU command queue will still be flushed.
bool BeginPresentFrame(bool frame_skip);

View File

@ -966,7 +966,7 @@ void SysMtgsThread::SetVSync(VsyncMode mode)
pxAssertRel(IsOpen(), "MTGS is running");
RunOnGSThread([mode]() {
Host::GetHostDisplay()->SetVSync(mode);
g_host_display->SetVSync(mode);
});
}

View File

@ -914,7 +914,7 @@ bool VMManager::Initialize(VMBootParameters boot_params)
};
Console.WriteLn("Opening PAD...");
if (PADinit() != 0 || PADopen(Host::GetHostDisplay()->GetWindowInfo()) != 0)
if (PADinit() != 0 || PADopen(g_host_display->GetWindowInfo()) != 0)
{
Host::ReportErrorAsync("Startup Error", "Failed to initialize PAD.");
return false;
@ -936,7 +936,7 @@ bool VMManager::Initialize(VMBootParameters boot_params)
};
Console.WriteLn("Opening USB...");
if (USBinit() != 0 || USBopen(Host::GetHostDisplay()->GetWindowInfo()) != 0)
if (USBinit() != 0 || USBopen(g_host_display->GetWindowInfo()) != 0)
{
Host::ReportErrorAsync("Startup Error", "Failed to initialize USB.");
return false;

View File

@ -107,55 +107,48 @@ bool Host::ConfirmMessage(const std::string_view& title, const std::string_view&
return true;
}
static std::unique_ptr<HostDisplay> s_host_display;
HostDisplay* Host::AcquireHostDisplay(HostDisplay::RenderAPI api)
bool Host::AcquireHostDisplay(HostDisplay::RenderAPI api)
{
sApp.OpenGsPanel();
// can't go anywhere if we don't have a window to render into!
if (g_gs_window_info.type == WindowInfo::Type::Surfaceless)
return nullptr;
return false;
s_host_display = HostDisplay::CreateDisplayForAPI(api);
if (!s_host_display)
return nullptr;
g_host_display = HostDisplay::CreateDisplayForAPI(api);
if (!g_host_display)
return false;
if (!s_host_display->CreateRenderDevice(g_gs_window_info, GSConfig.Adapter, EmuConfig.GetEffectiveVsyncMode(),
if (!g_host_display->CreateRenderDevice(g_gs_window_info, GSConfig.Adapter, EmuConfig.GetEffectiveVsyncMode(),
GSConfig.ThreadedPresentation, GSConfig.UseDebugDevice) ||
!s_host_display->InitializeRenderDevice(EmuFolders::Cache, GSConfig.UseDebugDevice) ||
!g_host_display->InitializeRenderDevice(EmuFolders::Cache, GSConfig.UseDebugDevice) ||
!ImGuiManager::Initialize())
{
s_host_display.reset();
return nullptr;
g_host_display.reset();
return false;
}
Console.WriteLn(Color_StrongGreen, "%s Graphics Driver Info:", HostDisplay::RenderAPIToString(s_host_display->GetRenderAPI()));
Console.Indent().WriteLn(s_host_display->GetDriverInfo());
Console.WriteLn(Color_StrongGreen, "%s Graphics Driver Info:", HostDisplay::RenderAPIToString(g_host_display->GetRenderAPI()));
Console.Indent().WriteLn(g_host_display->GetDriverInfo());
return s_host_display.get();
return true;
}
void Host::ReleaseHostDisplay()
{
ImGuiManager::Shutdown();
if (s_host_display)
s_host_display.reset();
if (g_host_display)
g_host_display.reset();
sApp.CloseGsPanel();
}
HostDisplay* Host::GetHostDisplay()
{
return s_host_display.get();
}
bool Host::BeginPresentFrame(bool frame_skip)
{
CheckForGSWindowResize();
if (!s_host_display->BeginPresent(frame_skip))
if (!g_host_display->BeginPresent(frame_skip))
{
// if we're skipping a frame, we need to reset imgui's state, since
// we won't be calling EndPresentFrame().
@ -169,7 +162,7 @@ bool Host::BeginPresentFrame(bool frame_skip)
void Host::EndPresentFrame()
{
ImGuiManager::RenderOSD();
s_host_display->EndPresent();
g_host_display->EndPresent();
ImGuiManager::NewFrame();
}
@ -214,11 +207,11 @@ void Host::CheckForGSWindowResize()
s_gs_window_resized.store(false);
}
if (!s_host_display)
if (!g_host_display)
return;
GSResetAPIState();
s_host_display->ResizeRenderWindow(width, height, scale);
g_host_display->ResizeRenderWindow(width, height, scale);
GSRestoreAPIState();
ImGuiManager::WindowResized();
}