mirror of
https://github.com/yuzu-emu/yuzu.git
synced 2024-07-04 23:31:19 +01:00
hle: nvflinger: Add implementation for ConsumerBase class.
This commit is contained in:
parent
d25cb12bff
commit
79e8cdf595
3 changed files with 190 additions and 0 deletions
|
@ -542,6 +542,8 @@ add_library(core STATIC
|
|||
hle/service/nvflinger/buffer_queue_defs.h
|
||||
hle/service/nvflinger/buffer_slot.h
|
||||
hle/service/nvflinger/buffer_transform_flags.h
|
||||
hle/service/nvflinger/consumer_base.cpp
|
||||
hle/service/nvflinger/consumer_base.h
|
||||
hle/service/nvflinger/consumer_listener.h
|
||||
hle/service/nvflinger/nvflinger.cpp
|
||||
hle/service/nvflinger/nvflinger.h
|
||||
|
|
129
src/core/hle/service/nvflinger/consumer_base.cpp
Normal file
129
src/core/hle/service/nvflinger/consumer_base.cpp
Normal file
|
@ -0,0 +1,129 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright 2021 yuzu Emulator Project
|
||||
// Copyright 2010 The Android Open Source Project
|
||||
// Parts of this implementation were base on:
|
||||
// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/ConsumerBase.cpp
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "core/hle/service/nvflinger/buffer_item.h"
|
||||
#include "core/hle/service/nvflinger/buffer_queue_consumer.h"
|
||||
#include "core/hle/service/nvflinger/buffer_queue_core.h"
|
||||
#include "core/hle/service/nvflinger/consumer_base.h"
|
||||
#include "core/hle/service/nvflinger/ui/graphic_buffer.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
ConsumerBase::ConsumerBase(std::unique_ptr<BufferQueueConsumer> consumer_)
|
||||
: consumer{std::move(consumer_)} {}
|
||||
|
||||
ConsumerBase::~ConsumerBase() {
|
||||
std::unique_lock lock(mutex);
|
||||
|
||||
ASSERT_MSG(is_abandoned, "consumer is not abandoned!");
|
||||
}
|
||||
|
||||
void ConsumerBase::Connect(bool controlled_by_app) {
|
||||
consumer->Connect(shared_from_this(), controlled_by_app);
|
||||
}
|
||||
|
||||
void ConsumerBase::FreeBufferLocked(s32 slot_index) {
|
||||
LOG_DEBUG(Service_NVFlinger, "slot_index={}", slot_index);
|
||||
|
||||
slots[slot_index].graphic_buffer = nullptr;
|
||||
slots[slot_index].fence = Fence::NoFence();
|
||||
slots[slot_index].frame_number = 0;
|
||||
}
|
||||
|
||||
void ConsumerBase::OnFrameAvailable(const BufferItem& item) {
|
||||
std::unique_lock lock(mutex);
|
||||
LOG_DEBUG(Service_NVFlinger, "called");
|
||||
}
|
||||
|
||||
void ConsumerBase::OnFrameReplaced(const BufferItem& item) {
|
||||
std::unique_lock lock(mutex);
|
||||
LOG_DEBUG(Service_NVFlinger, "called");
|
||||
}
|
||||
|
||||
void ConsumerBase::OnBuffersReleased() {
|
||||
std::unique_lock lock(mutex);
|
||||
LOG_DEBUG(Service_NVFlinger, "called");
|
||||
}
|
||||
|
||||
void ConsumerBase::OnSidebandStreamChanged() {}
|
||||
|
||||
Status ConsumerBase::AcquireBufferLocked(BufferItem* item, u64 present_when_ns,
|
||||
u64 max_frame_number) {
|
||||
if (is_abandoned) {
|
||||
LOG_ERROR(Service_NVFlinger, "consumer is abandoned!");
|
||||
return Status::NoInit;
|
||||
}
|
||||
|
||||
Status err = consumer->AcquireBuffer(item, present_when_ns, max_frame_number);
|
||||
if (err != Status::NoError) {
|
||||
return err;
|
||||
}
|
||||
|
||||
if (item->graphic_buffer != nullptr) {
|
||||
if (slots[item->slot].graphic_buffer != nullptr) {
|
||||
FreeBufferLocked(item->slot);
|
||||
}
|
||||
slots[item->slot].graphic_buffer = item->graphic_buffer;
|
||||
}
|
||||
|
||||
slots[item->slot].frame_number = item->frame_number;
|
||||
slots[item->slot].fence = item->fence;
|
||||
|
||||
LOG_DEBUG(Service_NVFlinger, "slot={}", item->slot);
|
||||
|
||||
return Status::NoError;
|
||||
}
|
||||
|
||||
Status ConsumerBase::AddReleaseFenceLocked(s32 slot,
|
||||
const std::shared_ptr<GraphicBuffer> graphic_buffer,
|
||||
const Fence& fence) {
|
||||
LOG_DEBUG(Service_NVFlinger, "slot={}", slot);
|
||||
|
||||
// If consumer no longer tracks this graphic_buffer, we can safely
|
||||
// drop this fence, as it will never be received by the producer.
|
||||
|
||||
if (!StillTracking(slot, graphic_buffer)) {
|
||||
return Status::NoError;
|
||||
}
|
||||
|
||||
slots[slot].fence = fence;
|
||||
|
||||
return Status::NoError;
|
||||
}
|
||||
|
||||
Status ConsumerBase::ReleaseBufferLocked(s32 slot,
|
||||
const std::shared_ptr<GraphicBuffer> graphic_buffer) {
|
||||
// If consumer no longer tracks this graphic_buffer (we received a new
|
||||
// buffer on the same slot), the buffer producer is definitely no longer
|
||||
// tracking it.
|
||||
|
||||
if (!StillTracking(slot, graphic_buffer)) {
|
||||
return Status::NoError;
|
||||
}
|
||||
|
||||
LOG_DEBUG(Service_NVFlinger, "slot={}", slot);
|
||||
Status err = consumer->ReleaseBuffer(slot, slots[slot].frame_number, slots[slot].fence);
|
||||
if (err == Status::StaleBufferSlot) {
|
||||
FreeBufferLocked(slot);
|
||||
}
|
||||
|
||||
slots[slot].fence = Fence::NoFence();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
bool ConsumerBase::StillTracking(s32 slot, const std::shared_ptr<GraphicBuffer> graphic_buffer) {
|
||||
if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (slots[slot].graphic_buffer != nullptr &&
|
||||
slots[slot].graphic_buffer->Handle() == graphic_buffer->Handle());
|
||||
}
|
||||
|
||||
} // namespace android
|
59
src/core/hle/service/nvflinger/consumer_base.h
Normal file
59
src/core/hle/service/nvflinger/consumer_base.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
// Copyright 2021 yuzu Emulator Project
|
||||
// Copyright 2010 The Android Open Source Project
|
||||
// Parts of this implementation were base on:
|
||||
// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/include/gui/ConsumerBase.h
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/service/nvflinger/buffer_queue_defs.h"
|
||||
#include "core/hle/service/nvflinger/consumer_listener.h"
|
||||
#include "core/hle/service/nvflinger/status.h"
|
||||
|
||||
namespace android {
|
||||
|
||||
class BufferItem;
|
||||
class BufferQueueConsumer;
|
||||
|
||||
class ConsumerBase : public IConsumerListener, public std::enable_shared_from_this<ConsumerBase> {
|
||||
public:
|
||||
void Connect(bool controlled_by_app);
|
||||
|
||||
protected:
|
||||
ConsumerBase(std::unique_ptr<BufferQueueConsumer> consumer_);
|
||||
virtual ~ConsumerBase();
|
||||
|
||||
virtual void OnFrameAvailable(const BufferItem& item) override;
|
||||
virtual void OnFrameReplaced(const BufferItem& item) override;
|
||||
virtual void OnBuffersReleased() override;
|
||||
virtual void OnSidebandStreamChanged() override;
|
||||
|
||||
void FreeBufferLocked(s32 slot_index);
|
||||
Status AcquireBufferLocked(BufferItem* item, u64 present_when_ns, u64 max_frame_number = 0);
|
||||
Status ReleaseBufferLocked(s32 slot, const std::shared_ptr<GraphicBuffer> graphic_buffer);
|
||||
bool StillTracking(s32 slot, const std::shared_ptr<GraphicBuffer> graphic_buffer);
|
||||
Status AddReleaseFenceLocked(s32 slot, const std::shared_ptr<GraphicBuffer> graphic_buffer,
|
||||
const Fence& fence);
|
||||
|
||||
struct Slot final {
|
||||
std::shared_ptr<GraphicBuffer> graphic_buffer;
|
||||
Fence fence;
|
||||
u64 frame_number{};
|
||||
};
|
||||
|
||||
protected:
|
||||
std::array<Slot, BufferQueueDefs::NUM_BUFFER_SLOTS> slots;
|
||||
|
||||
bool is_abandoned{};
|
||||
|
||||
std::unique_ptr<BufferQueueConsumer> consumer;
|
||||
|
||||
mutable std::mutex mutex;
|
||||
};
|
||||
|
||||
} // namespace android
|
Loading…
Reference in a new issue