From 218f6721d3f6ab97fa89be8580280e7ceed8ab19 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sat, 4 Jul 2020 20:05:49 +1000 Subject: [PATCH] libretro: Fix display rendering in D3D11/OpenGL --- .../libretro_d3d11_host_display.cpp | 30 +++++++++---------- .../libretro_d3d11_host_display.h | 4 ++- .../libretro_host_interface.cpp | 3 +- .../libretro_host_interface.h | 2 ++ .../libretro_opengl_host_display.cpp | 20 ++++++++----- 5 files changed, 33 insertions(+), 26 deletions(-) diff --git a/src/duckstation-libretro/libretro_d3d11_host_display.cpp b/src/duckstation-libretro/libretro_d3d11_host_display.cpp index 0a02a2276..9db4e060f 100644 --- a/src/duckstation-libretro/libretro_d3d11_host_display.cpp +++ b/src/duckstation-libretro/libretro_d3d11_host_display.cpp @@ -56,15 +56,13 @@ bool LibretroD3D11HostDisplay::CreateRenderDevice(const WindowInfo& wi, std::str m_device = d3d11_ri->device; m_context = d3d11_ri->context; - return CreateResources(); + return true; } -void LibretroD3D11HostDisplay::DestroyRenderDevice() +void LibretroD3D11HostDisplay::DestroyResources() { - DestroyResources(); + D3D11HostDisplay::DestroyResources(); m_framebuffer.Destroy(); - m_context.Reset(); - m_device.Reset(); } void LibretroD3D11HostDisplay::ResizeRenderWindow(s32 new_window_width, s32 new_window_height) @@ -75,8 +73,10 @@ void LibretroD3D11HostDisplay::ResizeRenderWindow(s32 new_window_width, s32 new_ bool LibretroD3D11HostDisplay::Render() { - // TODO: Skip framebuffer when offset is (0,0). - if (!CheckFramebufferSize(m_display_texture_view_width, m_display_texture_view_height)) + const u32 resolution_scale = g_libretro_host_interface.GetResolutionScale(); + const u32 display_width = static_cast(m_display_width) * resolution_scale; + const u32 display_height = static_cast(m_display_height) * resolution_scale; + if (!CheckFramebufferSize(display_width, display_height)) return false; // Ensure we're not currently bound. @@ -86,9 +86,10 @@ bool LibretroD3D11HostDisplay::Render() if (HasDisplayTexture()) { - RenderDisplay(0, 0, m_display_texture_view_width, m_display_texture_view_height, m_display_texture_handle, - m_display_texture_width, m_display_texture_height, m_display_texture_view_x, m_display_texture_view_y, - m_display_texture_view_width, m_display_texture_view_height, m_display_linear_filtering); + const auto [left, top, width, height] = CalculateDrawRect(display_width, display_height, 0); + RenderDisplay(left, top, width, height, m_display_texture_handle, m_display_texture_width, m_display_texture_height, + m_display_texture_view_x, m_display_texture_view_y, m_display_texture_view_width, + m_display_texture_view_height, m_display_linear_filtering); } if (HasSoftwareCursor()) @@ -101,18 +102,15 @@ bool LibretroD3D11HostDisplay::Render() // NOTE: libretro frontend expects the data bound to PS SRV slot 0. m_context->OMSetRenderTargets(0, nullptr, nullptr); m_context->PSSetShaderResources(0, 1, m_framebuffer.GetD3DSRVArray()); - g_retro_video_refresh_callback(RETRO_HW_FRAME_BUFFER_VALID, m_display_texture_view_width, - m_display_texture_view_height, 0); + g_retro_video_refresh_callback(RETRO_HW_FRAME_BUFFER_VALID, display_width, display_height, 0); return true; } bool LibretroD3D11HostDisplay::CheckFramebufferSize(u32 width, u32 height) { - if (m_framebuffer.GetWidth() >= width && m_framebuffer.GetHeight() >= height) + if (m_framebuffer.GetWidth() == width && m_framebuffer.GetHeight() == height) return true; - const u32 rounded_width = Common::AlignUpPow2(width, 1024); - const u32 rounded_height = Common::AlignUpPow2(height, 512); - return m_framebuffer.Create(m_device.Get(), rounded_width, rounded_height, DXGI_FORMAT_R8G8B8A8_UNORM, + return m_framebuffer.Create(m_device.Get(), width, height, DXGI_FORMAT_R8G8B8A8_UNORM, D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET); } diff --git a/src/duckstation-libretro/libretro_d3d11_host_display.h b/src/duckstation-libretro/libretro_d3d11_host_display.h index 1c043a4d3..663d4443d 100644 --- a/src/duckstation-libretro/libretro_d3d11_host_display.h +++ b/src/duckstation-libretro/libretro_d3d11_host_display.h @@ -12,7 +12,6 @@ public: static bool RequestHardwareRendererContext(retro_hw_render_callback* cb); bool CreateRenderDevice(const WindowInfo& wi, std::string_view adapter_name, bool debug_device) override; - void DestroyRenderDevice(); void ResizeRenderWindow(s32 new_window_width, s32 new_window_height) override; @@ -20,6 +19,9 @@ public: bool Render() override; +protected: + void DestroyResources() override; + private: bool CheckFramebufferSize(u32 width, u32 height); diff --git a/src/duckstation-libretro/libretro_host_interface.cpp b/src/duckstation-libretro/libretro_host_interface.cpp index ccd8de377..c88a2b9ac 100644 --- a/src/duckstation-libretro/libretro_host_interface.cpp +++ b/src/duckstation-libretro/libretro_host_interface.cpp @@ -778,7 +778,8 @@ void LibretroHostInterface::SwitchToHardwareRenderer() wi.surface_width = avi.geometry.base_width; wi.surface_height = avi.geometry.base_height; wi.surface_scale = 1.0f; - if (!display || !display->CreateRenderDevice(wi, {}, g_libretro_host_interface.m_settings.gpu_use_debug_device)) + if (!display || !display->CreateRenderDevice(wi, {}, g_libretro_host_interface.m_settings.gpu_use_debug_device) || + !display->InitializeRenderDevice({}, m_settings.gpu_use_debug_device)) { Log_ErrorPrintf("Failed to create hardware host display"); return; diff --git a/src/duckstation-libretro/libretro_host_interface.h b/src/duckstation-libretro/libretro_host_interface.h index 14bf734ea..7dda43e60 100644 --- a/src/duckstation-libretro/libretro_host_interface.h +++ b/src/duckstation-libretro/libretro_host_interface.h @@ -13,6 +13,8 @@ public: static bool SetCoreOptions(); static bool HasCoreVariablesChanged(); + ALWAYS_INLINE u32 GetResolutionScale() const { return m_settings.gpu_resolution_scale; } + bool Initialize() override; void Shutdown() override; diff --git a/src/duckstation-libretro/libretro_opengl_host_display.cpp b/src/duckstation-libretro/libretro_opengl_host_display.cpp index b456b0303..fbc70670d 100644 --- a/src/duckstation-libretro/libretro_opengl_host_display.cpp +++ b/src/duckstation-libretro/libretro_opengl_host_display.cpp @@ -99,7 +99,7 @@ bool LibretroOpenGLHostDisplay::CreateRenderDevice(const WindowInfo& wi, std::st return false; } - return CreateResources(); + return true; } void LibretroOpenGLHostDisplay::DestroyRenderDevice() @@ -117,28 +117,32 @@ bool LibretroOpenGLHostDisplay::Render() { const GLuint fbo = static_cast( static_cast(m_window_info.display_connection)->get_current_framebuffer()); + const u32 resolution_scale = g_libretro_host_interface.GetResolutionScale(); + const u32 display_width = static_cast(m_display_width) * resolution_scale; + const u32 display_height = static_cast(m_display_height) * resolution_scale; - glDisable(GL_SCISSOR_TEST); + glEnable(GL_SCISSOR_TEST); + glScissor(0, 0, display_width, display_height); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT); if (HasDisplayTexture()) { - RenderDisplay(0, 0, m_display_texture_view_width, m_display_texture_view_height, m_display_texture_handle, - m_display_texture_width, m_display_texture_height, m_display_texture_view_x, m_display_texture_view_y, - m_display_texture_view_width, m_display_texture_view_height, m_display_linear_filtering); + const auto [left, top, width, height] = CalculateDrawRect(display_width, display_height, 0); + RenderDisplay(left, top, width, height, m_display_texture_handle, m_display_texture_width, m_display_texture_height, + m_display_texture_view_x, m_display_texture_view_y, m_display_texture_view_width, + m_display_texture_view_height, m_display_linear_filtering); } if (HasSoftwareCursor()) { // TODO: Scale mouse x/y const auto [left, top, width, height] = CalculateSoftwareCursorDrawRect(m_mouse_position_x, m_mouse_position_y); - RenderSoftwareCursor(left, m_display_texture_view_height - top - height, width, height, m_cursor_texture.get()); + RenderSoftwareCursor(left, display_height - top - height, width, height, m_cursor_texture.get()); } - g_retro_video_refresh_callback(RETRO_HW_FRAME_BUFFER_VALID, m_display_texture_view_width, - m_display_texture_view_height, 0); + g_retro_video_refresh_callback(RETRO_HW_FRAME_BUFFER_VALID, display_width, display_height, 0); GL::Program::ResetLastProgram(); return true;