Merge pull request #55 from bunnei/subv-improvements
Improvements to IPC, AppletOE, APM, VI, SVC
This commit is contained in:
		| @@ -48,8 +48,8 @@ set(SRCS | ||||
|             hle/service/nvdrv/devices/nvdisp_disp0.cpp | ||||
|             hle/service/nvdrv/devices/nvhost_as_gpu.cpp | ||||
|             hle/service/nvdrv/devices/nvmap.cpp | ||||
|             hle/service/nvdrv/interface.cpp | ||||
|             hle/service/nvdrv/nvdrv.cpp | ||||
|             hle/service/nvdrv/nvdrv_a.cpp | ||||
|             hle/service/pctl/pctl.cpp | ||||
|             hle/service/pctl/pctl_a.cpp | ||||
|             hle/service/service.cpp | ||||
| @@ -136,8 +136,8 @@ set(HEADERS | ||||
|             hle/service/nvdrv/devices/nvdisp_disp0.h | ||||
|             hle/service/nvdrv/devices/nvhost_as_gpu.h | ||||
|             hle/service/nvdrv/devices/nvmap.h | ||||
|             hle/service/nvdrv/interface.h | ||||
|             hle/service/nvdrv/nvdrv.h | ||||
|             hle/service/nvdrv/nvdrv_a.h | ||||
|             hle/service/pctl/pctl.h | ||||
|             hle/service/pctl/pctl_a.h | ||||
|             hle/service/service.h | ||||
|   | ||||
| @@ -9,10 +9,13 @@ | ||||
| #include <type_traits> | ||||
| #include <utility> | ||||
| #include "core/hle/ipc.h" | ||||
| #include "core/hle/kernel/client_port.h" | ||||
| #include "core/hle/kernel/client_session.h" | ||||
| #include "core/hle/kernel/domain.h" | ||||
| #include "core/hle/kernel/handle_table.h" | ||||
| #include "core/hle/kernel/hle_ipc.h" | ||||
| #include "core/hle/kernel/kernel.h" | ||||
| #include "core/hle/kernel/server_port.h" | ||||
|  | ||||
| namespace IPC { | ||||
|  | ||||
| @@ -63,13 +66,20 @@ public: | ||||
|         : RequestHelperBase(context) { | ||||
|         memset(cmdbuf, 0, sizeof(u32) * IPC::COMMAND_BUFFER_LENGTH); | ||||
|  | ||||
|         context.ClearIncomingObjects(); | ||||
|  | ||||
|         IPC::CommandHeader header{}; | ||||
|  | ||||
|         // The entire size of the raw data section in u32 units, including the 16 bytes of mandatory | ||||
|         // padding. | ||||
|         u32 raw_data_size = sizeof(IPC::DataPayloadHeader) / 4 + 4 + normal_params_size; | ||||
|         if (context.IsDomain()) | ||||
|         if (context.IsDomain()) { | ||||
|             raw_data_size += sizeof(DomainMessageHeader) / 4 + num_domain_objects; | ||||
|         } else { | ||||
|             // If we're not in a domain, turn the domain object parameters into move handles. | ||||
|             num_handles_to_move += num_domain_objects; | ||||
|             num_domain_objects = 0; | ||||
|         } | ||||
|  | ||||
|         header.data_size.Assign(raw_data_size); | ||||
|         if (num_handles_to_copy || num_handles_to_move) { | ||||
| @@ -100,7 +110,15 @@ public: | ||||
|  | ||||
|     template <class T, class... Args> | ||||
|     void PushIpcInterface(Args&&... args) { | ||||
|         context->AddDomainObject(std::make_shared<T>(std::forward<Args>(args)...)); | ||||
|         auto iface = std::make_shared<T>(std::forward<Args>(args)...); | ||||
|         if (context->IsDomain()) { | ||||
|             context->AddDomainObject(std::move(iface)); | ||||
|         } else { | ||||
|             auto port = iface->CreatePort(); | ||||
|             auto session = port->Connect(); | ||||
|             ASSERT(session.Succeeded()); | ||||
|             context->AddMoveObject(std::move(session).Unwrap()); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // Validate on destruction, as there shouldn't be any case where we don't want it | ||||
|   | ||||
| @@ -175,6 +175,14 @@ public: | ||||
|         domain_objects.emplace_back(std::move(object)); | ||||
|     } | ||||
|  | ||||
|     /// Clears the list of objects so that no lingering objects are written accidentally to the | ||||
|     /// response buffer. | ||||
|     void ClearIncomingObjects() { | ||||
|         move_objects.clear(); | ||||
|         copy_objects.clear(); | ||||
|         domain_objects.clear(); | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     std::array<u32, IPC::COMMAND_BUFFER_LENGTH> cmd_buf; | ||||
|     SharedPtr<Kernel::Domain> domain; | ||||
|   | ||||
| @@ -255,7 +255,8 @@ static ResultCode CancelSynchronization(Handle thread_handle) { | ||||
| /// Attempts to locks a mutex, creating it if it does not already exist | ||||
| static ResultCode LockMutex(Handle holding_thread_handle, VAddr mutex_addr, | ||||
|                             Handle requesting_thread_handle) { | ||||
|     LOG_TRACE(Kernel_SVC, "called holding_thread_handle=0x%08X, mutex_addr=0x%llx, " | ||||
|     LOG_TRACE(Kernel_SVC, | ||||
|               "called holding_thread_handle=0x%08X, mutex_addr=0x%llx, " | ||||
|               "requesting_current_thread_handle=0x%08X", | ||||
|               holding_thread_handle, mutex_addr, requesting_thread_handle); | ||||
|  | ||||
| @@ -304,8 +305,6 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id) | ||||
|     LOG_TRACE(Kernel_SVC, "called info_id=0x%X, info_sub_id=0x%X, handle=0x%08X", info_id, | ||||
|               info_sub_id, handle); | ||||
|  | ||||
|     ASSERT(handle == 0 || handle == CurrentProcess); | ||||
|  | ||||
|     auto& vm_manager = g_current_process->vm_manager; | ||||
|  | ||||
|     switch (static_cast<GetInfoType>(info_id)) { | ||||
| @@ -321,6 +320,12 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id) | ||||
|     case GetInfoType::MapRegionSize: | ||||
|         *result = vm_manager.GetAddressSpaceSize(); | ||||
|         break; | ||||
|     case GetInfoType::HeapRegionBaseAddr: | ||||
|         *result = vm_manager.GetNewMapRegionBaseAddr() + vm_manager.GetNewMapRegionSize(); | ||||
|         break; | ||||
|     case GetInfoType::HeapRegionSize: | ||||
|         *result = Memory::HEAP_SIZE; | ||||
|         break; | ||||
|     case GetInfoType::TotalMemoryUsage: | ||||
|         *result = vm_manager.GetTotalMemoryUsage(); | ||||
|         break; | ||||
| @@ -345,6 +350,15 @@ static ResultCode GetInfo(u64* result, u64 info_id, u64 handle, u64 info_sub_id) | ||||
|     case GetInfoType::IsVirtualAddressMemoryEnabled: | ||||
|         *result = g_current_process->is_virtual_address_memory_enabled; | ||||
|         break; | ||||
|     case GetInfoType::TitleId: | ||||
|         LOG_WARNING(Kernel_SVC, "(STUBBED) Attempted to query titleid, returned 0"); | ||||
|         *result = 0; | ||||
|         break; | ||||
|     case GetInfoType::PrivilegedProcessId: | ||||
|         LOG_WARNING(Kernel_SVC, | ||||
|                     "(STUBBED) Attempted to query priviledged process id bounds, returned 0"); | ||||
|         *result = 0; | ||||
|         break; | ||||
|     default: | ||||
|         UNIMPLEMENTED(); | ||||
|     } | ||||
| @@ -533,7 +547,8 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V | ||||
|  | ||||
|     Core::System::GetInstance().PrepareReschedule(); | ||||
|  | ||||
|     LOG_TRACE(Kernel_SVC, "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, " | ||||
|     LOG_TRACE(Kernel_SVC, | ||||
|               "called entrypoint=0x%08X (%s), arg=0x%08X, stacktop=0x%08X, " | ||||
|               "threadpriority=0x%08X, processorid=0x%08X : created handle=0x%08X", | ||||
|               entry_point, name.c_str(), arg, stack_top, priority, processor_id, *out_handle); | ||||
|  | ||||
|   | ||||
| @@ -44,6 +44,7 @@ enum class GetInfoType : u64 { | ||||
|     // 3.0.0+ | ||||
|     IsVirtualAddressMemoryEnabled = 16, | ||||
|     TitleId = 18, | ||||
|     // 4.0.0+ | ||||
|     PrivilegedProcessId = 19, | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -6,6 +6,7 @@ | ||||
| #include "core/hle/ipc_helpers.h" | ||||
| #include "core/hle/kernel/event.h" | ||||
| #include "core/hle/service/am/applet_oe.h" | ||||
| #include "core/hle/service/apm/apm.h" | ||||
|  | ||||
| namespace Service { | ||||
| namespace AM { | ||||
| @@ -71,6 +72,15 @@ private: | ||||
|         // Takes 3 input u8s with each field located immediately after the previous u8, these are | ||||
|         // bool flags. No output. | ||||
|  | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|  | ||||
|         struct FocusHandlingModeParams { | ||||
|             u8 unknown0; | ||||
|             u8 unknown1; | ||||
|             u8 unknown2; | ||||
|         }; | ||||
|         auto flags = rp.PopRaw<FocusHandlingModeParams>(); | ||||
|  | ||||
|         IPC::RequestBuilder rb{ctx, 2}; | ||||
|         rb.Push(RESULT_SUCCESS); | ||||
|  | ||||
| @@ -85,27 +95,38 @@ private: | ||||
|     } | ||||
|  | ||||
|     void SetPerformanceModeChangedNotification(Kernel::HLERequestContext& ctx) { | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|  | ||||
|         bool flag = rp.Pop<bool>(); | ||||
|  | ||||
|         IPC::RequestBuilder rb{ctx, 2}; | ||||
|         rb.Push(RESULT_SUCCESS); | ||||
|  | ||||
|         LOG_WARNING(Service, "(STUBBED) called"); | ||||
|         LOG_WARNING(Service, "(STUBBED) called flag=%u", static_cast<u32>(flag)); | ||||
|     } | ||||
|  | ||||
|     void SetOperationModeChangedNotification(Kernel::HLERequestContext& ctx) { | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|  | ||||
|         bool flag = rp.Pop<bool>(); | ||||
|  | ||||
|         IPC::RequestBuilder rb{ctx, 2}; | ||||
|         rb.Push(RESULT_SUCCESS); | ||||
|  | ||||
|         LOG_WARNING(Service, "(STUBBED) called"); | ||||
|         LOG_WARNING(Service, "(STUBBED) called flag=%u", static_cast<u32>(flag)); | ||||
|     } | ||||
|  | ||||
|     void SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx) { | ||||
|         // Takes 3 input u8s with each field located immediately after the previous u8, these are | ||||
|         // bool flags. No output. | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|  | ||||
|         bool enabled = rp.Pop<bool>(); | ||||
|  | ||||
|         IPC::RequestBuilder rb{ctx, 2}; | ||||
|         rb.Push(RESULT_SUCCESS); | ||||
|  | ||||
|         LOG_WARNING(Service, "(STUBBED) called"); | ||||
|         LOG_WARNING(Service, "(STUBBED) called enabled=%u", static_cast<u32>(enabled)); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| @@ -115,6 +136,8 @@ public: | ||||
|         static const FunctionInfo functions[] = { | ||||
|             {0, &ICommonStateGetter::GetEventHandle, "GetEventHandle"}, | ||||
|             {1, &ICommonStateGetter::ReceiveMessage, "ReceiveMessage"}, | ||||
|             {5, &ICommonStateGetter::GetOperationMode, "GetOperationMode"}, | ||||
|             {6, &ICommonStateGetter::GetPerformanceMode, "GetPerformanceMode"}, | ||||
|             {9, &ICommonStateGetter::GetCurrentFocusState, "GetCurrentFocusState"}, | ||||
|         }; | ||||
|         RegisterHandlers(functions); | ||||
| @@ -123,6 +146,16 @@ public: | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     enum class FocusState : u8 { | ||||
|         InFocus = 1, | ||||
|         NotInFocus = 2, | ||||
|     }; | ||||
|  | ||||
|     enum class OperationMode : u8 { | ||||
|         Handheld = 0, | ||||
|         Docked = 1, | ||||
|     }; | ||||
|  | ||||
|     void GetEventHandle(Kernel::HLERequestContext& ctx) { | ||||
|         event->Signal(); | ||||
|  | ||||
| @@ -144,7 +177,23 @@ private: | ||||
|     void GetCurrentFocusState(Kernel::HLERequestContext& ctx) { | ||||
|         IPC::RequestBuilder rb{ctx, 3}; | ||||
|         rb.Push(RESULT_SUCCESS); | ||||
|         rb.Push<u32>(1); // 1: In focus, 2/3: Out of focus(running in "background") | ||||
|         rb.Push(static_cast<u8>(FocusState::InFocus)); | ||||
|  | ||||
|         LOG_WARNING(Service, "(STUBBED) called"); | ||||
|     } | ||||
|  | ||||
|     void GetOperationMode(Kernel::HLERequestContext& ctx) { | ||||
|         IPC::RequestBuilder rb{ctx, 3}; | ||||
|         rb.Push(RESULT_SUCCESS); | ||||
|         rb.Push(static_cast<u8>(OperationMode::Handheld)); | ||||
|  | ||||
|         LOG_WARNING(Service, "(STUBBED) called"); | ||||
|     } | ||||
|  | ||||
|     void GetPerformanceMode(Kernel::HLERequestContext& ctx) { | ||||
|         IPC::RequestBuilder rb{ctx, 3}; | ||||
|         rb.Push(RESULT_SUCCESS); | ||||
|         rb.Push(static_cast<u32>(APM::PerformanceMode::Handheld)); | ||||
|  | ||||
|         LOG_WARNING(Service, "(STUBBED) called"); | ||||
|     } | ||||
| @@ -160,6 +209,7 @@ public: | ||||
|             {66, &IApplicationFunctions::InitializeGamePlayRecording, | ||||
|              "InitializeGamePlayRecording"}, | ||||
|             {67, &IApplicationFunctions::SetGamePlayRecordingState, "SetGamePlayRecordingState"}, | ||||
|             {40, &IApplicationFunctions::NotifyRunning, "NotifyRunning"}, | ||||
|         }; | ||||
|         RegisterHandlers(functions); | ||||
|     } | ||||
| @@ -187,6 +237,15 @@ private: | ||||
|     void SetGamePlayRecordingState(Kernel::HLERequestContext& ctx) { | ||||
|         IPC::RequestBuilder rb{ctx, 2}; | ||||
|         rb.Push(RESULT_SUCCESS); | ||||
|  | ||||
|         LOG_WARNING(Service, "(STUBBED) called"); | ||||
|     } | ||||
|  | ||||
|     void NotifyRunning(Kernel::HLERequestContext& ctx) { | ||||
|         IPC::RequestBuilder rb{ctx, 3}; | ||||
|         rb.Push(RESULT_SUCCESS); | ||||
|         rb.Push<u8>(0); // Unknown, seems to be ignored by official processes | ||||
|  | ||||
|         LOG_WARNING(Service, "(STUBBED) called"); | ||||
|     } | ||||
| }; | ||||
|   | ||||
| @@ -13,12 +13,54 @@ void InstallInterfaces(SM::ServiceManager& service_manager) { | ||||
|     std::make_shared<APM>()->InstallAsService(service_manager); | ||||
| } | ||||
|  | ||||
| APM::APM() : ServiceFramework("apm") { | ||||
| class ISession final : public ServiceFramework<ISession> { | ||||
| public: | ||||
|     ISession() : ServiceFramework("ISession") { | ||||
|         static const FunctionInfo functions[] = { | ||||
|         {0x00000000, nullptr, "OpenSession"}, {0x00000001, nullptr, "GetPerformanceMode"}, | ||||
|             {0, &ISession::SetPerformanceConfiguration, "SetPerformanceConfiguration"}, | ||||
|             {1, &ISession::GetPerformanceConfiguration, "GetPerformanceConfiguration"}, | ||||
|         }; | ||||
|         RegisterHandlers(functions); | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     void SetPerformanceConfiguration(Kernel::HLERequestContext& ctx) { | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|  | ||||
|         auto mode = static_cast<PerformanceMode>(rp.Pop<u32>()); | ||||
|         u32 config = rp.Pop<u32>(); | ||||
|  | ||||
|         IPC::RequestBuilder rb{ctx, 2}; | ||||
|         rb.Push(RESULT_SUCCESS); | ||||
|  | ||||
|         LOG_WARNING(Service, "(STUBBED) called mode=%u config=%u", static_cast<u32>(mode), config); | ||||
|     } | ||||
|  | ||||
|     void GetPerformanceConfiguration(Kernel::HLERequestContext& ctx) { | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|  | ||||
|         auto mode = static_cast<PerformanceMode>(rp.Pop<u32>()); | ||||
|  | ||||
|         IPC::RequestBuilder rb{ctx, 3}; | ||||
|         rb.Push(RESULT_SUCCESS); | ||||
|         rb.Push<u32>(0); // Performance configuration | ||||
|  | ||||
|         LOG_WARNING(Service, "(STUBBED) called mode=%u", static_cast<u32>(mode)); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| APM::APM() : ServiceFramework("apm") { | ||||
|     static const FunctionInfo functions[] = { | ||||
|         {0x00000000, &APM::OpenSession, "OpenSession"}, {0x00000001, nullptr, "GetPerformanceMode"}, | ||||
|     }; | ||||
|     RegisterHandlers(functions); | ||||
| } | ||||
|  | ||||
| void APM::OpenSession(Kernel::HLERequestContext& ctx) { | ||||
|     IPC::RequestBuilder rb{ctx, 2, 0, 0, 1}; | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
|     rb.PushIpcInterface<ISession>(); | ||||
| } | ||||
|  | ||||
| } // namespace APM | ||||
| } // namespace Service | ||||
|   | ||||
| @@ -9,10 +9,18 @@ | ||||
| namespace Service { | ||||
| namespace APM { | ||||
|  | ||||
| enum class PerformanceMode : u8 { | ||||
|     Handheld = 0, | ||||
|     Docked = 1, | ||||
| }; | ||||
|  | ||||
| class APM final : public ServiceFramework<APM> { | ||||
| public: | ||||
|     APM(); | ||||
|     ~APM() = default; | ||||
|  | ||||
| private: | ||||
|     void OpenSession(Kernel::HLERequestContext& ctx); | ||||
| }; | ||||
|  | ||||
| /// Registers all AM services with the specified service manager. | ||||
|   | ||||
| @@ -8,7 +8,7 @@ | ||||
| #include "common/common_types.h" | ||||
|  | ||||
| namespace Service { | ||||
| namespace NVDRV { | ||||
| namespace Nvidia { | ||||
| namespace Devices { | ||||
|  | ||||
| /// Represents an abstract nvidia device node. It is to be subclassed by concrete device nodes to | ||||
| @@ -29,5 +29,5 @@ public: | ||||
| }; | ||||
|  | ||||
| } // namespace Devices | ||||
| } // namespace NVDRV | ||||
| } // namespace Nvidia | ||||
| } // namespace Service | ||||
|   | ||||
| @@ -10,7 +10,7 @@ | ||||
| #include "video_core/video_core.h" | ||||
|  | ||||
| namespace Service { | ||||
| namespace NVDRV { | ||||
| namespace Nvidia { | ||||
| namespace Devices { | ||||
|  | ||||
| u32 nvdisp_disp0::ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) { | ||||
| @@ -32,5 +32,5 @@ void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u3 | ||||
| } | ||||
|  | ||||
| } // namespace Devices | ||||
| } // namespace NVDRV | ||||
| } // namespace Nvidia | ||||
| } // namespace Service | ||||
|   | ||||
| @@ -10,7 +10,7 @@ | ||||
| #include "core/hle/service/nvdrv/devices/nvdevice.h" | ||||
|  | ||||
| namespace Service { | ||||
| namespace NVDRV { | ||||
| namespace Nvidia { | ||||
| namespace Devices { | ||||
|  | ||||
| class nvmap; | ||||
| @@ -30,5 +30,5 @@ private: | ||||
| }; | ||||
|  | ||||
| } // namespace Devices | ||||
| } // namespace NVDRV | ||||
| } // namespace Nvidia | ||||
| } // namespace Service | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
| #include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h" | ||||
|  | ||||
| namespace Service { | ||||
| namespace NVDRV { | ||||
| namespace Nvidia { | ||||
| namespace Devices { | ||||
|  | ||||
| u32 nvhost_as_gpu::ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) { | ||||
| @@ -16,5 +16,5 @@ u32 nvhost_as_gpu::ioctl(u32 command, const std::vector<u8>& input, std::vector< | ||||
| } | ||||
|  | ||||
| } // namespace Devices | ||||
| } // namespace NVDRV | ||||
| } // namespace Nvidia | ||||
| } // namespace Service | ||||
|   | ||||
| @@ -9,7 +9,7 @@ | ||||
| #include "core/hle/service/nvdrv/devices/nvdevice.h" | ||||
|  | ||||
| namespace Service { | ||||
| namespace NVDRV { | ||||
| namespace Nvidia { | ||||
| namespace Devices { | ||||
|  | ||||
| class nvhost_as_gpu final : public nvdevice { | ||||
| @@ -21,5 +21,5 @@ public: | ||||
| }; | ||||
|  | ||||
| } // namespace Devices | ||||
| } // namespace NVDRV | ||||
| } // namespace Nvidia | ||||
| } // namespace Service | ||||
|   | ||||
| @@ -9,7 +9,7 @@ | ||||
| #include "core/hle/service/nvdrv/devices/nvmap.h" | ||||
|  | ||||
| namespace Service { | ||||
| namespace NVDRV { | ||||
| namespace Nvidia { | ||||
| namespace Devices { | ||||
|  | ||||
| VAddr nvmap::GetObjectAddress(u32 handle) const { | ||||
| @@ -151,5 +151,5 @@ u32 nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output) { | ||||
| } | ||||
|  | ||||
| } // namespace Devices | ||||
| } // namespace NVDRV | ||||
| } // namespace Nvidia | ||||
| } // namespace Service | ||||
|   | ||||
| @@ -13,7 +13,7 @@ | ||||
| #include "core/hle/service/nvdrv/devices/nvdevice.h" | ||||
|  | ||||
| namespace Service { | ||||
| namespace NVDRV { | ||||
| namespace Nvidia { | ||||
| namespace Devices { | ||||
|  | ||||
| class nvmap final : public nvdevice { | ||||
| @@ -104,5 +104,5 @@ private: | ||||
| }; | ||||
|  | ||||
| } // namespace Devices | ||||
| } // namespace NVDRV | ||||
| } // namespace Nvidia | ||||
| } // namespace Service | ||||
|   | ||||
| @@ -4,35 +4,27 @@ | ||||
| 
 | ||||
| #include "common/logging/log.h" | ||||
| #include "core/hle/ipc_helpers.h" | ||||
| #include "core/hle/service/nvdrv/devices/nvdevice.h" | ||||
| #include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" | ||||
| #include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h" | ||||
| #include "core/hle/service/nvdrv/devices/nvmap.h" | ||||
| #include "core/hle/service/nvdrv/interface.h" | ||||
| #include "core/hle/service/nvdrv/nvdrv.h" | ||||
| #include "core/hle/service/nvdrv/nvdrv_a.h" | ||||
| 
 | ||||
| namespace Service { | ||||
| namespace NVDRV { | ||||
| namespace Nvidia { | ||||
| 
 | ||||
| void NVDRV_A::Open(Kernel::HLERequestContext& ctx) { | ||||
| void NVDRV::Open(Kernel::HLERequestContext& ctx) { | ||||
|     LOG_WARNING(Service, "(STUBBED) called"); | ||||
| 
 | ||||
|     auto buffer = ctx.BufferDescriptorA()[0]; | ||||
| 
 | ||||
|     std::string device_name = Memory::ReadCString(buffer.Address(), buffer.Size()); | ||||
| 
 | ||||
|     auto device = devices[device_name]; | ||||
|     u32 fd = next_fd++; | ||||
| 
 | ||||
|     open_files[fd] = device; | ||||
| 
 | ||||
|     u32 fd = nvdrv->Open(device_name); | ||||
|     IPC::RequestBuilder rb{ctx, 4}; | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
|     rb.Push<u32>(fd); | ||||
|     rb.Push<u32>(0); | ||||
| } | ||||
| 
 | ||||
| void NVDRV_A::Ioctl(Kernel::HLERequestContext& ctx) { | ||||
| void NVDRV::Ioctl(Kernel::HLERequestContext& ctx) { | ||||
|     LOG_WARNING(Service, "(STUBBED) called"); | ||||
| 
 | ||||
|     IPC::RequestParser rp{ctx}; | ||||
| @@ -46,11 +38,8 @@ void NVDRV_A::Ioctl(Kernel::HLERequestContext& ctx) { | ||||
|     std::vector<u8> output(output_buffer.Size()); | ||||
| 
 | ||||
|     Memory::ReadBlock(input_buffer.Address(), input.data(), input_buffer.Size()); | ||||
|     auto itr = open_files.find(fd); | ||||
|     ASSERT_MSG(itr != open_files.end(), "Tried to talk to an invalid device"); | ||||
| 
 | ||||
|     auto device = itr->second; | ||||
|     u32 nv_result = device->ioctl(command, input, output); | ||||
|     u32 nv_result = nvdrv->Ioctl(fd, command, input, output); | ||||
| 
 | ||||
|     Memory::WriteBlock(output_buffer.Address(), output.data(), output_buffer.Size()); | ||||
| 
 | ||||
| @@ -59,26 +48,22 @@ void NVDRV_A::Ioctl(Kernel::HLERequestContext& ctx) { | ||||
|     rb.Push(nv_result); | ||||
| } | ||||
| 
 | ||||
| void NVDRV_A::Initialize(Kernel::HLERequestContext& ctx) { | ||||
| void NVDRV::Initialize(Kernel::HLERequestContext& ctx) { | ||||
|     LOG_WARNING(Service, "(STUBBED) called"); | ||||
|     IPC::RequestBuilder rb{ctx, 3}; | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
|     rb.Push<u32>(0); | ||||
| } | ||||
| 
 | ||||
| NVDRV_A::NVDRV_A() : ServiceFramework("nvdrv:a") { | ||||
| NVDRV::NVDRV(std::shared_ptr<Module> nvdrv, const char* name) | ||||
|     : ServiceFramework(name), nvdrv(std::move(nvdrv)) { | ||||
|     static const FunctionInfo functions[] = { | ||||
|         {0, &NVDRV_A::Open, "Open"}, | ||||
|         {1, &NVDRV_A::Ioctl, "Ioctl"}, | ||||
|         {3, &NVDRV_A::Initialize, "Initialize"}, | ||||
|         {0, &NVDRV::Open, "Open"}, | ||||
|         {1, &NVDRV::Ioctl, "Ioctl"}, | ||||
|         {3, &NVDRV::Initialize, "Initialize"}, | ||||
|     }; | ||||
|     RegisterHandlers(functions); | ||||
| 
 | ||||
|     auto nvmap_dev = std::make_shared<Devices::nvmap>(); | ||||
|     devices["/dev/nvhost-as-gpu"] = std::make_shared<Devices::nvhost_as_gpu>(); | ||||
|     devices["/dev/nvmap"] = nvmap_dev; | ||||
|     devices["/dev/nvdisp_disp0"] = std::make_shared<Devices::nvdisp_disp0>(nvmap_dev); | ||||
| } | ||||
| 
 | ||||
| } // namespace NVDRV
 | ||||
| } // namespace Nvidia
 | ||||
| } // namespace Service
 | ||||
							
								
								
									
										29
									
								
								src/core/hle/service/nvdrv/interface.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/core/hle/service/nvdrv/interface.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| // Copyright 2018 yuzu emulator team | ||||
| // Licensed under GPLv2 or any later version | ||||
| // Refer to the license.txt file included. | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <memory> | ||||
| #include <string> | ||||
| #include "core/hle/service/nvdrv/nvdrv.h" | ||||
| #include "core/hle/service/service.h" | ||||
|  | ||||
| namespace Service { | ||||
| namespace Nvidia { | ||||
|  | ||||
| class NVDRV final : public ServiceFramework<NVDRV> { | ||||
| public: | ||||
|     NVDRV(std::shared_ptr<Module> nvdrv, const char* name); | ||||
|     ~NVDRV() = default; | ||||
|  | ||||
| private: | ||||
|     void Open(Kernel::HLERequestContext& ctx); | ||||
|     void Ioctl(Kernel::HLERequestContext& ctx); | ||||
|     void Initialize(Kernel::HLERequestContext& ctx); | ||||
|  | ||||
|     std::shared_ptr<Module> nvdrv; | ||||
| }; | ||||
|  | ||||
| } // namespace Nvidia | ||||
| } // namespace Service | ||||
| @@ -2,19 +2,52 @@ | ||||
| // Licensed under GPLv2 or any later version | ||||
| // Refer to the license.txt file included. | ||||
|  | ||||
| #include "core/hle/ipc_helpers.h" | ||||
| #include "core/hle/service/nvdrv/devices/nvdevice.h" | ||||
| #include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" | ||||
| #include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h" | ||||
| #include "core/hle/service/nvdrv/devices/nvmap.h" | ||||
| #include "core/hle/service/nvdrv/nvdrv.h" | ||||
| #include "core/hle/service/nvdrv/nvdrv_a.h" | ||||
| #include "core/hle/service/nvdrv/interface.h" | ||||
|  | ||||
| namespace Service { | ||||
| namespace NVDRV { | ||||
| namespace Nvidia { | ||||
|  | ||||
| std::weak_ptr<NVDRV_A> nvdrv_a; | ||||
| std::weak_ptr<Module> nvdrv; | ||||
|  | ||||
| void InstallInterfaces(SM::ServiceManager& service_manager) { | ||||
|     auto nvdrv = std::make_shared<NVDRV_A>(); | ||||
|     nvdrv->InstallAsService(service_manager); | ||||
|     nvdrv_a = nvdrv; | ||||
|     auto module_ = std::make_shared<Module>(); | ||||
|     std::make_shared<NVDRV>(module_, "nvdrv")->InstallAsService(service_manager); | ||||
|     std::make_shared<NVDRV>(module_, "nvdrv:a")->InstallAsService(service_manager); | ||||
|     nvdrv = module_; | ||||
| } | ||||
|  | ||||
| } // namespace NVDRV | ||||
| Module::Module() { | ||||
|     auto nvmap_dev = std::make_shared<Devices::nvmap>(); | ||||
|     devices["/dev/nvhost-as-gpu"] = std::make_shared<Devices::nvhost_as_gpu>(); | ||||
|     devices["/dev/nvmap"] = nvmap_dev; | ||||
|     devices["/dev/nvdisp_disp0"] = std::make_shared<Devices::nvdisp_disp0>(nvmap_dev); | ||||
| } | ||||
|  | ||||
| u32 Module::Open(std::string device_name) { | ||||
|     ASSERT_MSG(devices.find(device_name) != devices.end(), "Trying to open unknown device %s", | ||||
|                device_name.c_str()); | ||||
|  | ||||
|     auto device = devices[device_name]; | ||||
|     u32 fd = next_fd++; | ||||
|  | ||||
|     open_files[fd] = device; | ||||
|  | ||||
|     return fd; | ||||
| } | ||||
|  | ||||
| u32 Module::Ioctl(u32 fd, u32 command, const std::vector<u8>& input, std::vector<u8>& output) { | ||||
|     auto itr = open_files.find(fd); | ||||
|     ASSERT_MSG(itr != open_files.end(), "Tried to talk to an invalid device"); | ||||
|  | ||||
|     auto device = itr->second; | ||||
|     return device->ioctl(command, input, output); | ||||
| } | ||||
|  | ||||
| } // namespace Nvidia | ||||
| } // namespace Service | ||||
|   | ||||
| @@ -11,110 +11,46 @@ | ||||
| #include "core/hle/service/service.h" | ||||
|  | ||||
| namespace Service { | ||||
| namespace NVDRV { | ||||
| namespace Nvidia { | ||||
|  | ||||
| class nvdevice { | ||||
| namespace Devices { | ||||
| class nvdevice; | ||||
| } | ||||
|  | ||||
| class Module final { | ||||
| public: | ||||
|     virtual ~nvdevice() = default; | ||||
|     Module(); | ||||
|     ~Module() = default; | ||||
|  | ||||
|     virtual u32 ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) = 0; | ||||
| }; | ||||
|     /// Returns a pointer to one of the available devices, identified by its name. | ||||
|     template <typename T> | ||||
|     std::shared_ptr<T> GetDevice(std::string name) { | ||||
|         auto itr = devices.find(name); | ||||
|         if (itr == devices.end()) | ||||
|             return nullptr; | ||||
|         return std::static_pointer_cast<T>(itr->second); | ||||
|     } | ||||
|  | ||||
| class nvmap : public nvdevice { | ||||
| public: | ||||
|     /// Returns the allocated address of an nvmap object given its handle. | ||||
|     VAddr GetObjectAddress(u32 handle) const; | ||||
|  | ||||
|     u32 ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) override; | ||||
|     /// Opens a device node and returns a file descriptor to it. | ||||
|     u32 Open(std::string device_name); | ||||
|     /// Sends an ioctl command to the specified file descriptor. | ||||
|     u32 Ioctl(u32 fd, u32 command, const std::vector<u8>& input, std::vector<u8>& output); | ||||
|  | ||||
| private: | ||||
|     // Represents an nvmap object. | ||||
|     struct Object { | ||||
|         enum class Status { Created, Allocated }; | ||||
|         u32 id; | ||||
|         u32 size; | ||||
|         u32 flags; | ||||
|         u32 align; | ||||
|         u8 kind; | ||||
|         VAddr addr; | ||||
|         Status status; | ||||
|     }; | ||||
|     /// Id to use for the next open file descriptor. | ||||
|     u32 next_fd = 1; | ||||
|  | ||||
|     u32 next_handle = 1; | ||||
|     u32 next_id = 1; | ||||
|     std::unordered_map<u32, std::shared_ptr<Object>> handles; | ||||
|     /// Mapping of file descriptors to the devices they reference. | ||||
|     std::unordered_map<u32, std::shared_ptr<Devices::nvdevice>> open_files; | ||||
|  | ||||
|     enum IoctlCommands { | ||||
|         IocCreateCommand = 0xC0080101, | ||||
|         IocFromIdCommand = 0xC0080103, | ||||
|         IocAllocCommand = 0xC0200104, | ||||
|         IocParamCommand = 0xC00C0109, | ||||
|         IocGetIdCommand = 0xC008010E | ||||
|     }; | ||||
|  | ||||
|     struct IocCreateParams { | ||||
|         // Input | ||||
|         u32_le size; | ||||
|         // Output | ||||
|         u32_le handle; | ||||
|     }; | ||||
|  | ||||
|     struct IocAllocParams { | ||||
|         // Input | ||||
|         u32_le handle; | ||||
|         u32_le heap_mask; | ||||
|         u32_le flags; | ||||
|         u32_le align; | ||||
|         u8 kind; | ||||
|         INSERT_PADDING_BYTES(7); | ||||
|         u64_le addr; | ||||
|     }; | ||||
|  | ||||
|     struct IocGetIdParams { | ||||
|         // Output | ||||
|         u32_le id; | ||||
|         // Input | ||||
|         u32_le handle; | ||||
|     }; | ||||
|  | ||||
|     struct IocFromIdParams { | ||||
|         // Input | ||||
|         u32_le id; | ||||
|         // Output | ||||
|         u32_le handle; | ||||
|     }; | ||||
|  | ||||
|     struct IocParamParams { | ||||
|         // Input | ||||
|         u32_le handle; | ||||
|         u32_le type; | ||||
|         // Output | ||||
|         u32_le value; | ||||
|     }; | ||||
|  | ||||
|     u32 IocCreate(const std::vector<u8>& input, std::vector<u8>& output); | ||||
|     u32 IocAlloc(const std::vector<u8>& input, std::vector<u8>& output); | ||||
|     u32 IocGetId(const std::vector<u8>& input, std::vector<u8>& output); | ||||
|     u32 IocFromId(const std::vector<u8>& input, std::vector<u8>& output); | ||||
|     u32 IocParam(const std::vector<u8>& input, std::vector<u8>& output); | ||||
| }; | ||||
|  | ||||
| class nvdisp_disp0 : public nvdevice { | ||||
| public: | ||||
|     nvdisp_disp0(std::shared_ptr<nvmap> nvmap_dev) : nvdevice(), nvmap_dev(std::move(nvmap_dev)) {} | ||||
|     ~nvdisp_disp0() = default; | ||||
|  | ||||
|     u32 ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) override; | ||||
|  | ||||
|     /// Performs a screen flip, drawing the buffer pointed to by the handle. | ||||
|     void flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height, u32 stride); | ||||
|  | ||||
| private: | ||||
|     std::shared_ptr<nvmap> nvmap_dev; | ||||
|     /// Mapping of device node names to their implementation. | ||||
|     std::unordered_map<std::string, std::shared_ptr<Devices::nvdevice>> devices; | ||||
| }; | ||||
|  | ||||
| /// Registers all NVDRV services with the specified service manager. | ||||
| void InstallInterfaces(SM::ServiceManager& service_manager); | ||||
|  | ||||
| } // namespace NVDRV | ||||
| extern std::weak_ptr<Module> nvdrv; | ||||
|  | ||||
| } // namespace Nvidia | ||||
| } // namespace Service | ||||
|   | ||||
| @@ -1,51 +0,0 @@ | ||||
| // Copyright 2018 yuzu emulator team | ||||
| // Licensed under GPLv2 or any later version | ||||
| // Refer to the license.txt file included. | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <memory> | ||||
| #include <string> | ||||
| #include "core/hle/service/nvdrv/nvdrv.h" | ||||
| #include "core/hle/service/service.h" | ||||
|  | ||||
| namespace Service { | ||||
| namespace NVDRV { | ||||
|  | ||||
| namespace Devices { | ||||
| class nvdevice; | ||||
| } | ||||
|  | ||||
| class NVDRV_A final : public ServiceFramework<NVDRV_A> { | ||||
| public: | ||||
|     NVDRV_A(); | ||||
|     ~NVDRV_A() = default; | ||||
|  | ||||
|     /// Returns a pointer to one of the available devices, identified by its name. | ||||
|     template <typename T> | ||||
|     std::shared_ptr<T> GetDevice(std::string name) { | ||||
|         auto itr = devices.find(name); | ||||
|         if (itr == devices.end()) | ||||
|             return nullptr; | ||||
|         return std::static_pointer_cast<T>(itr->second); | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     void Open(Kernel::HLERequestContext& ctx); | ||||
|     void Ioctl(Kernel::HLERequestContext& ctx); | ||||
|     void Initialize(Kernel::HLERequestContext& ctx); | ||||
|  | ||||
|     /// Id to use for the next open file descriptor. | ||||
|     u32 next_fd = 1; | ||||
|  | ||||
|     /// Mapping of file descriptors to the devices they reference. | ||||
|     std::unordered_map<u32, std::shared_ptr<Devices::nvdevice>> open_files; | ||||
|  | ||||
|     /// Mapping of device node names to their implementation. | ||||
|     std::unordered_map<std::string, std::shared_ptr<Devices::nvdevice>> devices; | ||||
| }; | ||||
|  | ||||
| extern std::weak_ptr<NVDRV_A> nvdrv_a; | ||||
|  | ||||
| } // namespace NVDRV | ||||
| } // namespace Service | ||||
| @@ -170,7 +170,7 @@ void Init() { | ||||
|     Audio::InstallInterfaces(*SM::g_service_manager); | ||||
|     HID::InstallInterfaces(*SM::g_service_manager); | ||||
|     LM::InstallInterfaces(*SM::g_service_manager); | ||||
|     NVDRV::InstallInterfaces(*SM::g_service_manager); | ||||
|     Nvidia::InstallInterfaces(*SM::g_service_manager); | ||||
|     PCTL::InstallInterfaces(*SM::g_service_manager); | ||||
|     Time::InstallInterfaces(*SM::g_service_manager); | ||||
|     VI::InstallInterfaces(*SM::g_service_manager); | ||||
|   | ||||
| @@ -9,7 +9,7 @@ | ||||
| #include "core/core_timing.h" | ||||
| #include "core/hle/ipc_helpers.h" | ||||
| #include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" | ||||
| #include "core/hle/service/nvdrv/nvdrv_a.h" | ||||
| #include "core/hle/service/nvdrv/nvdrv.h" | ||||
| #include "core/hle/service/vi/vi.h" | ||||
| #include "core/hle/service/vi/vi_m.h" | ||||
| #include "video_core/renderer_base.h" | ||||
| @@ -361,7 +361,7 @@ public: | ||||
|         static const FunctionInfo functions[] = { | ||||
|             {0, &IHOSBinderDriver::TransactParcel, "TransactParcel"}, | ||||
|             {1, &IHOSBinderDriver::AdjustRefcount, "AdjustRefcount"}, | ||||
|             {2, nullptr, "GetNativeHandle"}, | ||||
|             {2, &IHOSBinderDriver::GetNativeHandle, "GetNativeHandle"}, | ||||
|             {3, nullptr, "TransactParcelAuto"}, | ||||
|         }; | ||||
|         RegisterHandlers(functions); | ||||
| @@ -463,6 +463,21 @@ private: | ||||
|         rb.Push(RESULT_SUCCESS); | ||||
|     } | ||||
|  | ||||
|     void GetNativeHandle(Kernel::HLERequestContext& ctx) { | ||||
|         IPC::RequestParser rp{ctx}; | ||||
|         u32 id = rp.Pop<u32>(); | ||||
|         u32 unknown = rp.Pop<u32>(); | ||||
|  | ||||
|         auto buffer_queue = nv_flinger->GetBufferQueue(id); | ||||
|  | ||||
|         // TODO(Subv): Find out what this actually is. | ||||
|  | ||||
|         LOG_WARNING(Service, "(STUBBED) called id=%u, unknown=%08X", id, unknown); | ||||
|         IPC::RequestBuilder rb{ctx, 2, 1}; | ||||
|         rb.Push(RESULT_SUCCESS); | ||||
|         rb.PushCopyObjects(buffer_queue->GetNativeHandle()); | ||||
|     } | ||||
|  | ||||
|     std::shared_ptr<NVFlinger> nv_flinger; | ||||
| }; | ||||
|  | ||||
| @@ -565,6 +580,15 @@ void IApplicationDisplayService::GetManagerDisplayService(Kernel::HLERequestCont | ||||
|     rb.PushIpcInterface<IManagerDisplayService>(nv_flinger); | ||||
| } | ||||
|  | ||||
| void IApplicationDisplayService::GetIndirectDisplayTransactionService( | ||||
|     Kernel::HLERequestContext& ctx) { | ||||
|     LOG_WARNING(Service, "(STUBBED) called"); | ||||
|  | ||||
|     IPC::RequestBuilder rb{ctx, 2, 0, 0, 1}; | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
|     rb.PushIpcInterface<IHOSBinderDriver>(nv_flinger); | ||||
| } | ||||
|  | ||||
| void IApplicationDisplayService::OpenDisplay(Kernel::HLERequestContext& ctx) { | ||||
|     LOG_WARNING(Service, "(STUBBED) called"); | ||||
|     IPC::RequestParser rp{ctx}; | ||||
| @@ -580,6 +604,15 @@ void IApplicationDisplayService::OpenDisplay(Kernel::HLERequestContext& ctx) { | ||||
|     rb.Push<u64>(nv_flinger->OpenDisplay(name)); | ||||
| } | ||||
|  | ||||
| void IApplicationDisplayService::CloseDisplay(Kernel::HLERequestContext& ctx) { | ||||
|     LOG_WARNING(Service, "(STUBBED) called"); | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     u64 display_id = rp.Pop<u64>(); | ||||
|  | ||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(4, 0, 0, 0); | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
| } | ||||
|  | ||||
| void IApplicationDisplayService::OpenLayer(Kernel::HLERequestContext& ctx) { | ||||
|     LOG_WARNING(Service, "(STUBBED) called"); | ||||
|     IPC::RequestParser rp{ctx}; | ||||
| @@ -605,6 +638,40 @@ void IApplicationDisplayService::OpenLayer(Kernel::HLERequestContext& ctx) { | ||||
|     rb.Push<u64>(data.size()); | ||||
| } | ||||
|  | ||||
| void IApplicationDisplayService::CreateStrayLayer(Kernel::HLERequestContext& ctx) { | ||||
|     LOG_WARNING(Service, "(STUBBED) called"); | ||||
|  | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     u32 flags = rp.Pop<u32>(); | ||||
|     u64 display_id = rp.Pop<u64>(); | ||||
|  | ||||
|     auto& buffer = ctx.BufferDescriptorB()[0]; | ||||
|  | ||||
|     // TODO(Subv): What's the difference between a Stray and a Managed layer? | ||||
|  | ||||
|     u64 layer_id = nv_flinger->CreateLayer(display_id); | ||||
|     u32 buffer_queue_id = nv_flinger->GetBufferQueueId(display_id, layer_id); | ||||
|  | ||||
|     NativeWindow native_window{buffer_queue_id}; | ||||
|     auto data = native_window.Serialize(); | ||||
|     Memory::WriteBlock(buffer.Address(), data.data(), data.size()); | ||||
|  | ||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(6, 0, 0, 0); | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
|     rb.Push(layer_id); | ||||
|     rb.Push<u64>(data.size()); | ||||
| } | ||||
|  | ||||
| void IApplicationDisplayService::DestroyStrayLayer(Kernel::HLERequestContext& ctx) { | ||||
|     LOG_WARNING(Service, "(STUBBED) called"); | ||||
|  | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     u64 layer_id = rp.Pop<u64>(); | ||||
|  | ||||
|     IPC::RequestBuilder rb = rp.MakeBuilder(2, 0, 0, 0); | ||||
|     rb.Push(RESULT_SUCCESS); | ||||
| } | ||||
|  | ||||
| void IApplicationDisplayService::SetLayerScalingMode(Kernel::HLERequestContext& ctx) { | ||||
|     LOG_WARNING(Service, "(STUBBED) called"); | ||||
|     IPC::RequestParser rp{ctx}; | ||||
| @@ -633,11 +700,15 @@ IApplicationDisplayService::IApplicationDisplayService(std::shared_ptr<NVFlinger | ||||
|         {100, &IApplicationDisplayService::GetRelayService, "GetRelayService"}, | ||||
|         {101, &IApplicationDisplayService::GetSystemDisplayService, "GetSystemDisplayService"}, | ||||
|         {102, &IApplicationDisplayService::GetManagerDisplayService, "GetManagerDisplayService"}, | ||||
|         {103, nullptr, "GetIndirectDisplayTransactionService"}, | ||||
|         {103, &IApplicationDisplayService::GetIndirectDisplayTransactionService, | ||||
|          "GetIndirectDisplayTransactionService"}, | ||||
|         {1000, nullptr, "ListDisplays"}, | ||||
|         {1010, &IApplicationDisplayService::OpenDisplay, "OpenDisplay"}, | ||||
|         {1020, &IApplicationDisplayService::CloseDisplay, "CloseDisplay"}, | ||||
|         {2101, &IApplicationDisplayService::SetLayerScalingMode, "SetLayerScalingMode"}, | ||||
|         {2020, &IApplicationDisplayService::OpenLayer, "OpenLayer"}, | ||||
|         {2030, &IApplicationDisplayService::CreateStrayLayer, "CreateStrayLayer"}, | ||||
|         {2031, &IApplicationDisplayService::DestroyStrayLayer, "DestroyStrayLayer"}, | ||||
|         {5202, &IApplicationDisplayService::GetDisplayVsyncEvent, "GetDisplayVsyncEvent"}, | ||||
|     }; | ||||
|     RegisterHandlers(functions); | ||||
| @@ -763,12 +834,12 @@ void NVFlinger::Compose() { | ||||
|         auto& igbp_buffer = buffer->igbp_buffer; | ||||
|  | ||||
|         // Now send the buffer to the GPU for drawing. | ||||
|         auto nvdrv = NVDRV::nvdrv_a.lock(); | ||||
|         auto nvdrv = Nvidia::nvdrv.lock(); | ||||
|         ASSERT(nvdrv); | ||||
|  | ||||
|         // TODO(Subv): Support more than just disp0. The display device selection is probably based | ||||
|         // on which display we're drawing (Default, Internal, External, etc) | ||||
|         auto nvdisp = nvdrv->GetDevice<NVDRV::Devices::nvdisp_disp0>("/dev/nvdisp_disp0"); | ||||
|         auto nvdisp = nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>("/dev/nvdisp_disp0"); | ||||
|         ASSERT(nvdisp); | ||||
|  | ||||
|         nvdisp->flip(igbp_buffer.gpu_buffer_id, igbp_buffer.offset, igbp_buffer.format, | ||||
| @@ -778,7 +849,9 @@ void NVFlinger::Compose() { | ||||
|     } | ||||
| } | ||||
|  | ||||
| BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) {} | ||||
| BufferQueue::BufferQueue(u32 id, u64 layer_id) : id(id), layer_id(layer_id) { | ||||
|     native_handle = Kernel::Event::Create(Kernel::ResetType::OneShot, "BufferQueue NativeHandle"); | ||||
| } | ||||
|  | ||||
| void BufferQueue::SetPreallocatedBuffer(u32 slot, IGBPBuffer& igbp_buffer) { | ||||
|     Buffer buffer{}; | ||||
|   | ||||
| @@ -59,11 +59,16 @@ public: | ||||
|         return id; | ||||
|     } | ||||
|  | ||||
|     Kernel::SharedPtr<Kernel::Event> GetNativeHandle() const { | ||||
|         return native_handle; | ||||
|     } | ||||
|  | ||||
| private: | ||||
|     u32 id; | ||||
|     u64 layer_id; | ||||
|  | ||||
|     std::vector<Buffer> queue; | ||||
|     Kernel::SharedPtr<Kernel::Event> native_handle; | ||||
| }; | ||||
|  | ||||
| struct Layer { | ||||
| @@ -138,9 +143,13 @@ private: | ||||
|     void GetRelayService(Kernel::HLERequestContext& ctx); | ||||
|     void GetSystemDisplayService(Kernel::HLERequestContext& ctx); | ||||
|     void GetManagerDisplayService(Kernel::HLERequestContext& ctx); | ||||
|     void GetIndirectDisplayTransactionService(Kernel::HLERequestContext& ctx); | ||||
|     void OpenDisplay(Kernel::HLERequestContext& ctx); | ||||
|     void CloseDisplay(Kernel::HLERequestContext& ctx); | ||||
|     void SetLayerScalingMode(Kernel::HLERequestContext& ctx); | ||||
|     void OpenLayer(Kernel::HLERequestContext& ctx); | ||||
|     void CreateStrayLayer(Kernel::HLERequestContext& ctx); | ||||
|     void DestroyStrayLayer(Kernel::HLERequestContext& ctx); | ||||
|     void GetDisplayVsyncEvent(Kernel::HLERequestContext& ctx); | ||||
|  | ||||
|     std::shared_ptr<NVFlinger> nv_flinger; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user