diff options
| author | 2024-01-20 13:34:32 -0500 | |
|---|---|---|
| committer | 2024-01-20 13:34:32 -0500 | |
| commit | 23fd1041c1373aea8ac36236c8bc681f9483d25d (patch) | |
| tree | 116693463c6c32b2eab47adc2262526218018a41 | |
| parent | Merge pull request #12713 from shinra-electric/mvk-127 (diff) | |
| parent | vi: check layer state before opening or closing (diff) | |
| download | yuzu-23fd1041c1373aea8ac36236c8bc681f9483d25d.tar.gz yuzu-23fd1041c1373aea8ac36236c8bc681f9483d25d.tar.xz yuzu-23fd1041c1373aea8ac36236c8bc681f9483d25d.zip | |
Merge pull request #12701 from liamwhite/flinger-layer-issues
vi: check layer state before opening or closing
| -rw-r--r-- | src/core/hle/service/nvnflinger/nvnflinger.cpp | 16 | ||||
| -rw-r--r-- | src/core/hle/service/nvnflinger/nvnflinger.h | 4 | ||||
| -rw-r--r-- | src/core/hle/service/vi/display/vi_display.cpp | 11 | ||||
| -rw-r--r-- | src/core/hle/service/vi/display/vi_display.h | 3 | ||||
| -rw-r--r-- | src/core/hle/service/vi/layer/vi_layer.h | 9 | ||||
| -rw-r--r-- | src/core/hle/service/vi/vi.cpp | 14 |
6 files changed, 42 insertions, 15 deletions
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.cpp b/src/core/hle/service/nvnflinger/nvnflinger.cpp index 0469110e8..af6591370 100644 --- a/src/core/hle/service/nvnflinger/nvnflinger.cpp +++ b/src/core/hle/service/nvnflinger/nvnflinger.cpp | |||
| @@ -112,9 +112,7 @@ void Nvnflinger::ShutdownLayers() { | |||
| 112 | { | 112 | { |
| 113 | const auto lock_guard = Lock(); | 113 | const auto lock_guard = Lock(); |
| 114 | for (auto& display : displays) { | 114 | for (auto& display : displays) { |
| 115 | for (size_t layer = 0; layer < display.GetNumLayers(); ++layer) { | 115 | display.Abandon(); |
| 116 | display.GetLayer(layer).GetConsumer().Abandon(); | ||
| 117 | } | ||
| 118 | } | 116 | } |
| 119 | 117 | ||
| 120 | is_abandoned = true; | 118 | is_abandoned = true; |
| @@ -176,24 +174,28 @@ void Nvnflinger::CreateLayerAtId(VI::Display& display, u64 layer_id) { | |||
| 176 | display.CreateLayer(layer_id, buffer_id, nvdrv->container); | 174 | display.CreateLayer(layer_id, buffer_id, nvdrv->container); |
| 177 | } | 175 | } |
| 178 | 176 | ||
| 179 | void Nvnflinger::OpenLayer(u64 layer_id) { | 177 | bool Nvnflinger::OpenLayer(u64 layer_id) { |
| 180 | const auto lock_guard = Lock(); | 178 | const auto lock_guard = Lock(); |
| 181 | 179 | ||
| 182 | for (auto& display : displays) { | 180 | for (auto& display : displays) { |
| 183 | if (auto* layer = display.FindLayer(layer_id); layer) { | 181 | if (auto* layer = display.FindLayer(layer_id); layer) { |
| 184 | layer->Open(); | 182 | return layer->Open(); |
| 185 | } | 183 | } |
| 186 | } | 184 | } |
| 185 | |||
| 186 | return false; | ||
| 187 | } | 187 | } |
| 188 | 188 | ||
| 189 | void Nvnflinger::CloseLayer(u64 layer_id) { | 189 | bool Nvnflinger::CloseLayer(u64 layer_id) { |
| 190 | const auto lock_guard = Lock(); | 190 | const auto lock_guard = Lock(); |
| 191 | 191 | ||
| 192 | for (auto& display : displays) { | 192 | for (auto& display : displays) { |
| 193 | if (auto* layer = display.FindLayer(layer_id); layer) { | 193 | if (auto* layer = display.FindLayer(layer_id); layer) { |
| 194 | layer->Close(); | 194 | return layer->Close(); |
| 195 | } | 195 | } |
| 196 | } | 196 | } |
| 197 | |||
| 198 | return false; | ||
| 197 | } | 199 | } |
| 198 | 200 | ||
| 199 | void Nvnflinger::DestroyLayer(u64 layer_id) { | 201 | void Nvnflinger::DestroyLayer(u64 layer_id) { |
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.h b/src/core/hle/service/nvnflinger/nvnflinger.h index 871285764..a60e0ae6b 100644 --- a/src/core/hle/service/nvnflinger/nvnflinger.h +++ b/src/core/hle/service/nvnflinger/nvnflinger.h | |||
| @@ -74,10 +74,10 @@ public: | |||
| 74 | [[nodiscard]] std::optional<u64> CreateLayer(u64 display_id); | 74 | [[nodiscard]] std::optional<u64> CreateLayer(u64 display_id); |
| 75 | 75 | ||
| 76 | /// Opens a layer on all displays for the given layer ID. | 76 | /// Opens a layer on all displays for the given layer ID. |
| 77 | void OpenLayer(u64 layer_id); | 77 | bool OpenLayer(u64 layer_id); |
| 78 | 78 | ||
| 79 | /// Closes a layer on all displays for the given layer ID. | 79 | /// Closes a layer on all displays for the given layer ID. |
| 80 | void CloseLayer(u64 layer_id); | 80 | bool CloseLayer(u64 layer_id); |
| 81 | 81 | ||
| 82 | /// Destroys the given layer ID. | 82 | /// Destroys the given layer ID. |
| 83 | void DestroyLayer(u64 layer_id); | 83 | void DestroyLayer(u64 layer_id); |
diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp index e2d9cd98a..725311c53 100644 --- a/src/core/hle/service/vi/display/vi_display.cpp +++ b/src/core/hle/service/vi/display/vi_display.cpp | |||
| @@ -91,6 +91,10 @@ void Display::CreateLayer(u64 layer_id, u32 binder_id, | |||
| 91 | layers.emplace_back(std::make_unique<Layer>(layer_id, binder_id, *core, *producer, | 91 | layers.emplace_back(std::make_unique<Layer>(layer_id, binder_id, *core, *producer, |
| 92 | std::move(buffer_item_consumer))); | 92 | std::move(buffer_item_consumer))); |
| 93 | 93 | ||
| 94 | if (is_abandoned) { | ||
| 95 | this->FindLayer(layer_id)->GetConsumer().Abandon(); | ||
| 96 | } | ||
| 97 | |||
| 94 | hos_binder_driver_server.RegisterProducer(std::move(producer)); | 98 | hos_binder_driver_server.RegisterProducer(std::move(producer)); |
| 95 | } | 99 | } |
| 96 | 100 | ||
| @@ -103,6 +107,13 @@ void Display::DestroyLayer(u64 layer_id) { | |||
| 103 | [layer_id](const auto& layer) { return layer->GetLayerId() == layer_id; }); | 107 | [layer_id](const auto& layer) { return layer->GetLayerId() == layer_id; }); |
| 104 | } | 108 | } |
| 105 | 109 | ||
| 110 | void Display::Abandon() { | ||
| 111 | for (auto& layer : layers) { | ||
| 112 | layer->GetConsumer().Abandon(); | ||
| 113 | } | ||
| 114 | is_abandoned = true; | ||
| 115 | } | ||
| 116 | |||
| 106 | Layer* Display::FindLayer(u64 layer_id) { | 117 | Layer* Display::FindLayer(u64 layer_id) { |
| 107 | const auto itr = | 118 | const auto itr = |
| 108 | std::find_if(layers.begin(), layers.end(), [layer_id](const std::unique_ptr<Layer>& layer) { | 119 | std::find_if(layers.begin(), layers.end(), [layer_id](const std::unique_ptr<Layer>& layer) { |
diff --git a/src/core/hle/service/vi/display/vi_display.h b/src/core/hle/service/vi/display/vi_display.h index 7e68ee79b..8eb8a5155 100644 --- a/src/core/hle/service/vi/display/vi_display.h +++ b/src/core/hle/service/vi/display/vi_display.h | |||
| @@ -98,6 +98,8 @@ public: | |||
| 98 | layers.clear(); | 98 | layers.clear(); |
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | void Abandon(); | ||
| 102 | |||
| 101 | /// Attempts to find a layer with the given ID. | 103 | /// Attempts to find a layer with the given ID. |
| 102 | /// | 104 | /// |
| 103 | /// @param layer_id The layer ID. | 105 | /// @param layer_id The layer ID. |
| @@ -124,6 +126,7 @@ private: | |||
| 124 | 126 | ||
| 125 | std::vector<std::unique_ptr<Layer>> layers; | 127 | std::vector<std::unique_ptr<Layer>> layers; |
| 126 | Kernel::KEvent* vsync_event{}; | 128 | Kernel::KEvent* vsync_event{}; |
| 129 | bool is_abandoned{}; | ||
| 127 | }; | 130 | }; |
| 128 | 131 | ||
| 129 | } // namespace Service::VI | 132 | } // namespace Service::VI |
diff --git a/src/core/hle/service/vi/layer/vi_layer.h b/src/core/hle/service/vi/layer/vi_layer.h index 295005e23..f95e2dc71 100644 --- a/src/core/hle/service/vi/layer/vi_layer.h +++ b/src/core/hle/service/vi/layer/vi_layer.h | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <memory> | 6 | #include <memory> |
| 7 | #include <utility> | ||
| 7 | 8 | ||
| 8 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
| 9 | 10 | ||
| @@ -75,12 +76,12 @@ public: | |||
| 75 | return open; | 76 | return open; |
| 76 | } | 77 | } |
| 77 | 78 | ||
| 78 | void Close() { | 79 | bool Close() { |
| 79 | open = false; | 80 | return std::exchange(open, false); |
| 80 | } | 81 | } |
| 81 | 82 | ||
| 82 | void Open() { | 83 | bool Open() { |
| 83 | open = true; | 84 | return !std::exchange(open, true); |
| 84 | } | 85 | } |
| 85 | 86 | ||
| 86 | private: | 87 | private: |
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 39d5be90d..bfcc27ddc 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp | |||
| @@ -719,7 +719,12 @@ private: | |||
| 719 | return; | 719 | return; |
| 720 | } | 720 | } |
| 721 | 721 | ||
| 722 | nvnflinger.OpenLayer(layer_id); | 722 | if (!nvnflinger.OpenLayer(layer_id)) { |
| 723 | LOG_WARNING(Service_VI, "Tried to open layer which was already open"); | ||
| 724 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 725 | rb.Push(ResultOperationFailed); | ||
| 726 | return; | ||
| 727 | } | ||
| 723 | 728 | ||
| 724 | android::OutputParcel parcel; | 729 | android::OutputParcel parcel; |
| 725 | parcel.WriteInterface(NativeWindow{*buffer_queue_id}); | 730 | parcel.WriteInterface(NativeWindow{*buffer_queue_id}); |
| @@ -737,7 +742,12 @@ private: | |||
| 737 | 742 | ||
| 738 | LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}", layer_id); | 743 | LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}", layer_id); |
| 739 | 744 | ||
| 740 | nvnflinger.CloseLayer(layer_id); | 745 | if (!nvnflinger.CloseLayer(layer_id)) { |
| 746 | LOG_WARNING(Service_VI, "Tried to close layer which was not open"); | ||
| 747 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 748 | rb.Push(ResultOperationFailed); | ||
| 749 | return; | ||
| 750 | } | ||
| 741 | 751 | ||
| 742 | IPC::ResponseBuilder rb{ctx, 2}; | 752 | IPC::ResponseBuilder rb{ctx, 2}; |
| 743 | rb.Push(ResultSuccess); | 753 | rb.Push(ResultSuccess); |