mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-07-02 04:45:54 +02:00
[hle,display,overlay,starter,hid] add overlay functions, starter applet (initially), HID handheld for system applets and fw21 stubs (#3080)
Adds fully functional overlay display. - Enable Overlay Applet via "View" -> "Enable Overlay Display Applet" - Open the overlay by pressing the home button for over 1s - Can adjust volume - Can toggle airplane mode (if on WiFi, maybe if overlay is enabled pretend to be on WiFi?) - Future TODO(?): Adjust Brightness implementation for host system - Inputs are properly registered. e.g. if overlay open, application does not register inputs. You can control volume and airplane mode outside of the emulator window Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3080 Reviewed-by: CamilleLaVey <camillelavey99@gmail.com> Reviewed-by: crueter <crueter@eden-emu.dev> Co-authored-by: Maufeat <sahyno1996@gmail.com> Co-committed-by: Maufeat <sahyno1996@gmail.com>
This commit is contained in:
parent
1efef85352
commit
f58097e814
75 changed files with 1634 additions and 181 deletions
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
|
@ -131,6 +134,38 @@ Result Container::SetLayerBlending(u64 layer_id, bool enabled) {
|
|||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result Container::SetLayerZIndex(u64 layer_id, s32 z_index) {
|
||||
std::scoped_lock lk{m_lock};
|
||||
|
||||
auto* const layer = m_layers.GetLayerById(layer_id);
|
||||
R_UNLESS(layer != nullptr, VI::ResultNotFound);
|
||||
|
||||
if (auto layer_ref = m_surface_flinger->FindLayer(layer->GetConsumerBinderId())) {
|
||||
LOG_DEBUG(Service_VI, "called, SetLayerZIndex layer_id={} z={} (cid={})", layer_id,
|
||||
z_index, layer->GetConsumerBinderId());
|
||||
layer_ref->z_index = z_index;
|
||||
} else {
|
||||
LOG_DEBUG(Service_VI, "called, SetLayerZIndex failed to find layer for layer_id={} (cid={})",
|
||||
layer_id, layer->GetConsumerBinderId());
|
||||
}
|
||||
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result Container::GetLayerZIndex(u64 layer_id, s32* out_z_index) {
|
||||
std::scoped_lock lk{m_lock};
|
||||
|
||||
auto* const layer = m_layers.GetLayerById(layer_id);
|
||||
R_UNLESS(layer != nullptr, VI::ResultNotFound);
|
||||
|
||||
if (auto layer_ref = m_surface_flinger->FindLayer(layer->GetConsumerBinderId())) {
|
||||
*out_z_index = layer_ref->z_index;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
R_RETURN(VI::ResultNotFound);
|
||||
}
|
||||
|
||||
void Container::LinkVsyncEvent(u64 display_id, Event* event) {
|
||||
std::scoped_lock lk{m_lock};
|
||||
m_conductor->LinkVsyncEvent(display_id, event);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
|
@ -62,6 +65,8 @@ public:
|
|||
|
||||
Result SetLayerVisibility(u64 layer_id, bool visible);
|
||||
Result SetLayerBlending(u64 layer_id, bool enabled);
|
||||
Result SetLayerZIndex(u64 layer_id, s32 z_index);
|
||||
Result GetLayerZIndex(u64 layer_id, s32* out_z_index);
|
||||
|
||||
void LinkVsyncEvent(u64 display_id, Event* event);
|
||||
void UnlinkVsyncEvent(u64 display_id, Event* event);
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
|
@ -116,6 +119,10 @@ Result IManagerDisplayService::SetLayerBlending(bool enabled, u64 layer_id) {
|
|||
R_RETURN(m_container->SetLayerBlending(layer_id, enabled));
|
||||
}
|
||||
|
||||
Result IManagerDisplayService::SetLayerZIndex(s32 z_index, u64 layer_id) {
|
||||
R_RETURN(m_container->SetLayerZIndex(layer_id, z_index));
|
||||
}
|
||||
|
||||
Result IManagerDisplayService::CreateManagedLayer(Out<u64> out_layer_id, u32 flags, u64 display_id,
|
||||
AppletResourceUserId aruid) {
|
||||
LOG_DEBUG(Service_VI, "called. flags={}, display={}, aruid={}", flags, display_id, aruid.pid);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
|
|
@ -22,6 +27,7 @@ public:
|
|||
void DestroySharedLayerSession(Kernel::KProcess* owner_process);
|
||||
|
||||
Result SetLayerBlending(bool enabled, u64 layer_id);
|
||||
Result SetLayerZIndex(s32 z_index, u64 layer_id);
|
||||
|
||||
public:
|
||||
Result CreateManagedLayer(Out<u64> out_layer_id, u32 flags, u64 display_id,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
|
@ -38,13 +41,13 @@ Result AllocateSharedBufferMemory(std::unique_ptr<Kernel::KPageGroup>* out_page_
|
|||
Kernel::KMemoryManager::EncodeOption(Kernel::KMemoryManager::Pool::Secure,
|
||||
Kernel::KMemoryManager::Direction::FromBack)));
|
||||
|
||||
// Fill the output data with red.
|
||||
// Initialize to fully transparent black to avoid covering content before first present.
|
||||
for (auto& block : *pg) {
|
||||
u32* start = system.DeviceMemory().GetPointer<u32>(block.GetAddress());
|
||||
u32* end = system.DeviceMemory().GetPointer<u32>(block.GetAddress() + block.GetSize());
|
||||
|
||||
for (; start < end; start++) {
|
||||
*start = 0xFF0000FF;
|
||||
for (; start < end; ++start) {
|
||||
*start = 0x00000000; // ARGB/RGBA with alpha=0
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -252,8 +255,9 @@ Result SharedBufferManager::CreateSession(Kernel::KProcess* owner_process, u64*
|
|||
R_TRY(m_container.CreateStrayLayer(std::addressof(producer_binder_id),
|
||||
std::addressof(session.layer_id), display_id));
|
||||
|
||||
// Configure blending.
|
||||
// Configure blending and z-index
|
||||
R_ASSERT(m_container.SetLayerBlending(session.layer_id, enable_blending));
|
||||
R_ASSERT(m_container.SetLayerZIndex(session.layer_id, 100000));
|
||||
|
||||
// Get the producer and set preallocated buffers.
|
||||
std::shared_ptr<android::BufferQueueProducer> producer;
|
||||
|
|
@ -370,6 +374,11 @@ Result SharedBufferManager::PresentSharedFrameBuffer(android::Fence fence,
|
|||
android::Status::NoError,
|
||||
VI::ResultOperationFailed);
|
||||
|
||||
// Ensure the layer is visible when content is presented.
|
||||
// Re-assert overlay priority in case clients reset it.
|
||||
(void)m_container.SetLayerZIndex(layer_id, 100000);
|
||||
(void)m_container.SetLayerVisibility(layer_id, true);
|
||||
|
||||
// We succeeded.
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
|
@ -406,23 +415,51 @@ Result SharedBufferManager::WriteAppletCaptureBuffer(bool* out_was_written, s32*
|
|||
// TODO: this could be optimized
|
||||
s64 e = -1280 * 768 * 4;
|
||||
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++) {
|
||||
*start = 0;
|
||||
u8* const block_start = m_system.DeviceMemory().GetPointer<u8>(block.GetAddress());
|
||||
u8* ptr = block_start;
|
||||
u8* const block_end = m_system.DeviceMemory().GetPointer<u8>(block.GetAddress() + block.GetSize());
|
||||
|
||||
for (; ptr < block_end; ++ptr) {
|
||||
if (e >= 0 && e < static_cast<s64>(capture_buffer.size())) {
|
||||
*start = capture_buffer[e];
|
||||
*ptr = capture_buffer[static_cast<size_t>(e)];
|
||||
} else {
|
||||
*ptr = 0;
|
||||
}
|
||||
e++;
|
||||
++e;
|
||||
}
|
||||
|
||||
m_system.GPU().Host1x().MemoryManager().ApplyOpOnPointer(start, scratch, [&](DAddr addr) {
|
||||
m_system.GPU().InvalidateRegion(addr, end - start);
|
||||
m_system.GPU().Host1x().MemoryManager().ApplyOpOnPointer(block_start, scratch, [&](DAddr addr) {
|
||||
m_system.GPU().InvalidateRegion(addr, block_end - block_start);
|
||||
});
|
||||
}
|
||||
|
||||
// After writing, present a frame on each active shared layer so it becomes visible.
|
||||
for (auto& [aruid, session] : m_sessions) {
|
||||
std::shared_ptr<android::BufferQueueProducer> producer;
|
||||
if (R_FAILED(m_container.GetLayerProducerHandle(std::addressof(producer), session.layer_id))) {
|
||||
continue;
|
||||
}
|
||||
s32 slot = -1;
|
||||
android::Fence fence = android::Fence::NoFence();
|
||||
if (producer->DequeueBuffer(&slot, &fence, SharedBufferAsync != 0, SharedBufferWidth,
|
||||
SharedBufferHeight, SharedBufferBlockLinearFormat, 0) !=
|
||||
android::Status::NoError) {
|
||||
continue;
|
||||
}
|
||||
std::shared_ptr<android::GraphicBuffer> gb;
|
||||
if (producer->RequestBuffer(slot, &gb) != android::Status::NoError) {
|
||||
producer->CancelBuffer(slot, android::Fence::NoFence());
|
||||
continue;
|
||||
}
|
||||
android::QueueBufferInput qin{};
|
||||
android::QueueBufferOutput qout{};
|
||||
qin.crop = {0, 0, static_cast<s32>(SharedBufferWidth), static_cast<s32>(SharedBufferHeight)};
|
||||
qin.fence = android::Fence::NoFence();
|
||||
qin.transform = static_cast<android::NativeWindowTransform>(0);
|
||||
qin.swap_interval = 1;
|
||||
(void)producer->QueueBuffer(slot, qin, &qout);
|
||||
}
|
||||
|
||||
*out_was_written = true;
|
||||
*out_layer_index = 1;
|
||||
R_SUCCEED();
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
|
@ -8,7 +11,6 @@
|
|||
#include "common/math_util.h"
|
||||
#include "core/hle/service/nvdrv/core/container.h"
|
||||
#include "core/hle/service/nvdrv/nvdata.h"
|
||||
#include "core/hle/service/nvnflinger/nvnflinger.h"
|
||||
#include "core/hle/service/nvnflinger/ui/fence.h"
|
||||
|
||||
namespace Kernel {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
|
@ -20,7 +23,7 @@ ISystemDisplayService::ISystemDisplayService(Core::System& system_,
|
|||
{1204, nullptr, "SetDisplayMagnification"},
|
||||
{2201, nullptr, "SetLayerPosition"},
|
||||
{2203, nullptr, "SetLayerSize"},
|
||||
{2204, nullptr, "GetLayerZ"},
|
||||
{2204, C<&ISystemDisplayService::GetLayerZ>, "GetLayerZ"},
|
||||
{2205, C<&ISystemDisplayService::SetLayerZ>, "SetLayerZ"},
|
||||
{2207, C<&ISystemDisplayService::SetLayerVisibility>, "SetLayerVisibility"},
|
||||
{2209, nullptr, "SetLayerAlpha"},
|
||||
|
|
@ -68,16 +71,26 @@ ISystemDisplayService::ISystemDisplayService(Core::System& system_,
|
|||
|
||||
ISystemDisplayService::~ISystemDisplayService() = default;
|
||||
|
||||
Result ISystemDisplayService::SetLayerZ(u32 z_value, u64 layer_id) {
|
||||
LOG_WARNING(Service_VI, "(STUBBED) called. layer_id={}, z_value={}", layer_id, z_value);
|
||||
Result ISystemDisplayService::GetLayerZ(Out<u64> out_z_value, u64 layer_id) {
|
||||
LOG_DEBUG(Service_VI, "called. layer_id={}", layer_id);
|
||||
s32 z{};
|
||||
const auto res = m_container->GetLayerZIndex(layer_id, &z);
|
||||
R_TRY(res);
|
||||
*out_z_value = static_cast<u64>(z);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result ISystemDisplayService::SetLayerZ(u64 layer_id, u64 z_value) {
|
||||
LOG_DEBUG(Service_VI, "called. layer_id={}, z_value={}", layer_id, z_value);
|
||||
// Forward to container using internal API when available
|
||||
R_RETURN(m_container->SetLayerZIndex(layer_id, static_cast<s32>(z_value)));
|
||||
}
|
||||
|
||||
// This function currently does nothing but return a success error code in
|
||||
// the vi library itself, so do the same thing, but log out the passed in values.
|
||||
Result ISystemDisplayService::SetLayerVisibility(bool visible, u64 layer_id) {
|
||||
LOG_DEBUG(Service_VI, "called, layer_id={}, visible={}", layer_id, visible);
|
||||
R_SUCCEED();
|
||||
R_RETURN(m_container->SetLayerVisibility(layer_id, visible));
|
||||
}
|
||||
|
||||
Result ISystemDisplayService::ListDisplayModes(
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
|
@ -18,7 +21,8 @@ public:
|
|||
~ISystemDisplayService() override;
|
||||
|
||||
private:
|
||||
Result SetLayerZ(u32 z_value, u64 layer_id);
|
||||
Result GetLayerZ(Out<u64> out_z_value, u64 layer_id);
|
||||
Result SetLayerZ(u64 layer_id, u64 z_value);
|
||||
Result SetLayerVisibility(bool visible, u64 layer_id);
|
||||
Result ListDisplayModes(Out<u64> out_count, u64 display_id,
|
||||
OutArray<DisplayMode, BufferAttr_HipcMapAlias> out_display_modes);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue