summaryrefslogtreecommitdiffstats
path: root/src/core/hle/service
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/service')
-rw-r--r--src/core/hle/service/audio/audren_u.cpp2
-rw-r--r--src/core/hle/service/filesystem/filesystem.h7
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.cpp18
-rw-r--r--src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp35
-rw-r--r--src/core/hle/service/nvnflinger/buffer_queue_core.cpp4
-rw-r--r--src/core/hle/service/nvnflinger/buffer_slot.h1
-rw-r--r--src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp3
-rw-r--r--src/core/hle/service/nvnflinger/nvnflinger.cpp42
-rw-r--r--src/core/hle/service/nvnflinger/nvnflinger.h11
-rw-r--r--src/core/hle/service/set/appln_settings.h1
-rw-r--r--src/core/hle/service/set/device_settings.h1
-rw-r--r--src/core/hle/service/vi/display/vi_display.cpp25
-rw-r--r--src/core/hle/service/vi/display/vi_display.h15
-rw-r--r--src/core/hle/service/vi/layer/vi_layer.cpp4
-rw-r--r--src/core/hle/service/vi/layer/vi_layer.h13
-rw-r--r--src/core/hle/service/vi/vi.cpp3
16 files changed, 131 insertions, 54 deletions
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index 2f09cade5..23e56c77a 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -359,7 +359,7 @@ private:
void GetActiveChannelCount(HLERequestContext& ctx) {
const auto& sink{system.AudioCore().GetOutputSink()};
- u32 channel_count{sink.GetDeviceChannels()};
+ u32 channel_count{sink.GetSystemChannels()};
LOG_DEBUG(Service_Audio, "(STUBBED) called. Channels={}", channel_count);
diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h
index e7e7c4c28..276d264e1 100644
--- a/src/core/hle/service/filesystem/filesystem.h
+++ b/src/core/hle/service/filesystem/filesystem.h
@@ -54,6 +54,13 @@ enum class ImageDirectoryId : u32 {
SdCard,
};
+enum class OpenDirectoryMode : u64 {
+ Directory = (1 << 0),
+ File = (1 << 1),
+ All = Directory | File
+};
+DECLARE_ENUM_FLAG_OPERATORS(OpenDirectoryMode);
+
class FileSystemController {
public:
explicit FileSystemController(Core::System& system_);
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp
index b1310d6e4..82ecc1b90 100644
--- a/src/core/hle/service/filesystem/fsp_srv.cpp
+++ b/src/core/hle/service/filesystem/fsp_srv.cpp
@@ -259,7 +259,7 @@ static void BuildEntryIndex(std::vector<FileSys::Entry>& entries, const std::vec
class IDirectory final : public ServiceFramework<IDirectory> {
public:
- explicit IDirectory(Core::System& system_, FileSys::VirtualDir backend_)
+ explicit IDirectory(Core::System& system_, FileSys::VirtualDir backend_, OpenDirectoryMode mode)
: ServiceFramework{system_, "IDirectory"}, backend(std::move(backend_)) {
static const FunctionInfo functions[] = {
{0, &IDirectory::Read, "Read"},
@@ -269,8 +269,12 @@ public:
// TODO(DarkLordZach): Verify that this is the correct behavior.
// Build entry index now to save time later.
- BuildEntryIndex(entries, backend->GetFiles(), FileSys::EntryType::File);
- BuildEntryIndex(entries, backend->GetSubdirectories(), FileSys::EntryType::Directory);
+ if (True(mode & OpenDirectoryMode::Directory)) {
+ BuildEntryIndex(entries, backend->GetSubdirectories(), FileSys::EntryType::Directory);
+ }
+ if (True(mode & OpenDirectoryMode::File)) {
+ BuildEntryIndex(entries, backend->GetFiles(), FileSys::EntryType::File);
+ }
}
private:
@@ -446,11 +450,9 @@ public:
const auto file_buffer = ctx.ReadBuffer();
const std::string name = Common::StringFromBuffer(file_buffer);
+ const auto mode = rp.PopRaw<OpenDirectoryMode>();
- // TODO(Subv): Implement this filter.
- const u32 filter_flags = rp.Pop<u32>();
-
- LOG_DEBUG(Service_FS, "called. directory={}, filter={}", name, filter_flags);
+ LOG_DEBUG(Service_FS, "called. directory={}, mode={}", name, mode);
FileSys::VirtualDir vfs_dir{};
auto result = backend.OpenDirectory(&vfs_dir, name);
@@ -460,7 +462,7 @@ public:
return;
}
- auto directory = std::make_shared<IDirectory>(system, vfs_dir);
+ auto directory = std::make_shared<IDirectory>(system, vfs_dir, mode);
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
diff --git a/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp b/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp
index d91886bed..bbe8e06d4 100644
--- a/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp
+++ b/src/core/hle/service/nvnflinger/buffer_queue_consumer.cpp
@@ -90,6 +90,18 @@ Status BufferQueueConsumer::AcquireBuffer(BufferItem* out_buffer,
LOG_DEBUG(Service_Nvnflinger, "acquiring slot={}", slot);
+ // If the front buffer is still being tracked, update its slot state
+ if (core->StillTracking(*front)) {
+ slots[slot].acquire_called = true;
+ slots[slot].needs_cleanup_on_release = false;
+ slots[slot].buffer_state = BufferState::Acquired;
+
+ // TODO: for now, avoid resetting the fence, so that when we next return this
+ // slot to the producer, it will wait for the fence to pass. We should fix this
+ // by properly waiting for the fence in the BufferItemConsumer.
+ // slots[slot].fence = Fence::NoFence();
+ }
+
// If the buffer has previously been acquired by the consumer, set graphic_buffer to nullptr to
// avoid unnecessarily remapping this buffer on the consumer side.
if (out_buffer->acquire_called) {
@@ -132,11 +144,28 @@ Status BufferQueueConsumer::ReleaseBuffer(s32 slot, u64 frame_number, const Fenc
++current;
}
- slots[slot].buffer_state = BufferState::Free;
+ if (slots[slot].buffer_state == BufferState::Acquired) {
+ // TODO: for now, avoid resetting the fence, so that when we next return this
+ // slot to the producer, it can wait for its own fence to pass. We should fix this
+ // by properly waiting for the fence in the BufferItemConsumer.
+ // slots[slot].fence = release_fence;
+ slots[slot].buffer_state = BufferState::Free;
- listener = core->connected_producer_listener;
+ listener = core->connected_producer_listener;
- LOG_DEBUG(Service_Nvnflinger, "releasing slot {}", slot);
+ LOG_DEBUG(Service_Nvnflinger, "releasing slot {}", slot);
+ } else if (slots[slot].needs_cleanup_on_release) {
+ LOG_DEBUG(Service_Nvnflinger, "releasing a stale buffer slot {} (state = {})", slot,
+ slots[slot].buffer_state);
+ slots[slot].needs_cleanup_on_release = false;
+ return Status::StaleBufferSlot;
+ } else {
+ LOG_ERROR(Service_Nvnflinger,
+ "attempted to release buffer slot {} but its state was {}", slot,
+ slots[slot].buffer_state);
+
+ return Status::BadValue;
+ }
core->SignalDequeueCondition();
}
diff --git a/src/core/hle/service/nvnflinger/buffer_queue_core.cpp b/src/core/hle/service/nvnflinger/buffer_queue_core.cpp
index 4ed5e5978..5d8c861fa 100644
--- a/src/core/hle/service/nvnflinger/buffer_queue_core.cpp
+++ b/src/core/hle/service/nvnflinger/buffer_queue_core.cpp
@@ -74,6 +74,10 @@ void BufferQueueCore::FreeBufferLocked(s32 slot) {
slots[slot].graphic_buffer.reset();
+ if (slots[slot].buffer_state == BufferState::Acquired) {
+ slots[slot].needs_cleanup_on_release = true;
+ }
+
slots[slot].buffer_state = BufferState::Free;
slots[slot].frame_number = UINT32_MAX;
slots[slot].acquire_called = false;
diff --git a/src/core/hle/service/nvnflinger/buffer_slot.h b/src/core/hle/service/nvnflinger/buffer_slot.h
index d25bca049..37daca78b 100644
--- a/src/core/hle/service/nvnflinger/buffer_slot.h
+++ b/src/core/hle/service/nvnflinger/buffer_slot.h
@@ -31,6 +31,7 @@ struct BufferSlot final {
u64 frame_number{};
Fence fence;
bool acquire_called{};
+ bool needs_cleanup_on_release{};
bool attached_by_consumer{};
bool is_preallocated{};
};
diff --git a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp
index 75bf31e32..2fef6cc1a 100644
--- a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp
+++ b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp
@@ -204,8 +204,9 @@ Result FbShareBufferManager::Initialize(u64* out_buffer_id, u64* out_layer_id, u
// Record the 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_flinger.OpenLayer(m_layer_id);
// Set up the buffer.
m_buffer_id = m_next_buffer_id++;
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.cpp b/src/core/hle/service/nvnflinger/nvnflinger.cpp
index 0745434c5..6352b09a9 100644
--- a/src/core/hle/service/nvnflinger/nvnflinger.cpp
+++ b/src/core/hle/service/nvnflinger/nvnflinger.cpp
@@ -176,17 +176,37 @@ void Nvnflinger::CreateLayerAtId(VI::Display& display, u64 layer_id) {
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) {
const auto lock_guard = Lock();
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) {
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) {
return std::nullopt;
@@ -240,24 +260,6 @@ VI::Layer* Nvnflinger::FindLayer(u64 display_id, u64 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() {
for (auto& display : displays) {
// Trigger vsync for this display at the end of drawing
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.h b/src/core/hle/service/nvnflinger/nvnflinger.h
index f5d73acdb..871285764 100644
--- a/src/core/hle/service/nvnflinger/nvnflinger.h
+++ b/src/core/hle/service/nvnflinger/nvnflinger.h
@@ -73,9 +73,15 @@ public:
/// If an invalid display ID is specified, then an empty optional is returned.
[[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.
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.
///
/// 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.
[[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.
void CreateLayerAtId(VI::Display& display, u64 layer_id);
diff --git a/src/core/hle/service/set/appln_settings.h b/src/core/hle/service/set/appln_settings.h
index b07df0ee7..126375860 100644
--- a/src/core/hle/service/set/appln_settings.h
+++ b/src/core/hle/service/set/appln_settings.h
@@ -4,6 +4,7 @@
#pragma once
#include <array>
+#include <cstddef>
#include "common/common_types.h"
diff --git a/src/core/hle/service/set/device_settings.h b/src/core/hle/service/set/device_settings.h
index b6cfe04f2..f291d0ebe 100644
--- a/src/core/hle/service/set/device_settings.h
+++ b/src/core/hle/service/set/device_settings.h
@@ -4,6 +4,7 @@
#pragma once
#include <array>
+#include <cstddef>
#include "common/common_types.h"
diff --git a/src/core/hle/service/vi/display/vi_display.cpp b/src/core/hle/service/vi/display/vi_display.cpp
index d30f49877..71ce9be50 100644
--- a/src/core/hle/service/vi/display/vi_display.cpp
+++ b/src/core/hle/service/vi/display/vi_display.cpp
@@ -51,11 +51,24 @@ Display::~Display() {
}
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 {
- return *layers.at(index);
+size_t Display::GetNumLayers() const {
+ return std::ranges::count_if(layers, [](auto& l) { return l->IsOpen(); });
}
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));
}
-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,
[layer_id](const auto& layer) { return layer->GetLayerId() == layer_id; });
}
diff --git a/src/core/hle/service/vi/display/vi_display.h b/src/core/hle/service/vi/display/vi_display.h
index 101cbce20..1d9360b96 100644
--- a/src/core/hle/service/vi/display/vi_display.h
+++ b/src/core/hle/service/vi/display/vi_display.h
@@ -66,18 +66,13 @@ public:
/// Whether or not this display has any layers added to it.
bool HasLayers() const {
- return !layers.empty();
+ return GetNumLayers() > 0;
}
/// Gets a layer for this display based off an index.
Layer& GetLayer(std::size_t index);
- /// Gets a layer for this display based off an index.
- const Layer& GetLayer(std::size_t index) const;
-
- std::size_t GetNumLayers() const {
- return layers.size();
- }
+ std::size_t GetNumLayers() const;
/**
* Gets the internal vsync event.
@@ -100,11 +95,11 @@ public:
///
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.
void Reset() {
diff --git a/src/core/hle/service/vi/layer/vi_layer.cpp b/src/core/hle/service/vi/layer/vi_layer.cpp
index 9ae2e0e44..04e52a23b 100644
--- a/src/core/hle/service/vi/layer/vi_layer.cpp
+++ b/src/core/hle/service/vi/layer/vi_layer.cpp
@@ -8,8 +8,8 @@ namespace Service::VI {
Layer::Layer(u64 layer_id_, u32 binder_id_, android::BufferQueueCore& core_,
android::BufferQueueProducer& binder_,
std::shared_ptr<android::BufferItemConsumer>&& consumer_)
- : layer_id{layer_id_}, binder_id{binder_id_}, core{core_}, binder{binder_}, consumer{std::move(
- consumer_)} {}
+ : layer_id{layer_id_}, binder_id{binder_id_}, core{core_}, binder{binder_},
+ consumer{std::move(consumer_)}, open{false} {}
Layer::~Layer() = default;
diff --git a/src/core/hle/service/vi/layer/vi_layer.h b/src/core/hle/service/vi/layer/vi_layer.h
index 8cf1b5275..295005e23 100644
--- a/src/core/hle/service/vi/layer/vi_layer.h
+++ b/src/core/hle/service/vi/layer/vi_layer.h
@@ -71,12 +71,25 @@ public:
return core;
}
+ bool IsOpen() const {
+ return open;
+ }
+
+ void Close() {
+ open = false;
+ }
+
+ void Open() {
+ open = true;
+ }
+
private:
const u64 layer_id;
const u32 binder_id;
android::BufferQueueCore& core;
android::BufferQueueProducer& binder;
std::shared_ptr<android::BufferItemConsumer> consumer;
+ bool open;
};
} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index b1bfb9898..9ab8788e3 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -719,6 +719,8 @@ private:
return;
}
+ nv_flinger.OpenLayer(layer_id);
+
android::OutputParcel parcel;
parcel.WriteInterface(NativeWindow{*buffer_queue_id});
@@ -783,6 +785,7 @@ private:
const u64 layer_id = rp.Pop<u64>();
LOG_WARNING(Service_VI, "(STUBBED) called. layer_id=0x{:016X}", layer_id);
+ nv_flinger.DestroyLayer(layer_id);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);