mirror of
				https://git.tardis.systems/mirrors/yuzu
				synced 2025-10-30 18:24:15 +01:00 
			
		
		
		
	vi: split into implementation files
This commit is contained in:
		
							parent
							
								
									db871677b0
								
							
						
					
					
						commit
						2e8c0e9247
					
				| @ -959,15 +959,24 @@ add_library(core STATIC | ||||
|     hle/service/vi/display/vi_display.h | ||||
|     hle/service/vi/layer/vi_layer.cpp | ||||
|     hle/service/vi/layer/vi_layer.h | ||||
|     hle/service/vi/application_display_service.cpp | ||||
|     hle/service/vi/application_display_service.h | ||||
|     hle/service/vi/application_root_service.cpp | ||||
|     hle/service/vi/application_root_service.h | ||||
|     hle/service/vi/hos_binder_driver.cpp | ||||
|     hle/service/vi/hos_binder_driver.h | ||||
|     hle/service/vi/manager_display_service.cpp | ||||
|     hle/service/vi/manager_display_service.h | ||||
|     hle/service/vi/manager_root_service.cpp | ||||
|     hle/service/vi/manager_root_service.h | ||||
|     hle/service/vi/system_display_service.cpp | ||||
|     hle/service/vi/system_display_service.h | ||||
|     hle/service/vi/system_root_service.cpp | ||||
|     hle/service/vi/system_root_service.h | ||||
|     hle/service/vi/vi_results.h | ||||
|     hle/service/vi/vi_types.h | ||||
|     hle/service/vi/vi.cpp | ||||
|     hle/service/vi/vi.h | ||||
|     hle/service/vi/vi_m.cpp | ||||
|     hle/service/vi/vi_m.h | ||||
|     hle/service/vi/vi_s.cpp | ||||
|     hle/service/vi/vi_s.h | ||||
|     hle/service/vi/vi_types.h | ||||
|     hle/service/vi/vi_u.cpp | ||||
|     hle/service/vi/vi_u.h | ||||
|     internal_network/network.cpp | ||||
|     internal_network/network.h | ||||
|     internal_network/network_interface.cpp | ||||
|  | ||||
							
								
								
									
										419
									
								
								src/core/hle/service/vi/application_display_service.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										419
									
								
								src/core/hle/service/vi/application_display_service.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,419 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #include "common/string_util.h" | ||||
| #include "core/hle/service/ipc_helpers.h" | ||||
| #include "core/hle/service/nvnflinger/nvnflinger.h" | ||||
| #include "core/hle/service/nvnflinger/parcel.h" | ||||
| #include "core/hle/service/vi/application_display_service.h" | ||||
| #include "core/hle/service/vi/hos_binder_driver.h" | ||||
| #include "core/hle/service/vi/manager_display_service.h" | ||||
| #include "core/hle/service/vi/system_display_service.h" | ||||
| #include "core/hle/service/vi/vi_results.h" | ||||
| 
 | ||||
| namespace Service::VI { | ||||
| 
 | ||||
| IApplicationDisplayService::IApplicationDisplayService( | ||||
|     Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_, | ||||
|     Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_) | ||||
|     : ServiceFramework{system_, "IApplicationDisplayService"}, nvnflinger{nvnflinger_}, | ||||
|       hos_binder_driver_server{hos_binder_driver_server_} { | ||||
| 
 | ||||
|     static const FunctionInfo functions[] = { | ||||
|         {100, &IApplicationDisplayService::GetRelayService, "GetRelayService"}, | ||||
|         {101, &IApplicationDisplayService::GetSystemDisplayService, "GetSystemDisplayService"}, | ||||
|         {102, &IApplicationDisplayService::GetManagerDisplayService, "GetManagerDisplayService"}, | ||||
|         {103, &IApplicationDisplayService::GetIndirectDisplayTransactionService, | ||||
|          "GetIndirectDisplayTransactionService"}, | ||||
|         {1000, &IApplicationDisplayService::ListDisplays, "ListDisplays"}, | ||||
|         {1010, &IApplicationDisplayService::OpenDisplay, "OpenDisplay"}, | ||||
|         {1011, &IApplicationDisplayService::OpenDefaultDisplay, "OpenDefaultDisplay"}, | ||||
|         {1020, &IApplicationDisplayService::CloseDisplay, "CloseDisplay"}, | ||||
|         {1101, &IApplicationDisplayService::SetDisplayEnabled, "SetDisplayEnabled"}, | ||||
|         {1102, &IApplicationDisplayService::GetDisplayResolution, "GetDisplayResolution"}, | ||||
|         {2020, &IApplicationDisplayService::OpenLayer, "OpenLayer"}, | ||||
|         {2021, &IApplicationDisplayService::CloseLayer, "CloseLayer"}, | ||||
|         {2030, &IApplicationDisplayService::CreateStrayLayer, "CreateStrayLayer"}, | ||||
|         {2031, &IApplicationDisplayService::DestroyStrayLayer, "DestroyStrayLayer"}, | ||||
|         {2101, &IApplicationDisplayService::SetLayerScalingMode, "SetLayerScalingMode"}, | ||||
|         {2102, &IApplicationDisplayService::ConvertScalingMode, "ConvertScalingMode"}, | ||||
|         {2450, &IApplicationDisplayService::GetIndirectLayerImageMap, "GetIndirectLayerImageMap"}, | ||||
|         {2451, nullptr, "GetIndirectLayerImageCropMap"}, | ||||
|         {2460, &IApplicationDisplayService::GetIndirectLayerImageRequiredMemoryInfo, | ||||
|          "GetIndirectLayerImageRequiredMemoryInfo"}, | ||||
|         {5202, &IApplicationDisplayService::GetDisplayVsyncEvent, "GetDisplayVsyncEvent"}, | ||||
|         {5203, nullptr, "GetDisplayVsyncEventForDebug"}, | ||||
|     }; | ||||
|     RegisterHandlers(functions); | ||||
| } | ||||
| 
 | ||||
| IApplicationDisplayService::~IApplicationDisplayService() { | ||||
|     for (const auto layer_id : stray_layer_ids) { | ||||
|         nvnflinger.DestroyLayer(layer_id); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void IApplicationDisplayService::GetRelayService(HLERequestContext& ctx) { | ||||
|     LOG_WARNING(Service_VI, "(STUBBED) called"); | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||||
|     rb.Push(ResultSuccess); | ||||
|     rb.PushIpcInterface<IHOSBinderDriver>(system, hos_binder_driver_server); | ||||
| } | ||||
| 
 | ||||
| void IApplicationDisplayService::GetSystemDisplayService(HLERequestContext& ctx) { | ||||
|     LOG_WARNING(Service_VI, "(STUBBED) called"); | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||||
|     rb.Push(ResultSuccess); | ||||
|     rb.PushIpcInterface<ISystemDisplayService>(system, nvnflinger); | ||||
| } | ||||
| 
 | ||||
| void IApplicationDisplayService::GetManagerDisplayService(HLERequestContext& ctx) { | ||||
|     LOG_WARNING(Service_VI, "(STUBBED) called"); | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||||
|     rb.Push(ResultSuccess); | ||||
|     rb.PushIpcInterface<IManagerDisplayService>(system, nvnflinger); | ||||
| } | ||||
| 
 | ||||
| void IApplicationDisplayService::GetIndirectDisplayTransactionService(HLERequestContext& ctx) { | ||||
|     LOG_WARNING(Service_VI, "(STUBBED) called"); | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||||
|     rb.Push(ResultSuccess); | ||||
|     rb.PushIpcInterface<IHOSBinderDriver>(system, hos_binder_driver_server); | ||||
| } | ||||
| 
 | ||||
| void IApplicationDisplayService::OpenDisplay(HLERequestContext& ctx) { | ||||
|     LOG_WARNING(Service_VI, "(STUBBED) called"); | ||||
| 
 | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const auto name_buf = rp.PopRaw<std::array<char, 0x40>>(); | ||||
| 
 | ||||
|     OpenDisplayImpl(ctx, std::string_view{name_buf.data(), name_buf.size()}); | ||||
| } | ||||
| 
 | ||||
| void IApplicationDisplayService::OpenDefaultDisplay(HLERequestContext& ctx) { | ||||
|     LOG_DEBUG(Service_VI, "called"); | ||||
| 
 | ||||
|     OpenDisplayImpl(ctx, "Default"); | ||||
| } | ||||
| 
 | ||||
| void IApplicationDisplayService::OpenDisplayImpl(HLERequestContext& ctx, std::string_view name) { | ||||
|     const auto trim_pos = name.find('\0'); | ||||
| 
 | ||||
|     if (trim_pos != std::string_view::npos) { | ||||
|         name.remove_suffix(name.size() - trim_pos); | ||||
|     } | ||||
| 
 | ||||
|     ASSERT_MSG(name == "Default", "Non-default displays aren't supported yet"); | ||||
| 
 | ||||
|     const auto display_id = nvnflinger.OpenDisplay(name); | ||||
|     if (!display_id) { | ||||
|         LOG_ERROR(Service_VI, "Display not found! display_name={}", name); | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ResultNotFound); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 4}; | ||||
|     rb.Push(ResultSuccess); | ||||
|     rb.Push<u64>(*display_id); | ||||
| } | ||||
| 
 | ||||
| void IApplicationDisplayService::CloseDisplay(HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const u64 display_id = rp.Pop<u64>(); | ||||
| 
 | ||||
|     const Result rc = nvnflinger.CloseDisplay(display_id) ? ResultSuccess : ResultUnknown; | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 2}; | ||||
|     rb.Push(rc); | ||||
| } | ||||
| 
 | ||||
| // This literally does nothing internally in the actual service itself,
 | ||||
| // and just returns a successful result code regardless of the input.
 | ||||
| void IApplicationDisplayService::SetDisplayEnabled(HLERequestContext& ctx) { | ||||
|     LOG_DEBUG(Service_VI, "called."); | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 2}; | ||||
|     rb.Push(ResultSuccess); | ||||
| } | ||||
| 
 | ||||
| void IApplicationDisplayService::GetDisplayResolution(HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const u64 display_id = rp.Pop<u64>(); | ||||
| 
 | ||||
|     LOG_DEBUG(Service_VI, "called. display_id=0x{:016X}", display_id); | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 6}; | ||||
|     rb.Push(ResultSuccess); | ||||
| 
 | ||||
|     // This only returns the fixed values of 1280x720 and makes no distinguishing
 | ||||
|     // between docked and undocked dimensions. We take the liberty of applying
 | ||||
|     // the resolution scaling factor here.
 | ||||
|     rb.Push(static_cast<u64>(DisplayResolution::UndockedWidth)); | ||||
|     rb.Push(static_cast<u64>(DisplayResolution::UndockedHeight)); | ||||
| } | ||||
| 
 | ||||
| void IApplicationDisplayService::SetLayerScalingMode(HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const auto scaling_mode = rp.PopEnum<NintendoScaleMode>(); | ||||
|     const u64 unknown = rp.Pop<u64>(); | ||||
| 
 | ||||
|     LOG_DEBUG(Service_VI, "called. scaling_mode=0x{:08X}, unknown=0x{:016X}", scaling_mode, | ||||
|               unknown); | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 2}; | ||||
| 
 | ||||
|     if (scaling_mode > NintendoScaleMode::PreserveAspectRatio) { | ||||
|         LOG_ERROR(Service_VI, "Invalid scaling mode provided."); | ||||
|         rb.Push(ResultOperationFailed); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if (scaling_mode != NintendoScaleMode::ScaleToWindow && | ||||
|         scaling_mode != NintendoScaleMode::PreserveAspectRatio) { | ||||
|         LOG_ERROR(Service_VI, "Unsupported scaling mode supplied."); | ||||
|         rb.Push(ResultNotSupported); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     rb.Push(ResultSuccess); | ||||
| } | ||||
| 
 | ||||
| void IApplicationDisplayService::ListDisplays(HLERequestContext& ctx) { | ||||
|     LOG_WARNING(Service_VI, "(STUBBED) called"); | ||||
| 
 | ||||
|     const DisplayInfo display_info; | ||||
|     ctx.WriteBuffer(&display_info, sizeof(DisplayInfo)); | ||||
|     IPC::ResponseBuilder rb{ctx, 4}; | ||||
|     rb.Push(ResultSuccess); | ||||
|     rb.Push<u64>(1); | ||||
| } | ||||
| 
 | ||||
| void IApplicationDisplayService::OpenLayer(HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const auto name_buf = rp.PopRaw<std::array<u8, 0x40>>(); | ||||
|     const std::string display_name(Common::StringFromBuffer(name_buf)); | ||||
| 
 | ||||
|     const u64 layer_id = rp.Pop<u64>(); | ||||
|     const u64 aruid = rp.Pop<u64>(); | ||||
| 
 | ||||
|     LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}, aruid=0x{:016X}", layer_id, aruid); | ||||
| 
 | ||||
|     const auto display_id = nvnflinger.OpenDisplay(display_name); | ||||
|     if (!display_id) { | ||||
|         LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id); | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ResultNotFound); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     const auto buffer_queue_id = nvnflinger.FindBufferQueueId(*display_id, layer_id); | ||||
|     if (!buffer_queue_id) { | ||||
|         LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id); | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ResultNotFound); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     if (!nvnflinger.OpenLayer(layer_id)) { | ||||
|         LOG_WARNING(Service_VI, "Tried to open layer which was already open"); | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ResultOperationFailed); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     android::OutputParcel parcel; | ||||
|     parcel.WriteInterface(NativeWindow{*buffer_queue_id}); | ||||
| 
 | ||||
|     const auto buffer_size = ctx.WriteBuffer(parcel.Serialize()); | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 4}; | ||||
|     rb.Push(ResultSuccess); | ||||
|     rb.Push<u64>(buffer_size); | ||||
| } | ||||
| 
 | ||||
| void IApplicationDisplayService::CloseLayer(HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const auto layer_id{rp.Pop<u64>()}; | ||||
| 
 | ||||
|     LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}", layer_id); | ||||
| 
 | ||||
|     if (!nvnflinger.CloseLayer(layer_id)) { | ||||
|         LOG_WARNING(Service_VI, "Tried to close layer which was not open"); | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ResultOperationFailed); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 2}; | ||||
|     rb.Push(ResultSuccess); | ||||
| } | ||||
| 
 | ||||
| void IApplicationDisplayService::CreateStrayLayer(HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const u32 flags = rp.Pop<u32>(); | ||||
|     rp.Pop<u32>(); // padding
 | ||||
|     const u64 display_id = rp.Pop<u64>(); | ||||
| 
 | ||||
|     LOG_DEBUG(Service_VI, "called. flags=0x{:08X}, display_id=0x{:016X}", flags, display_id); | ||||
| 
 | ||||
|     // TODO(Subv): What's the difference between a Stray and a Managed layer?
 | ||||
| 
 | ||||
|     const auto layer_id = nvnflinger.CreateLayer(display_id); | ||||
|     if (!layer_id) { | ||||
|         LOG_ERROR(Service_VI, "Layer not found! display_id={}", display_id); | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ResultNotFound); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     stray_layer_ids.push_back(*layer_id); | ||||
|     const auto buffer_queue_id = nvnflinger.FindBufferQueueId(display_id, *layer_id); | ||||
|     if (!buffer_queue_id) { | ||||
|         LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id); | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ResultNotFound); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     android::OutputParcel parcel; | ||||
|     parcel.WriteInterface(NativeWindow{*buffer_queue_id}); | ||||
| 
 | ||||
|     const auto buffer_size = ctx.WriteBuffer(parcel.Serialize()); | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 6}; | ||||
|     rb.Push(ResultSuccess); | ||||
|     rb.Push(*layer_id); | ||||
|     rb.Push<u64>(buffer_size); | ||||
| } | ||||
| 
 | ||||
| void IApplicationDisplayService::DestroyStrayLayer(HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const u64 layer_id = rp.Pop<u64>(); | ||||
| 
 | ||||
|     LOG_WARNING(Service_VI, "(STUBBED) called. layer_id=0x{:016X}", layer_id); | ||||
|     nvnflinger.DestroyLayer(layer_id); | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 2}; | ||||
|     rb.Push(ResultSuccess); | ||||
| } | ||||
| 
 | ||||
| void IApplicationDisplayService::GetDisplayVsyncEvent(HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const u64 display_id = rp.Pop<u64>(); | ||||
| 
 | ||||
|     LOG_DEBUG(Service_VI, "called. display_id={}", display_id); | ||||
| 
 | ||||
|     Kernel::KReadableEvent* vsync_event{}; | ||||
|     const auto result = nvnflinger.FindVsyncEvent(&vsync_event, display_id); | ||||
|     if (result != ResultSuccess) { | ||||
|         if (result == ResultNotFound) { | ||||
|             LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id); | ||||
|         } | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(result); | ||||
|         return; | ||||
|     } | ||||
|     if (vsync_event_fetched) { | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(VI::ResultPermissionDenied); | ||||
|         return; | ||||
|     } | ||||
|     vsync_event_fetched = true; | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 2, 1}; | ||||
|     rb.Push(ResultSuccess); | ||||
|     rb.PushCopyObjects(vsync_event); | ||||
| } | ||||
| 
 | ||||
| void IApplicationDisplayService::ConvertScalingMode(HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const auto mode = rp.PopEnum<NintendoScaleMode>(); | ||||
|     LOG_DEBUG(Service_VI, "called mode={}", mode); | ||||
| 
 | ||||
|     ConvertedScaleMode converted_mode{}; | ||||
|     const auto result = ConvertScalingModeImpl(&converted_mode, mode); | ||||
| 
 | ||||
|     if (result == ResultSuccess) { | ||||
|         IPC::ResponseBuilder rb{ctx, 4}; | ||||
|         rb.Push(ResultSuccess); | ||||
|         rb.PushEnum(converted_mode); | ||||
|     } else { | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(result); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void IApplicationDisplayService::GetIndirectLayerImageMap(HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const auto width = rp.Pop<s64>(); | ||||
|     const auto height = rp.Pop<s64>(); | ||||
|     const auto indirect_layer_consumer_handle = rp.Pop<u64>(); | ||||
|     const auto applet_resource_user_id = rp.Pop<u64>(); | ||||
| 
 | ||||
|     LOG_WARNING(Service_VI, | ||||
|                 "(STUBBED) called, width={}, height={}, indirect_layer_consumer_handle={}, " | ||||
|                 "applet_resource_user_id={}", | ||||
|                 width, height, indirect_layer_consumer_handle, applet_resource_user_id); | ||||
| 
 | ||||
|     std::vector<u8> out_buffer(0x46); | ||||
|     ctx.WriteBuffer(out_buffer); | ||||
| 
 | ||||
|     // TODO: Figure out what these are
 | ||||
| 
 | ||||
|     constexpr s64 unknown_result_1 = 0; | ||||
|     constexpr s64 unknown_result_2 = 0; | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 6}; | ||||
|     rb.Push(unknown_result_1); | ||||
|     rb.Push(unknown_result_2); | ||||
|     rb.Push(ResultSuccess); | ||||
| } | ||||
| 
 | ||||
| void IApplicationDisplayService::GetIndirectLayerImageRequiredMemoryInfo(HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const auto width = rp.Pop<u64>(); | ||||
|     const auto height = rp.Pop<u64>(); | ||||
|     LOG_DEBUG(Service_VI, "called width={}, height={}", width, height); | ||||
| 
 | ||||
|     constexpr u64 base_size = 0x20000; | ||||
|     constexpr u64 alignment = 0x1000; | ||||
|     const auto texture_size = width * height * 4; | ||||
|     const auto out_size = (texture_size + base_size - 1) / base_size * base_size; | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 6}; | ||||
|     rb.Push(ResultSuccess); | ||||
|     rb.Push(out_size); | ||||
|     rb.Push(alignment); | ||||
| } | ||||
| 
 | ||||
| Result IApplicationDisplayService::ConvertScalingModeImpl(ConvertedScaleMode* out_scaling_mode, | ||||
|                                                           NintendoScaleMode mode) { | ||||
|     switch (mode) { | ||||
|     case NintendoScaleMode::None: | ||||
|         *out_scaling_mode = ConvertedScaleMode::None; | ||||
|         return ResultSuccess; | ||||
|     case NintendoScaleMode::Freeze: | ||||
|         *out_scaling_mode = ConvertedScaleMode::Freeze; | ||||
|         return ResultSuccess; | ||||
|     case NintendoScaleMode::ScaleToWindow: | ||||
|         *out_scaling_mode = ConvertedScaleMode::ScaleToWindow; | ||||
|         return ResultSuccess; | ||||
|     case NintendoScaleMode::ScaleAndCrop: | ||||
|         *out_scaling_mode = ConvertedScaleMode::ScaleAndCrop; | ||||
|         return ResultSuccess; | ||||
|     case NintendoScaleMode::PreserveAspectRatio: | ||||
|         *out_scaling_mode = ConvertedScaleMode::PreserveAspectRatio; | ||||
|         return ResultSuccess; | ||||
|     default: | ||||
|         LOG_ERROR(Service_VI, "Invalid scaling mode specified, mode={}", mode); | ||||
|         return ResultOperationFailed; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| } // namespace Service::VI
 | ||||
							
								
								
									
										48
									
								
								src/core/hle/service/vi/application_display_service.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								src/core/hle/service/vi/application_display_service.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,48 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #include "core/hle/service/service.h" | ||||
| #include "core/hle/service/vi/vi_types.h" | ||||
| 
 | ||||
| namespace Service::VI { | ||||
| 
 | ||||
| class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> { | ||||
| public: | ||||
|     IApplicationDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_, | ||||
|                                Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_); | ||||
|     ~IApplicationDisplayService() override; | ||||
| 
 | ||||
| private: | ||||
|     void GetRelayService(HLERequestContext& ctx); | ||||
|     void GetSystemDisplayService(HLERequestContext& ctx); | ||||
|     void GetManagerDisplayService(HLERequestContext& ctx); | ||||
|     void GetIndirectDisplayTransactionService(HLERequestContext& ctx); | ||||
|     void OpenDisplay(HLERequestContext& ctx); | ||||
|     void OpenDefaultDisplay(HLERequestContext& ctx); | ||||
|     void OpenDisplayImpl(HLERequestContext& ctx, std::string_view name); | ||||
|     void CloseDisplay(HLERequestContext& ctx); | ||||
|     void SetDisplayEnabled(HLERequestContext& ctx); | ||||
|     void GetDisplayResolution(HLERequestContext& ctx); | ||||
|     void SetLayerScalingMode(HLERequestContext& ctx); | ||||
|     void ListDisplays(HLERequestContext& ctx); | ||||
|     void OpenLayer(HLERequestContext& ctx); | ||||
|     void CloseLayer(HLERequestContext& ctx); | ||||
|     void CreateStrayLayer(HLERequestContext& ctx); | ||||
|     void DestroyStrayLayer(HLERequestContext& ctx); | ||||
|     void GetDisplayVsyncEvent(HLERequestContext& ctx); | ||||
|     void ConvertScalingMode(HLERequestContext& ctx); | ||||
|     void GetIndirectLayerImageMap(HLERequestContext& ctx); | ||||
|     void GetIndirectLayerImageRequiredMemoryInfo(HLERequestContext& ctx); | ||||
| 
 | ||||
| private: | ||||
|     static Result ConvertScalingModeImpl(ConvertedScaleMode* out_scaling_mode, | ||||
|                                          NintendoScaleMode mode); | ||||
| 
 | ||||
| private: | ||||
|     Nvnflinger::Nvnflinger& nvnflinger; | ||||
|     Nvnflinger::HosBinderDriverServer& hos_binder_driver_server; | ||||
|     std::vector<u64> stray_layer_ids; | ||||
|     bool vsync_event_fetched{false}; | ||||
| }; | ||||
| 
 | ||||
| } // namespace Service::VI
 | ||||
| @ -1,27 +1,27 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #include "common/logging/log.h" | ||||
| #include "core/hle/service/vi/application_root_service.h" | ||||
| #include "core/hle/service/vi/vi.h" | ||||
| #include "core/hle/service/vi/vi_types.h" | ||||
| #include "core/hle/service/vi/vi_u.h" | ||||
| 
 | ||||
| namespace Service::VI { | ||||
| 
 | ||||
| VI_U::VI_U(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, | ||||
| IApplicationRootService::IApplicationRootService( | ||||
|     Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, | ||||
|     Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_) | ||||
|     : ServiceFramework{system_, "vi:u"}, nv_flinger{nv_flinger_}, | ||||
|       hos_binder_driver_server{hos_binder_driver_server_} { | ||||
|     static const FunctionInfo functions[] = { | ||||
|         {0, &VI_U::GetDisplayService, "GetDisplayService"}, | ||||
|         {0, &IApplicationRootService::GetDisplayService, "GetDisplayService"}, | ||||
|         {1, nullptr, "GetDisplayServiceWithProxyNameExchange"}, | ||||
|     }; | ||||
|     RegisterHandlers(functions); | ||||
| } | ||||
| 
 | ||||
| VI_U::~VI_U() = default; | ||||
| IApplicationRootService::~IApplicationRootService() = default; | ||||
| 
 | ||||
| void VI_U::GetDisplayService(HLERequestContext& ctx) { | ||||
| void IApplicationRootService::GetDisplayService(HLERequestContext& ctx) { | ||||
|     LOG_DEBUG(Service_VI, "called"); | ||||
| 
 | ||||
|     detail::GetDisplayServiceImpl(ctx, system, nv_flinger, hos_binder_driver_server, | ||||
| @ -16,11 +16,11 @@ class Nvnflinger; | ||||
| 
 | ||||
| namespace Service::VI { | ||||
| 
 | ||||
| class VI_S final : public ServiceFramework<VI_S> { | ||||
| class IApplicationRootService final : public ServiceFramework<IApplicationRootService> { | ||||
| public: | ||||
|     explicit VI_S(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, | ||||
|     explicit IApplicationRootService(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, | ||||
|                                      Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_); | ||||
|     ~VI_S() override; | ||||
|     ~IApplicationRootService() override; | ||||
| 
 | ||||
| private: | ||||
|     void GetDisplayService(HLERequestContext& ctx); | ||||
							
								
								
									
										64
									
								
								src/core/hle/service/vi/hos_binder_driver.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								src/core/hle/service/vi/hos_binder_driver.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,64 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #include "core/hle/service/ipc_helpers.h" | ||||
| #include "core/hle/service/nvnflinger/binder.h" | ||||
| #include "core/hle/service/nvnflinger/hos_binder_driver_server.h" | ||||
| #include "core/hle/service/vi/hos_binder_driver.h" | ||||
| 
 | ||||
| namespace Service::VI { | ||||
| 
 | ||||
| IHOSBinderDriver::IHOSBinderDriver(Core::System& system_, | ||||
|                                    Nvnflinger::HosBinderDriverServer& server_) | ||||
|     : ServiceFramework{system_, "IHOSBinderDriver"}, server(server_) { | ||||
|     static const FunctionInfo functions[] = { | ||||
|         {0, &IHOSBinderDriver::TransactParcel, "TransactParcel"}, | ||||
|         {1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"}, | ||||
|         {2, &IHOSBinderDriver::GetNativeHandle, "GetNativeHandle"}, | ||||
|         {3, &IHOSBinderDriver::TransactParcel, "TransactParcelAuto"}, | ||||
|     }; | ||||
|     RegisterHandlers(functions); | ||||
| } | ||||
| 
 | ||||
| IHOSBinderDriver::~IHOSBinderDriver() = default; | ||||
| 
 | ||||
| void IHOSBinderDriver::TransactParcel(HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const u32 id = rp.Pop<u32>(); | ||||
|     const auto transaction = static_cast<android::TransactionId>(rp.Pop<u32>()); | ||||
|     const u32 flags = rp.Pop<u32>(); | ||||
| 
 | ||||
|     LOG_DEBUG(Service_VI, "called. id=0x{:08X} transaction={:X}, flags=0x{:08X}", id, transaction, | ||||
|               flags); | ||||
| 
 | ||||
|     server.TryGetProducer(id)->Transact(ctx, transaction, flags); | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 2}; | ||||
|     rb.Push(ResultSuccess); | ||||
| } | ||||
| 
 | ||||
| void IHOSBinderDriver::AdjustRefcount(HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const u32 id = rp.Pop<u32>(); | ||||
|     const s32 addval = rp.PopRaw<s32>(); | ||||
|     const u32 type = rp.Pop<u32>(); | ||||
| 
 | ||||
|     LOG_WARNING(Service_VI, "(STUBBED) called id={}, addval={:08X}, type={:08X}", id, addval, type); | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 2}; | ||||
|     rb.Push(ResultSuccess); | ||||
| } | ||||
| 
 | ||||
| void IHOSBinderDriver::GetNativeHandle(HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const u32 id = rp.Pop<u32>(); | ||||
|     const u32 unknown = rp.Pop<u32>(); | ||||
| 
 | ||||
|     LOG_WARNING(Service_VI, "(STUBBED) called id={}, unknown={:08X}", id, unknown); | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 2, 1}; | ||||
|     rb.Push(ResultSuccess); | ||||
|     rb.PushCopyObjects(server.TryGetProducer(id)->GetNativeHandle()); | ||||
| } | ||||
| 
 | ||||
| } // namespace Service::VI
 | ||||
							
								
								
									
										22
									
								
								src/core/hle/service/vi/hos_binder_driver.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/core/hle/service/vi/hos_binder_driver.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,22 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #include "core/hle/service/service.h" | ||||
| 
 | ||||
| namespace Service::VI { | ||||
| 
 | ||||
| class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> { | ||||
| public: | ||||
|     explicit IHOSBinderDriver(Core::System& system_, Nvnflinger::HosBinderDriverServer& server_); | ||||
|     ~IHOSBinderDriver() override; | ||||
| 
 | ||||
| private: | ||||
|     void TransactParcel(HLERequestContext& ctx); | ||||
|     void AdjustRefcount(HLERequestContext& ctx); | ||||
|     void GetNativeHandle(HLERequestContext& ctx); | ||||
| 
 | ||||
| private: | ||||
|     Nvnflinger::HosBinderDriverServer& server; | ||||
| }; | ||||
| 
 | ||||
| } // namespace Service::VI
 | ||||
							
								
								
									
										164
									
								
								src/core/hle/service/vi/manager_display_service.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										164
									
								
								src/core/hle/service/vi/manager_display_service.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,164 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #include "core/hle/service/ipc_helpers.h" | ||||
| #include "core/hle/service/nvnflinger/nvnflinger.h" | ||||
| #include "core/hle/service/vi/manager_display_service.h" | ||||
| #include "core/hle/service/vi/vi_results.h" | ||||
| 
 | ||||
| namespace Service::VI { | ||||
| 
 | ||||
| IManagerDisplayService::IManagerDisplayService(Core::System& system_, | ||||
|                                                Nvnflinger::Nvnflinger& nvnflinger_) | ||||
|     : ServiceFramework{system_, "IManagerDisplayService"}, nvnflinger{nvnflinger_} { | ||||
|     // clang-format off
 | ||||
|     static const FunctionInfo functions[] = { | ||||
|         {200, nullptr, "AllocateProcessHeapBlock"}, | ||||
|         {201, nullptr, "FreeProcessHeapBlock"}, | ||||
|         {1020, &IManagerDisplayService::CloseDisplay, "CloseDisplay"}, | ||||
|         {1102, nullptr, "GetDisplayResolution"}, | ||||
|         {2010, &IManagerDisplayService::CreateManagedLayer, "CreateManagedLayer"}, | ||||
|         {2011, nullptr, "DestroyManagedLayer"}, | ||||
|         {2012, nullptr, "CreateStrayLayer"}, | ||||
|         {2050, nullptr, "CreateIndirectLayer"}, | ||||
|         {2051, nullptr, "DestroyIndirectLayer"}, | ||||
|         {2052, nullptr, "CreateIndirectProducerEndPoint"}, | ||||
|         {2053, nullptr, "DestroyIndirectProducerEndPoint"}, | ||||
|         {2054, nullptr, "CreateIndirectConsumerEndPoint"}, | ||||
|         {2055, nullptr, "DestroyIndirectConsumerEndPoint"}, | ||||
|         {2060, nullptr, "CreateWatermarkCompositor"}, | ||||
|         {2062, nullptr, "SetWatermarkText"}, | ||||
|         {2063, nullptr, "SetWatermarkLayerStacks"}, | ||||
|         {2300, nullptr, "AcquireLayerTexturePresentingEvent"}, | ||||
|         {2301, nullptr, "ReleaseLayerTexturePresentingEvent"}, | ||||
|         {2302, nullptr, "GetDisplayHotplugEvent"}, | ||||
|         {2303, nullptr, "GetDisplayModeChangedEvent"}, | ||||
|         {2402, nullptr, "GetDisplayHotplugState"}, | ||||
|         {2501, nullptr, "GetCompositorErrorInfo"}, | ||||
|         {2601, nullptr, "GetDisplayErrorEvent"}, | ||||
|         {2701, nullptr, "GetDisplayFatalErrorEvent"}, | ||||
|         {4201, nullptr, "SetDisplayAlpha"}, | ||||
|         {4203, nullptr, "SetDisplayLayerStack"}, | ||||
|         {4205, nullptr, "SetDisplayPowerState"}, | ||||
|         {4206, nullptr, "SetDefaultDisplay"}, | ||||
|         {4207, nullptr, "ResetDisplayPanel"}, | ||||
|         {4208, nullptr, "SetDisplayFatalErrorEnabled"}, | ||||
|         {4209, nullptr, "IsDisplayPanelOn"}, | ||||
|         {4300, nullptr, "GetInternalPanelId"}, | ||||
|         {6000, &IManagerDisplayService::AddToLayerStack, "AddToLayerStack"}, | ||||
|         {6001, nullptr, "RemoveFromLayerStack"}, | ||||
|         {6002, &IManagerDisplayService::SetLayerVisibility, "SetLayerVisibility"}, | ||||
|         {6003, nullptr, "SetLayerConfig"}, | ||||
|         {6004, nullptr, "AttachLayerPresentationTracer"}, | ||||
|         {6005, nullptr, "DetachLayerPresentationTracer"}, | ||||
|         {6006, nullptr, "StartLayerPresentationRecording"}, | ||||
|         {6007, nullptr, "StopLayerPresentationRecording"}, | ||||
|         {6008, nullptr, "StartLayerPresentationFenceWait"}, | ||||
|         {6009, nullptr, "StopLayerPresentationFenceWait"}, | ||||
|         {6010, nullptr, "GetLayerPresentationAllFencesExpiredEvent"}, | ||||
|         {6011, nullptr, "EnableLayerAutoClearTransitionBuffer"}, | ||||
|         {6012, nullptr, "DisableLayerAutoClearTransitionBuffer"}, | ||||
|         {6013, nullptr, "SetLayerOpacity"}, | ||||
|         {6014, nullptr, "AttachLayerWatermarkCompositor"}, | ||||
|         {6015, nullptr, "DetachLayerWatermarkCompositor"}, | ||||
|         {7000, nullptr, "SetContentVisibility"}, | ||||
|         {8000, nullptr, "SetConductorLayer"}, | ||||
|         {8001, nullptr, "SetTimestampTracking"}, | ||||
|         {8100, nullptr, "SetIndirectProducerFlipOffset"}, | ||||
|         {8200, nullptr, "CreateSharedBufferStaticStorage"}, | ||||
|         {8201, nullptr, "CreateSharedBufferTransferMemory"}, | ||||
|         {8202, nullptr, "DestroySharedBuffer"}, | ||||
|         {8203, nullptr, "BindSharedLowLevelLayerToManagedLayer"}, | ||||
|         {8204, nullptr, "BindSharedLowLevelLayerToIndirectLayer"}, | ||||
|         {8207, nullptr, "UnbindSharedLowLevelLayer"}, | ||||
|         {8208, nullptr, "ConnectSharedLowLevelLayerToSharedBuffer"}, | ||||
|         {8209, nullptr, "DisconnectSharedLowLevelLayerFromSharedBuffer"}, | ||||
|         {8210, nullptr, "CreateSharedLayer"}, | ||||
|         {8211, nullptr, "DestroySharedLayer"}, | ||||
|         {8216, nullptr, "AttachSharedLayerToLowLevelLayer"}, | ||||
|         {8217, nullptr, "ForceDetachSharedLayerFromLowLevelLayer"}, | ||||
|         {8218, nullptr, "StartDetachSharedLayerFromLowLevelLayer"}, | ||||
|         {8219, nullptr, "FinishDetachSharedLayerFromLowLevelLayer"}, | ||||
|         {8220, nullptr, "GetSharedLayerDetachReadyEvent"}, | ||||
|         {8221, nullptr, "GetSharedLowLevelLayerSynchronizedEvent"}, | ||||
|         {8222, nullptr, "CheckSharedLowLevelLayerSynchronized"}, | ||||
|         {8223, nullptr, "RegisterSharedBufferImporterAruid"}, | ||||
|         {8224, nullptr, "UnregisterSharedBufferImporterAruid"}, | ||||
|         {8227, nullptr, "CreateSharedBufferProcessHeap"}, | ||||
|         {8228, nullptr, "GetSharedLayerLayerStacks"}, | ||||
|         {8229, nullptr, "SetSharedLayerLayerStacks"}, | ||||
|         {8291, nullptr, "PresentDetachedSharedFrameBufferToLowLevelLayer"}, | ||||
|         {8292, nullptr, "FillDetachedSharedFrameBufferColor"}, | ||||
|         {8293, nullptr, "GetDetachedSharedFrameBufferImage"}, | ||||
|         {8294, nullptr, "SetDetachedSharedFrameBufferImage"}, | ||||
|         {8295, nullptr, "CopyDetachedSharedFrameBufferImage"}, | ||||
|         {8296, nullptr, "SetDetachedSharedFrameBufferSubImage"}, | ||||
|         {8297, nullptr, "GetSharedFrameBufferContentParameter"}, | ||||
|         {8298, nullptr, "ExpandStartupLogoOnSharedFrameBuffer"}, | ||||
|     }; | ||||
|     // clang-format on
 | ||||
| 
 | ||||
|     RegisterHandlers(functions); | ||||
| } | ||||
| 
 | ||||
| IManagerDisplayService::~IManagerDisplayService() = default; | ||||
| 
 | ||||
| void IManagerDisplayService::CloseDisplay(HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const u64 display = rp.Pop<u64>(); | ||||
| 
 | ||||
|     const Result rc = nvnflinger.CloseDisplay(display) ? ResultSuccess : ResultUnknown; | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 2}; | ||||
|     rb.Push(rc); | ||||
| } | ||||
| 
 | ||||
| void IManagerDisplayService::CreateManagedLayer(HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const u32 unknown = rp.Pop<u32>(); | ||||
|     rp.Skip(1, false); | ||||
|     const u64 display = rp.Pop<u64>(); | ||||
|     const u64 aruid = rp.Pop<u64>(); | ||||
| 
 | ||||
|     LOG_WARNING(Service_VI, | ||||
|                 "(STUBBED) called. unknown=0x{:08X}, display=0x{:016X}, aruid=0x{:016X}", unknown, | ||||
|                 display, aruid); | ||||
| 
 | ||||
|     const auto layer_id = nvnflinger.CreateLayer(display); | ||||
|     if (!layer_id) { | ||||
|         LOG_ERROR(Service_VI, "Layer not found! display=0x{:016X}", display); | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ResultNotFound); | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 4}; | ||||
|     rb.Push(ResultSuccess); | ||||
|     rb.Push(*layer_id); | ||||
| } | ||||
| 
 | ||||
| void IManagerDisplayService::AddToLayerStack(HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const u32 stack = rp.Pop<u32>(); | ||||
|     const u64 layer_id = rp.Pop<u64>(); | ||||
| 
 | ||||
|     LOG_WARNING(Service_VI, "(STUBBED) called. stack=0x{:08X}, layer_id=0x{:016X}", stack, | ||||
|                 layer_id); | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 2}; | ||||
|     rb.Push(ResultSuccess); | ||||
| } | ||||
| 
 | ||||
| void IManagerDisplayService::SetLayerVisibility(HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const u64 layer_id = rp.Pop<u64>(); | ||||
|     const bool visibility = rp.Pop<bool>(); | ||||
| 
 | ||||
|     LOG_WARNING(Service_VI, "(STUBBED) called, layer_id=0x{:X}, visibility={}", layer_id, | ||||
|                 visibility); | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 2}; | ||||
|     rb.Push(ResultSuccess); | ||||
| } | ||||
| 
 | ||||
| } // namespace Service::VI
 | ||||
							
								
								
									
										23
									
								
								src/core/hle/service/vi/manager_display_service.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/core/hle/service/vi/manager_display_service.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #include "core/hle/service/service.h" | ||||
| 
 | ||||
| namespace Service::VI { | ||||
| 
 | ||||
| class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> { | ||||
| public: | ||||
|     explicit IManagerDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_); | ||||
|     ~IManagerDisplayService() override; | ||||
| 
 | ||||
| private: | ||||
|     void CloseDisplay(HLERequestContext& ctx); | ||||
|     void CreateManagedLayer(HLERequestContext& ctx); | ||||
|     void AddToLayerStack(HLERequestContext& ctx); | ||||
|     void SetLayerVisibility(HLERequestContext& ctx); | ||||
| 
 | ||||
| private: | ||||
|     Nvnflinger::Nvnflinger& nvnflinger; | ||||
| }; | ||||
| 
 | ||||
| } // namespace Service::VI
 | ||||
| @ -1,19 +1,19 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #include "common/logging/log.h" | ||||
| #include "core/hle/service/vi/manager_root_service.h" | ||||
| #include "core/hle/service/vi/vi.h" | ||||
| #include "core/hle/service/vi/vi_m.h" | ||||
| #include "core/hle/service/vi/vi_types.h" | ||||
| 
 | ||||
| namespace Service::VI { | ||||
| 
 | ||||
| VI_M::VI_M(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, | ||||
| IManagerRootService::IManagerRootService( | ||||
|     Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, | ||||
|     Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_) | ||||
|     : ServiceFramework{system_, "vi:m"}, nv_flinger{nv_flinger_}, | ||||
|       hos_binder_driver_server{hos_binder_driver_server_} { | ||||
|     static const FunctionInfo functions[] = { | ||||
|         {2, &VI_M::GetDisplayService, "GetDisplayService"}, | ||||
|         {2, &IManagerRootService::GetDisplayService, "GetDisplayService"}, | ||||
|         {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, | ||||
|         {100, nullptr, "PrepareFatal"}, | ||||
|         {101, nullptr, "ShowFatal"}, | ||||
| @ -23,9 +23,9 @@ VI_M::VI_M(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, | ||||
|     RegisterHandlers(functions); | ||||
| } | ||||
| 
 | ||||
| VI_M::~VI_M() = default; | ||||
| IManagerRootService::~IManagerRootService() = default; | ||||
| 
 | ||||
| void VI_M::GetDisplayService(HLERequestContext& ctx) { | ||||
| void IManagerRootService::GetDisplayService(HLERequestContext& ctx) { | ||||
|     LOG_DEBUG(Service_VI, "called"); | ||||
| 
 | ||||
|     detail::GetDisplayServiceImpl(ctx, system, nv_flinger, hos_binder_driver_server, | ||||
| @ -16,11 +16,11 @@ class Nvnflinger; | ||||
| 
 | ||||
| namespace Service::VI { | ||||
| 
 | ||||
| class VI_U final : public ServiceFramework<VI_U> { | ||||
| class IManagerRootService final : public ServiceFramework<IManagerRootService> { | ||||
| public: | ||||
|     explicit VI_U(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, | ||||
|     explicit IManagerRootService(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, | ||||
|                                  Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_); | ||||
|     ~VI_U() override; | ||||
|     ~IManagerRootService() override; | ||||
| 
 | ||||
| private: | ||||
|     void GetDisplayService(HLERequestContext& ctx); | ||||
							
								
								
									
										218
									
								
								src/core/hle/service/vi/system_display_service.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										218
									
								
								src/core/hle/service/vi/system_display_service.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,218 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #include "common/settings.h" | ||||
| #include "core/hle/service/ipc_helpers.h" | ||||
| #include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" | ||||
| #include "core/hle/service/vi/system_display_service.h" | ||||
| #include "core/hle/service/vi/vi_types.h" | ||||
| 
 | ||||
| namespace Service::VI { | ||||
| 
 | ||||
| ISystemDisplayService::ISystemDisplayService(Core::System& system_, | ||||
|                                              Nvnflinger::Nvnflinger& nvnflinger_) | ||||
|     : ServiceFramework{system_, "ISystemDisplayService"}, nvnflinger{nvnflinger_} { | ||||
|     // clang-format off
 | ||||
|     static const FunctionInfo functions[] = { | ||||
|         {1200, nullptr, "GetZOrderCountMin"}, | ||||
|         {1202, nullptr, "GetZOrderCountMax"}, | ||||
|         {1203, nullptr, "GetDisplayLogicalResolution"}, | ||||
|         {1204, nullptr, "SetDisplayMagnification"}, | ||||
|         {2201, nullptr, "SetLayerPosition"}, | ||||
|         {2203, nullptr, "SetLayerSize"}, | ||||
|         {2204, nullptr, "GetLayerZ"}, | ||||
|         {2205, &ISystemDisplayService::SetLayerZ, "SetLayerZ"}, | ||||
|         {2207, &ISystemDisplayService::SetLayerVisibility, "SetLayerVisibility"}, | ||||
|         {2209, nullptr, "SetLayerAlpha"}, | ||||
|         {2210, nullptr, "SetLayerPositionAndSize"}, | ||||
|         {2312, nullptr, "CreateStrayLayer"}, | ||||
|         {2400, nullptr, "OpenIndirectLayer"}, | ||||
|         {2401, nullptr, "CloseIndirectLayer"}, | ||||
|         {2402, nullptr, "FlipIndirectLayer"}, | ||||
|         {3000, nullptr, "ListDisplayModes"}, | ||||
|         {3001, nullptr, "ListDisplayRgbRanges"}, | ||||
|         {3002, nullptr, "ListDisplayContentTypes"}, | ||||
|         {3200, &ISystemDisplayService::GetDisplayMode, "GetDisplayMode"}, | ||||
|         {3201, nullptr, "SetDisplayMode"}, | ||||
|         {3202, nullptr, "GetDisplayUnderscan"}, | ||||
|         {3203, nullptr, "SetDisplayUnderscan"}, | ||||
|         {3204, nullptr, "GetDisplayContentType"}, | ||||
|         {3205, nullptr, "SetDisplayContentType"}, | ||||
|         {3206, nullptr, "GetDisplayRgbRange"}, | ||||
|         {3207, nullptr, "SetDisplayRgbRange"}, | ||||
|         {3208, nullptr, "GetDisplayCmuMode"}, | ||||
|         {3209, nullptr, "SetDisplayCmuMode"}, | ||||
|         {3210, nullptr, "GetDisplayContrastRatio"}, | ||||
|         {3211, nullptr, "SetDisplayContrastRatio"}, | ||||
|         {3214, nullptr, "GetDisplayGamma"}, | ||||
|         {3215, nullptr, "SetDisplayGamma"}, | ||||
|         {3216, nullptr, "GetDisplayCmuLuma"}, | ||||
|         {3217, nullptr, "SetDisplayCmuLuma"}, | ||||
|         {3218, nullptr, "SetDisplayCrcMode"}, | ||||
|         {6013, nullptr, "GetLayerPresentationSubmissionTimestamps"}, | ||||
|         {8225, &ISystemDisplayService::GetSharedBufferMemoryHandleId, "GetSharedBufferMemoryHandleId"}, | ||||
|         {8250, &ISystemDisplayService::OpenSharedLayer, "OpenSharedLayer"}, | ||||
|         {8251, nullptr, "CloseSharedLayer"}, | ||||
|         {8252, &ISystemDisplayService::ConnectSharedLayer, "ConnectSharedLayer"}, | ||||
|         {8253, nullptr, "DisconnectSharedLayer"}, | ||||
|         {8254, &ISystemDisplayService::AcquireSharedFrameBuffer, "AcquireSharedFrameBuffer"}, | ||||
|         {8255, &ISystemDisplayService::PresentSharedFrameBuffer, "PresentSharedFrameBuffer"}, | ||||
|         {8256, &ISystemDisplayService::GetSharedFrameBufferAcquirableEvent, "GetSharedFrameBufferAcquirableEvent"}, | ||||
|         {8257, nullptr, "FillSharedFrameBufferColor"}, | ||||
|         {8258, nullptr, "CancelSharedFrameBuffer"}, | ||||
|         {9000, nullptr, "GetDp2hdmiController"}, | ||||
|     }; | ||||
|     // clang-format on
 | ||||
|     RegisterHandlers(functions); | ||||
| } | ||||
| 
 | ||||
| ISystemDisplayService::~ISystemDisplayService() = default; | ||||
| 
 | ||||
| void ISystemDisplayService::GetSharedBufferMemoryHandleId(HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const u64 buffer_id = rp.PopRaw<u64>(); | ||||
|     const u64 aruid = ctx.GetPID(); | ||||
| 
 | ||||
|     LOG_INFO(Service_VI, "called. buffer_id={:#x}, aruid={:#x}", buffer_id, aruid); | ||||
| 
 | ||||
|     struct OutputParameters { | ||||
|         s32 nvmap_handle; | ||||
|         u64 size; | ||||
|     }; | ||||
| 
 | ||||
|     OutputParameters out{}; | ||||
|     Nvnflinger::SharedMemoryPoolLayout layout{}; | ||||
|     const auto result = nvnflinger.GetSystemBufferManager().GetSharedBufferMemoryHandleId( | ||||
|         &out.size, &out.nvmap_handle, &layout, buffer_id, aruid); | ||||
| 
 | ||||
|     ctx.WriteBuffer(&layout, sizeof(layout)); | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 6}; | ||||
|     rb.Push(result); | ||||
|     rb.PushRaw(out); | ||||
| } | ||||
| 
 | ||||
| void ISystemDisplayService::OpenSharedLayer(HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const u64 layer_id = rp.PopRaw<u64>(); | ||||
| 
 | ||||
|     LOG_INFO(Service_VI, "(STUBBED) called. layer_id={:#x}", layer_id); | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 2}; | ||||
|     rb.Push(ResultSuccess); | ||||
| } | ||||
| 
 | ||||
| void ISystemDisplayService::ConnectSharedLayer(HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const u64 layer_id = rp.PopRaw<u64>(); | ||||
| 
 | ||||
|     LOG_INFO(Service_VI, "(STUBBED) called. layer_id={:#x}", layer_id); | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 2}; | ||||
|     rb.Push(ResultSuccess); | ||||
| } | ||||
| 
 | ||||
| void ISystemDisplayService::GetSharedFrameBufferAcquirableEvent(HLERequestContext& ctx) { | ||||
|     LOG_DEBUG(Service_VI, "called"); | ||||
| 
 | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const u64 layer_id = rp.PopRaw<u64>(); | ||||
| 
 | ||||
|     Kernel::KReadableEvent* event{}; | ||||
|     const auto result = | ||||
|         nvnflinger.GetSystemBufferManager().GetSharedFrameBufferAcquirableEvent(&event, layer_id); | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 2, 1}; | ||||
|     rb.Push(result); | ||||
|     rb.PushCopyObjects(event); | ||||
| } | ||||
| 
 | ||||
| void ISystemDisplayService::AcquireSharedFrameBuffer(HLERequestContext& ctx) { | ||||
|     LOG_DEBUG(Service_VI, "called"); | ||||
| 
 | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const u64 layer_id = rp.PopRaw<u64>(); | ||||
| 
 | ||||
|     struct OutputParameters { | ||||
|         android::Fence fence; | ||||
|         std::array<s32, 4> slots; | ||||
|         s64 target_slot; | ||||
|     }; | ||||
|     static_assert(sizeof(OutputParameters) == 0x40, "OutputParameters has wrong size"); | ||||
| 
 | ||||
|     OutputParameters out{}; | ||||
|     const auto result = nvnflinger.GetSystemBufferManager().AcquireSharedFrameBuffer( | ||||
|         &out.fence, out.slots, &out.target_slot, layer_id); | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 18}; | ||||
|     rb.Push(result); | ||||
|     rb.PushRaw(out); | ||||
| } | ||||
| 
 | ||||
| void ISystemDisplayService::PresentSharedFrameBuffer(HLERequestContext& ctx) { | ||||
|     LOG_DEBUG(Service_VI, "called"); | ||||
| 
 | ||||
|     struct InputParameters { | ||||
|         android::Fence fence; | ||||
|         Common::Rectangle<s32> crop_region; | ||||
|         u32 window_transform; | ||||
|         s32 swap_interval; | ||||
|         u64 layer_id; | ||||
|         s64 surface_id; | ||||
|     }; | ||||
|     static_assert(sizeof(InputParameters) == 0x50, "InputParameters has wrong size"); | ||||
| 
 | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     auto input = rp.PopRaw<InputParameters>(); | ||||
| 
 | ||||
|     const auto result = nvnflinger.GetSystemBufferManager().PresentSharedFrameBuffer( | ||||
|         input.fence, input.crop_region, input.window_transform, input.swap_interval, input.layer_id, | ||||
|         input.surface_id); | ||||
|     IPC::ResponseBuilder rb{ctx, 2}; | ||||
|     rb.Push(result); | ||||
| } | ||||
| 
 | ||||
| void ISystemDisplayService::SetLayerZ(HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const u64 layer_id = rp.Pop<u64>(); | ||||
|     const u64 z_value = rp.Pop<u64>(); | ||||
| 
 | ||||
|     LOG_WARNING(Service_VI, "(STUBBED) called. layer_id=0x{:016X}, z_value=0x{:016X}", layer_id, | ||||
|                 z_value); | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 2}; | ||||
|     rb.Push(ResultSuccess); | ||||
| } | ||||
| 
 | ||||
| // This function currently does nothing but return a success error code in
 | ||||
| // the vi library itself, so do the same thing, but log out the passed in values.
 | ||||
| void ISystemDisplayService::SetLayerVisibility(HLERequestContext& ctx) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const u64 layer_id = rp.Pop<u64>(); | ||||
|     const bool visibility = rp.Pop<bool>(); | ||||
| 
 | ||||
|     LOG_DEBUG(Service_VI, "called, layer_id=0x{:08X}, visibility={}", layer_id, visibility); | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 2}; | ||||
|     rb.Push(ResultSuccess); | ||||
| } | ||||
| 
 | ||||
| void ISystemDisplayService::GetDisplayMode(HLERequestContext& ctx) { | ||||
|     LOG_WARNING(Service_VI, "(STUBBED) called"); | ||||
| 
 | ||||
|     IPC::ResponseBuilder rb{ctx, 6}; | ||||
|     rb.Push(ResultSuccess); | ||||
| 
 | ||||
|     if (Settings::IsDockedMode()) { | ||||
|         rb.Push(static_cast<u32>(DisplayResolution::DockedWidth)); | ||||
|         rb.Push(static_cast<u32>(DisplayResolution::DockedHeight)); | ||||
|     } else { | ||||
|         rb.Push(static_cast<u32>(DisplayResolution::UndockedWidth)); | ||||
|         rb.Push(static_cast<u32>(DisplayResolution::UndockedHeight)); | ||||
|     } | ||||
| 
 | ||||
|     rb.PushRaw<float>(60.0f); // This wouldn't seem to be correct for 30 fps games.
 | ||||
|     rb.Push<u32>(0); | ||||
| } | ||||
| 
 | ||||
| } // namespace Service::VI
 | ||||
							
								
								
									
										28
									
								
								src/core/hle/service/vi/system_display_service.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/core/hle/service/vi/system_display_service.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #include "core/hle/service/service.h" | ||||
| 
 | ||||
| namespace Service::VI { | ||||
| 
 | ||||
| class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> { | ||||
| public: | ||||
|     explicit ISystemDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_); | ||||
|     ~ISystemDisplayService() override; | ||||
| 
 | ||||
| private: | ||||
|     void GetSharedBufferMemoryHandleId(HLERequestContext& ctx); | ||||
|     void OpenSharedLayer(HLERequestContext& ctx); | ||||
|     void ConnectSharedLayer(HLERequestContext& ctx); | ||||
|     void GetSharedFrameBufferAcquirableEvent(HLERequestContext& ctx); | ||||
|     void AcquireSharedFrameBuffer(HLERequestContext& ctx); | ||||
|     void PresentSharedFrameBuffer(HLERequestContext& ctx); | ||||
|     void SetLayerZ(HLERequestContext& ctx); | ||||
|     void SetLayerVisibility(HLERequestContext& ctx); | ||||
|     void GetDisplayMode(HLERequestContext& ctx); | ||||
| 
 | ||||
| private: | ||||
|     Nvnflinger::Nvnflinger& nvnflinger; | ||||
| }; | ||||
| 
 | ||||
| } // namespace Service::VI
 | ||||
| @ -1,27 +1,26 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #include "common/logging/log.h" | ||||
| #include "core/hle/service/vi/system_root_service.h" | ||||
| #include "core/hle/service/vi/vi.h" | ||||
| #include "core/hle/service/vi/vi_s.h" | ||||
| #include "core/hle/service/vi/vi_types.h" | ||||
| 
 | ||||
| namespace Service::VI { | ||||
| 
 | ||||
| VI_S::VI_S(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, | ||||
| ISystemRootService::ISystemRootService(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, | ||||
|                                        Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_) | ||||
|     : ServiceFramework{system_, "vi:s"}, nv_flinger{nv_flinger_}, | ||||
|       hos_binder_driver_server{hos_binder_driver_server_} { | ||||
|     static const FunctionInfo functions[] = { | ||||
|         {1, &VI_S::GetDisplayService, "GetDisplayService"}, | ||||
|         {1, &ISystemRootService::GetDisplayService, "GetDisplayService"}, | ||||
|         {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, | ||||
|     }; | ||||
|     RegisterHandlers(functions); | ||||
| } | ||||
| 
 | ||||
| VI_S::~VI_S() = default; | ||||
| ISystemRootService::~ISystemRootService() = default; | ||||
| 
 | ||||
| void VI_S::GetDisplayService(HLERequestContext& ctx) { | ||||
| void ISystemRootService::GetDisplayService(HLERequestContext& ctx) { | ||||
|     LOG_DEBUG(Service_VI, "called"); | ||||
| 
 | ||||
|     detail::GetDisplayServiceImpl(ctx, system, nv_flinger, hos_binder_driver_server, | ||||
| @ -16,11 +16,11 @@ class Nvnflinger; | ||||
| 
 | ||||
| namespace Service::VI { | ||||
| 
 | ||||
| class VI_M final : public ServiceFramework<VI_M> { | ||||
| class ISystemRootService final : public ServiceFramework<ISystemRootService> { | ||||
| public: | ||||
|     explicit VI_M(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, | ||||
|     explicit ISystemRootService(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, | ||||
|                                 Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_); | ||||
|     ~VI_M() override; | ||||
|     ~ISystemRootService() override; | ||||
| 
 | ||||
| private: | ||||
|     void GetDisplayService(HLERequestContext& ctx); | ||||
| @ -1,891 +1,18 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #include <array> | ||||
| #include <memory> | ||||
| #include <optional> | ||||
| #include <type_traits> | ||||
| #include <utility> | ||||
| 
 | ||||
| #include "common/assert.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/math_util.h" | ||||
| #include "common/settings.h" | ||||
| #include "common/string_util.h" | ||||
| #include "core/hle/kernel/k_readable_event.h" | ||||
| #include "core/hle/kernel/k_thread.h" | ||||
| #include "core/hle/service/ipc_helpers.h" | ||||
| #include "core/hle/service/nvdrv/nvdrv.h" | ||||
| #include "core/hle/service/nvnflinger/binder.h" | ||||
| #include "core/hle/service/nvnflinger/buffer_queue_producer.h" | ||||
| #include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" | ||||
| #include "core/hle/service/nvnflinger/hos_binder_driver_server.h" | ||||
| #include "core/hle/service/nvnflinger/nvnflinger.h" | ||||
| #include "core/hle/service/nvnflinger/parcel.h" | ||||
| #include "core/hle/service/server_manager.h" | ||||
| #include "core/hle/service/service.h" | ||||
| #include "core/hle/service/vi/application_display_service.h" | ||||
| #include "core/hle/service/vi/application_root_service.h" | ||||
| #include "core/hle/service/vi/manager_root_service.h" | ||||
| #include "core/hle/service/vi/system_root_service.h" | ||||
| #include "core/hle/service/vi/vi.h" | ||||
| #include "core/hle/service/vi/vi_m.h" | ||||
| #include "core/hle/service/vi/vi_results.h" | ||||
| #include "core/hle/service/vi/vi_s.h" | ||||
| #include "core/hle/service/vi/vi_types.h" | ||||
| #include "core/hle/service/vi/vi_u.h" | ||||
| 
 | ||||
| namespace Service::VI { | ||||
| 
 | ||||
| class IHOSBinderDriver final : public ServiceFramework<IHOSBinderDriver> { | ||||
| public: | ||||
|     explicit IHOSBinderDriver(Core::System& system_, Nvnflinger::HosBinderDriverServer& server_) | ||||
|         : ServiceFramework{system_, "IHOSBinderDriver"}, server(server_) { | ||||
|         static const FunctionInfo functions[] = { | ||||
|             {0, &IHOSBinderDriver::TransactParcel, "TransactParcel"}, | ||||
|             {1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"}, | ||||
|             {2, &IHOSBinderDriver::GetNativeHandle, "GetNativeHandle"}, | ||||
|             {3, &IHOSBinderDriver::TransactParcel, "TransactParcelAuto"}, | ||||
|         }; | ||||
|         RegisterHandlers(functions); | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     void TransactParcel(HLERequestContext& ctx) { | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         const u32 id = rp.Pop<u32>(); | ||||
|         const auto transaction = static_cast<android::TransactionId>(rp.Pop<u32>()); | ||||
|         const u32 flags = rp.Pop<u32>(); | ||||
| 
 | ||||
|         LOG_DEBUG(Service_VI, "called. id=0x{:08X} transaction={:X}, flags=0x{:08X}", id, | ||||
|                   transaction, flags); | ||||
| 
 | ||||
|         server.TryGetProducer(id)->Transact(ctx, transaction, flags); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ResultSuccess); | ||||
|     } | ||||
| 
 | ||||
|     void AdjustRefcount(HLERequestContext& ctx) { | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         const u32 id = rp.Pop<u32>(); | ||||
|         const s32 addval = rp.PopRaw<s32>(); | ||||
|         const u32 type = rp.Pop<u32>(); | ||||
| 
 | ||||
|         LOG_WARNING(Service_VI, "(STUBBED) called id={}, addval={:08X}, type={:08X}", id, addval, | ||||
|                     type); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ResultSuccess); | ||||
|     } | ||||
| 
 | ||||
|     void GetNativeHandle(HLERequestContext& ctx) { | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         const u32 id = rp.Pop<u32>(); | ||||
|         const u32 unknown = rp.Pop<u32>(); | ||||
| 
 | ||||
|         LOG_WARNING(Service_VI, "(STUBBED) called id={}, unknown={:08X}", id, unknown); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2, 1}; | ||||
|         rb.Push(ResultSuccess); | ||||
|         rb.PushCopyObjects(server.TryGetProducer(id)->GetNativeHandle()); | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     Nvnflinger::HosBinderDriverServer& server; | ||||
| }; | ||||
| 
 | ||||
| class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> { | ||||
| public: | ||||
|     explicit ISystemDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_) | ||||
|         : ServiceFramework{system_, "ISystemDisplayService"}, nvnflinger{nvnflinger_} { | ||||
|         // clang-format off
 | ||||
|         static const FunctionInfo functions[] = { | ||||
|             {1200, nullptr, "GetZOrderCountMin"}, | ||||
|             {1202, nullptr, "GetZOrderCountMax"}, | ||||
|             {1203, nullptr, "GetDisplayLogicalResolution"}, | ||||
|             {1204, nullptr, "SetDisplayMagnification"}, | ||||
|             {2201, nullptr, "SetLayerPosition"}, | ||||
|             {2203, nullptr, "SetLayerSize"}, | ||||
|             {2204, nullptr, "GetLayerZ"}, | ||||
|             {2205, &ISystemDisplayService::SetLayerZ, "SetLayerZ"}, | ||||
|             {2207, &ISystemDisplayService::SetLayerVisibility, "SetLayerVisibility"}, | ||||
|             {2209, nullptr, "SetLayerAlpha"}, | ||||
|             {2210, nullptr, "SetLayerPositionAndSize"}, | ||||
|             {2312, nullptr, "CreateStrayLayer"}, | ||||
|             {2400, nullptr, "OpenIndirectLayer"}, | ||||
|             {2401, nullptr, "CloseIndirectLayer"}, | ||||
|             {2402, nullptr, "FlipIndirectLayer"}, | ||||
|             {3000, nullptr, "ListDisplayModes"}, | ||||
|             {3001, nullptr, "ListDisplayRgbRanges"}, | ||||
|             {3002, nullptr, "ListDisplayContentTypes"}, | ||||
|             {3200, &ISystemDisplayService::GetDisplayMode, "GetDisplayMode"}, | ||||
|             {3201, nullptr, "SetDisplayMode"}, | ||||
|             {3202, nullptr, "GetDisplayUnderscan"}, | ||||
|             {3203, nullptr, "SetDisplayUnderscan"}, | ||||
|             {3204, nullptr, "GetDisplayContentType"}, | ||||
|             {3205, nullptr, "SetDisplayContentType"}, | ||||
|             {3206, nullptr, "GetDisplayRgbRange"}, | ||||
|             {3207, nullptr, "SetDisplayRgbRange"}, | ||||
|             {3208, nullptr, "GetDisplayCmuMode"}, | ||||
|             {3209, nullptr, "SetDisplayCmuMode"}, | ||||
|             {3210, nullptr, "GetDisplayContrastRatio"}, | ||||
|             {3211, nullptr, "SetDisplayContrastRatio"}, | ||||
|             {3214, nullptr, "GetDisplayGamma"}, | ||||
|             {3215, nullptr, "SetDisplayGamma"}, | ||||
|             {3216, nullptr, "GetDisplayCmuLuma"}, | ||||
|             {3217, nullptr, "SetDisplayCmuLuma"}, | ||||
|             {3218, nullptr, "SetDisplayCrcMode"}, | ||||
|             {6013, nullptr, "GetLayerPresentationSubmissionTimestamps"}, | ||||
|             {8225, &ISystemDisplayService::GetSharedBufferMemoryHandleId, "GetSharedBufferMemoryHandleId"}, | ||||
|             {8250, &ISystemDisplayService::OpenSharedLayer, "OpenSharedLayer"}, | ||||
|             {8251, nullptr, "CloseSharedLayer"}, | ||||
|             {8252, &ISystemDisplayService::ConnectSharedLayer, "ConnectSharedLayer"}, | ||||
|             {8253, nullptr, "DisconnectSharedLayer"}, | ||||
|             {8254, &ISystemDisplayService::AcquireSharedFrameBuffer, "AcquireSharedFrameBuffer"}, | ||||
|             {8255, &ISystemDisplayService::PresentSharedFrameBuffer, "PresentSharedFrameBuffer"}, | ||||
|             {8256, &ISystemDisplayService::GetSharedFrameBufferAcquirableEvent, "GetSharedFrameBufferAcquirableEvent"}, | ||||
|             {8257, nullptr, "FillSharedFrameBufferColor"}, | ||||
|             {8258, nullptr, "CancelSharedFrameBuffer"}, | ||||
|             {9000, nullptr, "GetDp2hdmiController"}, | ||||
|         }; | ||||
|         // clang-format on
 | ||||
|         RegisterHandlers(functions); | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     void GetSharedBufferMemoryHandleId(HLERequestContext& ctx) { | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         const u64 buffer_id = rp.PopRaw<u64>(); | ||||
|         const u64 aruid = ctx.GetPID(); | ||||
| 
 | ||||
|         LOG_INFO(Service_VI, "called. buffer_id={:#x}, aruid={:#x}", buffer_id, aruid); | ||||
| 
 | ||||
|         struct OutputParameters { | ||||
|             s32 nvmap_handle; | ||||
|             u64 size; | ||||
|         }; | ||||
| 
 | ||||
|         OutputParameters out{}; | ||||
|         Nvnflinger::SharedMemoryPoolLayout layout{}; | ||||
|         const auto result = nvnflinger.GetSystemBufferManager().GetSharedBufferMemoryHandleId( | ||||
|             &out.size, &out.nvmap_handle, &layout, buffer_id, aruid); | ||||
| 
 | ||||
|         ctx.WriteBuffer(&layout, sizeof(layout)); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 6}; | ||||
|         rb.Push(result); | ||||
|         rb.PushRaw(out); | ||||
|     } | ||||
| 
 | ||||
|     void OpenSharedLayer(HLERequestContext& ctx) { | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         const u64 layer_id = rp.PopRaw<u64>(); | ||||
| 
 | ||||
|         LOG_INFO(Service_VI, "(STUBBED) called. layer_id={:#x}", layer_id); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ResultSuccess); | ||||
|     } | ||||
| 
 | ||||
|     void ConnectSharedLayer(HLERequestContext& ctx) { | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         const u64 layer_id = rp.PopRaw<u64>(); | ||||
| 
 | ||||
|         LOG_INFO(Service_VI, "(STUBBED) called. layer_id={:#x}", layer_id); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ResultSuccess); | ||||
|     } | ||||
| 
 | ||||
|     void GetSharedFrameBufferAcquirableEvent(HLERequestContext& ctx) { | ||||
|         LOG_DEBUG(Service_VI, "called"); | ||||
| 
 | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         const u64 layer_id = rp.PopRaw<u64>(); | ||||
| 
 | ||||
|         Kernel::KReadableEvent* event{}; | ||||
|         const auto result = nvnflinger.GetSystemBufferManager().GetSharedFrameBufferAcquirableEvent( | ||||
|             &event, layer_id); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2, 1}; | ||||
|         rb.Push(result); | ||||
|         rb.PushCopyObjects(event); | ||||
|     } | ||||
| 
 | ||||
|     void AcquireSharedFrameBuffer(HLERequestContext& ctx) { | ||||
|         LOG_DEBUG(Service_VI, "called"); | ||||
| 
 | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         const u64 layer_id = rp.PopRaw<u64>(); | ||||
| 
 | ||||
|         struct OutputParameters { | ||||
|             android::Fence fence; | ||||
|             std::array<s32, 4> slots; | ||||
|             s64 target_slot; | ||||
|         }; | ||||
|         static_assert(sizeof(OutputParameters) == 0x40, "OutputParameters has wrong size"); | ||||
| 
 | ||||
|         OutputParameters out{}; | ||||
|         const auto result = nvnflinger.GetSystemBufferManager().AcquireSharedFrameBuffer( | ||||
|             &out.fence, out.slots, &out.target_slot, layer_id); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 18}; | ||||
|         rb.Push(result); | ||||
|         rb.PushRaw(out); | ||||
|     } | ||||
| 
 | ||||
|     void PresentSharedFrameBuffer(HLERequestContext& ctx) { | ||||
|         LOG_DEBUG(Service_VI, "called"); | ||||
| 
 | ||||
|         struct InputParameters { | ||||
|             android::Fence fence; | ||||
|             Common::Rectangle<s32> crop_region; | ||||
|             u32 window_transform; | ||||
|             s32 swap_interval; | ||||
|             u64 layer_id; | ||||
|             s64 surface_id; | ||||
|         }; | ||||
|         static_assert(sizeof(InputParameters) == 0x50, "InputParameters has wrong size"); | ||||
| 
 | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         auto input = rp.PopRaw<InputParameters>(); | ||||
| 
 | ||||
|         const auto result = nvnflinger.GetSystemBufferManager().PresentSharedFrameBuffer( | ||||
|             input.fence, input.crop_region, input.window_transform, input.swap_interval, | ||||
|             input.layer_id, input.surface_id); | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(result); | ||||
|     } | ||||
| 
 | ||||
|     void SetLayerZ(HLERequestContext& ctx) { | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         const u64 layer_id = rp.Pop<u64>(); | ||||
|         const u64 z_value = rp.Pop<u64>(); | ||||
| 
 | ||||
|         LOG_WARNING(Service_VI, "(STUBBED) called. layer_id=0x{:016X}, z_value=0x{:016X}", layer_id, | ||||
|                     z_value); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ResultSuccess); | ||||
|     } | ||||
| 
 | ||||
|     // This function currently does nothing but return a success error code in
 | ||||
|     // the vi library itself, so do the same thing, but log out the passed in values.
 | ||||
|     void SetLayerVisibility(HLERequestContext& ctx) { | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         const u64 layer_id = rp.Pop<u64>(); | ||||
|         const bool visibility = rp.Pop<bool>(); | ||||
| 
 | ||||
|         LOG_DEBUG(Service_VI, "called, layer_id=0x{:08X}, visibility={}", layer_id, visibility); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ResultSuccess); | ||||
|     } | ||||
| 
 | ||||
|     void GetDisplayMode(HLERequestContext& ctx) { | ||||
|         LOG_WARNING(Service_VI, "(STUBBED) called"); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 6}; | ||||
|         rb.Push(ResultSuccess); | ||||
| 
 | ||||
|         if (Settings::IsDockedMode()) { | ||||
|             rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedWidth)); | ||||
|             rb.Push(static_cast<u32>(Service::VI::DisplayResolution::DockedHeight)); | ||||
|         } else { | ||||
|             rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedWidth)); | ||||
|             rb.Push(static_cast<u32>(Service::VI::DisplayResolution::UndockedHeight)); | ||||
|         } | ||||
| 
 | ||||
|         rb.PushRaw<float>(60.0f); // This wouldn't seem to be correct for 30 fps games.
 | ||||
|         rb.Push<u32>(0); | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     Nvnflinger::Nvnflinger& nvnflinger; | ||||
| }; | ||||
| 
 | ||||
| class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> { | ||||
| public: | ||||
|     explicit IManagerDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_) | ||||
|         : ServiceFramework{system_, "IManagerDisplayService"}, nvnflinger{nvnflinger_} { | ||||
|         // clang-format off
 | ||||
|         static const FunctionInfo functions[] = { | ||||
|             {200, nullptr, "AllocateProcessHeapBlock"}, | ||||
|             {201, nullptr, "FreeProcessHeapBlock"}, | ||||
|             {1020, &IManagerDisplayService::CloseDisplay, "CloseDisplay"}, | ||||
|             {1102, nullptr, "GetDisplayResolution"}, | ||||
|             {2010, &IManagerDisplayService::CreateManagedLayer, "CreateManagedLayer"}, | ||||
|             {2011, nullptr, "DestroyManagedLayer"}, | ||||
|             {2012, nullptr, "CreateStrayLayer"}, | ||||
|             {2050, nullptr, "CreateIndirectLayer"}, | ||||
|             {2051, nullptr, "DestroyIndirectLayer"}, | ||||
|             {2052, nullptr, "CreateIndirectProducerEndPoint"}, | ||||
|             {2053, nullptr, "DestroyIndirectProducerEndPoint"}, | ||||
|             {2054, nullptr, "CreateIndirectConsumerEndPoint"}, | ||||
|             {2055, nullptr, "DestroyIndirectConsumerEndPoint"}, | ||||
|             {2060, nullptr, "CreateWatermarkCompositor"}, | ||||
|             {2062, nullptr, "SetWatermarkText"}, | ||||
|             {2063, nullptr, "SetWatermarkLayerStacks"}, | ||||
|             {2300, nullptr, "AcquireLayerTexturePresentingEvent"}, | ||||
|             {2301, nullptr, "ReleaseLayerTexturePresentingEvent"}, | ||||
|             {2302, nullptr, "GetDisplayHotplugEvent"}, | ||||
|             {2303, nullptr, "GetDisplayModeChangedEvent"}, | ||||
|             {2402, nullptr, "GetDisplayHotplugState"}, | ||||
|             {2501, nullptr, "GetCompositorErrorInfo"}, | ||||
|             {2601, nullptr, "GetDisplayErrorEvent"}, | ||||
|             {2701, nullptr, "GetDisplayFatalErrorEvent"}, | ||||
|             {4201, nullptr, "SetDisplayAlpha"}, | ||||
|             {4203, nullptr, "SetDisplayLayerStack"}, | ||||
|             {4205, nullptr, "SetDisplayPowerState"}, | ||||
|             {4206, nullptr, "SetDefaultDisplay"}, | ||||
|             {4207, nullptr, "ResetDisplayPanel"}, | ||||
|             {4208, nullptr, "SetDisplayFatalErrorEnabled"}, | ||||
|             {4209, nullptr, "IsDisplayPanelOn"}, | ||||
|             {4300, nullptr, "GetInternalPanelId"}, | ||||
|             {6000, &IManagerDisplayService::AddToLayerStack, "AddToLayerStack"}, | ||||
|             {6001, nullptr, "RemoveFromLayerStack"}, | ||||
|             {6002, &IManagerDisplayService::SetLayerVisibility, "SetLayerVisibility"}, | ||||
|             {6003, nullptr, "SetLayerConfig"}, | ||||
|             {6004, nullptr, "AttachLayerPresentationTracer"}, | ||||
|             {6005, nullptr, "DetachLayerPresentationTracer"}, | ||||
|             {6006, nullptr, "StartLayerPresentationRecording"}, | ||||
|             {6007, nullptr, "StopLayerPresentationRecording"}, | ||||
|             {6008, nullptr, "StartLayerPresentationFenceWait"}, | ||||
|             {6009, nullptr, "StopLayerPresentationFenceWait"}, | ||||
|             {6010, nullptr, "GetLayerPresentationAllFencesExpiredEvent"}, | ||||
|             {6011, nullptr, "EnableLayerAutoClearTransitionBuffer"}, | ||||
|             {6012, nullptr, "DisableLayerAutoClearTransitionBuffer"}, | ||||
|             {6013, nullptr, "SetLayerOpacity"}, | ||||
|             {6014, nullptr, "AttachLayerWatermarkCompositor"}, | ||||
|             {6015, nullptr, "DetachLayerWatermarkCompositor"}, | ||||
|             {7000, nullptr, "SetContentVisibility"}, | ||||
|             {8000, nullptr, "SetConductorLayer"}, | ||||
|             {8001, nullptr, "SetTimestampTracking"}, | ||||
|             {8100, nullptr, "SetIndirectProducerFlipOffset"}, | ||||
|             {8200, nullptr, "CreateSharedBufferStaticStorage"}, | ||||
|             {8201, nullptr, "CreateSharedBufferTransferMemory"}, | ||||
|             {8202, nullptr, "DestroySharedBuffer"}, | ||||
|             {8203, nullptr, "BindSharedLowLevelLayerToManagedLayer"}, | ||||
|             {8204, nullptr, "BindSharedLowLevelLayerToIndirectLayer"}, | ||||
|             {8207, nullptr, "UnbindSharedLowLevelLayer"}, | ||||
|             {8208, nullptr, "ConnectSharedLowLevelLayerToSharedBuffer"}, | ||||
|             {8209, nullptr, "DisconnectSharedLowLevelLayerFromSharedBuffer"}, | ||||
|             {8210, nullptr, "CreateSharedLayer"}, | ||||
|             {8211, nullptr, "DestroySharedLayer"}, | ||||
|             {8216, nullptr, "AttachSharedLayerToLowLevelLayer"}, | ||||
|             {8217, nullptr, "ForceDetachSharedLayerFromLowLevelLayer"}, | ||||
|             {8218, nullptr, "StartDetachSharedLayerFromLowLevelLayer"}, | ||||
|             {8219, nullptr, "FinishDetachSharedLayerFromLowLevelLayer"}, | ||||
|             {8220, nullptr, "GetSharedLayerDetachReadyEvent"}, | ||||
|             {8221, nullptr, "GetSharedLowLevelLayerSynchronizedEvent"}, | ||||
|             {8222, nullptr, "CheckSharedLowLevelLayerSynchronized"}, | ||||
|             {8223, nullptr, "RegisterSharedBufferImporterAruid"}, | ||||
|             {8224, nullptr, "UnregisterSharedBufferImporterAruid"}, | ||||
|             {8227, nullptr, "CreateSharedBufferProcessHeap"}, | ||||
|             {8228, nullptr, "GetSharedLayerLayerStacks"}, | ||||
|             {8229, nullptr, "SetSharedLayerLayerStacks"}, | ||||
|             {8291, nullptr, "PresentDetachedSharedFrameBufferToLowLevelLayer"}, | ||||
|             {8292, nullptr, "FillDetachedSharedFrameBufferColor"}, | ||||
|             {8293, nullptr, "GetDetachedSharedFrameBufferImage"}, | ||||
|             {8294, nullptr, "SetDetachedSharedFrameBufferImage"}, | ||||
|             {8295, nullptr, "CopyDetachedSharedFrameBufferImage"}, | ||||
|             {8296, nullptr, "SetDetachedSharedFrameBufferSubImage"}, | ||||
|             {8297, nullptr, "GetSharedFrameBufferContentParameter"}, | ||||
|             {8298, nullptr, "ExpandStartupLogoOnSharedFrameBuffer"}, | ||||
|         }; | ||||
|         // clang-format on
 | ||||
| 
 | ||||
|         RegisterHandlers(functions); | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     void CloseDisplay(HLERequestContext& ctx) { | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         const u64 display = rp.Pop<u64>(); | ||||
| 
 | ||||
|         const Result rc = nvnflinger.CloseDisplay(display) ? ResultSuccess : ResultUnknown; | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(rc); | ||||
|     } | ||||
| 
 | ||||
|     void CreateManagedLayer(HLERequestContext& ctx) { | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         const u32 unknown = rp.Pop<u32>(); | ||||
|         rp.Skip(1, false); | ||||
|         const u64 display = rp.Pop<u64>(); | ||||
|         const u64 aruid = rp.Pop<u64>(); | ||||
| 
 | ||||
|         LOG_WARNING(Service_VI, | ||||
|                     "(STUBBED) called. unknown=0x{:08X}, display=0x{:016X}, aruid=0x{:016X}", | ||||
|                     unknown, display, aruid); | ||||
| 
 | ||||
|         const auto layer_id = nvnflinger.CreateLayer(display); | ||||
|         if (!layer_id) { | ||||
|             LOG_ERROR(Service_VI, "Layer not found! display=0x{:016X}", display); | ||||
|             IPC::ResponseBuilder rb{ctx, 2}; | ||||
|             rb.Push(ResultNotFound); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 4}; | ||||
|         rb.Push(ResultSuccess); | ||||
|         rb.Push(*layer_id); | ||||
|     } | ||||
| 
 | ||||
|     void AddToLayerStack(HLERequestContext& ctx) { | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         const u32 stack = rp.Pop<u32>(); | ||||
|         const u64 layer_id = rp.Pop<u64>(); | ||||
| 
 | ||||
|         LOG_WARNING(Service_VI, "(STUBBED) called. stack=0x{:08X}, layer_id=0x{:016X}", stack, | ||||
|                     layer_id); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ResultSuccess); | ||||
|     } | ||||
| 
 | ||||
|     void SetLayerVisibility(HLERequestContext& ctx) { | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         const u64 layer_id = rp.Pop<u64>(); | ||||
|         const bool visibility = rp.Pop<bool>(); | ||||
| 
 | ||||
|         LOG_WARNING(Service_VI, "(STUBBED) called, layer_id=0x{:X}, visibility={}", layer_id, | ||||
|                     visibility); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ResultSuccess); | ||||
|     } | ||||
| 
 | ||||
|     Nvnflinger::Nvnflinger& nvnflinger; | ||||
| }; | ||||
| 
 | ||||
| class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> { | ||||
| public: | ||||
|     IApplicationDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_, | ||||
|                                Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_) | ||||
|         : ServiceFramework{system_, "IApplicationDisplayService"}, nvnflinger{nvnflinger_}, | ||||
|           hos_binder_driver_server{hos_binder_driver_server_} { | ||||
| 
 | ||||
|         static const FunctionInfo functions[] = { | ||||
|             {100, &IApplicationDisplayService::GetRelayService, "GetRelayService"}, | ||||
|             {101, &IApplicationDisplayService::GetSystemDisplayService, "GetSystemDisplayService"}, | ||||
|             {102, &IApplicationDisplayService::GetManagerDisplayService, | ||||
|              "GetManagerDisplayService"}, | ||||
|             {103, &IApplicationDisplayService::GetIndirectDisplayTransactionService, | ||||
|              "GetIndirectDisplayTransactionService"}, | ||||
|             {1000, &IApplicationDisplayService::ListDisplays, "ListDisplays"}, | ||||
|             {1010, &IApplicationDisplayService::OpenDisplay, "OpenDisplay"}, | ||||
|             {1011, &IApplicationDisplayService::OpenDefaultDisplay, "OpenDefaultDisplay"}, | ||||
|             {1020, &IApplicationDisplayService::CloseDisplay, "CloseDisplay"}, | ||||
|             {1101, &IApplicationDisplayService::SetDisplayEnabled, "SetDisplayEnabled"}, | ||||
|             {1102, &IApplicationDisplayService::GetDisplayResolution, "GetDisplayResolution"}, | ||||
|             {2020, &IApplicationDisplayService::OpenLayer, "OpenLayer"}, | ||||
|             {2021, &IApplicationDisplayService::CloseLayer, "CloseLayer"}, | ||||
|             {2030, &IApplicationDisplayService::CreateStrayLayer, "CreateStrayLayer"}, | ||||
|             {2031, &IApplicationDisplayService::DestroyStrayLayer, "DestroyStrayLayer"}, | ||||
|             {2101, &IApplicationDisplayService::SetLayerScalingMode, "SetLayerScalingMode"}, | ||||
|             {2102, &IApplicationDisplayService::ConvertScalingMode, "ConvertScalingMode"}, | ||||
|             {2450, &IApplicationDisplayService::GetIndirectLayerImageMap, | ||||
|              "GetIndirectLayerImageMap"}, | ||||
|             {2451, nullptr, "GetIndirectLayerImageCropMap"}, | ||||
|             {2460, &IApplicationDisplayService::GetIndirectLayerImageRequiredMemoryInfo, | ||||
|              "GetIndirectLayerImageRequiredMemoryInfo"}, | ||||
|             {5202, &IApplicationDisplayService::GetDisplayVsyncEvent, "GetDisplayVsyncEvent"}, | ||||
|             {5203, nullptr, "GetDisplayVsyncEventForDebug"}, | ||||
|         }; | ||||
|         RegisterHandlers(functions); | ||||
|     } | ||||
| 
 | ||||
|     ~IApplicationDisplayService() { | ||||
|         for (const auto layer_id : stray_layer_ids) { | ||||
|             nvnflinger.DestroyLayer(layer_id); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     enum class ConvertedScaleMode : u64 { | ||||
|         Freeze = 0, | ||||
|         ScaleToWindow = 1, | ||||
|         ScaleAndCrop = 2, | ||||
|         None = 3, | ||||
|         PreserveAspectRatio = 4, | ||||
|     }; | ||||
| 
 | ||||
|     enum class NintendoScaleMode : u32 { | ||||
|         None = 0, | ||||
|         Freeze = 1, | ||||
|         ScaleToWindow = 2, | ||||
|         ScaleAndCrop = 3, | ||||
|         PreserveAspectRatio = 4, | ||||
|     }; | ||||
| 
 | ||||
|     void GetRelayService(HLERequestContext& ctx) { | ||||
|         LOG_WARNING(Service_VI, "(STUBBED) called"); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||||
|         rb.Push(ResultSuccess); | ||||
|         rb.PushIpcInterface<IHOSBinderDriver>(system, hos_binder_driver_server); | ||||
|     } | ||||
| 
 | ||||
|     void GetSystemDisplayService(HLERequestContext& ctx) { | ||||
|         LOG_WARNING(Service_VI, "(STUBBED) called"); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||||
|         rb.Push(ResultSuccess); | ||||
|         rb.PushIpcInterface<ISystemDisplayService>(system, nvnflinger); | ||||
|     } | ||||
| 
 | ||||
|     void GetManagerDisplayService(HLERequestContext& ctx) { | ||||
|         LOG_WARNING(Service_VI, "(STUBBED) called"); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||||
|         rb.Push(ResultSuccess); | ||||
|         rb.PushIpcInterface<IManagerDisplayService>(system, nvnflinger); | ||||
|     } | ||||
| 
 | ||||
|     void GetIndirectDisplayTransactionService(HLERequestContext& ctx) { | ||||
|         LOG_WARNING(Service_VI, "(STUBBED) called"); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||||
|         rb.Push(ResultSuccess); | ||||
|         rb.PushIpcInterface<IHOSBinderDriver>(system, hos_binder_driver_server); | ||||
|     } | ||||
| 
 | ||||
|     void OpenDisplay(HLERequestContext& ctx) { | ||||
|         LOG_WARNING(Service_VI, "(STUBBED) called"); | ||||
| 
 | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         const auto name_buf = rp.PopRaw<std::array<char, 0x40>>(); | ||||
| 
 | ||||
|         OpenDisplayImpl(ctx, std::string_view{name_buf.data(), name_buf.size()}); | ||||
|     } | ||||
| 
 | ||||
|     void OpenDefaultDisplay(HLERequestContext& ctx) { | ||||
|         LOG_DEBUG(Service_VI, "called"); | ||||
| 
 | ||||
|         OpenDisplayImpl(ctx, "Default"); | ||||
|     } | ||||
| 
 | ||||
|     void OpenDisplayImpl(HLERequestContext& ctx, std::string_view name) { | ||||
|         const auto trim_pos = name.find('\0'); | ||||
| 
 | ||||
|         if (trim_pos != std::string_view::npos) { | ||||
|             name.remove_suffix(name.size() - trim_pos); | ||||
|         } | ||||
| 
 | ||||
|         ASSERT_MSG(name == "Default", "Non-default displays aren't supported yet"); | ||||
| 
 | ||||
|         const auto display_id = nvnflinger.OpenDisplay(name); | ||||
|         if (!display_id) { | ||||
|             LOG_ERROR(Service_VI, "Display not found! display_name={}", name); | ||||
|             IPC::ResponseBuilder rb{ctx, 2}; | ||||
|             rb.Push(ResultNotFound); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 4}; | ||||
|         rb.Push(ResultSuccess); | ||||
|         rb.Push<u64>(*display_id); | ||||
|     } | ||||
| 
 | ||||
|     void CloseDisplay(HLERequestContext& ctx) { | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         const u64 display_id = rp.Pop<u64>(); | ||||
| 
 | ||||
|         const Result rc = nvnflinger.CloseDisplay(display_id) ? ResultSuccess : ResultUnknown; | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(rc); | ||||
|     } | ||||
| 
 | ||||
|     // This literally does nothing internally in the actual service itself,
 | ||||
|     // and just returns a successful result code regardless of the input.
 | ||||
|     void SetDisplayEnabled(HLERequestContext& ctx) { | ||||
|         LOG_DEBUG(Service_VI, "called."); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ResultSuccess); | ||||
|     } | ||||
| 
 | ||||
|     void GetDisplayResolution(HLERequestContext& ctx) { | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         const u64 display_id = rp.Pop<u64>(); | ||||
| 
 | ||||
|         LOG_DEBUG(Service_VI, "called. display_id=0x{:016X}", display_id); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 6}; | ||||
|         rb.Push(ResultSuccess); | ||||
| 
 | ||||
|         // This only returns the fixed values of 1280x720 and makes no distinguishing
 | ||||
|         // between docked and undocked dimensions. We take the liberty of applying
 | ||||
|         // the resolution scaling factor here.
 | ||||
|         rb.Push(static_cast<u64>(DisplayResolution::UndockedWidth)); | ||||
|         rb.Push(static_cast<u64>(DisplayResolution::UndockedHeight)); | ||||
|     } | ||||
| 
 | ||||
|     void SetLayerScalingMode(HLERequestContext& ctx) { | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         const auto scaling_mode = rp.PopEnum<NintendoScaleMode>(); | ||||
|         const u64 unknown = rp.Pop<u64>(); | ||||
| 
 | ||||
|         LOG_DEBUG(Service_VI, "called. scaling_mode=0x{:08X}, unknown=0x{:016X}", scaling_mode, | ||||
|                   unknown); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
| 
 | ||||
|         if (scaling_mode > NintendoScaleMode::PreserveAspectRatio) { | ||||
|             LOG_ERROR(Service_VI, "Invalid scaling mode provided."); | ||||
|             rb.Push(ResultOperationFailed); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         if (scaling_mode != NintendoScaleMode::ScaleToWindow && | ||||
|             scaling_mode != NintendoScaleMode::PreserveAspectRatio) { | ||||
|             LOG_ERROR(Service_VI, "Unsupported scaling mode supplied."); | ||||
|             rb.Push(ResultNotSupported); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         rb.Push(ResultSuccess); | ||||
|     } | ||||
| 
 | ||||
|     void ListDisplays(HLERequestContext& ctx) { | ||||
|         LOG_WARNING(Service_VI, "(STUBBED) called"); | ||||
| 
 | ||||
|         const DisplayInfo display_info; | ||||
|         ctx.WriteBuffer(&display_info, sizeof(DisplayInfo)); | ||||
|         IPC::ResponseBuilder rb{ctx, 4}; | ||||
|         rb.Push(ResultSuccess); | ||||
|         rb.Push<u64>(1); | ||||
|     } | ||||
| 
 | ||||
|     void OpenLayer(HLERequestContext& ctx) { | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         const auto name_buf = rp.PopRaw<std::array<u8, 0x40>>(); | ||||
|         const std::string display_name(Common::StringFromBuffer(name_buf)); | ||||
| 
 | ||||
|         const u64 layer_id = rp.Pop<u64>(); | ||||
|         const u64 aruid = rp.Pop<u64>(); | ||||
| 
 | ||||
|         LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}, aruid=0x{:016X}", layer_id, aruid); | ||||
| 
 | ||||
|         const auto display_id = nvnflinger.OpenDisplay(display_name); | ||||
|         if (!display_id) { | ||||
|             LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id); | ||||
|             IPC::ResponseBuilder rb{ctx, 2}; | ||||
|             rb.Push(ResultNotFound); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         const auto buffer_queue_id = nvnflinger.FindBufferQueueId(*display_id, layer_id); | ||||
|         if (!buffer_queue_id) { | ||||
|             LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id); | ||||
|             IPC::ResponseBuilder rb{ctx, 2}; | ||||
|             rb.Push(ResultNotFound); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         if (!nvnflinger.OpenLayer(layer_id)) { | ||||
|             LOG_WARNING(Service_VI, "Tried to open layer which was already open"); | ||||
|             IPC::ResponseBuilder rb{ctx, 2}; | ||||
|             rb.Push(ResultOperationFailed); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         android::OutputParcel parcel; | ||||
|         parcel.WriteInterface(NativeWindow{*buffer_queue_id}); | ||||
| 
 | ||||
|         const auto buffer_size = ctx.WriteBuffer(parcel.Serialize()); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 4}; | ||||
|         rb.Push(ResultSuccess); | ||||
|         rb.Push<u64>(buffer_size); | ||||
|     } | ||||
| 
 | ||||
|     void CloseLayer(HLERequestContext& ctx) { | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         const auto layer_id{rp.Pop<u64>()}; | ||||
| 
 | ||||
|         LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}", layer_id); | ||||
| 
 | ||||
|         if (!nvnflinger.CloseLayer(layer_id)) { | ||||
|             LOG_WARNING(Service_VI, "Tried to close layer which was not open"); | ||||
|             IPC::ResponseBuilder rb{ctx, 2}; | ||||
|             rb.Push(ResultOperationFailed); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ResultSuccess); | ||||
|     } | ||||
| 
 | ||||
|     void CreateStrayLayer(HLERequestContext& ctx) { | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         const u32 flags = rp.Pop<u32>(); | ||||
|         rp.Pop<u32>(); // padding
 | ||||
|         const u64 display_id = rp.Pop<u64>(); | ||||
| 
 | ||||
|         LOG_DEBUG(Service_VI, "called. flags=0x{:08X}, display_id=0x{:016X}", flags, display_id); | ||||
| 
 | ||||
|         // TODO(Subv): What's the difference between a Stray and a Managed layer?
 | ||||
| 
 | ||||
|         const auto layer_id = nvnflinger.CreateLayer(display_id); | ||||
|         if (!layer_id) { | ||||
|             LOG_ERROR(Service_VI, "Layer not found! display_id={}", display_id); | ||||
|             IPC::ResponseBuilder rb{ctx, 2}; | ||||
|             rb.Push(ResultNotFound); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         stray_layer_ids.push_back(*layer_id); | ||||
|         const auto buffer_queue_id = nvnflinger.FindBufferQueueId(display_id, *layer_id); | ||||
|         if (!buffer_queue_id) { | ||||
|             LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id); | ||||
|             IPC::ResponseBuilder rb{ctx, 2}; | ||||
|             rb.Push(ResultNotFound); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         android::OutputParcel parcel; | ||||
|         parcel.WriteInterface(NativeWindow{*buffer_queue_id}); | ||||
| 
 | ||||
|         const auto buffer_size = ctx.WriteBuffer(parcel.Serialize()); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 6}; | ||||
|         rb.Push(ResultSuccess); | ||||
|         rb.Push(*layer_id); | ||||
|         rb.Push<u64>(buffer_size); | ||||
|     } | ||||
| 
 | ||||
|     void DestroyStrayLayer(HLERequestContext& ctx) { | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         const u64 layer_id = rp.Pop<u64>(); | ||||
| 
 | ||||
|         LOG_WARNING(Service_VI, "(STUBBED) called. layer_id=0x{:016X}", layer_id); | ||||
|         nvnflinger.DestroyLayer(layer_id); | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ResultSuccess); | ||||
|     } | ||||
| 
 | ||||
|     void GetDisplayVsyncEvent(HLERequestContext& ctx) { | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         const u64 display_id = rp.Pop<u64>(); | ||||
| 
 | ||||
|         LOG_DEBUG(Service_VI, "called. display_id={}", display_id); | ||||
| 
 | ||||
|         Kernel::KReadableEvent* vsync_event{}; | ||||
|         const auto result = nvnflinger.FindVsyncEvent(&vsync_event, display_id); | ||||
|         if (result != ResultSuccess) { | ||||
|             if (result == ResultNotFound) { | ||||
|                 LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id); | ||||
|             } | ||||
| 
 | ||||
|             IPC::ResponseBuilder rb{ctx, 2}; | ||||
|             rb.Push(result); | ||||
|             return; | ||||
|         } | ||||
|         if (vsync_event_fetched) { | ||||
|             IPC::ResponseBuilder rb{ctx, 2}; | ||||
|             rb.Push(VI::ResultPermissionDenied); | ||||
|             return; | ||||
|         } | ||||
|         vsync_event_fetched = true; | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 2, 1}; | ||||
|         rb.Push(ResultSuccess); | ||||
|         rb.PushCopyObjects(vsync_event); | ||||
|     } | ||||
| 
 | ||||
|     void ConvertScalingMode(HLERequestContext& ctx) { | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         const auto mode = rp.PopEnum<NintendoScaleMode>(); | ||||
|         LOG_DEBUG(Service_VI, "called mode={}", mode); | ||||
| 
 | ||||
|         ConvertedScaleMode converted_mode{}; | ||||
|         const auto result = ConvertScalingModeImpl(&converted_mode, mode); | ||||
| 
 | ||||
|         if (result == ResultSuccess) { | ||||
|             IPC::ResponseBuilder rb{ctx, 4}; | ||||
|             rb.Push(ResultSuccess); | ||||
|             rb.PushEnum(converted_mode); | ||||
|         } else { | ||||
|             IPC::ResponseBuilder rb{ctx, 2}; | ||||
|             rb.Push(result); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     void GetIndirectLayerImageMap(HLERequestContext& ctx) { | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         const auto width = rp.Pop<s64>(); | ||||
|         const auto height = rp.Pop<s64>(); | ||||
|         const auto indirect_layer_consumer_handle = rp.Pop<u64>(); | ||||
|         const auto applet_resource_user_id = rp.Pop<u64>(); | ||||
| 
 | ||||
|         LOG_WARNING(Service_VI, | ||||
|                     "(STUBBED) called, width={}, height={}, indirect_layer_consumer_handle={}, " | ||||
|                     "applet_resource_user_id={}", | ||||
|                     width, height, indirect_layer_consumer_handle, applet_resource_user_id); | ||||
| 
 | ||||
|         std::vector<u8> out_buffer(0x46); | ||||
|         ctx.WriteBuffer(out_buffer); | ||||
| 
 | ||||
|         // TODO: Figure out what these are
 | ||||
| 
 | ||||
|         constexpr s64 unknown_result_1 = 0; | ||||
|         constexpr s64 unknown_result_2 = 0; | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 6}; | ||||
|         rb.Push(unknown_result_1); | ||||
|         rb.Push(unknown_result_2); | ||||
|         rb.Push(ResultSuccess); | ||||
|     } | ||||
| 
 | ||||
|     void GetIndirectLayerImageRequiredMemoryInfo(HLERequestContext& ctx) { | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         const auto width = rp.Pop<u64>(); | ||||
|         const auto height = rp.Pop<u64>(); | ||||
|         LOG_DEBUG(Service_VI, "called width={}, height={}", width, height); | ||||
| 
 | ||||
|         constexpr u64 base_size = 0x20000; | ||||
|         constexpr u64 alignment = 0x1000; | ||||
|         const auto texture_size = width * height * 4; | ||||
|         const auto out_size = (texture_size + base_size - 1) / base_size * base_size; | ||||
| 
 | ||||
|         IPC::ResponseBuilder rb{ctx, 6}; | ||||
|         rb.Push(ResultSuccess); | ||||
|         rb.Push(out_size); | ||||
|         rb.Push(alignment); | ||||
|     } | ||||
| 
 | ||||
|     static Result ConvertScalingModeImpl(ConvertedScaleMode* out_scaling_mode, | ||||
|                                          NintendoScaleMode mode) { | ||||
|         switch (mode) { | ||||
|         case NintendoScaleMode::None: | ||||
|             *out_scaling_mode = ConvertedScaleMode::None; | ||||
|             return ResultSuccess; | ||||
|         case NintendoScaleMode::Freeze: | ||||
|             *out_scaling_mode = ConvertedScaleMode::Freeze; | ||||
|             return ResultSuccess; | ||||
|         case NintendoScaleMode::ScaleToWindow: | ||||
|             *out_scaling_mode = ConvertedScaleMode::ScaleToWindow; | ||||
|             return ResultSuccess; | ||||
|         case NintendoScaleMode::ScaleAndCrop: | ||||
|             *out_scaling_mode = ConvertedScaleMode::ScaleAndCrop; | ||||
|             return ResultSuccess; | ||||
|         case NintendoScaleMode::PreserveAspectRatio: | ||||
|             *out_scaling_mode = ConvertedScaleMode::PreserveAspectRatio; | ||||
|             return ResultSuccess; | ||||
|         default: | ||||
|             LOG_ERROR(Service_VI, "Invalid scaling mode specified, mode={}", mode); | ||||
|             return ResultOperationFailed; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     Nvnflinger::Nvnflinger& nvnflinger; | ||||
|     Nvnflinger::HosBinderDriverServer& hos_binder_driver_server; | ||||
|     std::vector<u64> stray_layer_ids; | ||||
|     bool vsync_event_fetched{false}; | ||||
| }; | ||||
| 
 | ||||
| static bool IsValidServiceAccess(Permission permission, Policy policy) { | ||||
|     if (permission == Permission::User) { | ||||
|         return policy == Policy::User; | ||||
| @ -921,12 +48,12 @@ void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nvnflinger, | ||||
|                  Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) { | ||||
|     auto server_manager = std::make_unique<ServerManager>(system); | ||||
| 
 | ||||
|     server_manager->RegisterNamedService("vi:m", std::make_shared<IManagerRootService>( | ||||
|                                                      system, nvnflinger, hos_binder_driver_server)); | ||||
|     server_manager->RegisterNamedService( | ||||
|         "vi:m", std::make_shared<VI_M>(system, nvnflinger, hos_binder_driver_server)); | ||||
|     server_manager->RegisterNamedService( | ||||
|         "vi:s", std::make_shared<VI_S>(system, nvnflinger, hos_binder_driver_server)); | ||||
|     server_manager->RegisterNamedService( | ||||
|         "vi:u", std::make_shared<VI_U>(system, nvnflinger, hos_binder_driver_server)); | ||||
|         "vi:s", std::make_shared<ISystemRootService>(system, nvnflinger, hos_binder_driver_server)); | ||||
|     server_manager->RegisterNamedService("vi:u", std::make_shared<IApplicationRootService>( | ||||
|                                                      system, nvnflinger, hos_binder_driver_server)); | ||||
|     ServerManager::RunServer(std::move(server_manager)); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -3,8 +3,6 @@ | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include "common/common_types.h" | ||||
| 
 | ||||
| namespace Core { | ||||
| class System; | ||||
| } | ||||
|  | ||||
| @ -28,6 +28,22 @@ enum class Policy { | ||||
|     Compositor, | ||||
| }; | ||||
| 
 | ||||
| enum class ConvertedScaleMode : u64 { | ||||
|     Freeze = 0, | ||||
|     ScaleToWindow = 1, | ||||
|     ScaleAndCrop = 2, | ||||
|     None = 3, | ||||
|     PreserveAspectRatio = 4, | ||||
| }; | ||||
| 
 | ||||
| enum class NintendoScaleMode : u32 { | ||||
|     None = 0, | ||||
|     Freeze = 1, | ||||
|     ScaleToWindow = 2, | ||||
|     ScaleAndCrop = 3, | ||||
|     PreserveAspectRatio = 4, | ||||
| }; | ||||
| 
 | ||||
| struct DisplayInfo { | ||||
|     /// The name of this particular display.
 | ||||
|     char display_name[0x40]{"Default"}; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user