From 5076d7dfe8836ae4ebe188a8c73cf331212906dd Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Tue, 7 Jan 2020 14:27:48 +1000 Subject: [PATCH] Qt: Fix handling of display window size in hidpi --- src/duckstation-qt/d3d11displaywindow.cpp | 406 ++++++++++++++++++++ src/duckstation-qt/d3d11displaywindow.h | 95 +++++ src/duckstation-qt/hotkeysettingswidget.cpp | 1 + src/duckstation-qt/main.cpp | 5 +- src/duckstation-qt/opengldisplaywindow.cpp | 12 +- src/duckstation-qt/qtdisplaywindow.cpp | 16 +- src/duckstation-qt/qtdisplaywindow.h | 3 + 7 files changed, 525 insertions(+), 13 deletions(-) create mode 100644 src/duckstation-qt/d3d11displaywindow.cpp create mode 100644 src/duckstation-qt/d3d11displaywindow.h diff --git a/src/duckstation-qt/d3d11displaywindow.cpp b/src/duckstation-qt/d3d11displaywindow.cpp new file mode 100644 index 000000000..9dbe21b99 --- /dev/null +++ b/src/duckstation-qt/d3d11displaywindow.cpp @@ -0,0 +1,406 @@ +#include "d3d11displaywindow.h" +#include "YBaseLib/Log.h" +#include "common/d3d11/shader_compiler.h" +#include +#include +#include +Log_SetChannel(D3D11DisplayWindow); + +class D3D11DisplayWindowTexture : public HostDisplayTexture +{ +public: + template + using ComPtr = Microsoft::WRL::ComPtr; + + D3D11DisplayWindowTexture(ComPtr texture, ComPtr srv, u32 width, u32 height, + bool dynamic) + : m_texture(std::move(texture)), m_srv(std::move(srv)), m_width(width), m_height(height), m_dynamic(dynamic) + { + } + ~D3D11DisplayWindowTexture() override = default; + + void* GetHandle() const override { return m_srv.Get(); } + u32 GetWidth() const override { return m_width; } + u32 GetHeight() const override { return m_height; } + + ID3D11Texture2D* GetD3DTexture() const { return m_texture.Get(); } + ID3D11ShaderResourceView* GetD3DSRV() const { return m_srv.Get(); } + bool IsDynamic() const { return m_dynamic; } + + static std::unique_ptr Create(ID3D11Device* device, u32 width, u32 height, const void* data, + u32 data_stride, bool dynamic) + { + const CD3D11_TEXTURE2D_DESC desc(DXGI_FORMAT_R8G8B8A8_UNORM, width, height, 1, 1, D3D11_BIND_SHADER_RESOURCE, + dynamic ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT, + dynamic ? D3D11_CPU_ACCESS_WRITE : 0, 1, 0, 0); + const D3D11_SUBRESOURCE_DATA srd{data, data_stride, data_stride * height}; + ComPtr texture; + HRESULT hr = device->CreateTexture2D(&desc, data ? &srd : nullptr, texture.GetAddressOf()); + if (FAILED(hr)) + return {}; + + const CD3D11_SHADER_RESOURCE_VIEW_DESC srv_desc(D3D11_SRV_DIMENSION_TEXTURE2D, DXGI_FORMAT_R8G8B8A8_UNORM, 0, 1, 0, + 1); + ComPtr srv; + hr = device->CreateShaderResourceView(texture.Get(), &srv_desc, srv.GetAddressOf()); + if (FAILED(hr)) + return {}; + + return std::make_unique(std::move(texture), std::move(srv), width, height, dynamic); + } + +private: + ComPtr m_texture; + ComPtr m_srv; + u32 m_width; + u32 m_height; + bool m_dynamic; +}; + +D3D11DisplayWindow::D3D11DisplayWindow(QtHostInterface* host_interface, QWindow* parent) + : QtDisplayWindow(host_interface, parent) +{ + +} + +D3D11DisplayWindow::~D3D11DisplayWindow() = default; + +HostDisplay::RenderAPI D3D11DisplayWindow::GetRenderAPI() const +{ + return HostDisplay::RenderAPI::D3D11; +} + +void* D3D11DisplayWindow::GetRenderDevice() const +{ + return m_device.Get(); +} + +void* D3D11DisplayWindow::GetRenderContext() const +{ + return m_context.Get(); +} + +void* D3D11DisplayWindow::GetRenderWindow() const +{ + return const_cast(static_cast(this)); +} + +void D3D11DisplayWindow::ChangeRenderWindow(void* new_window) +{ + Panic("Not supported"); +} + +std::unique_ptr D3D11DisplayWindow::CreateTexture(u32 width, u32 height, const void* data, + u32 data_stride, bool dynamic) +{ + return D3D11DisplayWindowTexture::Create(m_device.Get(), width, height, data, data_stride, dynamic); +} + +void D3D11DisplayWindow::UpdateTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height, const void* data, + u32 data_stride) +{ + D3D11DisplayWindowTexture* d3d11_texture = static_cast(texture); + if (!d3d11_texture->IsDynamic()) + { + const CD3D11_BOX dst_box(x, y, 0, x + width, y + height, 1); + m_context->UpdateSubresource(d3d11_texture->GetD3DTexture(), 0, &dst_box, data, data_stride, data_stride * height); + } + else + { + D3D11_MAPPED_SUBRESOURCE sr; + HRESULT hr = m_context->Map(d3d11_texture->GetD3DTexture(), 0, D3D11_MAP_WRITE_DISCARD, 0, &sr); + if (FAILED(hr)) + Panic("Failed to map dynamic host display texture"); + + char* dst_ptr = static_cast(sr.pData) + (y * sr.RowPitch) + (x * sizeof(u32)); + const char* src_ptr = static_cast(data); + if (sr.RowPitch == data_stride) + { + std::memcpy(dst_ptr, src_ptr, data_stride * height); + } + else + { + for (u32 row = 0; row < height; row++) + { + std::memcpy(dst_ptr, src_ptr, width * sizeof(u32)); + src_ptr += data_stride; + dst_ptr += sr.RowPitch; + } + } + + m_context->Unmap(d3d11_texture->GetD3DTexture(), 0); + } +} + +void D3D11DisplayWindow::SetDisplayTexture(void* texture, s32 offset_x, s32 offset_y, s32 width, s32 height, + u32 texture_width, u32 texture_height, float aspect_ratio) +{ + m_display_srv = static_cast(texture); + m_display_offset_x = offset_x; + m_display_offset_y = offset_y; + m_display_width = width; + m_display_height = height; + m_display_texture_width = texture_width; + m_display_texture_height = texture_height; + m_display_aspect_ratio = aspect_ratio; + m_display_texture_changed = true; +} + +void D3D11DisplayWindow::SetDisplayLinearFiltering(bool enabled) +{ + m_display_linear_filtering = enabled; +} + +void D3D11DisplayWindow::SetDisplayTopMargin(int height) +{ + m_display_top_margin = height; +} + +void D3D11DisplayWindow::SetVSync(bool enabled) +{ + m_vsync = enabled; +} + +std::tuple D3D11DisplayWindow::GetWindowSize() const +{ + const QSize s = size(); + return std::make_tuple(static_cast(s.width()), static_cast(s.height())); +} + +void D3D11DisplayWindow::WindowResized() +{ +} + +void D3D11DisplayWindow::onWindowResized(int width, int height) +{ + QtDisplayWindow::onWindowResized(width, height); + + m_swap_chain_rtv.Reset(); + + HRESULT hr = m_swap_chain->ResizeBuffers(0, 0, 0, DXGI_FORMAT_UNKNOWN, 0); + if (FAILED(hr)) + Log_ErrorPrintf("ResizeBuffers() failed: 0x%08X", hr); + + if (!createSwapChainRTV()) + Panic("Failed to recreate swap chain RTV after resize"); +} + +bool D3D11DisplayWindow::createDeviceContext(QThread* worker_thread) +{ + const bool debug = true; + + UINT create_flags = 0; + if (debug) + create_flags |= D3D11_CREATE_DEVICE_DEBUG; + + DXGI_SWAP_CHAIN_DESC swap_chain_desc = {}; + swap_chain_desc.BufferDesc.Width = m_window_width; + swap_chain_desc.BufferDesc.Height = m_window_height; + swap_chain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + swap_chain_desc.SampleDesc.Count = 1; + swap_chain_desc.BufferCount = 3; + swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swap_chain_desc.OutputWindow = syswm.info.win.window; + swap_chain_desc.Windowed = TRUE; + swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + + HRESULT hr = D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, create_flags, nullptr, 0, + D3D11_SDK_VERSION, &swap_chain_desc, m_swap_chain.GetAddressOf(), + m_device.GetAddressOf(), nullptr, m_context.GetAddressOf()); + + if (FAILED(hr)) + { + Log_WarningPrintf("Failed to create a flip-discard swap chain, trying discard."); + swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + } + + if (FAILED(hr)) + { + Log_ErrorPrintf("D3D11CreateDeviceAndSwapChain failed: 0x%08X", hr); + return false; + } + +#if 0 + ComPtr info; + hr = m_device.As(&info); + if (SUCCEEDED(hr)) + { + info->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, TRUE); + info->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_WARNING, TRUE); + } +#endif + + return true; +} + +bool D3D11DisplayWindow::CreateSwapChainRTV() +{ + ComPtr backbuffer; + HRESULT hr = m_swap_chain->GetBuffer(0, IID_PPV_ARGS(backbuffer.GetAddressOf())); + if (FAILED(hr)) + { + Log_ErrorPrintf("GetBuffer for RTV failed: 0x%08X", hr); + return false; + } + + D3D11_TEXTURE2D_DESC backbuffer_desc; + backbuffer->GetDesc(&backbuffer_desc); + + CD3D11_RENDER_TARGET_VIEW_DESC rtv_desc(D3D11_RTV_DIMENSION_TEXTURE2D, backbuffer_desc.Format, 0, 0, + backbuffer_desc.ArraySize); + hr = m_device->CreateRenderTargetView(backbuffer.Get(), &rtv_desc, m_swap_chain_rtv.GetAddressOf()); + if (FAILED(hr)) + { + Log_ErrorPrintf("CreateRenderTargetView for swap chain failed: 0x%08X", hr); + return false; + } + + return true; +} + +bool D3D11DisplayWindow::CreateD3DResources() +{ + static constexpr char fullscreen_quad_vertex_shader[] = R"( +cbuffer UBOBlock : register(b0) +{ + float4 u_src_rect; +}; + +void main(in uint vertex_id : SV_VertexID, + out float2 v_tex0 : TEXCOORD0, + out float4 o_pos : SV_Position) +{ + float2 pos = float2(float((vertex_id << 1) & 2u), float(vertex_id & 2u)); + v_tex0 = u_src_rect.xy + pos * u_src_rect.zw; + o_pos = float4(pos * float2(2.0f, -2.0f) + float2(-1.0f, 1.0f), 0.0f, 1.0f); +} +)"; + + static constexpr char display_pixel_shader[] = R"( +Texture2D samp0 : register(t0); +SamplerState samp0_ss : register(s0); + +void main(in float2 v_tex0 : TEXCOORD0, + out float4 o_col0 : SV_Target) +{ + o_col0 = samp0.Sample(samp0_ss, v_tex0); +} +)"; + + HRESULT hr; + + m_display_vertex_shader = + D3D11::ShaderCompiler::CompileAndCreateVertexShader(m_device.Get(), fullscreen_quad_vertex_shader, false); + m_display_pixel_shader = + D3D11::ShaderCompiler::CompileAndCreatePixelShader(m_device.Get(), display_pixel_shader, false); + if (!m_display_vertex_shader || !m_display_pixel_shader) + return false; + + if (!m_display_uniform_buffer.Create(m_device.Get(), D3D11_BIND_CONSTANT_BUFFER, DISPLAY_UNIFORM_BUFFER_SIZE)) + return false; + + CD3D11_RASTERIZER_DESC rasterizer_desc = CD3D11_RASTERIZER_DESC(CD3D11_DEFAULT()); + rasterizer_desc.CullMode = D3D11_CULL_NONE; + hr = m_device->CreateRasterizerState(&rasterizer_desc, m_display_rasterizer_state.GetAddressOf()); + if (FAILED(hr)) + return false; + + CD3D11_DEPTH_STENCIL_DESC depth_stencil_desc = CD3D11_DEPTH_STENCIL_DESC(CD3D11_DEFAULT()); + depth_stencil_desc.DepthEnable = FALSE; + depth_stencil_desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO; + hr = m_device->CreateDepthStencilState(&depth_stencil_desc, m_display_depth_stencil_state.GetAddressOf()); + if (FAILED(hr)) + return false; + + CD3D11_BLEND_DESC blend_desc = CD3D11_BLEND_DESC(CD3D11_DEFAULT()); + hr = m_device->CreateBlendState(&blend_desc, m_display_blend_state.GetAddressOf()); + if (FAILED(hr)) + return false; + + CD3D11_SAMPLER_DESC sampler_desc = CD3D11_SAMPLER_DESC(CD3D11_DEFAULT()); + sampler_desc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; + hr = m_device->CreateSamplerState(&sampler_desc, m_point_sampler.GetAddressOf()); + if (FAILED(hr)) + return false; + + sampler_desc.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT; + hr = m_device->CreateSamplerState(&sampler_desc, m_linear_sampler.GetAddressOf()); + if (FAILED(hr)) + return false; + + return true; +} + +bool D3D11DisplayWindow::CreateImGuiContext() +{ + if (!ImGui_ImplSDL2_InitForD3D(m_window) || !ImGui_ImplDX11_Init(m_device.Get(), m_context.Get())) + return false; + + ImGui_ImplDX11_NewFrame(); + ImGui_ImplSDL2_NewFrame(m_window); + return true; +} + +std::unique_ptr D3D11DisplayWindow::Create(SDL_Window* window) +{ + std::unique_ptr display = std::make_unique(window); + if (!display->CreateD3DDevice() || !display->CreateSwapChainRTV() || !display->CreateD3DResources() || + !display->CreateImGuiContext()) + { + return nullptr; + } + + return display; +} + +void D3D11DisplayWindow::Render() +{ + static constexpr std::array clear_color = {}; + m_context->ClearRenderTargetView(m_swap_chain_rtv.Get(), clear_color.data()); + m_context->OMSetRenderTargets(1, m_swap_chain_rtv.GetAddressOf(), nullptr); + + RenderDisplay(); + + ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); + + m_swap_chain->Present(BoolToUInt32(m_vsync), 0); + + ImGui_ImplSDL2_NewFrame(m_window); + ImGui_ImplDX11_NewFrame(); +} + +void D3D11DisplayWindow::RenderDisplay() +{ + if (!m_display_srv) + 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; + + m_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + m_context->VSSetShader(m_display_vertex_shader.Get(), nullptr, 0); + m_context->PSSetShader(m_display_pixel_shader.Get(), nullptr, 0); + m_context->PSSetShaderResources(0, 1, &m_display_srv); + m_context->PSSetSamplers( + 0, 1, m_display_linear_filtering ? m_linear_sampler.GetAddressOf() : m_point_sampler.GetAddressOf()); + + const float uniforms[4] = {static_cast(m_display_offset_x) / static_cast(m_display_texture_width), + static_cast(m_display_offset_y) / static_cast(m_display_texture_height), + static_cast(m_display_width) / static_cast(m_display_texture_width), + static_cast(m_display_height) / static_cast(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)); + m_context->VSSetConstantBuffers(0, 1, m_display_uniform_buffer.GetD3DBufferArray()); + + const CD3D11_VIEWPORT vp(static_cast(vp_left), static_cast(vp_top), static_cast(vp_width), + static_cast(vp_height)); + m_context->RSSetViewports(1, &vp); + m_context->RSSetState(m_display_rasterizer_state.Get()); + m_context->OMSetDepthStencilState(m_display_depth_stencil_state.Get(), 0); + m_context->OMSetBlendState(m_display_blend_state.Get(), nullptr, 0xFFFFFFFFu); + + m_context->Draw(3, 0); +} diff --git a/src/duckstation-qt/d3d11displaywindow.h b/src/duckstation-qt/d3d11displaywindow.h new file mode 100644 index 000000000..57a355800 --- /dev/null +++ b/src/duckstation-qt/d3d11displaywindow.h @@ -0,0 +1,95 @@ +#pragma once +#include "YBaseLib/Windows/WindowsHeaders.h" +#include "common/d3d11/stream_buffer.h" +#include "common/d3d11/texture.h" +#include "core/host_display.h" +#include "qtdisplaywindow.h" +#include +#include +#include + +class D3D11DisplayWindow final : public QtDisplayWindow, private HostDisplay +{ + Q_OBJECT + +public: + template + using ComPtr = Microsoft::WRL::ComPtr; + + D3D11DisplayWindow(QtHostInterface* host_interface, QWindow* parent); + ~D3D11DisplayWindow(); + + HostDisplay* getHostDisplayInterface() override; + + bool createDeviceContext(QThread* worker_thread) override; + bool initializeDeviceContext() override; + void destroyDeviceContext() override; + + RenderAPI GetRenderAPI() const override; + void* GetRenderDevice() const override; + void* GetRenderContext() const override; + void* GetRenderWindow() const override; + + void ChangeRenderWindow(void* new_window) override; + + std::unique_ptr CreateTexture(u32 width, u32 height, const void* data, u32 data_stride, + bool dynamic) override; + void UpdateTexture(HostDisplayTexture* texture, u32 x, u32 y, u32 width, u32 height, const void* data, + u32 data_stride) override; + + void SetDisplayTexture(void* texture, s32 offset_x, s32 offset_y, s32 width, s32 height, u32 texture_width, + u32 texture_height, float aspect_ratio) override; + void SetDisplayLinearFiltering(bool enabled) override; + void SetDisplayTopMargin(int height) override; + + void SetVSync(bool enabled) override; + + std::tuple 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; + + bool createImGuiContext() override; + void destroyImGuiContext() override; + bool createDeviceResources() override; + void destroyDeviceResources() override; + + bool createSwapChainRTV(); + + void renderDisplay(); + + ComPtr m_device; + ComPtr m_context; + ComPtr m_swap_chain; + ComPtr m_swap_chain_rtv; + + ComPtr m_display_rasterizer_state; + ComPtr m_display_depth_stencil_state; + ComPtr m_display_blend_state; + ComPtr m_display_vertex_shader; + ComPtr m_display_pixel_shader; + ComPtr m_point_sampler; + ComPtr m_linear_sampler; + + D3D11::Texture m_display_pixels_texture; + D3D11::StreamBuffer m_display_uniform_buffer; + + ID3D11ShaderResourceView* m_display_srv = nullptr; + s32 m_display_offset_x = 0; + s32 m_display_offset_y = 0; + s32 m_display_width = 0; + s32 m_display_height = 0; + u32 m_display_texture_width = 0; + u32 m_display_texture_height = 0; + int m_display_top_margin = 0; + float m_display_aspect_ratio = 1.0f; + + bool m_display_texture_changed = false; + bool m_display_linear_filtering = false; + bool m_vsync = false; +}; diff --git a/src/duckstation-qt/hotkeysettingswidget.cpp b/src/duckstation-qt/hotkeysettingswidget.cpp index e76087927..041841b73 100644 --- a/src/duckstation-qt/hotkeysettingswidget.cpp +++ b/src/duckstation-qt/hotkeysettingswidget.cpp @@ -20,6 +20,7 @@ HotkeySettingsWidget::~HotkeySettingsWidget() = default; void HotkeySettingsWidget::createUi() { QGridLayout* layout = new QGridLayout(this); + layout->setContentsMargins(0, 0, 0, 0); m_tab_widget = new QTabWidget(this); diff --git a/src/duckstation-qt/main.cpp b/src/duckstation-qt/main.cpp index b4dcadf61..835bc79c3 100644 --- a/src/duckstation-qt/main.cpp +++ b/src/duckstation-qt/main.cpp @@ -20,7 +20,10 @@ int main(int argc, char* argv[]) { InitLogging(); - QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); +#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0) + QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); +#endif QApplication app(argc, argv); diff --git a/src/duckstation-qt/opengldisplaywindow.cpp b/src/duckstation-qt/opengldisplaywindow.cpp index 68dd92610..76f123391 100644 --- a/src/duckstation-qt/opengldisplaywindow.cpp +++ b/src/duckstation-qt/opengldisplaywindow.cpp @@ -191,13 +191,11 @@ void OpenGLDisplayWindow::SetVSync(bool enabled) std::tuple OpenGLDisplayWindow::GetWindowSize() const { - const QSize s = size(); - return std::make_tuple(static_cast(s.width()), static_cast(s.height())); + return std::make_tuple(static_cast(m_window_width), static_cast(m_window_height)); } void OpenGLDisplayWindow::WindowResized() {} - const char* OpenGLDisplayWindow::GetGLSLVersionString() const { return m_is_gles ? "#version 300 es" : "#version 130\n"; @@ -483,11 +481,10 @@ void OpenGLDisplayWindow::renderDisplay() return; // - 20 for main menu padding - const QSize window_size = size(); - const auto [vp_left, vp_top, vp_width, vp_height] = CalculateDrawRect( - window_size.width(), std::max(window_size.height() - m_display_top_margin, 1), m_display_aspect_ratio); + 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); - glViewport(vp_left, window_size.height() - (m_display_top_margin + vp_top) - vp_height, vp_width, vp_height); + glViewport(vp_left, m_window_height - (m_display_top_margin + vp_top) - vp_height, vp_width, vp_height); glDisable(GL_BLEND); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); @@ -504,4 +501,3 @@ void OpenGLDisplayWindow::renderDisplay() glDrawArrays(GL_TRIANGLES, 0, 3); glBindSampler(0, 0); } - diff --git a/src/duckstation-qt/qtdisplaywindow.cpp b/src/duckstation-qt/qtdisplaywindow.cpp index d7b2064b2..8258ac124 100644 --- a/src/duckstation-qt/qtdisplaywindow.cpp +++ b/src/duckstation-qt/qtdisplaywindow.cpp @@ -1,12 +1,14 @@ #include "qtdisplaywindow.h" #include "imgui.h" -#include "qtutils.h" #include "qthostinterface.h" +#include "qtutils.h" #include QtDisplayWindow::QtDisplayWindow(QtHostInterface* host_interface, QWindow* parent) : QWindow(parent), m_host_interface(host_interface) { + m_window_width = static_cast(static_cast(width()) * devicePixelRatio()); + m_window_height = static_cast(static_cast(height()) * devicePixelRatio()); } QtDisplayWindow::~QtDisplayWindow() = default; @@ -40,8 +42,8 @@ bool QtDisplayWindow::createImGuiContext() ImGui::CreateContext(); auto& io = ImGui::GetIO(); - io.DisplaySize.x = static_cast(width()); - io.DisplaySize.y = static_cast(height()); + io.DisplaySize.x = static_cast(m_window_width); + io.DisplaySize.y = static_cast(m_window_height); return true; } @@ -62,6 +64,9 @@ void QtDisplayWindow::Render() {} void QtDisplayWindow::onWindowResized(int width, int height) { + m_window_width = width; + m_window_height = height; + // imgui may not have been initialized yet if (!ImGui::GetCurrentContext()) return; @@ -90,5 +95,8 @@ void QtDisplayWindow::keyReleaseEvent(QKeyEvent* event) void QtDisplayWindow::resizeEvent(QResizeEvent* event) { QWindow::resizeEvent(event); - emit windowResizedEvent(event->size().width(), event->size().height()); + + const int width = static_cast(static_cast(event->size().width()) * devicePixelRatio()); + const int height = static_cast(static_cast(event->size().height()) * devicePixelRatio()); + emit windowResizedEvent(width, height); } diff --git a/src/duckstation-qt/qtdisplaywindow.h b/src/duckstation-qt/qtdisplaywindow.h index d14f070f2..6252aed09 100644 --- a/src/duckstation-qt/qtdisplaywindow.h +++ b/src/duckstation-qt/qtdisplaywindow.h @@ -41,4 +41,7 @@ protected: virtual void resizeEvent(QResizeEvent* event) override; QtHostInterface* m_host_interface; + + int m_window_width = 0; + int m_window_height = 0; };