diff --git a/rpcs3/Emu/RSX/GL/GLDraw.cpp b/rpcs3/Emu/RSX/GL/GLDraw.cpp index 955bfbd59b..213275b9c4 100644 --- a/rpcs3/Emu/RSX/GL/GLDraw.cpp +++ b/rpcs3/Emu/RSX/GL/GLDraw.cpp @@ -485,7 +485,7 @@ void GLGSRender::bind_texture_env() } else { - auto target = gl::get_target(current_fragment_program.get_texture_dimension(i)); + const auto target = gl::get_target(current_fragment_program.get_texture_dimension(i)); cmd->bind_texture(GL_FRAGMENT_TEXTURES_START + i, target, m_null_textures[target]->id()); if (current_fragment_program.texture_state.redirected_textures & (1 << i)) diff --git a/rpcs3/Emu/RSX/GL/GLGSRender.h b/rpcs3/Emu/RSX/GL/GLGSRender.h index 51b126cc73..465fa51584 100644 --- a/rpcs3/Emu/RSX/GL/GLGSRender.h +++ b/rpcs3/Emu/RSX/GL/GLGSRender.h @@ -137,6 +137,8 @@ class GLGSRender : public GSRender, public ::rsx::reports::ZCULL_control std::unique_ptr m_flip_tex_color[2]; // Present + gl::fbo m_sshot_fbo; + std::unique_ptr m_sshot_tex; std::unique_ptr m_upscaler; output_scaling_mode m_output_scaling = output_scaling_mode::bilinear; diff --git a/rpcs3/Emu/RSX/GL/GLPresent.cpp b/rpcs3/Emu/RSX/GL/GLPresent.cpp index ed71652063..f0bedc075b 100644 --- a/rpcs3/Emu/RSX/GL/GLPresent.cpp +++ b/rpcs3/Emu/RSX/GL/GLPresent.cpp @@ -204,7 +204,8 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info) // Enable drawing to window backbuffer gl::screen.bind(); - gl::texture *image_to_flip = nullptr, *image_to_flip2 = nullptr; + gl::texture* image_to_flip = nullptr; + gl::texture* image_to_flip2 = nullptr; if (info.buffer < display_buffers_count && buffer_width && buffer_height) { @@ -276,15 +277,86 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info) gl::screen.clear(gl::buffers::color); } + if (m_overlay_manager && m_overlay_manager->has_dirty()) + { + m_overlay_manager->lock_shared(); + + std::vector uids_to_dispose; + uids_to_dispose.reserve(m_overlay_manager->get_dirty().size()); + + for (const auto& view : m_overlay_manager->get_dirty()) + { + m_ui_renderer.remove_temp_resources(view->uid); + uids_to_dispose.push_back(view->uid); + } + + m_overlay_manager->unlock_shared(); + m_overlay_manager->dispose(uids_to_dispose); + } + + const auto render_overlays = [this, &cmd](gl::texture* dst, const areau& aspect_ratio) + { + if (m_overlay_manager && m_overlay_manager->has_visible()) + { + GLuint target = 0; + + if (dst) + { + m_sshot_fbo.bind(); + m_sshot_fbo.color = dst->id(); + target = dst->id(); + } + else + { + gl::screen.bind(); + } + + // Lock to avoid modification during run-update chain + std::lock_guard lock(*m_overlay_manager); + + for (const auto& view : m_overlay_manager->get_views()) + { + m_ui_renderer.run(cmd, aspect_ratio, target, *view.get()); + } + } + }; + if (image_to_flip) { if (g_user_asked_for_screenshot || (g_recording_mode != recording_mode::stopped && m_frame->can_consume_frame())) { + static const gl::pixel_pack_settings pack_settings{}; + + gl::texture* tex = image_to_flip; + + if (g_cfg.video.record_with_overlays) + { + m_sshot_fbo.create(); + m_sshot_tex = std::make_unique( + GLenum(image_to_flip->get_target()), + image_to_flip->width(), + image_to_flip->height(), + image_to_flip->depth(), + image_to_flip->levels(), + image_to_flip->samples(), + GLenum(image_to_flip->get_internal_format()), + image_to_flip->format_class()); + + tex = m_sshot_tex.get(); + + static const position3u offset{}; + gl::g_hw_blitter->copy_image(cmd, image_to_flip, tex, 0, 0, offset, offset, { tex->width(), tex->height(), 1 }); + + render_overlays(tex, areau(0, 0, image_to_flip->width(), image_to_flip->height())); + m_sshot_fbo.remove(); + } + std::vector sshot_frame(buffer_height * buffer_width * 4); glGetError(); - gl::pixel_pack_settings pack_settings{}; - image_to_flip->copy_to(sshot_frame.data(), gl::texture::format::rgba, gl::texture::type::ubyte, pack_settings); + tex->copy_to(sshot_frame.data(), gl::texture::format::rgba, gl::texture::type::ubyte, pack_settings); + + m_sshot_tex.reset(); if (GLenum err = glGetError(); err != GL_NO_ERROR) { @@ -296,7 +368,7 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info) } else { - m_frame->present_frame(sshot_frame, buffer_width * 4, buffer_width, buffer_height, false); + m_frame->present_frame(std::move(sshot_frame), buffer_width * 4, buffer_width, buffer_height, false); } } @@ -349,38 +421,7 @@ void GLGSRender::flip(const rsx::display_flip_info_t& info) } } - if (m_overlay_manager) - { - if (m_overlay_manager->has_dirty()) - { - m_overlay_manager->lock_shared(); - - std::vector uids_to_dispose; - uids_to_dispose.reserve(m_overlay_manager->get_dirty().size()); - - for (const auto& view : m_overlay_manager->get_dirty()) - { - m_ui_renderer.remove_temp_resources(view->uid); - uids_to_dispose.push_back(view->uid); - } - - m_overlay_manager->unlock_shared(); - m_overlay_manager->dispose(uids_to_dispose); - } - - if (m_overlay_manager->has_visible()) - { - gl::screen.bind(); - - // Lock to avoid modification during run-update chain - std::lock_guard lock(*m_overlay_manager); - - for (const auto& view : m_overlay_manager->get_views()) - { - m_ui_renderer.run(cmd, areau(aspect_ratio), 0, *view.get()); - } - } - } + render_overlays(nullptr, areau(aspect_ratio)); if (g_cfg.video.debug_overlay) { diff --git a/rpcs3/Emu/RSX/GL/glutils/image.h b/rpcs3/Emu/RSX/GL/glutils/image.h index 896c3ee088..6617caa54c 100644 --- a/rpcs3/Emu/RSX/GL/glutils/image.h +++ b/rpcs3/Emu/RSX/GL/glutils/image.h @@ -353,7 +353,7 @@ namespace gl GLenum m_aspect_flags = 0; texture* m_image_data = nullptr; - GLenum component_swizzle[4]; + GLenum component_swizzle[4] {}; texture_view() = default; diff --git a/rpcs3/Emu/RSX/GSFrameBase.h b/rpcs3/Emu/RSX/GSFrameBase.h index ef17378dd3..69d2832c55 100644 --- a/rpcs3/Emu/RSX/GSFrameBase.h +++ b/rpcs3/Emu/RSX/GSFrameBase.h @@ -31,6 +31,6 @@ public: virtual display_handle_t handle() const = 0; virtual bool can_consume_frame() const = 0; - virtual void present_frame(std::vector& data, u32 pitch, u32 width, u32 height, bool is_bgra) const = 0; + virtual void present_frame(std::vector&& data, u32 pitch, u32 width, u32 height, bool is_bgra) const = 0; virtual void take_screenshot(std::vector&& sshot_data, u32 sshot_width, u32 sshot_height, bool is_bgra) = 0; }; diff --git a/rpcs3/Emu/RSX/Overlays/HomeMenu/overlay_home_menu_settings.cpp b/rpcs3/Emu/RSX/Overlays/HomeMenu/overlay_home_menu_settings.cpp index 119f411a24..fe55a4aaa4 100644 --- a/rpcs3/Emu/RSX/Overlays/HomeMenu/overlay_home_menu_settings.cpp +++ b/rpcs3/Emu/RSX/Overlays/HomeMenu/overlay_home_menu_settings.cpp @@ -99,6 +99,7 @@ namespace rsx add_checkbox(&g_cfg.misc.show_pressure_intensity_toggle_hint, localized_string_id::HOME_MENU_SETTINGS_OVERLAYS_SHOW_PRESSURE_INTENSITY_TOGGLE_HINT); add_checkbox(&g_cfg.misc.show_analog_limiter_toggle_hint, localized_string_id::HOME_MENU_SETTINGS_OVERLAYS_SHOW_ANALOG_LIMITER_TOGGLE_HINT); add_checkbox(&g_cfg.misc.show_mouse_and_keyboard_toggle_hint, localized_string_id::HOME_MENU_SETTINGS_OVERLAYS_SHOW_MOUSE_AND_KB_TOGGLE_HINT); + add_checkbox(&g_cfg.video.record_with_overlays, localized_string_id::HOME_MENU_SETTINGS_OVERLAYS_RECORD_WITH_OVERLAYS); apply_layout(); } diff --git a/rpcs3/Emu/RSX/VK/VKFramebuffer.cpp b/rpcs3/Emu/RSX/VK/VKFramebuffer.cpp index e0bbad628a..d1fc5a4764 100644 --- a/rpcs3/Emu/RSX/VK/VKFramebuffer.cpp +++ b/rpcs3/Emu/RSX/VK/VKFramebuffer.cpp @@ -29,9 +29,9 @@ namespace vk vk::framebuffer_holder* get_framebuffer(VkDevice dev, u16 width, u16 height, VkBool32 has_input_attachments, VkRenderPass renderpass, const std::vector& image_list) { framebuffer_storage_key key(width, height, has_input_attachments); - auto &queue = g_framebuffers_cache[key.encoded]; + auto& queue = g_framebuffers_cache[key.encoded]; - for (auto &fbo : queue) + for (const auto& fbo : queue) { if (fbo->matches(image_list, width, height)) { @@ -42,7 +42,7 @@ namespace vk std::vector> image_views; image_views.reserve(image_list.size()); - for (auto &e : image_list) + for (const auto& e : image_list) { const VkImageSubresourceRange subres = { e->aspect(), 0, 1, 0, 1 }; image_views.push_back(std::make_unique(dev, e, VK_IMAGE_VIEW_TYPE_2D, vk::default_component_map, subres)); @@ -58,9 +58,9 @@ namespace vk vk::framebuffer_holder* get_framebuffer(VkDevice dev, u16 width, u16 height, VkBool32 has_input_attachments, VkRenderPass renderpass, VkFormat format, VkImage attachment) { framebuffer_storage_key key(width, height, has_input_attachments); - auto &queue = g_framebuffers_cache[key.encoded]; + auto& queue = g_framebuffers_cache[key.encoded]; - for (const auto &e : queue) + for (const auto& e : queue) { if (e->attachments[0]->info.image == attachment) { diff --git a/rpcs3/Emu/RSX/VK/VKPresent.cpp b/rpcs3/Emu/RSX/VK/VKPresent.cpp index a685dbabaa..187d6bd886 100644 --- a/rpcs3/Emu/RSX/VK/VKPresent.cpp +++ b/rpcs3/Emu/RSX/VK/VKPresent.cpp @@ -613,6 +613,21 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info) } } + const bool has_overlay = (m_overlay_manager && m_overlay_manager->has_visible()); + const auto render_overlays = [&](vk::framebuffer_holder* fbo, const areau& area) + { + if (!has_overlay) return; + + // Lock to avoid modification during run-update chain + auto ui_renderer = vk::get_overlay_pass(); + std::lock_guard lock(*m_overlay_manager); + + for (const auto& view : m_overlay_manager->get_views()) + { + ui_renderer->run(*m_current_command_buffer, area, fbo, single_target_pass, m_texture_upload_buffer_ring_info, *view.get()); + } + }; + if (image_to_flip) { const bool use_full_rgb_range_output = g_cfg.video.full_rgb_range_output.get(); @@ -699,17 +714,48 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info) copy_info.imageExtent.height = buffer_height; copy_info.imageExtent.depth = 1; - image_to_flip->push_layout(*m_current_command_buffer, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); - vk::copy_image_to_buffer(*m_current_command_buffer, image_to_flip, &sshot_vkbuf, copy_info); - image_to_flip->pop_layout(*m_current_command_buffer); + std::unique_ptr tmp_tex; + vk::image* image_to_copy = image_to_flip; + + if (g_cfg.video.record_with_overlays && has_overlay) + { + const auto key = vk::get_renderpass_key(m_swapchain->get_surface_format()); + single_target_pass = vk::get_renderpass(*m_device, key); + ensure(single_target_pass != VK_NULL_HANDLE); + + tmp_tex = std::make_unique(*m_device, m_device->get_memory_mapping().device_local, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, + image_to_flip->type(), image_to_flip->format(), image_to_flip->width(), image_to_flip->height(), 1, 1, image_to_flip->layers(), VK_SAMPLE_COUNT_1_BIT, image_to_flip->current_layout, + VK_IMAGE_TILING_OPTIMAL, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, + 0, VMM_ALLOCATION_POOL_UNDEFINED); + + tmp_tex->change_layout(*m_current_command_buffer, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); + image_to_flip->push_layout(*m_current_command_buffer, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + + const areai rect = areai(0, 0, buffer_width, buffer_height); + vk::copy_image(*m_current_command_buffer, image_to_flip, tmp_tex.get(), rect, rect, 1); + + image_to_flip->pop_layout(*m_current_command_buffer); + tmp_tex->change_layout(*m_current_command_buffer, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + + vk::framebuffer_holder* sshot_fbo = vk::get_framebuffer(*m_device, buffer_width, buffer_height, VK_FALSE, single_target_pass, { tmp_tex.get() }); + sshot_fbo->add_ref(); + render_overlays(sshot_fbo, areau(rect)); + sshot_fbo->release(); + + image_to_copy = tmp_tex.get(); + } + + image_to_copy->push_layout(*m_current_command_buffer, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); + vk::copy_image_to_buffer(*m_current_command_buffer, image_to_copy, &sshot_vkbuf, copy_info); + image_to_copy->pop_layout(*m_current_command_buffer); flush_command_queue(true); - auto src = sshot_vkbuf.map(0, sshot_size); + const auto src = sshot_vkbuf.map(0, sshot_size); std::vector sshot_frame(sshot_size); memcpy(sshot_frame.data(), src, sshot_size); sshot_vkbuf.unmap(); - const bool is_bgra = image_to_flip->format() == VK_FORMAT_B8G8R8A8_UNORM; + const bool is_bgra = image_to_copy->format() == VK_FORMAT_B8G8R8A8_UNORM; if (g_user_asked_for_screenshot.exchange(false)) { @@ -717,12 +763,11 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info) } else { - m_frame->present_frame(sshot_frame, buffer_width * 4, buffer_width, buffer_height, is_bgra); + m_frame->present_frame(std::move(sshot_frame), buffer_width * 4, buffer_width, buffer_height, is_bgra); } } } - const bool has_overlay = (m_overlay_manager && m_overlay_manager->has_visible()); if (g_cfg.video.debug_overlay || has_overlay) { if (target_layout != VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) @@ -754,17 +799,7 @@ void VKGSRender::flip(const rsx::display_flip_info_t& info) direct_fbo->add_ref(); - if (has_overlay) - { - // Lock to avoid modification during run-update chain - auto ui_renderer = vk::get_overlay_pass(); - std::lock_guard lock(*m_overlay_manager); - - for (const auto& view : m_overlay_manager->get_views()) - { - ui_renderer->run(*m_current_command_buffer, areau(aspect_ratio), direct_fbo, single_target_pass, m_texture_upload_buffer_ring_info, *view.get()); - } - } + render_overlays(direct_fbo, areau(aspect_ratio)); if (g_cfg.video.debug_overlay) { diff --git a/rpcs3/Emu/RSX/VK/vkutils/framebuffer_object.hpp b/rpcs3/Emu/RSX/VK/vkutils/framebuffer_object.hpp index 03ce077bcc..257d93e42e 100644 --- a/rpcs3/Emu/RSX/VK/vkutils/framebuffer_object.hpp +++ b/rpcs3/Emu/RSX/VK/vkutils/framebuffer_object.hpp @@ -47,35 +47,35 @@ namespace vk vkDestroyFramebuffer(m_device, value, nullptr); } - u32 width() + u32 width() const { return m_width; } - u32 height() + u32 height() const { return m_height; } - u8 samples() + u8 samples() const { ensure(!attachments.empty()); return attachments[0]->image()->samples(); } - VkFormat format() + VkFormat format() const { ensure(!attachments.empty()); return attachments[0]->image()->format(); } - VkFormat depth_format() + VkFormat depth_format() const { ensure(!attachments.empty()); return attachments.back()->image()->format(); } - bool matches(const std::vector& fbo_images, u32 width, u32 height) + bool matches(const std::vector& fbo_images, u32 width, u32 height) const { if (m_width != width || m_height != height) return false; diff --git a/rpcs3/Emu/localized_string_id.h b/rpcs3/Emu/localized_string_id.h index 408403fd1f..00f644d993 100644 --- a/rpcs3/Emu/localized_string_id.h +++ b/rpcs3/Emu/localized_string_id.h @@ -244,6 +244,7 @@ enum class localized_string_id HOME_MENU_SETTINGS_OVERLAYS_SHOW_PRESSURE_INTENSITY_TOGGLE_HINT, HOME_MENU_SETTINGS_OVERLAYS_SHOW_ANALOG_LIMITER_TOGGLE_HINT, HOME_MENU_SETTINGS_OVERLAYS_SHOW_MOUSE_AND_KB_TOGGLE_HINT, + HOME_MENU_SETTINGS_OVERLAYS_RECORD_WITH_OVERLAYS, HOME_MENU_SETTINGS_PERFORMANCE_OVERLAY, HOME_MENU_SETTINGS_PERFORMANCE_OVERLAY_ENABLE, HOME_MENU_SETTINGS_PERFORMANCE_OVERLAY_ENABLE_FRAMERATE_GRAPH, diff --git a/rpcs3/Emu/system_config.h b/rpcs3/Emu/system_config.h index 92031a51db..b95d7f213f 100644 --- a/rpcs3/Emu/system_config.h +++ b/rpcs3/Emu/system_config.h @@ -181,6 +181,7 @@ struct cfg_root : cfg::node cfg::_bool disable_msl_fast_math{ this, "Disable MSL Fast Math", false }; cfg::_bool disable_async_host_memory_manager{ this, "Disable Asynchronous Memory Manager", false, true }; cfg::_enum output_scaling{ this, "Output Scaling Mode", output_scaling_mode::bilinear, true }; + cfg::_bool record_with_overlays{ this, "Record With Overlays", true, true }; struct node_vk : cfg::node { diff --git a/rpcs3/rpcs3qt/emu_settings_type.h b/rpcs3/rpcs3qt/emu_settings_type.h index 0fda096705..d705f2892a 100644 --- a/rpcs3/rpcs3qt/emu_settings_type.h +++ b/rpcs3/rpcs3qt/emu_settings_type.h @@ -106,6 +106,7 @@ enum class emu_settings_type OutputScalingMode, ForceHwMSAAResolve, DisableAsyncHostMM, + RecordWithOverlays, // Performance Overlay PerfOverlayEnabled, @@ -301,6 +302,7 @@ inline static const std::map settings_location { emu_settings_type::OutputScalingMode, { "Video", "Output Scaling Mode"}}, { emu_settings_type::ForceHwMSAAResolve, { "Video", "Force Hardware MSAA Resolve"}}, { emu_settings_type::DisableAsyncHostMM, { "Video", "Disable Asynchronous Memory Manager"}}, + { emu_settings_type::RecordWithOverlays, { "Video", "Record With Overlays"}}, // Vulkan { emu_settings_type::VulkanAsyncTextureUploads, { "Video", "Vulkan", "Asynchronous Texture Streaming 2"}}, diff --git a/rpcs3/rpcs3qt/gs_frame.cpp b/rpcs3/rpcs3qt/gs_frame.cpp index 8cd2a2bc9b..44115f6138 100644 --- a/rpcs3/rpcs3qt/gs_frame.cpp +++ b/rpcs3/rpcs3qt/gs_frame.cpp @@ -795,10 +795,10 @@ bool gs_frame::can_consume_frame() const return video_provider.can_consume_frame(); } -void gs_frame::present_frame(std::vector& data, u32 pitch, u32 width, u32 height, bool is_bgra) const +void gs_frame::present_frame(std::vector&& data, u32 pitch, u32 width, u32 height, bool is_bgra) const { utils::video_provider& video_provider = g_fxo->get(); - video_provider.present_frame(data, pitch, width, height, is_bgra); + video_provider.present_frame(std::move(data), pitch, width, height, is_bgra); } void gs_frame::take_screenshot(std::vector&& data, u32 sshot_width, u32 sshot_height, bool is_bgra) diff --git a/rpcs3/rpcs3qt/gs_frame.h b/rpcs3/rpcs3qt/gs_frame.h index 38bbaa0a3e..858a06340d 100644 --- a/rpcs3/rpcs3qt/gs_frame.h +++ b/rpcs3/rpcs3qt/gs_frame.h @@ -78,7 +78,7 @@ public: bool get_mouse_lock_state(); bool can_consume_frame() const override; - void present_frame(std::vector& data, u32 pitch, u32 width, u32 height, bool is_bgra) const override; + void present_frame(std::vector&& data, u32 pitch, u32 width, u32 height, bool is_bgra) const override; void take_screenshot(std::vector&& data, u32 sshot_width, u32 sshot_height, bool is_bgra) override; protected: diff --git a/rpcs3/rpcs3qt/localized_emu.h b/rpcs3/rpcs3qt/localized_emu.h index 1beab0f082..426795bffb 100644 --- a/rpcs3/rpcs3qt/localized_emu.h +++ b/rpcs3/rpcs3qt/localized_emu.h @@ -265,6 +265,7 @@ private: case localized_string_id::HOME_MENU_SETTINGS_OVERLAYS_SHOW_PRESSURE_INTENSITY_TOGGLE_HINT: return tr("Show Pressure Intensity Toggle Hint", "Overlays"); case localized_string_id::HOME_MENU_SETTINGS_OVERLAYS_SHOW_ANALOG_LIMITER_TOGGLE_HINT: return tr( "Show Analog Limiter Toggle Hint", "Overlays"); case localized_string_id::HOME_MENU_SETTINGS_OVERLAYS_SHOW_MOUSE_AND_KB_TOGGLE_HINT: return tr("Show Mouse And Keyboard Toggle Hint", "Overlays"); + case localized_string_id::HOME_MENU_SETTINGS_OVERLAYS_RECORD_WITH_OVERLAYS: return tr("Record With Overlays", "Overlays"); case localized_string_id::HOME_MENU_SETTINGS_PERFORMANCE_OVERLAY: return tr("Performance Overlay"); case localized_string_id::HOME_MENU_SETTINGS_PERFORMANCE_OVERLAY_ENABLE: return tr("Enable Performance Overlay", "Performance Overlay"); case localized_string_id::HOME_MENU_SETTINGS_PERFORMANCE_OVERLAY_ENABLE_FRAMERATE_GRAPH: return tr("Enable Framerate Graph", "Performance Overlay"); diff --git a/rpcs3/rpcs3qt/settings_dialog.cpp b/rpcs3/rpcs3qt/settings_dialog.cpp index 7ad9023f4e..c9e7f52f5c 100644 --- a/rpcs3/rpcs3qt/settings_dialog.cpp +++ b/rpcs3/rpcs3qt/settings_dialog.cpp @@ -1862,6 +1862,9 @@ settings_dialog::settings_dialog(std::shared_ptr gui_settings, std m_emu_settings->EnhanceCheckBox(ui->showMouseAndKeyboardToggleHint, emu_settings_type::ShowMouseAndKeyboardToggleHint); SubscribeTooltip(ui->showMouseAndKeyboardToggleHint, tooltips.settings.show_mouse_and_keyboard_toggle_hint); + m_emu_settings->EnhanceCheckBox(ui->recordWithOverlays, emu_settings_type::RecordWithOverlays); + SubscribeTooltip(ui->recordWithOverlays, tooltips.settings.record_with_overlays); + m_emu_settings->EnhanceCheckBox(ui->pauseDuringHomeMenu, emu_settings_type::PauseDuringHomeMenu); SubscribeTooltip(ui->pauseDuringHomeMenu, tooltips.settings.pause_during_home_menu); diff --git a/rpcs3/rpcs3qt/settings_dialog.ui b/rpcs3/rpcs3qt/settings_dialog.ui index 7a3d4951a8..48614e1f7d 100644 --- a/rpcs3/rpcs3qt/settings_dialog.ui +++ b/rpcs3/rpcs3qt/settings_dialog.ui @@ -3022,6 +3022,13 @@ + + + + Record with overlays + + + diff --git a/rpcs3/rpcs3qt/tooltips.h b/rpcs3/rpcs3qt/tooltips.h index 41cfc1e6d8..fd2998291d 100644 --- a/rpcs3/rpcs3qt/tooltips.h +++ b/rpcs3/rpcs3qt/tooltips.h @@ -150,6 +150,7 @@ public: const QString show_analog_limiter_toggle_hint = tr("Shows analog limiter toggle hint using the native overlay."); const QString show_mouse_and_keyboard_toggle_hint = tr("Shows mouse and keyboard toggle hint using the native overlay."); const QString use_native_interface = tr("Enables use of native HUD within the game window that can interact with game controllers.\nWhen disabled, regular Qt dialogs are used instead.\nCurrently, the on-screen keyboard only supports the English key layout."); + const QString record_with_overlays = tr("Enables recording with overlays.\nThis also affects screenshots."); const QString pause_during_home_menu = tr("When enabled, opening the home menu will also pause emulation.\nWhile most games pause themselves while the home menu is shown, some do not.\nIn that case it can be helpful to pause the emulation whenever the home menu is open."); const QString perf_overlay_enabled = tr("Enables or disables the performance overlay."); diff --git a/rpcs3/util/video_provider.cpp b/rpcs3/util/video_provider.cpp index 82f133b91e..e3ce23f9ae 100644 --- a/rpcs3/util/video_provider.cpp +++ b/rpcs3/util/video_provider.cpp @@ -122,7 +122,7 @@ namespace utils return pts > m_last_video_pts_incoming; } - void video_provider::present_frame(std::vector& data, u32 pitch, u32 width, u32 height, bool is_bgra) + void video_provider::present_frame(std::vector&& data, u32 pitch, u32 width, u32 height, bool is_bgra) { if (!m_active) { diff --git a/rpcs3/util/video_provider.h b/rpcs3/util/video_provider.h index e21b5185ee..bff3f92b19 100644 --- a/rpcs3/util/video_provider.h +++ b/rpcs3/util/video_provider.h @@ -21,7 +21,7 @@ namespace utils void set_pause_time_us(usz pause_time_us); bool can_consume_frame(); - void present_frame(std::vector& data, u32 pitch, u32 width, u32 height, bool is_bgra); + void present_frame(std::vector&& data, u32 pitch, u32 width, u32 height, bool is_bgra); void present_samples(const u8* buf, u32 sample_count, u16 channels);