diff options
author | Liam <byteslice@airmail.cc> | 2024-02-15 05:44:05 +0100 |
---|---|---|
committer | Liam <byteslice@airmail.cc> | 2024-02-18 00:08:38 +0100 |
commit | 812f23d05c77fb10407546c3e7a95447fcbea395 (patch) | |
tree | bbfb035c35ccffb6dbe0995002c2937bd94edc2d /src/core/hle/service/nvnflinger/surface_flinger.cpp | |
parent | vi: move shared buffer management from nvnflinger (diff) | |
download | yuzu-812f23d05c77fb10407546c3e7a95447fcbea395.tar yuzu-812f23d05c77fb10407546c3e7a95447fcbea395.tar.gz yuzu-812f23d05c77fb10407546c3e7a95447fcbea395.tar.bz2 yuzu-812f23d05c77fb10407546c3e7a95447fcbea395.tar.lz yuzu-812f23d05c77fb10407546c3e7a95447fcbea395.tar.xz yuzu-812f23d05c77fb10407546c3e7a95447fcbea395.tar.zst yuzu-812f23d05c77fb10407546c3e7a95447fcbea395.zip |
Diffstat (limited to '')
-rw-r--r-- | src/core/hle/service/nvnflinger/surface_flinger.cpp | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/src/core/hle/service/nvnflinger/surface_flinger.cpp b/src/core/hle/service/nvnflinger/surface_flinger.cpp new file mode 100644 index 000000000..0e9714a03 --- /dev/null +++ b/src/core/hle/service/nvnflinger/surface_flinger.cpp @@ -0,0 +1,123 @@ +// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "core/core.h" +#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" +#include "core/hle/service/nvdrv/nvdrv_interface.h" +#include "core/hle/service/nvnflinger/display.h" +#include "core/hle/service/nvnflinger/hos_binder_driver_server.h" +#include "core/hle/service/nvnflinger/surface_flinger.h" +#include "core/hle/service/sm/sm.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_producer.h" + +namespace Service::Nvnflinger { + +SurfaceFlinger::SurfaceFlinger(Core::System& system, HosBinderDriverServer& server) + : m_system(system), m_server(server), m_context(m_system, "SurfaceFlinger") { + nvdrv = m_system.ServiceManager().GetService<Nvidia::NVDRV>("nvdrv:s", true)->GetModule(); + disp_fd = nvdrv->Open("/dev/nvdisp_disp0", {}); +} + +SurfaceFlinger::~SurfaceFlinger() { + nvdrv->Close(disp_fd); +} + +void SurfaceFlinger::AddDisplay(u64 display_id) { + m_displays.emplace_back(display_id); +} + +void SurfaceFlinger::RemoveDisplay(u64 display_id) { + std::erase_if(m_displays, [&](auto& display) { return display.id == display_id; }); +} + +void SurfaceFlinger::ComposeDisplay(s32* out_swap_interval, f32* out_compose_speed_scale, + u64 display_id) { + auto* const display = this->FindDisplay(display_id); + if (!display) { + return; + } + + *out_swap_interval = + m_composer.ComposeLocked(out_compose_speed_scale, *display, + *nvdrv->GetDevice<Nvidia::Devices::nvdisp_disp0>(disp_fd)); +} + +void SurfaceFlinger::AddLayerToDisplayStack(u64 display_id, s32 consumer_binder_id) { + auto* const display = this->FindDisplay(display_id); + auto binder = std::static_pointer_cast<android::BufferQueueConsumer>( + m_server.TryGetBinder(consumer_binder_id)); + + if (!display || !binder) { + return; + } + + auto buffer_item_consumer = std::make_shared<android::BufferItemConsumer>(std::move(binder)); + buffer_item_consumer->Connect(false); + + display->stack.layers.emplace_back(std::move(buffer_item_consumer), consumer_binder_id); +} + +void SurfaceFlinger::RemoveLayerFromDisplayStack(u64 display_id, s32 consumer_binder_id) { + auto* const display = this->FindDisplay(display_id); + if (!display) { + return; + } + + m_composer.RemoveLayerLocked(*display, consumer_binder_id); + std::erase_if(display->stack.layers, + [&](auto& layer) { return layer.consumer_id == consumer_binder_id; }); +} + +void SurfaceFlinger::SetLayerVisibility(s32 consumer_binder_id, bool visible) { + if (auto* layer = this->FindLayer(consumer_binder_id); layer != nullptr) { + layer->visible = visible; + return; + } +} + +void SurfaceFlinger::SetLayerBlending(s32 consumer_binder_id, LayerBlending blending) { + if (auto* layer = this->FindLayer(consumer_binder_id); layer != nullptr) { + layer->blending = blending; + return; + } +} + +Display* SurfaceFlinger::FindDisplay(u64 display_id) { + for (auto& display : m_displays) { + if (display.id == display_id) { + return &display; + } + } + + return nullptr; +} + +Layer* SurfaceFlinger::FindLayer(s32 consumer_binder_id) { + for (auto& display : m_displays) { + if (auto* layer = display.FindLayer(consumer_binder_id); layer != nullptr) { + return layer; + } + } + + return nullptr; +} + +void SurfaceFlinger::CreateBufferQueue(s32* out_consumer_binder_id, s32* out_producer_binder_id) { + auto& nvmap = nvdrv->GetContainer().GetNvMapFile(); + auto core = std::make_shared<android::BufferQueueCore>(); + auto producer = std::make_shared<android::BufferQueueProducer>(m_context, core, nvmap); + auto consumer = std::make_shared<android::BufferQueueConsumer>(core); + + *out_consumer_binder_id = m_server.RegisterBinder(std::move(consumer)); + *out_producer_binder_id = m_server.RegisterBinder(std::move(producer)); +} + +void SurfaceFlinger::DestroyBufferQueue(s32 consumer_binder_id, s32 producer_binder_id) { + m_server.UnregisterBinder(producer_binder_id); + m_server.UnregisterBinder(consumer_binder_id); +} + +} // namespace Service::Nvnflinger |