mirror of
https://github.com/WinampDesktop/winamp.git
synced 2025-06-18 09:15:46 -04:00
GPU: Implement "Crop Mode" (none, overscan, all borders)
This commit is contained in:
@ -98,6 +98,25 @@ void D3D11DisplayWindow::ChangeRenderWindow(void* new_window)
|
||||
Panic("Not supported");
|
||||
}
|
||||
|
||||
void D3D11DisplayWindow::WindowResized(s32 new_window_width, s32 new_window_height)
|
||||
{
|
||||
QtDisplayWindow::WindowResized(new_window_width, new_window_height);
|
||||
HostDisplay::WindowResized(new_window_width, new_window_height);
|
||||
|
||||
if (!m_swap_chain)
|
||||
return;
|
||||
|
||||
m_swap_chain_rtv.Reset();
|
||||
|
||||
HRESULT hr = m_swap_chain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN,
|
||||
m_allow_tearing_supported ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0);
|
||||
if (FAILED(hr))
|
||||
Log_ErrorPrintf("ResizeBuffers() failed: 0x%08X", hr);
|
||||
|
||||
if (!createSwapChainRTV())
|
||||
Panic("Failed to recreate swap chain RTV after resize");
|
||||
}
|
||||
|
||||
std::unique_ptr<HostDisplayTexture> D3D11DisplayWindow::CreateTexture(u32 width, u32 height, const void* data,
|
||||
u32 data_stride, bool dynamic)
|
||||
{
|
||||
@ -145,32 +164,6 @@ void D3D11DisplayWindow::SetVSync(bool enabled)
|
||||
m_vsync = enabled;
|
||||
}
|
||||
|
||||
std::tuple<u32, u32> D3D11DisplayWindow::GetWindowSize() const
|
||||
{
|
||||
const QSize s = size();
|
||||
return std::make_tuple(static_cast<u32>(s.width()), static_cast<u32>(s.height()));
|
||||
}
|
||||
|
||||
void D3D11DisplayWindow::WindowResized() {}
|
||||
|
||||
void D3D11DisplayWindow::onWindowResized(int width, int height)
|
||||
{
|
||||
QtDisplayWindow::onWindowResized(width, height);
|
||||
|
||||
if (!m_swap_chain)
|
||||
return;
|
||||
|
||||
m_swap_chain_rtv.Reset();
|
||||
|
||||
HRESULT hr = m_swap_chain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN,
|
||||
m_allow_tearing_supported ? DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING : 0);
|
||||
if (FAILED(hr))
|
||||
Log_ErrorPrintf("ResizeBuffers() failed: 0x%08X", hr);
|
||||
|
||||
if (!createSwapChainRTV())
|
||||
Panic("Failed to recreate swap chain RTV after resize");
|
||||
}
|
||||
|
||||
bool D3D11DisplayWindow::hasDeviceContext() const
|
||||
{
|
||||
return static_cast<bool>(m_device);
|
||||
@ -415,10 +408,7 @@ void D3D11DisplayWindow::renderDisplay()
|
||||
if (!m_display_texture_handle)
|
||||
return;
|
||||
|
||||
// - 20 for main menu padding
|
||||
auto [vp_left, vp_top, vp_width, vp_height] =
|
||||
CalculateDrawRect(m_window_width, std::max(m_window_height - m_display_top_margin, 1), m_display_aspect_ratio);
|
||||
vp_top += m_display_top_margin;
|
||||
auto [vp_left, vp_top, vp_width, vp_height] = CalculateDrawRect();
|
||||
|
||||
m_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
m_context->VSSetShader(m_display_vertex_shader.Get(), nullptr, 0);
|
||||
@ -427,11 +417,11 @@ void D3D11DisplayWindow::renderDisplay()
|
||||
m_context->PSSetSamplers(
|
||||
0, 1, m_display_linear_filtering ? m_linear_sampler.GetAddressOf() : m_point_sampler.GetAddressOf());
|
||||
|
||||
const float uniforms[4] = {static_cast<float>(m_display_offset_x) / static_cast<float>(m_display_texture_width),
|
||||
static_cast<float>(m_display_offset_y) / static_cast<float>(m_display_texture_height),
|
||||
(static_cast<float>(m_display_width) - 0.5f) / static_cast<float>(m_display_texture_width),
|
||||
(static_cast<float>(m_display_height) - 0.5f) /
|
||||
static_cast<float>(m_display_texture_height)};
|
||||
const float uniforms[4] = {
|
||||
static_cast<float>(m_display_texture_rect.left) / static_cast<float>(m_display_texture_width),
|
||||
static_cast<float>(m_display_texture_rect.top) / static_cast<float>(m_display_texture_height),
|
||||
(static_cast<float>(m_display_texture_rect.GetWidth()) - 0.5f) / static_cast<float>(m_display_texture_width),
|
||||
(static_cast<float>(m_display_texture_rect.GetHeight()) - 0.5f) / static_cast<float>(m_display_texture_height)};
|
||||
const auto map = m_display_uniform_buffer.Map(m_context.Get(), sizeof(uniforms), sizeof(uniforms));
|
||||
std::memcpy(map.pointer, uniforms, sizeof(uniforms));
|
||||
m_display_uniform_buffer.Unmap(m_context.Get(), sizeof(uniforms));
|
||||
|
@ -32,6 +32,7 @@ public:
|
||||
void* GetRenderWindow() const override;
|
||||
|
||||
void ChangeRenderWindow(void* new_window) override;
|
||||
void WindowResized(s32 new_window_width, s32 new_window_height) override;
|
||||
|
||||
std::unique_ptr<HostDisplayTexture> CreateTexture(u32 width, u32 height, const void* data, u32 data_stride,
|
||||
bool dynamic) override;
|
||||
@ -40,13 +41,8 @@ public:
|
||||
|
||||
void SetVSync(bool enabled) override;
|
||||
|
||||
std::tuple<u32, u32> GetWindowSize() const override;
|
||||
void WindowResized() override;
|
||||
|
||||
void Render() override;
|
||||
|
||||
void onWindowResized(int width, int height) override;
|
||||
|
||||
private:
|
||||
static constexpr u32 DISPLAY_UNIFORM_BUFFER_SIZE = 16;
|
||||
|
||||
|
@ -11,15 +11,18 @@ GPUSettingsWidget::GPUSettingsWidget(QtHostInterface* host_interface, QWidget* p
|
||||
|
||||
SettingWidgetBinder::BindWidgetToEnumSetting(m_host_interface, m_ui.renderer, "GPU/Renderer",
|
||||
&Settings::ParseRendererName, &Settings::GetRendererName);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.fullscreen, "Display/Fullscreen");
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.useDebugDevice, "GPU/UseDebugDevice");
|
||||
SettingWidgetBinder::BindWidgetToEnumSetting(m_host_interface, m_ui.cropMode, "Display/CropMode",
|
||||
&Settings::ParseDisplayCropMode, &Settings::GetDisplayCropModeName);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.forceProgressiveScan,
|
||||
"Display/ForceProgressiveScan");
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.displayLinearFiltering,
|
||||
"Display/LinearFiltering");
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.startFullscreen, "Display/Fullscreen");
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.vsync, "Display/VSync");
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(m_host_interface, m_ui.resolutionScale, "GPU/ResolutionScale");
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.trueColor, "GPU/TrueColor");
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.linearTextureFiltering, "GPU/TextureFiltering");
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.forceProgressiveScan, "GPU/ForceProgressiveScan");
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(m_host_interface, m_ui.useDebugDevice, "GPU/UseDebugDevice");
|
||||
}
|
||||
|
||||
GPUSettingsWidget::~GPUSettingsWidget() = default;
|
||||
@ -29,6 +32,12 @@ void GPUSettingsWidget::setupAdditionalUi()
|
||||
for (u32 i = 0; i < static_cast<u32>(GPURenderer::Count); i++)
|
||||
m_ui.renderer->addItem(QString::fromLocal8Bit(Settings::GetRendererDisplayName(static_cast<GPURenderer>(i))));
|
||||
|
||||
for (u32 i = 0; i < static_cast<u32>(DisplayCropMode::Count); i++)
|
||||
{
|
||||
m_ui.cropMode->addItem(
|
||||
QString::fromLocal8Bit(Settings::GetDisplayCropModeDisplayName(static_cast<DisplayCropMode>(i))));
|
||||
}
|
||||
|
||||
m_ui.resolutionScale->addItem(tr("Automatic based on window size"));
|
||||
for (u32 i = 1; i <= GPU::MAX_RESOLUTION_SCALE; i++)
|
||||
m_ui.resolutionScale->addItem(tr("%1x (%2x%3)").arg(i).arg(GPU::VRAM_WIDTH * i).arg(GPU::VRAM_HEIGHT * i));
|
||||
|
@ -42,31 +42,57 @@
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="renderer"/>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="useDebugDevice">
|
||||
<property name="text">
|
||||
<string>Use Debug Device</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="title">
|
||||
<string>Screen Display</string>
|
||||
</property>
|
||||
<layout class="QFormLayout" name="formLayout_4">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Crop:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="cropMode"/>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="forceProgressiveScan">
|
||||
<property name="text">
|
||||
<string>Force Progressive Scan</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="displayLinearFiltering">
|
||||
<property name="text">
|
||||
<string>Linear Upscaling</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="vsync">
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="startFullscreen">
|
||||
<property name="text">
|
||||
<string>VSync</string>
|
||||
<string>Start Fullscreen</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="fullscreen">
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="vsync">
|
||||
<property name="text">
|
||||
<string>Fullscreen</string>
|
||||
<string>VSync</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -103,13 +129,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="forceProgressiveScan">
|
||||
<property name="text">
|
||||
<string>Force Progressive Scan</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -134,6 +134,12 @@ void OpenGLDisplayWindow::ChangeRenderWindow(void* new_window)
|
||||
Panic("Not implemented");
|
||||
}
|
||||
|
||||
void OpenGLDisplayWindow::WindowResized(s32 new_window_width, s32 new_window_height)
|
||||
{
|
||||
QtDisplayWindow::WindowResized(new_window_width, new_window_height);
|
||||
HostDisplay::WindowResized(new_window_width, new_window_height);
|
||||
}
|
||||
|
||||
std::unique_ptr<HostDisplayTexture> OpenGLDisplayWindow::CreateTexture(u32 width, u32 height, const void* data,
|
||||
u32 data_stride, bool dynamic)
|
||||
{
|
||||
@ -165,13 +171,6 @@ void OpenGLDisplayWindow::SetVSync(bool enabled)
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, current_fbo);
|
||||
}
|
||||
|
||||
std::tuple<u32, u32> OpenGLDisplayWindow::GetWindowSize() const
|
||||
{
|
||||
return std::make_tuple(static_cast<u32>(m_window_width), static_cast<u32>(m_window_height));
|
||||
}
|
||||
|
||||
void OpenGLDisplayWindow::WindowResized() {}
|
||||
|
||||
const char* OpenGLDisplayWindow::GetGLSLVersionString() const
|
||||
{
|
||||
if (m_gl_context->isOpenGLES())
|
||||
@ -466,9 +465,7 @@ void OpenGLDisplayWindow::renderDisplay()
|
||||
if (!m_display_texture_handle)
|
||||
return;
|
||||
|
||||
// - 20 for main menu padding
|
||||
const auto [vp_left, vp_top, vp_width, vp_height] =
|
||||
CalculateDrawRect(m_window_width, std::max(m_window_height - m_display_top_margin, 1), m_display_aspect_ratio);
|
||||
const auto [vp_left, vp_top, vp_width, vp_height] = CalculateDrawRect();
|
||||
|
||||
glViewport(vp_left, m_window_height - (m_display_top_margin + vp_top) - vp_height, vp_width, vp_height);
|
||||
glDisable(GL_BLEND);
|
||||
@ -478,10 +475,10 @@ void OpenGLDisplayWindow::renderDisplay()
|
||||
glDepthMask(GL_FALSE);
|
||||
m_display_program.Bind();
|
||||
m_display_program.Uniform4f(
|
||||
0, static_cast<float>(m_display_offset_x) / static_cast<float>(m_display_texture_width),
|
||||
static_cast<float>(m_display_offset_y) / static_cast<float>(m_display_texture_height),
|
||||
(static_cast<float>(m_display_width) - 0.5f) / static_cast<float>(m_display_texture_width),
|
||||
(static_cast<float>(m_display_height) - 0.5f) / static_cast<float>(m_display_texture_height));
|
||||
0, static_cast<float>(m_display_texture_rect.left) / static_cast<float>(m_display_texture_width),
|
||||
static_cast<float>(m_display_texture_rect.top) / static_cast<float>(m_display_texture_height),
|
||||
(static_cast<float>(m_display_texture_rect.GetWidth()) - 0.5f) / static_cast<float>(m_display_texture_width),
|
||||
(static_cast<float>(m_display_texture_rect.GetHeight()) - 0.5f) / static_cast<float>(m_display_texture_height));
|
||||
glBindTexture(GL_TEXTURE_2D, static_cast<GLuint>(reinterpret_cast<uintptr_t>(m_display_texture_handle)));
|
||||
glBindSampler(0, m_display_linear_filtering ? m_display_linear_sampler : m_display_nearest_sampler);
|
||||
glBindVertexArray(m_display_vao);
|
||||
|
@ -38,6 +38,7 @@ public:
|
||||
void* GetRenderWindow() const override;
|
||||
|
||||
void ChangeRenderWindow(void* new_window) override;
|
||||
void WindowResized(s32 new_window_width, s32 new_window_height) override;
|
||||
|
||||
std::unique_ptr<HostDisplayTexture> CreateTexture(u32 width, u32 height, const void* data, u32 data_stride,
|
||||
bool dynamic) override;
|
||||
@ -46,9 +47,6 @@ public:
|
||||
|
||||
void SetVSync(bool enabled) override;
|
||||
|
||||
std::tuple<u32, u32> GetWindowSize() const override;
|
||||
void WindowResized() override;
|
||||
|
||||
void Render() override;
|
||||
|
||||
private:
|
||||
|
@ -28,9 +28,6 @@ bool QtDisplayWindow::createDeviceContext(QThread* worker_thread, bool debug_dev
|
||||
|
||||
bool QtDisplayWindow::initializeDeviceContext(bool debug_device)
|
||||
{
|
||||
m_window_width = static_cast<int>(static_cast<qreal>(width()) * devicePixelRatio());
|
||||
m_window_height = static_cast<int>(static_cast<qreal>(height()) * devicePixelRatio());
|
||||
|
||||
if (!createImGuiContext() || !createDeviceResources())
|
||||
return false;
|
||||
|
||||
@ -49,8 +46,8 @@ bool QtDisplayWindow::createImGuiContext()
|
||||
|
||||
auto& io = ImGui::GetIO();
|
||||
io.IniFilename = nullptr;
|
||||
io.DisplaySize.x = static_cast<float>(m_window_width);
|
||||
io.DisplaySize.y = static_cast<float>(m_window_height);
|
||||
io.DisplaySize.x = static_cast<float>(getScaledWindowWidth());
|
||||
io.DisplaySize.y = static_cast<float>(getScaledWindowHeight());
|
||||
|
||||
const float framebuffer_scale = static_cast<float>(devicePixelRatio());
|
||||
io.DisplayFramebufferScale.x = framebuffer_scale;
|
||||
@ -73,18 +70,15 @@ bool QtDisplayWindow::createDeviceResources()
|
||||
|
||||
void QtDisplayWindow::destroyDeviceResources() {}
|
||||
|
||||
void QtDisplayWindow::onWindowResized(int width, int height)
|
||||
void QtDisplayWindow::WindowResized(s32 new_window_width, s32 new_window_height)
|
||||
{
|
||||
m_window_width = width;
|
||||
m_window_height = height;
|
||||
|
||||
// imgui may not have been initialized yet
|
||||
if (!ImGui::GetCurrentContext())
|
||||
return;
|
||||
|
||||
auto& io = ImGui::GetIO();
|
||||
io.DisplaySize.x = static_cast<float>(width);
|
||||
io.DisplaySize.y = static_cast<float>(height);
|
||||
io.DisplaySize.x = static_cast<float>(new_window_width);
|
||||
io.DisplaySize.y = static_cast<float>(new_window_height);
|
||||
}
|
||||
|
||||
void QtDisplayWindow::keyPressEvent(QKeyEvent* event)
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include <QtGui/QWindow>
|
||||
#include "common/types.h"
|
||||
|
||||
class QKeyEvent;
|
||||
class QResizeEvent;
|
||||
@ -26,12 +27,15 @@ public:
|
||||
virtual void Render() = 0;
|
||||
|
||||
// this comes back on the emu thread
|
||||
virtual void onWindowResized(int width, int height);
|
||||
virtual void WindowResized(s32 new_window_width, s32 new_window_height);
|
||||
|
||||
Q_SIGNALS:
|
||||
void windowResizedEvent(int width, int height);
|
||||
|
||||
protected:
|
||||
int getScaledWindowWidth() const { return static_cast<int>(static_cast<qreal>(width()) * devicePixelRatio()); }
|
||||
int getScaledWindowHeight() const { return static_cast<int>(static_cast<qreal>(height()) * devicePixelRatio()); }
|
||||
|
||||
virtual bool createImGuiContext();
|
||||
virtual void destroyImGuiContext();
|
||||
virtual bool createDeviceResources();
|
||||
@ -42,7 +46,4 @@ protected:
|
||||
virtual void resizeEvent(QResizeEvent* event) override;
|
||||
|
||||
QtHostInterface* m_host_interface;
|
||||
|
||||
int m_window_width = 0;
|
||||
int m_window_height = 0;
|
||||
};
|
||||
|
@ -201,7 +201,7 @@ void QtHostInterface::onDisplayWindowResized(int width, int height)
|
||||
{
|
||||
// this can be null if it was destroyed and the main thread is late catching up
|
||||
if (m_display_window)
|
||||
m_display_window->onWindowResized(width, height);
|
||||
m_display_window->WindowResized(width, height);
|
||||
}
|
||||
|
||||
bool QtHostInterface::AcquireHostDisplay()
|
||||
|
Reference in New Issue
Block a user