forked from eden-emu/eden
		
	service: am: Implement ISelfController::SaveCurrentScreenshot
This commit is contained in:
		
							parent
							
								
									43be2bfe33
								
							
						
					
					
						commit
						f26dddf3b5
					
				
					 6 changed files with 82 additions and 17 deletions
				
			
		|  | @ -31,6 +31,7 @@ | ||||||
| #include "core/hle/service/apm/apm_controller.h" | #include "core/hle/service/apm/apm_controller.h" | ||||||
| #include "core/hle/service/apm/apm_interface.h" | #include "core/hle/service/apm/apm_interface.h" | ||||||
| #include "core/hle/service/bcat/backend/backend.h" | #include "core/hle/service/bcat/backend/backend.h" | ||||||
|  | #include "core/hle/service/caps/caps_su.h" | ||||||
| #include "core/hle/service/caps/caps_types.h" | #include "core/hle/service/caps/caps_types.h" | ||||||
| #include "core/hle/service/filesystem/filesystem.h" | #include "core/hle/service/filesystem/filesystem.h" | ||||||
| #include "core/hle/service/ipc_helpers.h" | #include "core/hle/service/ipc_helpers.h" | ||||||
|  | @ -702,9 +703,17 @@ void ISelfController::SetAlbumImageTakenNotificationEnabled(HLERequestContext& c | ||||||
| void ISelfController::SaveCurrentScreenshot(HLERequestContext& ctx) { | void ISelfController::SaveCurrentScreenshot(HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp{ctx}; |     IPC::RequestParser rp{ctx}; | ||||||
| 
 | 
 | ||||||
|     const auto album_report_option = rp.PopEnum<Capture::AlbumReportOption>(); |     const auto report_option = rp.PopEnum<Capture::AlbumReportOption>(); | ||||||
| 
 | 
 | ||||||
|     LOG_WARNING(Service_AM, "(STUBBED) called. album_report_option={}", album_report_option); |     LOG_INFO(Service_AM, "called, report_option={}", report_option); | ||||||
|  | 
 | ||||||
|  |     const auto screenshot_service = | ||||||
|  |         system.ServiceManager().GetService<Service::Capture::IScreenShotApplicationService>( | ||||||
|  |             "caps:su"); | ||||||
|  | 
 | ||||||
|  |     if (screenshot_service) { | ||||||
|  |         screenshot_service->CaptureAndSaveScreenshot(report_option); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|     IPC::ResponseBuilder rb{ctx, 2}; |     IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|     rb.Push(ResultSuccess); |     rb.Push(ResultSuccess); | ||||||
|  |  | ||||||
|  | @ -228,12 +228,14 @@ Result AlbumManager::LoadAlbumScreenShotThumbnail( | ||||||
| 
 | 
 | ||||||
| Result AlbumManager::SaveScreenShot(ApplicationAlbumEntry& out_entry, | Result AlbumManager::SaveScreenShot(ApplicationAlbumEntry& out_entry, | ||||||
|                                     const ScreenShotAttribute& attribute, |                                     const ScreenShotAttribute& attribute, | ||||||
|                                     std::span<const u8> image_data, u64 aruid) { |                                     AlbumReportOption report_option, std::span<const u8> image_data, | ||||||
|     return SaveScreenShot(out_entry, attribute, {}, image_data, aruid); |                                     u64 aruid) { | ||||||
|  |     return SaveScreenShot(out_entry, attribute, report_option, {}, image_data, aruid); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Result AlbumManager::SaveScreenShot(ApplicationAlbumEntry& out_entry, | Result AlbumManager::SaveScreenShot(ApplicationAlbumEntry& out_entry, | ||||||
|                                     const ScreenShotAttribute& attribute, |                                     const ScreenShotAttribute& attribute, | ||||||
|  |                                     AlbumReportOption report_option, | ||||||
|                                     const ApplicationData& app_data, std::span<const u8> image_data, |                                     const ApplicationData& app_data, std::span<const u8> image_data, | ||||||
|                                     u64 aruid) { |                                     u64 aruid) { | ||||||
|     const u64 title_id = system.GetApplicationProcessProgramID(); |     const u64 title_id = system.GetApplicationProcessProgramID(); | ||||||
|  | @ -407,10 +409,14 @@ Result AlbumManager::LoadImage(std::span<u8> out_image, const std::filesystem::p | ||||||
|     return ResultSuccess; |     return ResultSuccess; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void PNGToMemory(void* context, void* png, int len) { | void AlbumManager::FlipVerticallyOnWrite(bool flip) { | ||||||
|  |     stbi_flip_vertically_on_write(flip); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void PNGToMemory(void* context, void* data, int len) { | ||||||
|     std::vector<u8>* png_image = static_cast<std::vector<u8>*>(context); |     std::vector<u8>* png_image = static_cast<std::vector<u8>*>(context); | ||||||
|     png_image->reserve(len); |     unsigned char* png = static_cast<unsigned char*>(data); | ||||||
|     std::memcpy(png_image->data(), png, len); |     png_image->insert(png_image->end(), png, png + len); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| Result AlbumManager::SaveImage(ApplicationAlbumEntry& out_entry, std::span<const u8> image, | Result AlbumManager::SaveImage(ApplicationAlbumEntry& out_entry, std::span<const u8> image, | ||||||
|  |  | ||||||
|  | @ -59,14 +59,17 @@ public: | ||||||
|                                         const ScreenShotDecodeOption& decoder_options) const; |                                         const ScreenShotDecodeOption& decoder_options) const; | ||||||
| 
 | 
 | ||||||
|     Result SaveScreenShot(ApplicationAlbumEntry& out_entry, const ScreenShotAttribute& attribute, |     Result SaveScreenShot(ApplicationAlbumEntry& out_entry, const ScreenShotAttribute& attribute, | ||||||
|                           std::span<const u8> image_data, u64 aruid); |                           AlbumReportOption report_option, std::span<const u8> image_data, | ||||||
|     Result SaveScreenShot(ApplicationAlbumEntry& out_entry, const ScreenShotAttribute& attribute, |  | ||||||
|                           const ApplicationData& app_data, std::span<const u8> image_data, |  | ||||||
|                           u64 aruid); |                           u64 aruid); | ||||||
|  |     Result SaveScreenShot(ApplicationAlbumEntry& out_entry, const ScreenShotAttribute& attribute, | ||||||
|  |                           AlbumReportOption report_option, const ApplicationData& app_data, | ||||||
|  |                           std::span<const u8> image_data, u64 aruid); | ||||||
|     Result SaveEditedScreenShot(ApplicationAlbumEntry& out_entry, |     Result SaveEditedScreenShot(ApplicationAlbumEntry& out_entry, | ||||||
|                                 const ScreenShotAttribute& attribute, const AlbumFileId& file_id, |                                 const ScreenShotAttribute& attribute, const AlbumFileId& file_id, | ||||||
|                                 std::span<const u8> image_data); |                                 std::span<const u8> image_data); | ||||||
| 
 | 
 | ||||||
|  |     void FlipVerticallyOnWrite(bool flip); | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
|     static constexpr std::size_t NandAlbumFileLimit = 1000; |     static constexpr std::size_t NandAlbumFileLimit = 1000; | ||||||
|     static constexpr std::size_t SdAlbumFileLimit = 10000; |     static constexpr std::size_t SdAlbumFileLimit = 10000; | ||||||
|  |  | ||||||
|  | @ -34,7 +34,7 @@ void IScreenShotService::SaveScreenShotEx0(HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp{ctx}; |     IPC::RequestParser rp{ctx}; | ||||||
|     struct Parameters { |     struct Parameters { | ||||||
|         ScreenShotAttribute attribute{}; |         ScreenShotAttribute attribute{}; | ||||||
|         u32 report_option{}; |         AlbumReportOption report_option{}; | ||||||
|         INSERT_PADDING_BYTES(0x4); |         INSERT_PADDING_BYTES(0x4); | ||||||
|         u64 applet_resource_user_id{}; |         u64 applet_resource_user_id{}; | ||||||
|     }; |     }; | ||||||
|  | @ -49,13 +49,16 @@ void IScreenShotService::SaveScreenShotEx0(HLERequestContext& ctx) { | ||||||
|              parameters.applet_resource_user_id); |              parameters.applet_resource_user_id); | ||||||
| 
 | 
 | ||||||
|     ApplicationAlbumEntry entry{}; |     ApplicationAlbumEntry entry{}; | ||||||
|     const auto result = manager->SaveScreenShot(entry, parameters.attribute, image_data_buffer, |     manager->FlipVerticallyOnWrite(false); | ||||||
|                                                 parameters.applet_resource_user_id); |     const auto result = | ||||||
|  |         manager->SaveScreenShot(entry, parameters.attribute, parameters.report_option, | ||||||
|  |                                 image_data_buffer, parameters.applet_resource_user_id); | ||||||
| 
 | 
 | ||||||
|     IPC::ResponseBuilder rb{ctx, 10}; |     IPC::ResponseBuilder rb{ctx, 10}; | ||||||
|     rb.Push(result); |     rb.Push(result); | ||||||
|     rb.PushRaw(entry); |     rb.PushRaw(entry); | ||||||
| } | } | ||||||
|  | 
 | ||||||
| void IScreenShotService::SaveEditedScreenShotEx1(HLERequestContext& ctx) { | void IScreenShotService::SaveEditedScreenShotEx1(HLERequestContext& ctx) { | ||||||
|     IPC::RequestParser rp{ctx}; |     IPC::RequestParser rp{ctx}; | ||||||
|     struct Parameters { |     struct Parameters { | ||||||
|  | @ -83,6 +86,7 @@ void IScreenShotService::SaveEditedScreenShotEx1(HLERequestContext& ctx) { | ||||||
|              image_data_buffer.size(), thumbnail_image_data_buffer.size()); |              image_data_buffer.size(), thumbnail_image_data_buffer.size()); | ||||||
| 
 | 
 | ||||||
|     ApplicationAlbumEntry entry{}; |     ApplicationAlbumEntry entry{}; | ||||||
|  |     manager->FlipVerticallyOnWrite(false); | ||||||
|     const auto result = manager->SaveEditedScreenShot(entry, parameters.attribute, |     const auto result = manager->SaveEditedScreenShot(entry, parameters.attribute, | ||||||
|                                                       parameters.file_id, image_data_buffer); |                                                       parameters.file_id, image_data_buffer); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -2,10 +2,12 @@ | ||||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||||
| 
 | 
 | ||||||
| #include "common/logging/log.h" | #include "common/logging/log.h" | ||||||
|  | #include "core/core.h" | ||||||
| #include "core/hle/service/caps/caps_manager.h" | #include "core/hle/service/caps/caps_manager.h" | ||||||
| #include "core/hle/service/caps/caps_su.h" | #include "core/hle/service/caps/caps_su.h" | ||||||
| #include "core/hle/service/caps/caps_types.h" | #include "core/hle/service/caps/caps_types.h" | ||||||
| #include "core/hle/service/ipc_helpers.h" | #include "core/hle/service/ipc_helpers.h" | ||||||
|  | #include "video_core/renderer_base.h" | ||||||
| 
 | 
 | ||||||
| namespace Service::Capture { | namespace Service::Capture { | ||||||
| 
 | 
 | ||||||
|  | @ -58,8 +60,10 @@ void IScreenShotApplicationService::SaveScreenShotEx0(HLERequestContext& ctx) { | ||||||
|              parameters.applet_resource_user_id); |              parameters.applet_resource_user_id); | ||||||
| 
 | 
 | ||||||
|     ApplicationAlbumEntry entry{}; |     ApplicationAlbumEntry entry{}; | ||||||
|     const auto result = manager->SaveScreenShot(entry, parameters.attribute, image_data_buffer, |     manager->FlipVerticallyOnWrite(false); | ||||||
|                                                 parameters.applet_resource_user_id); |     const auto result = | ||||||
|  |         manager->SaveScreenShot(entry, parameters.attribute, parameters.report_option, | ||||||
|  |                                 image_data_buffer, parameters.applet_resource_user_id); | ||||||
| 
 | 
 | ||||||
|     IPC::ResponseBuilder rb{ctx, 10}; |     IPC::ResponseBuilder rb{ctx, 10}; | ||||||
|     rb.Push(result); |     rb.Push(result); | ||||||
|  | @ -88,13 +92,43 @@ void IScreenShotApplicationService::SaveScreenShotEx1(HLERequestContext& ctx) { | ||||||
|     ApplicationAlbumEntry entry{}; |     ApplicationAlbumEntry entry{}; | ||||||
|     ApplicationData app_data{}; |     ApplicationData app_data{}; | ||||||
|     std::memcpy(&app_data, app_data_buffer.data(), sizeof(ApplicationData)); |     std::memcpy(&app_data, app_data_buffer.data(), sizeof(ApplicationData)); | ||||||
|  |     manager->FlipVerticallyOnWrite(false); | ||||||
|     const auto result = |     const auto result = | ||||||
|         manager->SaveScreenShot(entry, parameters.attribute, app_data, image_data_buffer, |         manager->SaveScreenShot(entry, parameters.attribute, parameters.report_option, app_data, | ||||||
|                                 parameters.applet_resource_user_id); |                                 image_data_buffer, parameters.applet_resource_user_id); | ||||||
| 
 | 
 | ||||||
|     IPC::ResponseBuilder rb{ctx, 10}; |     IPC::ResponseBuilder rb{ctx, 10}; | ||||||
|     rb.Push(result); |     rb.Push(result); | ||||||
|     rb.PushRaw(entry); |     rb.PushRaw(entry); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void IScreenShotApplicationService::CaptureAndSaveScreenshot(AlbumReportOption report_option) { | ||||||
|  |     auto& renderer = system.Renderer(); | ||||||
|  |     Layout::FramebufferLayout layout = | ||||||
|  |         Layout::DefaultFrameLayout(screenshot_width, screenshot_height); | ||||||
|  | 
 | ||||||
|  |     const Capture::ScreenShotAttribute attribute{ | ||||||
|  |         .unknown_0{}, | ||||||
|  |         .orientation = Capture::AlbumImageOrientation::None, | ||||||
|  |         .unknown_1{}, | ||||||
|  |         .unknown_2{}, | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     renderer.RequestScreenshot( | ||||||
|  |         image_data.data(), | ||||||
|  |         [attribute, report_option, this](bool invert_y) { | ||||||
|  |             // Convert from BGRA to RGBA
 | ||||||
|  |             for (std::size_t i = 0; i < image_data.size(); i += bytes_per_pixel) { | ||||||
|  |                 const u8 temp = image_data[i]; | ||||||
|  |                 image_data[i] = image_data[i + 2]; | ||||||
|  |                 image_data[i + 2] = temp; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             Capture::ApplicationAlbumEntry entry{}; | ||||||
|  |             manager->FlipVerticallyOnWrite(invert_y); | ||||||
|  |             manager->SaveScreenShot(entry, attribute, report_option, image_data, {}); | ||||||
|  |         }, | ||||||
|  |         layout); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } // namespace Service::Capture
 | } // namespace Service::Capture
 | ||||||
|  |  | ||||||
|  | @ -10,6 +10,7 @@ class System; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| namespace Service::Capture { | namespace Service::Capture { | ||||||
|  | enum class AlbumReportOption : s32; | ||||||
| class AlbumManager; | class AlbumManager; | ||||||
| 
 | 
 | ||||||
| class IScreenShotApplicationService final : public ServiceFramework<IScreenShotApplicationService> { | class IScreenShotApplicationService final : public ServiceFramework<IScreenShotApplicationService> { | ||||||
|  | @ -18,11 +19,19 @@ public: | ||||||
|                                            std::shared_ptr<AlbumManager> album_manager); |                                            std::shared_ptr<AlbumManager> album_manager); | ||||||
|     ~IScreenShotApplicationService() override; |     ~IScreenShotApplicationService() override; | ||||||
| 
 | 
 | ||||||
|  |     void CaptureAndSaveScreenshot(AlbumReportOption report_option); | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
|  |     static constexpr std::size_t screenshot_width = 1280; | ||||||
|  |     static constexpr std::size_t screenshot_height = 720; | ||||||
|  |     static constexpr std::size_t bytes_per_pixel = 4; | ||||||
|  | 
 | ||||||
|     void SetShimLibraryVersion(HLERequestContext& ctx); |     void SetShimLibraryVersion(HLERequestContext& ctx); | ||||||
|     void SaveScreenShotEx0(HLERequestContext& ctx); |     void SaveScreenShotEx0(HLERequestContext& ctx); | ||||||
|     void SaveScreenShotEx1(HLERequestContext& ctx); |     void SaveScreenShotEx1(HLERequestContext& ctx); | ||||||
| 
 | 
 | ||||||
|  |     std::array<u8, screenshot_width * screenshot_height * bytes_per_pixel> image_data; | ||||||
|  | 
 | ||||||
|     std::shared_ptr<AlbumManager> manager; |     std::shared_ptr<AlbumManager> manager; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Narr the Reg
						Narr the Reg