mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-09-06 12:13:57 +00:00
return ClearAppletCaptureBuffer etc.
This commit is contained in:
@@ -221,10 +221,17 @@ void DisplayLayerManager::SetOverlayZIndex(s32 z_index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result DisplayLayerManager::WriteAppletCaptureBuffer(bool* out_was_written,
|
Result DisplayLayerManager::WriteAppletCaptureBuffer(bool* out_was_written,
|
||||||
s32* out_fbshare_layer_index) {
|
s32* out_fbshare_layer_index,
|
||||||
|
VI::CaptureKind kind) {
|
||||||
R_UNLESS(m_buffer_sharing_enabled, VI::ResultPermissionDenied);
|
R_UNLESS(m_buffer_sharing_enabled, VI::ResultPermissionDenied);
|
||||||
R_RETURN(m_display_service->GetContainer()->GetSharedBufferManager()->WriteAppletCaptureBuffer(
|
R_RETURN(m_display_service->GetContainer()->GetSharedBufferManager()->WriteAppletCaptureBuffer(
|
||||||
out_was_written, out_fbshare_layer_index));
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ class KProcess;
|
|||||||
namespace Service::VI {
|
namespace Service::VI {
|
||||||
class IApplicationDisplayService;
|
class IApplicationDisplayService;
|
||||||
class IManagerDisplayService;
|
class IManagerDisplayService;
|
||||||
|
enum class CaptureKind : u32;
|
||||||
} // namespace Service::VI
|
} // namespace Service::VI
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
@@ -48,7 +49,9 @@ public:
|
|||||||
|
|
||||||
void SetOverlayZIndex(s32 z_index);
|
void SetOverlayZIndex(s32 z_index);
|
||||||
|
|
||||||
Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_fbshare_layer_index);
|
Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_fbshare_layer_index,
|
||||||
|
VI::CaptureKind kind);
|
||||||
|
Result ClearAppletCaptureBuffer(s32 fbshare_layer_index, u32 color);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
u32 GetLayerStackMask() const;
|
u32 GetLayerStackMask() const;
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include "core/hle/service/am/applet.h"
|
#include "core/hle/service/am/applet.h"
|
||||||
#include "core/hle/service/am/service/display_controller.h"
|
#include "core/hle/service/am/service/display_controller.h"
|
||||||
#include "core/hle/service/cmif_serialization.h"
|
#include "core/hle/service/cmif_serialization.h"
|
||||||
|
#include "core/hle/service/vi/shared_buffer_manager.h"
|
||||||
|
|
||||||
namespace Service::AM {
|
namespace Service::AM {
|
||||||
|
|
||||||
@@ -71,16 +72,16 @@ Result IDisplayController::TakeScreenShotOfOwnLayer(bool unknown0, s32 fbshare_l
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result IDisplayController::ClearCaptureBuffer(bool unknown0, s32 fbshare_layer_index, u32 color) {
|
Result IDisplayController::ClearCaptureBuffer(bool unknown0, s32 fbshare_layer_index, u32 color) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called, unknown0={} fbshare_layer_index={} color={:#x}",
|
LOG_DEBUG(Service_AM, "called, unknown0={} fbshare_layer_index={} color={:#x}", unknown0,
|
||||||
unknown0, fbshare_layer_index, color);
|
fbshare_layer_index, color);
|
||||||
R_SUCCEED();
|
R_RETURN(applet->display_layer_manager.ClearAppletCaptureBuffer(fbshare_layer_index, color));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result IDisplayController::AcquireLastForegroundCaptureSharedBuffer(
|
Result IDisplayController::AcquireLastForegroundCaptureSharedBuffer(
|
||||||
Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) {
|
Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer(out_was_written,
|
R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer(
|
||||||
out_fbshare_layer_index));
|
out_was_written, out_fbshare_layer_index, VI::CaptureKind::LastForeground));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result IDisplayController::ReleaseLastForegroundCaptureSharedBuffer() {
|
Result IDisplayController::ReleaseLastForegroundCaptureSharedBuffer() {
|
||||||
@@ -90,9 +91,9 @@ Result IDisplayController::ReleaseLastForegroundCaptureSharedBuffer() {
|
|||||||
|
|
||||||
Result IDisplayController::AcquireCallerAppletCaptureSharedBuffer(
|
Result IDisplayController::AcquireCallerAppletCaptureSharedBuffer(
|
||||||
Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) {
|
Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer(out_was_written,
|
R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer(
|
||||||
out_fbshare_layer_index));
|
out_was_written, out_fbshare_layer_index, VI::CaptureKind::CallerApplet));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result IDisplayController::ReleaseCallerAppletCaptureSharedBuffer() {
|
Result IDisplayController::ReleaseCallerAppletCaptureSharedBuffer() {
|
||||||
@@ -102,9 +103,9 @@ Result IDisplayController::ReleaseCallerAppletCaptureSharedBuffer() {
|
|||||||
|
|
||||||
Result IDisplayController::AcquireLastApplicationCaptureSharedBuffer(
|
Result IDisplayController::AcquireLastApplicationCaptureSharedBuffer(
|
||||||
Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) {
|
Out<bool> out_was_written, Out<s32> out_fbshare_layer_index) {
|
||||||
LOG_WARNING(Service_AM, "(STUBBED) called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer(out_was_written,
|
R_RETURN(applet->display_layer_manager.WriteAppletCaptureBuffer(
|
||||||
out_fbshare_layer_index));
|
out_was_written, out_fbshare_layer_index, VI::CaptureKind::LastApplication));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result IDisplayController::ReleaseLastApplicationCaptureSharedBuffer() {
|
Result IDisplayController::ReleaseLastApplicationCaptureSharedBuffer() {
|
||||||
|
|||||||
@@ -168,7 +168,14 @@ constexpr u32 SharedBufferBlockLinearWidth = 1280;
|
|||||||
constexpr u32 SharedBufferBlockLinearHeight = 768;
|
constexpr u32 SharedBufferBlockLinearHeight = 768;
|
||||||
constexpr u32 SharedBufferBlockLinearStride =
|
constexpr u32 SharedBufferBlockLinearStride =
|
||||||
SharedBufferBlockLinearWidth * SharedBufferBlockLinearBpp;
|
SharedBufferBlockLinearWidth * SharedBufferBlockLinearBpp;
|
||||||
constexpr u32 SharedBufferNumSlots = 7;
|
|
||||||
|
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 SharedBufferWidth = 1280;
|
constexpr u32 SharedBufferWidth = 1280;
|
||||||
constexpr u32 SharedBufferHeight = 720;
|
constexpr u32 SharedBufferHeight = 720;
|
||||||
@@ -192,6 +199,43 @@ constexpr SharedMemoryPoolLayout SharedBufferPoolLayout = [] {
|
|||||||
return layout;
|
return layout;
|
||||||
}();
|
}();
|
||||||
|
|
||||||
|
constexpr u32 GetCaptureSlot(CaptureKind kind) {
|
||||||
|
return static_cast<u32>(kind);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
void ForEachPoolChunk(Core::System& system, Kernel::KPageGroup& page_group, u64 offset, u64 size,
|
||||||
|
F&& writer) {
|
||||||
|
Common::ScratchBuffer<u32> 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<u8>(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 slot, u32 handle) {
|
void MakeGraphicBuffer(android::BufferQueueProducer& producer, u32 slot, u32 handle) {
|
||||||
auto buffer = std::make_shared<android::NvGraphicBuffer>();
|
auto buffer = std::make_shared<android::NvGraphicBuffer>();
|
||||||
buffer->width = SharedBufferWidth;
|
buffer->width = SharedBufferWidth;
|
||||||
@@ -404,31 +448,47 @@ Result SharedBufferManager::GetSharedFrameBufferAcquirableEvent(Kernel::KReadabl
|
|||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result SharedBufferManager::WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index) {
|
Result SharedBufferManager::WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index, CaptureKind kind) {
|
||||||
std::vector<u8> capture_buffer(m_system.GPU().GetAppletCaptureBuffer());
|
std::scoped_lock lk{m_guard};
|
||||||
Common::ScratchBuffer<u32> scratch;
|
R_UNLESS(m_buffer_page_group != nullptr, VI::ResultNotFound);
|
||||||
|
|
||||||
// TODO: this could be optimized
|
const std::vector<u8> capture = m_system.GPU().GetAppletCaptureBuffer();
|
||||||
s64 e = -1280 * 768 * 4;
|
const u32 slot = GetCaptureSlot(kind);
|
||||||
for (auto& block : *m_buffer_page_group) {
|
|
||||||
u8* start = m_system.DeviceMemory().GetPointer<u8>(block.GetAddress());
|
|
||||||
u8* end = m_system.DeviceMemory().GetPointer<u8>(block.GetAddress() + block.GetSize());
|
|
||||||
|
|
||||||
for (; start < end; start++) {
|
if (capture.size() < SharedBufferSlotSize) {
|
||||||
*start = 0;
|
//LOG_WARNING(Service_VI, "Capture buffer is {} bytes, expected at least {}; not writing",
|
||||||
if (e >= 0 && e < static_cast<s64>(capture_buffer.size())) {
|
// capture.size(), SharedBufferSlotSize);
|
||||||
*start = capture_buffer[e];
|
*out_was_written = false;
|
||||||
}
|
*out_layer_index = static_cast<s32>(slot);
|
||||||
e++;
|
R_SUCCEED();
|
||||||
}
|
|
||||||
|
|
||||||
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_was_written = true;
|
||||||
*out_layer_index = 1;
|
*out_layer_index = static_cast<s32>(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<s32>(SharedBufferNumCaptureSlots)) {
|
||||||
|
LOG_WARNING(Service_VI, "Couldnt clear non-capture slot {}", layer_index);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
ForEachPoolChunk(m_system, *m_buffer_page_group, u64{static_cast<u32>(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<u32*>(dst), length / sizeof(u32), color);
|
||||||
|
});
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,12 @@ static_assert(sizeof(SharedMemoryPoolLayout) == 0x188, "SharedMemoryPoolLayout h
|
|||||||
|
|
||||||
struct SharedBufferSession;
|
struct SharedBufferSession;
|
||||||
|
|
||||||
|
enum class CaptureKind : u32 {
|
||||||
|
LastApplication,
|
||||||
|
LastForeground,
|
||||||
|
CallerApplet,
|
||||||
|
};
|
||||||
|
|
||||||
class SharedBufferManager final {
|
class SharedBufferManager final {
|
||||||
public:
|
public:
|
||||||
explicit SharedBufferManager(Core::System& system, Container& container,
|
explicit SharedBufferManager(Core::System& system, Container& container,
|
||||||
@@ -68,7 +74,8 @@ public:
|
|||||||
Result CancelSharedFrameBuffer(u64 layer_id, s64 slot);
|
Result CancelSharedFrameBuffer(u64 layer_id, s64 slot);
|
||||||
Result GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event, u64 layer_id);
|
Result GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event, u64 layer_id);
|
||||||
|
|
||||||
Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index);
|
Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index, CaptureKind kind);
|
||||||
|
Result ClearAppletCaptureBuffer(s32 layer_index, u32 color);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
u64 m_next_buffer_id = 1;
|
u64 m_next_buffer_id = 1;
|
||||||
@@ -89,6 +96,7 @@ struct SharedBufferSession {
|
|||||||
Nvidia::NvCore::SessionId session_id = {};
|
Nvidia::NvCore::SessionId session_id = {};
|
||||||
u64 layer_id = {};
|
u64 layer_id = {};
|
||||||
u32 buffer_nvmap_handle = 0;
|
u32 buffer_nvmap_handle = 0;
|
||||||
|
u32 presentation_slot_base = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::VI
|
} // namespace Service::VI
|
||||||
|
|||||||
Reference in New Issue
Block a user