mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-10-10 06:56:49 +00:00
find?
This commit is contained in:
@@ -211,6 +211,10 @@ constexpr u32 GetCaptureSlot(CaptureKind kind) {
|
|||||||
static_assert(static_cast<u32>(CaptureKind::CallerApplet) + 1 == SharedBufferNumCaptureSlots,
|
static_assert(static_cast<u32>(CaptureKind::CallerApplet) + 1 == SharedBufferNumCaptureSlots,
|
||||||
"Capture slot count does not match CaptureKind");
|
"Capture slot count does not match CaptureKind");
|
||||||
|
|
||||||
|
constexpr u32 GetPresentationSlot(u32 slot_base, u32 index) {
|
||||||
|
return SharedBufferNumCaptureSlots + slot_base + index;
|
||||||
|
}
|
||||||
|
|
||||||
constexpr u32 ColorOpaqueBlackRgba32 = 0xFF000000;
|
constexpr u32 ColorOpaqueBlackRgba32 = 0xFF000000;
|
||||||
|
|
||||||
template <typename F>
|
template <typename F>
|
||||||
@@ -246,7 +250,7 @@ void ForEachPoolChunk(Core::System& system, Kernel::KPageGroup& page_group, u64
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MakeGraphicBuffer(android::BufferQueueProducer& producer, u32 slot, u32 handle) {
|
void MakeGraphicBuffer(android::BufferQueueProducer& producer, u32 producer_slot, u32 pool_slot, u32 handle) {
|
||||||
auto buffer = std::make_shared<android::NvGraphicBuffer>();
|
auto buffer = std::make_shared<android::NvGraphicBuffer>();
|
||||||
buffer->width = SharedBufferWidth;
|
buffer->width = SharedBufferWidth;
|
||||||
buffer->height = SharedBufferHeight;
|
buffer->height = SharedBufferHeight;
|
||||||
@@ -254,8 +258,8 @@ void MakeGraphicBuffer(android::BufferQueueProducer& producer, u32 slot, u32 han
|
|||||||
buffer->format = SharedBufferBlockLinearFormat;
|
buffer->format = SharedBufferBlockLinearFormat;
|
||||||
buffer->external_format = SharedBufferBlockLinearFormat;
|
buffer->external_format = SharedBufferBlockLinearFormat;
|
||||||
buffer->buffer_id = handle;
|
buffer->buffer_id = handle;
|
||||||
buffer->offset = slot * SharedBufferSlotSize;
|
buffer->offset = pool_slot * SharedBufferSlotSize;
|
||||||
ASSERT(producer.SetPreallocatedBuffer(slot, buffer) == android::Status::NoError);
|
ASSERT(producer.SetPreallocatedBuffer(producer_slot, buffer) == android::Status::NoError);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
@@ -269,19 +273,20 @@ SharedBufferManager::~SharedBufferManager() = default;
|
|||||||
Result SharedBufferManager::CreateSession(Kernel::KProcess* owner_process, u64* out_buffer_id,
|
Result SharedBufferManager::CreateSession(Kernel::KProcess* owner_process, u64* out_buffer_id,
|
||||||
u64* out_layer_handle, u64 display_id,
|
u64* out_layer_handle, u64 display_id,
|
||||||
bool enable_blending) {
|
bool enable_blending) {
|
||||||
std::scoped_lock lk{m_guard};
|
{
|
||||||
|
std::scoped_lock lk{m_guard};
|
||||||
|
|
||||||
// Ensure we haven't already created.
|
// Ensure we haven't already created.
|
||||||
const u64 aruid = owner_process->GetProcessId();
|
const u64 aruid = owner_process->GetProcessId();
|
||||||
R_UNLESS(!m_sessions.contains(aruid), VI::ResultPermissionDenied);
|
R_UNLESS(!m_sessions.contains(aruid), VI::ResultPermissionDenied);
|
||||||
|
|
||||||
// Allocate memory for the shared buffer if needed.
|
// Allocate memory for the shared buffer if needed.
|
||||||
if (!m_buffer_page_group) {
|
if (!m_buffer_page_group) {
|
||||||
R_TRY(AllocateSharedBufferMemory(std::addressof(m_buffer_page_group), m_system,
|
R_TRY(AllocateSharedBufferMemory(std::addressof(m_buffer_page_group), m_system,
|
||||||
SharedBufferSize));
|
SharedBufferSize));
|
||||||
|
|
||||||
// Record buffer id.
|
// Record buffer id.
|
||||||
m_buffer_id = m_next_buffer_id++;
|
m_buffer_id = m_next_buffer_id++;
|
||||||
|
|
||||||
// Record display id.
|
// Record display id.
|
||||||
m_display_id = display_id;
|
m_display_id = display_id;
|
||||||
@@ -304,32 +309,32 @@ Result SharedBufferManager::CreateSession(Kernel::KProcess* owner_process, u64*
|
|||||||
auto [it, was_emplaced] = m_sessions.emplace(aruid, SharedBufferSession{});
|
auto [it, was_emplaced] = m_sessions.emplace(aruid, SharedBufferSession{});
|
||||||
auto& session = it->second;
|
auto& session = it->second;
|
||||||
|
|
||||||
auto& container = m_nvdrv->GetContainer();
|
auto& container = m_nvdrv->GetContainer();
|
||||||
session.session_id = container.OpenSession(owner_process);
|
session.session_id = container.OpenSession(owner_process);
|
||||||
session.nvmap_fd = m_nvdrv->Open("/dev/nvmap", session.session_id);
|
session.nvmap_fd = m_nvdrv->Open("/dev/nvmap", session.session_id);
|
||||||
|
|
||||||
// Create an nvmap handle for the buffer and assign the memory to it.
|
// Create an nvmap handle for the buffer and assign the memory to it.
|
||||||
R_TRY(AllocateHandleForBuffer(std::addressof(session.buffer_nvmap_handle), *m_nvdrv,
|
R_TRY(AllocateHandleForBuffer(std::addressof(session.buffer_nvmap_handle), *m_nvdrv,
|
||||||
session.nvmap_fd, map_address, SharedBufferSize));
|
session.nvmap_fd, map_address, SharedBufferSize));
|
||||||
|
|
||||||
// Create and open a layer for the display.
|
// Create and open a layer for the display.
|
||||||
s32 producer_binder_id;
|
s32 producer_binder_id;
|
||||||
R_TRY(m_container.CreateStrayLayer(std::addressof(producer_binder_id),
|
R_TRY(m_container.CreateStrayLayer(std::addressof(producer_binder_id),
|
||||||
std::addressof(session.layer_id), display_id));
|
std::addressof(session.layer_id), display_id));
|
||||||
|
|
||||||
// Configure blending and z-index
|
// Configure blending and z-index
|
||||||
R_ASSERT(m_container.SetLayerBlending(session.layer_id, enable_blending));
|
R_ASSERT(m_container.SetLayerBlending(session.layer_id, enable_blending));
|
||||||
|
|
||||||
// Get the producer and set preallocated buffers.
|
// Get the producer and set preallocated buffers.
|
||||||
std::shared_ptr<android::BufferQueueProducer> producer;
|
std::shared_ptr<android::BufferQueueProducer> producer;
|
||||||
R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), session.layer_id));
|
R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), session.layer_id));
|
||||||
MakeGraphicBuffer(*producer, 0, session.buffer_nvmap_handle);
|
for (u32 i = 0; i < SharedBufferSlotsPerSession; i++)
|
||||||
MakeGraphicBuffer(*producer, 1, session.buffer_nvmap_handle);
|
MakeGraphicBuffer(*producer, i, GetPresentationSlot(session.presentation_slot_base, i), session.buffer_nvmap_handle);
|
||||||
|
|
||||||
// Assign outputs.
|
|
||||||
*out_buffer_id = m_buffer_id;
|
|
||||||
*out_layer_handle = session.layer_id;
|
|
||||||
|
|
||||||
|
// Assign outputs.
|
||||||
|
*out_buffer_id = m_buffer_id;
|
||||||
|
*out_layer_handle = session.layer_id;
|
||||||
|
}
|
||||||
// We succeeded.
|
// We succeeded.
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
@@ -398,14 +403,51 @@ Result SharedBufferManager::AcquireSharedFrameBuffer(android::Fence* out_fence,
|
|||||||
SharedBufferBlockLinearFormat, 0) == android::Status::NoError,
|
SharedBufferBlockLinearFormat, 0) == android::Status::NoError,
|
||||||
VI::ResultOperationFailed);
|
VI::ResultOperationFailed);
|
||||||
|
|
||||||
// Assign remaining outputs.
|
out_slot_indexes.fill(-1);
|
||||||
*out_target_slot = slot;
|
|
||||||
out_slot_indexes = {0, 1, -1, -1};
|
{
|
||||||
|
std::scoped_lock lk{m_guard};
|
||||||
|
const auto* const session = this->FindSessionByLayerIdLocked(layer_id);
|
||||||
|
if (session == nullptr) {
|
||||||
|
producer->CancelBuffer(slot, *out_fence);
|
||||||
|
// LOG_DEBUG(Service_VI, "No Session found");
|
||||||
|
R_THROW(VI::ResultNotFound);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 i = 0; i < SharedBufferSlotsPerSession; i++)
|
||||||
|
out_slot_indexes[i] =
|
||||||
|
static_cast<s32>(GetPresentationSlot(session->presentation_slot_base, i));
|
||||||
|
|
||||||
|
*out_target_slot = static_cast<s64>(
|
||||||
|
GetPresentationSlot(session->presentation_slot_base, static_cast<u32>(slot)));
|
||||||
|
}
|
||||||
|
|
||||||
// We succeeded.
|
// We succeeded.
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result SharedBufferManager::GetProducerSlotLocked(s32* out_producer_slot, u64 layer_id,
|
||||||
|
s64 pool_slot) const {
|
||||||
|
const auto* const session = this->FindSessionByLayerIdLocked(layer_id);
|
||||||
|
R_UNLESS(session != nullptr, VI::ResultNotFound);
|
||||||
|
|
||||||
|
const s64 base = GetPresentationSlot(session->presentation_slot_base, 0);
|
||||||
|
const s64 producer_slot = pool_slot - base;
|
||||||
|
R_UNLESS(producer_slot >= 0 && producer_slot < SharedBufferSlotsPerSession,
|
||||||
|
VI::ResultOperationFailed);
|
||||||
|
|
||||||
|
*out_producer_slot = static_cast<s32>(producer_slot);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
const SharedBufferSession* SharedBufferManager::FindSessionByLayerIdLocked(u64 layer_id) const {
|
||||||
|
for (const auto& [aruid, session] : m_sessions)
|
||||||
|
if (session.layer_id == layer_id)
|
||||||
|
return std::addressof(session);
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
Result SharedBufferManager::PresentSharedFrameBuffer(android::Fence fence,
|
Result SharedBufferManager::PresentSharedFrameBuffer(android::Fence fence,
|
||||||
Common::Rectangle<s32> crop_region,
|
Common::Rectangle<s32> crop_region,
|
||||||
u32 transform, s32 swap_interval, u64 layer_id,
|
u32 transform, s32 swap_interval, u64 layer_id,
|
||||||
@@ -414,14 +456,20 @@ Result SharedBufferManager::PresentSharedFrameBuffer(android::Fence fence,
|
|||||||
std::shared_ptr<android::BufferQueueProducer> producer;
|
std::shared_ptr<android::BufferQueueProducer> producer;
|
||||||
R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), layer_id));
|
R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), layer_id));
|
||||||
|
|
||||||
|
s32 producer_slot;
|
||||||
|
{
|
||||||
|
std::scoped_lock lk{m_guard};
|
||||||
|
R_TRY(this->GetProducerSlotLocked(std::addressof(producer_slot), layer_id, slot));
|
||||||
|
}
|
||||||
|
|
||||||
// Request to queue the buffer.
|
// Request to queue the buffer.
|
||||||
std::shared_ptr<android::GraphicBuffer> buffer;
|
std::shared_ptr<android::GraphicBuffer> buffer;
|
||||||
R_UNLESS(producer->RequestBuffer(static_cast<s32>(slot), std::addressof(buffer)) ==
|
R_UNLESS(producer->RequestBuffer(producer_slot, std::addressof(buffer)) ==
|
||||||
android::Status::NoError,
|
android::Status::NoError,
|
||||||
VI::ResultOperationFailed);
|
VI::ResultOperationFailed);
|
||||||
|
|
||||||
ON_RESULT_FAILURE {
|
ON_RESULT_FAILURE {
|
||||||
producer->CancelBuffer(static_cast<s32>(slot), fence);
|
producer->CancelBuffer(producer_slot, fence);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Queue the buffer to the producer.
|
// Queue the buffer to the producer.
|
||||||
@@ -431,12 +479,10 @@ Result SharedBufferManager::PresentSharedFrameBuffer(android::Fence fence,
|
|||||||
input.fence = fence;
|
input.fence = fence;
|
||||||
input.transform = static_cast<android::NativeWindowTransform>(transform);
|
input.transform = static_cast<android::NativeWindowTransform>(transform);
|
||||||
input.swap_interval = swap_interval;
|
input.swap_interval = swap_interval;
|
||||||
R_UNLESS(producer->QueueBuffer(static_cast<s32>(slot), input, std::addressof(output)) ==
|
R_UNLESS(producer->QueueBuffer(producer_slot, input, std::addressof(output)) ==
|
||||||
android::Status::NoError,
|
android::Status::NoError,
|
||||||
VI::ResultOperationFailed);
|
VI::ResultOperationFailed);
|
||||||
|
|
||||||
(void)m_container.SetLayerZIndex(layer_id, 100000);
|
|
||||||
|
|
||||||
// We succeeded.
|
// We succeeded.
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
@@ -446,8 +492,14 @@ Result SharedBufferManager::CancelSharedFrameBuffer(u64 layer_id, s64 slot) {
|
|||||||
std::shared_ptr<android::BufferQueueProducer> producer;
|
std::shared_ptr<android::BufferQueueProducer> producer;
|
||||||
R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), layer_id));
|
R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), layer_id));
|
||||||
|
|
||||||
|
s32 producer_slot;
|
||||||
|
{
|
||||||
|
std::scoped_lock lk{m_guard};
|
||||||
|
R_TRY(this->GetProducerSlotLocked(std::addressof(producer_slot), layer_id, slot));
|
||||||
|
}
|
||||||
|
|
||||||
// Cancel.
|
// Cancel.
|
||||||
producer->CancelBuffer(static_cast<s32>(slot), android::Fence::NoFence());
|
producer->CancelBuffer(producer_slot, android::Fence::NoFence());
|
||||||
|
|
||||||
// We succeeded.
|
// We succeeded.
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
|
|||||||
@@ -78,6 +78,11 @@ public:
|
|||||||
Result ClearAppletCaptureBuffer(s32 layer_index, u32 color);
|
Result ClearAppletCaptureBuffer(s32 layer_index, u32 color);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
const SharedBufferSession* FindSessionByLayerIdLocked(u64 layer_id) const;
|
||||||
|
|
||||||
|
/// Converts a pool slot index, which is what the guest works in, back to the buffer queues slot index
|
||||||
|
Result GetProducerSlotLocked(s32* out_producer_slot, u64 layer_id, s64 pool_slot) const;
|
||||||
|
|
||||||
u64 m_next_buffer_id = 1;
|
u64 m_next_buffer_id = 1;
|
||||||
u64 m_display_id = 0;
|
u64 m_display_id = 0;
|
||||||
u64 m_buffer_id = 0;
|
u64 m_buffer_id = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user