forked from suyu/suyu
Merge pull request #12331 from liamwhite/layer-confusion
vi: fix confusion between closing and destroying layers
This commit is contained in:
commit
4bf1f217ae
8 changed files with 74 additions and 42 deletions
|
@ -204,8 +204,9 @@ Result FbShareBufferManager::Initialize(u64* out_buffer_id, u64* out_layer_id, u
|
||||||
// Record the display id.
|
// Record the display id.
|
||||||
m_display_id = display_id;
|
m_display_id = display_id;
|
||||||
|
|
||||||
// Create a layer for the display.
|
// Create and open a layer for the display.
|
||||||
m_layer_id = m_flinger.CreateLayer(m_display_id).value();
|
m_layer_id = m_flinger.CreateLayer(m_display_id).value();
|
||||||
|
m_flinger.OpenLayer(m_layer_id);
|
||||||
|
|
||||||
// Set up the buffer.
|
// Set up the buffer.
|
||||||
m_buffer_id = m_next_buffer_id++;
|
m_buffer_id = m_next_buffer_id++;
|
||||||
|
|
|
@ -176,17 +176,37 @@ 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) {
|
||||||
|
const auto lock_guard = Lock();
|
||||||
|
|
||||||
|
for (auto& display : displays) {
|
||||||
|
if (auto* layer = display.FindLayer(layer_id); layer) {
|
||||||
|
layer->Open();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Nvnflinger::CloseLayer(u64 layer_id) {
|
void Nvnflinger::CloseLayer(u64 layer_id) {
|
||||||
const auto lock_guard = Lock();
|
const auto lock_guard = Lock();
|
||||||
|
|
||||||
for (auto& display : displays) {
|
for (auto& display : displays) {
|
||||||
display.CloseLayer(layer_id);
|
if (auto* layer = display.FindLayer(layer_id); layer) {
|
||||||
|
layer->Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Nvnflinger::DestroyLayer(u64 layer_id) {
|
||||||
|
const auto lock_guard = Lock();
|
||||||
|
|
||||||
|
for (auto& display : displays) {
|
||||||
|
display.DestroyLayer(layer_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<u32> Nvnflinger::FindBufferQueueId(u64 display_id, u64 layer_id) {
|
std::optional<u32> Nvnflinger::FindBufferQueueId(u64 display_id, u64 layer_id) {
|
||||||
const auto lock_guard = Lock();
|
const auto lock_guard = Lock();
|
||||||
const auto* const layer = FindOrCreateLayer(display_id, layer_id);
|
const auto* const layer = FindLayer(display_id, layer_id);
|
||||||
|
|
||||||
if (layer == nullptr) {
|
if (layer == nullptr) {
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
@ -240,24 +260,6 @@ VI::Layer* Nvnflinger::FindLayer(u64 display_id, u64 layer_id) {
|
||||||
return display->FindLayer(layer_id);
|
return display->FindLayer(layer_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
VI::Layer* Nvnflinger::FindOrCreateLayer(u64 display_id, u64 layer_id) {
|
|
||||||
auto* const display = FindDisplay(display_id);
|
|
||||||
|
|
||||||
if (display == nullptr) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* layer = display->FindLayer(layer_id);
|
|
||||||
|
|
||||||
if (layer == nullptr) {
|
|
||||||
LOG_DEBUG(Service_Nvnflinger, "Layer at id {} not found. Trying to create it.", layer_id);
|
|
||||||
CreateLayerAtId(*display, layer_id);
|
|
||||||
return display->FindLayer(layer_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return layer;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Nvnflinger::Compose() {
|
void Nvnflinger::Compose() {
|
||||||
for (auto& display : displays) {
|
for (auto& display : displays) {
|
||||||
// Trigger vsync for this display at the end of drawing
|
// Trigger vsync for this display at the end of drawing
|
||||||
|
|
|
@ -73,9 +73,15 @@ public:
|
||||||
/// If an invalid display ID is specified, then an empty optional is returned.
|
/// If an invalid display ID is specified, then an empty optional is returned.
|
||||||
[[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.
|
||||||
|
void 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);
|
void CloseLayer(u64 layer_id);
|
||||||
|
|
||||||
|
/// Destroys the given layer ID.
|
||||||
|
void DestroyLayer(u64 layer_id);
|
||||||
|
|
||||||
/// Finds the buffer queue ID of the specified layer in the specified display.
|
/// 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.
|
/// If an invalid display ID or layer ID is provided, then an empty optional is returned.
|
||||||
|
@ -117,11 +123,6 @@ private:
|
||||||
/// Finds the layer identified by the specified ID in the desired display.
|
/// Finds the layer identified by the specified ID in the desired display.
|
||||||
[[nodiscard]] VI::Layer* FindLayer(u64 display_id, u64 layer_id);
|
[[nodiscard]] VI::Layer* FindLayer(u64 display_id, u64 layer_id);
|
||||||
|
|
||||||
/// Finds the layer identified by the specified ID in the desired display,
|
|
||||||
/// or creates the layer if it is not found.
|
|
||||||
/// To be used when the system expects the specified ID to already exist.
|
|
||||||
[[nodiscard]] VI::Layer* FindOrCreateLayer(u64 display_id, u64 layer_id);
|
|
||||||
|
|
||||||
/// Creates a layer with the specified layer ID in the desired display.
|
/// Creates a layer with the specified layer ID in the desired display.
|
||||||
void CreateLayerAtId(VI::Display& display, u64 layer_id);
|
void CreateLayerAtId(VI::Display& display, u64 layer_id);
|
||||||
|
|
||||||
|
|
|
@ -51,11 +51,24 @@ Display::~Display() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Layer& Display::GetLayer(std::size_t index) {
|
Layer& Display::GetLayer(std::size_t index) {
|
||||||
return *layers.at(index);
|
size_t i = 0;
|
||||||
|
for (auto& layer : layers) {
|
||||||
|
if (!layer->IsOpen()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == index) {
|
||||||
|
return *layer;
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
|
||||||
const Layer& Display::GetLayer(std::size_t index) const {
|
size_t Display::GetNumLayers() const {
|
||||||
return *layers.at(index);
|
return std::ranges::count_if(layers, [](auto& l) { return l->IsOpen(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Display::GetVSyncEvent(Kernel::KReadableEvent** out_vsync_event) {
|
Result Display::GetVSyncEvent(Kernel::KReadableEvent** out_vsync_event) {
|
||||||
|
@ -92,7 +105,11 @@ void Display::CreateLayer(u64 layer_id, u32 binder_id,
|
||||||
hos_binder_driver_server.RegisterProducer(std::move(producer));
|
hos_binder_driver_server.RegisterProducer(std::move(producer));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Display::CloseLayer(u64 layer_id) {
|
void Display::DestroyLayer(u64 layer_id) {
|
||||||
|
if (auto* layer = this->FindLayer(layer_id); layer != nullptr) {
|
||||||
|
layer->GetConsumer().Abandon();
|
||||||
|
}
|
||||||
|
|
||||||
std::erase_if(layers,
|
std::erase_if(layers,
|
||||||
[layer_id](const auto& layer) { return layer->GetLayerId() == layer_id; });
|
[layer_id](const auto& layer) { return layer->GetLayerId() == layer_id; });
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,18 +66,13 @@ public:
|
||||||
|
|
||||||
/// Whether or not this display has any layers added to it.
|
/// Whether or not this display has any layers added to it.
|
||||||
bool HasLayers() const {
|
bool HasLayers() const {
|
||||||
return !layers.empty();
|
return GetNumLayers() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a layer for this display based off an index.
|
/// Gets a layer for this display based off an index.
|
||||||
Layer& GetLayer(std::size_t index);
|
Layer& GetLayer(std::size_t index);
|
||||||
|
|
||||||
/// Gets a layer for this display based off an index.
|
std::size_t GetNumLayers() const;
|
||||||
const Layer& GetLayer(std::size_t index) const;
|
|
||||||
|
|
||||||
std::size_t GetNumLayers() const {
|
|
||||||
return layers.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the internal vsync event.
|
* Gets the internal vsync event.
|
||||||
|
@ -100,11 +95,11 @@ public:
|
||||||
///
|
///
|
||||||
void CreateLayer(u64 layer_id, u32 binder_id, Service::Nvidia::NvCore::Container& core);
|
void CreateLayer(u64 layer_id, u32 binder_id, Service::Nvidia::NvCore::Container& core);
|
||||||
|
|
||||||
/// Closes and removes a layer from this display with the given ID.
|
/// Removes a layer from this display with the given ID.
|
||||||
///
|
///
|
||||||
/// @param layer_id The ID assigned to the layer to close.
|
/// @param layer_id The ID assigned to the layer to destroy.
|
||||||
///
|
///
|
||||||
void CloseLayer(u64 layer_id);
|
void DestroyLayer(u64 layer_id);
|
||||||
|
|
||||||
/// Resets the display for a new connection.
|
/// Resets the display for a new connection.
|
||||||
void Reset() {
|
void Reset() {
|
||||||
|
|
|
@ -8,8 +8,8 @@ namespace Service::VI {
|
||||||
Layer::Layer(u64 layer_id_, u32 binder_id_, android::BufferQueueCore& core_,
|
Layer::Layer(u64 layer_id_, u32 binder_id_, android::BufferQueueCore& core_,
|
||||||
android::BufferQueueProducer& binder_,
|
android::BufferQueueProducer& binder_,
|
||||||
std::shared_ptr<android::BufferItemConsumer>&& consumer_)
|
std::shared_ptr<android::BufferItemConsumer>&& consumer_)
|
||||||
: layer_id{layer_id_}, binder_id{binder_id_}, core{core_}, binder{binder_}, consumer{std::move(
|
: layer_id{layer_id_}, binder_id{binder_id_}, core{core_}, binder{binder_},
|
||||||
consumer_)} {}
|
consumer{std::move(consumer_)}, open{false} {}
|
||||||
|
|
||||||
Layer::~Layer() = default;
|
Layer::~Layer() = default;
|
||||||
|
|
||||||
|
|
|
@ -71,12 +71,25 @@ public:
|
||||||
return core;
|
return core;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsOpen() const {
|
||||||
|
return open;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Close() {
|
||||||
|
open = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Open() {
|
||||||
|
open = true;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const u64 layer_id;
|
const u64 layer_id;
|
||||||
const u32 binder_id;
|
const u32 binder_id;
|
||||||
android::BufferQueueCore& core;
|
android::BufferQueueCore& core;
|
||||||
android::BufferQueueProducer& binder;
|
android::BufferQueueProducer& binder;
|
||||||
std::shared_ptr<android::BufferItemConsumer> consumer;
|
std::shared_ptr<android::BufferItemConsumer> consumer;
|
||||||
|
bool open;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::VI
|
} // namespace Service::VI
|
||||||
|
|
|
@ -719,6 +719,8 @@ private:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
nv_flinger.OpenLayer(layer_id);
|
||||||
|
|
||||||
android::OutputParcel parcel;
|
android::OutputParcel parcel;
|
||||||
parcel.WriteInterface(NativeWindow{*buffer_queue_id});
|
parcel.WriteInterface(NativeWindow{*buffer_queue_id});
|
||||||
|
|
||||||
|
@ -783,6 +785,7 @@ private:
|
||||||
const u64 layer_id = rp.Pop<u64>();
|
const u64 layer_id = rp.Pop<u64>();
|
||||||
|
|
||||||
LOG_WARNING(Service_VI, "(STUBBED) called. layer_id=0x{:016X}", layer_id);
|
LOG_WARNING(Service_VI, "(STUBBED) called. layer_id=0x{:016X}", layer_id);
|
||||||
|
nv_flinger.DestroyLayer(layer_id);
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2};
|
IPC::ResponseBuilder rb{ctx, 2};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
|
Loading…
Reference in a new issue