From 2f5ef90bca0bf6c3b75cc4142b190b15df2c7085 Mon Sep 17 00:00:00 2001 From: PavelBARABANOV Date: Sat, 5 Sep 2026 04:25:24 +0300 Subject: [PATCH] for convenience --- .../hle/service/am/display_layer_manager.cpp | 53 +-- .../hle/service/am/display_layer_manager.h | 10 +- .../service/am/service/display_controller.cpp | 27 +- .../hle/service/vi/shared_buffer_manager.cpp | 317 +++++------------- .../hle/service/vi/shared_buffer_manager.h | 17 +- 5 files changed, 104 insertions(+), 320 deletions(-) diff --git a/src/core/hle/service/am/display_layer_manager.cpp b/src/core/hle/service/am/display_layer_manager.cpp index 8f1e1b5f2e..6789629310 100644 --- a/src/core/hle/service/am/display_layer_manager.cpp +++ b/src/core/hle/service/am/display_layer_manager.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -6,7 +6,6 @@ #include "core/core.h" #include "core/hle/service/am/display_layer_manager.h" -#include "core/hle/service/nvnflinger/hwc_layer.h" #include "core/hle/service/sm/sm.h" #include "core/hle/service/vi/application_display_service.h" #include "core/hle/service/vi/container.h" @@ -34,7 +33,6 @@ void DisplayLayerManager::Initialize(Core::System& system, Kernel::KProcess* pro m_system_shared_buffer_id = 0; m_system_shared_layer_id = 0; m_applet_id = applet_id; - m_library_applet_mode = mode; m_buffer_sharing_enabled = false; m_blending_enabled = mode == LibraryAppletMode::PartialForeground || mode == LibraryAppletMode::PartialForegroundIndirectDisplay; @@ -74,16 +72,14 @@ Result DisplayLayerManager::CreateManagedDisplayLayer(u64* out_layer_id) { out_layer_id, 0, display_id, Service::AppletResourceUserId{m_process->GetProcessId()})); m_manager_display_service->SetLayerVisibility(m_visible, *out_layer_id); - (void)m_display_service->GetContainer()->SetLayerStackMask(*out_layer_id, - this->GetLayerStackMask()); if (m_applet_id != AppletId::Application) { (void)m_manager_display_service->SetLayerBlending(m_blending_enabled, *out_layer_id); if (m_applet_id == AppletId::OverlayDisplay) { - (void)m_manager_display_service->SetLayerZIndex(Overlay, *out_layer_id); + (void)m_manager_display_service->SetLayerZIndex(-1, *out_layer_id); (void)m_display_service->GetContainer()->SetLayerIsOverlay(*out_layer_id, true); } else { - (void)m_manager_display_service->SetLayerZIndex(Foreground, *out_layer_id); + (void)m_manager_display_service->SetLayerZIndex(1, *out_layer_id); } } @@ -126,8 +122,6 @@ Result DisplayLayerManager::IsSystemBufferSharingEnabled() { // Ensure the overlay layer is visible m_manager_display_service->SetLayerVisibility(m_visible, m_system_shared_layer_id); - (void)m_display_service->GetContainer()->SetLayerStackMask(m_system_shared_layer_id, - this->GetLayerStackMask()); m_manager_display_service->SetLayerBlending(m_blending_enabled, m_system_shared_layer_id); s32 initial_z = 1; if (m_applet_id == AppletId::OverlayDisplay) { @@ -148,36 +142,6 @@ Result DisplayLayerManager::GetSystemSharedLayerHandle(u64* out_system_shared_bu R_SUCCEED(); } -u32 DisplayLayerManager::GetLayerStackMask() const { - using Nvnflinger::LayerStackBit; - using Nvnflinger::LayerStackId; - - constexpr u32 Displayed = LayerStackBit(LayerStackId::Default); - constexpr u32 Screenshot = LayerStackBit(LayerStackId::Screenshot); - constexpr u32 Recording = LayerStackBit(LayerStackId::Recording); - constexpr u32 LastFrame = LayerStackBit(LayerStackId::LastFrame); - constexpr u32 Debug = LayerStackBit(LayerStackId::ApplicationForDebug); - - switch (m_applet_id) { - case AppletId::Application: - return Displayed | Screenshot | Recording | LastFrame | Debug; - case AppletId::OverlayDisplay: - return Displayed; - case AppletId::QLaunch: - return Displayed; - default: - break; - } - - switch (m_library_applet_mode) { - case LibraryAppletMode::AllForeground: - case LibraryAppletMode::AllForegroundInitiallyHidden: - return Displayed | Screenshot | LastFrame; - default: - return Displayed | Screenshot; - } -} - void DisplayLayerManager::SetWindowVisibility(bool visible) { if (m_visible == visible) { return; @@ -221,17 +185,10 @@ void DisplayLayerManager::SetOverlayZIndex(s32 z_index) { } Result DisplayLayerManager::WriteAppletCaptureBuffer(bool* out_was_written, - s32* out_fbshare_layer_index, - VI::CaptureKind kind) { + s32* out_fbshare_layer_index) { R_UNLESS(m_buffer_sharing_enabled, VI::ResultPermissionDenied); R_RETURN(m_display_service->GetContainer()->GetSharedBufferManager()->WriteAppletCaptureBuffer( - out_was_written, out_fbshare_layer_index, kind)); -} - -Result DisplayLayerManager::ClearAppletCaptureBuffer(s32 fbshare_layer_index, u32 color) { - R_UNLESS(m_buffer_sharing_enabled, VI::ResultPermissionDenied); - R_RETURN(m_display_service->GetContainer()->GetSharedBufferManager()->ClearAppletCaptureBuffer( - fbshare_layer_index, color)); + out_was_written, out_fbshare_layer_index)); } } // namespace Service::AM diff --git a/src/core/hle/service/am/display_layer_manager.h b/src/core/hle/service/am/display_layer_manager.h index e9f48476d2..423eb432fa 100644 --- a/src/core/hle/service/am/display_layer_manager.h +++ b/src/core/hle/service/am/display_layer_manager.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -23,7 +23,6 @@ class KProcess; namespace Service::VI { class IApplicationDisplayService; class IManagerDisplayService; -enum class CaptureKind : u32; } // namespace Service::VI namespace Service::AM { @@ -49,13 +48,9 @@ public: void SetOverlayZIndex(s32 z_index); - Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_fbshare_layer_index, - VI::CaptureKind kind); - Result ClearAppletCaptureBuffer(s32 fbshare_layer_index, u32 color); + Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_fbshare_layer_index); private: - u32 GetLayerStackMask() const; - Kernel::KProcess* m_process{}; std::shared_ptr m_display_service{}; std::shared_ptr m_manager_display_service{}; @@ -64,7 +59,6 @@ private: u64 m_system_shared_buffer_id{}; u64 m_system_shared_layer_id{}; AppletId m_applet_id{}; - LibraryAppletMode m_library_applet_mode{}; bool m_buffer_sharing_enabled{}; bool m_blending_enabled{}; bool m_visible{true}; diff --git a/src/core/hle/service/am/service/display_controller.cpp b/src/core/hle/service/am/service/display_controller.cpp index 8f87327b17..a02f012a92 100644 --- a/src/core/hle/service/am/service/display_controller.cpp +++ b/src/core/hle/service/am/service/display_controller.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project @@ -8,7 +8,6 @@ #include "core/hle/service/am/applet.h" #include "core/hle/service/am/service/display_controller.h" #include "core/hle/service/cmif_serialization.h" -#include "core/hle/service/vi/shared_buffer_manager.h" namespace Service::AM { @@ -72,16 +71,16 @@ Result IDisplayController::TakeScreenShotOfOwnLayer(bool unknown0, s32 fbshare_l } Result IDisplayController::ClearCaptureBuffer(bool unknown0, s32 fbshare_layer_index, u32 color) { - LOG_DEBUG(Service_AM, "called, unknown0={} fbshare_layer_index={} color={:#x}", unknown0, - fbshare_layer_index, color); - R_RETURN(applet->display_layer_manager.ClearAppletCaptureBuffer(fbshare_layer_index, color)); + LOG_WARNING(Service_AM, "(STUBBED) called, unknown0={} fbshare_layer_index={} color={:#x}", + unknown0, fbshare_layer_index, color); + R_SUCCEED(); } Result IDisplayController::AcquireLastForegroundCaptureSharedBuffer( Out out_was_written, Out out_fbshare_layer_index) { - LOG_DEBUG(Service_AM, "called"); - R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer( - out_was_written, out_fbshare_layer_index, VI::CaptureKind::LastForeground)); + LOG_WARNING(Service_AM, "(STUBBED) called"); + R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer(out_was_written, + out_fbshare_layer_index)); } Result IDisplayController::ReleaseLastForegroundCaptureSharedBuffer() { @@ -91,9 +90,9 @@ Result IDisplayController::ReleaseLastForegroundCaptureSharedBuffer() { Result IDisplayController::AcquireCallerAppletCaptureSharedBuffer( Out out_was_written, Out out_fbshare_layer_index) { - LOG_DEBUG(Service_AM, "called"); - R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer( - out_was_written, out_fbshare_layer_index, VI::CaptureKind::CallerApplet)); + LOG_WARNING(Service_AM, "(STUBBED) called"); + R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer(out_was_written, + out_fbshare_layer_index)); } Result IDisplayController::ReleaseCallerAppletCaptureSharedBuffer() { @@ -103,9 +102,9 @@ Result IDisplayController::ReleaseCallerAppletCaptureSharedBuffer() { Result IDisplayController::AcquireLastApplicationCaptureSharedBuffer( Out out_was_written, Out out_fbshare_layer_index) { - LOG_DEBUG(Service_AM, "called"); - R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer( - out_was_written, out_fbshare_layer_index, VI::CaptureKind::LastApplication)); + LOG_WARNING(Service_AM, "(STUBBED) called"); + R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer(out_was_written, + out_fbshare_layer_index)); } Result IDisplayController::ReleaseLastApplicationCaptureSharedBuffer() { diff --git a/src/core/hle/service/vi/shared_buffer_manager.cpp b/src/core/hle/service/vi/shared_buffer_manager.cpp index 483c1f71ba..21e42e2094 100644 --- a/src/core/hle/service/vi/shared_buffer_manager.cpp +++ b/src/core/hle/service/vi/shared_buffer_manager.cpp @@ -4,15 +4,9 @@ // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later -#include -#include #include -#include "common/assert.h" -#include "common/logging.h" -#include "common/scratch_buffer.h" #include "core/core.h" -#include "core/hle/kernel/k_page_group.h" #include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_system_resource.h" #include "core/hle/service/nvdrv/devices/nvmap.h" @@ -53,7 +47,7 @@ Result AllocateSharedBufferMemory(std::unique_ptr* out_page_ u32* end = system.DeviceMemory().GetPointer(block.GetAddress() + block.GetSize()); for (; start < end; start++) { - *start = 0x00000000; + *start = 0xFF0000FF; } } @@ -174,14 +168,7 @@ constexpr u32 SharedBufferBlockLinearWidth = 1280; constexpr u32 SharedBufferBlockLinearHeight = 768; constexpr u32 SharedBufferBlockLinearStride = SharedBufferBlockLinearWidth * SharedBufferBlockLinearBpp; - -constexpr u32 SharedBufferNumCaptureSlots = 3; -constexpr u32 SharedBufferSlotsPerSession = 2; -constexpr u32 SharedBufferMaxSessions = 2; - -constexpr u32 SharedBufferNumSlots = - SharedBufferNumCaptureSlots + SharedBufferSlotsPerSession * SharedBufferMaxSessions; -static_assert(SharedBufferNumSlots <= 16, "Shared buffer pool exceeds the maximum texture count"); +constexpr u32 SharedBufferNumSlots = 7; constexpr u32 SharedBufferWidth = 1280; constexpr u32 SharedBufferHeight = 720; @@ -205,52 +192,7 @@ constexpr SharedMemoryPoolLayout SharedBufferPoolLayout = [] { return layout; }(); -constexpr u32 GetCaptureSlot(CaptureKind kind) { - return static_cast(kind); -} -static_assert(static_cast(CaptureKind::CallerApplet) + 1 == SharedBufferNumCaptureSlots, - "Capture slot count does not match CaptureKind"); - -constexpr u32 GetPresentationSlot(u32 slot_base, u32 index) { - return SharedBufferNumCaptureSlots + slot_base + index; -} - -constexpr u32 ColorOpaqueBlackRgba32 = 0xFF000000; - -template -void ForEachPoolChunk(Core::System& system, Kernel::KPageGroup& page_group, u64 offset, u64 size, - F&& writer) { - Common::ScratchBuffer scratch; - const u64 range_end = offset + size; - u64 pool_pos = 0; - - for (auto& block : page_group) { - const u64 block_begin = pool_pos; - const u64 block_end = block_begin + block.GetSize(); - pool_pos = block_end; - - if (block_end <= offset) { - continue; - } - if (block_begin >= range_end) { - break; - } - - const u64 chunk_begin = (std::max)(block_begin, offset); - const u64 chunk_end = (std::min)(block_end, range_end); - const u64 chunk_size = chunk_end - chunk_begin; - - u8* const dst = - system.DeviceMemory().GetPointer(block.GetAddress()) + (chunk_begin - block_begin); - - writer(dst, chunk_begin - offset, chunk_size); - - system.GPU().Host1x().MemoryManager().ApplyOpOnPointer( - dst, scratch, [&](DAddr addr) { system.GPU().InvalidateRegion(addr, chunk_size); }); - } -} - -void MakeGraphicBuffer(android::BufferQueueProducer& producer, u32 producer_slot, u32 pool_slot, u32 handle) { +void MakeGraphicBuffer(android::BufferQueueProducer& producer, u32 slot, u32 handle) { auto buffer = std::make_shared(); buffer->width = SharedBufferWidth; buffer->height = SharedBufferHeight; @@ -258,8 +200,8 @@ void MakeGraphicBuffer(android::BufferQueueProducer& producer, u32 producer_slot buffer->format = SharedBufferBlockLinearFormat; buffer->external_format = SharedBufferBlockLinearFormat; buffer->buffer_id = handle; - buffer->offset = pool_slot * SharedBufferSlotSize; - ASSERT(producer.SetPreallocatedBuffer(producer_slot, buffer) == android::Status::NoError); + buffer->offset = slot * SharedBufferSlotSize; + ASSERT(producer.SetPreallocatedBuffer(slot, buffer) == android::Status::NoError); } } // namespace @@ -273,91 +215,59 @@ SharedBufferManager::~SharedBufferManager() = default; Result SharedBufferManager::CreateSession(Kernel::KProcess* owner_process, u64* out_buffer_id, u64* out_layer_handle, u64 display_id, bool enable_blending) { - { - std::scoped_lock lk{m_guard}; + std::scoped_lock lk{m_guard}; - // Ensure we haven't already created. - const u64 aruid = owner_process->GetProcessId(); - R_UNLESS(!m_sessions.contains(aruid), VI::ResultPermissionDenied); + // Ensure we haven't already created. + const u64 aruid = owner_process->GetProcessId(); + R_UNLESS(!m_sessions.contains(aruid), VI::ResultPermissionDenied); - // Allocate memory for the shared buffer if needed. - if (!m_buffer_page_group) { - R_TRY(AllocateSharedBufferMemory(std::addressof(m_buffer_page_group), m_system, - SharedBufferSize)); + // Allocate memory for the shared buffer if needed. + if (!m_buffer_page_group) { + R_TRY(AllocateSharedBufferMemory(std::addressof(m_buffer_page_group), m_system, + SharedBufferSize)); - // Record buffer id. - m_buffer_id = m_next_buffer_id++; + // Record buffer id. + m_buffer_id = m_next_buffer_id++; - // Record display id. - m_display_id = display_id; - - for (u32 slot = 0; slot < SharedBufferNumCaptureSlots; slot++) { - ForEachPoolChunk(m_system, *m_buffer_page_group, u64{slot} * SharedBufferSlotSize, - SharedBufferSlotSize, [](u8* dst, u64, u64 length) { - std::fill_n(reinterpret_cast(dst), length / sizeof(u32), - ColorOpaqueBlackRgba32); - }); - } - } - - // Claim a presentation slot range. - u32 slot_base = 0; - - std::array in_use{}; - for (const auto& [existing_aruid, existing] : m_sessions) { - const u32 index = existing.presentation_slot_base / SharedBufferSlotsPerSession; - - if (index < in_use.size()) - in_use[index] = true; - } - - u32 index = 0; - while (index < in_use.size() && in_use[index]) - index++; - - if (index >= in_use.size()) { - LOG_ERROR(Service_VI, "Out of shared buffer presentation slots ({} sessions)", SharedBufferMaxSessions); - R_THROW(VI::ResultOperationFailed); - } - - slot_base = index * SharedBufferSlotsPerSession; - - // Map into process. - Common::ProcessAddress map_address{}; - R_TRY(MapSharedBufferIntoProcessAddressSpace(std::addressof(map_address), m_buffer_page_group, - owner_process, m_system)); - - // Create new session. - auto [it, was_emplaced] = m_sessions.emplace(aruid, SharedBufferSession{}); - auto& session = it->second; - session.presentation_slot_base = slot_base; - - auto& container = m_nvdrv->GetContainer(); - session.session_id = container.OpenSession(owner_process); - session.nvmap_fd = m_nvdrv->Open("/dev/nvmap", session.session_id); - - // Create an nvmap handle for the buffer and assign the memory to it. - R_TRY(AllocateHandleForBuffer(std::addressof(session.buffer_nvmap_handle), *m_nvdrv, - session.nvmap_fd, map_address, SharedBufferSize)); - - // Create and open a layer for the display. - s32 producer_binder_id; - R_TRY(m_container.CreateStrayLayer(std::addressof(producer_binder_id), - std::addressof(session.layer_id), display_id)); - - // Configure blending and z-index - R_ASSERT(m_container.SetLayerBlending(session.layer_id, enable_blending)); - - // Get the producer and set preallocated buffers. - std::shared_ptr producer; - R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), session.layer_id)); - for (u32 i = 0; i < SharedBufferSlotsPerSession; i++) - 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; + // Record display id. + m_display_id = display_id; } + + // Map into process. + Common::ProcessAddress map_address{}; + R_TRY(MapSharedBufferIntoProcessAddressSpace(std::addressof(map_address), m_buffer_page_group, + owner_process, m_system)); + + // Create new session. + auto [it, was_emplaced] = m_sessions.emplace(aruid, SharedBufferSession{}); + auto& session = it->second; + + auto& container = m_nvdrv->GetContainer(); + session.session_id = container.OpenSession(owner_process); + session.nvmap_fd = m_nvdrv->Open("/dev/nvmap", session.session_id); + + // Create an nvmap handle for the buffer and assign the memory to it. + R_TRY(AllocateHandleForBuffer(std::addressof(session.buffer_nvmap_handle), *m_nvdrv, + session.nvmap_fd, map_address, SharedBufferSize)); + + // Create and open a layer for the display. + s32 producer_binder_id; + R_TRY(m_container.CreateStrayLayer(std::addressof(producer_binder_id), + std::addressof(session.layer_id), display_id)); + + // Configure blending and z-index + R_ASSERT(m_container.SetLayerBlending(session.layer_id, enable_blending)); + + // Get the producer and set preallocated buffers. + std::shared_ptr producer; + R_TRY(m_container.GetLayerProducerHandle(std::addressof(producer), session.layer_id)); + MakeGraphicBuffer(*producer, 0, session.buffer_nvmap_handle); + MakeGraphicBuffer(*producer, 1, session.buffer_nvmap_handle); + + // Assign outputs. + *out_buffer_id = m_buffer_id; + *out_layer_handle = session.layer_id; + // We succeeded. R_SUCCEED(); } @@ -426,51 +336,14 @@ Result SharedBufferManager::AcquireSharedFrameBuffer(android::Fence* out_fence, SharedBufferBlockLinearFormat, 0) == android::Status::NoError, VI::ResultOperationFailed); - out_slot_indexes.fill(-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(GetPresentationSlot(session->presentation_slot_base, i)); - - *out_target_slot = static_cast( - GetPresentationSlot(session->presentation_slot_base, static_cast(slot))); - } + // Assign remaining outputs. + *out_target_slot = slot; + out_slot_indexes = {0, 1, -1, -1}; // We succeeded. 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(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, Common::Rectangle crop_region, u32 transform, s32 swap_interval, u64 layer_id, @@ -479,20 +352,14 @@ Result SharedBufferManager::PresentSharedFrameBuffer(android::Fence fence, std::shared_ptr producer; 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. std::shared_ptr buffer; - R_UNLESS(producer->RequestBuffer(producer_slot, std::addressof(buffer)) == + R_UNLESS(producer->RequestBuffer(static_cast(slot), std::addressof(buffer)) == android::Status::NoError, VI::ResultOperationFailed); ON_RESULT_FAILURE { - producer->CancelBuffer(producer_slot, fence); + producer->CancelBuffer(static_cast(slot), fence); }; // Queue the buffer to the producer. @@ -502,10 +369,12 @@ Result SharedBufferManager::PresentSharedFrameBuffer(android::Fence fence, input.fence = fence; input.transform = static_cast(transform); input.swap_interval = swap_interval; - R_UNLESS(producer->QueueBuffer(producer_slot, input, std::addressof(output)) == + R_UNLESS(producer->QueueBuffer(static_cast(slot), input, std::addressof(output)) == android::Status::NoError, VI::ResultOperationFailed); + (void)m_container.SetLayerZIndex(layer_id, 100000); + // We succeeded. R_SUCCEED(); } @@ -515,14 +384,8 @@ Result SharedBufferManager::CancelSharedFrameBuffer(u64 layer_id, s64 slot) { std::shared_ptr producer; 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. - producer->CancelBuffer(producer_slot, android::Fence::NoFence()); + producer->CancelBuffer(static_cast(slot), android::Fence::NoFence()); // We succeeded. R_SUCCEED(); @@ -541,47 +404,31 @@ Result SharedBufferManager::GetSharedFrameBufferAcquirableEvent(Kernel::KReadabl R_SUCCEED(); } -Result SharedBufferManager::WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index, CaptureKind kind) { - std::scoped_lock lk{m_guard}; - R_UNLESS(m_buffer_page_group != nullptr, VI::ResultNotFound); +Result SharedBufferManager::WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index) { + std::vector capture_buffer(m_system.GPU().GetAppletCaptureBuffer()); + Common::ScratchBuffer scratch; - const std::vector capture = m_system.GPU().GetAppletCaptureBuffer(); - const u32 slot = GetCaptureSlot(kind); + // TODO: this could be optimized + s64 e = -1280 * 768 * 4; + for (auto& block : *m_buffer_page_group) { + u8* start = m_system.DeviceMemory().GetPointer(block.GetAddress()); + u8* end = m_system.DeviceMemory().GetPointer(block.GetAddress() + block.GetSize()); - if (capture.size() < SharedBufferSlotSize) { - //LOG_WARNING(Service_VI, "Capture buffer is {} bytes, expected at least {}; not writing", - // capture.size(), SharedBufferSlotSize); - *out_was_written = false; - *out_layer_index = static_cast(slot); - R_SUCCEED(); + for (; start < end; start++) { + *start = 0; + if (e >= 0 && e < static_cast(capture_buffer.size())) { + *start = capture_buffer[e]; + } + e++; + } + + m_system.GPU().Host1x().MemoryManager().ApplyOpOnPointer(start, scratch, [&](DAddr addr) { + m_system.GPU().InvalidateRegion(addr, end - start); + }); } - ForEachPoolChunk(m_system, *m_buffer_page_group, u64{slot} * SharedBufferSlotSize, - SharedBufferSlotSize, - [&](u8* dst, u64 src_offset, u64 length) { - std::memcpy(dst, capture.data() + src_offset, length); - }); - *out_was_written = true; - *out_layer_index = static_cast(slot); - R_SUCCEED(); -} - -Result SharedBufferManager::ClearAppletCaptureBuffer(s32 layer_index, u32 color) { - std::scoped_lock lk{m_guard}; - R_UNLESS(m_buffer_page_group != nullptr, VI::ResultNotFound); - - if (layer_index < 0 || layer_index >= static_cast(SharedBufferNumCaptureSlots)) { - LOG_WARNING(Service_VI, "Couldnt clear non-capture slot {}", layer_index); - R_SUCCEED(); - } - - ForEachPoolChunk(m_system, *m_buffer_page_group, u64{static_cast(layer_index)} * SharedBufferSlotSize, - SharedBufferSlotSize, [&](u8* dst, u64 src_offset, u64 length) { - ASSERT(src_offset % sizeof(u32) == 0 && length % sizeof(u32) == 0); - std::fill_n(reinterpret_cast(dst), length / sizeof(u32), color); - }); - + *out_layer_index = 1; R_SUCCEED(); } diff --git a/src/core/hle/service/vi/shared_buffer_manager.h b/src/core/hle/service/vi/shared_buffer_manager.h index 807db10f31..9ef6234867 100644 --- a/src/core/hle/service/vi/shared_buffer_manager.h +++ b/src/core/hle/service/vi/shared_buffer_manager.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -48,12 +48,6 @@ static_assert(sizeof(SharedMemoryPoolLayout) == 0x188, "SharedMemoryPoolLayout h struct SharedBufferSession; -enum class CaptureKind : u32 { - LastApplication, - LastForeground, - CallerApplet, -}; - class SharedBufferManager final { public: explicit SharedBufferManager(Core::System& system, Container& container, @@ -74,15 +68,9 @@ public: Result CancelSharedFrameBuffer(u64 layer_id, s64 slot); Result GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event, u64 layer_id); - Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index, CaptureKind kind); - Result ClearAppletCaptureBuffer(s32 layer_index, u32 color); + Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index); 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_display_id = 0; u64 m_buffer_id = 0; @@ -101,7 +89,6 @@ struct SharedBufferSession { Nvidia::NvCore::SessionId session_id = {}; u64 layer_id = {}; u32 buffer_nvmap_handle = 0; - u32 presentation_slot_base = 0; }; } // namespace Service::VI