From 64c56315793d2b6dbf7a55f99d4bcc51929f03cb Mon Sep 17 00:00:00 2001 From: bunnei Date: Sat, 4 Jan 2020 00:45:06 -0500 Subject: [PATCH] service: vi: Implement CloseLayer. - Needed for Undertale. --- src/core/hle/service/nvflinger/nvflinger.cpp | 6 +++++ src/core/hle/service/nvflinger/nvflinger.h | 3 +++ .../hle/service/vi/display/vi_display.cpp | 27 ++++++++++++------- src/core/hle/service/vi/display/vi_display.h | 9 ++++++- src/core/hle/service/vi/vi.cpp | 14 +++++++++- 5 files changed, 48 insertions(+), 11 deletions(-) diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index 52623cf89..a58ea9c59 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp @@ -88,6 +88,12 @@ std::optional NVFlinger::CreateLayer(u64 display_id) { return layer_id; } +void NVFlinger::CloseLayer(u64 layer_id) { + for (auto& display : displays) { + display.CloseLayer(layer_id); + } +} + std::optional NVFlinger::FindBufferQueueId(u64 display_id, u64 layer_id) const { const auto* const layer = FindLayer(display_id, layer_id); diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h index e3cc14bdc..57a21f33b 100644 --- a/src/core/hle/service/nvflinger/nvflinger.h +++ b/src/core/hle/service/nvflinger/nvflinger.h @@ -54,6 +54,9 @@ public: /// If an invalid display ID is specified, then an empty optional is returned. std::optional CreateLayer(u64 display_id); + /// Closes a layer on all displays for the given layer ID. + void CloseLayer(u64 layer_id); + /// Finds the buffer queue ID of the specified layer in the specified display. /// /// If an invalid display ID or layer ID is provided, then an empty optional is returned. diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp index cd18c1610..5a202ac81 100644 --- a/src/core/hle/service/vi/display/vi_display.cpp +++ b/src/core/hle/service/vi/display/vi_display.cpp @@ -24,11 +24,11 @@ Display::Display(u64 id, std::string name, Core::System& system) : id{id}, name{ Display::~Display() = default; Layer& Display::GetLayer(std::size_t index) { - return layers.at(index); + return *layers.at(index); } const Layer& Display::GetLayer(std::size_t index) const { - return layers.at(index); + return *layers.at(index); } std::shared_ptr Display::GetVSyncEvent() const { @@ -43,29 +43,38 @@ void Display::CreateLayer(u64 id, NVFlinger::BufferQueue& buffer_queue) { // TODO(Subv): Support more than 1 layer. ASSERT_MSG(layers.empty(), "Only one layer is supported per display at the moment"); - layers.emplace_back(id, buffer_queue); + layers.emplace_back(std::make_shared(id, buffer_queue)); +} + +void Display::CloseLayer(u64 id) { + layers.erase( + std::remove_if(layers.begin(), layers.end(), + [id](const std::shared_ptr& layer) { return layer->GetID() == id; }), + layers.end()); } Layer* Display::FindLayer(u64 id) { - const auto itr = std::find_if(layers.begin(), layers.end(), - [id](const VI::Layer& layer) { return layer.GetID() == id; }); + const auto itr = + std::find_if(layers.begin(), layers.end(), + [id](const std::shared_ptr& layer) { return layer->GetID() == id; }); if (itr == layers.end()) { return nullptr; } - return &*itr; + return itr->get(); } const Layer* Display::FindLayer(u64 id) const { - const auto itr = std::find_if(layers.begin(), layers.end(), - [id](const VI::Layer& layer) { return layer.GetID() == id; }); + const auto itr = + std::find_if(layers.begin(), layers.end(), + [id](const std::shared_ptr& layer) { return layer->GetID() == id; }); if (itr == layers.end()) { return nullptr; } - return &*itr; + return itr->get(); } } // namespace Service::VI diff --git a/src/core/hle/service/vi/display/vi_display.h b/src/core/hle/service/vi/display/vi_display.h index 8bb966a85..a3855d8cd 100644 --- a/src/core/hle/service/vi/display/vi_display.h +++ b/src/core/hle/service/vi/display/vi_display.h @@ -4,6 +4,7 @@ #pragma once +#include #include #include @@ -69,6 +70,12 @@ public: /// void CreateLayer(u64 id, NVFlinger::BufferQueue& buffer_queue); + /// Closes and removes a layer from this display with the given ID. + /// + /// @param id The ID assigned to the layer to close. + /// + void CloseLayer(u64 id); + /// Attempts to find a layer with the given ID. /// /// @param id The layer ID. @@ -91,7 +98,7 @@ private: u64 id; std::string name; - std::vector layers; + std::vector> layers; Kernel::EventPair vsync_event; }; diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 651c89dc0..519da74e0 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp @@ -1066,6 +1066,18 @@ private: rb.Push(ctx.WriteBuffer(native_window.Serialize())); } + void CloseLayer(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto layer_id{rp.Pop()}; + + LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}", layer_id); + + nv_flinger->CloseLayer(layer_id); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(RESULT_SUCCESS); + } + void CreateStrayLayer(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp{ctx}; const u32 flags = rp.Pop(); @@ -1178,7 +1190,7 @@ IApplicationDisplayService::IApplicationDisplayService( {1101, &IApplicationDisplayService::SetDisplayEnabled, "SetDisplayEnabled"}, {1102, &IApplicationDisplayService::GetDisplayResolution, "GetDisplayResolution"}, {2020, &IApplicationDisplayService::OpenLayer, "OpenLayer"}, - {2021, nullptr, "CloseLayer"}, + {2021, &IApplicationDisplayService::CloseLayer, "CloseLayer"}, {2030, &IApplicationDisplayService::CreateStrayLayer, "CreateStrayLayer"}, {2031, &IApplicationDisplayService::DestroyStrayLayer, "DestroyStrayLayer"}, {2101, &IApplicationDisplayService::SetLayerScalingMode, "SetLayerScalingMode"},