Merge branch 'yuzu-emu:master' into import-firmware
This commit is contained in:
		| @@ -959,14 +959,26 @@ 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/service_creator.cpp | ||||
|     hle/service/vi/service_creator.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_u.cpp | ||||
|     hle/service/vi/vi_u.h | ||||
|     internal_network/network.cpp | ||||
|     internal_network/network.h | ||||
|     internal_network/network_interface.cpp | ||||
|   | ||||
| @@ -11,6 +11,7 @@ | ||||
| #include "core/hle/service/pm/pm.h" | ||||
| #include "core/hle/service/sm/sm.h" | ||||
| #include "core/hle/service/vi/vi.h" | ||||
| #include "core/hle/service/vi/vi_types.h" | ||||
|  | ||||
| namespace Service::AM { | ||||
|  | ||||
|   | ||||
| @@ -106,7 +106,7 @@ void AudCtl::GetAudioOutputMode(HLERequestContext& ctx) { | ||||
|     const auto target{rp.PopEnum<Set::AudioOutputModeTarget>()}; | ||||
|  | ||||
|     Set::AudioOutputMode output_mode{}; | ||||
|     const auto result = m_set_sys->GetAudioOutputMode(output_mode, target); | ||||
|     const auto result = m_set_sys->GetAudioOutputMode(&output_mode, target); | ||||
|  | ||||
|     LOG_INFO(Service_SET, "called, target={}, output_mode={}", target, output_mode); | ||||
|  | ||||
| @@ -188,7 +188,7 @@ void AudCtl::SetSpeakerAutoMuteEnabled(HLERequestContext& ctx) { | ||||
|  | ||||
| void AudCtl::IsSpeakerAutoMuteEnabled(HLERequestContext& ctx) { | ||||
|     bool is_speaker_auto_mute_enabled{}; | ||||
|     const auto result = m_set_sys->GetSpeakerAutoMuteFlag(is_speaker_auto_mute_enabled); | ||||
|     const auto result = m_set_sys->GetSpeakerAutoMuteFlag(&is_speaker_auto_mute_enabled); | ||||
|  | ||||
|     LOG_WARNING(Audio, "(STUBBED) called, is_speaker_auto_mute_enabled={}", | ||||
|                 is_speaker_auto_mute_enabled); | ||||
|   | ||||
| @@ -21,19 +21,6 @@ | ||||
|  | ||||
| namespace Service::Glue::Time { | ||||
| namespace { | ||||
|  | ||||
| template <typename T> | ||||
| T GetSettingsItemValue(std::shared_ptr<Service::Set::ISystemSettingsServer>& set_sys, | ||||
|                        const char* category, const char* name) { | ||||
|     std::vector<u8> interval_buf; | ||||
|     auto res = set_sys->GetSettingsItemValue(interval_buf, category, name); | ||||
|     ASSERT(res == ResultSuccess); | ||||
|  | ||||
|     T v{}; | ||||
|     std::memcpy(&v, interval_buf.data(), sizeof(T)); | ||||
|     return v; | ||||
| } | ||||
|  | ||||
| s64 CalendarTimeToEpoch(Service::PSC::Time::CalendarTime calendar) { | ||||
|     constexpr auto is_leap = [](s32 year) -> bool { | ||||
|         return (((year) % 4) == 0 && (((year) % 100) != 0 || ((year) % 400) == 0)); | ||||
| @@ -65,13 +52,15 @@ s64 CalendarTimeToEpoch(Service::PSC::Time::CalendarTime calendar) { | ||||
|  | ||||
| s64 GetEpochTimeFromInitialYear(std::shared_ptr<Service::Set::ISystemSettingsServer>& set_sys) { | ||||
|     Service::PSC::Time::CalendarTime calendar{ | ||||
|         .year = GetSettingsItemValue<s16>(set_sys, "time", "standard_user_clock_initial_year"), | ||||
|         .year = 2000, | ||||
|         .month = 1, | ||||
|         .day = 1, | ||||
|         .hour = 0, | ||||
|         .minute = 0, | ||||
|         .second = 0, | ||||
|     }; | ||||
|     set_sys->GetSettingsItemValueImpl<s16>(calendar.year, "time", | ||||
|                                            "standard_user_clock_initial_year"); | ||||
|     return CalendarTimeToEpoch(calendar); | ||||
| } | ||||
|  | ||||
| @@ -124,7 +113,7 @@ TimeManager::TimeManager(Core::System& system) | ||||
|     ASSERT(res == ResultSuccess); | ||||
|  | ||||
|     Service::PSC::Time::SystemClockContext user_clock_context{}; | ||||
|     res = m_set_sys->GetUserSystemClockContext(user_clock_context); | ||||
|     res = m_set_sys->GetUserSystemClockContext(&user_clock_context); | ||||
|     ASSERT(res == ResultSuccess); | ||||
|  | ||||
|     // TODO the local clock should initialise with this epoch time, and be updated somewhere else on | ||||
| @@ -140,11 +129,12 @@ TimeManager::TimeManager(Core::System& system) | ||||
|     ASSERT(res == ResultSuccess); | ||||
|  | ||||
|     Service::PSC::Time::SystemClockContext network_clock_context{}; | ||||
|     res = m_set_sys->GetNetworkSystemClockContext(network_clock_context); | ||||
|     res = m_set_sys->GetNetworkSystemClockContext(&network_clock_context); | ||||
|     ASSERT(res == ResultSuccess); | ||||
|  | ||||
|     auto network_accuracy_m{GetSettingsItemValue<s32>( | ||||
|         m_set_sys, "time", "standard_network_clock_sufficient_accuracy_minutes")}; | ||||
|     s32 network_accuracy_m{}; | ||||
|     m_set_sys->GetSettingsItemValueImpl<s32>(network_accuracy_m, "time", | ||||
|                                              "standard_network_clock_sufficient_accuracy_minutes"); | ||||
|     auto one_minute_ns{ | ||||
|         std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::minutes(1)).count()}; | ||||
|     s64 network_accuracy_ns{network_accuracy_m * one_minute_ns}; | ||||
| @@ -153,12 +143,12 @@ TimeManager::TimeManager(Core::System& system) | ||||
|     ASSERT(res == ResultSuccess); | ||||
|  | ||||
|     bool is_automatic_correction_enabled{}; | ||||
|     res = m_set_sys->IsUserSystemClockAutomaticCorrectionEnabled(is_automatic_correction_enabled); | ||||
|     res = m_set_sys->IsUserSystemClockAutomaticCorrectionEnabled(&is_automatic_correction_enabled); | ||||
|     ASSERT(res == ResultSuccess); | ||||
|  | ||||
|     Service::PSC::Time::SteadyClockTimePoint automatic_correction_time_point{}; | ||||
|     res = m_set_sys->GetUserSystemClockAutomaticCorrectionUpdatedTime( | ||||
|         automatic_correction_time_point); | ||||
|         &automatic_correction_time_point); | ||||
|     ASSERT(res == ResultSuccess); | ||||
|  | ||||
|     res = m_time_m->SetupStandardUserSystemClockCore(is_automatic_correction_enabled, | ||||
| @@ -198,11 +188,11 @@ TimeManager::TimeManager(Core::System& system) | ||||
|  | ||||
| Result TimeManager::SetupStandardSteadyClockCore() { | ||||
|     Common::UUID external_clock_source_id{}; | ||||
|     auto res = m_set_sys->GetExternalSteadyClockSourceId(external_clock_source_id); | ||||
|     auto res = m_set_sys->GetExternalSteadyClockSourceId(&external_clock_source_id); | ||||
|     ASSERT(res == ResultSuccess); | ||||
|  | ||||
|     s64 external_steady_clock_internal_offset_s{}; | ||||
|     res = m_set_sys->GetExternalSteadyClockInternalOffset(external_steady_clock_internal_offset_s); | ||||
|     res = m_set_sys->GetExternalSteadyClockInternalOffset(&external_steady_clock_internal_offset_s); | ||||
|     ASSERT(res == ResultSuccess); | ||||
|  | ||||
|     auto one_second_ns{ | ||||
| @@ -210,8 +200,9 @@ Result TimeManager::SetupStandardSteadyClockCore() { | ||||
|     s64 external_steady_clock_internal_offset_ns{external_steady_clock_internal_offset_s * | ||||
|                                                  one_second_ns}; | ||||
|  | ||||
|     s32 standard_steady_clock_test_offset_m{ | ||||
|         GetSettingsItemValue<s32>(m_set_sys, "time", "standard_steady_clock_test_offset_minutes")}; | ||||
|     s32 standard_steady_clock_test_offset_m{}; | ||||
|     m_set_sys->GetSettingsItemValueImpl<s32>(standard_steady_clock_test_offset_m, "time", | ||||
|                                              "standard_steady_clock_test_offset_minutes"); | ||||
|     auto one_minute_ns{ | ||||
|         std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::minutes(1)).count()}; | ||||
|     s64 standard_steady_clock_test_offset_ns{standard_steady_clock_test_offset_m * one_minute_ns}; | ||||
| @@ -237,7 +228,7 @@ Result TimeManager::SetupStandardSteadyClockCore() { | ||||
|  | ||||
| Result TimeManager::SetupTimeZoneServiceCore() { | ||||
|     Service::PSC::Time::LocationName name{}; | ||||
|     auto res = m_set_sys->GetDeviceTimeZoneLocationName(name); | ||||
|     auto res = m_set_sys->GetDeviceTimeZoneLocationName(&name); | ||||
|     ASSERT(res == ResultSuccess); | ||||
|  | ||||
|     auto configured_zone = GetTimeZoneString(name); | ||||
| @@ -255,7 +246,7 @@ Result TimeManager::SetupTimeZoneServiceCore() { | ||||
|     } | ||||
|  | ||||
|     Service::PSC::Time::SteadyClockTimePoint time_point{}; | ||||
|     res = m_set_sys->GetDeviceTimeZoneLocationUpdatedTime(time_point); | ||||
|     res = m_set_sys->GetDeviceTimeZoneLocationUpdatedTime(&time_point); | ||||
|     ASSERT(res == ResultSuccess); | ||||
|  | ||||
|     auto location_count = GetTimeZoneCount(); | ||||
|   | ||||
| @@ -20,19 +20,6 @@ | ||||
| #include "core/hle/service/sm/sm.h" | ||||
|  | ||||
| namespace Service::Glue::Time { | ||||
| namespace { | ||||
| template <typename T> | ||||
| T GetSettingsItemValue(std::shared_ptr<Service::Set::ISystemSettingsServer>& set_sys, | ||||
|                        const char* category, const char* name) { | ||||
|     std::vector<u8> interval_buf; | ||||
|     auto res = set_sys->GetSettingsItemValue(interval_buf, category, name); | ||||
|     ASSERT(res == ResultSuccess); | ||||
|  | ||||
|     T v{}; | ||||
|     std::memcpy(&v, interval_buf.data(), sizeof(T)); | ||||
|     return v; | ||||
| } | ||||
| } // namespace | ||||
|  | ||||
| StaticService::StaticService(Core::System& system_, | ||||
|                              Service::PSC::Time::StaticServiceSetupInfo setup_info, | ||||
| @@ -181,8 +168,8 @@ Result StaticService::SetStandardUserSystemClockAutomaticCorrectionEnabled( | ||||
| Result StaticService::GetStandardUserSystemClockInitialYear(Out<s32> out_year) { | ||||
|     SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. out_year={}", *out_year); }); | ||||
|  | ||||
|     *out_year = GetSettingsItemValue<s32>(m_set_sys, "time", "standard_user_clock_initial_year"); | ||||
|     R_SUCCEED(); | ||||
|     R_RETURN(m_set_sys->GetSettingsItemValueImpl<s32>(*out_year, "time", | ||||
|                                                       "standard_user_clock_initial_year")); | ||||
| } | ||||
|  | ||||
| Result StaticService::IsStandardNetworkSystemClockAccuracySufficient(Out<bool> out_is_sufficient) { | ||||
|   | ||||
| @@ -27,7 +27,7 @@ template <typename T> | ||||
| T GetSettingsItemValue(std::shared_ptr<Service::Set::ISystemSettingsServer>& set_sys, | ||||
|                        const char* category, const char* name) { | ||||
|     std::vector<u8> interval_buf; | ||||
|     auto res = set_sys->GetSettingsItemValue(interval_buf, category, name); | ||||
|     auto res = set_sys->GetSettingsItemValueImpl(interval_buf, category, name); | ||||
|     ASSERT(res == ResultSuccess); | ||||
|  | ||||
|     T v{}; | ||||
|   | ||||
| @@ -207,7 +207,8 @@ private: | ||||
|  | ||||
|     Result DestroyFile() { | ||||
|         bool is_db_test_mode_enabled{}; | ||||
|         m_set_sys->GetSettingsItemValue(is_db_test_mode_enabled, "mii", "is_db_test_mode_enabled"); | ||||
|         m_set_sys->GetSettingsItemValueImpl(is_db_test_mode_enabled, "mii", | ||||
|                                             "is_db_test_mode_enabled"); | ||||
|  | ||||
|         LOG_INFO(Service_Mii, "called is_db_test_mode_enabled={}", is_db_test_mode_enabled); | ||||
|         R_UNLESS(is_db_test_mode_enabled, ResultTestModeOnly); | ||||
| @@ -217,7 +218,8 @@ private: | ||||
|  | ||||
|     Result DeleteFile() { | ||||
|         bool is_db_test_mode_enabled{}; | ||||
|         m_set_sys->GetSettingsItemValue(is_db_test_mode_enabled, "mii", "is_db_test_mode_enabled"); | ||||
|         m_set_sys->GetSettingsItemValueImpl(is_db_test_mode_enabled, "mii", | ||||
|                                             "is_db_test_mode_enabled"); | ||||
|  | ||||
|         LOG_INFO(Service_Mii, "called is_db_test_mode_enabled={}", is_db_test_mode_enabled); | ||||
|         R_UNLESS(is_db_test_mode_enabled, ResultTestModeOnly); | ||||
| @@ -227,7 +229,8 @@ private: | ||||
|  | ||||
|     Result Format() { | ||||
|         bool is_db_test_mode_enabled{}; | ||||
|         m_set_sys->GetSettingsItemValue(is_db_test_mode_enabled, "mii", "is_db_test_mode_enabled"); | ||||
|         m_set_sys->GetSettingsItemValueImpl(is_db_test_mode_enabled, "mii", | ||||
|                                             "is_db_test_mode_enabled"); | ||||
|  | ||||
|         LOG_INFO(Service_Mii, "called is_db_test_mode_enabled={}", is_db_test_mode_enabled); | ||||
|         R_UNLESS(is_db_test_mode_enabled, ResultTestModeOnly); | ||||
|   | ||||
| @@ -6,6 +6,8 @@ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <span> | ||||
|  | ||||
| #include "common/common_types.h" | ||||
|  | ||||
| namespace Kernel { | ||||
| @@ -38,7 +40,8 @@ enum class TransactionId { | ||||
| class IBinder { | ||||
| public: | ||||
|     virtual ~IBinder() = default; | ||||
|     virtual void Transact(HLERequestContext& ctx, android::TransactionId code, u32 flags) = 0; | ||||
|     virtual void Transact(android::TransactionId code, u32 flags, std::span<const u8> parcel_data, | ||||
|                           std::span<u8> parcel_reply) = 0; | ||||
|     virtual Kernel::KReadableEvent& GetNativeHandle() = 0; | ||||
| }; | ||||
|  | ||||
|   | ||||
| @@ -807,9 +807,10 @@ Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot, | ||||
|     return Status::NoError; | ||||
| } | ||||
|  | ||||
| void BufferQueueProducer::Transact(HLERequestContext& ctx, TransactionId code, u32 flags) { | ||||
| void BufferQueueProducer::Transact(TransactionId code, u32 flags, std::span<const u8> parcel_data, | ||||
|                                    std::span<u8> parcel_reply) { | ||||
|     Status status{Status::NoError}; | ||||
|     InputParcel parcel_in{ctx.ReadBuffer()}; | ||||
|     InputParcel parcel_in{parcel_data}; | ||||
|     OutputParcel parcel_out{}; | ||||
|  | ||||
|     switch (code) { | ||||
| @@ -917,7 +918,9 @@ void BufferQueueProducer::Transact(HLERequestContext& ctx, TransactionId code, u | ||||
|  | ||||
|     parcel_out.Write(status); | ||||
|  | ||||
|     ctx.WriteBuffer(parcel_out.Serialize()); | ||||
|     const auto serialized = parcel_out.Serialize(); | ||||
|     std::memcpy(parcel_reply.data(), serialized.data(), | ||||
|                 std::min(parcel_reply.size(), serialized.size())); | ||||
| } | ||||
|  | ||||
| Kernel::KReadableEvent& BufferQueueProducer::GetNativeHandle() { | ||||
|   | ||||
| @@ -47,7 +47,8 @@ public: | ||||
|                                  Service::Nvidia::NvCore::NvMap& nvmap_); | ||||
|     ~BufferQueueProducer(); | ||||
|  | ||||
|     void Transact(HLERequestContext& ctx, android::TransactionId code, u32 flags) override; | ||||
|     void Transact(android::TransactionId code, u32 flags, std::span<const u8> parcel_data, | ||||
|                   std::span<u8> parcel_reply) override; | ||||
|  | ||||
|     Kernel::KReadableEvent& GetNativeHandle() override; | ||||
|  | ||||
|   | ||||
| @@ -244,7 +244,7 @@ struct SystemSettings { | ||||
|     INSERT_PADDING_BYTES(0x60); // Reserved | ||||
|  | ||||
|     // nn::settings::system::AccountNotificationSettings | ||||
|     u32 account_notification_settings_count; | ||||
|     s32 account_notification_settings_count; | ||||
|     INSERT_PADDING_BYTES(0xC); // Reserved | ||||
|     std::array<AccountNotificationSettings, 8> account_notification_settings; | ||||
|     INSERT_PADDING_BYTES(0x140); // Reserved | ||||
| @@ -308,7 +308,7 @@ struct SystemSettings { | ||||
|     INSERT_PADDING_BYTES(0x34); // Reserved | ||||
|  | ||||
|     // nn::settings::system::EulaVersion | ||||
|     u32 eula_version_count; | ||||
|     s32 eula_version_count; | ||||
|     INSERT_PADDING_BYTES(0xC); // Reserved | ||||
|     std::array<EulaVersion, 32> eula_versions; | ||||
|     INSERT_PADDING_BYTES(0x200); // Reserved | ||||
|   | ||||
| @@ -12,6 +12,7 @@ | ||||
| #include "core/hle/service/psc/time/common.h" | ||||
|  | ||||
| namespace Service::Set { | ||||
| using SettingItemName = std::array<u8, 0x48>; | ||||
|  | ||||
| /// This is nn::settings::system::AudioOutputMode | ||||
| enum class AudioOutputMode : u32 { | ||||
| @@ -413,16 +414,18 @@ struct FirmwareVersionFormat { | ||||
|     u8 major; | ||||
|     u8 minor; | ||||
|     u8 micro; | ||||
|     INSERT_PADDING_BYTES(1); | ||||
|     INSERT_PADDING_BYTES_NOINIT(1); | ||||
|     u8 revision_major; | ||||
|     u8 revision_minor; | ||||
|     INSERT_PADDING_BYTES(2); | ||||
|     INSERT_PADDING_BYTES_NOINIT(2); | ||||
|     std::array<char, 0x20> platform; | ||||
|     std::array<u8, 0x40> version_hash; | ||||
|     std::array<char, 0x18> display_version; | ||||
|     std::array<char, 0x80> display_title; | ||||
| }; | ||||
| static_assert(sizeof(FirmwareVersionFormat) == 0x100, "FirmwareVersionFormat is an invalid size"); | ||||
| static_assert(std::is_trivial_v<FirmwareVersionFormat>, | ||||
|               "FirmwareVersionFormat type must be trivially copyable."); | ||||
|  | ||||
| /// This is nn::settings::system::HomeMenuScheme | ||||
| struct HomeMenuScheme { | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -11,6 +11,7 @@ | ||||
| #include "common/polyfill_thread.h" | ||||
| #include "common/uuid.h" | ||||
| #include "core/hle/result.h" | ||||
| #include "core/hle/service/cmif_types.h" | ||||
| #include "core/hle/service/psc/time/common.h" | ||||
| #include "core/hle/service/service.h" | ||||
| #include "core/hle/service/set/setting_formats/appln_settings.h" | ||||
| @@ -33,13 +34,14 @@ public: | ||||
|     explicit ISystemSettingsServer(Core::System& system_); | ||||
|     ~ISystemSettingsServer() override; | ||||
|  | ||||
|     Result GetSettingsItemValue(std::vector<u8>& out_value, const std::string& category, | ||||
|                                 const std::string& name); | ||||
|     Result GetSettingsItemValueImpl(std::vector<u8>& out_value, const std::string& category, | ||||
|                                     const std::string& name); | ||||
|  | ||||
|     template <typename T> | ||||
|     Result GetSettingsItemValue(T& value, const std::string& category, const std::string& name) { | ||||
|     Result GetSettingsItemValueImpl(T& value, const std::string& category, | ||||
|                                     const std::string& name) { | ||||
|         std::vector<u8> data; | ||||
|         const auto result = GetSettingsItemValue(data, category, name); | ||||
|         const auto result = GetSettingsItemValueImpl(data, category, name); | ||||
|         if (result.IsError()) { | ||||
|             return result; | ||||
|         } | ||||
| @@ -48,120 +50,114 @@ public: | ||||
|         return result; | ||||
|     } | ||||
|  | ||||
|     Result GetVibrationMasterVolume(f32& out_volume) const; | ||||
|     Result SetVibrationMasterVolume(f32 volume); | ||||
|     Result GetAudioOutputMode(AudioOutputMode& out_output_mode, AudioOutputModeTarget target) const; | ||||
| public: | ||||
|     Result SetLanguageCode(LanguageCode language_code); | ||||
|     Result GetFirmwareVersion( | ||||
|         OutLargeData<FirmwareVersionFormat, BufferAttr_HipcPointer> out_firmware_data); | ||||
|     Result GetFirmwareVersion2( | ||||
|         OutLargeData<FirmwareVersionFormat, BufferAttr_HipcPointer> out_firmware_data); | ||||
|     Result GetLockScreenFlag(Out<bool> out_lock_screen_flag); | ||||
|     Result SetLockScreenFlag(bool lock_screen_flag); | ||||
|     Result GetExternalSteadyClockSourceId(Out<Common::UUID> out_clock_source_id); | ||||
|     Result SetExternalSteadyClockSourceId(const Common::UUID& clock_source_id); | ||||
|     Result GetUserSystemClockContext(Out<Service::PSC::Time::SystemClockContext> out_clock_context); | ||||
|     Result SetUserSystemClockContext(const Service::PSC::Time::SystemClockContext& clock_context); | ||||
|     Result GetAccountSettings(Out<AccountSettings> out_account_settings); | ||||
|     Result SetAccountSettings(AccountSettings account_settings); | ||||
|     Result GetEulaVersions(Out<s32> out_count, | ||||
|                            OutArray<EulaVersion, BufferAttr_HipcMapAlias> out_eula_versions); | ||||
|     Result SetEulaVersions(InArray<EulaVersion, BufferAttr_HipcMapAlias> eula_versions); | ||||
|     Result GetColorSetId(Out<ColorSet> out_color_set_id); | ||||
|     Result SetColorSetId(ColorSet color_set_id); | ||||
|     Result GetNotificationSettings(Out<NotificationSettings> out_notification_settings); | ||||
|     Result SetNotificationSettings(const NotificationSettings& notification_settings); | ||||
|     Result GetAccountNotificationSettings( | ||||
|         Out<s32> out_count, OutArray<AccountNotificationSettings, BufferAttr_HipcMapAlias> | ||||
|                                 out_account_notification_settings); | ||||
|     Result SetAccountNotificationSettings( | ||||
|         InArray<AccountNotificationSettings, BufferAttr_HipcMapAlias> | ||||
|             account_notification_settings); | ||||
|     Result GetVibrationMasterVolume(Out<f32> vibration_master_volume); | ||||
|     Result SetVibrationMasterVolume(f32 vibration_master_volume); | ||||
|     Result GetSettingsItemValueSize( | ||||
|         Out<u64> out_size, | ||||
|         InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_category_buffer, | ||||
|         InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_name_buf); | ||||
|     Result GetSettingsItemValue( | ||||
|         OutBuffer<BufferAttr_HipcMapAlias> out_data, | ||||
|         InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_category_buffer, | ||||
|         InLargeData<SettingItemName, BufferAttr_HipcPointer> setting_name_buffer); | ||||
|     Result GetTvSettings(Out<TvSettings> out_tv_settings); | ||||
|     Result SetTvSettings(TvSettings tv_settings); | ||||
|     Result GetAudioOutputMode(Out<AudioOutputMode> out_output_mode, AudioOutputModeTarget target); | ||||
|     Result SetAudioOutputMode(AudioOutputModeTarget target, AudioOutputMode output_mode); | ||||
|     Result GetSpeakerAutoMuteFlag(bool& is_auto_mute) const; | ||||
|     Result SetSpeakerAutoMuteFlag(bool auto_mute); | ||||
|     Result GetExternalSteadyClockSourceId(Common::UUID& out_id) const; | ||||
|     Result SetExternalSteadyClockSourceId(const Common::UUID& id); | ||||
|     Result GetUserSystemClockContext(Service::PSC::Time::SystemClockContext& out_context) const; | ||||
|     Result SetUserSystemClockContext(const Service::PSC::Time::SystemClockContext& context); | ||||
|     Result GetDeviceTimeZoneLocationName(Service::PSC::Time::LocationName& out_name) const; | ||||
|     Result GetSpeakerAutoMuteFlag(Out<bool> out_force_mute_on_headphone_removed); | ||||
|     Result SetSpeakerAutoMuteFlag(bool force_mute_on_headphone_removed); | ||||
|     Result GetQuestFlag(Out<QuestFlag> out_quest_flag); | ||||
|     Result SetQuestFlag(QuestFlag quest_flag); | ||||
|     Result GetDeviceTimeZoneLocationName(Out<Service::PSC::Time::LocationName> out_name); | ||||
|     Result SetDeviceTimeZoneLocationName(const Service::PSC::Time::LocationName& name); | ||||
|     Result GetNetworkSystemClockContext(Service::PSC::Time::SystemClockContext& out_context) const; | ||||
|     Result SetRegionCode(SystemRegionCode region_code); | ||||
|     Result GetNetworkSystemClockContext(Out<Service::PSC::Time::SystemClockContext> out_context); | ||||
|     Result SetNetworkSystemClockContext(const Service::PSC::Time::SystemClockContext& context); | ||||
|     Result IsUserSystemClockAutomaticCorrectionEnabled(bool& out_enabled) const; | ||||
|     Result SetUserSystemClockAutomaticCorrectionEnabled(bool enabled); | ||||
|     Result IsUserSystemClockAutomaticCorrectionEnabled(Out<bool> out_automatic_correction_enabled); | ||||
|     Result SetUserSystemClockAutomaticCorrectionEnabled(bool automatic_correction_enabled); | ||||
|     Result GetDebugModeFlag(Out<bool> is_debug_mode_enabled); | ||||
|     Result GetPrimaryAlbumStorage(Out<PrimaryAlbumStorage> out_primary_album_storage); | ||||
|     Result SetPrimaryAlbumStorage(PrimaryAlbumStorage primary_album_storage); | ||||
|     Result GetBatteryLot(Out<BatteryLot> out_battery_lot); | ||||
|     Result GetSerialNumber(Out<SerialNumber> out_console_serial); | ||||
|     Result GetNfcEnableFlag(Out<bool> out_nfc_enable_flag); | ||||
|     Result SetNfcEnableFlag(bool nfc_enable_flag); | ||||
|     Result GetSleepSettings(Out<SleepSettings> out_sleep_settings); | ||||
|     Result SetSleepSettings(SleepSettings sleep_settings); | ||||
|     Result GetWirelessLanEnableFlag(Out<bool> out_wireless_lan_enable_flag); | ||||
|     Result SetWirelessLanEnableFlag(bool wireless_lan_enable_flag); | ||||
|     Result GetInitialLaunchSettings(Out<InitialLaunchSettings> out_initial_launch_settings); | ||||
|     Result SetInitialLaunchSettings(InitialLaunchSettings initial_launch_settings); | ||||
|     Result GetDeviceNickName( | ||||
|         OutLargeData<std::array<u8, 0x80>, BufferAttr_HipcMapAlias> out_device_name); | ||||
|     Result SetDeviceNickName( | ||||
|         InLargeData<std::array<u8, 0x80>, BufferAttr_HipcMapAlias> device_name_buffer); | ||||
|     Result GetProductModel(Out<u32> out_product_model); | ||||
|     Result GetBluetoothEnableFlag(Out<bool> out_bluetooth_enable_flag); | ||||
|     Result SetBluetoothEnableFlag(bool bluetooth_enable_flag); | ||||
|     Result GetMiiAuthorId(Out<Common::UUID> out_mii_author_id); | ||||
|     Result GetAutoUpdateEnableFlag(Out<bool> out_auto_update_enable_flag); | ||||
|     Result SetAutoUpdateEnableFlag(bool auto_update_enable_flag); | ||||
|     Result GetBatteryPercentageFlag(Out<bool> out_battery_percentage_flag); | ||||
|     Result SetBatteryPercentageFlag(bool battery_percentage_flag); | ||||
|     Result SetExternalSteadyClockInternalOffset(s64 offset); | ||||
|     Result GetExternalSteadyClockInternalOffset(s64& out_offset) const; | ||||
|     Result GetExternalSteadyClockInternalOffset(Out<s64> out_offset); | ||||
|     Result GetPushNotificationActivityModeOnSleep( | ||||
|         Out<s32> out_push_notification_activity_mode_on_sleep); | ||||
|     Result SetPushNotificationActivityModeOnSleep(s32 push_notification_activity_mode_on_sleep); | ||||
|     Result GetErrorReportSharePermission( | ||||
|         Out<ErrorReportSharePermission> out_error_report_share_permission); | ||||
|     Result SetErrorReportSharePermission(ErrorReportSharePermission error_report_share_permission); | ||||
|     Result GetAppletLaunchFlags(Out<u32> out_applet_launch_flag); | ||||
|     Result SetAppletLaunchFlags(u32 applet_launch_flag); | ||||
|     Result GetKeyboardLayout(Out<KeyboardLayout> out_keyboard_layout); | ||||
|     Result SetKeyboardLayout(KeyboardLayout keyboard_layout); | ||||
|     Result GetDeviceTimeZoneLocationUpdatedTime( | ||||
|         Service::PSC::Time::SteadyClockTimePoint& out_time_point) const; | ||||
|         Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point); | ||||
|     Result SetDeviceTimeZoneLocationUpdatedTime( | ||||
|         const Service::PSC::Time::SteadyClockTimePoint& time_point); | ||||
|     Result GetUserSystemClockAutomaticCorrectionUpdatedTime( | ||||
|         Service::PSC::Time::SteadyClockTimePoint& out_time_point) const; | ||||
|         Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point); | ||||
|     Result SetUserSystemClockAutomaticCorrectionUpdatedTime( | ||||
|         const Service::PSC::Time::SteadyClockTimePoint& time_point); | ||||
|     Result GetTouchScreenMode(TouchScreenMode& touch_screen_mode) const; | ||||
|         const Service::PSC::Time::SteadyClockTimePoint& out_time_point); | ||||
|     Result GetChineseTraditionalInputMethod( | ||||
|         Out<ChineseTraditionalInputMethod> out_chinese_traditional_input_method); | ||||
|     Result GetHomeMenuScheme(Out<HomeMenuScheme> out_home_menu_scheme); | ||||
|     Result GetHomeMenuSchemeModel(Out<u32> out_home_menu_scheme_model); | ||||
|     Result GetTouchScreenMode(Out<TouchScreenMode> out_touch_screen_mode); | ||||
|     Result SetTouchScreenMode(TouchScreenMode touch_screen_mode); | ||||
|     Result GetFieldTestingFlag(Out<bool> out_field_testing_flag); | ||||
|     Result GetPanelCrcMode(Out<s32> out_panel_crc_mode); | ||||
|     Result SetPanelCrcMode(s32 panel_crc_mode); | ||||
|  | ||||
| private: | ||||
|     void SetLanguageCode(HLERequestContext& ctx); | ||||
|     void GetFirmwareVersion(HLERequestContext& ctx); | ||||
|     void GetFirmwareVersion2(HLERequestContext& ctx); | ||||
|     void GetLockScreenFlag(HLERequestContext& ctx); | ||||
|     void SetLockScreenFlag(HLERequestContext& ctx); | ||||
|     void GetExternalSteadyClockSourceId(HLERequestContext& ctx); | ||||
|     void SetExternalSteadyClockSourceId(HLERequestContext& ctx); | ||||
|     void GetUserSystemClockContext(HLERequestContext& ctx); | ||||
|     void SetUserSystemClockContext(HLERequestContext& ctx); | ||||
|     void GetAccountSettings(HLERequestContext& ctx); | ||||
|     void SetAccountSettings(HLERequestContext& ctx); | ||||
|     void GetEulaVersions(HLERequestContext& ctx); | ||||
|     void SetEulaVersions(HLERequestContext& ctx); | ||||
|     void GetColorSetId(HLERequestContext& ctx); | ||||
|     void SetColorSetId(HLERequestContext& ctx); | ||||
|     void GetNotificationSettings(HLERequestContext& ctx); | ||||
|     void SetNotificationSettings(HLERequestContext& ctx); | ||||
|     void GetAccountNotificationSettings(HLERequestContext& ctx); | ||||
|     void SetAccountNotificationSettings(HLERequestContext& ctx); | ||||
|     void GetVibrationMasterVolume(HLERequestContext& ctx); | ||||
|     void SetVibrationMasterVolume(HLERequestContext& ctx); | ||||
|     void GetSettingsItemValueSize(HLERequestContext& ctx); | ||||
|     void GetSettingsItemValue(HLERequestContext& ctx); | ||||
|     void GetTvSettings(HLERequestContext& ctx); | ||||
|     void SetTvSettings(HLERequestContext& ctx); | ||||
|     void GetAudioOutputMode(HLERequestContext& ctx); | ||||
|     void SetAudioOutputMode(HLERequestContext& ctx); | ||||
|     void GetSpeakerAutoMuteFlag(HLERequestContext& ctx); | ||||
|     void SetSpeakerAutoMuteFlag(HLERequestContext& ctx); | ||||
|     void GetDebugModeFlag(HLERequestContext& ctx); | ||||
|     void GetQuestFlag(HLERequestContext& ctx); | ||||
|     void SetQuestFlag(HLERequestContext& ctx); | ||||
|     void GetDeviceTimeZoneLocationName(HLERequestContext& ctx); | ||||
|     void SetDeviceTimeZoneLocationName(HLERequestContext& ctx); | ||||
|     void SetRegionCode(HLERequestContext& ctx); | ||||
|     void GetNetworkSystemClockContext(HLERequestContext& ctx); | ||||
|     void SetNetworkSystemClockContext(HLERequestContext& ctx); | ||||
|     void IsUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx); | ||||
|     void SetUserSystemClockAutomaticCorrectionEnabled(HLERequestContext& ctx); | ||||
|     void GetPrimaryAlbumStorage(HLERequestContext& ctx); | ||||
|     void SetPrimaryAlbumStorage(HLERequestContext& ctx); | ||||
|     void GetBatteryLot(HLERequestContext& ctx); | ||||
|     void GetSerialNumber(HLERequestContext& ctx); | ||||
|     void GetNfcEnableFlag(HLERequestContext& ctx); | ||||
|     void SetNfcEnableFlag(HLERequestContext& ctx); | ||||
|     void GetSleepSettings(HLERequestContext& ctx); | ||||
|     void SetSleepSettings(HLERequestContext& ctx); | ||||
|     void GetWirelessLanEnableFlag(HLERequestContext& ctx); | ||||
|     void SetWirelessLanEnableFlag(HLERequestContext& ctx); | ||||
|     void GetInitialLaunchSettings(HLERequestContext& ctx); | ||||
|     void SetInitialLaunchSettings(HLERequestContext& ctx); | ||||
|     void GetDeviceNickName(HLERequestContext& ctx); | ||||
|     void SetDeviceNickName(HLERequestContext& ctx); | ||||
|     void GetProductModel(HLERequestContext& ctx); | ||||
|     void GetBluetoothEnableFlag(HLERequestContext& ctx); | ||||
|     void SetBluetoothEnableFlag(HLERequestContext& ctx); | ||||
|     void GetMiiAuthorId(HLERequestContext& ctx); | ||||
|     void GetAutoUpdateEnableFlag(HLERequestContext& ctx); | ||||
|     void SetAutoUpdateEnableFlag(HLERequestContext& ctx); | ||||
|     void GetBatteryPercentageFlag(HLERequestContext& ctx); | ||||
|     void SetBatteryPercentageFlag(HLERequestContext& ctx); | ||||
|     void SetExternalSteadyClockInternalOffset(HLERequestContext& ctx); | ||||
|     void GetExternalSteadyClockInternalOffset(HLERequestContext& ctx); | ||||
|     void GetPushNotificationActivityModeOnSleep(HLERequestContext& ctx); | ||||
|     void SetPushNotificationActivityModeOnSleep(HLERequestContext& ctx); | ||||
|     void GetErrorReportSharePermission(HLERequestContext& ctx); | ||||
|     void SetErrorReportSharePermission(HLERequestContext& ctx); | ||||
|     void GetAppletLaunchFlags(HLERequestContext& ctx); | ||||
|     void SetAppletLaunchFlags(HLERequestContext& ctx); | ||||
|     void GetKeyboardLayout(HLERequestContext& ctx); | ||||
|     void SetKeyboardLayout(HLERequestContext& ctx); | ||||
|     void GetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx); | ||||
|     void SetDeviceTimeZoneLocationUpdatedTime(HLERequestContext& ctx); | ||||
|     void GetUserSystemClockAutomaticCorrectionUpdatedTime(HLERequestContext& ctx); | ||||
|     void SetUserSystemClockAutomaticCorrectionUpdatedTime(HLERequestContext& ctx); | ||||
|     void GetChineseTraditionalInputMethod(HLERequestContext& ctx); | ||||
|     void GetHomeMenuScheme(HLERequestContext& ctx); | ||||
|     void GetHomeMenuSchemeModel(HLERequestContext& ctx); | ||||
|     void GetTouchScreenMode(HLERequestContext& ctx); | ||||
|     void SetTouchScreenMode(HLERequestContext& ctx); | ||||
|     void GetFieldTestingFlag(HLERequestContext& ctx); | ||||
|     void GetPanelCrcMode(HLERequestContext& ctx); | ||||
|     void SetPanelCrcMode(HLERequestContext& ctx); | ||||
|  | ||||
|     bool LoadSettingsFile(std::filesystem::path& path, auto&& default_func); | ||||
|     bool StoreSettingsFile(std::filesystem::path& path, auto& settings); | ||||
|     void SetupSettings(); | ||||
|   | ||||
							
								
								
									
										319
									
								
								src/core/hle/service/vi/application_display_service.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										319
									
								
								src/core/hle/service/vi/application_display_service.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,319 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| #include "core/hle/service/cmif_serialization.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"}, m_nvnflinger{nvnflinger}, | ||||
|       m_hos_binder_driver_server{hos_binder_driver_server} { | ||||
|  | ||||
|     // clang-format off | ||||
|     static const FunctionInfo functions[] = { | ||||
|         {100, C<&IApplicationDisplayService::GetRelayService>, "GetRelayService"}, | ||||
|         {101, C<&IApplicationDisplayService::GetSystemDisplayService>, "GetSystemDisplayService"}, | ||||
|         {102, C<&IApplicationDisplayService::GetManagerDisplayService>, "GetManagerDisplayService"}, | ||||
|         {103, C<&IApplicationDisplayService::GetIndirectDisplayTransactionService>, "GetIndirectDisplayTransactionService"}, | ||||
|         {1000, C<&IApplicationDisplayService::ListDisplays>, "ListDisplays"}, | ||||
|         {1010, C<&IApplicationDisplayService::OpenDisplay>, "OpenDisplay"}, | ||||
|         {1011, C<&IApplicationDisplayService::OpenDefaultDisplay>, "OpenDefaultDisplay"}, | ||||
|         {1020, C<&IApplicationDisplayService::CloseDisplay>, "CloseDisplay"}, | ||||
|         {1101, C<&IApplicationDisplayService::SetDisplayEnabled>, "SetDisplayEnabled"}, | ||||
|         {1102, C<&IApplicationDisplayService::GetDisplayResolution>, "GetDisplayResolution"}, | ||||
|         {2020, C<&IApplicationDisplayService::OpenLayer>, "OpenLayer"}, | ||||
|         {2021, C<&IApplicationDisplayService::CloseLayer>, "CloseLayer"}, | ||||
|         {2030, C<&IApplicationDisplayService::CreateStrayLayer>, "CreateStrayLayer"}, | ||||
|         {2031, C<&IApplicationDisplayService::DestroyStrayLayer>, "DestroyStrayLayer"}, | ||||
|         {2101, C<&IApplicationDisplayService::SetLayerScalingMode>, "SetLayerScalingMode"}, | ||||
|         {2102, C<&IApplicationDisplayService::ConvertScalingMode>, "ConvertScalingMode"}, | ||||
|         {2450, C<&IApplicationDisplayService::GetIndirectLayerImageMap>, "GetIndirectLayerImageMap"}, | ||||
|         {2451, nullptr, "GetIndirectLayerImageCropMap"}, | ||||
|         {2460, C<&IApplicationDisplayService::GetIndirectLayerImageRequiredMemoryInfo>, "GetIndirectLayerImageRequiredMemoryInfo"}, | ||||
|         {5202, C<&IApplicationDisplayService::GetDisplayVsyncEvent>, "GetDisplayVsyncEvent"}, | ||||
|         {5203, nullptr, "GetDisplayVsyncEventForDebug"}, | ||||
|     }; | ||||
|     // clang-format on | ||||
|  | ||||
|     RegisterHandlers(functions); | ||||
| } | ||||
|  | ||||
| IApplicationDisplayService::~IApplicationDisplayService() { | ||||
|     for (const auto layer_id : m_stray_layer_ids) { | ||||
|         m_nvnflinger.DestroyLayer(layer_id); | ||||
|     } | ||||
| } | ||||
|  | ||||
| Result IApplicationDisplayService::GetRelayService( | ||||
|     Out<SharedPointer<IHOSBinderDriver>> out_relay_service) { | ||||
|     LOG_WARNING(Service_VI, "(STUBBED) called"); | ||||
|     *out_relay_service = std::make_shared<IHOSBinderDriver>(system, m_hos_binder_driver_server); | ||||
|     R_SUCCEED(); | ||||
| } | ||||
|  | ||||
| Result IApplicationDisplayService::GetSystemDisplayService( | ||||
|     Out<SharedPointer<ISystemDisplayService>> out_system_display_service) { | ||||
|     LOG_WARNING(Service_VI, "(STUBBED) called"); | ||||
|     *out_system_display_service = std::make_shared<ISystemDisplayService>(system, m_nvnflinger); | ||||
|     R_SUCCEED(); | ||||
| } | ||||
|  | ||||
| Result IApplicationDisplayService::GetManagerDisplayService( | ||||
|     Out<SharedPointer<IManagerDisplayService>> out_manager_display_service) { | ||||
|     LOG_WARNING(Service_VI, "(STUBBED) called"); | ||||
|     *out_manager_display_service = std::make_shared<IManagerDisplayService>(system, m_nvnflinger); | ||||
|     R_SUCCEED(); | ||||
| } | ||||
|  | ||||
| Result IApplicationDisplayService::GetIndirectDisplayTransactionService( | ||||
|     Out<SharedPointer<IHOSBinderDriver>> out_indirect_display_transaction_service) { | ||||
|     LOG_WARNING(Service_VI, "(STUBBED) called"); | ||||
|     *out_indirect_display_transaction_service = | ||||
|         std::make_shared<IHOSBinderDriver>(system, m_hos_binder_driver_server); | ||||
|     R_SUCCEED(); | ||||
| } | ||||
|  | ||||
| Result IApplicationDisplayService::OpenDisplay(Out<u64> out_display_id, DisplayName display_name) { | ||||
|     LOG_WARNING(Service_VI, "(STUBBED) called"); | ||||
|  | ||||
|     display_name[display_name.size() - 1] = '\0'; | ||||
|     ASSERT_MSG(strcmp(display_name.data(), "Default") == 0, | ||||
|                "Non-default displays aren't supported yet"); | ||||
|  | ||||
|     const auto display_id = m_nvnflinger.OpenDisplay(display_name.data()); | ||||
|     if (!display_id) { | ||||
|         LOG_ERROR(Service_VI, "Display not found! display_name={}", display_name.data()); | ||||
|         R_THROW(VI::ResultNotFound); | ||||
|     } | ||||
|  | ||||
|     *out_display_id = *display_id; | ||||
|     R_SUCCEED(); | ||||
| } | ||||
|  | ||||
| Result IApplicationDisplayService::OpenDefaultDisplay(Out<u64> out_display_id) { | ||||
|     LOG_DEBUG(Service_VI, "called"); | ||||
|     R_RETURN(this->OpenDisplay(out_display_id, DisplayName{"Default"})); | ||||
| } | ||||
|  | ||||
| Result IApplicationDisplayService::CloseDisplay(u64 display_id) { | ||||
|     LOG_DEBUG(Service_VI, "called"); | ||||
|     R_SUCCEED_IF(m_nvnflinger.CloseDisplay(display_id)); | ||||
|     R_THROW(ResultUnknown); | ||||
| } | ||||
|  | ||||
| Result IApplicationDisplayService::SetDisplayEnabled(u32 state, u64 display_id) { | ||||
|     LOG_DEBUG(Service_VI, "called"); | ||||
|  | ||||
|     // This literally does nothing internally in the actual service itself, | ||||
|     // and just returns a successful result code regardless of the input. | ||||
|     R_SUCCEED(); | ||||
| } | ||||
|  | ||||
| Result IApplicationDisplayService::GetDisplayResolution(Out<s64> out_width, Out<s64> out_height, | ||||
|                                                         u64 display_id) { | ||||
|     LOG_DEBUG(Service_VI, "called. display_id={}", display_id); | ||||
|  | ||||
|     // This only returns the fixed values of 1280x720 and makes no distinguishing | ||||
|     // between docked and undocked dimensions. | ||||
|     *out_width = static_cast<s64>(DisplayResolution::UndockedWidth); | ||||
|     *out_height = static_cast<s64>(DisplayResolution::UndockedHeight); | ||||
|     R_SUCCEED(); | ||||
| } | ||||
|  | ||||
| Result IApplicationDisplayService::SetLayerScalingMode(NintendoScaleMode scale_mode, u64 layer_id) { | ||||
|     LOG_DEBUG(Service_VI, "called. scale_mode={}, unknown=0x{:016X}", scale_mode, layer_id); | ||||
|  | ||||
|     if (scale_mode > NintendoScaleMode::PreserveAspectRatio) { | ||||
|         LOG_ERROR(Service_VI, "Invalid scaling mode provided."); | ||||
|         R_THROW(VI::ResultOperationFailed); | ||||
|     } | ||||
|  | ||||
|     if (scale_mode != NintendoScaleMode::ScaleToWindow && | ||||
|         scale_mode != NintendoScaleMode::PreserveAspectRatio) { | ||||
|         LOG_ERROR(Service_VI, "Unsupported scaling mode supplied."); | ||||
|         R_THROW(VI::ResultNotSupported); | ||||
|     } | ||||
|  | ||||
|     R_SUCCEED(); | ||||
| } | ||||
|  | ||||
| Result IApplicationDisplayService::ListDisplays( | ||||
|     Out<u64> out_count, OutArray<DisplayInfo, BufferAttr_HipcMapAlias> out_displays) { | ||||
|     LOG_WARNING(Service_VI, "(STUBBED) called"); | ||||
|  | ||||
|     if (out_displays.size() > 0) { | ||||
|         out_displays[0] = DisplayInfo{}; | ||||
|         *out_count = 1; | ||||
|     } else { | ||||
|         *out_count = 0; | ||||
|     } | ||||
|  | ||||
|     R_SUCCEED(); | ||||
| } | ||||
|  | ||||
| Result IApplicationDisplayService::OpenLayer(Out<u64> out_size, | ||||
|                                              OutBuffer<BufferAttr_HipcMapAlias> out_native_window, | ||||
|                                              DisplayName display_name, u64 layer_id, | ||||
|                                              ClientAppletResourceUserId aruid) { | ||||
|     display_name[display_name.size() - 1] = '\0'; | ||||
|  | ||||
|     LOG_DEBUG(Service_VI, "called. layer_id={}, aruid={:#x}", layer_id, aruid.pid); | ||||
|  | ||||
|     const auto display_id = m_nvnflinger.OpenDisplay(display_name.data()); | ||||
|     if (!display_id) { | ||||
|         LOG_ERROR(Service_VI, "Layer not found! layer_id={}", layer_id); | ||||
|         R_THROW(VI::ResultNotFound); | ||||
|     } | ||||
|  | ||||
|     const auto buffer_queue_id = m_nvnflinger.FindBufferQueueId(*display_id, layer_id); | ||||
|     if (!buffer_queue_id) { | ||||
|         LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", *display_id); | ||||
|         R_THROW(VI::ResultNotFound); | ||||
|     } | ||||
|  | ||||
|     if (!m_nvnflinger.OpenLayer(layer_id)) { | ||||
|         LOG_WARNING(Service_VI, "Tried to open layer which was already open"); | ||||
|         R_THROW(VI::ResultOperationFailed); | ||||
|     } | ||||
|  | ||||
|     android::OutputParcel parcel; | ||||
|     parcel.WriteInterface(NativeWindow{*buffer_queue_id}); | ||||
|  | ||||
|     const auto buffer = parcel.Serialize(); | ||||
|     std::memcpy(out_native_window.data(), buffer.data(), | ||||
|                 std::min(out_native_window.size(), buffer.size())); | ||||
|     *out_size = buffer.size(); | ||||
|  | ||||
|     R_SUCCEED(); | ||||
| } | ||||
|  | ||||
| Result IApplicationDisplayService::CloseLayer(u64 layer_id) { | ||||
|     LOG_DEBUG(Service_VI, "called. layer_id={}", layer_id); | ||||
|  | ||||
|     if (!m_nvnflinger.CloseLayer(layer_id)) { | ||||
|         LOG_WARNING(Service_VI, "Tried to close layer which was not open"); | ||||
|         R_THROW(VI::ResultOperationFailed); | ||||
|     } | ||||
|  | ||||
|     R_SUCCEED(); | ||||
| } | ||||
|  | ||||
| Result IApplicationDisplayService::CreateStrayLayer( | ||||
|     Out<u64> out_layer_id, Out<u64> out_size, OutBuffer<BufferAttr_HipcMapAlias> out_native_window, | ||||
|     u32 flags, u64 display_id) { | ||||
|     LOG_DEBUG(Service_VI, "called. flags={}, display_id={}", flags, display_id); | ||||
|  | ||||
|     const auto layer_id = m_nvnflinger.CreateLayer(display_id); | ||||
|     if (!layer_id) { | ||||
|         LOG_ERROR(Service_VI, "Layer not found! display_id={}", display_id); | ||||
|         R_THROW(VI::ResultNotFound); | ||||
|     } | ||||
|  | ||||
|     m_stray_layer_ids.push_back(*layer_id); | ||||
|     const auto buffer_queue_id = m_nvnflinger.FindBufferQueueId(display_id, *layer_id); | ||||
|     if (!buffer_queue_id) { | ||||
|         LOG_ERROR(Service_VI, "Buffer queue id not found! display_id={}", display_id); | ||||
|         R_THROW(VI::ResultNotFound); | ||||
|     } | ||||
|  | ||||
|     android::OutputParcel parcel; | ||||
|     parcel.WriteInterface(NativeWindow{*buffer_queue_id}); | ||||
|  | ||||
|     const auto buffer = parcel.Serialize(); | ||||
|     std::memcpy(out_native_window.data(), buffer.data(), | ||||
|                 std::min(out_native_window.size(), buffer.size())); | ||||
|  | ||||
|     *out_layer_id = *layer_id; | ||||
|     *out_size = buffer.size(); | ||||
|  | ||||
|     R_SUCCEED(); | ||||
| } | ||||
|  | ||||
| Result IApplicationDisplayService::DestroyStrayLayer(u64 layer_id) { | ||||
|     LOG_WARNING(Service_VI, "(STUBBED) called. layer_id={}", layer_id); | ||||
|     m_nvnflinger.DestroyLayer(layer_id); | ||||
|     R_SUCCEED(); | ||||
| } | ||||
|  | ||||
| Result IApplicationDisplayService::GetDisplayVsyncEvent( | ||||
|     OutCopyHandle<Kernel::KReadableEvent> out_vsync_event, u64 display_id) { | ||||
|     LOG_DEBUG(Service_VI, "called. display_id={}", display_id); | ||||
|  | ||||
|     const auto result = m_nvnflinger.FindVsyncEvent(out_vsync_event, display_id); | ||||
|     if (result != ResultSuccess) { | ||||
|         if (result == ResultNotFound) { | ||||
|             LOG_ERROR(Service_VI, "Vsync event was not found for display_id={}", display_id); | ||||
|         } | ||||
|  | ||||
|         R_THROW(result); | ||||
|     } | ||||
|  | ||||
|     R_UNLESS(!m_vsync_event_fetched, VI::ResultPermissionDenied); | ||||
|     m_vsync_event_fetched = true; | ||||
|  | ||||
|     R_SUCCEED(); | ||||
| } | ||||
|  | ||||
| Result IApplicationDisplayService::ConvertScalingMode(Out<ConvertedScaleMode> out_scaling_mode, | ||||
|                                                       NintendoScaleMode mode) { | ||||
|     LOG_DEBUG(Service_VI, "called mode={}", mode); | ||||
|  | ||||
|     switch (mode) { | ||||
|     case NintendoScaleMode::None: | ||||
|         *out_scaling_mode = ConvertedScaleMode::None; | ||||
|         R_SUCCEED(); | ||||
|     case NintendoScaleMode::Freeze: | ||||
|         *out_scaling_mode = ConvertedScaleMode::Freeze; | ||||
|         R_SUCCEED(); | ||||
|     case NintendoScaleMode::ScaleToWindow: | ||||
|         *out_scaling_mode = ConvertedScaleMode::ScaleToWindow; | ||||
|         R_SUCCEED(); | ||||
|     case NintendoScaleMode::ScaleAndCrop: | ||||
|         *out_scaling_mode = ConvertedScaleMode::ScaleAndCrop; | ||||
|         R_SUCCEED(); | ||||
|     case NintendoScaleMode::PreserveAspectRatio: | ||||
|         *out_scaling_mode = ConvertedScaleMode::PreserveAspectRatio; | ||||
|         R_SUCCEED(); | ||||
|     default: | ||||
|         LOG_ERROR(Service_VI, "Invalid scaling mode specified, mode={}", mode); | ||||
|         R_THROW(VI::ResultOperationFailed); | ||||
|     } | ||||
| } | ||||
|  | ||||
| Result IApplicationDisplayService::GetIndirectLayerImageMap( | ||||
|     Out<u64> out_size, Out<u64> out_stride, | ||||
|     OutBuffer<BufferAttr_HipcMapTransferAllowsNonSecure | BufferAttr_HipcMapAlias> out_buffer, | ||||
|     s64 width, s64 height, u64 indirect_layer_consumer_handle, ClientAppletResourceUserId aruid) { | ||||
|     LOG_WARNING( | ||||
|         Service_VI, | ||||
|         "(STUBBED) called, width={}, height={}, indirect_layer_consumer_handle={}, aruid={:#x}", | ||||
|         width, height, indirect_layer_consumer_handle, aruid.pid); | ||||
|     *out_size = 0; | ||||
|     *out_stride = 0; | ||||
|     R_SUCCEED(); | ||||
| } | ||||
|  | ||||
| Result IApplicationDisplayService::GetIndirectLayerImageRequiredMemoryInfo(Out<s64> out_size, | ||||
|                                                                            Out<s64> out_alignment, | ||||
|                                                                            s64 width, s64 height) { | ||||
|     LOG_DEBUG(Service_VI, "called width={}, height={}", width, height); | ||||
|  | ||||
|     constexpr u64 base_size = 0x20000; | ||||
|     const auto texture_size = width * height * 4; | ||||
|  | ||||
|     *out_alignment = 0x1000; | ||||
|     *out_size = (texture_size + base_size - 1) / base_size * base_size; | ||||
|  | ||||
|     R_SUCCEED(); | ||||
| } | ||||
|  | ||||
| } // namespace Service::VI | ||||
							
								
								
									
										65
									
								
								src/core/hle/service/vi/application_display_service.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								src/core/hle/service/vi/application_display_service.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| #include "core/hle/service/cmif_types.h" | ||||
| #include "core/hle/service/service.h" | ||||
| #include "core/hle/service/vi/vi_types.h" | ||||
|  | ||||
| namespace Kernel { | ||||
| class KReadableEvent; | ||||
| } | ||||
|  | ||||
| namespace Service::VI { | ||||
|  | ||||
| class IHOSBinderDriver; | ||||
| class IManagerDisplayService; | ||||
| class ISystemDisplayService; | ||||
|  | ||||
| class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> { | ||||
| public: | ||||
|     IApplicationDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, | ||||
|                                Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); | ||||
|     ~IApplicationDisplayService() override; | ||||
|  | ||||
| private: | ||||
|     Result GetRelayService(Out<SharedPointer<IHOSBinderDriver>> out_relay_service); | ||||
|     Result GetSystemDisplayService( | ||||
|         Out<SharedPointer<ISystemDisplayService>> out_system_display_service); | ||||
|     Result GetManagerDisplayService( | ||||
|         Out<SharedPointer<IManagerDisplayService>> out_manager_display_service); | ||||
|     Result GetIndirectDisplayTransactionService( | ||||
|         Out<SharedPointer<IHOSBinderDriver>> out_indirect_display_transaction_service); | ||||
|     Result OpenDisplay(Out<u64> out_display_id, DisplayName display_name); | ||||
|     Result OpenDefaultDisplay(Out<u64> out_display_id); | ||||
|     Result CloseDisplay(u64 display_id); | ||||
|     Result SetDisplayEnabled(u32 state, u64 display_id); | ||||
|     Result GetDisplayResolution(Out<s64> out_width, Out<s64> out_height, u64 display_id); | ||||
|     Result SetLayerScalingMode(NintendoScaleMode scale_mode, u64 layer_id); | ||||
|     Result ListDisplays(Out<u64> out_count, | ||||
|                         OutArray<DisplayInfo, BufferAttr_HipcMapAlias> out_displays); | ||||
|     Result OpenLayer(Out<u64> out_size, OutBuffer<BufferAttr_HipcMapAlias> out_native_window, | ||||
|                      DisplayName display_name, u64 layer_id, ClientAppletResourceUserId aruid); | ||||
|     Result CloseLayer(u64 layer_id); | ||||
|     Result CreateStrayLayer(Out<u64> out_layer_id, Out<u64> out_size, | ||||
|                             OutBuffer<BufferAttr_HipcMapAlias> out_native_window, u32 flags, | ||||
|                             u64 display_id); | ||||
|     Result DestroyStrayLayer(u64 layer_id); | ||||
|     Result GetDisplayVsyncEvent(OutCopyHandle<Kernel::KReadableEvent> out_vsync_event, | ||||
|                                 u64 display_id); | ||||
|     Result ConvertScalingMode(Out<ConvertedScaleMode> out_scaling_mode, NintendoScaleMode mode); | ||||
|     Result GetIndirectLayerImageMap( | ||||
|         Out<u64> out_size, Out<u64> out_stride, | ||||
|         OutBuffer<BufferAttr_HipcMapTransferAllowsNonSecure | BufferAttr_HipcMapAlias> out_buffer, | ||||
|         s64 width, s64 height, u64 indirect_layer_consumer_handle, | ||||
|         ClientAppletResourceUserId aruid); | ||||
|     Result GetIndirectLayerImageRequiredMemoryInfo(Out<s64> out_size, Out<s64> out_alignment, | ||||
|                                                    s64 width, s64 height); | ||||
|  | ||||
| private: | ||||
|     Nvnflinger::Nvnflinger& m_nvnflinger; | ||||
|     Nvnflinger::HosBinderDriverServer& m_hos_binder_driver_server; | ||||
|     std::vector<u64> m_stray_layer_ids; | ||||
|     bool m_vsync_event_fetched{false}; | ||||
| }; | ||||
|  | ||||
| } // namespace Service::VI | ||||
							
								
								
									
										34
									
								
								src/core/hle/service/vi/application_root_service.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/core/hle/service/vi/application_root_service.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| #include "core/hle/service/cmif_serialization.h" | ||||
| #include "core/hle/service/vi/application_display_service.h" | ||||
| #include "core/hle/service/vi/application_root_service.h" | ||||
| #include "core/hle/service/vi/service_creator.h" | ||||
| #include "core/hle/service/vi/vi.h" | ||||
| #include "core/hle/service/vi/vi_types.h" | ||||
|  | ||||
| namespace Service::VI { | ||||
|  | ||||
| IApplicationRootService::IApplicationRootService( | ||||
|     Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, | ||||
|     Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) | ||||
|     : ServiceFramework{system_, "vi:u"}, m_nvnflinger{nvnflinger}, m_hos_binder_driver_server{ | ||||
|                                                                        hos_binder_driver_server} { | ||||
|     static const FunctionInfo functions[] = { | ||||
|         {0, C<&IApplicationRootService::GetDisplayService>, "GetDisplayService"}, | ||||
|         {1, nullptr, "GetDisplayServiceWithProxyNameExchange"}, | ||||
|     }; | ||||
|     RegisterHandlers(functions); | ||||
| } | ||||
|  | ||||
| IApplicationRootService::~IApplicationRootService() = default; | ||||
|  | ||||
| Result IApplicationRootService::GetDisplayService( | ||||
|     Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, Policy policy) { | ||||
|     LOG_DEBUG(Service_VI, "called"); | ||||
|     R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_nvnflinger, | ||||
|                                           m_hos_binder_driver_server, Permission::User, policy)); | ||||
| } | ||||
|  | ||||
| } // namespace Service::VI | ||||
							
								
								
									
										39
									
								
								src/core/hle/service/vi/application_root_service.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/core/hle/service/vi/application_root_service.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "core/hle/service/cmif_types.h" | ||||
| #include "core/hle/service/service.h" | ||||
|  | ||||
| namespace Core { | ||||
| class System; | ||||
| } | ||||
|  | ||||
| namespace Service::Nvnflinger { | ||||
| class HosBinderDriverServer; | ||||
| class Nvnflinger; | ||||
| } // namespace Service::Nvnflinger | ||||
|  | ||||
| namespace Service::VI { | ||||
|  | ||||
| class IApplicationDisplayService; | ||||
| enum class Policy : u32; | ||||
|  | ||||
| class IApplicationRootService final : public ServiceFramework<IApplicationRootService> { | ||||
| public: | ||||
|     explicit IApplicationRootService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, | ||||
|                                      Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); | ||||
|     ~IApplicationRootService() override; | ||||
|  | ||||
| private: | ||||
|     Result GetDisplayService( | ||||
|         Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, | ||||
|         Policy policy); | ||||
|  | ||||
| private: | ||||
|     Nvnflinger::Nvnflinger& m_nvnflinger; | ||||
|     Nvnflinger::HosBinderDriverServer& m_hos_binder_driver_server; | ||||
| }; | ||||
|  | ||||
| } // namespace Service::VI | ||||
							
								
								
									
										53
									
								
								src/core/hle/service/vi/hos_binder_driver.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/core/hle/service/vi/hos_binder_driver.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| #include "core/hle/service/cmif_serialization.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"}, m_server(server) { | ||||
|     static const FunctionInfo functions[] = { | ||||
|         {0, C<&IHOSBinderDriver::TransactParcel>, "TransactParcel"}, | ||||
|         {1, C<&IHOSBinderDriver::AdjustRefcount>, "AdjustRefcount"}, | ||||
|         {2, C<&IHOSBinderDriver::GetNativeHandle>, "GetNativeHandle"}, | ||||
|         {3, C<&IHOSBinderDriver::TransactParcelAuto>, "TransactParcelAuto"}, | ||||
|     }; | ||||
|     RegisterHandlers(functions); | ||||
| } | ||||
|  | ||||
| IHOSBinderDriver::~IHOSBinderDriver() = default; | ||||
|  | ||||
| Result IHOSBinderDriver::TransactParcel(s32 binder_id, android::TransactionId transaction_id, | ||||
|                                         InBuffer<BufferAttr_HipcMapAlias> parcel_data, | ||||
|                                         OutBuffer<BufferAttr_HipcMapAlias> parcel_reply, | ||||
|                                         u32 flags) { | ||||
|     LOG_DEBUG(Service_VI, "called. id={} transaction={}, flags={}", binder_id, transaction_id, | ||||
|               flags); | ||||
|     m_server.TryGetProducer(binder_id)->Transact(transaction_id, flags, parcel_data, parcel_reply); | ||||
|     R_SUCCEED(); | ||||
| } | ||||
|  | ||||
| Result IHOSBinderDriver::AdjustRefcount(s32 binder_id, s32 addval, s32 type) { | ||||
|     LOG_WARNING(Service_VI, "(STUBBED) called id={}, addval={}, type={}", binder_id, addval, type); | ||||
|     R_SUCCEED(); | ||||
| } | ||||
|  | ||||
| Result IHOSBinderDriver::GetNativeHandle(s32 binder_id, u32 type_id, | ||||
|                                          OutCopyHandle<Kernel::KReadableEvent> out_handle) { | ||||
|     LOG_WARNING(Service_VI, "(STUBBED) called id={}, type_id={}", binder_id, type_id); | ||||
|     *out_handle = &m_server.TryGetProducer(binder_id)->GetNativeHandle(); | ||||
|     R_SUCCEED(); | ||||
| } | ||||
|  | ||||
| Result IHOSBinderDriver::TransactParcelAuto(s32 binder_id, android::TransactionId transaction_id, | ||||
|                                             InBuffer<BufferAttr_HipcAutoSelect> parcel_data, | ||||
|                                             OutBuffer<BufferAttr_HipcAutoSelect> parcel_reply, | ||||
|                                             u32 flags) { | ||||
|     R_RETURN(this->TransactParcel(binder_id, transaction_id, parcel_data, parcel_reply, flags)); | ||||
| } | ||||
|  | ||||
| } // namespace Service::VI | ||||
							
								
								
									
										30
									
								
								src/core/hle/service/vi/hos_binder_driver.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/core/hle/service/vi/hos_binder_driver.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| #include "core/hle/service/cmif_types.h" | ||||
| #include "core/hle/service/nvnflinger/binder.h" | ||||
| #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: | ||||
|     Result TransactParcel(s32 binder_id, android::TransactionId transaction_id, | ||||
|                           InBuffer<BufferAttr_HipcMapAlias> parcel_data, | ||||
|                           OutBuffer<BufferAttr_HipcMapAlias> parcel_reply, u32 flags); | ||||
|     Result AdjustRefcount(s32 binder_id, s32 addval, s32 type); | ||||
|     Result GetNativeHandle(s32 binder_id, u32 type_id, | ||||
|                            OutCopyHandle<Kernel::KReadableEvent> out_handle); | ||||
|     Result TransactParcelAuto(s32 binder_id, android::TransactionId transaction_id, | ||||
|                               InBuffer<BufferAttr_HipcAutoSelect> parcel_data, | ||||
|                               OutBuffer<BufferAttr_HipcAutoSelect> parcel_reply, u32 flags); | ||||
|  | ||||
| private: | ||||
|     Nvnflinger::HosBinderDriverServer& m_server; | ||||
| }; | ||||
|  | ||||
| } // namespace Service::VI | ||||
							
								
								
									
										130
									
								
								src/core/hle/service/vi/manager_display_service.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										130
									
								
								src/core/hle/service/vi/manager_display_service.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,130 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| #include "core/hle/service/cmif_serialization.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"}, m_nvnflinger{nvnflinger} { | ||||
|     // clang-format off | ||||
|     static const FunctionInfo functions[] = { | ||||
|         {200, nullptr, "AllocateProcessHeapBlock"}, | ||||
|         {201, nullptr, "FreeProcessHeapBlock"}, | ||||
|         {1102, nullptr, "GetDisplayResolution"}, | ||||
|         {2010, C<&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, C<&IManagerDisplayService::AddToLayerStack>, "AddToLayerStack"}, | ||||
|         {6001, nullptr, "RemoveFromLayerStack"}, | ||||
|         {6002, C<&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; | ||||
|  | ||||
| Result IManagerDisplayService::CreateManagedLayer(Out<u64> out_layer_id, u32 unknown, | ||||
|                                                   u64 display_id, AppletResourceUserId aruid) { | ||||
|     LOG_WARNING(Service_VI, "(STUBBED) called. unknown={}, display={}, aruid={}", unknown, | ||||
|                 display_id, aruid.pid); | ||||
|  | ||||
|     const auto layer_id = m_nvnflinger.CreateLayer(display_id); | ||||
|     if (!layer_id) { | ||||
|         LOG_ERROR(Service_VI, "Layer not found! display={}", display_id); | ||||
|         R_THROW(VI::ResultNotFound); | ||||
|     } | ||||
|  | ||||
|     *out_layer_id = *layer_id; | ||||
|     R_SUCCEED(); | ||||
| } | ||||
|  | ||||
| Result IManagerDisplayService::AddToLayerStack(u32 stack_id, u64 layer_id) { | ||||
|     LOG_WARNING(Service_VI, "(STUBBED) called. stack_id={}, layer_id={}", stack_id, layer_id); | ||||
|     R_SUCCEED(); | ||||
| } | ||||
|  | ||||
| Result IManagerDisplayService::SetLayerVisibility(bool visible, u64 layer_id) { | ||||
|     LOG_WARNING(Service_VI, "(STUBBED) called, layer_id={}, visible={}", layer_id, visible); | ||||
|     R_SUCCEED(); | ||||
| } | ||||
|  | ||||
| } // namespace Service::VI | ||||
							
								
								
									
										24
									
								
								src/core/hle/service/vi/manager_display_service.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/core/hle/service/vi/manager_display_service.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| #include "core/hle/service/cmif_types.h" | ||||
| #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: | ||||
|     Result CreateManagedLayer(Out<u64> out_layer_id, u32 unknown, u64 display_id, | ||||
|                               AppletResourceUserId aruid); | ||||
|     Result AddToLayerStack(u32 stack_id, u64 layer_id); | ||||
|     Result SetLayerVisibility(bool visible, u64 layer_id); | ||||
|  | ||||
| private: | ||||
|     Nvnflinger::Nvnflinger& m_nvnflinger; | ||||
| }; | ||||
|  | ||||
| } // namespace Service::VI | ||||
							
								
								
									
										38
									
								
								src/core/hle/service/vi/manager_root_service.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/core/hle/service/vi/manager_root_service.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| #include "core/hle/service/cmif_serialization.h" | ||||
| #include "core/hle/service/vi/application_display_service.h" | ||||
| #include "core/hle/service/vi/manager_root_service.h" | ||||
| #include "core/hle/service/vi/service_creator.h" | ||||
| #include "core/hle/service/vi/vi.h" | ||||
| #include "core/hle/service/vi/vi_types.h" | ||||
|  | ||||
| namespace Service::VI { | ||||
|  | ||||
| IManagerRootService::IManagerRootService( | ||||
|     Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, | ||||
|     Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) | ||||
|     : ServiceFramework{system_, "vi:m"}, m_nvnflinger{nvnflinger}, m_hos_binder_driver_server{ | ||||
|                                                                        hos_binder_driver_server} { | ||||
|     static const FunctionInfo functions[] = { | ||||
|         {2, C<&IManagerRootService::GetDisplayService>, "GetDisplayService"}, | ||||
|         {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, | ||||
|         {100, nullptr, "PrepareFatal"}, | ||||
|         {101, nullptr, "ShowFatal"}, | ||||
|         {102, nullptr, "DrawFatalRectangle"}, | ||||
|         {103, nullptr, "DrawFatalText32"}, | ||||
|     }; | ||||
|     RegisterHandlers(functions); | ||||
| } | ||||
|  | ||||
| IManagerRootService::~IManagerRootService() = default; | ||||
|  | ||||
| Result IManagerRootService::GetDisplayService( | ||||
|     Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, Policy policy) { | ||||
|     LOG_DEBUG(Service_VI, "called"); | ||||
|     R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_nvnflinger, | ||||
|                                           m_hos_binder_driver_server, Permission::Manager, policy)); | ||||
| } | ||||
|  | ||||
| } // namespace Service::VI | ||||
							
								
								
									
										38
									
								
								src/core/hle/service/vi/manager_root_service.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/core/hle/service/vi/manager_root_service.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "core/hle/service/cmif_types.h" | ||||
| #include "core/hle/service/service.h" | ||||
|  | ||||
| namespace Core { | ||||
| class System; | ||||
| } | ||||
|  | ||||
| namespace Service::Nvnflinger { | ||||
| class HosBinderDriverServer; | ||||
| class Nvnflinger; | ||||
| } // namespace Service::Nvnflinger | ||||
|  | ||||
| namespace Service::VI { | ||||
|  | ||||
| class IApplicationDisplayService; | ||||
| enum class Policy : u32; | ||||
|  | ||||
| class IManagerRootService final : public ServiceFramework<IManagerRootService> { | ||||
| public: | ||||
|     explicit IManagerRootService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, | ||||
|                                  Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); | ||||
|     ~IManagerRootService() override; | ||||
|  | ||||
| private: | ||||
|     Result GetDisplayService( | ||||
|         Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, | ||||
|         Policy policy); | ||||
|  | ||||
|     Nvnflinger::Nvnflinger& m_nvnflinger; | ||||
|     Nvnflinger::HosBinderDriverServer& m_hos_binder_driver_server; | ||||
| }; | ||||
|  | ||||
| } // namespace Service::VI | ||||
							
								
								
									
										39
									
								
								src/core/hle/service/vi/service_creator.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/core/hle/service/vi/service_creator.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| #include "core/hle/service/vi/application_display_service.h" | ||||
| #include "core/hle/service/vi/service_creator.h" | ||||
| #include "core/hle/service/vi/vi_results.h" | ||||
| #include "core/hle/service/vi/vi_types.h" | ||||
|  | ||||
| namespace Service::VI { | ||||
|  | ||||
| static bool IsValidServiceAccess(Permission permission, Policy policy) { | ||||
|     if (permission == Permission::User) { | ||||
|         return policy == Policy::User; | ||||
|     } | ||||
|  | ||||
|     if (permission == Permission::System || permission == Permission::Manager) { | ||||
|         return policy == Policy::User || policy == Policy::Compositor; | ||||
|     } | ||||
|  | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| Result GetApplicationDisplayService( | ||||
|     std::shared_ptr<IApplicationDisplayService>* out_application_display_service, | ||||
|     Core::System& system, Nvnflinger::Nvnflinger& nvnflinger, | ||||
|     Nvnflinger::HosBinderDriverServer& hos_binder_driver_server, Permission permission, | ||||
|     Policy policy) { | ||||
|  | ||||
|     if (!IsValidServiceAccess(permission, policy)) { | ||||
|         LOG_ERROR(Service_VI, "Permission denied for policy {}", policy); | ||||
|         R_THROW(ResultPermissionDenied); | ||||
|     } | ||||
|  | ||||
|     *out_application_display_service = | ||||
|         std::make_shared<IApplicationDisplayService>(system, nvnflinger, hos_binder_driver_server); | ||||
|     R_SUCCEED(); | ||||
| } | ||||
|  | ||||
| } // namespace Service::VI | ||||
							
								
								
									
										33
									
								
								src/core/hle/service/vi/service_creator.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/core/hle/service/vi/service_creator.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <memory> | ||||
|  | ||||
| #include "common/common_types.h" | ||||
|  | ||||
| namespace Core { | ||||
| class System; | ||||
| } | ||||
|  | ||||
| namespace Service::Nvnflinger { | ||||
| class HosBinderDriverServer; | ||||
| class Nvnflinger; | ||||
| } // namespace Service::Nvnflinger | ||||
|  | ||||
| union Result; | ||||
|  | ||||
| namespace Service::VI { | ||||
|  | ||||
| class IApplicationDisplayService; | ||||
| enum class Permission; | ||||
| enum class Policy : u32; | ||||
|  | ||||
| Result GetApplicationDisplayService( | ||||
|     std::shared_ptr<IApplicationDisplayService>* out_application_display_service, | ||||
|     Core::System& system, Nvnflinger::Nvnflinger& nvnflinger, | ||||
|     Nvnflinger::HosBinderDriverServer& hos_binder_driver_server, Permission permission, | ||||
|     Policy policy); | ||||
|  | ||||
| } // namespace Service::VI | ||||
							
								
								
									
										145
									
								
								src/core/hle/service/vi/system_display_service.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										145
									
								
								src/core/hle/service/vi/system_display_service.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,145 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| #include "common/settings.h" | ||||
| #include "core/hle/service/cmif_serialization.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"}, m_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, C<&ISystemDisplayService::SetLayerZ>, "SetLayerZ"}, | ||||
|         {2207, C<&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, C<&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, C<&ISystemDisplayService::GetSharedBufferMemoryHandleId>, "GetSharedBufferMemoryHandleId"}, | ||||
|         {8250, C<&ISystemDisplayService::OpenSharedLayer>, "OpenSharedLayer"}, | ||||
|         {8251, nullptr, "CloseSharedLayer"}, | ||||
|         {8252, C<&ISystemDisplayService::ConnectSharedLayer>, "ConnectSharedLayer"}, | ||||
|         {8253, nullptr, "DisconnectSharedLayer"}, | ||||
|         {8254, C<&ISystemDisplayService::AcquireSharedFrameBuffer>, "AcquireSharedFrameBuffer"}, | ||||
|         {8255, C<&ISystemDisplayService::PresentSharedFrameBuffer>, "PresentSharedFrameBuffer"}, | ||||
|         {8256, C<&ISystemDisplayService::GetSharedFrameBufferAcquirableEvent>, "GetSharedFrameBufferAcquirableEvent"}, | ||||
|         {8257, nullptr, "FillSharedFrameBufferColor"}, | ||||
|         {8258, nullptr, "CancelSharedFrameBuffer"}, | ||||
|         {9000, nullptr, "GetDp2hdmiController"}, | ||||
|     }; | ||||
|     // clang-format on | ||||
|     RegisterHandlers(functions); | ||||
| } | ||||
|  | ||||
| ISystemDisplayService::~ISystemDisplayService() = default; | ||||
|  | ||||
| Result ISystemDisplayService::SetLayerZ(u32 z_value, u64 layer_id) { | ||||
|     LOG_WARNING(Service_VI, "(STUBBED) called. layer_id={}, z_value={}", layer_id, z_value); | ||||
|     R_SUCCEED(); | ||||
| } | ||||
|  | ||||
| // 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. | ||||
| Result ISystemDisplayService::SetLayerVisibility(bool visible, u64 layer_id) { | ||||
|     LOG_DEBUG(Service_VI, "called, layer_id={}, visible={}", layer_id, visible); | ||||
|     R_SUCCEED(); | ||||
| } | ||||
|  | ||||
| Result ISystemDisplayService::GetDisplayMode(Out<u32> out_width, Out<u32> out_height, | ||||
|                                              Out<f32> out_refresh_rate, Out<u32> out_unknown) { | ||||
|     LOG_WARNING(Service_VI, "(STUBBED) called"); | ||||
|  | ||||
|     if (Settings::IsDockedMode()) { | ||||
|         *out_width = static_cast<u32>(DisplayResolution::DockedWidth); | ||||
|         *out_height = static_cast<u32>(DisplayResolution::DockedHeight); | ||||
|     } else { | ||||
|         *out_width = static_cast<u32>(DisplayResolution::UndockedWidth); | ||||
|         *out_height = static_cast<u32>(DisplayResolution::UndockedHeight); | ||||
|     } | ||||
|  | ||||
|     *out_refresh_rate = 60.f; // This wouldn't seem to be correct for 30 fps games. | ||||
|     *out_unknown = 0; | ||||
|  | ||||
|     R_SUCCEED(); | ||||
| } | ||||
|  | ||||
| Result ISystemDisplayService::GetSharedBufferMemoryHandleId( | ||||
|     Out<s32> out_nvmap_handle, Out<u64> out_size, | ||||
|     OutLargeData<Nvnflinger::SharedMemoryPoolLayout, BufferAttr_HipcMapAlias> out_pool_layout, | ||||
|     u64 buffer_id, ClientAppletResourceUserId aruid) { | ||||
|     LOG_INFO(Service_VI, "called. buffer_id={}, aruid={:#x}", buffer_id, aruid.pid); | ||||
|  | ||||
|     R_RETURN(m_nvnflinger.GetSystemBufferManager().GetSharedBufferMemoryHandleId( | ||||
|         out_size, out_nvmap_handle, out_pool_layout, buffer_id, aruid.pid)); | ||||
| } | ||||
|  | ||||
| Result ISystemDisplayService::OpenSharedLayer(u64 layer_id) { | ||||
|     LOG_INFO(Service_VI, "(STUBBED) called. layer_id={}", layer_id); | ||||
|     R_SUCCEED(); | ||||
| } | ||||
|  | ||||
| Result ISystemDisplayService::ConnectSharedLayer(u64 layer_id) { | ||||
|     LOG_INFO(Service_VI, "(STUBBED) called. layer_id={}", layer_id); | ||||
|     R_SUCCEED(); | ||||
| } | ||||
|  | ||||
| Result ISystemDisplayService::AcquireSharedFrameBuffer(Out<android::Fence> out_fence, | ||||
|                                                        Out<std::array<s32, 4>> out_slots, | ||||
|                                                        Out<s64> out_target_slot, u64 layer_id) { | ||||
|     LOG_DEBUG(Service_VI, "called"); | ||||
|     R_RETURN(m_nvnflinger.GetSystemBufferManager().AcquireSharedFrameBuffer( | ||||
|         out_fence, *out_slots, out_target_slot, layer_id)); | ||||
| } | ||||
|  | ||||
| Result ISystemDisplayService::PresentSharedFrameBuffer(android::Fence fence, | ||||
|                                                        Common::Rectangle<s32> crop_region, | ||||
|                                                        u32 window_transform, s32 swap_interval, | ||||
|                                                        u64 layer_id, s64 surface_id) { | ||||
|     LOG_DEBUG(Service_VI, "called"); | ||||
|     R_RETURN(m_nvnflinger.GetSystemBufferManager().PresentSharedFrameBuffer( | ||||
|         fence, crop_region, window_transform, swap_interval, layer_id, surface_id)); | ||||
| } | ||||
|  | ||||
| Result ISystemDisplayService::GetSharedFrameBufferAcquirableEvent( | ||||
|     OutCopyHandle<Kernel::KReadableEvent> out_event, u64 layer_id) { | ||||
|     LOG_DEBUG(Service_VI, "called"); | ||||
|     R_RETURN(m_nvnflinger.GetSystemBufferManager().GetSharedFrameBufferAcquirableEvent(out_event, | ||||
|                                                                                        layer_id)); | ||||
| } | ||||
|  | ||||
| } // namespace Service::VI | ||||
							
								
								
									
										45
									
								
								src/core/hle/service/vi/system_display_service.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/core/hle/service/vi/system_display_service.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| #include "common/math_util.h" | ||||
| #include "core/hle/service/cmif_types.h" | ||||
| #include "core/hle/service/nvnflinger/ui/fence.h" | ||||
| #include "core/hle/service/service.h" | ||||
|  | ||||
| namespace Service::Nvnflinger { | ||||
| struct SharedMemoryPoolLayout; | ||||
| } | ||||
|  | ||||
| namespace Service::VI { | ||||
|  | ||||
| class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> { | ||||
| public: | ||||
|     explicit ISystemDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger); | ||||
|     ~ISystemDisplayService() override; | ||||
|  | ||||
| private: | ||||
|     Result SetLayerZ(u32 z_value, u64 layer_id); | ||||
|     Result SetLayerVisibility(bool visible, u64 layer_id); | ||||
|     Result GetDisplayMode(Out<u32> out_width, Out<u32> out_height, Out<f32> out_refresh_rate, | ||||
|                           Out<u32> out_unknown); | ||||
|  | ||||
|     Result GetSharedBufferMemoryHandleId( | ||||
|         Out<s32> out_nvmap_handle, Out<u64> out_size, | ||||
|         OutLargeData<Nvnflinger::SharedMemoryPoolLayout, BufferAttr_HipcMapAlias> out_pool_layout, | ||||
|         u64 buffer_id, ClientAppletResourceUserId aruid); | ||||
|     Result OpenSharedLayer(u64 layer_id); | ||||
|     Result ConnectSharedLayer(u64 layer_id); | ||||
|     Result GetSharedFrameBufferAcquirableEvent(OutCopyHandle<Kernel::KReadableEvent> out_event, | ||||
|                                                u64 layer_id); | ||||
|     Result AcquireSharedFrameBuffer(Out<android::Fence> out_fence, | ||||
|                                     Out<std::array<s32, 4>> out_slots, Out<s64> out_target_slot, | ||||
|                                     u64 layer_id); | ||||
|     Result PresentSharedFrameBuffer(android::Fence fence, Common::Rectangle<s32> crop_region, | ||||
|                                     u32 window_transform, s32 swap_interval, u64 layer_id, | ||||
|                                     s64 surface_id); | ||||
|  | ||||
| private: | ||||
|     Nvnflinger::Nvnflinger& m_nvnflinger; | ||||
| }; | ||||
|  | ||||
| } // namespace Service::VI | ||||
							
								
								
									
										33
									
								
								src/core/hle/service/vi/system_root_service.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/core/hle/service/vi/system_root_service.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| #include "core/hle/service/cmif_serialization.h" | ||||
| #include "core/hle/service/vi/application_display_service.h" | ||||
| #include "core/hle/service/vi/service_creator.h" | ||||
| #include "core/hle/service/vi/system_root_service.h" | ||||
| #include "core/hle/service/vi/vi.h" | ||||
| #include "core/hle/service/vi/vi_types.h" | ||||
|  | ||||
| namespace Service::VI { | ||||
|  | ||||
| ISystemRootService::ISystemRootService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, | ||||
|                                        Nvnflinger::HosBinderDriverServer& hos_binder_driver_server) | ||||
|     : ServiceFramework{system_, "vi:s"}, m_nvnflinger{nvnflinger}, m_hos_binder_driver_server{ | ||||
|                                                                        hos_binder_driver_server} { | ||||
|     static const FunctionInfo functions[] = { | ||||
|         {1, C<&ISystemRootService::GetDisplayService>, "GetDisplayService"}, | ||||
|         {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, | ||||
|     }; | ||||
|     RegisterHandlers(functions); | ||||
| } | ||||
|  | ||||
| ISystemRootService::~ISystemRootService() = default; | ||||
|  | ||||
| Result ISystemRootService::GetDisplayService( | ||||
|     Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, Policy policy) { | ||||
|     LOG_DEBUG(Service_VI, "called"); | ||||
|     R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_nvnflinger, | ||||
|                                           m_hos_binder_driver_server, Permission::System, policy)); | ||||
| } | ||||
|  | ||||
| } // namespace Service::VI | ||||
							
								
								
									
										38
									
								
								src/core/hle/service/vi/system_root_service.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/core/hle/service/vi/system_root_service.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "core/hle/service/cmif_types.h" | ||||
| #include "core/hle/service/service.h" | ||||
|  | ||||
| namespace Core { | ||||
| class System; | ||||
| } | ||||
|  | ||||
| namespace Service::Nvnflinger { | ||||
| class HosBinderDriverServer; | ||||
| class Nvnflinger; | ||||
| } // namespace Service::Nvnflinger | ||||
|  | ||||
| namespace Service::VI { | ||||
|  | ||||
| class IApplicationDisplayService; | ||||
| enum class Policy : u32; | ||||
|  | ||||
| class ISystemRootService final : public ServiceFramework<ISystemRootService> { | ||||
| public: | ||||
|     explicit ISystemRootService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger, | ||||
|                                 Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); | ||||
|     ~ISystemRootService() override; | ||||
|  | ||||
| private: | ||||
|     Result GetDisplayService( | ||||
|         Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, | ||||
|         Policy policy); | ||||
|  | ||||
|     Nvnflinger::Nvnflinger& m_nvnflinger; | ||||
|     Nvnflinger::HosBinderDriverServer& m_hos_binder_driver_server; | ||||
| }; | ||||
|  | ||||
| } // namespace Service::VI | ||||
| @@ -1,974 +1,25 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| #include <algorithm> | ||||
| #include <array> | ||||
| #include <cstring> | ||||
| #include <memory> | ||||
| #include <optional> | ||||
| #include <type_traits> | ||||
| #include <utility> | ||||
|  | ||||
| #include "common/alignment.h" | ||||
| #include "common/assert.h" | ||||
| #include "common/common_funcs.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/math_util.h" | ||||
| #include "common/settings.h" | ||||
| #include "common/string_util.h" | ||||
| #include "common/swap.h" | ||||
| #include "core/core_timing.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/devices/nvmap.h" | ||||
| #include "core/hle/service/nvdrv/nvdata.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_u.h" | ||||
|  | ||||
| namespace Service::VI { | ||||
|  | ||||
| struct DisplayInfo { | ||||
|     /// The name of this particular display. | ||||
|     char display_name[0x40]{"Default"}; | ||||
|  | ||||
|     /// Whether or not the display has a limited number of layers. | ||||
|     u8 has_limited_layers{1}; | ||||
|     INSERT_PADDING_BYTES(7); | ||||
|  | ||||
|     /// Indicates the total amount of layers supported by the display. | ||||
|     /// @note This is only valid if has_limited_layers is set. | ||||
|     u64 max_layers{1}; | ||||
|  | ||||
|     /// Maximum width in pixels. | ||||
|     u64 width{1920}; | ||||
|  | ||||
|     /// Maximum height in pixels. | ||||
|     u64 height{1080}; | ||||
| }; | ||||
| static_assert(sizeof(DisplayInfo) == 0x60, "DisplayInfo has wrong size"); | ||||
|  | ||||
| class NativeWindow final { | ||||
| public: | ||||
|     constexpr explicit NativeWindow(u32 id_) : id{id_} {} | ||||
|     constexpr explicit NativeWindow(const NativeWindow& other) = default; | ||||
|  | ||||
| private: | ||||
|     const u32 magic = 2; | ||||
|     const u32 process_id = 1; | ||||
|     const u64 id; | ||||
|     INSERT_PADDING_WORDS(2); | ||||
|     std::array<u8, 8> dispdrv = {'d', 'i', 's', 'p', 'd', 'r', 'v', '\0'}; | ||||
|     INSERT_PADDING_WORDS(2); | ||||
| }; | ||||
| static_assert(sizeof(NativeWindow) == 0x28, "NativeWindow has wrong size"); | ||||
|  | ||||
| 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; | ||||
|     } | ||||
|  | ||||
|     if (permission == Permission::System || permission == Permission::Manager) { | ||||
|         return policy == Policy::User || policy == Policy::Compositor; | ||||
|     } | ||||
|  | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| void detail::GetDisplayServiceImpl(HLERequestContext& ctx, Core::System& system, | ||||
|                                    Nvnflinger::Nvnflinger& nvnflinger, | ||||
|                                    Nvnflinger::HosBinderDriverServer& hos_binder_driver_server, | ||||
|                                    Permission permission) { | ||||
|     IPC::RequestParser rp{ctx}; | ||||
|     const auto policy = rp.PopEnum<Policy>(); | ||||
|  | ||||
|     if (!IsValidServiceAccess(permission, policy)) { | ||||
|         LOG_ERROR(Service_VI, "Permission denied for policy {}", policy); | ||||
|         IPC::ResponseBuilder rb{ctx, 2}; | ||||
|         rb.Push(ResultPermissionDenied); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | ||||
|     rb.Push(ResultSuccess); | ||||
|     rb.PushIpcInterface<IApplicationDisplayService>(system, nvnflinger, hos_binder_driver_server); | ||||
| } | ||||
|  | ||||
| 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,16 +3,10 @@ | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "common/common_types.h" | ||||
|  | ||||
| namespace Core { | ||||
| class System; | ||||
| } | ||||
|  | ||||
| namespace Service { | ||||
| class HLERequestContext; | ||||
| } | ||||
|  | ||||
| namespace Service::Nvnflinger { | ||||
| class HosBinderDriverServer; | ||||
| class Nvnflinger; | ||||
| @@ -20,34 +14,6 @@ class Nvnflinger; | ||||
|  | ||||
| namespace Service::VI { | ||||
|  | ||||
| enum class DisplayResolution : u32 { | ||||
|     DockedWidth = 1920, | ||||
|     DockedHeight = 1080, | ||||
|     UndockedWidth = 1280, | ||||
|     UndockedHeight = 720, | ||||
| }; | ||||
|  | ||||
| /// Permission level for a particular VI service instance | ||||
| enum class Permission { | ||||
|     User, | ||||
|     System, | ||||
|     Manager, | ||||
| }; | ||||
|  | ||||
| /// A policy type that may be requested via GetDisplayService and | ||||
| /// GetDisplayServiceWithProxyNameExchange | ||||
| enum class Policy { | ||||
|     User, | ||||
|     Compositor, | ||||
| }; | ||||
|  | ||||
| namespace detail { | ||||
| void GetDisplayServiceImpl(HLERequestContext& ctx, Core::System& system, | ||||
|                            Nvnflinger::Nvnflinger& nv_flinger, | ||||
|                            Nvnflinger::HosBinderDriverServer& hos_binder_driver_server, | ||||
|                            Permission permission); | ||||
| } // namespace detail | ||||
|  | ||||
| void LoopProcess(Core::System& system, Nvnflinger::Nvnflinger& nvnflinger, | ||||
|                  Nvnflinger::HosBinderDriverServer& hos_binder_driver_server); | ||||
|  | ||||
|   | ||||
| @@ -1,34 +0,0 @@ | ||||
| // 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/vi.h" | ||||
| #include "core/hle/service/vi/vi_m.h" | ||||
|  | ||||
| namespace Service::VI { | ||||
|  | ||||
| VI_M::VI_M(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"}, | ||||
|         {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, | ||||
|         {100, nullptr, "PrepareFatal"}, | ||||
|         {101, nullptr, "ShowFatal"}, | ||||
|         {102, nullptr, "DrawFatalRectangle"}, | ||||
|         {103, nullptr, "DrawFatalText32"}, | ||||
|     }; | ||||
|     RegisterHandlers(functions); | ||||
| } | ||||
|  | ||||
| VI_M::~VI_M() = default; | ||||
|  | ||||
| void VI_M::GetDisplayService(HLERequestContext& ctx) { | ||||
|     LOG_DEBUG(Service_VI, "called"); | ||||
|  | ||||
|     detail::GetDisplayServiceImpl(ctx, system, nv_flinger, hos_binder_driver_server, | ||||
|                                   Permission::Manager); | ||||
| } | ||||
|  | ||||
| } // namespace Service::VI | ||||
| @@ -1,32 +0,0 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "core/hle/service/service.h" | ||||
|  | ||||
| namespace Core { | ||||
| class System; | ||||
| } | ||||
|  | ||||
| namespace Service::Nvnflinger { | ||||
| class HosBinderDriverServer; | ||||
| class Nvnflinger; | ||||
| } // namespace Service::Nvnflinger | ||||
|  | ||||
| namespace Service::VI { | ||||
|  | ||||
| class VI_M final : public ServiceFramework<VI_M> { | ||||
| public: | ||||
|     explicit VI_M(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, | ||||
|                   Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_); | ||||
|     ~VI_M() override; | ||||
|  | ||||
| private: | ||||
|     void GetDisplayService(HLERequestContext& ctx); | ||||
|  | ||||
|     Nvnflinger::Nvnflinger& nv_flinger; | ||||
|     Nvnflinger::HosBinderDriverServer& hos_binder_driver_server; | ||||
| }; | ||||
|  | ||||
| } // namespace Service::VI | ||||
| @@ -1,30 +0,0 @@ | ||||
| // 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/vi.h" | ||||
| #include "core/hle/service/vi/vi_s.h" | ||||
|  | ||||
| namespace Service::VI { | ||||
|  | ||||
| VI_S::VI_S(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"}, | ||||
|         {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, | ||||
|     }; | ||||
|     RegisterHandlers(functions); | ||||
| } | ||||
|  | ||||
| VI_S::~VI_S() = default; | ||||
|  | ||||
| void VI_S::GetDisplayService(HLERequestContext& ctx) { | ||||
|     LOG_DEBUG(Service_VI, "called"); | ||||
|  | ||||
|     detail::GetDisplayServiceImpl(ctx, system, nv_flinger, hos_binder_driver_server, | ||||
|                                   Permission::System); | ||||
| } | ||||
|  | ||||
| } // namespace Service::VI | ||||
| @@ -1,32 +0,0 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "core/hle/service/service.h" | ||||
|  | ||||
| namespace Core { | ||||
| class System; | ||||
| } | ||||
|  | ||||
| namespace Service::Nvnflinger { | ||||
| class HosBinderDriverServer; | ||||
| class Nvnflinger; | ||||
| } // namespace Service::Nvnflinger | ||||
|  | ||||
| namespace Service::VI { | ||||
|  | ||||
| class VI_S final : public ServiceFramework<VI_S> { | ||||
| public: | ||||
|     explicit VI_S(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, | ||||
|                   Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_); | ||||
|     ~VI_S() override; | ||||
|  | ||||
| private: | ||||
|     void GetDisplayService(HLERequestContext& ctx); | ||||
|  | ||||
|     Nvnflinger::Nvnflinger& nv_flinger; | ||||
|     Nvnflinger::HosBinderDriverServer& hos_binder_driver_server; | ||||
| }; | ||||
|  | ||||
| } // namespace Service::VI | ||||
							
								
								
									
										84
									
								
								src/core/hle/service/vi/vi_types.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								src/core/hle/service/vi/vi_types.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,84 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "common/common_funcs.h" | ||||
|  | ||||
| namespace Service::VI { | ||||
|  | ||||
| enum class DisplayResolution : u32 { | ||||
|     DockedWidth = 1920, | ||||
|     DockedHeight = 1080, | ||||
|     UndockedWidth = 1280, | ||||
|     UndockedHeight = 720, | ||||
| }; | ||||
|  | ||||
| /// Permission level for a particular VI service instance | ||||
| enum class Permission { | ||||
|     User, | ||||
|     System, | ||||
|     Manager, | ||||
| }; | ||||
|  | ||||
| /// A policy type that may be requested via GetDisplayService and | ||||
| /// GetDisplayServiceWithProxyNameExchange | ||||
| enum class Policy : u32 { | ||||
|     User, | ||||
|     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, | ||||
| }; | ||||
|  | ||||
| using DisplayName = std::array<char, 0x40>; | ||||
|  | ||||
| struct DisplayInfo { | ||||
|     /// The name of this particular display. | ||||
|     DisplayName display_name{"Default"}; | ||||
|  | ||||
|     /// Whether or not the display has a limited number of layers. | ||||
|     u8 has_limited_layers{1}; | ||||
|     INSERT_PADDING_BYTES(7); | ||||
|  | ||||
|     /// Indicates the total amount of layers supported by the display. | ||||
|     /// @note This is only valid if has_limited_layers is set. | ||||
|     u64 max_layers{1}; | ||||
|  | ||||
|     /// Maximum width in pixels. | ||||
|     u64 width{1920}; | ||||
|  | ||||
|     /// Maximum height in pixels. | ||||
|     u64 height{1080}; | ||||
| }; | ||||
| static_assert(sizeof(DisplayInfo) == 0x60, "DisplayInfo has wrong size"); | ||||
|  | ||||
| class NativeWindow final { | ||||
| public: | ||||
|     constexpr explicit NativeWindow(u32 id_) : id{id_} {} | ||||
|     constexpr explicit NativeWindow(const NativeWindow& other) = default; | ||||
|  | ||||
| private: | ||||
|     const u32 magic = 2; | ||||
|     const u32 process_id = 1; | ||||
|     const u64 id; | ||||
|     INSERT_PADDING_WORDS(2); | ||||
|     std::array<u8, 8> dispdrv = {'d', 'i', 's', 'p', 'd', 'r', 'v', '\0'}; | ||||
|     INSERT_PADDING_WORDS(2); | ||||
| }; | ||||
| static_assert(sizeof(NativeWindow) == 0x28, "NativeWindow has wrong size"); | ||||
|  | ||||
| } // namespace Service::VI | ||||
| @@ -1,30 +0,0 @@ | ||||
| // 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/vi.h" | ||||
| #include "core/hle/service/vi/vi_u.h" | ||||
|  | ||||
| namespace Service::VI { | ||||
|  | ||||
| VI_U::VI_U(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"}, | ||||
|         {1, nullptr, "GetDisplayServiceWithProxyNameExchange"}, | ||||
|     }; | ||||
|     RegisterHandlers(functions); | ||||
| } | ||||
|  | ||||
| VI_U::~VI_U() = default; | ||||
|  | ||||
| void VI_U::GetDisplayService(HLERequestContext& ctx) { | ||||
|     LOG_DEBUG(Service_VI, "called"); | ||||
|  | ||||
|     detail::GetDisplayServiceImpl(ctx, system, nv_flinger, hos_binder_driver_server, | ||||
|                                   Permission::User); | ||||
| } | ||||
|  | ||||
| } // namespace Service::VI | ||||
| @@ -1,32 +0,0 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include "core/hle/service/service.h" | ||||
|  | ||||
| namespace Core { | ||||
| class System; | ||||
| } | ||||
|  | ||||
| namespace Service::Nvnflinger { | ||||
| class HosBinderDriverServer; | ||||
| class Nvnflinger; | ||||
| } // namespace Service::Nvnflinger | ||||
|  | ||||
| namespace Service::VI { | ||||
|  | ||||
| class VI_U final : public ServiceFramework<VI_U> { | ||||
| public: | ||||
|     explicit VI_U(Core::System& system_, Nvnflinger::Nvnflinger& nv_flinger_, | ||||
|                   Nvnflinger::HosBinderDriverServer& hos_binder_driver_server_); | ||||
|     ~VI_U() override; | ||||
|  | ||||
| private: | ||||
|     void GetDisplayService(HLERequestContext& ctx); | ||||
|  | ||||
|     Nvnflinger::Nvnflinger& nv_flinger; | ||||
|     Nvnflinger::HosBinderDriverServer& hos_binder_driver_server; | ||||
| }; | ||||
|  | ||||
| } // namespace Service::VI | ||||
| @@ -22,29 +22,30 @@ void HidFirmwareSettings::LoadSettings(bool reload_config) { | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     m_set_sys->GetSettingsItemValue<bool>(is_debug_pad_enabled, "hid_debug", "enables_debugpad"); | ||||
|     m_set_sys->GetSettingsItemValue<bool>(is_device_managed, "hid_debug", "manages_devices"); | ||||
|     m_set_sys->GetSettingsItemValue<bool>(is_touch_i2c_managed, "hid_debug", | ||||
|                                           "manages_touch_ic_i2c"); | ||||
|     m_set_sys->GetSettingsItemValue<bool>(is_future_devices_emulated, "hid_debug", | ||||
|                                           "emulate_future_device"); | ||||
|     m_set_sys->GetSettingsItemValue<bool>(is_mcu_hardware_error_emulated, "hid_debug", | ||||
|                                           "emulate_mcu_hardware_error"); | ||||
|     m_set_sys->GetSettingsItemValue<bool>(is_rail_enabled, "hid_debug", "enables_rail"); | ||||
|     m_set_sys->GetSettingsItemValue<bool>(is_firmware_update_failure_emulated, "hid_debug", | ||||
|                                           "emulate_firmware_update_failure"); | ||||
|     m_set_sys->GetSettingsItemValueImpl<bool>(is_debug_pad_enabled, "hid_debug", | ||||
|                                               "enables_debugpad"); | ||||
|     m_set_sys->GetSettingsItemValueImpl<bool>(is_device_managed, "hid_debug", "manages_devices"); | ||||
|     m_set_sys->GetSettingsItemValueImpl<bool>(is_touch_i2c_managed, "hid_debug", | ||||
|                                               "manages_touch_ic_i2c"); | ||||
|     m_set_sys->GetSettingsItemValueImpl<bool>(is_future_devices_emulated, "hid_debug", | ||||
|                                               "emulate_future_device"); | ||||
|     m_set_sys->GetSettingsItemValueImpl<bool>(is_mcu_hardware_error_emulated, "hid_debug", | ||||
|                                               "emulate_mcu_hardware_error"); | ||||
|     m_set_sys->GetSettingsItemValueImpl<bool>(is_rail_enabled, "hid_debug", "enables_rail"); | ||||
|     m_set_sys->GetSettingsItemValueImpl<bool>(is_firmware_update_failure_emulated, "hid_debug", | ||||
|                                               "emulate_firmware_update_failure"); | ||||
|     is_firmware_update_failure = {}; | ||||
|     m_set_sys->GetSettingsItemValue<bool>(is_ble_disabled, "hid_debug", "ble_disabled"); | ||||
|     m_set_sys->GetSettingsItemValue<bool>(is_dscale_disabled, "hid_debug", "dscale_disabled"); | ||||
|     m_set_sys->GetSettingsItemValue<bool>(is_handheld_forced, "hid_debug", "force_handheld"); | ||||
|     m_set_sys->GetSettingsItemValueImpl<bool>(is_ble_disabled, "hid_debug", "ble_disabled"); | ||||
|     m_set_sys->GetSettingsItemValueImpl<bool>(is_dscale_disabled, "hid_debug", "dscale_disabled"); | ||||
|     m_set_sys->GetSettingsItemValueImpl<bool>(is_handheld_forced, "hid_debug", "force_handheld"); | ||||
|     features_per_id_disabled = {}; | ||||
|     m_set_sys->GetSettingsItemValue<bool>(is_touch_firmware_auto_update_disabled, "hid_debug", | ||||
|                                           "touch_firmware_auto_update_disabled"); | ||||
|     m_set_sys->GetSettingsItemValueImpl<bool>(is_touch_firmware_auto_update_disabled, "hid_debug", | ||||
|                                               "touch_firmware_auto_update_disabled"); | ||||
|  | ||||
|     bool has_rail_interface{}; | ||||
|     bool has_sio_mcu{}; | ||||
|     m_set_sys->GetSettingsItemValue<bool>(has_rail_interface, "hid", "has_rail_interface"); | ||||
|     m_set_sys->GetSettingsItemValue<bool>(has_sio_mcu, "hid", "has_sio_mcu"); | ||||
|     m_set_sys->GetSettingsItemValueImpl<bool>(has_rail_interface, "hid", "has_rail_interface"); | ||||
|     m_set_sys->GetSettingsItemValueImpl<bool>(has_sio_mcu, "hid", "has_sio_mcu"); | ||||
|     platform_config.has_rail_interface.Assign(has_rail_interface); | ||||
|     platform_config.has_sio_mcu.Assign(has_sio_mcu); | ||||
|  | ||||
|   | ||||
| @@ -15,7 +15,7 @@ Result NpadVibration::Activate() { | ||||
|     std::scoped_lock lock{mutex}; | ||||
|  | ||||
|     f32 master_volume = 1.0f; | ||||
|     m_set_sys->GetVibrationMasterVolume(master_volume); | ||||
|     m_set_sys->GetVibrationMasterVolume(&master_volume); | ||||
|     if (master_volume < 0.0f || master_volume > 1.0f) { | ||||
|         return ResultVibrationStrengthOutOfRange; | ||||
|     } | ||||
| @@ -57,7 +57,7 @@ Result NpadVibration::GetVibrationMasterVolume(f32& out_volume) const { | ||||
|     std::scoped_lock lock{mutex}; | ||||
|  | ||||
|     f32 master_volume = 1.0f; | ||||
|     m_set_sys->GetVibrationMasterVolume(master_volume); | ||||
|     m_set_sys->GetVibrationMasterVolume(&master_volume); | ||||
|     if (master_volume < 0.0f || master_volume > 1.0f) { | ||||
|         return ResultVibrationStrengthOutOfRange; | ||||
|     } | ||||
| @@ -77,7 +77,7 @@ Result NpadVibration::EndPermitVibrationSession() { | ||||
|     std::scoped_lock lock{mutex}; | ||||
|  | ||||
|     f32 master_volume = 1.0f; | ||||
|     m_set_sys->GetVibrationMasterVolume(master_volume); | ||||
|     m_set_sys->GetVibrationMasterVolume(&master_volume); | ||||
|     if (master_volume < 0.0f || master_volume > 1.0f) { | ||||
|         return ResultVibrationStrengthOutOfRange; | ||||
|     } | ||||
|   | ||||
| @@ -48,7 +48,7 @@ Result TouchResource::ActivateTouch() { | ||||
|     } | ||||
|  | ||||
|     Set::TouchScreenMode touch_mode{Set::TouchScreenMode::Standard}; | ||||
|     m_set_sys->GetTouchScreenMode(touch_mode); | ||||
|     m_set_sys->GetTouchScreenMode(&touch_mode); | ||||
|     default_touch_screen_mode = static_cast<Core::HID::TouchScreenModeForNx>(touch_mode); | ||||
|  | ||||
|     global_ref_counter++; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user