diff --git a/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp b/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp index 2913d25819..3bc23aa976 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp +++ b/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2014 The Android Open Source Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -100,14 +97,6 @@ Status BufferQueueConsumer::AcquireBuffer(BufferItem* out_buffer, slots[slot].needs_cleanup_on_release = false; slots[slot].buffer_state = BufferState::Acquired; - // Mark tracked buffer history records as acquired - for (auto& buffer_history_record : core->buffer_history) { - if (buffer_history_record.frame_number == core->frame_counter) { - buffer_history_record.state = BufferState::Acquired; - break; - } - } - // TODO: for now, avoid resetting the fence, so that when we next return this // slot to the producer, it will wait for the fence to pass. We should fix this // by properly waiting for the fence in the BufferItemConsumer. @@ -331,7 +320,7 @@ void BufferQueueConsumer::Transact(u32 code, std::span parcel_data, const auto serialized = parcel_out.Serialize(); std::memcpy(parcel_reply.data(), serialized.data(), - (std::min)(parcel_reply.size(), serialized.size())); + std::min(parcel_reply.size(), serialized.size())); } Kernel::KReadableEvent* BufferQueueConsumer::GetNativeHandle(u32 type_id) { diff --git a/src/core/hle/service/nvnflinger/buffer_queue_core.cpp b/src/core/hle/service/nvnflinger/buffer_queue_core.cpp index 6120d8eae1..5d8c861fa7 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_core.cpp +++ b/src/core/hle/service/nvnflinger/buffer_queue_core.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2014 The Android Open Source Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -14,17 +11,8 @@ namespace Service::android { BufferQueueCore::BufferQueueCore() = default; -BufferQueueCore::~BufferQueueCore() = default; -void BufferQueueCore::PushHistory(u64 frame_number, s64 queue_time, s64 presentation_time, BufferState state) { - buffer_history_pos = (buffer_history_pos + 1) % BUFFER_HISTORY_SIZE; - buffer_history[buffer_history_pos] = BufferHistoryInfo{ - .frame_number = frame_number, - .queue_time = queue_time, - .presentation_time = presentation_time, - .state = state, - }; -} +BufferQueueCore::~BufferQueueCore() = default; void BufferQueueCore::SignalDequeueCondition() { dequeue_possible.store(true); diff --git a/src/core/hle/service/nvnflinger/buffer_queue_core.h b/src/core/hle/service/nvnflinger/buffer_queue_core.h index ed7d4b4069..e513d183bf 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_core.h +++ b/src/core/hle/service/nvnflinger/buffer_queue_core.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2014 The Android Open Source Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -18,29 +15,12 @@ #include "core/hle/service/nvnflinger/buffer_item.h" #include "core/hle/service/nvnflinger/buffer_queue_defs.h" -#include "core/hle/service/nvnflinger/buffer_slot.h" #include "core/hle/service/nvnflinger/pixel_format.h" #include "core/hle/service/nvnflinger/status.h" #include "core/hle/service/nvnflinger/window.h" namespace Service::android { -#ifdef _MSC_VER -#pragma pack(push, 1) -struct BufferHistoryInfo { -#elif defined(__GNUC__) || defined(__clang__) -struct __attribute__((packed)) BufferHistoryInfo { -#endif - u64 frame_number; - s64 queue_time; - s64 presentation_time; - BufferState state; -}; -#ifdef _MSC_VER -#pragma pack(pop) -#endif -static_assert(sizeof(BufferHistoryInfo) == 0x1C, "BufferHistoryInfo must be 28 bytes"); - class IConsumerListener; class IProducerListener; @@ -50,13 +30,10 @@ class BufferQueueCore final { public: static constexpr s32 INVALID_BUFFER_SLOT = BufferItem::INVALID_BUFFER_SLOT; - static constexpr u32 BUFFER_HISTORY_SIZE = 8; BufferQueueCore(); ~BufferQueueCore(); - void PushHistory(u64 frame_number, s64 queue_time, s64 presentation_time, BufferState state); - private: void SignalDequeueCondition(); bool WaitForDequeueCondition(std::unique_lock& lk); @@ -92,8 +69,6 @@ private: const s32 max_acquired_buffer_count{}; // This is always zero on HOS bool buffer_has_been_queued{}; u64 frame_counter{}; - std::array buffer_history{}; - u32 buffer_history_pos{BUFFER_HISTORY_SIZE-1}; u32 transform_hint{}; bool is_allocating{}; mutable std::condition_variable_any is_allocating_condition; diff --git a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp index bc3076d20b..9e5091eebd 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp +++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.cpp @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2014 The Android Open Source Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -515,8 +512,6 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input, slots[slot].buffer_state = BufferState::Queued; ++core->frame_counter; slots[slot].frame_number = core->frame_counter; - slots[slot].queue_time = timestamp; - slots[slot].presentation_time = 0; item.acquire_called = slots[slot].acquire_called; item.graphic_buffer = slots[slot].graphic_buffer; @@ -549,15 +544,6 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input, // mark it as freed if (core->StillTracking(*front)) { slots[front->slot].buffer_state = BufferState::Free; - - // Mark tracked buffer history records as free - for (auto& buffer_history_record : core->buffer_history) { - if (buffer_history_record.frame_number == front->frame_number) { - buffer_history_record.state = BufferState::Free; - break; - } - } - // Reset the frame number of the freed buffer so that it is the first in line to // be dequeued again slots[front->slot].frame_number = 0; @@ -571,7 +557,6 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input, } } - core->PushHistory(core->frame_counter, slots[slot].queue_time, slots[slot].presentation_time, BufferState::Queued); core->buffer_has_been_queued = true; core->SignalDequeueCondition(); output->Inflate(core->default_width, core->default_height, core->transform_hint, @@ -736,26 +721,22 @@ Status BufferQueueProducer::Connect(const std::shared_ptr& li return status; } -// https://android.googlesource.com/platform/frameworks/native/%2B/master/libs/gui/BufferQueueProducer.cpp#1457 Status BufferQueueProducer::Disconnect(NativeWindowApi api) { - LOG_DEBUG(Service_Nvnflinger, "disconnect api = {}", api); + LOG_DEBUG(Service_Nvnflinger, "api = {}", api); - std::shared_ptr listener; Status status = Status::NoError; + std::shared_ptr listener; { std::scoped_lock lock{core->mutex}; + core->WaitWhileAllocatingLocked(); if (core->is_abandoned) { + // Disconnecting after the surface has been abandoned is a no-op. return Status::NoError; } - if (core->connected_api == NativeWindowApi::NoConnectedApi) { - LOG_DEBUG(Service_Nvnflinger, "disconnect: not connected (req = {})", api); - return Status::NoInit; - } - switch (api) { case NativeWindowApi::Egl: case NativeWindowApi::Cpu: @@ -770,20 +751,20 @@ Status BufferQueueProducer::Disconnect(NativeWindowApi api) { buffer_wait_event->Signal(); listener = core->consumer_listener; } else { - LOG_ERROR(Service_Nvnflinger, - "disconnect: still connected to another api (cur = {} req = {})", + LOG_ERROR(Service_Nvnflinger, "still connected to another api (cur = {} req = {})", core->connected_api, api); status = Status::BadValue; } break; default: - LOG_ERROR(Service_Nvnflinger, "disconnect: unknown api = {}", api); + LOG_ERROR(Service_Nvnflinger, "unknown api = {}", api); status = Status::BadValue; break; } } - if (listener) { + // Call back without lock held + if (listener != nullptr) { listener->OnBuffersReleased(); } @@ -822,10 +803,6 @@ Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot, return Status::NoError; } -Kernel::KReadableEvent* BufferQueueProducer::GetNativeHandle(u32 type_id) { - return &buffer_wait_event->GetReadableEvent(); -} - void BufferQueueProducer::Transact(u32 code, std::span parcel_data, std::span parcel_reply, u32 flags) { // Values used by BnGraphicBufferProducer onTransact @@ -945,49 +922,9 @@ void BufferQueueProducer::Transact(u32 code, std::span parcel_data, status = SetBufferCount(buffer_count); break; } - case TransactionId::GetBufferHistory: { - LOG_DEBUG(Service_Nvnflinger, "called, transaction=GetBufferHistory"); - - const s32 request = parcel_in.Read(); - if (request <= 0) { - parcel_out.Write(Status::BadValue); - parcel_out.Write(0); - break; - } - - constexpr u32 history_max = BufferQueueCore::BUFFER_HISTORY_SIZE; - std::array buffer_history_snapshot{}; - s32 valid_index{}; - { - std::scoped_lock lk(core->mutex); - - const u32 current_history_pos = core->buffer_history_pos; - u32 index_reversed{}; - for (u32 i = 0; i < history_max; ++i) { - // Wrap values backwards e.g. 7, 6, 5, etc. in the range of 0-7 - index_reversed = (current_history_pos + history_max - i) % history_max; - const auto& current_history_buffer = core->buffer_history[index_reversed]; - - // Here we use the frame number as a terminator. - // Because a buffer without frame_number is not considered complete - if (current_history_buffer.frame_number == 0) { - break; - } - - buffer_history_snapshot[valid_index] = current_history_buffer; - ++valid_index; - } - } - - const s32 limit = std::min(request, valid_index); - parcel_out.Write(Status::NoError); - parcel_out.Write(limit); - for (s32 i = 0; i < limit; ++i) { - parcel_out.Write(buffer_history_snapshot[i]); - } - + case TransactionId::GetBufferHistory: + LOG_WARNING(Service_Nvnflinger, "(STUBBED) called, transaction=GetBufferHistory"); break; - } default: ASSERT_MSG(false, "Unimplemented TransactionId {}", code); break; @@ -997,8 +934,11 @@ void BufferQueueProducer::Transact(u32 code, std::span parcel_data, const auto serialized = parcel_out.Serialize(); std::memcpy(parcel_reply.data(), serialized.data(), - (std::min)(parcel_reply.size(), serialized.size())); + std::min(parcel_reply.size(), serialized.size())); } +Kernel::KReadableEvent* BufferQueueProducer::GetNativeHandle(u32 type_id) { + return &buffer_wait_event->GetReadableEvent(); +} } // namespace Service::android diff --git a/src/core/hle/service/nvnflinger/buffer_queue_producer.h b/src/core/hle/service/nvnflinger/buffer_queue_producer.h index 6610e0853a..048523514c 100644 --- a/src/core/hle/service/nvnflinger/buffer_queue_producer.h +++ b/src/core/hle/service/nvnflinger/buffer_queue_producer.h @@ -1,6 +1,3 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project -// SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2014 The Android Open Source Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -89,8 +86,6 @@ private: s32 current_callback_ticket{}; std::condition_variable_any callback_condition; - u64 position; - Service::Nvidia::NvCore::NvMap& nvmap; };