diff --git a/src/core/hle/service/kernel_helpers.cpp b/src/core/hle/service/kernel_helpers.cpp index 04b01a5..78b2138 100644 --- a/src/core/hle/service/kernel_helpers.cpp +++ b/src/core/hle/service/kernel_helpers.cpp @@ -14,7 +14,7 @@ namespace Service::KernelHelpers { ServiceContext::ServiceContext(Core::System& system_, std::string name_) - : kernel(system_.Kernel()) { + : m_system(system_), kernel(system_.Kernel()) { if (process = Kernel::GetCurrentProcessPointer(kernel); process != nullptr) { return; } diff --git a/src/core/hle/service/kernel_helpers.h b/src/core/hle/service/kernel_helpers.h index bf2471c..9015221 100644 --- a/src/core/hle/service/kernel_helpers.h +++ b/src/core/hle/service/kernel_helpers.h @@ -26,6 +26,8 @@ public: void CloseEvent(Kernel::KEvent* event); + Core::System& m_system; + private: Kernel::KernelCore& kernel; Kernel::KProcess* process{}; diff --git a/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp b/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp index fd5b6ad..70670f9 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp +++ b/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp @@ -11,6 +11,7 @@ #include "core/hle/service/nvnflinger/buffer_queue_core.h" #include "core/hle/service/nvnflinger/parcel.h" #include "core/hle/service/nvnflinger/producer_listener.h" +#include "core/hle/service/time/clock_types.h" namespace Service::android { @@ -104,7 +105,7 @@ Status BufferQueueConsumer::AcquireBuffer(BufferItem* out_buffer, const auto target_frame_number = slots[slot].frame_number; for (int i = 0; i < core->history.size(); i++) { - if (core->history[i].frame_number = target_frame_number) { + if (core->history[i].frame_number == target_frame_number) { core->history[i].state = BufferState::Acquired; break; } @@ -263,14 +264,28 @@ Status BufferQueueConsumer::GetReleasedBuffers(u64* out_slot_mask) { return Status::NoError; } -/* SetPresentTime -for (int i = 0; i < core->history.size(); i++) { - if (core->history[i].frame_number = target_frame_number) { - core->history[i].state == BufferState::Acquired; - break; +Status BufferQueueConsumer::SetPresentTime(s32 slot, u64 frame_number, + Time::Clock::TimeSpanType presentation_time) { + if (slot < 0 || slot >= slots.size()) + return Status::BadValue; + + std::scoped_lock lock{core->mutex}; + + if (slots[slot].frame_number != frame_number) + return Status::StaleBufferSlot; + + if (slots[slot].presentation_time.nanoseconds == 0) + slots[slot].presentation_time = presentation_time; + + for (int i = 0; i < core->history.size(); i++) { + if (core->history[i].frame_number == frame_number) { + core->history[i].presentation_time = presentation_time; + break; + } } + + return Status::NoError; } -*/ void BufferQueueConsumer::Transact(u32 code, std::span parcel_data, std::span parcel_reply, u32 flags) { @@ -328,6 +343,15 @@ void BufferQueueConsumer::Transact(u32 code, std::span parcel_data, parcel_out.Write(slot_mask); break; } + case TransactionId::SetTransformHint: { + std::scoped_lock lock{core->mutex}; + + const u32 transform_hint = parcel_in.Read(); + LOG_WARNING(Service_Nvnflinger, "Transact::SetTransformHint={}", transform_hint); + status = Status::NoError; + parcel_out.Write(transform_hint); + break; + } default: ASSERT_MSG(false, "called, code={} flags={}", code, flags); break; diff --git a/src/core/hle/service/nvnflinger/buffer_queue_consumer.h b/src/core/hle/service/nvnflinger/buffer_queue_consumer.h index 7fea9ad..bf74412 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_consumer.h +++ b/src/core/hle/service/nvnflinger/buffer_queue_consumer.h @@ -14,6 +14,14 @@ #include "core/hle/service/nvnflinger/buffer_queue_defs.h" #include "core/hle/service/nvnflinger/status.h" +namespace Service { +namespace Time { +namespace Clock { +struct TimeSpanType; +} // namespace Clock +} // namespace Time +} // namespace Service + namespace Service::android { class BufferItem; @@ -30,6 +38,7 @@ public: Status Connect(std::shared_ptr consumer_listener, bool controlled_by_app); Status Disconnect(); Status GetReleasedBuffers(u64* out_slot_mask); + Status SetPresentTime(s32 slot, u64 frame_number, Time::Clock::TimeSpanType presentation_time); void Transact(u32 code, std::span parcel_data, std::span parcel_reply, u32 flags) override; diff --git a/src/core/hle/service/nvnflinger/buffer_queue_core.h b/src/core/hle/service/nvnflinger/buffer_queue_core.h index 669166d..d17ceaf 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_core.h +++ b/src/core/hle/service/nvnflinger/buffer_queue_core.h @@ -18,6 +18,7 @@ #include "core/hle/service/nvnflinger/pixel_format.h" #include "core/hle/service/nvnflinger/status.h" #include "core/hle/service/nvnflinger/window.h" +#include "core/hle/service/time/clock_types.h" namespace Service::android { @@ -76,7 +77,7 @@ private: class BufferInfo final { public: u64 frame_number{}; - s64 queue_time{}, presentation_time{}; + Time::Clock::TimeSpanType queue_time, presentation_time; BufferState state{BufferState::Free}; }; diff --git a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp index 0f8009d..900c6ff 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp +++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp @@ -6,6 +6,7 @@ #include "common/assert.h" #include "common/logging/log.h" +#include "core/core_timing.h" #include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_readable_event.h" #include "core/hle/kernel/kernel.h" @@ -16,6 +17,7 @@ #include "core/hle/service/nvnflinger/parcel.h" #include "core/hle/service/nvnflinger/ui/graphic_buffer.h" #include "core/hle/service/nvnflinger/window.h" +#include "core/hle/service/time/clock_types.h" namespace Service::android { @@ -278,6 +280,9 @@ Status BufferQueueProducer::DequeueBuffer(s32* out_slot, Fence* out_fence, bool return_flags |= Status::BufferNeedsReallocation; } + slots[found].queue_time = Time::Clock::TimeSpanType::FromSeconds(0); + slots[found].presentation_time = Time::Clock::TimeSpanType::FromSeconds(0); + *out_fence = slots[found].fence; slots[found].fence = Fence::NoFence(); } @@ -508,12 +513,17 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input, return Status::BadValue; } + auto& ctx = service_context; + auto& system = ctx.m_system; + slots[slot].fence = fence; slots[slot].buffer_state = BufferState::Queued; ++core->frame_counter; slots[slot].frame_number = core->frame_counter; - slots[slot].queue_time = 0; // this is not the true value - slots[slot].presentation_time = 0; // doesn't need to be set afaik but do it anyway + slots[slot].queue_time = Time::Clock::TimeSpanType::FromTicks( + system.CoreTiming().GetClockTicks()); // this is not the true value + slots[slot].presentation_time = Time::Clock::TimeSpanType::FromSeconds( + 0); // doesn't need to be set afaik but do it anyway item.acquire_called = slots[slot].acquire_called; item.graphic_buffer = slots[slot].graphic_buffer; @@ -569,7 +579,12 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input, core->buffer_has_been_queued = true; core->SignalDequeueCondition(); output->Inflate(core->default_width, core->default_height, core->transform_hint, - static_cast(core->queue.size())); + static_cast(core->queue.size()), core->frame_counter); + + if ((sticky_transform & 8) != 0) { + output->transform_hint |= (u32)NativeWindowTransform::ReturnFrameNumber; + output->frame_number = slots[slot].frame_number; + } // Take a ticket for the callback functions callback_ticket = next_callback_ticket++; @@ -670,7 +685,7 @@ Status BufferQueueProducer::Query(NativeWindow what, s32* out_value) { return Status::BadValue; } - LOG_DEBUG(Service_Nvnflinger, "what = {}, value = {}", what, value); + LOG_WARNING(Service_Nvnflinger, "what = {}, value = {}", what, value); *out_value = static_cast(value); @@ -714,7 +729,7 @@ Status BufferQueueProducer::Connect(const std::shared_ptr& li case NativeWindowApi::Camera: core->connected_api = api; output->Inflate(core->default_width, core->default_height, core->transform_hint, - static_cast(core->queue.size())); + static_cast(core->queue.size()), core->frame_counter); core->connected_producer_listener = listener; break; default: @@ -849,7 +864,12 @@ void BufferQueueProducer::Transact(u32 code, std::span parcel_data, status = Connect(listener, api, producer_controlled_by_app, &output); + LOG_WARNING(Service_Nvnflinger, "Connect, output.frame_number={}, output.transform_hint={}", + output.frame_number, output.transform_hint); + parcel_out.Write(output); + if (output.transform_hint & (u32)NativeWindowTransform::ReturnFrameNumber) + parcel_out.Write(output.frame_number); break; } case TransactionId::SetPreallocatedBuffer: { @@ -892,8 +912,13 @@ void BufferQueueProducer::Transact(u32 code, std::span parcel_data, QueueBufferOutput output; status = QueueBuffer(slot, input, &output); + LOG_WARNING(Service_Nvnflinger, + "QueueBuffer, output.frame_number={}, output.transform_hint={}", + output.frame_number, output.transform_hint); parcel_out.Write(output); + if (output.transform_hint & (u32)NativeWindowTransform::ReturnFrameNumber) + parcel_out.Write(output.frame_number); break; } case TransactionId::Query: { @@ -948,6 +973,7 @@ void BufferQueueProducer::Transact(u32 code, std::span parcel_data, pos--; } + parcel_out.Write(buffer_history_count); parcel_out.WriteFlattenedObject(info); status = Status::NoError; diff --git a/src/core/hle/service/nvnflinger/buffer_slot.h b/src/core/hle/service/nvnflinger/buffer_slot.h index 3f69181..77dae2a 100644 --- a/src/core/hle/service/nvnflinger/buffer_slot.h +++ b/src/core/hle/service/nvnflinger/buffer_slot.h @@ -10,6 +10,7 @@ #include "common/common_types.h" #include "core/hle/service/nvnflinger/ui/fence.h" +#include "core/hle/service/time/clock_types.h" namespace Service::android { @@ -35,7 +36,7 @@ struct BufferSlot final { bool attached_by_consumer{}; bool is_preallocated{}; - s64 queue_time{}, presentation_time{}; + Time::Clock::TimeSpanType queue_time, presentation_time; }; } // namespace Service::android diff --git a/src/core/hle/service/nvnflinger/graphic_buffer_producer.h b/src/core/hle/service/nvnflinger/graphic_buffer_producer.h index 86080e1..d5f2578 100644 --- a/src/core/hle/service/nvnflinger/graphic_buffer_producer.h +++ b/src/core/hle/service/nvnflinger/graphic_buffer_producer.h @@ -51,26 +51,31 @@ static_assert(sizeof(QueueBufferInput) == 84, "QueueBufferInput has wrong size") struct QueueBufferOutput final { QueueBufferOutput(); - void Deflate(u32* width_, u32* height_, u32* transform_hint_, u32* num_pending_buffers_) const { + void Deflate(u32* width_, u32* height_, u32* transform_hint_, u32* num_pending_buffers_, + u64* frame_number_) const { *width_ = width; *height_ = height; *transform_hint_ = transform_hint; *num_pending_buffers_ = num_pending_buffers; + *frame_number_ = frame_number; } - void Inflate(u32 width_, u32 height_, u32 transform_hint_, u32 num_pending_buffers_) { + void Inflate(u32 width_, u32 height_, u32 transform_hint_, u32 num_pending_buffers_, + u64 frame_number_) { width = width_; height = height_; transform_hint = transform_hint_; num_pending_buffers = num_pending_buffers_; + frame_number = frame_number_; } -private: +public: u32 width{}; u32 height{}; u32 transform_hint{}; u32 num_pending_buffers{}; + u64 frame_number{}; }; -static_assert(sizeof(QueueBufferOutput) == 16, "QueueBufferOutput has wrong size"); +static_assert(sizeof(QueueBufferOutput) == 24, "QueueBufferOutput has wrong size"); } // namespace Service::android diff --git a/src/core/hle/service/nvnflinger/window.h b/src/core/hle/service/nvnflinger/window.h index a5fc7d7..755d6a6 100644 --- a/src/core/hle/service/nvnflinger/window.h +++ b/src/core/hle/service/nvnflinger/window.h @@ -48,6 +48,7 @@ enum class NativeWindowScalingMode : s32 { enum class NativeWindowTransform : u32 { None = 0x0, InverseDisplay = 0x08, + ReturnFrameNumber = 0x20 }; DECLARE_ENUM_FLAG_OPERATORS(NativeWindowTransform);