nvnflinger: use graphic buffer lifetime for map handle

master
Liam 2023-10-29 16:37:11 +07:00
parent 911d2216be
commit 79e7d7f4ba
12 changed files with 71 additions and 37 deletions

@ -715,6 +715,7 @@ add_library(core STATIC
hle/service/nvnflinger/producer_listener.h hle/service/nvnflinger/producer_listener.h
hle/service/nvnflinger/status.h hle/service/nvnflinger/status.h
hle/service/nvnflinger/ui/fence.h hle/service/nvnflinger/ui/fence.h
hle/service/nvnflinger/ui/graphic_buffer.cpp
hle/service/nvnflinger/ui/graphic_buffer.h hle/service/nvnflinger/ui/graphic_buffer.h
hle/service/nvnflinger/window.h hle/service/nvnflinger/window.h
hle/service/olsc/olsc.cpp hle/service/olsc/olsc.cpp

@ -15,7 +15,7 @@
namespace Service::android { namespace Service::android {
struct GraphicBuffer; class GraphicBuffer;
class BufferItem final { class BufferItem final {
public: public:

@ -5,7 +5,6 @@
// https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/BufferQueueConsumer.cpp // https://cs.android.com/android/platform/superproject/+/android-5.1.1_r38:frameworks/native/libs/gui/BufferQueueConsumer.cpp
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/hle/service/nvdrv/core/nvmap.h"
#include "core/hle/service/nvnflinger/buffer_item.h" #include "core/hle/service/nvnflinger/buffer_item.h"
#include "core/hle/service/nvnflinger/buffer_queue_consumer.h" #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_core.h"
@ -14,9 +13,8 @@
namespace Service::android { namespace Service::android {
BufferQueueConsumer::BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_, BufferQueueConsumer::BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_)
Service::Nvidia::NvCore::NvMap& nvmap_) : core{std::move(core_)}, slots{core->slots} {}
: core{std::move(core_)}, slots{core->slots}, nvmap(nvmap_) {}
BufferQueueConsumer::~BufferQueueConsumer() = default; BufferQueueConsumer::~BufferQueueConsumer() = default;
@ -136,8 +134,6 @@ Status BufferQueueConsumer::ReleaseBuffer(s32 slot, u64 frame_number, const Fenc
slots[slot].buffer_state = BufferState::Free; slots[slot].buffer_state = BufferState::Free;
nvmap.FreeHandle(slots[slot].graphic_buffer->BufferId(), true);
listener = core->connected_producer_listener; listener = core->connected_producer_listener;
LOG_DEBUG(Service_Nvnflinger, "releasing slot {}", slot); LOG_DEBUG(Service_Nvnflinger, "releasing slot {}", slot);

@ -13,10 +13,6 @@
#include "core/hle/service/nvnflinger/buffer_queue_defs.h" #include "core/hle/service/nvnflinger/buffer_queue_defs.h"
#include "core/hle/service/nvnflinger/status.h" #include "core/hle/service/nvnflinger/status.h"
namespace Service::Nvidia::NvCore {
class NvMap;
} // namespace Service::Nvidia::NvCore
namespace Service::android { namespace Service::android {
class BufferItem; class BufferItem;
@ -25,8 +21,7 @@ class IConsumerListener;
class BufferQueueConsumer final { class BufferQueueConsumer final {
public: public:
explicit BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_, explicit BufferQueueConsumer(std::shared_ptr<BufferQueueCore> core_);
Service::Nvidia::NvCore::NvMap& nvmap_);
~BufferQueueConsumer(); ~BufferQueueConsumer();
Status AcquireBuffer(BufferItem* out_buffer, std::chrono::nanoseconds expected_present); Status AcquireBuffer(BufferItem* out_buffer, std::chrono::nanoseconds expected_present);
@ -37,7 +32,6 @@ public:
private: private:
std::shared_ptr<BufferQueueCore> core; std::shared_ptr<BufferQueueCore> core;
BufferQueueDefs::SlotsType& slots; BufferQueueDefs::SlotsType& slots;
Service::Nvidia::NvCore::NvMap& nvmap;
}; };
} // namespace Service::android } // namespace Service::android

@ -13,7 +13,6 @@
#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/kernel.h"
#include "core/hle/service/hle_ipc.h" #include "core/hle/service/hle_ipc.h"
#include "core/hle/service/kernel_helpers.h" #include "core/hle/service/kernel_helpers.h"
#include "core/hle/service/nvdrv/core/nvmap.h"
#include "core/hle/service/nvnflinger/buffer_queue_core.h" #include "core/hle/service/nvnflinger/buffer_queue_core.h"
#include "core/hle/service/nvnflinger/buffer_queue_producer.h" #include "core/hle/service/nvnflinger/buffer_queue_producer.h"
#include "core/hle/service/nvnflinger/consumer_listener.h" #include "core/hle/service/nvnflinger/consumer_listener.h"
@ -533,8 +532,6 @@ Status BufferQueueProducer::QueueBuffer(s32 slot, const QueueBufferInput& input,
item.is_droppable = core->dequeue_buffer_cannot_block || async; item.is_droppable = core->dequeue_buffer_cannot_block || async;
item.swap_interval = swap_interval; item.swap_interval = swap_interval;
nvmap.DuplicateHandle(item.graphic_buffer->BufferId(), true);
sticky_transform = sticky_transform_; sticky_transform = sticky_transform_;
if (core->queue.empty()) { if (core->queue.empty()) {
@ -744,19 +741,13 @@ Status BufferQueueProducer::Disconnect(NativeWindowApi api) {
return Status::NoError; return Status::NoError;
} }
// HACK: We are not Android. Remove handle for items in queue, and clear queue.
// Allows synchronous destruction of nvmap handles.
for (auto& item : core->queue) {
nvmap.FreeHandle(item.graphic_buffer->BufferId(), true);
}
core->queue.clear();
switch (api) { switch (api) {
case NativeWindowApi::Egl: case NativeWindowApi::Egl:
case NativeWindowApi::Cpu: case NativeWindowApi::Cpu:
case NativeWindowApi::Media: case NativeWindowApi::Media:
case NativeWindowApi::Camera: case NativeWindowApi::Camera:
if (core->connected_api == api) { if (core->connected_api == api) {
core->queue.clear();
core->FreeAllBuffersLocked(); core->FreeAllBuffersLocked();
core->connected_producer_listener = nullptr; core->connected_producer_listener = nullptr;
core->connected_api = NativeWindowApi::NoConnectedApi; core->connected_api = NativeWindowApi::NoConnectedApi;
@ -785,7 +776,7 @@ Status BufferQueueProducer::Disconnect(NativeWindowApi api) {
} }
Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot, Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot,
const std::shared_ptr<GraphicBuffer>& buffer) { const std::shared_ptr<NvGraphicBuffer>& buffer) {
LOG_DEBUG(Service_Nvnflinger, "slot {}", slot); LOG_DEBUG(Service_Nvnflinger, "slot {}", slot);
if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) { if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {
@ -796,7 +787,7 @@ Status BufferQueueProducer::SetPreallocatedBuffer(s32 slot,
slots[slot] = {}; slots[slot] = {};
slots[slot].fence = Fence::NoFence(); slots[slot].fence = Fence::NoFence();
slots[slot].graphic_buffer = buffer; slots[slot].graphic_buffer = std::make_shared<GraphicBuffer>(nvmap, buffer);
slots[slot].frame_number = 0; slots[slot].frame_number = 0;
// Most games preallocate a buffer and pass a valid buffer here. However, it is possible for // Most games preallocate a buffer and pass a valid buffer here. However, it is possible for
@ -839,7 +830,7 @@ void BufferQueueProducer::Transact(HLERequestContext& ctx, TransactionId code, u
} }
case TransactionId::SetPreallocatedBuffer: { case TransactionId::SetPreallocatedBuffer: {
const auto slot = parcel_in.Read<s32>(); const auto slot = parcel_in.Read<s32>();
const auto buffer = parcel_in.ReadObject<GraphicBuffer>(); const auto buffer = parcel_in.ReadObject<NvGraphicBuffer>();
status = SetPreallocatedBuffer(slot, buffer); status = SetPreallocatedBuffer(slot, buffer);
break; break;
@ -867,7 +858,7 @@ void BufferQueueProducer::Transact(HLERequestContext& ctx, TransactionId code, u
status = RequestBuffer(slot, &buf); status = RequestBuffer(slot, &buf);
parcel_out.WriteFlattenedObject(buf); parcel_out.WriteFlattenedObject<NvGraphicBuffer>(buf.get());
break; break;
} }
case TransactionId::QueueBuffer: { case TransactionId::QueueBuffer: {

@ -38,6 +38,7 @@ namespace Service::android {
class BufferQueueCore; class BufferQueueCore;
class IProducerListener; class IProducerListener;
struct NvGraphicBuffer;
class BufferQueueProducer final : public IBinder { class BufferQueueProducer final : public IBinder {
public: public:
@ -65,7 +66,7 @@ public:
bool producer_controlled_by_app, QueueBufferOutput* output); bool producer_controlled_by_app, QueueBufferOutput* output);
Status Disconnect(NativeWindowApi api); Status Disconnect(NativeWindowApi api);
Status SetPreallocatedBuffer(s32 slot, const std::shared_ptr<GraphicBuffer>& buffer); Status SetPreallocatedBuffer(s32 slot, const std::shared_ptr<NvGraphicBuffer>& buffer);
private: private:
BufferQueueProducer(const BufferQueueProducer&) = delete; BufferQueueProducer(const BufferQueueProducer&) = delete;

@ -13,7 +13,7 @@
namespace Service::android { namespace Service::android {
struct GraphicBuffer; class GraphicBuffer;
enum class BufferState : u32 { enum class BufferState : u32 {
Free = 0, Free = 0,

@ -179,7 +179,7 @@ constexpr SharedMemoryPoolLayout SharedBufferPoolLayout = [] {
}(); }();
void MakeGraphicBuffer(android::BufferQueueProducer& producer, u32 slot, u32 handle) { void MakeGraphicBuffer(android::BufferQueueProducer& producer, u32 slot, u32 handle) {
auto buffer = std::make_shared<android::GraphicBuffer>(); auto buffer = std::make_shared<android::NvGraphicBuffer>();
buffer->width = SharedBufferWidth; buffer->width = SharedBufferWidth;
buffer->height = SharedBufferHeight; buffer->height = SharedBufferHeight;
buffer->stride = SharedBufferBlockLinearStride; buffer->stride = SharedBufferBlockLinearStride;

@ -19,7 +19,7 @@ enum class Status : s32 {
Busy = -16, Busy = -16,
NoInit = -19, NoInit = -19,
BadValue = -22, BadValue = -22,
InvalidOperation = -37, InvalidOperation = -38,
BufferNeedsReallocation = 1, BufferNeedsReallocation = 1,
ReleaseAllBuffers = 2, ReleaseAllBuffers = 2,
}; };

@ -0,0 +1,34 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "core/hle/service/nvdrv/core/nvmap.h"
#include "core/hle/service/nvnflinger/ui/graphic_buffer.h"
namespace Service::android {
static NvGraphicBuffer GetBuffer(std::shared_ptr<NvGraphicBuffer>& buffer) {
if (buffer) {
return *buffer;
} else {
return {};
}
}
GraphicBuffer::GraphicBuffer(u32 width_, u32 height_, PixelFormat format_, u32 usage_)
: NvGraphicBuffer(width_, height_, format_, usage_), m_nvmap(nullptr) {}
GraphicBuffer::GraphicBuffer(Service::Nvidia::NvCore::NvMap& nvmap,
std::shared_ptr<NvGraphicBuffer> buffer)
: NvGraphicBuffer(GetBuffer(buffer)), m_nvmap(std::addressof(nvmap)) {
if (this->BufferId() > 0) {
m_nvmap->DuplicateHandle(this->BufferId(), true);
}
}
GraphicBuffer::~GraphicBuffer() {
if (m_nvmap != nullptr && this->BufferId() > 0) {
m_nvmap->FreeHandle(this->BufferId(), true);
}
}
} // namespace Service::android

@ -6,16 +6,22 @@
#pragma once #pragma once
#include <memory>
#include "common/common_funcs.h" #include "common/common_funcs.h"
#include "common/common_types.h" #include "common/common_types.h"
#include "core/hle/service/nvnflinger/pixel_format.h" #include "core/hle/service/nvnflinger/pixel_format.h"
namespace Service::Nvidia::NvCore {
class NvMap;
} // namespace Service::Nvidia::NvCore
namespace Service::android { namespace Service::android {
struct GraphicBuffer final { struct NvGraphicBuffer {
constexpr GraphicBuffer() = default; constexpr NvGraphicBuffer() = default;
constexpr GraphicBuffer(u32 width_, u32 height_, PixelFormat format_, u32 usage_) constexpr NvGraphicBuffer(u32 width_, u32 height_, PixelFormat format_, u32 usage_)
: width{static_cast<s32>(width_)}, height{static_cast<s32>(height_)}, format{format_}, : width{static_cast<s32>(width_)}, height{static_cast<s32>(height_)}, format{format_},
usage{static_cast<s32>(usage_)} {} usage{static_cast<s32>(usage_)} {}
@ -93,6 +99,17 @@ struct GraphicBuffer final {
u32 offset{}; u32 offset{};
INSERT_PADDING_WORDS(60); INSERT_PADDING_WORDS(60);
}; };
static_assert(sizeof(GraphicBuffer) == 0x16C, "GraphicBuffer has wrong size"); static_assert(sizeof(NvGraphicBuffer) == 0x16C, "NvGraphicBuffer has wrong size");
class GraphicBuffer final : public NvGraphicBuffer {
public:
explicit GraphicBuffer(u32 width, u32 height, PixelFormat format, u32 usage);
explicit GraphicBuffer(Service::Nvidia::NvCore::NvMap& nvmap,
std::shared_ptr<NvGraphicBuffer> buffer);
~GraphicBuffer();
private:
Service::Nvidia::NvCore::NvMap* m_nvmap{};
};
} // namespace Service::android } // namespace Service::android

@ -35,7 +35,7 @@ static BufferQueue CreateBufferQueue(KernelHelpers::ServiceContext& service_cont
return { return {
buffer_queue_core, buffer_queue_core,
std::make_unique<android::BufferQueueProducer>(service_context, buffer_queue_core, nvmap), std::make_unique<android::BufferQueueProducer>(service_context, buffer_queue_core, nvmap),
std::make_unique<android::BufferQueueConsumer>(buffer_queue_core, nvmap)}; std::make_unique<android::BufferQueueConsumer>(buffer_queue_core)};
} }
Display::Display(u64 id, std::string name_, Display::Display(u64 id, std::string name_,