Merge pull request #12701 from liamwhite/flinger-layer-issues
vi: check layer state before opening or closing
This commit is contained in:
		| @@ -112,9 +112,7 @@ void Nvnflinger::ShutdownLayers() { | |||||||
|     { |     { | ||||||
|         const auto lock_guard = Lock(); |         const auto lock_guard = Lock(); | ||||||
|         for (auto& display : displays) { |         for (auto& display : displays) { | ||||||
|             for (size_t layer = 0; layer < display.GetNumLayers(); ++layer) { |             display.Abandon(); | ||||||
|                 display.GetLayer(layer).GetConsumer().Abandon(); |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         is_abandoned = true; |         is_abandoned = true; | ||||||
| @@ -176,24 +174,28 @@ void Nvnflinger::CreateLayerAtId(VI::Display& display, u64 layer_id) { | |||||||
|     display.CreateLayer(layer_id, buffer_id, nvdrv->container); |     display.CreateLayer(layer_id, buffer_id, nvdrv->container); | ||||||
| } | } | ||||||
|  |  | ||||||
| void Nvnflinger::OpenLayer(u64 layer_id) { | bool Nvnflinger::OpenLayer(u64 layer_id) { | ||||||
|     const auto lock_guard = Lock(); |     const auto lock_guard = Lock(); | ||||||
|  |  | ||||||
|     for (auto& display : displays) { |     for (auto& display : displays) { | ||||||
|         if (auto* layer = display.FindLayer(layer_id); layer) { |         if (auto* layer = display.FindLayer(layer_id); layer) { | ||||||
|             layer->Open(); |             return layer->Open(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     return false; | ||||||
| } | } | ||||||
|  |  | ||||||
| void Nvnflinger::CloseLayer(u64 layer_id) { | bool Nvnflinger::CloseLayer(u64 layer_id) { | ||||||
|     const auto lock_guard = Lock(); |     const auto lock_guard = Lock(); | ||||||
|  |  | ||||||
|     for (auto& display : displays) { |     for (auto& display : displays) { | ||||||
|         if (auto* layer = display.FindLayer(layer_id); layer) { |         if (auto* layer = display.FindLayer(layer_id); layer) { | ||||||
|             layer->Close(); |             return layer->Close(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     return false; | ||||||
| } | } | ||||||
|  |  | ||||||
| void Nvnflinger::DestroyLayer(u64 layer_id) { | void Nvnflinger::DestroyLayer(u64 layer_id) { | ||||||
|   | |||||||
| @@ -74,10 +74,10 @@ public: | |||||||
|     [[nodiscard]] std::optional<u64> CreateLayer(u64 display_id); |     [[nodiscard]] std::optional<u64> CreateLayer(u64 display_id); | ||||||
|  |  | ||||||
|     /// Opens a layer on all displays for the given layer ID. |     /// Opens a layer on all displays for the given layer ID. | ||||||
|     void OpenLayer(u64 layer_id); |     bool OpenLayer(u64 layer_id); | ||||||
|  |  | ||||||
|     /// Closes a layer on all displays for the given layer ID. |     /// Closes a layer on all displays for the given layer ID. | ||||||
|     void CloseLayer(u64 layer_id); |     bool CloseLayer(u64 layer_id); | ||||||
|  |  | ||||||
|     /// Destroys the given layer ID. |     /// Destroys the given layer ID. | ||||||
|     void DestroyLayer(u64 layer_id); |     void DestroyLayer(u64 layer_id); | ||||||
|   | |||||||
| @@ -91,6 +91,10 @@ void Display::CreateLayer(u64 layer_id, u32 binder_id, | |||||||
|     layers.emplace_back(std::make_unique<Layer>(layer_id, binder_id, *core, *producer, |     layers.emplace_back(std::make_unique<Layer>(layer_id, binder_id, *core, *producer, | ||||||
|                                                 std::move(buffer_item_consumer))); |                                                 std::move(buffer_item_consumer))); | ||||||
|  |  | ||||||
|  |     if (is_abandoned) { | ||||||
|  |         this->FindLayer(layer_id)->GetConsumer().Abandon(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     hos_binder_driver_server.RegisterProducer(std::move(producer)); |     hos_binder_driver_server.RegisterProducer(std::move(producer)); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -103,6 +107,13 @@ void Display::DestroyLayer(u64 layer_id) { | |||||||
|                   [layer_id](const auto& layer) { return layer->GetLayerId() == layer_id; }); |                   [layer_id](const auto& layer) { return layer->GetLayerId() == layer_id; }); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | void Display::Abandon() { | ||||||
|  |     for (auto& layer : layers) { | ||||||
|  |         layer->GetConsumer().Abandon(); | ||||||
|  |     } | ||||||
|  |     is_abandoned = true; | ||||||
|  | } | ||||||
|  |  | ||||||
| Layer* Display::FindLayer(u64 layer_id) { | Layer* Display::FindLayer(u64 layer_id) { | ||||||
|     const auto itr = |     const auto itr = | ||||||
|         std::find_if(layers.begin(), layers.end(), [layer_id](const std::unique_ptr<Layer>& layer) { |         std::find_if(layers.begin(), layers.end(), [layer_id](const std::unique_ptr<Layer>& layer) { | ||||||
|   | |||||||
| @@ -98,6 +98,8 @@ public: | |||||||
|         layers.clear(); |         layers.clear(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     void Abandon(); | ||||||
|  |  | ||||||
|     /// Attempts to find a layer with the given ID. |     /// Attempts to find a layer with the given ID. | ||||||
|     /// |     /// | ||||||
|     /// @param layer_id The layer ID. |     /// @param layer_id The layer ID. | ||||||
| @@ -124,6 +126,7 @@ private: | |||||||
|  |  | ||||||
|     std::vector<std::unique_ptr<Layer>> layers; |     std::vector<std::unique_ptr<Layer>> layers; | ||||||
|     Kernel::KEvent* vsync_event{}; |     Kernel::KEvent* vsync_event{}; | ||||||
|  |     bool is_abandoned{}; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| } // namespace Service::VI | } // namespace Service::VI | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include <memory> | #include <memory> | ||||||
|  | #include <utility> | ||||||
|  |  | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
|  |  | ||||||
| @@ -75,12 +76,12 @@ public: | |||||||
|         return open; |         return open; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void Close() { |     bool Close() { | ||||||
|         open = false; |         return std::exchange(open, false); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     void Open() { |     bool Open() { | ||||||
|         open = true; |         return !std::exchange(open, true); | ||||||
|     } |     } | ||||||
|  |  | ||||||
| private: | private: | ||||||
|   | |||||||
| @@ -719,7 +719,12 @@ private: | |||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         nvnflinger.OpenLayer(layer_id); |         if (!nvnflinger.OpenLayer(layer_id)) { | ||||||
|  |             LOG_WARNING(Service_VI, "Tried to open layer which was already open"); | ||||||
|  |             IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|  |             rb.Push(ResultOperationFailed); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         android::OutputParcel parcel; |         android::OutputParcel parcel; | ||||||
|         parcel.WriteInterface(NativeWindow{*buffer_queue_id}); |         parcel.WriteInterface(NativeWindow{*buffer_queue_id}); | ||||||
| @@ -737,7 +742,12 @@ private: | |||||||
|  |  | ||||||
|         LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}", layer_id); |         LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}", layer_id); | ||||||
|  |  | ||||||
|         nvnflinger.CloseLayer(layer_id); |         if (!nvnflinger.CloseLayer(layer_id)) { | ||||||
|  |             LOG_WARNING(Service_VI, "Tried to close layer which was not open"); | ||||||
|  |             IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|  |             rb.Push(ResultOperationFailed); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         IPC::ResponseBuilder rb{ctx, 2}; |         IPC::ResponseBuilder rb{ctx, 2}; | ||||||
|         rb.Push(ResultSuccess); |         rb.Push(ResultSuccess); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user