mirror of
https://github.com/WinampDesktop/winamp.git
synced 2025-06-15 18:15:47 -04:00
Rewrite host GPU abstraction
- Don't have to repeat the same thing for 4 renderers. - Add native Metal renderer.
This commit is contained in:
@ -198,7 +198,7 @@ if(WIN32)
|
||||
)
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
if(APPLE AND NOT CMAKE_GENERATOR MATCHES "Xcode")
|
||||
set(BUNDLE_PATH ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/DuckStation.app)
|
||||
|
||||
# Ask for an application bundle.
|
||||
|
@ -333,6 +333,8 @@ void AdvancedSettingsWidget::addTweakOptions()
|
||||
Settings::DEFAULT_GPU_MAX_RUN_AHEAD);
|
||||
addBooleanTweakOption(m_dialog, m_ui.tweakOptionTable, tr("Use Debug Host GPU Device"), "GPU", "UseDebugDevice",
|
||||
false);
|
||||
addBooleanTweakOption(m_dialog, m_ui.tweakOptionTable, tr("Disable Shader Cache"), "GPU", "DisableShaderCache",
|
||||
false);
|
||||
|
||||
addBooleanTweakOption(m_dialog, m_ui.tweakOptionTable, tr("Stretch Display Vertically"), "Display",
|
||||
"StretchVertically", false);
|
||||
@ -388,6 +390,7 @@ void AdvancedSettingsWidget::onResetToDefaultClicked()
|
||||
setIntRangeTweakOption(m_ui.tweakOptionTable, i++,
|
||||
static_cast<int>(Settings::DEFAULT_GPU_MAX_RUN_AHEAD)); // GPU max run-ahead
|
||||
setBooleanTweakOption(m_ui.tweakOptionTable, i++, false); // Use debug host GPU device
|
||||
setBooleanTweakOption(m_ui.tweakOptionTable, i++, false); // Disable Shader Cache
|
||||
setBooleanTweakOption(m_ui.tweakOptionTable, i++, false); // Stretch Display Vertically
|
||||
setBooleanTweakOption(m_ui.tweakOptionTable, i++, true); // Increase Timer Resolution
|
||||
setBooleanTweakOption(m_ui.tweakOptionTable, i++, false); // Allow booting without SBI file
|
||||
|
@ -12,11 +12,11 @@
|
||||
|
||||
// For enumerating adapters.
|
||||
#ifdef _WIN32
|
||||
#include "util/d3d11_host_display.h"
|
||||
#include "util/d3d12_host_display.h"
|
||||
#include "util/d3d11_device.h"
|
||||
#include "util/d3d12_device.h"
|
||||
#endif
|
||||
#ifdef WITH_VULKAN
|
||||
#include "util/vulkan_host_display.h"
|
||||
#include "util/vulkan_device.h"
|
||||
#endif
|
||||
|
||||
DisplaySettingsWidget::DisplaySettingsWidget(SettingsDialog* dialog, QWidget* parent)
|
||||
@ -187,23 +187,28 @@ void DisplaySettingsWidget::setupAdditionalUi()
|
||||
|
||||
void DisplaySettingsWidget::populateGPUAdaptersAndResolutions()
|
||||
{
|
||||
HostDisplay::AdapterAndModeList aml;
|
||||
GPUDevice::AdapterAndModeList aml;
|
||||
bool thread_supported = false;
|
||||
bool threaded_presentation_supported = false;
|
||||
switch (static_cast<GPURenderer>(m_ui.renderer->currentIndex()))
|
||||
{
|
||||
#ifdef _WIN32
|
||||
case GPURenderer::HardwareD3D11:
|
||||
aml = D3D11HostDisplay::StaticGetAdapterAndModeList();
|
||||
aml = D3D11Device::StaticGetAdapterAndModeList();
|
||||
break;
|
||||
|
||||
case GPURenderer::HardwareD3D12:
|
||||
aml = D3D12HostDisplay::StaticGetAdapterAndModeList();
|
||||
aml = D3D12Device::StaticGetAdapterAndModeList();
|
||||
break;
|
||||
#endif
|
||||
#ifdef __APPLE__
|
||||
case GPURenderer::HardwareMetal:
|
||||
aml = GPUDevice::WrapGetMetalAdapterAndModeList();
|
||||
break;
|
||||
#endif
|
||||
#ifdef WITH_VULKAN
|
||||
case GPURenderer::HardwareVulkan:
|
||||
aml = VulkanHostDisplay::StaticGetAdapterAndModeList(nullptr);
|
||||
aml = VulkanDevice::StaticGetAdapterAndModeList();
|
||||
threaded_presentation_supported = true;
|
||||
break;
|
||||
#endif
|
||||
|
@ -2,8 +2,11 @@
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "util/window_info.h"
|
||||
|
||||
#include "common/types.h"
|
||||
#include "common/window_info.h"
|
||||
|
||||
#include <QtWidgets/QStackedWidget>
|
||||
#include <QtWidgets/QWidget>
|
||||
#include <optional>
|
||||
|
@ -24,7 +24,7 @@
|
||||
#include "core/system.h"
|
||||
|
||||
#include "util/cd_image.h"
|
||||
#include "util/host_display.h"
|
||||
#include "util/gpu_device.h"
|
||||
#include "util/platform_misc.h"
|
||||
|
||||
#include "common/assert.h"
|
||||
@ -218,77 +218,33 @@ bool MainWindow::nativeEvent(const QByteArray& eventType, void* message, qintptr
|
||||
|
||||
#endif
|
||||
|
||||
bool MainWindow::createDisplay(bool fullscreen, bool render_to_main)
|
||||
std::optional<WindowInfo> MainWindow::acquireRenderWindow(bool recreate_window, bool fullscreen, bool render_to_main,
|
||||
bool surfaceless, bool use_main_window_pos)
|
||||
{
|
||||
Log_DevPrintf("createDisplay(%u, %u)", static_cast<u32>(fullscreen), static_cast<u32>(render_to_main));
|
||||
|
||||
const std::string fullscreen_mode(Host::GetBaseStringSettingValue("GPU", "FullscreenMode", ""));
|
||||
const bool is_exclusive_fullscreen = (fullscreen && !fullscreen_mode.empty() && g_host_display->SupportsFullscreen());
|
||||
|
||||
createDisplayWidget(fullscreen, render_to_main, is_exclusive_fullscreen);
|
||||
|
||||
std::optional<WindowInfo> wi = m_display_widget->getWindowInfo();
|
||||
if (!wi.has_value())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Failed to get window info from widget"));
|
||||
destroyDisplayWidget(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
g_emu_thread->connectDisplaySignals(m_display_widget);
|
||||
|
||||
if (!g_host_display->CreateDevice(wi.value(), System::ShouldUseVSync()))
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Failed to create host display device context."));
|
||||
destroyDisplayWidget(true);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_display_created = true;
|
||||
|
||||
if (is_exclusive_fullscreen)
|
||||
setDisplayFullscreen(fullscreen_mode);
|
||||
|
||||
updateWindowTitle();
|
||||
updateWindowState();
|
||||
|
||||
m_ui.actionStartFullscreenUI->setEnabled(false);
|
||||
m_ui.actionStartFullscreenUI2->setEnabled(false);
|
||||
|
||||
updateDisplayWidgetCursor();
|
||||
updateDisplayRelatedActions(true, render_to_main, fullscreen);
|
||||
|
||||
m_display_widget->setFocus();
|
||||
|
||||
g_host_display->DoneCurrent();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MainWindow::updateDisplay(bool fullscreen, bool render_to_main, bool surfaceless)
|
||||
{
|
||||
Log_DevPrintf("updateDisplay() fullscreen=%s render_to_main=%s surfaceless=%s", fullscreen ? "true" : "false",
|
||||
render_to_main ? "true" : "false", surfaceless ? "true" : "false");
|
||||
Log_DevPrintf(
|
||||
"acquireRenderWindow() recreate=%s fullscreen=%s render_to_main=%s surfaceless=%s use_main_window_pos=%s",
|
||||
recreate_window ? "true" : "false", fullscreen ? "true" : "false", render_to_main ? "true" : "false",
|
||||
surfaceless ? "true" : "false", use_main_window_pos ? "true" : "false");
|
||||
|
||||
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("GPU", "FullscreenMode", ""));
|
||||
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 true;
|
||||
if (m_display_created && !recreate_window && fullscreen == is_fullscreen && is_rendering_to_main == render_to_main &&
|
||||
!changing_surfaceless)
|
||||
{
|
||||
return m_display_widget ? m_display_widget->getWindowInfo() : WindowInfo();
|
||||
}
|
||||
|
||||
// Skip recreating the surface if we're just transitioning between fullscreen and windowed with render-to-main off.
|
||||
// .. except on Wayland, where everything tends to break if you don't recreate.
|
||||
const bool has_container = (m_display_container != nullptr);
|
||||
const bool needs_container = DisplayContainer::isNeeded(fullscreen, render_to_main);
|
||||
if (!is_rendering_to_main && !render_to_main && !is_exclusive_fullscreen && has_container == needs_container &&
|
||||
!needs_container && !changing_surfaceless)
|
||||
if (m_display_created && !recreate_window && !is_rendering_to_main && !render_to_main &&
|
||||
has_container == needs_container && !needs_container && !changing_surfaceless)
|
||||
{
|
||||
Log_DevPrintf("Toggling to %s without recreating surface", (fullscreen ? "fullscreen" : "windowed"));
|
||||
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)
|
||||
@ -306,53 +262,48 @@ bool MainWindow::updateDisplay(bool fullscreen, bool render_to_main, bool surfac
|
||||
|
||||
updateDisplayWidgetCursor();
|
||||
m_display_widget->setFocus();
|
||||
updateWindowState();
|
||||
|
||||
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||
return true;
|
||||
return m_display_widget->getWindowInfo();
|
||||
}
|
||||
|
||||
g_host_display->DestroySurface();
|
||||
|
||||
destroyDisplayWidget(surfaceless || fullscreen);
|
||||
destroyDisplayWidget(surfaceless);
|
||||
m_display_created = true;
|
||||
|
||||
// if we're going to surfaceless, we're done here
|
||||
if (surfaceless)
|
||||
{
|
||||
updateWindowState();
|
||||
updateDisplayRelatedActions(false, render_to_main, fullscreen);
|
||||
return true;
|
||||
}
|
||||
return WindowInfo();
|
||||
|
||||
createDisplayWidget(fullscreen, render_to_main, is_exclusive_fullscreen);
|
||||
createDisplayWidget(fullscreen, render_to_main, use_main_window_pos);
|
||||
|
||||
// we need the surface visible.. this might be able to be replaced with something else
|
||||
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||
|
||||
std::optional<WindowInfo> wi = m_display_widget->getWindowInfo();
|
||||
if (!wi.has_value())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Error"), tr("Failed to get new window info from widget"));
|
||||
QMessageBox::critical(this, tr("Error"), tr("Failed to get window info from widget"));
|
||||
destroyDisplayWidget(true);
|
||||
return false;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
g_emu_thread->connectDisplaySignals(m_display_widget);
|
||||
|
||||
if (!g_host_display->ChangeWindow(wi.value()))
|
||||
Panic("Failed to recreate surface on new widget.");
|
||||
|
||||
if (is_exclusive_fullscreen)
|
||||
setDisplayFullscreen(fullscreen_mode);
|
||||
|
||||
updateWindowTitle();
|
||||
updateWindowState();
|
||||
|
||||
m_ui.actionStartFullscreenUI->setEnabled(false);
|
||||
m_ui.actionStartFullscreenUI2->setEnabled(false);
|
||||
|
||||
updateDisplayWidgetCursor();
|
||||
updateDisplayRelatedActions(true, render_to_main, fullscreen);
|
||||
m_display_widget->setFocus();
|
||||
|
||||
QSignalBlocker blocker(m_ui.actionFullscreen);
|
||||
m_ui.actionFullscreen->setChecked(fullscreen);
|
||||
return true;
|
||||
return wi;
|
||||
}
|
||||
|
||||
void MainWindow::createDisplayWidget(bool fullscreen, bool render_to_main, bool is_exclusive_fullscreen)
|
||||
void MainWindow::createDisplayWidget(bool fullscreen, bool render_to_main, bool use_main_window_pos)
|
||||
{
|
||||
// If we're rendering to main and were hidden (e.g. coming back from fullscreen),
|
||||
// make sure we're visible before trying to add ourselves. Otherwise Wayland breaks.
|
||||
@ -388,20 +339,21 @@ void MainWindow::createDisplayWidget(bool fullscreen, bool render_to_main, bool
|
||||
// and positioning has no effect anyway.
|
||||
if (!s_use_central_widget)
|
||||
{
|
||||
if (isVisible())
|
||||
if (isVisible() && g_emu_thread->shouldRenderToMain())
|
||||
container->move(pos());
|
||||
else
|
||||
restoreDisplayWindowGeometryFromConfig();
|
||||
}
|
||||
|
||||
if (!is_exclusive_fullscreen)
|
||||
container->showFullScreen();
|
||||
else
|
||||
container->showNormal();
|
||||
container->showFullScreen();
|
||||
}
|
||||
else if (!render_to_main)
|
||||
{
|
||||
restoreDisplayWindowGeometryFromConfig();
|
||||
// See lameland comment above.
|
||||
if (use_main_window_pos && !s_use_central_widget)
|
||||
container->move(pos());
|
||||
else
|
||||
restoreDisplayWindowGeometryFromConfig();
|
||||
container->showNormal();
|
||||
}
|
||||
else if (s_use_central_widget)
|
||||
@ -420,27 +372,13 @@ void MainWindow::createDisplayWidget(bool fullscreen, bool render_to_main, bool
|
||||
m_ui.mainContainer->setCurrentIndex(1);
|
||||
}
|
||||
|
||||
updateDisplayRelatedActions(true, render_to_main, fullscreen);
|
||||
|
||||
// We need the surface visible.
|
||||
QGuiApplication::sync();
|
||||
}
|
||||
|
||||
void MainWindow::setDisplayFullscreen(const std::string& fullscreen_mode)
|
||||
{
|
||||
u32 width, height;
|
||||
float refresh_rate;
|
||||
bool result = false;
|
||||
|
||||
if (HostDisplay::ParseFullscreenMode(fullscreen_mode, &width, &height, &refresh_rate))
|
||||
{
|
||||
result = g_host_display->SetFullscreen(true, width, height, refresh_rate);
|
||||
if (result)
|
||||
Host::AddOSDMessage(TRANSLATE_STR("OSDMessage", "Acquired exclusive fullscreen."), 10.0f);
|
||||
else
|
||||
Host::AddOSDMessage(TRANSLATE_STR("OSDMessage", "Failed to acquire exclusive fullscreen."), 10.0f);
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::displaySizeRequested(qint32 width, qint32 height)
|
||||
void MainWindow::displayResizeRequested(qint32 width, qint32 height)
|
||||
{
|
||||
if (!m_display_widget)
|
||||
return;
|
||||
@ -462,7 +400,7 @@ void MainWindow::displaySizeRequested(qint32 width, qint32 height)
|
||||
QtUtils::ResizePotentiallyFixedSizeWindow(this, width, height + extra_height);
|
||||
}
|
||||
|
||||
void MainWindow::destroyDisplay()
|
||||
void MainWindow::releaseRenderWindow()
|
||||
{
|
||||
// Now we can safely destroy the display window.
|
||||
destroyDisplayWidget(true);
|
||||
@ -470,6 +408,8 @@ void MainWindow::destroyDisplay()
|
||||
|
||||
updateDisplayRelatedActions(false, false, false);
|
||||
|
||||
m_ui.actionViewSystemDisplay->setEnabled(false);
|
||||
m_ui.actionFullscreen->setEnabled(false);
|
||||
m_ui.actionStartFullscreenUI->setEnabled(true);
|
||||
m_ui.actionStartFullscreenUI2->setEnabled(true);
|
||||
}
|
||||
@ -532,7 +472,7 @@ void MainWindow::updateDisplayWidgetCursor()
|
||||
void MainWindow::updateDisplayRelatedActions(bool has_surface, bool render_to_main, bool fullscreen)
|
||||
{
|
||||
// rendering to main, or switched to gamelist/grid
|
||||
m_ui.actionViewSystemDisplay->setEnabled((has_surface && render_to_main) || (!has_surface && g_host_display));
|
||||
m_ui.actionViewSystemDisplay->setEnabled((has_surface && render_to_main) || (!has_surface && g_gpu_device));
|
||||
m_ui.menuWindowSize->setEnabled(has_surface && !fullscreen);
|
||||
m_ui.actionFullscreen->setEnabled(has_surface);
|
||||
|
||||
@ -1842,10 +1782,10 @@ bool MainWindow::isShowingGameList() const
|
||||
|
||||
bool MainWindow::isRenderingFullscreen() const
|
||||
{
|
||||
if (!g_host_display || !m_display_widget)
|
||||
if (!g_gpu_device || !m_display_widget)
|
||||
return false;
|
||||
|
||||
return getDisplayContainer()->isFullScreen() || g_host_display->IsFullscreen();
|
||||
return getDisplayContainer()->isFullScreen();
|
||||
}
|
||||
|
||||
bool MainWindow::isRenderingToMain() const
|
||||
@ -1999,12 +1939,11 @@ void MainWindow::connectSignals()
|
||||
Qt::QueuedConnection);
|
||||
connect(g_emu_thread, &EmuThread::errorReported, this, &MainWindow::reportError, Qt::BlockingQueuedConnection);
|
||||
connect(g_emu_thread, &EmuThread::messageConfirmed, this, &MainWindow::confirmMessage, Qt::BlockingQueuedConnection);
|
||||
connect(g_emu_thread, &EmuThread::createDisplayRequested, this, &MainWindow::createDisplay,
|
||||
connect(g_emu_thread, &EmuThread::onAcquireRenderWindowRequested, this, &MainWindow::acquireRenderWindow,
|
||||
Qt::BlockingQueuedConnection);
|
||||
connect(g_emu_thread, &EmuThread::destroyDisplayRequested, this, &MainWindow::destroyDisplay);
|
||||
connect(g_emu_thread, &EmuThread::updateDisplayRequested, this, &MainWindow::updateDisplay,
|
||||
connect(g_emu_thread, &EmuThread::onReleaseRenderWindowRequested, this, &MainWindow::releaseRenderWindow);
|
||||
connect(g_emu_thread, &EmuThread::onResizeRenderWindowRequested, this, &MainWindow::displayResizeRequested,
|
||||
Qt::BlockingQueuedConnection);
|
||||
connect(g_emu_thread, &EmuThread::displaySizeRequested, this, &MainWindow::displaySizeRequested);
|
||||
connect(g_emu_thread, &EmuThread::focusDisplayWidgetRequested, this, &MainWindow::focusDisplayWidget);
|
||||
connect(g_emu_thread, &EmuThread::systemStarting, this, &MainWindow::onSystemStarting);
|
||||
connect(g_emu_thread, &EmuThread::systemStarted, this, &MainWindow::onSystemStarted);
|
||||
@ -2415,6 +2354,7 @@ void MainWindow::closeEvent(QCloseEvent* event)
|
||||
if (!s_system_valid)
|
||||
{
|
||||
saveGeometryToConfig();
|
||||
g_emu_thread->stopFullscreenUI();
|
||||
QMainWindow::closeEvent(event);
|
||||
return;
|
||||
}
|
||||
|
@ -2,6 +2,16 @@
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "controllersettingsdialog.h"
|
||||
#include "displaywidget.h"
|
||||
#include "settingsdialog.h"
|
||||
#include "ui_mainwindow.h"
|
||||
|
||||
#include "core/types.h"
|
||||
|
||||
#include "util/window_info.h"
|
||||
|
||||
#include <QtCore/QThread>
|
||||
#include <QtWidgets/QLabel>
|
||||
#include <QtWidgets/QMainWindow>
|
||||
@ -10,13 +20,6 @@
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#include "controllersettingsdialog.h"
|
||||
#include "common/window_info.h"
|
||||
#include "core/types.h"
|
||||
#include "displaywidget.h"
|
||||
#include "settingsdialog.h"
|
||||
#include "ui_mainwindow.h"
|
||||
|
||||
class QLabel;
|
||||
class QThread;
|
||||
class QProgressBar;
|
||||
@ -29,7 +32,7 @@ class CheatManagerDialog;
|
||||
class DebuggerWindow;
|
||||
class MainWindow;
|
||||
|
||||
class HostDisplay;
|
||||
class GPUDevice;
|
||||
namespace GameList {
|
||||
struct Entry;
|
||||
}
|
||||
@ -110,10 +113,11 @@ public Q_SLOTS:
|
||||
private Q_SLOTS:
|
||||
void reportError(const QString& title, const QString& message);
|
||||
bool confirmMessage(const QString& title, const QString& message);
|
||||
bool createDisplay(bool fullscreen, bool render_to_main);
|
||||
bool updateDisplay(bool fullscreen, bool render_to_main, bool surfaceless);
|
||||
void displaySizeRequested(qint32 width, qint32 height);
|
||||
void destroyDisplay();
|
||||
|
||||
std::optional<WindowInfo> acquireRenderWindow(bool recreate_window, bool fullscreen, bool render_to_main,
|
||||
bool surfaceless, bool use_main_window_pos);
|
||||
void displayResizeRequested(qint32 width, qint32 height);
|
||||
void releaseRenderWindow();
|
||||
void focusDisplayWidget();
|
||||
void onMouseModeRequested(bool relative_mode, bool hide_cursor);
|
||||
|
||||
@ -208,11 +212,10 @@ private:
|
||||
void restoreGeometryFromConfig();
|
||||
void saveDisplayWindowGeometryToConfig();
|
||||
void restoreDisplayWindowGeometryFromConfig();
|
||||
void createDisplayWidget(bool fullscreen, bool render_to_main, bool is_exclusive_fullscreen);
|
||||
void createDisplayWidget(bool fullscreen, bool render_to_main, bool use_main_window_pos);
|
||||
void destroyDisplayWidget(bool show_game_list);
|
||||
void updateDisplayWidgetCursor();
|
||||
void updateDisplayRelatedActions(bool has_surface, bool render_to_main, bool fullscreen);
|
||||
void setDisplayFullscreen(const std::string& fullscreen_mode);
|
||||
|
||||
SettingsDialog* getSettingsDialog();
|
||||
void doSettings(const char* category = nullptr);
|
||||
|
@ -4,7 +4,9 @@
|
||||
#include "postprocessingchainconfigwidget.h"
|
||||
#include "postprocessingshaderconfigwidget.h"
|
||||
#include "qthost.h"
|
||||
|
||||
#include "util/postprocessing_chain.h"
|
||||
|
||||
#include <QtGui/QCursor>
|
||||
#include <QtWidgets/QMenu>
|
||||
#include <QtWidgets/QMessageBox>
|
||||
@ -71,9 +73,9 @@ void PostProcessingChainConfigWidget::updateList()
|
||||
|
||||
for (u32 i = 0; i < m_chain.GetStageCount(); i++)
|
||||
{
|
||||
const FrontendCommon::PostProcessingShader& shader = m_chain.GetShaderStage(i);
|
||||
const PostProcessingShader* shader = m_chain.GetShaderStage(i);
|
||||
|
||||
QListWidgetItem* item = new QListWidgetItem(QString::fromStdString(shader.GetName()), m_ui.shaders);
|
||||
QListWidgetItem* item = new QListWidgetItem(QString::fromStdString(shader->GetName()), m_ui.shaders);
|
||||
item->setData(Qt::UserRole, QVariant(i));
|
||||
}
|
||||
|
||||
@ -94,7 +96,7 @@ void PostProcessingChainConfigWidget::updateButtonStates(std::optional<u32> inde
|
||||
m_ui.clear->setEnabled(!m_chain.IsEmpty());
|
||||
// m_ui.reload->setEnabled(!m_chain.IsEmpty());
|
||||
m_ui.shaderSettings->setEnabled(index.has_value() && (index.value() < m_chain.GetStageCount()) &&
|
||||
m_chain.GetShaderStage(index.value()).HasOptions());
|
||||
m_chain.GetShaderStage(index.value())->HasOptions());
|
||||
|
||||
if (index.has_value())
|
||||
{
|
||||
@ -112,7 +114,7 @@ void PostProcessingChainConfigWidget::onAddButtonClicked()
|
||||
{
|
||||
QMenu menu;
|
||||
|
||||
const std::vector<std::string> shaders(FrontendCommon::PostProcessingChain::GetAvailableShaderNames());
|
||||
const std::vector<std::string> shaders(PostProcessingChain::GetAvailableShaderNames());
|
||||
if (shaders.empty())
|
||||
{
|
||||
menu.addAction(tr("No Shaders Available"))->setEnabled(false);
|
||||
@ -198,7 +200,7 @@ void PostProcessingChainConfigWidget::onShaderConfigButtonClicked()
|
||||
std::optional<u32> index = getSelectedIndex();
|
||||
if (index.has_value() && index.value() < m_chain.GetStageCount())
|
||||
{
|
||||
PostProcessingShaderConfigDialog shader_config(this, &m_chain.GetShaderStage(index.value()));
|
||||
PostProcessingShaderConfigDialog shader_config(this, m_chain.GetShaderStage(index.value()));
|
||||
connect(&shader_config, &PostProcessingShaderConfigDialog::configChanged, [this]() { configChanged(); });
|
||||
shader_config.exec();
|
||||
}
|
||||
|
@ -2,12 +2,15 @@
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#pragma once
|
||||
#include "common/types.h"
|
||||
#include "ui_postprocessingchainconfigwidget.h"
|
||||
|
||||
#include "util/postprocessing_chain.h"
|
||||
|
||||
#include "common/types.h"
|
||||
|
||||
#include <QtWidgets/QWidget>
|
||||
#include <optional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
|
||||
namespace FrontendCommon {
|
||||
@ -22,7 +25,7 @@ public:
|
||||
PostProcessingChainConfigWidget(QWidget* parent);
|
||||
~PostProcessingChainConfigWidget();
|
||||
|
||||
ALWAYS_INLINE FrontendCommon::PostProcessingChain& getChain() { return m_chain; }
|
||||
ALWAYS_INLINE PostProcessingChain& getChain() { return m_chain; }
|
||||
|
||||
bool setConfigString(const std::string_view& config_string);
|
||||
void setOptionsButtonVisible(bool visible);
|
||||
@ -51,5 +54,5 @@ private:
|
||||
|
||||
Ui::PostProcessingChainConfigWidget m_ui;
|
||||
|
||||
FrontendCommon::PostProcessingChain m_chain;
|
||||
PostProcessingChain m_chain;
|
||||
};
|
||||
|
@ -71,11 +71,11 @@ void PostProcessingSettingsWidget::updateShaderConfigPanel(s32 index)
|
||||
if (index < 0)
|
||||
return;
|
||||
|
||||
FrontendCommon::PostProcessingShader& shader = m_ui.widget->getChain().GetShaderStage(static_cast<u32>(index));
|
||||
if (!shader.HasOptions())
|
||||
PostProcessingShader* shader = m_ui.widget->getChain().GetShaderStage(static_cast<u32>(index));
|
||||
if (!shader->HasOptions())
|
||||
return;
|
||||
|
||||
m_shader_config = new PostProcessingShaderConfigWidget(m_ui.scrollArea, &shader);
|
||||
m_shader_config = new PostProcessingShaderConfigWidget(m_ui.scrollArea, shader);
|
||||
connect(m_shader_config, &PostProcessingShaderConfigWidget::configChanged,
|
||||
[this]() { onConfigChanged(m_ui.widget->getChain().GetConfigString()); });
|
||||
m_ui.scrollArea->setWidget(m_shader_config);
|
||||
|
@ -8,10 +8,8 @@
|
||||
#include <QtWidgets/QLabel>
|
||||
#include <QtWidgets/QSlider>
|
||||
|
||||
using FrontendCommon::PostProcessingShader;
|
||||
|
||||
PostProcessingShaderConfigWidget::PostProcessingShaderConfigWidget(QWidget* parent,
|
||||
FrontendCommon::PostProcessingShader* shader)
|
||||
PostProcessingShader* shader)
|
||||
: QWidget(parent), m_shader(shader)
|
||||
{
|
||||
createUi();
|
||||
@ -146,7 +144,7 @@ void PostProcessingShaderConfigWidget::onResetToDefaultsClicked()
|
||||
}
|
||||
|
||||
PostProcessingShaderConfigDialog::PostProcessingShaderConfigDialog(QWidget* parent,
|
||||
FrontendCommon::PostProcessingShader* shader)
|
||||
PostProcessingShader* shader)
|
||||
: QDialog(parent)
|
||||
{
|
||||
setWindowTitle(tr("%1 Shader Options").arg(QString::fromStdString(shader->GetName())));
|
||||
|
@ -2,7 +2,9 @@
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "util/postprocessing_shader.h"
|
||||
|
||||
#include <QtWidgets/QDialog>
|
||||
#include <QtWidgets/QWidget>
|
||||
|
||||
@ -13,7 +15,7 @@ class PostProcessingShaderConfigWidget : public QWidget
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PostProcessingShaderConfigWidget(QWidget* parent, FrontendCommon::PostProcessingShader* shader);
|
||||
PostProcessingShaderConfigWidget(QWidget* parent, PostProcessingShader* shader);
|
||||
~PostProcessingShaderConfigWidget();
|
||||
|
||||
QGridLayout* getLayout() { return m_layout; }
|
||||
@ -28,7 +30,7 @@ private Q_SLOTS:
|
||||
protected:
|
||||
void createUi();
|
||||
|
||||
FrontendCommon::PostProcessingShader* m_shader;
|
||||
PostProcessingShader* m_shader;
|
||||
QGridLayout* m_layout;
|
||||
};
|
||||
|
||||
@ -37,7 +39,7 @@ class PostProcessingShaderConfigDialog : public QDialog
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PostProcessingShaderConfigDialog(QWidget* parent, FrontendCommon::PostProcessingShader* shader);
|
||||
PostProcessingShaderConfigDialog(QWidget* parent, PostProcessingShader* shader);
|
||||
~PostProcessingShaderConfigDialog();
|
||||
|
||||
Q_SIGNALS:
|
||||
|
@ -27,7 +27,6 @@
|
||||
#include "common/log.h"
|
||||
#include "common/path.h"
|
||||
#include "common/string_util.h"
|
||||
#include "common/window_info.h"
|
||||
|
||||
#include "util/audio_stream.h"
|
||||
#include "util/imgui_manager.h"
|
||||
@ -107,7 +106,9 @@ static bool s_start_fullscreen_ui_fullscreen = false;
|
||||
EmuThread* g_emu_thread;
|
||||
GDBServer* g_gdb_server;
|
||||
|
||||
EmuThread::EmuThread(QThread* ui_thread) : QThread(), m_ui_thread(ui_thread) {}
|
||||
EmuThread::EmuThread(QThread* ui_thread) : QThread(), m_ui_thread(ui_thread)
|
||||
{
|
||||
}
|
||||
|
||||
EmuThread::~EmuThread() = default;
|
||||
|
||||
@ -336,24 +337,31 @@ void EmuThread::setInitialState(std::optional<bool> override_fullscreen)
|
||||
m_is_surfaceless = false;
|
||||
}
|
||||
|
||||
void EmuThread::checkForSettingsChanges(const Settings& old_settings)
|
||||
{
|
||||
if (g_main_window)
|
||||
{
|
||||
QMetaObject::invokeMethod(g_main_window, &MainWindow::checkForSettingChanges, Qt::QueuedConnection);
|
||||
updatePerformanceCounters();
|
||||
}
|
||||
|
||||
if (g_gpu_device)
|
||||
{
|
||||
const bool render_to_main = shouldRenderToMain();
|
||||
if (m_is_rendering_to_main != render_to_main)
|
||||
{
|
||||
m_is_rendering_to_main = render_to_main;
|
||||
g_gpu_device->UpdateWindow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Host::CheckForSettingsChanges(const Settings& old_settings)
|
||||
{
|
||||
CommonHost::CheckForSettingsChanges(old_settings);
|
||||
g_emu_thread->checkForSettingsChanges(old_settings);
|
||||
}
|
||||
|
||||
void EmuThread::checkForSettingsChanges(const Settings& old_settings)
|
||||
{
|
||||
const bool render_to_main = shouldRenderToMain();
|
||||
if (m_is_rendering_to_main != render_to_main)
|
||||
{
|
||||
m_is_rendering_to_main = render_to_main;
|
||||
updateDisplayState();
|
||||
}
|
||||
|
||||
QMetaObject::invokeMethod(g_main_window, &MainWindow::checkForSettingChanges, Qt::QueuedConnection);
|
||||
}
|
||||
|
||||
void EmuThread::setDefaultSettings(bool system /* = true */, bool controller /* = true */)
|
||||
{
|
||||
if (isOnThread())
|
||||
@ -399,7 +407,7 @@ void Host::RequestResizeHostDisplay(s32 new_window_width, s32 new_window_height)
|
||||
if (g_emu_thread->isFullscreen())
|
||||
return;
|
||||
|
||||
emit g_emu_thread->displaySizeRequested(new_window_width, new_window_height);
|
||||
emit g_emu_thread->onResizeRenderWindowRequested(new_window_width, new_window_height);
|
||||
}
|
||||
|
||||
void EmuThread::applySettings(bool display_osd_messages /* = false */)
|
||||
@ -456,8 +464,10 @@ void EmuThread::startFullscreenUI()
|
||||
setInitialState(s_start_fullscreen_ui_fullscreen ? std::optional<bool>(true) : std::optional<bool>());
|
||||
m_run_fullscreen_ui = true;
|
||||
|
||||
if (!acquireHostDisplay(Settings::GetRenderAPIForRenderer(g_settings.gpu_renderer)))
|
||||
if (!Host::CreateGPUDevice(Settings::GetRenderAPIForRenderer(g_settings.gpu_renderer)) || !FullscreenUI::Initialize())
|
||||
{
|
||||
Host::ReleaseGPUDevice();
|
||||
Host::ReleaseRenderWindow();
|
||||
m_run_fullscreen_ui = false;
|
||||
return;
|
||||
}
|
||||
@ -475,7 +485,7 @@ void EmuThread::stopFullscreenUI()
|
||||
QMetaObject::invokeMethod(this, &EmuThread::stopFullscreenUI, Qt::QueuedConnection);
|
||||
|
||||
// wait until the host display is gone
|
||||
while (g_host_display)
|
||||
while (g_gpu_device)
|
||||
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents, 1);
|
||||
|
||||
return;
|
||||
@ -484,11 +494,12 @@ void EmuThread::stopFullscreenUI()
|
||||
if (System::IsValid())
|
||||
shutdownSystem();
|
||||
|
||||
if (!g_host_display)
|
||||
if (!g_gpu_device)
|
||||
return;
|
||||
|
||||
m_run_fullscreen_ui = false;
|
||||
releaseHostDisplay();
|
||||
Host::ReleaseGPUDevice();
|
||||
Host::ReleaseRenderWindow();
|
||||
}
|
||||
|
||||
void EmuThread::bootSystem(std::shared_ptr<SystemBootParameters> params)
|
||||
@ -506,7 +517,7 @@ void EmuThread::bootSystem(std::shared_ptr<SystemBootParameters> params)
|
||||
return;
|
||||
|
||||
// force a frame to be drawn to repaint the window
|
||||
renderDisplay(false);
|
||||
Host::InvalidateDisplay();
|
||||
}
|
||||
|
||||
void EmuThread::bootOrLoadState(std::string path)
|
||||
@ -568,8 +579,8 @@ void EmuThread::onDisplayWindowMouseMoveEvent(bool relative, float x, float y)
|
||||
DebugAssert(isOnThread());
|
||||
if (!relative)
|
||||
{
|
||||
if (g_host_display)
|
||||
g_host_display->SetMousePosition(static_cast<s32>(x), static_cast<s32>(y));
|
||||
if (g_gpu_device)
|
||||
g_gpu_device->SetMousePosition(static_cast<s32>(x), static_cast<s32>(y));
|
||||
|
||||
InputManager::UpdatePointerAbsolutePosition(0, x, y);
|
||||
ImGuiManager::UpdateMousePosition(x, y);
|
||||
@ -581,11 +592,11 @@ void EmuThread::onDisplayWindowMouseMoveEvent(bool relative, float x, float y)
|
||||
if (y != 0.0f)
|
||||
InputManager::UpdatePointerRelativeDelta(0, InputPointerAxis::Y, y);
|
||||
|
||||
if (g_host_display)
|
||||
if (g_gpu_device)
|
||||
{
|
||||
const float abs_x = static_cast<float>(g_host_display->GetMousePositionX()) + x;
|
||||
const float abs_y = static_cast<float>(g_host_display->GetMousePositionY()) + y;
|
||||
g_host_display->SetMousePosition(static_cast<s32>(abs_x), static_cast<s32>(abs_y));
|
||||
const float abs_x = static_cast<float>(g_gpu_device->GetMousePositionX()) + x;
|
||||
const float abs_y = static_cast<float>(g_gpu_device->GetMousePositionY()) + y;
|
||||
g_gpu_device->SetMousePosition(static_cast<s32>(abs_x), static_cast<s32>(abs_y));
|
||||
ImGuiManager::UpdateMousePosition(abs_x, abs_y);
|
||||
}
|
||||
}
|
||||
@ -612,33 +623,9 @@ void EmuThread::onDisplayWindowMouseWheelEvent(const QPoint& delta_angle)
|
||||
InputManager::UpdatePointerRelativeDelta(0, InputPointerAxis::WheelY, dy);
|
||||
}
|
||||
|
||||
void EmuThread::onDisplayWindowResized(int width, int height)
|
||||
void EmuThread::onDisplayWindowResized(int width, int height, float scale)
|
||||
{
|
||||
// this can be null if it was destroyed and the main thread is late catching up
|
||||
if (!g_host_display)
|
||||
return;
|
||||
|
||||
Log_DevPrintf("Display window resized to %dx%d", width, height);
|
||||
g_host_display->ResizeWindow(width, height);
|
||||
ImGuiManager::WindowResized();
|
||||
System::HostDisplayResized();
|
||||
|
||||
// re-render the display, since otherwise it will be out of date and stretched if paused
|
||||
if (System::IsValid())
|
||||
{
|
||||
if (m_is_exclusive_fullscreen && !g_host_display->IsFullscreen())
|
||||
{
|
||||
// we lost exclusive fullscreen, switch to borderless
|
||||
Host::AddOSDMessage(TRANSLATE_STR("OSDMessage", "Lost exclusive fullscreen."), 10.0f);
|
||||
m_is_exclusive_fullscreen = false;
|
||||
m_is_fullscreen = false;
|
||||
m_lost_exclusive_fullscreen = true;
|
||||
}
|
||||
|
||||
// force redraw if we're paused
|
||||
if (!System::IsRunning() && !FullscreenUI::HasActiveWindow())
|
||||
renderDisplay(false);
|
||||
}
|
||||
Host::ResizeDisplayWindow(width, height, scale);
|
||||
}
|
||||
|
||||
void EmuThread::redrawDisplayWindow()
|
||||
@ -649,10 +636,10 @@ void EmuThread::redrawDisplayWindow()
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_host_display || System::IsShutdown())
|
||||
if (!g_gpu_device || System::IsShutdown())
|
||||
return;
|
||||
|
||||
renderDisplay(false);
|
||||
Host::RenderDisplay(false);
|
||||
}
|
||||
|
||||
void EmuThread::toggleFullscreen()
|
||||
@ -663,22 +650,24 @@ void EmuThread::toggleFullscreen()
|
||||
return;
|
||||
}
|
||||
|
||||
setFullscreen(!m_is_fullscreen);
|
||||
setFullscreen(!m_is_fullscreen, true);
|
||||
}
|
||||
|
||||
void EmuThread::setFullscreen(bool fullscreen)
|
||||
void EmuThread::setFullscreen(bool fullscreen, bool allow_render_to_main)
|
||||
{
|
||||
if (!isOnThread())
|
||||
{
|
||||
QMetaObject::invokeMethod(this, "setFullscreen", Qt::QueuedConnection, Q_ARG(bool, fullscreen));
|
||||
QMetaObject::invokeMethod(this, "setFullscreen", Qt::QueuedConnection, Q_ARG(bool, fullscreen),
|
||||
Q_ARG(bool, allow_render_to_main));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_host_display || m_is_fullscreen == fullscreen)
|
||||
if (!g_gpu_device || m_is_fullscreen == fullscreen)
|
||||
return;
|
||||
|
||||
m_is_fullscreen = fullscreen;
|
||||
updateDisplayState();
|
||||
m_is_rendering_to_main = allow_render_to_main && shouldRenderToMain();
|
||||
Host::UpdateDisplayWindow();
|
||||
}
|
||||
|
||||
bool Host::IsFullscreen()
|
||||
@ -688,7 +677,7 @@ bool Host::IsFullscreen()
|
||||
|
||||
void Host::SetFullscreen(bool enabled)
|
||||
{
|
||||
g_emu_thread->setFullscreen(enabled);
|
||||
g_emu_thread->setFullscreen(enabled, true);
|
||||
}
|
||||
|
||||
void EmuThread::setSurfaceless(bool surfaceless)
|
||||
@ -699,11 +688,11 @@ void EmuThread::setSurfaceless(bool surfaceless)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_host_display || m_is_surfaceless == surfaceless)
|
||||
if (!g_gpu_device || m_is_surfaceless == surfaceless)
|
||||
return;
|
||||
|
||||
m_is_surfaceless = surfaceless;
|
||||
updateDisplayState();
|
||||
Host::UpdateDisplayWindow();
|
||||
}
|
||||
|
||||
void EmuThread::requestDisplaySize(float scale)
|
||||
@ -720,52 +709,25 @@ void EmuThread::requestDisplaySize(float scale)
|
||||
System::RequestDisplaySize(scale);
|
||||
}
|
||||
|
||||
bool EmuThread::acquireHostDisplay(RenderAPI api)
|
||||
std::optional<WindowInfo> EmuThread::acquireRenderWindow(bool recreate_window)
|
||||
{
|
||||
if (g_host_display)
|
||||
{
|
||||
if (g_host_display->GetRenderAPI() == api)
|
||||
{
|
||||
// current is fine
|
||||
return true;
|
||||
}
|
||||
DebugAssert(g_gpu_device);
|
||||
u32 fs_width, fs_height;
|
||||
float fs_refresh_rate;
|
||||
m_is_exclusive_fullscreen = (m_is_fullscreen && g_gpu_device->SupportsExclusiveFullscreen() &&
|
||||
GPUDevice::GetRequestedExclusiveFullscreenMode(&fs_width, &fs_height, &fs_refresh_rate));
|
||||
|
||||
// otherwise we need to switch
|
||||
releaseHostDisplay();
|
||||
}
|
||||
const bool window_fullscreen = m_is_fullscreen && !m_is_exclusive_fullscreen;
|
||||
const bool render_to_main = !m_is_exclusive_fullscreen && !window_fullscreen && m_is_rendering_to_main;
|
||||
const bool use_main_window_pos = m_is_exclusive_fullscreen && shouldRenderToMain();
|
||||
|
||||
g_host_display = Host::CreateDisplayForAPI(api);
|
||||
if (!g_host_display)
|
||||
return false;
|
||||
return emit onAcquireRenderWindowRequested(recreate_window, window_fullscreen, render_to_main, m_is_surfaceless,
|
||||
use_main_window_pos);
|
||||
}
|
||||
|
||||
if (!createDisplayRequested(m_is_fullscreen, m_is_rendering_to_main))
|
||||
{
|
||||
emit destroyDisplayRequested();
|
||||
g_host_display.reset();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!g_host_display->MakeCurrent() || !g_host_display->SetupDevice() || !ImGuiManager::Initialize() ||
|
||||
!CommonHost::CreateHostDisplayResources())
|
||||
{
|
||||
ImGuiManager::Shutdown();
|
||||
CommonHost::ReleaseHostDisplayResources();
|
||||
g_host_display.reset();
|
||||
emit destroyDisplayRequested();
|
||||
return false;
|
||||
}
|
||||
|
||||
m_is_exclusive_fullscreen = g_host_display->IsFullscreen();
|
||||
|
||||
if (m_run_fullscreen_ui && !FullscreenUI::Initialize())
|
||||
{
|
||||
Log_ErrorPrint("Failed to initialize fullscreen UI");
|
||||
releaseHostDisplay();
|
||||
m_run_fullscreen_ui = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
void EmuThread::releaseRenderWindow()
|
||||
{
|
||||
emit onReleaseRenderWindowRequested();
|
||||
}
|
||||
|
||||
void EmuThread::connectDisplaySignals(DisplayWidget* widget)
|
||||
@ -781,46 +743,6 @@ void EmuThread::connectDisplaySignals(DisplayWidget* widget)
|
||||
connect(widget, &DisplayWidget::windowMouseWheelEvent, this, &EmuThread::onDisplayWindowMouseWheelEvent);
|
||||
}
|
||||
|
||||
void EmuThread::updateDisplayState()
|
||||
{
|
||||
if (!g_host_display)
|
||||
return;
|
||||
|
||||
// this expects the context to get moved back to us afterwards
|
||||
g_host_display->DoneCurrent();
|
||||
|
||||
updateDisplayRequested(m_is_fullscreen, m_is_rendering_to_main && !m_is_fullscreen, m_is_surfaceless);
|
||||
if (!g_host_display->MakeCurrent())
|
||||
Panic("Failed to make device context current after updating");
|
||||
|
||||
m_is_exclusive_fullscreen = g_host_display->IsFullscreen();
|
||||
ImGuiManager::WindowResized();
|
||||
System::HostDisplayResized();
|
||||
|
||||
if (!System::IsShutdown())
|
||||
{
|
||||
System::UpdateSoftwareCursor();
|
||||
|
||||
if (!FullscreenUI::IsInitialized() || System::IsPaused())
|
||||
redrawDisplayWindow();
|
||||
}
|
||||
|
||||
System::UpdateSpeedLimiterState();
|
||||
}
|
||||
|
||||
void EmuThread::releaseHostDisplay()
|
||||
{
|
||||
if (!g_host_display)
|
||||
return;
|
||||
|
||||
CommonHost::ReleaseHostDisplayResources();
|
||||
FullscreenUI::Shutdown();
|
||||
ImGuiManager::Shutdown();
|
||||
g_host_display.reset();
|
||||
emit destroyDisplayRequested();
|
||||
m_is_fullscreen = false;
|
||||
}
|
||||
|
||||
void Host::OnSystemStarting()
|
||||
{
|
||||
CommonHost::OnSystemStarting();
|
||||
@ -844,7 +766,7 @@ void Host::OnSystemPaused()
|
||||
|
||||
emit g_emu_thread->systemPaused();
|
||||
g_emu_thread->startBackgroundControllerPollTimer();
|
||||
g_emu_thread->renderDisplay(false);
|
||||
Host::InvalidateDisplay();
|
||||
}
|
||||
|
||||
void Host::OnSystemResumed()
|
||||
@ -1246,7 +1168,7 @@ void EmuThread::singleStepCPU()
|
||||
return;
|
||||
|
||||
System::SingleStepCPU();
|
||||
renderDisplay(false);
|
||||
Host::InvalidateDisplay();
|
||||
}
|
||||
|
||||
void EmuThread::dumpRAM(const QString& filename)
|
||||
@ -1449,11 +1371,11 @@ void EmuThread::run()
|
||||
|
||||
m_event_loop->processEvents(QEventLoop::AllEvents);
|
||||
CommonHost::PumpMessagesOnCPUThread();
|
||||
if (g_host_display)
|
||||
if (g_gpu_device)
|
||||
{
|
||||
renderDisplay(false);
|
||||
if (!g_host_display->IsVsyncEnabled())
|
||||
g_host_display->ThrottlePresentation();
|
||||
Host::RenderDisplay(false);
|
||||
if (!g_gpu_device->IsVsyncEnabled())
|
||||
g_gpu_device->ThrottlePresentation();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1468,35 +1390,8 @@ void EmuThread::run()
|
||||
moveToThread(m_ui_thread);
|
||||
}
|
||||
|
||||
void EmuThread::renderDisplay(bool skip_present)
|
||||
void Host::BeginPresentFrame()
|
||||
{
|
||||
// acquire for IO.MousePos.
|
||||
std::atomic_thread_fence(std::memory_order_acquire);
|
||||
|
||||
if (!skip_present)
|
||||
{
|
||||
FullscreenUI::Render();
|
||||
ImGuiManager::RenderTextOverlays();
|
||||
ImGuiManager::RenderOSDMessages();
|
||||
}
|
||||
|
||||
// Debug windows are always rendered, otherwise mouse input breaks on skip.
|
||||
ImGuiManager::RenderOverlayWindows();
|
||||
ImGuiManager::RenderDebugWindows();
|
||||
|
||||
g_host_display->Render(skip_present);
|
||||
|
||||
ImGuiManager::NewFrame();
|
||||
}
|
||||
|
||||
void Host::InvalidateDisplay()
|
||||
{
|
||||
g_emu_thread->renderDisplay(false);
|
||||
}
|
||||
|
||||
void Host::RenderDisplay(bool skip_present)
|
||||
{
|
||||
g_emu_thread->renderDisplay(skip_present);
|
||||
}
|
||||
|
||||
void EmuThread::wakeThread()
|
||||
@ -1605,39 +1500,34 @@ void Host::CommitBaseSettingChanges()
|
||||
QtHost::QueueSettingsSave();
|
||||
}
|
||||
|
||||
bool Host::AcquireHostDisplay(RenderAPI api)
|
||||
std::optional<WindowInfo> Host::AcquireRenderWindow(bool recreate_window)
|
||||
{
|
||||
return g_emu_thread->acquireHostDisplay(api);
|
||||
return g_emu_thread->acquireRenderWindow(recreate_window);
|
||||
}
|
||||
|
||||
void Host::ReleaseHostDisplay()
|
||||
void Host::ReleaseRenderWindow()
|
||||
{
|
||||
if (g_emu_thread->isRunningFullscreenUI())
|
||||
{
|
||||
// keep display alive when running fsui
|
||||
return;
|
||||
}
|
||||
|
||||
g_emu_thread->releaseHostDisplay();
|
||||
g_emu_thread->releaseRenderWindow();
|
||||
}
|
||||
|
||||
void EmuThread::updatePerformanceCounters()
|
||||
{
|
||||
GPURenderer renderer = GPURenderer::Count;
|
||||
const RenderAPI render_api = g_gpu_device ? g_gpu_device->GetRenderAPI() : RenderAPI::None;
|
||||
const bool hardware_renderer = g_gpu && g_gpu->IsHardwareRenderer();
|
||||
u32 render_width = 0;
|
||||
u32 render_height = 0;
|
||||
|
||||
if (g_gpu)
|
||||
{
|
||||
renderer = g_gpu->GetRendererType();
|
||||
std::tie(render_width, render_height) = g_gpu->GetEffectiveDisplayResolution();
|
||||
}
|
||||
|
||||
if (renderer != m_last_renderer)
|
||||
if (render_api != m_last_render_api || hardware_renderer != m_last_hardware_renderer)
|
||||
{
|
||||
const QString renderer_str = hardware_renderer ? QString::fromUtf8(GPUDevice::RenderAPIToString(render_api)) :
|
||||
qApp->translate("GPURenderer", "Software");
|
||||
QMetaObject::invokeMethod(g_main_window->getStatusRendererWidget(), "setText", Qt::QueuedConnection,
|
||||
Q_ARG(const QString&, QString::fromUtf8(Settings::GetRendererName(renderer))));
|
||||
m_last_renderer = renderer;
|
||||
Q_ARG(const QString&, renderer_str));
|
||||
m_last_render_api = render_api;
|
||||
m_last_hardware_renderer = hardware_renderer;
|
||||
}
|
||||
if (render_width != m_last_render_width || render_height != m_last_render_height)
|
||||
{
|
||||
@ -1674,7 +1564,8 @@ void EmuThread::resetPerformanceCounters()
|
||||
m_last_video_fps = std::numeric_limits<float>::infinity();
|
||||
m_last_render_width = std::numeric_limits<u32>::max();
|
||||
m_last_render_height = std::numeric_limits<u32>::max();
|
||||
m_last_renderer = GPURenderer::Count;
|
||||
m_last_render_api = RenderAPI::None;
|
||||
m_last_hardware_renderer = false;
|
||||
|
||||
QString blank;
|
||||
QMetaObject::invokeMethod(g_main_window->getStatusRendererWidget(), "setText", Qt::QueuedConnection,
|
||||
|
@ -2,16 +2,20 @@
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "gdbserver.h"
|
||||
#include "qtutils.h"
|
||||
|
||||
#include "core/host.h"
|
||||
#include "util/host_display.h"
|
||||
#include "core/host_settings.h"
|
||||
#include "core/system.h"
|
||||
#include "core/types.h"
|
||||
#include "core/common_host.h"
|
||||
#include "core/game_list.h"
|
||||
|
||||
#include "util/gpu_device.h"
|
||||
#include "util/input_manager.h"
|
||||
#include "gdbserver.h"
|
||||
#include "qtutils.h"
|
||||
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QMetaType>
|
||||
#include <QtCore/QObject>
|
||||
@ -39,7 +43,7 @@ class QTranslator;
|
||||
|
||||
class INISettingsInterface;
|
||||
|
||||
class HostDisplay;
|
||||
class GPUDevice;
|
||||
|
||||
class MainWindow;
|
||||
class DisplayWidget;
|
||||
@ -95,10 +99,9 @@ public:
|
||||
ALWAYS_INLINE bool isSurfaceless() const { return m_is_surfaceless; }
|
||||
ALWAYS_INLINE bool isRunningFullscreenUI() const { return m_run_fullscreen_ui; }
|
||||
|
||||
bool acquireHostDisplay(RenderAPI api);
|
||||
std::optional<WindowInfo> acquireRenderWindow(bool recreate_window);
|
||||
void connectDisplaySignals(DisplayWidget* widget);
|
||||
void releaseHostDisplay();
|
||||
void renderDisplay(bool skip_present);
|
||||
void releaseRenderWindow();
|
||||
|
||||
void startBackgroundControllerPollTimer();
|
||||
void stopBackgroundControllerPollTimer();
|
||||
@ -132,11 +135,11 @@ Q_SIGNALS:
|
||||
void systemPaused();
|
||||
void systemResumed();
|
||||
void gameListRefreshed();
|
||||
bool createDisplayRequested(bool fullscreen, bool render_to_main);
|
||||
bool updateDisplayRequested(bool fullscreen, bool render_to_main, bool surfaceless);
|
||||
void displaySizeRequested(qint32 width, qint32 height);
|
||||
std::optional<WindowInfo> onAcquireRenderWindowRequested(bool recreate_window, bool fullscreen, bool render_to_main,
|
||||
bool surfaceless, bool use_main_window_pos);
|
||||
void onResizeRenderWindowRequested(qint32 width, qint32 height);
|
||||
void onReleaseRenderWindowRequested();
|
||||
void focusDisplayWidgetRequested();
|
||||
void destroyDisplayRequested();
|
||||
void runningGameChanged(const QString& filename, const QString& game_serial, const QString& game_title);
|
||||
void inputProfileLoaded();
|
||||
void mouseModeRequested(bool relative, bool hide_cursor);
|
||||
@ -180,7 +183,7 @@ public Q_SLOTS:
|
||||
void saveScreenshot();
|
||||
void redrawDisplayWindow();
|
||||
void toggleFullscreen();
|
||||
void setFullscreen(bool fullscreen);
|
||||
void setFullscreen(bool fullscreen, bool allow_render_to_main);
|
||||
void setSurfaceless(bool surfaceless);
|
||||
void requestDisplaySize(float scale);
|
||||
void loadCheatList(const QString& filename);
|
||||
@ -194,7 +197,7 @@ private Q_SLOTS:
|
||||
void onDisplayWindowMouseMoveEvent(bool relative, float x, float y);
|
||||
void onDisplayWindowMouseButtonEvent(int button, bool pressed);
|
||||
void onDisplayWindowMouseWheelEvent(const QPoint& delta_angle);
|
||||
void onDisplayWindowResized(int width, int height);
|
||||
void onDisplayWindowResized(int width, int height, float scale);
|
||||
void onDisplayWindowKeyEvent(int key, bool pressed);
|
||||
void onDisplayWindowTextEntered(const QString& text);
|
||||
void doBackgroundControllerPoll();
|
||||
@ -210,7 +213,6 @@ private:
|
||||
void createBackgroundControllerPollTimer();
|
||||
void destroyBackgroundControllerPollTimer();
|
||||
void setInitialState(std::optional<bool> override_fullscreen);
|
||||
void updateDisplayState();
|
||||
|
||||
QThread* m_ui_thread;
|
||||
QSemaphore m_started_semaphore;
|
||||
@ -233,7 +235,8 @@ private:
|
||||
float m_last_video_fps = std::numeric_limits<float>::infinity();
|
||||
u32 m_last_render_width = std::numeric_limits<u32>::max();
|
||||
u32 m_last_render_height = std::numeric_limits<u32>::max();
|
||||
GPURenderer m_last_renderer = GPURenderer::Count;
|
||||
RenderAPI m_last_render_api = RenderAPI::None;
|
||||
bool m_last_hardware_renderer = false;
|
||||
};
|
||||
|
||||
extern EmuThread* g_emu_thread;
|
||||
|
@ -2,8 +2,11 @@
|
||||
// SPDX-License-Identifier: (GPL-3.0 OR CC-BY-NC-ND-4.0)
|
||||
|
||||
#pragma once
|
||||
#include "common/window_info.h"
|
||||
|
||||
#include "util/window_info.h"
|
||||
|
||||
#include "common/types.h"
|
||||
|
||||
#include <QtCore/QByteArray>
|
||||
#include <QtCore/QMetaType>
|
||||
#include <QtCore/QString>
|
||||
|
Reference in New Issue
Block a user