diff options
Diffstat (limited to 'src/core/hle/service')
44 files changed, 781 insertions, 274 deletions
diff --git a/src/core/hle/service/glue/glue.cpp b/src/core/hle/service/glue/glue.cpp index 10376bfac..ea2843462 100644 --- a/src/core/hle/service/glue/glue.cpp +++ b/src/core/hle/service/glue/glue.cpp @@ -31,8 +31,11 @@ void LoopProcess(Core::System& system) { // Error Context server_manager->RegisterNamedService("ectx:aw", std::make_shared<ECTX_AW>(system)); - // Notification Services for application - server_manager->RegisterNamedService("notif:a", std::make_shared<NOTIF_A>(system)); + // Notification Services + server_manager->RegisterNamedService( + "notif:a", std::make_shared<INotificationServicesForApplication>(system)); + server_manager->RegisterNamedService("notif:s", + std::make_shared<INotificationServices>(system)); // Time auto time = std::make_shared<Time::TimeManager>(system); diff --git a/src/core/hle/service/glue/notif.cpp b/src/core/hle/service/glue/notif.cpp index fec4ad86c..5a03d34c1 100644 --- a/src/core/hle/service/glue/notif.cpp +++ b/src/core/hle/service/glue/notif.cpp @@ -6,48 +6,31 @@ #include "common/assert.h" #include "common/logging/log.h" +#include "core/hle/service/cmif_serialization.h" #include "core/hle/service/glue/notif.h" #include "core/hle/service/ipc_helpers.h" +#include "core/hle/service/kernel_helpers.h" namespace Service::Glue { -NOTIF_A::NOTIF_A(Core::System& system_) : ServiceFramework{system_, "notif:a"} { - // clang-format off - static const FunctionInfo functions[] = { - {500, &NOTIF_A::RegisterAlarmSetting, "RegisterAlarmSetting"}, - {510, &NOTIF_A::UpdateAlarmSetting, "UpdateAlarmSetting"}, - {520, &NOTIF_A::ListAlarmSettings, "ListAlarmSettings"}, - {530, &NOTIF_A::LoadApplicationParameter, "LoadApplicationParameter"}, - {540, &NOTIF_A::DeleteAlarmSetting, "DeleteAlarmSetting"}, - {1000, &NOTIF_A::Initialize, "Initialize"}, - }; - // clang-format on - - RegisterHandlers(functions); -} - -NOTIF_A::~NOTIF_A() = default; +namespace { -void NOTIF_A::RegisterAlarmSetting(HLERequestContext& ctx) { - const auto alarm_setting_buffer_size = ctx.GetReadBufferSize(0); - const auto application_parameter_size = ctx.GetReadBufferSize(1); - - ASSERT_MSG(alarm_setting_buffer_size == sizeof(AlarmSetting), - "alarm_setting_buffer_size is not 0x40 bytes"); - ASSERT_MSG(application_parameter_size <= sizeof(ApplicationParameter), - "application_parameter_size is bigger than 0x400 bytes"); +constexpr inline std::size_t MaxAlarms = 8; - AlarmSetting new_alarm{}; - memcpy(&new_alarm, ctx.ReadBuffer(0).data(), sizeof(AlarmSetting)); +} - // TODO: Count alarms per game id - if (alarms.size() >= max_alarms) { +Result NotificationServiceImpl::RegisterAlarmSetting(AlarmSettingId* out_alarm_setting_id, + const AlarmSetting& alarm_setting, + std::span<const u8> application_parameter) { + if (alarms.size() > MaxAlarms) { LOG_ERROR(Service_NOTIF, "Alarm limit reached"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultUnknown); - return; + R_THROW(ResultUnknown); } + ASSERT_MSG(application_parameter.size() <= sizeof(ApplicationParameter), + "application_parameter_size is bigger than 0x400 bytes"); + + AlarmSetting new_alarm = alarm_setting; new_alarm.alarm_setting_id = last_alarm_setting_id++; alarms.push_back(new_alarm); @@ -55,100 +38,82 @@ void NOTIF_A::RegisterAlarmSetting(HLERequestContext& ctx) { LOG_WARNING(Service_NOTIF, "(STUBBED) called, application_parameter_size={}, setting_id={}, kind={}, muted={}", - application_parameter_size, new_alarm.alarm_setting_id, new_alarm.kind, + application_parameter.size(), new_alarm.alarm_setting_id, new_alarm.kind, new_alarm.muted); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - rb.Push(new_alarm.alarm_setting_id); + *out_alarm_setting_id = new_alarm.alarm_setting_id; + R_SUCCEED(); } -void NOTIF_A::UpdateAlarmSetting(HLERequestContext& ctx) { - const auto alarm_setting_buffer_size = ctx.GetReadBufferSize(0); - const auto application_parameter_size = ctx.GetReadBufferSize(1); - - ASSERT_MSG(alarm_setting_buffer_size == sizeof(AlarmSetting), - "alarm_setting_buffer_size is not 0x40 bytes"); - ASSERT_MSG(application_parameter_size <= sizeof(ApplicationParameter), +Result NotificationServiceImpl::UpdateAlarmSetting(const AlarmSetting& alarm_setting, + std::span<const u8> application_parameter) { + ASSERT_MSG(application_parameter.size() <= sizeof(ApplicationParameter), "application_parameter_size is bigger than 0x400 bytes"); - AlarmSetting alarm_setting{}; - memcpy(&alarm_setting, ctx.ReadBuffer(0).data(), sizeof(AlarmSetting)); - const auto alarm_it = GetAlarmFromId(alarm_setting.alarm_setting_id); if (alarm_it != alarms.end()) { LOG_DEBUG(Service_NOTIF, "Alarm updated"); *alarm_it = alarm_setting; - // TODO: Save application parameter data } LOG_WARNING(Service_NOTIF, "(STUBBED) called, application_parameter_size={}, setting_id={}, kind={}, muted={}", - application_parameter_size, alarm_setting.alarm_setting_id, alarm_setting.kind, + application_parameter.size(), alarm_setting.alarm_setting_id, alarm_setting.kind, alarm_setting.muted); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + R_SUCCEED(); } -void NOTIF_A::ListAlarmSettings(HLERequestContext& ctx) { +Result NotificationServiceImpl::ListAlarmSettings(s32* out_count, + std::span<AlarmSetting> out_alarms) { LOG_INFO(Service_NOTIF, "called, alarm_count={}", alarms.size()); - // TODO: Only return alarms of this game id - ctx.WriteBuffer(alarms); + const auto count = std::min(out_alarms.size(), alarms.size()); + for (size_t i = 0; i < count; i++) { + out_alarms[i] = alarms[i]; + } - IPC::ResponseBuilder rb{ctx, 3}; - rb.Push(ResultSuccess); - rb.Push(static_cast<u32>(alarms.size())); + *out_count = static_cast<s32>(count); + R_SUCCEED(); } -void NOTIF_A::LoadApplicationParameter(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto alarm_setting_id{rp.Pop<AlarmSettingId>()}; - +Result NotificationServiceImpl::LoadApplicationParameter(u32* out_size, + std::span<u8> out_application_parameter, + AlarmSettingId alarm_setting_id) { const auto alarm_it = GetAlarmFromId(alarm_setting_id); if (alarm_it == alarms.end()) { LOG_ERROR(Service_NOTIF, "Invalid alarm setting id={}", alarm_setting_id); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultUnknown); - return; + R_THROW(ResultUnknown); } // TODO: Read application parameter related to this setting id ApplicationParameter application_parameter{}; LOG_WARNING(Service_NOTIF, "(STUBBED) called, alarm_setting_id={}", alarm_setting_id); + std::memcpy(out_application_parameter.data(), application_parameter.data(), + std::min(sizeof(application_parameter), out_application_parameter.size())); - ctx.WriteBuffer(application_parameter); - - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); - rb.Push(static_cast<u32>(application_parameter.size())); + *out_size = static_cast<u32>(application_parameter.size()); + R_SUCCEED(); } -void NOTIF_A::DeleteAlarmSetting(HLERequestContext& ctx) { - IPC::RequestParser rp{ctx}; - const auto alarm_setting_id{rp.Pop<AlarmSettingId>()}; - +Result NotificationServiceImpl::DeleteAlarmSetting(AlarmSettingId alarm_setting_id) { std::erase_if(alarms, [alarm_setting_id](const AlarmSetting& alarm) { return alarm.alarm_setting_id == alarm_setting_id; }); LOG_INFO(Service_NOTIF, "called, alarm_setting_id={}", alarm_setting_id); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + R_SUCCEED(); } -void NOTIF_A::Initialize(HLERequestContext& ctx) { +Result NotificationServiceImpl::Initialize(u64 aruid) { // TODO: Load previous alarms from config LOG_WARNING(Service_NOTIF, "(STUBBED) called"); - IPC::ResponseBuilder rb{ctx, 2}; - rb.Push(ResultSuccess); + R_SUCCEED(); } -std::vector<NOTIF_A::AlarmSetting>::iterator NOTIF_A::GetAlarmFromId( +std::vector<AlarmSetting>::iterator NotificationServiceImpl::GetAlarmFromId( AlarmSettingId alarm_setting_id) { return std::find_if(alarms.begin(), alarms.end(), [alarm_setting_id](const AlarmSetting& alarm) { @@ -156,4 +121,174 @@ std::vector<NOTIF_A::AlarmSetting>::iterator NOTIF_A::GetAlarmFromId( }); } +INotificationServicesForApplication::INotificationServicesForApplication(Core::System& system_) + : ServiceFramework{system_, "notif:a"} { + // clang-format off + static const FunctionInfo functions[] = { + {500, D<&INotificationServicesForApplication::RegisterAlarmSetting>, "RegisterAlarmSetting"}, + {510, D<&INotificationServicesForApplication::UpdateAlarmSetting>, "UpdateAlarmSetting"}, + {520, D<&INotificationServicesForApplication::ListAlarmSettings>, "ListAlarmSettings"}, + {530, D<&INotificationServicesForApplication::LoadApplicationParameter>, "LoadApplicationParameter"}, + {540, D<&INotificationServicesForApplication::DeleteAlarmSetting>, "DeleteAlarmSetting"}, + {1000, D<&INotificationServicesForApplication::Initialize>, "Initialize"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +INotificationServicesForApplication::~INotificationServicesForApplication() = default; + +Result INotificationServicesForApplication::RegisterAlarmSetting( + Out<AlarmSettingId> out_alarm_setting_id, + InLargeData<AlarmSetting, BufferAttr_HipcMapAlias> alarm_setting, + InBuffer<BufferAttr_HipcMapAlias> application_parameter) { + R_RETURN(impl.RegisterAlarmSetting(out_alarm_setting_id.Get(), *alarm_setting, + application_parameter)); +} + +Result INotificationServicesForApplication::UpdateAlarmSetting( + InLargeData<AlarmSetting, BufferAttr_HipcMapAlias> alarm_setting, + InBuffer<BufferAttr_HipcMapAlias> application_parameter) { + R_RETURN(impl.UpdateAlarmSetting(*alarm_setting, application_parameter)); +} + +Result INotificationServicesForApplication::ListAlarmSettings( + Out<s32> out_count, OutArray<AlarmSetting, BufferAttr_HipcMapAlias> out_alarms) { + R_RETURN(impl.ListAlarmSettings(out_count.Get(), out_alarms)); +} + +Result INotificationServicesForApplication::LoadApplicationParameter( + Out<u32> out_size, OutBuffer<BufferAttr_HipcMapAlias> out_application_parameter, + AlarmSettingId alarm_setting_id) { + R_RETURN( + impl.LoadApplicationParameter(out_size.Get(), out_application_parameter, alarm_setting_id)); +} + +Result INotificationServicesForApplication::DeleteAlarmSetting(AlarmSettingId alarm_setting_id) { + R_RETURN(impl.DeleteAlarmSetting(alarm_setting_id)); +} + +Result INotificationServicesForApplication::Initialize(ClientAppletResourceUserId aruid) { + R_RETURN(impl.Initialize(*aruid)); +} + +class INotificationSystemEventAccessor final + : public ServiceFramework<INotificationSystemEventAccessor> { +public: + explicit INotificationSystemEventAccessor(Core::System& system_) + : ServiceFramework{system_, "INotificationSystemEventAccessor"}, + service_context{system_, "INotificationSystemEventAccessor"} { + // clang-format off + static const FunctionInfo functions[] = { + {0, D<&INotificationSystemEventAccessor::GetSystemEvent>, "GetSystemEvent"}, + }; + // clang-format on + + RegisterHandlers(functions); + + notification_event = + service_context.CreateEvent("INotificationSystemEventAccessor:NotificationEvent"); + } + + ~INotificationSystemEventAccessor() { + service_context.CloseEvent(notification_event); + } + +private: + Result GetSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_readable_event) { + LOG_WARNING(Service_NOTIF, "(STUBBED) called"); + + *out_readable_event = ¬ification_event->GetReadableEvent(); + R_SUCCEED(); + } + + KernelHelpers::ServiceContext service_context; + Kernel::KEvent* notification_event; +}; + +INotificationServices::INotificationServices(Core::System& system_) + : ServiceFramework{system_, "notif:s"} { + // clang-format off + static const FunctionInfo functions[] = { + {500, D<&INotificationServices::RegisterAlarmSetting>, "RegisterAlarmSetting"}, + {510, D<&INotificationServices::UpdateAlarmSetting>, "UpdateAlarmSetting"}, + {520, D<&INotificationServices::ListAlarmSettings>, "ListAlarmSettings"}, + {530, D<&INotificationServices::LoadApplicationParameter>, "LoadApplicationParameter"}, + {540, D<&INotificationServices::DeleteAlarmSetting>, "DeleteAlarmSetting"}, + {1000, D<&INotificationServices::Initialize>, "Initialize"}, + {1010, nullptr, "ListNotifications"}, + {1020, nullptr, "DeleteNotification"}, + {1030, nullptr, "ClearNotifications"}, + {1040, D<&INotificationServices::OpenNotificationSystemEventAccessor>, "OpenNotificationSystemEventAccessor"}, + {1500, nullptr, "SetNotificationPresentationSetting"}, + {1510, D<&INotificationServices::GetNotificationPresentationSetting>, "GetNotificationPresentationSetting"}, + {2000, nullptr, "GetAlarmSetting"}, + {2001, nullptr, "GetAlarmSettingWithApplicationParameter"}, + {2010, nullptr, "MuteAlarmSetting"}, + {2020, nullptr, "IsAlarmSettingReady"}, + {8000, nullptr, "RegisterAppletResourceUserId"}, + {8010, nullptr, "UnregisterAppletResourceUserId"}, + {8999, nullptr, "GetCurrentTime"}, + {9000, nullptr, "GetAlarmSettingNextNotificationTime"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +INotificationServices::~INotificationServices() = default; + +Result INotificationServices::RegisterAlarmSetting( + Out<AlarmSettingId> out_alarm_setting_id, + InLargeData<AlarmSetting, BufferAttr_HipcMapAlias> alarm_setting, + InBuffer<BufferAttr_HipcMapAlias> application_parameter) { + R_RETURN(impl.RegisterAlarmSetting(out_alarm_setting_id.Get(), *alarm_setting, + application_parameter)); +} + +Result INotificationServices::UpdateAlarmSetting( + InLargeData<AlarmSetting, BufferAttr_HipcMapAlias> alarm_setting, + InBuffer<BufferAttr_HipcMapAlias> application_parameter) { + R_RETURN(impl.UpdateAlarmSetting(*alarm_setting, application_parameter)); +} + +Result INotificationServices::ListAlarmSettings( + Out<s32> out_count, OutArray<AlarmSetting, BufferAttr_HipcMapAlias> out_alarms) { + R_RETURN(impl.ListAlarmSettings(out_count.Get(), out_alarms)); +} + +Result INotificationServices::LoadApplicationParameter( + Out<u32> out_size, OutBuffer<BufferAttr_HipcMapAlias> out_application_parameter, + AlarmSettingId alarm_setting_id) { + R_RETURN( + impl.LoadApplicationParameter(out_size.Get(), out_application_parameter, alarm_setting_id)); +} + +Result INotificationServices::DeleteAlarmSetting(AlarmSettingId alarm_setting_id) { + R_RETURN(impl.DeleteAlarmSetting(alarm_setting_id)); +} + +Result INotificationServices::Initialize(ClientAppletResourceUserId aruid) { + R_RETURN(impl.Initialize(*aruid)); +} + +Result INotificationServices::OpenNotificationSystemEventAccessor( + Out<SharedPointer<INotificationSystemEventAccessor>> out_notification_system_event_accessor) { + LOG_WARNING(Service_NOTIF, "(STUBBED) called"); + + *out_notification_system_event_accessor = + std::make_shared<INotificationSystemEventAccessor>(system); + R_SUCCEED(); +} + +Result INotificationServices::GetNotificationPresentationSetting( + Out<NotificationPresentationSetting> out_notification_presentation_setting, + NotificationChannel notification_channel) { + LOG_WARNING(Service_NOTIF, "(STUBBED) called"); + + *out_notification_presentation_setting = {}; + R_SUCCEED(); +} + } // namespace Service::Glue diff --git a/src/core/hle/service/glue/notif.h b/src/core/hle/service/glue/notif.h index b1187f3a3..ef2522fdf 100644 --- a/src/core/hle/service/glue/notif.h +++ b/src/core/hle/service/glue/notif.h @@ -7,6 +7,7 @@ #include <vector> #include "common/uuid.h" +#include "core/hle/service/cmif_types.h" #include "core/hle/service/service.h" namespace Core { @@ -15,58 +16,117 @@ class System; namespace Service::Glue { -class NOTIF_A final : public ServiceFramework<NOTIF_A> { +// This is nn::notification::AlarmSettingId +using AlarmSettingId = u16; +static_assert(sizeof(AlarmSettingId) == 0x2, "AlarmSettingId is an invalid size"); + +using ApplicationParameter = std::array<u8, 0x400>; +static_assert(sizeof(ApplicationParameter) == 0x400, "ApplicationParameter is an invalid size"); + +struct DailyAlarmSetting { + s8 hour; + s8 minute; +}; +static_assert(sizeof(DailyAlarmSetting) == 0x2, "DailyAlarmSetting is an invalid size"); + +struct WeeklyScheduleAlarmSetting { + INSERT_PADDING_BYTES_NOINIT(0xA); + std::array<DailyAlarmSetting, 0x7> day_of_week; +}; +static_assert(sizeof(WeeklyScheduleAlarmSetting) == 0x18, + "WeeklyScheduleAlarmSetting is an invalid size"); + +// This is nn::notification::AlarmSetting +struct AlarmSetting { + AlarmSettingId alarm_setting_id; + u8 kind; + u8 muted; + INSERT_PADDING_BYTES_NOINIT(0x4); + Common::UUID account_id; + u64 application_id; + INSERT_PADDING_BYTES_NOINIT(0x8); + WeeklyScheduleAlarmSetting schedule; +}; +static_assert(sizeof(AlarmSetting) == 0x40, "AlarmSetting is an invalid size"); + +enum class NotificationChannel : u8 { + Unknown0 = 0, +}; + +struct NotificationPresentationSetting { + INSERT_PADDING_BYTES_NOINIT(0x10); +}; +static_assert(sizeof(NotificationPresentationSetting) == 0x10, + "NotificationPresentationSetting is an invalid size"); + +class NotificationServiceImpl { public: - explicit NOTIF_A(Core::System& system_); - ~NOTIF_A() override; + Result RegisterAlarmSetting(AlarmSettingId* out_alarm_setting_id, + const AlarmSetting& alarm_setting, + std::span<const u8> application_parameter); + Result UpdateAlarmSetting(const AlarmSetting& alarm_setting, + std::span<const u8> application_parameter); + Result ListAlarmSettings(s32* out_count, std::span<AlarmSetting> out_alarms); + Result LoadApplicationParameter(u32* out_size, std::span<u8> out_application_parameter, + AlarmSettingId alarm_setting_id); + Result DeleteAlarmSetting(AlarmSettingId alarm_setting_id); + Result Initialize(u64 aruid); private: - static constexpr std::size_t max_alarms = 8; - - // This is nn::notification::AlarmSettingId - using AlarmSettingId = u16; - static_assert(sizeof(AlarmSettingId) == 0x2, "AlarmSettingId is an invalid size"); - - using ApplicationParameter = std::array<u8, 0x400>; - static_assert(sizeof(ApplicationParameter) == 0x400, "ApplicationParameter is an invalid size"); - - struct DailyAlarmSetting { - s8 hour; - s8 minute; - }; - static_assert(sizeof(DailyAlarmSetting) == 0x2, "DailyAlarmSetting is an invalid size"); - - struct WeeklyScheduleAlarmSetting { - INSERT_PADDING_BYTES(0xA); - std::array<DailyAlarmSetting, 0x7> day_of_week; - }; - static_assert(sizeof(WeeklyScheduleAlarmSetting) == 0x18, - "WeeklyScheduleAlarmSetting is an invalid size"); - - // This is nn::notification::AlarmSetting - struct AlarmSetting { - AlarmSettingId alarm_setting_id; - u8 kind; - u8 muted; - INSERT_PADDING_BYTES(0x4); - Common::UUID account_id; - u64 application_id; - INSERT_PADDING_BYTES(0x8); - WeeklyScheduleAlarmSetting schedule; - }; - static_assert(sizeof(AlarmSetting) == 0x40, "AlarmSetting is an invalid size"); - - void RegisterAlarmSetting(HLERequestContext& ctx); - void UpdateAlarmSetting(HLERequestContext& ctx); - void ListAlarmSettings(HLERequestContext& ctx); - void LoadApplicationParameter(HLERequestContext& ctx); - void DeleteAlarmSetting(HLERequestContext& ctx); - void Initialize(HLERequestContext& ctx); - std::vector<AlarmSetting>::iterator GetAlarmFromId(AlarmSettingId alarm_setting_id); - std::vector<AlarmSetting> alarms{}; AlarmSettingId last_alarm_setting_id{}; }; +class INotificationServicesForApplication final + : public ServiceFramework<INotificationServicesForApplication> { +public: + explicit INotificationServicesForApplication(Core::System& system_); + ~INotificationServicesForApplication() override; + +private: + Result RegisterAlarmSetting(Out<AlarmSettingId> out_alarm_setting_id, + InLargeData<AlarmSetting, BufferAttr_HipcMapAlias> alarm_setting, + InBuffer<BufferAttr_HipcMapAlias> application_parameter); + Result UpdateAlarmSetting(InLargeData<AlarmSetting, BufferAttr_HipcMapAlias> alarm_setting, + InBuffer<BufferAttr_HipcMapAlias> application_parameter); + Result ListAlarmSettings(Out<s32> out_count, + OutArray<AlarmSetting, BufferAttr_HipcMapAlias> out_alarms); + Result LoadApplicationParameter(Out<u32> out_size, + OutBuffer<BufferAttr_HipcMapAlias> out_application_parameter, + AlarmSettingId alarm_setting_id); + Result DeleteAlarmSetting(AlarmSettingId alarm_setting_id); + Result Initialize(ClientAppletResourceUserId aruid); + + NotificationServiceImpl impl; +}; + +class INotificationSystemEventAccessor; + +class INotificationServices final : public ServiceFramework<INotificationServices> { +public: + explicit INotificationServices(Core::System& system_); + ~INotificationServices() override; + +private: + Result RegisterAlarmSetting(Out<AlarmSettingId> out_alarm_setting_id, + InLargeData<AlarmSetting, BufferAttr_HipcMapAlias> alarm_setting, + InBuffer<BufferAttr_HipcMapAlias> application_parameter); + Result UpdateAlarmSetting(InLargeData<AlarmSetting, BufferAttr_HipcMapAlias> alarm_setting, + InBuffer<BufferAttr_HipcMapAlias> application_parameter); + Result ListAlarmSettings(Out<s32> out_count, + OutArray<AlarmSetting, BufferAttr_HipcMapAlias> out_alarms); + Result LoadApplicationParameter(Out<u32> out_size, + OutBuffer<BufferAttr_HipcMapAlias> out_application_parameter, + AlarmSettingId alarm_setting_id); + Result DeleteAlarmSetting(AlarmSettingId alarm_setting_id); + Result Initialize(ClientAppletResourceUserId aruid); + Result OpenNotificationSystemEventAccessor(Out<SharedPointer<INotificationSystemEventAccessor>> + out_notification_system_event_accessor); + Result GetNotificationPresentationSetting( + Out<NotificationPresentationSetting> out_notification_presentation_setting, + NotificationChannel notification_channel); + + NotificationServiceImpl impl; +}; } // namespace Service::Glue diff --git a/src/core/hle/service/glue/time/static.cpp b/src/core/hle/service/glue/time/static.cpp index f56db76e1..f8c1218f3 100644 --- a/src/core/hle/service/glue/time/static.cpp +++ b/src/core/hle/service/glue/time/static.cpp @@ -200,7 +200,7 @@ Result StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( } Result StaticService::CalculateMonotonicSystemClockBaseTimePoint( - Out<s64> out_time, Service::PSC::Time::SystemClockContext& context) { + Out<s64> out_time, const Service::PSC::Time::SystemClockContext& context) { SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. context={} out_time={}", context, *out_time); }); R_RETURN(m_wrapped_service->CalculateMonotonicSystemClockBaseTimePoint(out_time, context)); @@ -216,8 +216,8 @@ Result StaticService::GetClockSnapshot(OutClockSnapshot out_snapshot, Result StaticService::GetClockSnapshotFromSystemClockContext( Service::PSC::Time::TimeType type, OutClockSnapshot out_snapshot, - Service::PSC::Time::SystemClockContext& user_context, - Service::PSC::Time::SystemClockContext& network_context) { + const Service::PSC::Time::SystemClockContext& user_context, + const Service::PSC::Time::SystemClockContext& network_context) { SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. type={} out_snapshot={} user_context={} network_context={}", type, diff --git a/src/core/hle/service/glue/time/static.h b/src/core/hle/service/glue/time/static.h index d3cc0fdd6..5d3623182 100644 --- a/src/core/hle/service/glue/time/static.h +++ b/src/core/hle/service/glue/time/static.h @@ -58,12 +58,12 @@ public: Result GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point); Result CalculateMonotonicSystemClockBaseTimePoint( - Out<s64> out_time, Service::PSC::Time::SystemClockContext& context); + Out<s64> out_time, const Service::PSC::Time::SystemClockContext& context); Result GetClockSnapshot(OutClockSnapshot out_snapshot, Service::PSC::Time::TimeType type); Result GetClockSnapshotFromSystemClockContext( Service::PSC::Time::TimeType type, OutClockSnapshot out_snapshot, - Service::PSC::Time::SystemClockContext& user_context, - Service::PSC::Time::SystemClockContext& network_context); + const Service::PSC::Time::SystemClockContext& user_context, + const Service::PSC::Time::SystemClockContext& network_context); Result CalculateStandardUserSystemClockDifferenceByUser(Out<s64> out_difference, InClockSnapshot a, InClockSnapshot b); Result CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a, InClockSnapshot b); diff --git a/src/core/hle/service/glue/time/time_zone.cpp b/src/core/hle/service/glue/time/time_zone.cpp index 98d928697..36f163419 100644 --- a/src/core/hle/service/glue/time/time_zone.cpp +++ b/src/core/hle/service/glue/time/time_zone.cpp @@ -62,7 +62,8 @@ Result TimeZoneService::GetDeviceLocationName( R_RETURN(m_wrapped_service->GetDeviceLocationName(out_location_name)); } -Result TimeZoneService::SetDeviceLocationName(Service::PSC::Time::LocationName& location_name) { +Result TimeZoneService::SetDeviceLocationName( + const Service::PSC::Time::LocationName& location_name) { LOG_DEBUG(Service_Time, "called. location_name={}", location_name); R_UNLESS(m_can_write_timezone_device_location, Service::PSC::Time::ResultPermissionDenied); @@ -110,7 +111,8 @@ Result TimeZoneService::LoadLocationNameList( R_RETURN(GetTimeZoneLocationList(*out_count, out_names, out_names.size(), index)); } -Result TimeZoneService::LoadTimeZoneRule(OutRule out_rule, Service::PSC::Time::LocationName& name) { +Result TimeZoneService::LoadTimeZoneRule(OutRule out_rule, + const Service::PSC::Time::LocationName& name) { LOG_DEBUG(Service_Time, "called. name={}", name); std::scoped_lock l{m_mutex}; @@ -139,7 +141,8 @@ Result TimeZoneService::GetDeviceLocationNameAndUpdatedTime( } Result TimeZoneService::SetDeviceLocationNameWithTimeZoneRule( - Service::PSC::Time::LocationName& location_name, InBuffer<BufferAttr_HipcAutoSelect> binary) { + const Service::PSC::Time::LocationName& location_name, + InBuffer<BufferAttr_HipcAutoSelect> binary) { LOG_DEBUG(Service_Time, "called. location_name={}", location_name); R_UNLESS(m_can_write_timezone_device_location, Service::PSC::Time::ResultPermissionDenied); diff --git a/src/core/hle/service/glue/time/time_zone.h b/src/core/hle/service/glue/time/time_zone.h index 9c1530966..beb54ddde 100644 --- a/src/core/hle/service/glue/time/time_zone.h +++ b/src/core/hle/service/glue/time/time_zone.h @@ -46,18 +46,20 @@ public: ~TimeZoneService() override; Result GetDeviceLocationName(Out<Service::PSC::Time::LocationName> out_location_name); - Result SetDeviceLocationName(Service::PSC::Time::LocationName& location_name); + Result SetDeviceLocationName(const Service::PSC::Time::LocationName& location_name); Result GetTotalLocationNameCount(Out<u32> out_count); Result LoadLocationNameList( Out<u32> out_count, OutArray<Service::PSC::Time::LocationName, BufferAttr_HipcMapAlias> out_names, u32 index); - Result LoadTimeZoneRule(OutRule out_rule, Service::PSC::Time::LocationName& location_name); + Result LoadTimeZoneRule(OutRule out_rule, + const Service::PSC::Time::LocationName& location_name); Result GetTimeZoneRuleVersion(Out<Service::PSC::Time::RuleVersion> out_rule_version); Result GetDeviceLocationNameAndUpdatedTime( Out<Service::PSC::Time::LocationName> location_name, Out<Service::PSC::Time::SteadyClockTimePoint> out_time_point); - Result SetDeviceLocationNameWithTimeZoneRule(Service::PSC::Time::LocationName& location_name, - InBuffer<BufferAttr_HipcAutoSelect> binary); + Result SetDeviceLocationNameWithTimeZoneRule( + const Service::PSC::Time::LocationName& location_name, + InBuffer<BufferAttr_HipcAutoSelect> binary); Result ParseTimeZoneBinary(OutRule out_rule, InBuffer<BufferAttr_HipcAutoSelect> binary); Result GetDeviceLocationNameOperationEventReadableHandle( OutCopyHandle<Kernel::KReadableEvent> out_event); diff --git a/src/core/hle/service/glue/time/time_zone_binary.cpp b/src/core/hle/service/glue/time/time_zone_binary.cpp index cc50b6b7b..d5f7ca3d2 100644 --- a/src/core/hle/service/glue/time/time_zone_binary.cpp +++ b/src/core/hle/service/glue/time/time_zone_binary.cpp @@ -98,7 +98,7 @@ void GetTimeZoneBinaryVersionPath(std::string& out_path) { out_path = "/version.txt"; } -void GetTimeZoneZonePath(std::string& out_path, Service::PSC::Time::LocationName& name) { +void GetTimeZoneZonePath(std::string& out_path, const Service::PSC::Time::LocationName& name) { if (g_time_zone_binary_mount_result != ResultSuccess) { return; } @@ -106,7 +106,7 @@ void GetTimeZoneZonePath(std::string& out_path, Service::PSC::Time::LocationName out_path = fmt::format("/zoneinfo/{}", name.data()); } -bool IsTimeZoneBinaryValid(Service::PSC::Time::LocationName& name) { +bool IsTimeZoneBinaryValid(const Service::PSC::Time::LocationName& name) { std::string path{}; GetTimeZoneZonePath(path, name); @@ -155,7 +155,7 @@ Result GetTimeZoneVersion(Service::PSC::Time::RuleVersion& out_rule_version) { } Result GetTimeZoneRule(std::span<const u8>& out_rule, size_t& out_rule_size, - Service::PSC::Time::LocationName& name) { + const Service::PSC::Time::LocationName& name) { std::string path{}; GetTimeZoneZonePath(path, name); diff --git a/src/core/hle/service/glue/time/time_zone_binary.h b/src/core/hle/service/glue/time/time_zone_binary.h index 461f4577e..9d0a8dfe9 100644 --- a/src/core/hle/service/glue/time/time_zone_binary.h +++ b/src/core/hle/service/glue/time/time_zone_binary.h @@ -19,12 +19,12 @@ void ResetTimeZoneBinary(); Result MountTimeZoneBinary(Core::System& system); void GetTimeZoneBinaryListPath(std::string& out_path); void GetTimeZoneBinaryVersionPath(std::string& out_path); -void GetTimeZoneZonePath(std::string& out_path, Service::PSC::Time::LocationName& name); -bool IsTimeZoneBinaryValid(Service::PSC::Time::LocationName& name); +void GetTimeZoneZonePath(std::string& out_path, const Service::PSC::Time::LocationName& name); +bool IsTimeZoneBinaryValid(const Service::PSC::Time::LocationName& name); u32 GetTimeZoneCount(); Result GetTimeZoneVersion(Service::PSC::Time::RuleVersion& out_rule_version); Result GetTimeZoneRule(std::span<const u8>& out_rule, size_t& out_rule_size, - Service::PSC::Time::LocationName& name); + const Service::PSC::Time::LocationName& name); Result GetTimeZoneLocationList(u32& out_count, std::span<Service::PSC::Time::LocationName> out_names, size_t max_names, u32 index); diff --git a/src/core/hle/service/jit/jit.cpp b/src/core/hle/service/jit/jit.cpp index 1f2cbcb61..4941a71a0 100644 --- a/src/core/hle/service/jit/jit.cpp +++ b/src/core/hle/service/jit/jit.cpp @@ -126,7 +126,7 @@ public: R_THROW(ResultUnknown); } - Result LoadPlugin(u64 tmem_size, InCopyHandle<Kernel::KTransferMemory>& tmem, + Result LoadPlugin(u64 tmem_size, InCopyHandle<Kernel::KTransferMemory> tmem, InBuffer<BufferAttr_HipcMapAlias> nrr, InBuffer<BufferAttr_HipcMapAlias> nro) { if (!tmem) { @@ -268,9 +268,9 @@ public: private: Result CreateJitEnvironment(Out<SharedPointer<IJitEnvironment>> out_jit_environment, - u64 rx_size, u64 ro_size, InCopyHandle<Kernel::KProcess>& process, - InCopyHandle<Kernel::KCodeMemory>& rx_mem, - InCopyHandle<Kernel::KCodeMemory>& ro_mem) { + u64 rx_size, u64 ro_size, InCopyHandle<Kernel::KProcess> process, + InCopyHandle<Kernel::KCodeMemory> rx_mem, + InCopyHandle<Kernel::KCodeMemory> ro_mem) { if (!process) { LOG_ERROR(Service_JIT, "process is null"); R_THROW(ResultUnknown); diff --git a/src/core/hle/service/mii/mii.cpp b/src/core/hle/service/mii/mii.cpp index efb7f6e32..0086f82c5 100644 --- a/src/core/hle/service/mii/mii.cpp +++ b/src/core/hle/service/mii/mii.cpp @@ -189,7 +189,7 @@ private: R_RETURN(manager->Move(metadata, new_index, create_id)); } - Result AddOrReplace(StoreData& store_data) { + Result AddOrReplace(const StoreData& store_data) { LOG_INFO(Service_Mii, "called"); R_UNLESS(is_system, ResultPermissionDenied); diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp index c1ebbd62d..abe95303e 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp @@ -1,6 +1,8 @@ // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later +#include <boost/container/small_vector.hpp> + #include "common/assert.h" #include "common/logging/log.h" #include "core/core.h" @@ -38,19 +40,30 @@ NvResult nvdisp_disp0::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> in void nvdisp_disp0::OnOpen(NvCore::SessionId session_id, DeviceFD fd) {} void nvdisp_disp0::OnClose(DeviceFD fd) {} -void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, android::PixelFormat format, u32 width, - u32 height, u32 stride, android::BufferTransformFlags transform, - const Common::Rectangle<int>& crop_rect, - std::array<Service::Nvidia::NvFence, 4>& fences, u32 num_fences) { - const DAddr addr = nvmap.GetHandleAddress(buffer_handle); - LOG_TRACE(Service, - "Drawing from address {:X} offset {:08X} Width {} Height {} Stride {} Format {}", - addr, offset, width, height, stride, format); +void nvdisp_disp0::Composite(std::span<const Nvnflinger::HwcLayer> sorted_layers) { + std::vector<Tegra::FramebufferConfig> output_layers; + std::vector<Service::Nvidia::NvFence> output_fences; + output_layers.reserve(sorted_layers.size()); + output_fences.reserve(sorted_layers.size()); + + for (auto& layer : sorted_layers) { + output_layers.emplace_back(Tegra::FramebufferConfig{ + .address = nvmap.GetHandleAddress(layer.buffer_handle), + .offset = layer.offset, + .width = layer.width, + .height = layer.height, + .stride = layer.stride, + .pixel_format = layer.format, + .transform_flags = layer.transform, + .crop_rect = layer.crop_rect, + }); - const Tegra::FramebufferConfig framebuffer{addr, offset, width, height, - stride, format, transform, crop_rect}; + for (size_t i = 0; i < layer.acquire_fence.num_fences; i++) { + output_fences.push_back(layer.acquire_fence.fences[i]); + } + } - system.GPU().RequestSwapBuffers(&framebuffer, fences, num_fences); + system.GPU().RequestComposite(std::move(output_layers), std::move(output_fences)); system.SpeedLimiter().DoSpeedLimiting(system.CoreTiming().GetGlobalTimeUs()); system.GetPerfStats().EndSystemFrame(); system.GetPerfStats().BeginSystemFrame(); diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h index 5f13a50a2..1082b85c2 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h @@ -8,8 +8,7 @@ #include "common/common_types.h" #include "common/math_util.h" #include "core/hle/service/nvdrv/devices/nvdevice.h" -#include "core/hle/service/nvnflinger/buffer_transform_flags.h" -#include "core/hle/service/nvnflinger/pixel_format.h" +#include "core/hle/service/nvnflinger/hwc_layer.h" namespace Service::Nvidia::NvCore { class Container; @@ -35,11 +34,8 @@ public: void OnOpen(NvCore::SessionId session_id, DeviceFD fd) override; void OnClose(DeviceFD fd) override; - /// Performs a screen flip, drawing the buffer pointed to by the handle. - void flip(u32 buffer_handle, u32 offset, android::PixelFormat format, u32 width, u32 height, - u32 stride, android::BufferTransformFlags transform, - const Common::Rectangle<int>& crop_rect, - std::array<Service::Nvidia::NvFence, 4>& fences, u32 num_fences); + /// Performs a screen flip, compositing each buffer. + void Composite(std::span<const Nvnflinger::HwcLayer> sorted_layers); Kernel::KEvent* QueryEvent(u32 event_id) override; diff --git a/src/core/hle/service/nvnflinger/hardware_composer.cpp b/src/core/hle/service/nvnflinger/hardware_composer.cpp new file mode 100644 index 000000000..c720dd1f8 --- /dev/null +++ b/src/core/hle/service/nvnflinger/hardware_composer.cpp @@ -0,0 +1,215 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#include <boost/container/small_vector.hpp> + +#include "common/microprofile.h" +#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" +#include "core/hle/service/nvnflinger/buffer_item.h" +#include "core/hle/service/nvnflinger/buffer_item_consumer.h" +#include "core/hle/service/nvnflinger/buffer_queue_producer.h" +#include "core/hle/service/nvnflinger/hardware_composer.h" +#include "core/hle/service/nvnflinger/hwc_layer.h" +#include "core/hle/service/nvnflinger/ui/graphic_buffer.h" +#include "core/hle/service/vi/display/vi_display.h" +#include "core/hle/service/vi/layer/vi_layer.h" + +namespace Service::Nvnflinger { + +namespace { + +s32 NormalizeSwapInterval(f32* out_speed_scale, s32 swap_interval) { + if (swap_interval <= 0) { + // As an extension, treat nonpositive swap interval as speed multiplier. + if (out_speed_scale) { + *out_speed_scale = 2.f * static_cast<f32>(1 - swap_interval); + } + + swap_interval = 1; + } + + if (swap_interval >= 5) { + // As an extension, treat high swap interval as precise speed control. + if (out_speed_scale) { + *out_speed_scale = static_cast<f32>(swap_interval) / 100.f; + } + + swap_interval = 1; + } + + return swap_interval; +} + +} // namespace + +HardwareComposer::HardwareComposer() = default; +HardwareComposer::~HardwareComposer() = default; + +u32 HardwareComposer::ComposeLocked(f32* out_speed_scale, VI::Display& display, + Nvidia::Devices::nvdisp_disp0& nvdisp, u32 frame_advance) { + boost::container::small_vector<HwcLayer, 2> composition_stack; + + m_frame_number += frame_advance; + + // Release any necessary framebuffers. + for (auto& [layer_id, framebuffer] : m_framebuffers) { + if (framebuffer.release_frame_number > m_frame_number) { + // Not yet ready to release this framebuffer. + continue; + } + + if (!framebuffer.is_acquired) { + // Already released. + continue; + } + + if (auto* layer = display.FindLayer(layer_id); layer != nullptr) { + // TODO: support release fence + // This is needed to prevent screen tearing + layer->GetConsumer().ReleaseBuffer(framebuffer.item, android::Fence::NoFence()); + framebuffer.is_acquired = false; + } + } + + // Set default speed limit to 100%. + *out_speed_scale = 1.0f; + + // Determine the number of vsync periods to wait before composing again. + std::optional<s32> swap_interval{}; + bool has_acquired_buffer{}; + + // Acquire all necessary framebuffers. + for (size_t i = 0; i < display.GetNumLayers(); i++) { + auto& layer = display.GetLayer(i); + auto layer_id = layer.GetLayerId(); + + // Try to fetch the framebuffer (either new or stale). + const auto result = this->CacheFramebufferLocked(layer, layer_id); + + // If we failed, skip this layer. + if (result == CacheStatus::NoBufferAvailable) { + continue; + } + + // If we acquired a new buffer, we need to present. + if (result == CacheStatus::BufferAcquired) { + has_acquired_buffer = true; + } + + const auto& buffer = m_framebuffers[layer_id]; + const auto& item = buffer.item; + const auto& igbp_buffer = *item.graphic_buffer; + + // TODO: get proper Z-index from layer + composition_stack.emplace_back(HwcLayer{ + .buffer_handle = igbp_buffer.BufferId(), + .offset = igbp_buffer.Offset(), + .format = igbp_buffer.ExternalFormat(), + .width = igbp_buffer.Width(), + .height = igbp_buffer.Height(), + .stride = igbp_buffer.Stride(), + .z_index = 0, + .transform = static_cast<android::BufferTransformFlags>(item.transform), + .crop_rect = item.crop, + .acquire_fence = item.fence, + }); + + // We need to compose again either before this frame is supposed to + // be released, or exactly on the vsync period it should be released. + const s32 item_swap_interval = NormalizeSwapInterval(out_speed_scale, item.swap_interval); + + // TODO: handle cases where swap intervals are relatively prime. So far, + // only swap intervals of 0, 1 and 2 have been observed, but if 3 were + // to be introduced, this would cause an issue. + if (swap_interval) { + swap_interval = std::min(*swap_interval, item_swap_interval); + } else { + swap_interval = item_swap_interval; + } + } + + // If any new buffers were acquired, we can present. + if (has_acquired_buffer) { + // Sort by Z-index. + std::stable_sort(composition_stack.begin(), composition_stack.end(), + [&](auto& l, auto& r) { return l.z_index < r.z_index; }); + + // Composite. + nvdisp.Composite(composition_stack); + } + + // Render MicroProfile. + MicroProfileFlip(); + + // Advance by at least one frame. + return swap_interval.value_or(1); +} + +void HardwareComposer::RemoveLayerLocked(VI::Display& display, LayerId layer_id) { + // Check if we are tracking a slot with this layer_id. + const auto it = m_framebuffers.find(layer_id); + if (it == m_framebuffers.end()) { + return; + } + + // Try to release the buffer item. + auto* const layer = display.FindLayer(layer_id); + if (layer && it->second.is_acquired) { + layer->GetConsumer().ReleaseBuffer(it->second.item, android::Fence::NoFence()); + } + + // Erase the slot. + m_framebuffers.erase(it); +} + +bool HardwareComposer::TryAcquireFramebufferLocked(VI::Layer& layer, Framebuffer& framebuffer) { + // Attempt the update. + const auto status = layer.GetConsumer().AcquireBuffer(&framebuffer.item, {}, false); + if (status != android::Status::NoError) { + return false; + } + + // We succeeded, so set the new release frame info. + framebuffer.release_frame_number = + NormalizeSwapInterval(nullptr, framebuffer.item.swap_interval); + framebuffer.is_acquired = true; + + return true; +} + +HardwareComposer::CacheStatus HardwareComposer::CacheFramebufferLocked(VI::Layer& layer, + LayerId layer_id) { + // Check if this framebuffer is already present. + const auto it = m_framebuffers.find(layer_id); + if (it != m_framebuffers.end()) { + // If it's currently still acquired, we are done. + if (it->second.is_acquired) { + return CacheStatus::CachedBufferReused; + } + + // Try to acquire a new item. + if (this->TryAcquireFramebufferLocked(layer, it->second)) { + // We got a new item. + return CacheStatus::BufferAcquired; + } else { + // We didn't acquire a new item, but we can reuse the slot. + return CacheStatus::CachedBufferReused; + } + } + + // Framebuffer is not present, so try to create it. + Framebuffer framebuffer{}; + + if (this->TryAcquireFramebufferLocked(layer, framebuffer)) { + // Move the buffer item into a new slot. + m_framebuffers.emplace(layer_id, std::move(framebuffer)); + + // We succeeded. + return CacheStatus::BufferAcquired; + } + + // We couldn't acquire the buffer item, so don't create a slot. + return CacheStatus::NoBufferAvailable; +} + +} // namespace Service::Nvnflinger diff --git a/src/core/hle/service/nvnflinger/hardware_composer.h b/src/core/hle/service/nvnflinger/hardware_composer.h new file mode 100644 index 000000000..ddab94ac9 --- /dev/null +++ b/src/core/hle/service/nvnflinger/hardware_composer.h @@ -0,0 +1,59 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include <memory> +#include <boost/container/flat_map.hpp> + +#include "core/hle/service/nvnflinger/buffer_item.h" + +namespace Service::Nvidia::Devices { +class nvdisp_disp0; +} + +namespace Service::VI { +class Display; +class Layer; +} // namespace Service::VI + +namespace Service::Nvnflinger { + +using LayerId = u64; + +class HardwareComposer { +public: + explicit HardwareComposer(); + ~HardwareComposer(); + + u32 ComposeLocked(f32* out_speed_scale, VI::Display& display, + Nvidia::Devices::nvdisp_disp0& nvdisp, u32 frame_advance); + void RemoveLayerLocked(VI::Display& display, LayerId layer_id); + +private: + // TODO: do we want to track frame number in vi instead? + u64 m_frame_number{0}; + +private: + using ReleaseFrameNumber = u64; + + struct Framebuffer { + android::BufferItem item{}; + ReleaseFrameNumber release_frame_number{}; + bool is_acquired{false}; + }; + + enum class CacheStatus : u32 { + NoBufferAvailable, + BufferAcquired, + CachedBufferReused, + }; + + boost::container::flat_map<LayerId, Framebuffer> m_framebuffers{}; + +private: + bool TryAcquireFramebufferLocked(VI::Layer& layer, Framebuffer& framebuffer); + CacheStatus CacheFramebufferLocked(VI::Layer& layer, LayerId layer_id); +}; + +} // namespace Service::Nvnflinger diff --git a/src/core/hle/service/nvnflinger/hwc_layer.h b/src/core/hle/service/nvnflinger/hwc_layer.h new file mode 100644 index 000000000..3af668a25 --- /dev/null +++ b/src/core/hle/service/nvnflinger/hwc_layer.h @@ -0,0 +1,27 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#include "common/math_util.h" +#include "core/hle/service/nvdrv/nvdata.h" +#include "core/hle/service/nvnflinger/buffer_transform_flags.h" +#include "core/hle/service/nvnflinger/pixel_format.h" +#include "core/hle/service/nvnflinger/ui/fence.h" + +namespace Service::Nvnflinger { + +struct HwcLayer { + u32 buffer_handle; + u32 offset; + android::PixelFormat format; + u32 width; + u32 height; + u32 stride; + s32 z_index; + android::BufferTransformFlags transform; + Common::Rectangle<int> crop_rect; + android::Fence acquire_fence; +}; + +} // namespace Service::Nvnflinger diff --git a/src/core/hle/service/nvnflinger/nvnflinger.cpp b/src/core/hle/service/nvnflinger/nvnflinger.cpp index 51133853c..a4e848882 100644 --- a/src/core/hle/service/nvnflinger/nvnflinger.cpp +++ b/src/core/hle/service/nvnflinger/nvnflinger.cpp @@ -18,6 +18,7 @@ #include "core/hle/service/nvnflinger/buffer_item_consumer.h" #include "core/hle/service/nvnflinger/buffer_queue_core.h" #include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" +#include "core/hle/service/nvnflinger/hardware_composer.h" #include "core/hle/service/nvnflinger/hos_binder_driver_server.h" #include "core/hle/service/nvnflinger/nvnflinger.h" #include "core/hle/service/nvnflinger/ui/graphic_buffer.h" @@ -279,45 +280,19 @@ void Nvnflinger::Compose() { SCOPE_EXIT({ display.SignalVSyncEvent(); }); // Don't do anything for displays without layers. - if (!display.HasLayers()) - continue; - - // TODO(Subv): Support more than 1 layer. - VI::Layer& layer = display.GetLayer(0); - - android::BufferItem buffer{}; - const auto status = layer.GetConsumer().AcquireBuffer(&buffer, {}, false); - - if (status != android::Status::NoError) { + if (!display.HasLayers()) { continue; } - const auto& igbp_buffer = *buffer.graphic_buffer; - if (!system.IsPoweredOn()) { return; // We are likely shutting down } - // Now send the buffer to the GPU for drawing. - // TODO(Subv): Support more than just disp0. The display device selection is probably based - // on which display we're drawing (Default, Internal, External, etc) auto nvdisp = nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>(disp_fd); ASSERT(nvdisp); - Common::Rectangle<int> crop_rect{ - static_cast<int>(buffer.crop.Left()), static_cast<int>(buffer.crop.Top()), - static_cast<int>(buffer.crop.Right()), static_cast<int>(buffer.crop.Bottom())}; - - nvdisp->flip(igbp_buffer.BufferId(), igbp_buffer.Offset(), igbp_buffer.ExternalFormat(), - igbp_buffer.Width(), igbp_buffer.Height(), igbp_buffer.Stride(), - static_cast<android::BufferTransformFlags>(buffer.transform), crop_rect, - buffer.fence.fences, buffer.fence.num_fences); - - MicroProfileFlip(); - - swap_interval = buffer.swap_interval; - - layer.GetConsumer().ReleaseBuffer(buffer, android::Fence::NoFence()); + swap_interval = display.GetComposer().ComposeLocked(&compose_speed_scale, display, *nvdisp, + swap_interval); } } @@ -334,15 +309,16 @@ s64 Nvnflinger::GetNextTicks() const { speed_scale = 0.01f; } } + + // Adjust by speed limit determined during composition. + speed_scale /= compose_speed_scale; + if (system.GetNVDECActive() && settings.use_video_framerate.GetValue()) { // Run at intended presentation rate during video playback. speed_scale = 1.f; } - // As an extension, treat nonpositive swap interval as framerate multiplier. - const f32 effective_fps = swap_interval <= 0 ? 120.f * static_cast<f32>(1 - swap_interval) - : 60.f / static_cast<f32>(swap_interval); - + const f32 effective_fps = 60.f / static_cast<f32>(swap_interval); return static_cast<s64>(speed_scale * (1000000000.f / effective_fps)); } diff --git a/src/core/hle/service/nvnflinger/nvnflinger.h b/src/core/hle/service/nvnflinger/nvnflinger.h index 369439142..c984d55a0 100644 --- a/src/core/hle/service/nvnflinger/nvnflinger.h +++ b/src/core/hle/service/nvnflinger/nvnflinger.h @@ -46,6 +46,7 @@ class BufferQueueProducer; namespace Service::Nvnflinger { class FbShareBufferManager; +class HardwareComposer; class HosBinderDriverServer; class Nvnflinger final { @@ -143,6 +144,7 @@ private: u32 next_buffer_queue_id = 1; s32 swap_interval = 1; + f32 compose_speed_scale = 1.0f; bool is_abandoned = false; diff --git a/src/core/hle/service/psc/time/clocks/context_writers.cpp b/src/core/hle/service/psc/time/clocks/context_writers.cpp index ac8700f76..a44486b43 100644 --- a/src/core/hle/service/psc/time/clocks/context_writers.cpp +++ b/src/core/hle/service/psc/time/clocks/context_writers.cpp @@ -22,7 +22,7 @@ LocalSystemClockContextWriter::LocalSystemClockContextWriter(Core::System& syste SharedMemory& shared_memory) : m_system{system}, m_shared_memory{shared_memory} {} -Result LocalSystemClockContextWriter::Write(SystemClockContext& context) { +Result LocalSystemClockContextWriter::Write(const SystemClockContext& context) { if (m_in_use) { R_SUCCEED_IF(context == m_context); m_context = context; @@ -43,7 +43,7 @@ NetworkSystemClockContextWriter::NetworkSystemClockContextWriter(Core::System& s SystemClockCore& system_clock) : m_system{system}, m_shared_memory{shared_memory}, m_system_clock{system_clock} {} -Result NetworkSystemClockContextWriter::Write(SystemClockContext& context) { +Result NetworkSystemClockContextWriter::Write(const SystemClockContext& context) { s64 time{}; [[maybe_unused]] auto res = m_system_clock.GetCurrentTime(&time); @@ -66,7 +66,7 @@ EphemeralNetworkSystemClockContextWriter::EphemeralNetworkSystemClockContextWrit Core::System& system) : m_system{system} {} -Result EphemeralNetworkSystemClockContextWriter::Write(SystemClockContext& context) { +Result EphemeralNetworkSystemClockContextWriter::Write(const SystemClockContext& context) { if (m_in_use) { R_SUCCEED_IF(context == m_context); m_context = context; diff --git a/src/core/hle/service/psc/time/clocks/context_writers.h b/src/core/hle/service/psc/time/clocks/context_writers.h index afd3725d4..6643fc9f2 100644 --- a/src/core/hle/service/psc/time/clocks/context_writers.h +++ b/src/core/hle/service/psc/time/clocks/context_writers.h @@ -24,7 +24,7 @@ private: public: virtual ~ContextWriter() = default; - virtual Result Write(SystemClockContext& context) = 0; + virtual Result Write(const SystemClockContext& context) = 0; void SignalAllNodes(); void Link(OperationEvent& operation_event); @@ -37,7 +37,7 @@ class LocalSystemClockContextWriter : public ContextWriter { public: explicit LocalSystemClockContextWriter(Core::System& system, SharedMemory& shared_memory); - Result Write(SystemClockContext& context) override; + Result Write(const SystemClockContext& context) override; private: Core::System& m_system; @@ -52,7 +52,7 @@ public: explicit NetworkSystemClockContextWriter(Core::System& system, SharedMemory& shared_memory, SystemClockCore& system_clock); - Result Write(SystemClockContext& context) override; + Result Write(const SystemClockContext& context) override; private: Core::System& m_system; @@ -67,7 +67,7 @@ class EphemeralNetworkSystemClockContextWriter : public ContextWriter { public: EphemeralNetworkSystemClockContextWriter(Core::System& system); - Result Write(SystemClockContext& context) override; + Result Write(const SystemClockContext& context) override; private: Core::System& m_system; diff --git a/src/core/hle/service/psc/time/clocks/standard_local_system_clock_core.cpp b/src/core/hle/service/psc/time/clocks/standard_local_system_clock_core.cpp index 36dca6689..6a74d4594 100644 --- a/src/core/hle/service/psc/time/clocks/standard_local_system_clock_core.cpp +++ b/src/core/hle/service/psc/time/clocks/standard_local_system_clock_core.cpp @@ -5,7 +5,7 @@ namespace Service::PSC::Time { -void StandardLocalSystemClockCore::Initialize(SystemClockContext& context, s64 time) { +void StandardLocalSystemClockCore::Initialize(const SystemClockContext& context, s64 time) { SteadyClockTimePoint time_point{}; if (GetCurrentTimePoint(time_point) == ResultSuccess && context.steady_time_point.IdMatches(time_point)) { diff --git a/src/core/hle/service/psc/time/clocks/standard_local_system_clock_core.h b/src/core/hle/service/psc/time/clocks/standard_local_system_clock_core.h index 176ba3e94..5722d8e96 100644 --- a/src/core/hle/service/psc/time/clocks/standard_local_system_clock_core.h +++ b/src/core/hle/service/psc/time/clocks/standard_local_system_clock_core.h @@ -17,7 +17,7 @@ public: : SystemClockCore{steady_clock} {} ~StandardLocalSystemClockCore() override = default; - void Initialize(SystemClockContext& context, s64 time); + void Initialize(const SystemClockContext& context, s64 time); }; } // namespace Service::PSC::Time diff --git a/src/core/hle/service/psc/time/clocks/standard_network_system_clock_core.cpp b/src/core/hle/service/psc/time/clocks/standard_network_system_clock_core.cpp index 8d6cb7db1..6938d369f 100644 --- a/src/core/hle/service/psc/time/clocks/standard_network_system_clock_core.cpp +++ b/src/core/hle/service/psc/time/clocks/standard_network_system_clock_core.cpp @@ -5,7 +5,7 @@ namespace Service::PSC::Time { -void StandardNetworkSystemClockCore::Initialize(SystemClockContext& context, s64 accuracy) { +void StandardNetworkSystemClockCore::Initialize(const SystemClockContext& context, s64 accuracy) { if (SetContextAndWrite(context) != ResultSuccess) { LOG_ERROR(Service_Time, "Failed to SetContext"); } diff --git a/src/core/hle/service/psc/time/clocks/standard_network_system_clock_core.h b/src/core/hle/service/psc/time/clocks/standard_network_system_clock_core.h index 933d2c8e3..bfafc7d71 100644 --- a/src/core/hle/service/psc/time/clocks/standard_network_system_clock_core.h +++ b/src/core/hle/service/psc/time/clocks/standard_network_system_clock_core.h @@ -19,7 +19,7 @@ public: : SystemClockCore{steady_clock} {} ~StandardNetworkSystemClockCore() override = default; - void Initialize(SystemClockContext& context, s64 accuracy); + void Initialize(const SystemClockContext& context, s64 accuracy); bool IsAccuracySufficient(); private: diff --git a/src/core/hle/service/psc/time/clocks/standard_user_system_clock_core.cpp b/src/core/hle/service/psc/time/clocks/standard_user_system_clock_core.cpp index 9e9be05d6..31ed27396 100644 --- a/src/core/hle/service/psc/time/clocks/standard_user_system_clock_core.cpp +++ b/src/core/hle/service/psc/time/clocks/standard_user_system_clock_core.cpp @@ -46,7 +46,7 @@ Result StandardUserSystemClockCore::GetContext(SystemClockContext& out_context) R_RETURN(m_local_system_clock.GetContext(out_context)); } -Result StandardUserSystemClockCore::SetContext(SystemClockContext& context) { +Result StandardUserSystemClockCore::SetContext(const SystemClockContext& context) { R_RETURN(ResultNotImplemented); } diff --git a/src/core/hle/service/psc/time/clocks/standard_user_system_clock_core.h b/src/core/hle/service/psc/time/clocks/standard_user_system_clock_core.h index a7fe7648d..32b8bc3bc 100644 --- a/src/core/hle/service/psc/time/clocks/standard_user_system_clock_core.h +++ b/src/core/hle/service/psc/time/clocks/standard_user_system_clock_core.h @@ -36,7 +36,7 @@ public: Result SetAutomaticCorrection(bool automatic_correction); Result GetContext(SystemClockContext& out_context) const override; - Result SetContext(SystemClockContext& context) override; + Result SetContext(const SystemClockContext& context) override; Result GetTimePoint(SteadyClockTimePoint& out_time_point); void SetTimePointAndSignal(SteadyClockTimePoint& time_point); diff --git a/src/core/hle/service/psc/time/clocks/system_clock_core.cpp b/src/core/hle/service/psc/time/clocks/system_clock_core.cpp index c507ef517..2b7466831 100644 --- a/src/core/hle/service/psc/time/clocks/system_clock_core.cpp +++ b/src/core/hle/service/psc/time/clocks/system_clock_core.cpp @@ -51,12 +51,12 @@ Result SystemClockCore::GetContext(SystemClockContext& out_context) const { R_SUCCEED(); } -Result SystemClockCore::SetContext(SystemClockContext& context) { +Result SystemClockCore::SetContext(const SystemClockContext& context) { m_context = context; R_SUCCEED(); } -Result SystemClockCore::SetContextAndWrite(SystemClockContext& context) { +Result SystemClockCore::SetContextAndWrite(const SystemClockContext& context) { R_TRY(SetContext(context)); if (m_context_writer) { diff --git a/src/core/hle/service/psc/time/clocks/system_clock_core.h b/src/core/hle/service/psc/time/clocks/system_clock_core.h index 73811712e..0b928432f 100644 --- a/src/core/hle/service/psc/time/clocks/system_clock_core.h +++ b/src/core/hle/service/psc/time/clocks/system_clock_core.h @@ -41,8 +41,8 @@ public: } virtual Result GetContext(SystemClockContext& out_context) const; - virtual Result SetContext(SystemClockContext& context); - Result SetContextAndWrite(SystemClockContext& context); + virtual Result SetContext(const SystemClockContext& context); + Result SetContextAndWrite(const SystemClockContext& context); void LinkOperationEvent(OperationEvent& operation_event); diff --git a/src/core/hle/service/psc/time/service_manager.cpp b/src/core/hle/service/psc/time/service_manager.cpp index 4e1643fcb..ed9fb32cd 100644 --- a/src/core/hle/service/psc/time/service_manager.cpp +++ b/src/core/hle/service/psc/time/service_manager.cpp @@ -78,8 +78,9 @@ Result ServiceManager::GetStaticServiceAsServiceManager(OutInterface<StaticServi } Result ServiceManager::SetupStandardSteadyClockCore(bool is_rtc_reset_detected, - Common::UUID& clock_source_id, s64 rtc_offset, - s64 internal_offset, s64 test_offset) { + const Common::UUID& clock_source_id, + s64 rtc_offset, s64 internal_offset, + s64 test_offset) { LOG_DEBUG(Service_Time, "called. is_rtc_reset_detected={} clock_source_id={} rtc_offset={} " "internal_offset={} test_offset={}", @@ -102,7 +103,8 @@ Result ServiceManager::SetupStandardSteadyClockCore(bool is_rtc_reset_detected, R_SUCCEED(); } -Result ServiceManager::SetupStandardLocalSystemClockCore(SystemClockContext& context, s64 time) { +Result ServiceManager::SetupStandardLocalSystemClockCore(const SystemClockContext& context, + s64 time) { LOG_DEBUG(Service_Time, "called. context={} context.steady_time_point.clock_source_id={} time={}", context, context.steady_time_point.clock_source_id.RawString(), time); @@ -114,7 +116,7 @@ Result ServiceManager::SetupStandardLocalSystemClockCore(SystemClockContext& con R_SUCCEED(); } -Result ServiceManager::SetupStandardNetworkSystemClockCore(SystemClockContext& context, +Result ServiceManager::SetupStandardNetworkSystemClockCore(SystemClockContext context, s64 accuracy) { LOG_DEBUG(Service_Time, "called. context={} steady_time_point.clock_source_id={} accuracy={}", context, context.steady_time_point.clock_source_id.RawString(), accuracy); @@ -131,7 +133,7 @@ Result ServiceManager::SetupStandardNetworkSystemClockCore(SystemClockContext& c } Result ServiceManager::SetupStandardUserSystemClockCore(bool automatic_correction, - SteadyClockTimePoint& time_point) { + SteadyClockTimePoint time_point) { LOG_DEBUG(Service_Time, "called. automatic_correction={} time_point={} clock_source_id={}", automatic_correction, time_point, time_point.clock_source_id.RawString()); @@ -144,9 +146,9 @@ Result ServiceManager::SetupStandardUserSystemClockCore(bool automatic_correctio R_SUCCEED(); } -Result ServiceManager::SetupTimeZoneServiceCore(LocationName& name, RuleVersion& rule_version, - u32 location_count, - SteadyClockTimePoint& time_point, +Result ServiceManager::SetupTimeZoneServiceCore(const LocationName& name, + const RuleVersion& rule_version, u32 location_count, + const SteadyClockTimePoint& time_point, InBuffer<BufferAttr_HipcAutoSelect> rule_buffer) { LOG_DEBUG(Service_Time, "called. name={} rule_version={} location_count={} time_point={} " diff --git a/src/core/hle/service/psc/time/service_manager.h b/src/core/hle/service/psc/time/service_manager.h index 25d361d4f..22720e161 100644 --- a/src/core/hle/service/psc/time/service_manager.h +++ b/src/core/hle/service/psc/time/service_manager.h @@ -34,14 +34,15 @@ public: Result GetStaticServiceAsAdmin(OutInterface<StaticService> out_service); Result GetStaticServiceAsRepair(OutInterface<StaticService> out_service); Result GetStaticServiceAsServiceManager(OutInterface<StaticService> out_service); - Result SetupStandardSteadyClockCore(bool is_rtc_reset_detected, Common::UUID& clock_source_id, - s64 rtc_offset, s64 internal_offset, s64 test_offset); - Result SetupStandardLocalSystemClockCore(SystemClockContext& context, s64 time); - Result SetupStandardNetworkSystemClockCore(SystemClockContext& context, s64 accuracy); + Result SetupStandardSteadyClockCore(bool is_rtc_reset_detected, + const Common::UUID& clock_source_id, s64 rtc_offset, + s64 internal_offset, s64 test_offset); + Result SetupStandardLocalSystemClockCore(const SystemClockContext& context, s64 time); + Result SetupStandardNetworkSystemClockCore(SystemClockContext context, s64 accuracy); Result SetupStandardUserSystemClockCore(bool automatic_correction, - SteadyClockTimePoint& time_point); - Result SetupTimeZoneServiceCore(LocationName& name, RuleVersion& rule_version, - u32 location_count, SteadyClockTimePoint& time_point, + SteadyClockTimePoint time_point); + Result SetupTimeZoneServiceCore(const LocationName& name, const RuleVersion& rule_version, + u32 location_count, const SteadyClockTimePoint& time_point, InBuffer<BufferAttr_HipcAutoSelect> rule_buffer); Result SetupEphemeralNetworkSystemClockCore(); Result GetStandardLocalClockOperationEvent(OutCopyHandle<Kernel::KReadableEvent> out_event); diff --git a/src/core/hle/service/psc/time/shared_memory.cpp b/src/core/hle/service/psc/time/shared_memory.cpp index defaceebe..adef6bcd8 100644 --- a/src/core/hle/service/psc/time/shared_memory.cpp +++ b/src/core/hle/service/psc/time/shared_memory.cpp @@ -51,11 +51,11 @@ SharedMemory::SharedMemory(Core::System& system) std::memset(m_shared_memory_ptr, 0, sizeof(*m_shared_memory_ptr)); } -void SharedMemory::SetLocalSystemContext(SystemClockContext& context) { +void SharedMemory::SetLocalSystemContext(const SystemClockContext& context) { WriteToLockFreeAtomicType(&m_shared_memory_ptr->local_system_clock_contexts, context); } -void SharedMemory::SetNetworkSystemContext(SystemClockContext& context) { +void SharedMemory::SetNetworkSystemContext(const SystemClockContext& context) { WriteToLockFreeAtomicType(&m_shared_memory_ptr->network_system_clock_contexts, context); } @@ -64,7 +64,7 @@ void SharedMemory::SetSteadyClockTimePoint(ClockSourceId clock_source_id, s64 ti {time_point, clock_source_id}); } -void SharedMemory::SetContinuousAdjustment(ContinuousAdjustmentTimePoint& time_point) { +void SharedMemory::SetContinuousAdjustment(const ContinuousAdjustmentTimePoint& time_point) { WriteToLockFreeAtomicType(&m_shared_memory_ptr->continuous_adjustment_time_points, time_point); } diff --git a/src/core/hle/service/psc/time/shared_memory.h b/src/core/hle/service/psc/time/shared_memory.h index f9bf97d5c..b7bd00fc1 100644 --- a/src/core/hle/service/psc/time/shared_memory.h +++ b/src/core/hle/service/psc/time/shared_memory.h @@ -54,10 +54,10 @@ public: return m_k_shared_memory; } - void SetLocalSystemContext(SystemClockContext& context); - void SetNetworkSystemContext(SystemClockContext& context); + void SetLocalSystemContext(const SystemClockContext& context); + void SetNetworkSystemContext(const SystemClockContext& context); void SetSteadyClockTimePoint(ClockSourceId clock_source_id, s64 time_diff); - void SetContinuousAdjustment(ContinuousAdjustmentTimePoint& time_point); + void SetContinuousAdjustment(const ContinuousAdjustmentTimePoint& time_point); void SetAutomaticCorrection(bool automatic_correction); void UpdateBaseTime(s64 time); diff --git a/src/core/hle/service/psc/time/static.cpp b/src/core/hle/service/psc/time/static.cpp index 3ca3311af..24b85cc61 100644 --- a/src/core/hle/service/psc/time/static.cpp +++ b/src/core/hle/service/psc/time/static.cpp @@ -198,8 +198,8 @@ Result StaticService::GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( R_SUCCEED(); } -Result StaticService::CalculateMonotonicSystemClockBaseTimePoint(Out<s64> out_time, - SystemClockContext& context) { +Result StaticService::CalculateMonotonicSystemClockBaseTimePoint( + Out<s64> out_time, const SystemClockContext& context) { SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. context={} out_time={}", context, *out_time); }); R_UNLESS(m_time->m_standard_steady_clock.IsInitialized(), ResultClockUninitialized); @@ -231,10 +231,9 @@ Result StaticService::GetClockSnapshot(OutClockSnapshot out_snapshot, TimeType t R_RETURN(GetClockSnapshotImpl(out_snapshot, user_context, network_context, type)); } -Result StaticService::GetClockSnapshotFromSystemClockContext(TimeType type, - OutClockSnapshot out_snapshot, - SystemClockContext& user_context, - SystemClockContext& network_context) { +Result StaticService::GetClockSnapshotFromSystemClockContext( + TimeType type, OutClockSnapshot out_snapshot, const SystemClockContext& user_context, + const SystemClockContext& network_context) { SCOPE_EXIT({ LOG_DEBUG(Service_Time, "called. type={} user_context={} network_context={} out_snapshot={}", type, @@ -294,8 +293,9 @@ Result StaticService::CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a, } Result StaticService::GetClockSnapshotImpl(OutClockSnapshot out_snapshot, - SystemClockContext& user_context, - SystemClockContext& network_context, TimeType type) { + const SystemClockContext& user_context, + const SystemClockContext& network_context, + TimeType type) { out_snapshot->user_context = user_context; out_snapshot->network_context = network_context; diff --git a/src/core/hle/service/psc/time/static.h b/src/core/hle/service/psc/time/static.h index 120bab259..e11db8093 100644 --- a/src/core/hle/service/psc/time/static.h +++ b/src/core/hle/service/psc/time/static.h @@ -55,18 +55,19 @@ public: Result GetStandardUserSystemClockAutomaticCorrectionUpdatedTime( Out<SteadyClockTimePoint> out_time_point); Result CalculateMonotonicSystemClockBaseTimePoint(Out<s64> out_time, - SystemClockContext& context); + const SystemClockContext& context); Result GetClockSnapshot(OutClockSnapshot out_snapshot, TimeType type); Result GetClockSnapshotFromSystemClockContext(TimeType type, OutClockSnapshot out_snapshot, - SystemClockContext& user_context, - SystemClockContext& network_context); + const SystemClockContext& user_context, + const SystemClockContext& network_context); Result CalculateStandardUserSystemClockDifferenceByUser(Out<s64> out_difference, InClockSnapshot a, InClockSnapshot b); Result CalculateSpanBetween(Out<s64> out_time, InClockSnapshot a, InClockSnapshot b); private: - Result GetClockSnapshotImpl(OutClockSnapshot out_snapshot, SystemClockContext& user_context, - SystemClockContext& network_context, TimeType type); + Result GetClockSnapshotImpl(OutClockSnapshot out_snapshot, + const SystemClockContext& user_context, + const SystemClockContext& network_context, TimeType type); Core::System& m_system; StaticServiceSetupInfo m_setup_info; diff --git a/src/core/hle/service/psc/time/system_clock.cpp b/src/core/hle/service/psc/time/system_clock.cpp index 0695502d5..b4e9264d8 100644 --- a/src/core/hle/service/psc/time/system_clock.cpp +++ b/src/core/hle/service/psc/time/system_clock.cpp @@ -53,7 +53,7 @@ Result SystemClock::GetSystemClockContext(Out<SystemClockContext> out_context) { R_RETURN(m_clock_core.GetContext(*out_context)); } -Result SystemClock::SetSystemClockContext(SystemClockContext& context) { +Result SystemClock::SetSystemClockContext(const SystemClockContext& context) { LOG_DEBUG(Service_Time, "called. context={}", context); R_UNLESS(m_can_write_clock, ResultPermissionDenied); diff --git a/src/core/hle/service/psc/time/system_clock.h b/src/core/hle/service/psc/time/system_clock.h index b40d73595..3c11fb2f8 100644 --- a/src/core/hle/service/psc/time/system_clock.h +++ b/src/core/hle/service/psc/time/system_clock.h @@ -26,7 +26,7 @@ public: Result GetCurrentTime(Out<s64> out_time); Result SetCurrentTime(s64 time); Result GetSystemClockContext(Out<SystemClockContext> out_context); - Result SetSystemClockContext(SystemClockContext& context); + Result SetSystemClockContext(const SystemClockContext& context); Result GetOperationEventReadableHandle(OutCopyHandle<Kernel::KReadableEvent> out_event); private: diff --git a/src/core/hle/service/psc/time/time_zone.cpp b/src/core/hle/service/psc/time/time_zone.cpp index cc855c763..81bfb9092 100644 --- a/src/core/hle/service/psc/time/time_zone.cpp +++ b/src/core/hle/service/psc/time/time_zone.cpp @@ -55,7 +55,7 @@ constexpr bool GetTimeZoneTime(s64& out_time, const Tz::Rule& rule, s64 time, s3 } } // namespace -void TimeZone::SetTimePoint(SteadyClockTimePoint& time_point) { +void TimeZone::SetTimePoint(const SteadyClockTimePoint& time_point) { std::scoped_lock l{m_mutex}; m_steady_clock_time_point = time_point; } @@ -65,7 +65,7 @@ void TimeZone::SetTotalLocationNameCount(u32 count) { m_total_location_name_count = count; } -void TimeZone::SetRuleVersion(RuleVersion& rule_version) { +void TimeZone::SetRuleVersion(const RuleVersion& rule_version) { std::scoped_lock l{m_mutex}; m_rule_version = rule_version; } @@ -123,7 +123,7 @@ Result TimeZone::ToCalendarTimeWithMyRule(CalendarTime& calendar_time, R_RETURN(ToCalendarTimeImpl(calendar_time, calendar_additional, time, m_my_rule)); } -Result TimeZone::ParseBinary(LocationName& name, std::span<const u8> binary) { +Result TimeZone::ParseBinary(const LocationName& name, std::span<const u8> binary) { std::scoped_lock l{m_mutex}; Tz::Rule tmp_rule{}; diff --git a/src/core/hle/service/psc/time/time_zone.h b/src/core/hle/service/psc/time/time_zone.h index 6248e45f9..0e4ed6ed0 100644 --- a/src/core/hle/service/psc/time/time_zone.h +++ b/src/core/hle/service/psc/time/time_zone.h @@ -23,9 +23,9 @@ public: m_initialized = true; } - void SetTimePoint(SteadyClockTimePoint& time_point); + void SetTimePoint(const SteadyClockTimePoint& time_point); void SetTotalLocationNameCount(u32 count); - void SetRuleVersion(RuleVersion& rule_version); + void SetRuleVersion(const RuleVersion& rule_version); Result GetLocationName(LocationName& out_name); Result GetTotalLocationCount(u32& out_count); Result GetRuleVersion(RuleVersion& out_rule_version); @@ -36,7 +36,7 @@ public: const Tz::Rule& rule); Result ToCalendarTimeWithMyRule(CalendarTime& calendar_time, CalendarAdditionalInfo& calendar_additional, s64 time); - Result ParseBinary(LocationName& name, std::span<const u8> binary); + Result ParseBinary(const LocationName& name, std::span<const u8> binary); Result ParseBinaryInto(Tz::Rule& out_rule, std::span<const u8> binary); Result ToPosixTime(u32& out_count, std::span<s64> out_times, size_t out_times_max_count, const CalendarTime& calendar, const Tz::Rule& rule); diff --git a/src/core/hle/service/psc/time/time_zone_service.cpp b/src/core/hle/service/psc/time/time_zone_service.cpp index eb81f5b03..2f80030a4 100644 --- a/src/core/hle/service/psc/time/time_zone_service.cpp +++ b/src/core/hle/service/psc/time/time_zone_service.cpp @@ -42,7 +42,7 @@ Result TimeZoneService::GetDeviceLocationName(Out<LocationName> out_location_nam R_RETURN(m_time_zone.GetLocationName(*out_location_name)); } -Result TimeZoneService::SetDeviceLocationName(LocationName& location_name) { +Result TimeZoneService::SetDeviceLocationName(const LocationName& location_name) { LOG_DEBUG(Service_Time, "called. This function is not implemented!"); R_UNLESS(m_can_write_timezone_device_location, ResultPermissionDenied); @@ -62,7 +62,7 @@ Result TimeZoneService::LoadLocationNameList( R_RETURN(ResultNotImplemented); } -Result TimeZoneService::LoadTimeZoneRule(OutRule out_rule, LocationName& location_name) { +Result TimeZoneService::LoadTimeZoneRule(OutRule out_rule, const LocationName& location_name) { LOG_DEBUG(Service_Time, "called. This function is not implemented!"); R_RETURN(ResultNotImplemented); @@ -86,7 +86,7 @@ Result TimeZoneService::GetDeviceLocationNameAndUpdatedTime( } Result TimeZoneService::SetDeviceLocationNameWithTimeZoneRule( - LocationName& location_name, InBuffer<BufferAttr_HipcAutoSelect> binary) { + const LocationName& location_name, InBuffer<BufferAttr_HipcAutoSelect> binary) { LOG_DEBUG(Service_Time, "called. location_name={}", location_name); R_UNLESS(m_can_write_timezone_device_location, ResultPermissionDenied); diff --git a/src/core/hle/service/psc/time/time_zone_service.h b/src/core/hle/service/psc/time/time_zone_service.h index 6eb9ddc4b..79b6073e5 100644 --- a/src/core/hle/service/psc/time/time_zone_service.h +++ b/src/core/hle/service/psc/time/time_zone_service.h @@ -31,16 +31,16 @@ public: ~TimeZoneService() override = default; Result GetDeviceLocationName(Out<LocationName> out_location_name); - Result SetDeviceLocationName(LocationName& location_name); + Result SetDeviceLocationName(const LocationName& location_name); Result GetTotalLocationNameCount(Out<u32> out_count); Result LoadLocationNameList(Out<u32> out_count, OutArray<LocationName, BufferAttr_HipcMapAlias> out_names, u32 index); - Result LoadTimeZoneRule(OutRule out_rule, LocationName& location_name); + Result LoadTimeZoneRule(OutRule out_rule, const LocationName& location_name); Result GetTimeZoneRuleVersion(Out<RuleVersion> out_rule_version); Result GetDeviceLocationNameAndUpdatedTime(Out<LocationName> location_name, Out<SteadyClockTimePoint> out_time_point); - Result SetDeviceLocationNameWithTimeZoneRule(LocationName& location_name, + Result SetDeviceLocationNameWithTimeZoneRule(const LocationName& location_name, InBuffer<BufferAttr_HipcAutoSelect> binary); Result ParseTimeZoneBinary(OutRule out_rule, InBuffer<BufferAttr_HipcAutoSelect> binary); Result GetDeviceLocationNameOperationEventReadableHandle( diff --git a/src/core/hle/service/ro/ro.cpp b/src/core/hle/service/ro/ro.cpp index 51196170a..3d3ad2d62 100644 --- a/src/core/hle/service/ro/ro.cpp +++ b/src/core/hle/service/ro/ro.cpp @@ -549,13 +549,13 @@ public: } Result RegisterProcessHandle(ClientProcessId client_pid, - InCopyHandle<Kernel::KProcess>& process) { + InCopyHandle<Kernel::KProcess> process) { // Register the process. R_RETURN(m_ro->RegisterProcess(std::addressof(m_context_id), process.Get(), *client_pid)); } Result RegisterProcessModuleInfo(ClientProcessId client_pid, u64 nrr_address, u64 nrr_size, - InCopyHandle<Kernel::KProcess>& process) { + InCopyHandle<Kernel::KProcess> process) { // Validate the process. R_TRY(m_ro->ValidateProcess(m_context_id, *client_pid)); diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp index dab1905cc..7f2af9acc 100644 --- a/src/core/hle/service/vi/display/vi_display.cpp +++ b/src/core/hle/service/vi/display/vi_display.cpp @@ -16,6 +16,7 @@ #include "core/hle/service/nvnflinger/buffer_queue_consumer.h" #include "core/hle/service/nvnflinger/buffer_queue_core.h" #include "core/hle/service/nvnflinger/buffer_queue_producer.h" +#include "core/hle/service/nvnflinger/hardware_composer.h" #include "core/hle/service/nvnflinger/hos_binder_driver_server.h" #include "core/hle/service/vi/display/vi_display.h" #include "core/hle/service/vi/layer/vi_layer.h" @@ -43,6 +44,7 @@ Display::Display(u64 id, std::string name_, KernelHelpers::ServiceContext& service_context_, Core::System& system_) : display_id{id}, name{std::move(name_)}, hos_binder_driver_server{hos_binder_driver_server_}, service_context{service_context_} { + hardware_composer = std::make_unique<Nvnflinger::HardwareComposer>(); vsync_event = service_context.CreateEvent(fmt::format("Display VSync Event {}", id)); } @@ -81,8 +83,6 @@ void Display::SignalVSyncEvent() { void Display::CreateLayer(u64 layer_id, u32 binder_id, Service::Nvidia::NvCore::Container& nv_core) { - ASSERT_MSG(layers.empty(), "Only one layer is supported per display at the moment"); - auto [core, producer, consumer] = CreateBufferQueue(service_context, nv_core.GetNvMapFile()); auto buffer_item_consumer = std::make_shared<android::BufferItemConsumer>(std::move(consumer)); diff --git a/src/core/hle/service/vi/display/vi_display.h b/src/core/hle/service/vi/display/vi_display.h index 8eb8a5155..220292cff 100644 --- a/src/core/hle/service/vi/display/vi_display.h +++ b/src/core/hle/service/vi/display/vi_display.h @@ -11,9 +11,14 @@ #include "common/common_types.h" #include "core/hle/result.h" +namespace Core { +class System; +} + namespace Kernel { class KEvent; -} +class KReadableEvent; +} // namespace Kernel namespace Service::android { class BufferQueueProducer; @@ -24,8 +29,9 @@ class ServiceContext; } namespace Service::Nvnflinger { +class HardwareComposer; class HosBinderDriverServer; -} +} // namespace Service::Nvnflinger namespace Service::Nvidia::NvCore { class Container; @@ -118,6 +124,10 @@ public: /// const Layer* FindLayer(u64 layer_id) const; + Nvnflinger::HardwareComposer& GetComposer() const { + return *hardware_composer; + } + private: u64 display_id; std::string name; @@ -125,6 +135,7 @@ private: KernelHelpers::ServiceContext& service_context; std::vector<std::unique_ptr<Layer>> layers; + std::unique_ptr<Nvnflinger::HardwareComposer> hardware_composer; Kernel::KEvent* vsync_event{}; bool is_abandoned{}; }; diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 73058db9a..d508ed28c 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -195,8 +195,9 @@ 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}", buffer_id); + LOG_INFO(Service_VI, "called. buffer_id={:#x}, aruid={:#x}", buffer_id, aruid); struct OutputParameters { s32 nvmap_handle; @@ -206,7 +207,7 @@ private: OutputParameters out{}; Nvnflinger::SharedMemoryPoolLayout layout{}; const auto result = nvnflinger.GetSystemBufferManager().GetSharedBufferMemoryHandleId( - &out.size, &out.nvmap_handle, &layout, buffer_id, 0); + &out.size, &out.nvmap_handle, &layout, buffer_id, aruid); ctx.WriteBuffer(&layout, sizeof(layout)); |