summaryrefslogtreecommitdiff
path: root/src/core/hle/service/vi
diff options
context:
space:
mode:
authorGravatar Liam2024-02-14 16:29:24 -0500
committerGravatar Liam2024-02-17 18:01:41 -0500
commitdcce9837d240fa2492f29e5ae2649085ae8f711c (patch)
tree8a93012b952276e29fa63490b4183a57cf346878 /src/core/hle/service/vi
parentnvnflinger: convert to process (diff)
downloadyuzu-dcce9837d240fa2492f29e5ae2649085ae8f711c.tar.gz
yuzu-dcce9837d240fa2492f29e5ae2649085ae8f711c.tar.xz
yuzu-dcce9837d240fa2492f29e5ae2649085ae8f711c.zip
vi: move shared buffer management from nvnflinger
Diffstat (limited to 'src/core/hle/service/vi')
-rw-r--r--src/core/hle/service/vi/application_display_service.cpp8
-rw-r--r--src/core/hle/service/vi/application_display_service.h9
-rw-r--r--src/core/hle/service/vi/application_root_service.cpp8
-rw-r--r--src/core/hle/service/vi/application_root_service.h5
-rw-r--r--src/core/hle/service/vi/fbshare_buffer_manager.cpp447
-rw-r--r--src/core/hle/service/vi/fbshare_buffer_manager.h83
-rw-r--r--src/core/hle/service/vi/manager_root_service.cpp9
-rw-r--r--src/core/hle/service/vi/manager_root_service.h7
-rw-r--r--src/core/hle/service/vi/service_creator.cpp5
-rw-r--r--src/core/hle/service/vi/service_creator.h4
-rw-r--r--src/core/hle/service/vi/system_display_service.cpp22
-rw-r--r--src/core/hle/service/vi/system_display_service.h10
-rw-r--r--src/core/hle/service/vi/system_root_service.cpp8
-rw-r--r--src/core/hle/service/vi/system_root_service.h5
-rw-r--r--src/core/hle/service/vi/vi.cpp16
15 files changed, 609 insertions, 37 deletions
diff --git a/src/core/hle/service/vi/application_display_service.cpp b/src/core/hle/service/vi/application_display_service.cpp
index a6e04bf60..9c009f902 100644
--- a/src/core/hle/service/vi/application_display_service.cpp
+++ b/src/core/hle/service/vi/application_display_service.cpp
@@ -13,10 +13,12 @@
13namespace Service::VI { 13namespace Service::VI {
14 14
15IApplicationDisplayService::IApplicationDisplayService( 15IApplicationDisplayService::IApplicationDisplayService(
16 Core::System& system_, std::shared_ptr<Nvnflinger::IHOSBinderDriver> binder_service) 16 Core::System& system_, std::shared_ptr<Nvnflinger::IHOSBinderDriver> binder_service,
17 std::shared_ptr<FbshareBufferManager> shared_buffer_manager)
17 : ServiceFramework{system_, "IApplicationDisplayService"}, 18 : ServiceFramework{system_, "IApplicationDisplayService"},
18 m_binder_service{std::move(binder_service)}, 19 m_binder_service{std::move(binder_service)},
19 m_surface_flinger{m_binder_service->GetSurfaceFlinger()} { 20 m_surface_flinger{m_binder_service->GetSurfaceFlinger()},
21 m_shared_buffer_manager{std::move(shared_buffer_manager)} {
20 22
21 // clang-format off 23 // clang-format off
22 static const FunctionInfo functions[] = { 24 static const FunctionInfo functions[] = {
@@ -64,7 +66,7 @@ Result IApplicationDisplayService::GetSystemDisplayService(
64 Out<SharedPointer<ISystemDisplayService>> out_system_display_service) { 66 Out<SharedPointer<ISystemDisplayService>> out_system_display_service) {
65 LOG_WARNING(Service_VI, "(STUBBED) called"); 67 LOG_WARNING(Service_VI, "(STUBBED) called");
66 *out_system_display_service = 68 *out_system_display_service =
67 std::make_shared<ISystemDisplayService>(system, m_surface_flinger); 69 std::make_shared<ISystemDisplayService>(system, m_surface_flinger, m_shared_buffer_manager);
68 R_SUCCEED(); 70 R_SUCCEED();
69} 71}
70 72
diff --git a/src/core/hle/service/vi/application_display_service.h b/src/core/hle/service/vi/application_display_service.h
index e56490f9f..5022b2f63 100644
--- a/src/core/hle/service/vi/application_display_service.h
+++ b/src/core/hle/service/vi/application_display_service.h
@@ -16,15 +16,21 @@ class IHOSBinderDriver;
16 16
17namespace Service::VI { 17namespace Service::VI {
18 18
19class FbshareBufferManager;
19class IManagerDisplayService; 20class IManagerDisplayService;
20class ISystemDisplayService; 21class ISystemDisplayService;
21 22
22class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> { 23class IApplicationDisplayService final : public ServiceFramework<IApplicationDisplayService> {
23public: 24public:
24 IApplicationDisplayService(Core::System& system_, 25 IApplicationDisplayService(Core::System& system_,
25 std::shared_ptr<Nvnflinger::IHOSBinderDriver> binder_service); 26 std::shared_ptr<Nvnflinger::IHOSBinderDriver> binder_service,
27 std::shared_ptr<FbshareBufferManager> shared_buffer_manager);
26 ~IApplicationDisplayService() override; 28 ~IApplicationDisplayService() override;
27 29
30 std::shared_ptr<FbshareBufferManager> GetSharedBufferManager() const {
31 return m_shared_buffer_manager;
32 }
33
28private: 34private:
29 Result GetRelayService(Out<SharedPointer<Nvnflinger::IHOSBinderDriver>> out_relay_service); 35 Result GetRelayService(Out<SharedPointer<Nvnflinger::IHOSBinderDriver>> out_relay_service);
30 Result GetSystemDisplayService( 36 Result GetSystemDisplayService(
@@ -62,6 +68,7 @@ private:
62private: 68private:
63 const std::shared_ptr<Nvnflinger::IHOSBinderDriver> m_binder_service; 69 const std::shared_ptr<Nvnflinger::IHOSBinderDriver> m_binder_service;
64 const std::shared_ptr<Nvnflinger::Nvnflinger> m_surface_flinger; 70 const std::shared_ptr<Nvnflinger::Nvnflinger> m_surface_flinger;
71 const std::shared_ptr<FbshareBufferManager> m_shared_buffer_manager;
65 std::vector<u64> m_stray_layer_ids; 72 std::vector<u64> m_stray_layer_ids;
66 bool m_vsync_event_fetched{false}; 73 bool m_vsync_event_fetched{false};
67}; 74};
diff --git a/src/core/hle/service/vi/application_root_service.cpp b/src/core/hle/service/vi/application_root_service.cpp
index 501fbdd6a..ed8c9b1b3 100644
--- a/src/core/hle/service/vi/application_root_service.cpp
+++ b/src/core/hle/service/vi/application_root_service.cpp
@@ -11,8 +11,10 @@
11namespace Service::VI { 11namespace Service::VI {
12 12
13IApplicationRootService::IApplicationRootService( 13IApplicationRootService::IApplicationRootService(
14 Core::System& system_, std::shared_ptr<Nvnflinger::IHOSBinderDriver> binder_service) 14 Core::System& system_, std::shared_ptr<Nvnflinger::IHOSBinderDriver> binder_service,
15 : ServiceFramework{system_, "vi:u"}, m_binder_service{std::move(binder_service)} { 15 std::shared_ptr<FbshareBufferManager> shared_buffer_manager)
16 : ServiceFramework{system_, "vi:u"}, m_binder_service{std::move(binder_service)},
17 m_shared_buffer_manager{std::move(shared_buffer_manager)} {
16 static const FunctionInfo functions[] = { 18 static const FunctionInfo functions[] = {
17 {0, C<&IApplicationRootService::GetDisplayService>, "GetDisplayService"}, 19 {0, C<&IApplicationRootService::GetDisplayService>, "GetDisplayService"},
18 {1, nullptr, "GetDisplayServiceWithProxyNameExchange"}, 20 {1, nullptr, "GetDisplayServiceWithProxyNameExchange"},
@@ -26,7 +28,7 @@ Result IApplicationRootService::GetDisplayService(
26 Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, Policy policy) { 28 Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, Policy policy) {
27 LOG_DEBUG(Service_VI, "called"); 29 LOG_DEBUG(Service_VI, "called");
28 R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_binder_service, 30 R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_binder_service,
29 Permission::User, policy)); 31 m_shared_buffer_manager, Permission::User, policy));
30} 32}
31 33
32} // namespace Service::VI 34} // namespace Service::VI
diff --git a/src/core/hle/service/vi/application_root_service.h b/src/core/hle/service/vi/application_root_service.h
index d1f023e9e..5970b6e68 100644
--- a/src/core/hle/service/vi/application_root_service.h
+++ b/src/core/hle/service/vi/application_root_service.h
@@ -16,13 +16,15 @@ class IHOSBinderDriver;
16 16
17namespace Service::VI { 17namespace Service::VI {
18 18
19class FbshareBufferManager;
19class IApplicationDisplayService; 20class IApplicationDisplayService;
20enum class Policy : u32; 21enum class Policy : u32;
21 22
22class IApplicationRootService final : public ServiceFramework<IApplicationRootService> { 23class IApplicationRootService final : public ServiceFramework<IApplicationRootService> {
23public: 24public:
24 explicit IApplicationRootService(Core::System& system_, 25 explicit IApplicationRootService(Core::System& system_,
25 std::shared_ptr<Nvnflinger::IHOSBinderDriver> binder_service); 26 std::shared_ptr<Nvnflinger::IHOSBinderDriver> binder_service,
27 std::shared_ptr<FbshareBufferManager> shared_buffer_manager);
26 ~IApplicationRootService() override; 28 ~IApplicationRootService() override;
27 29
28private: 30private:
@@ -32,6 +34,7 @@ private:
32 34
33private: 35private:
34 const std::shared_ptr<Nvnflinger::IHOSBinderDriver> m_binder_service; 36 const std::shared_ptr<Nvnflinger::IHOSBinderDriver> m_binder_service;
37 const std::shared_ptr<FbshareBufferManager> m_shared_buffer_manager;
35}; 38};
36 39
37} // namespace Service::VI 40} // namespace Service::VI
diff --git a/src/core/hle/service/vi/fbshare_buffer_manager.cpp b/src/core/hle/service/vi/fbshare_buffer_manager.cpp
new file mode 100644
index 000000000..e61c02e1c
--- /dev/null
+++ b/src/core/hle/service/vi/fbshare_buffer_manager.cpp
@@ -0,0 +1,447 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include <random>
5
6#include "core/core.h"
7#include "core/hle/kernel/k_process.h"
8#include "core/hle/kernel/k_system_resource.h"
9#include "core/hle/service/nvdrv/devices/nvmap.h"
10#include "core/hle/service/nvdrv/nvdrv.h"
11#include "core/hle/service/nvnflinger/buffer_queue_producer.h"
12#include "core/hle/service/nvnflinger/pixel_format.h"
13#include "core/hle/service/nvnflinger/ui/graphic_buffer.h"
14#include "core/hle/service/vi/fbshare_buffer_manager.h"
15#include "core/hle/service/vi/layer/vi_layer.h"
16#include "core/hle/service/vi/vi_results.h"
17#include "video_core/gpu.h"
18#include "video_core/host1x/host1x.h"
19
20namespace Service::VI {
21
22namespace {
23
24Result AllocateSharedBufferMemory(std::unique_ptr<Kernel::KPageGroup>* out_page_group,
25 Core::System& system, u32 size) {
26 using Core::Memory::YUZU_PAGESIZE;
27
28 // Allocate memory for the system shared buffer.
29 auto& kernel = system.Kernel();
30
31 // Hold a temporary page group reference while we try to map it.
32 auto pg = std::make_unique<Kernel::KPageGroup>(
33 kernel, std::addressof(kernel.GetSystemSystemResource().GetBlockInfoManager()));
34
35 // Allocate memory from secure pool.
36 R_TRY(kernel.MemoryManager().AllocateAndOpen(
37 pg.get(), size / YUZU_PAGESIZE,
38 Kernel::KMemoryManager::EncodeOption(Kernel::KMemoryManager::Pool::Secure,
39 Kernel::KMemoryManager::Direction::FromBack)));
40
41 // Fill the output data with red.
42 for (auto& block : *pg) {
43 u32* start = system.DeviceMemory().GetPointer<u32>(block.GetAddress());
44 u32* end = system.DeviceMemory().GetPointer<u32>(block.GetAddress() + block.GetSize());
45
46 for (; start < end; start++) {
47 *start = 0xFF0000FF;
48 }
49 }
50
51 // Return the mapped page group.
52 *out_page_group = std::move(pg);
53
54 // We succeeded.
55 R_SUCCEED();
56}
57
58Result MapSharedBufferIntoProcessAddressSpace(Common::ProcessAddress* out_map_address,
59 std::unique_ptr<Kernel::KPageGroup>& pg,
60 Kernel::KProcess* process, Core::System& system) {
61 using Core::Memory::YUZU_PAGESIZE;
62
63 auto& page_table = process->GetPageTable();
64
65 // Get bounds of where mapping is possible.
66 const VAddr alias_code_begin = GetInteger(page_table.GetAliasCodeRegionStart());
67 const VAddr alias_code_size = page_table.GetAliasCodeRegionSize() / YUZU_PAGESIZE;
68 const auto state = Kernel::KMemoryState::IoMemory;
69 const auto perm = Kernel::KMemoryPermission::UserReadWrite;
70 std::mt19937_64 rng{process->GetRandomEntropy(0)};
71
72 // Retry up to 64 times to map into alias code range.
73 Result res = ResultSuccess;
74 int i;
75 for (i = 0; i < 64; i++) {
76 *out_map_address = alias_code_begin + ((rng() % alias_code_size) * YUZU_PAGESIZE);
77 res = page_table.MapPageGroup(*out_map_address, *pg, state, perm);
78 if (R_SUCCEEDED(res)) {
79 break;
80 }
81 }
82
83 // Return failure, if necessary
84 R_UNLESS(i < 64, res);
85
86 // We succeeded.
87 R_SUCCEED();
88}
89
90Result CreateNvMapHandle(u32* out_nv_map_handle, Nvidia::Devices::nvmap& nvmap, u32 size) {
91 // Create a handle.
92 Nvidia::Devices::nvmap::IocCreateParams create_params{
93 .size = size,
94 .handle = 0,
95 };
96 R_UNLESS(nvmap.IocCreate(create_params) == Nvidia::NvResult::Success,
97 VI::ResultOperationFailed);
98
99 // Assign the output handle.
100 *out_nv_map_handle = create_params.handle;
101
102 // We succeeded.
103 R_SUCCEED();
104}
105
106Result FreeNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle, Nvidia::DeviceFD nvmap_fd) {
107 // Free the handle.
108 Nvidia::Devices::nvmap::IocFreeParams free_params{
109 .handle = handle,
110 };
111 R_UNLESS(nvmap.IocFree(free_params, nvmap_fd) == Nvidia::NvResult::Success,
112 VI::ResultOperationFailed);
113
114 // We succeeded.
115 R_SUCCEED();
116}
117
118Result AllocNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle, Common::ProcessAddress buffer,
119 u32 size, Nvidia::DeviceFD nvmap_fd) {
120 // Assign the allocated memory to the handle.
121 Nvidia::Devices::nvmap::IocAllocParams alloc_params{
122 .handle = handle,
123 .heap_mask = 0,
124 .flags = {},
125 .align = 0,
126 .kind = 0,
127 .address = GetInteger(buffer),
128 };
129 R_UNLESS(nvmap.IocAlloc(alloc_params, nvmap_fd) == Nvidia::NvResult::Success,
130 VI::ResultOperationFailed);
131
132 // We succeeded.
133 R_SUCCEED();
134}
135
136Result AllocateHandleForBuffer(u32* out_handle, Nvidia::Module& nvdrv, Nvidia::DeviceFD nvmap_fd,
137 Common::ProcessAddress buffer, u32 size) {
138 // Get the nvmap device.
139 auto nvmap = nvdrv.GetDevice<Nvidia::Devices::nvmap>(nvmap_fd);
140 ASSERT(nvmap != nullptr);
141
142 // Create a handle.
143 R_TRY(CreateNvMapHandle(out_handle, *nvmap, size));
144
145 // Ensure we maintain a clean state on failure.
146 ON_RESULT_FAILURE {
147 R_ASSERT(FreeNvMapHandle(*nvmap, *out_handle, nvmap_fd));
148 };
149
150 // Assign the allocated memory to the handle.
151 R_RETURN(AllocNvMapHandle(*nvmap, *out_handle, buffer, size, nvmap_fd));
152}
153
154void FreeHandle(u32 handle, Nvidia::Module& nvdrv, Nvidia::DeviceFD nvmap_fd) {
155 auto nvmap = nvdrv.GetDevice<Nvidia::Devices::nvmap>(nvmap_fd);
156 ASSERT(nvmap != nullptr);
157
158 R_ASSERT(FreeNvMapHandle(*nvmap, handle, nvmap_fd));
159}
160
161constexpr auto SharedBufferBlockLinearFormat = android::PixelFormat::Rgba8888;
162constexpr u32 SharedBufferBlockLinearBpp = 4;
163
164constexpr u32 SharedBufferBlockLinearWidth = 1280;
165constexpr u32 SharedBufferBlockLinearHeight = 768;
166constexpr u32 SharedBufferBlockLinearStride =
167 SharedBufferBlockLinearWidth * SharedBufferBlockLinearBpp;
168constexpr u32 SharedBufferNumSlots = 7;
169
170constexpr u32 SharedBufferWidth = 1280;
171constexpr u32 SharedBufferHeight = 720;
172constexpr u32 SharedBufferAsync = false;
173
174constexpr u32 SharedBufferSlotSize =
175 SharedBufferBlockLinearWidth * SharedBufferBlockLinearHeight * SharedBufferBlockLinearBpp;
176constexpr u32 SharedBufferSize = SharedBufferSlotSize * SharedBufferNumSlots;
177
178constexpr SharedMemoryPoolLayout SharedBufferPoolLayout = [] {
179 SharedMemoryPoolLayout layout{};
180 layout.num_slots = SharedBufferNumSlots;
181
182 for (u32 i = 0; i < SharedBufferNumSlots; i++) {
183 layout.slots[i].buffer_offset = i * SharedBufferSlotSize;
184 layout.slots[i].size = SharedBufferSlotSize;
185 layout.slots[i].width = SharedBufferWidth;
186 layout.slots[i].height = SharedBufferHeight;
187 }
188
189 return layout;
190}();
191
192void MakeGraphicBuffer(android::BufferQueueProducer& producer, u32 slot, u32 handle) {
193 auto buffer = std::make_shared<android::NvGraphicBuffer>();
194 buffer->width = SharedBufferWidth;
195 buffer->height = SharedBufferHeight;
196 buffer->stride = SharedBufferBlockLinearStride;
197 buffer->format = SharedBufferBlockLinearFormat;
198 buffer->external_format = SharedBufferBlockLinearFormat;
199 buffer->buffer_id = handle;
200 buffer->offset = slot * SharedBufferSlotSize;
201 ASSERT(producer.SetPreallocatedBuffer(slot, buffer) == android::Status::NoError);
202}
203
204} // namespace
205
206FbshareBufferManager::FbshareBufferManager(Core::System& system,
207 std::shared_ptr<Nvnflinger::Nvnflinger> surface_flinger,
208 std::shared_ptr<Nvidia::Module> nvdrv)
209 : m_system(system), m_surface_flinger(std::move(surface_flinger)), m_nvdrv(std::move(nvdrv)) {}
210
211FbshareBufferManager::~FbshareBufferManager() = default;
212
213Result FbshareBufferManager::Initialize(Kernel::KProcess* owner_process, u64* out_buffer_id,
214 u64* out_layer_handle, u64 display_id,
215 Nvnflinger::LayerBlending blending) {
216 std::scoped_lock lk{m_guard};
217
218 // Ensure we haven't already created.
219 const u64 aruid = owner_process->GetProcessId();
220 R_UNLESS(!m_sessions.contains(aruid), VI::ResultPermissionDenied);
221
222 // Allocate memory for the shared buffer if needed.
223 if (!m_buffer_page_group) {
224 R_TRY(AllocateSharedBufferMemory(std::addressof(m_buffer_page_group), m_system,
225 SharedBufferSize));
226
227 // Record buffer id.
228 m_buffer_id = m_next_buffer_id++;
229
230 // Record display id.
231 m_display_id = display_id;
232 }
233
234 // Map into process.
235 Common::ProcessAddress map_address{};
236 R_TRY(MapSharedBufferIntoProcessAddressSpace(std::addressof(map_address), m_buffer_page_group,
237 owner_process, m_system));
238
239 // Create new session.
240 auto [it, was_emplaced] = m_sessions.emplace(aruid, FbshareSession{});
241 auto& session = it->second;
242
243 auto& container = m_nvdrv->GetContainer();
244 session.session_id = container.OpenSession(owner_process);
245 session.nvmap_fd = m_nvdrv->Open("/dev/nvmap", session.session_id);
246
247 // Create an nvmap handle for the buffer and assign the memory to it.
248 R_TRY(AllocateHandleForBuffer(std::addressof(session.buffer_nvmap_handle), *m_nvdrv,
249 session.nvmap_fd, map_address, SharedBufferSize));
250
251 // Create and open a layer for the display.
252 session.layer_id = m_surface_flinger->CreateLayer(m_display_id, blending).value();
253 m_surface_flinger->OpenLayer(session.layer_id);
254
255 // Get the layer.
256 VI::Layer* layer = m_surface_flinger->FindLayer(m_display_id, session.layer_id);
257 ASSERT(layer != nullptr);
258
259 // Get the producer and set preallocated buffers.
260 auto& producer = layer->GetBufferQueue();
261 MakeGraphicBuffer(producer, 0, session.buffer_nvmap_handle);
262 MakeGraphicBuffer(producer, 1, session.buffer_nvmap_handle);
263
264 // Assign outputs.
265 *out_buffer_id = m_buffer_id;
266 *out_layer_handle = session.layer_id;
267
268 // We succeeded.
269 R_SUCCEED();
270}
271
272void FbshareBufferManager::Finalize(Kernel::KProcess* owner_process) {
273 std::scoped_lock lk{m_guard};
274
275 if (m_buffer_id == 0) {
276 return;
277 }
278
279 const u64 aruid = owner_process->GetProcessId();
280 const auto it = m_sessions.find(aruid);
281 if (it == m_sessions.end()) {
282 return;
283 }
284
285 auto& session = it->second;
286
287 // Destroy the layer.
288 m_surface_flinger->DestroyLayer(session.layer_id);
289
290 // Close nvmap handle.
291 FreeHandle(session.buffer_nvmap_handle, *m_nvdrv, session.nvmap_fd);
292
293 // Close nvmap device.
294 m_nvdrv->Close(session.nvmap_fd);
295
296 // Close session.
297 auto& container = m_nvdrv->GetContainer();
298 container.CloseSession(session.session_id);
299
300 // Erase.
301 m_sessions.erase(it);
302}
303
304Result FbshareBufferManager::GetSharedBufferMemoryHandleId(u64* out_buffer_size,
305 s32* out_nvmap_handle,
306 SharedMemoryPoolLayout* out_pool_layout,
307 u64 buffer_id,
308 u64 applet_resource_user_id) {
309 std::scoped_lock lk{m_guard};
310
311 R_UNLESS(m_buffer_id > 0, VI::ResultNotFound);
312 R_UNLESS(buffer_id == m_buffer_id, VI::ResultNotFound);
313 R_UNLESS(m_sessions.contains(applet_resource_user_id), VI::ResultNotFound);
314
315 *out_pool_layout = SharedBufferPoolLayout;
316 *out_buffer_size = SharedBufferSize;
317 *out_nvmap_handle = m_sessions[applet_resource_user_id].buffer_nvmap_handle;
318
319 R_SUCCEED();
320}
321
322Result FbshareBufferManager::GetLayerFromId(VI::Layer** out_layer, u64 layer_id) {
323 // Ensure the layer id is valid.
324 R_UNLESS(layer_id > 0, VI::ResultNotFound);
325
326 // Get the layer.
327 VI::Layer* layer = m_surface_flinger->FindLayer(m_display_id, layer_id);
328 R_UNLESS(layer != nullptr, VI::ResultNotFound);
329
330 // We succeeded.
331 *out_layer = layer;
332 R_SUCCEED();
333}
334
335Result FbshareBufferManager::AcquireSharedFrameBuffer(android::Fence* out_fence,
336 std::array<s32, 4>& out_slot_indexes,
337 s64* out_target_slot, u64 layer_id) {
338 std::scoped_lock lk{m_guard};
339
340 // Get the layer.
341 VI::Layer* layer;
342 R_TRY(this->GetLayerFromId(std::addressof(layer), layer_id));
343
344 // Get the producer.
345 auto& producer = layer->GetBufferQueue();
346
347 // Get the next buffer from the producer.
348 s32 slot;
349 R_UNLESS(producer.DequeueBuffer(std::addressof(slot), out_fence, SharedBufferAsync != 0,
350 SharedBufferWidth, SharedBufferHeight,
351 SharedBufferBlockLinearFormat, 0) == android::Status::NoError,
352 VI::ResultOperationFailed);
353
354 // Assign remaining outputs.
355 *out_target_slot = slot;
356 out_slot_indexes = {0, 1, -1, -1};
357
358 // We succeeded.
359 R_SUCCEED();
360}
361
362Result FbshareBufferManager::PresentSharedFrameBuffer(android::Fence fence,
363 Common::Rectangle<s32> crop_region,
364 u32 transform, s32 swap_interval,
365 u64 layer_id, s64 slot) {
366 std::scoped_lock lk{m_guard};
367
368 // Get the layer.
369 VI::Layer* layer;
370 R_TRY(this->GetLayerFromId(std::addressof(layer), layer_id));
371
372 // Get the producer.
373 auto& producer = layer->GetBufferQueue();
374
375 // Request to queue the buffer.
376 std::shared_ptr<android::GraphicBuffer> buffer;
377 R_UNLESS(producer.RequestBuffer(static_cast<s32>(slot), std::addressof(buffer)) ==
378 android::Status::NoError,
379 VI::ResultOperationFailed);
380
381 ON_RESULT_FAILURE {
382 producer.CancelBuffer(static_cast<s32>(slot), fence);
383 };
384
385 // Queue the buffer to the producer.
386 android::QueueBufferInput input{};
387 android::QueueBufferOutput output{};
388 input.crop = crop_region;
389 input.fence = fence;
390 input.transform = static_cast<android::NativeWindowTransform>(transform);
391 input.swap_interval = swap_interval;
392 R_UNLESS(producer.QueueBuffer(static_cast<s32>(slot), input, std::addressof(output)) ==
393 android::Status::NoError,
394 VI::ResultOperationFailed);
395
396 // We succeeded.
397 R_SUCCEED();
398}
399
400Result FbshareBufferManager::GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event,
401 u64 layer_id) {
402 std::scoped_lock lk{m_guard};
403
404 // Get the layer.
405 VI::Layer* layer;
406 R_TRY(this->GetLayerFromId(std::addressof(layer), layer_id));
407
408 // Get the producer.
409 auto& producer = layer->GetBufferQueue();
410
411 // Set the event.
412 *out_event = std::addressof(producer.GetNativeHandle());
413
414 // We succeeded.
415 R_SUCCEED();
416}
417
418Result FbshareBufferManager::WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index) {
419 std::vector<u8> capture_buffer(m_system.GPU().GetAppletCaptureBuffer());
420 Common::ScratchBuffer<u32> scratch;
421
422 // TODO: this could be optimized
423 s64 e = -1280 * 768 * 4;
424 for (auto& block : *m_buffer_page_group) {
425 u8* start = m_system.DeviceMemory().GetPointer<u8>(block.GetAddress());
426 u8* end = m_system.DeviceMemory().GetPointer<u8>(block.GetAddress() + block.GetSize());
427
428 for (; start < end; start++) {
429 *start = 0;
430
431 if (e >= 0 && e < static_cast<s64>(capture_buffer.size())) {
432 *start = capture_buffer[e];
433 }
434 e++;
435 }
436
437 m_system.GPU().Host1x().MemoryManager().ApplyOpOnPointer(start, scratch, [&](DAddr addr) {
438 m_system.GPU().InvalidateRegion(addr, end - start);
439 });
440 }
441
442 *out_was_written = true;
443 *out_layer_index = 1;
444 R_SUCCEED();
445}
446
447} // namespace Service::VI
diff --git a/src/core/hle/service/vi/fbshare_buffer_manager.h b/src/core/hle/service/vi/fbshare_buffer_manager.h
new file mode 100644
index 000000000..b9e99e61f
--- /dev/null
+++ b/src/core/hle/service/vi/fbshare_buffer_manager.h
@@ -0,0 +1,83 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <map>
7
8#include "common/math_util.h"
9#include "core/hle/service/nvdrv/core/container.h"
10#include "core/hle/service/nvdrv/nvdata.h"
11#include "core/hle/service/nvnflinger/hwc_layer.h"
12#include "core/hle/service/nvnflinger/nvnflinger.h"
13#include "core/hle/service/nvnflinger/ui/fence.h"
14
15namespace Kernel {
16class KPageGroup;
17}
18
19namespace Service::VI {
20
21struct SharedMemorySlot {
22 u64 buffer_offset;
23 u64 size;
24 s32 width;
25 s32 height;
26};
27static_assert(sizeof(SharedMemorySlot) == 0x18, "SharedMemorySlot has wrong size");
28
29struct SharedMemoryPoolLayout {
30 s32 num_slots;
31 std::array<SharedMemorySlot, 0x10> slots;
32};
33static_assert(sizeof(SharedMemoryPoolLayout) == 0x188, "SharedMemoryPoolLayout has wrong size");
34
35struct FbshareSession;
36
37class FbshareBufferManager final {
38public:
39 explicit FbshareBufferManager(Core::System& system,
40 std::shared_ptr<Nvnflinger::Nvnflinger> surface_flinger,
41 std::shared_ptr<Nvidia::Module> nvdrv);
42 ~FbshareBufferManager();
43
44 Result Initialize(Kernel::KProcess* owner_process, u64* out_buffer_id, u64* out_layer_handle,
45 u64 display_id, Nvnflinger::LayerBlending blending);
46 void Finalize(Kernel::KProcess* owner_process);
47
48 Result GetSharedBufferMemoryHandleId(u64* out_buffer_size, s32* out_nvmap_handle,
49 SharedMemoryPoolLayout* out_pool_layout, u64 buffer_id,
50 u64 applet_resource_user_id);
51 Result AcquireSharedFrameBuffer(android::Fence* out_fence, std::array<s32, 4>& out_slots,
52 s64* out_target_slot, u64 layer_id);
53 Result PresentSharedFrameBuffer(android::Fence fence, Common::Rectangle<s32> crop_region,
54 u32 transform, s32 swap_interval, u64 layer_id, s64 slot);
55 Result GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event, u64 layer_id);
56
57 Result WriteAppletCaptureBuffer(bool* out_was_written, s32* out_layer_index);
58
59private:
60 Result GetLayerFromId(VI::Layer** out_layer, u64 layer_id);
61
62private:
63 u64 m_next_buffer_id = 1;
64 u64 m_display_id = 0;
65 u64 m_buffer_id = 0;
66 SharedMemoryPoolLayout m_pool_layout = {};
67 std::map<u64, FbshareSession> m_sessions;
68 std::unique_ptr<Kernel::KPageGroup> m_buffer_page_group;
69
70 std::mutex m_guard;
71 Core::System& m_system;
72 const std::shared_ptr<Nvnflinger::Nvnflinger> m_surface_flinger;
73 const std::shared_ptr<Nvidia::Module> m_nvdrv;
74};
75
76struct FbshareSession {
77 Nvidia::DeviceFD nvmap_fd = {};
78 Nvidia::NvCore::SessionId session_id = {};
79 u64 layer_id = {};
80 u32 buffer_nvmap_handle = 0;
81};
82
83} // namespace Service::VI
diff --git a/src/core/hle/service/vi/manager_root_service.cpp b/src/core/hle/service/vi/manager_root_service.cpp
index 36b84909a..b61f0ecb6 100644
--- a/src/core/hle/service/vi/manager_root_service.cpp
+++ b/src/core/hle/service/vi/manager_root_service.cpp
@@ -2,6 +2,7 @@
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "core/hle/service/cmif_serialization.h" 4#include "core/hle/service/cmif_serialization.h"
5#include "core/hle/service/nvnflinger/hos_binder_driver.h"
5#include "core/hle/service/vi/application_display_service.h" 6#include "core/hle/service/vi/application_display_service.h"
6#include "core/hle/service/vi/manager_root_service.h" 7#include "core/hle/service/vi/manager_root_service.h"
7#include "core/hle/service/vi/service_creator.h" 8#include "core/hle/service/vi/service_creator.h"
@@ -11,8 +12,10 @@
11namespace Service::VI { 12namespace Service::VI {
12 13
13IManagerRootService::IManagerRootService( 14IManagerRootService::IManagerRootService(
14 Core::System& system_, std::shared_ptr<Nvnflinger::IHOSBinderDriver> binder_service) 15 Core::System& system_, std::shared_ptr<Nvnflinger::IHOSBinderDriver> binder_service,
15 : ServiceFramework{system_, "vi:m"}, m_binder_service{std::move(binder_service)} { 16 std::shared_ptr<FbshareBufferManager> shared_buffer_manager)
17 : ServiceFramework{system_, "vi:m"}, m_binder_service{std::move(binder_service)},
18 m_shared_buffer_manager{std::move(shared_buffer_manager)} {
16 static const FunctionInfo functions[] = { 19 static const FunctionInfo functions[] = {
17 {2, C<&IManagerRootService::GetDisplayService>, "GetDisplayService"}, 20 {2, C<&IManagerRootService::GetDisplayService>, "GetDisplayService"},
18 {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, 21 {3, nullptr, "GetDisplayServiceWithProxyNameExchange"},
@@ -30,7 +33,7 @@ Result IManagerRootService::GetDisplayService(
30 Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, Policy policy) { 33 Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, Policy policy) {
31 LOG_DEBUG(Service_VI, "called"); 34 LOG_DEBUG(Service_VI, "called");
32 R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_binder_service, 35 R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_binder_service,
33 Permission::Manager, policy)); 36 m_shared_buffer_manager, Permission::Manager, policy));
34} 37}
35 38
36} // namespace Service::VI 39} // namespace Service::VI
diff --git a/src/core/hle/service/vi/manager_root_service.h b/src/core/hle/service/vi/manager_root_service.h
index 26aa95a88..509445b7b 100644
--- a/src/core/hle/service/vi/manager_root_service.h
+++ b/src/core/hle/service/vi/manager_root_service.h
@@ -16,21 +16,24 @@ class IHOSBinderDriver;
16 16
17namespace Service::VI { 17namespace Service::VI {
18 18
19class FbshareBufferManager;
19class IApplicationDisplayService; 20class IApplicationDisplayService;
20enum class Policy : u32; 21enum class Policy : u32;
21 22
22class IManagerRootService final : public ServiceFramework<IManagerRootService> { 23class IManagerRootService final : public ServiceFramework<IManagerRootService> {
23public: 24public:
24 explicit IManagerRootService(Core::System& system_, 25 explicit IManagerRootService(Core::System& system_,
25 std::shared_ptr<Nvnflinger::IHOSBinderDriver> binder_service); 26 std::shared_ptr<Nvnflinger::IHOSBinderDriver> binder_service,
27 std::shared_ptr<FbshareBufferManager> shared_buffer_manager);
26 ~IManagerRootService() override; 28 ~IManagerRootService() override;
27 29
28private:
29 Result GetDisplayService( 30 Result GetDisplayService(
30 Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, 31 Out<SharedPointer<IApplicationDisplayService>> out_application_display_service,
31 Policy policy); 32 Policy policy);
32 33
34private:
33 const std::shared_ptr<Nvnflinger::IHOSBinderDriver> m_binder_service; 35 const std::shared_ptr<Nvnflinger::IHOSBinderDriver> m_binder_service;
36 const std::shared_ptr<FbshareBufferManager> m_shared_buffer_manager;
34}; 37};
35 38
36} // namespace Service::VI 39} // namespace Service::VI
diff --git a/src/core/hle/service/vi/service_creator.cpp b/src/core/hle/service/vi/service_creator.cpp
index 594e57398..414bd6655 100644
--- a/src/core/hle/service/vi/service_creator.cpp
+++ b/src/core/hle/service/vi/service_creator.cpp
@@ -23,7 +23,8 @@ static bool IsValidServiceAccess(Permission permission, Policy policy) {
23Result GetApplicationDisplayService( 23Result GetApplicationDisplayService(
24 std::shared_ptr<IApplicationDisplayService>* out_application_display_service, 24 std::shared_ptr<IApplicationDisplayService>* out_application_display_service,
25 Core::System& system, std::shared_ptr<Nvnflinger::IHOSBinderDriver> binder_service, 25 Core::System& system, std::shared_ptr<Nvnflinger::IHOSBinderDriver> binder_service,
26 Permission permission, Policy policy) { 26 std::shared_ptr<FbshareBufferManager> shared_buffer_manager, Permission permission,
27 Policy policy) {
27 28
28 if (!IsValidServiceAccess(permission, policy)) { 29 if (!IsValidServiceAccess(permission, policy)) {
29 LOG_ERROR(Service_VI, "Permission denied for policy {}", policy); 30 LOG_ERROR(Service_VI, "Permission denied for policy {}", policy);
@@ -31,7 +32,7 @@ Result GetApplicationDisplayService(
31 } 32 }
32 33
33 *out_application_display_service = 34 *out_application_display_service =
34 std::make_shared<IApplicationDisplayService>(system, binder_service); 35 std::make_shared<IApplicationDisplayService>(system, binder_service, shared_buffer_manager);
35 R_SUCCEED(); 36 R_SUCCEED();
36} 37}
37 38
diff --git a/src/core/hle/service/vi/service_creator.h b/src/core/hle/service/vi/service_creator.h
index bdfac8a08..6691f25c0 100644
--- a/src/core/hle/service/vi/service_creator.h
+++ b/src/core/hle/service/vi/service_creator.h
@@ -19,6 +19,7 @@ union Result;
19 19
20namespace Service::VI { 20namespace Service::VI {
21 21
22class FbshareBufferManager;
22class IApplicationDisplayService; 23class IApplicationDisplayService;
23enum class Permission; 24enum class Permission;
24enum class Policy : u32; 25enum class Policy : u32;
@@ -26,6 +27,7 @@ enum class Policy : u32;
26Result GetApplicationDisplayService( 27Result GetApplicationDisplayService(
27 std::shared_ptr<IApplicationDisplayService>* out_application_display_service, 28 std::shared_ptr<IApplicationDisplayService>* out_application_display_service,
28 Core::System& system, std::shared_ptr<Nvnflinger::IHOSBinderDriver> binder_service, 29 Core::System& system, std::shared_ptr<Nvnflinger::IHOSBinderDriver> binder_service,
29 Permission permission, Policy policy); 30 std::shared_ptr<FbshareBufferManager> shared_buffer_manager, Permission permission,
31 Policy policy);
30 32
31} // namespace Service::VI 33} // namespace Service::VI
diff --git a/src/core/hle/service/vi/system_display_service.cpp b/src/core/hle/service/vi/system_display_service.cpp
index 8d6c3f04c..4670cf4cc 100644
--- a/src/core/hle/service/vi/system_display_service.cpp
+++ b/src/core/hle/service/vi/system_display_service.cpp
@@ -3,16 +3,17 @@
3 3
4#include "common/settings.h" 4#include "common/settings.h"
5#include "core/hle/service/cmif_serialization.h" 5#include "core/hle/service/cmif_serialization.h"
6#include "core/hle/service/nvnflinger/fb_share_buffer_manager.h"
7#include "core/hle/service/vi/system_display_service.h" 6#include "core/hle/service/vi/system_display_service.h"
8#include "core/hle/service/vi/vi_types.h" 7#include "core/hle/service/vi/vi_types.h"
9 8
10namespace Service::VI { 9namespace Service::VI {
11 10
12ISystemDisplayService::ISystemDisplayService( 11ISystemDisplayService::ISystemDisplayService(
13 Core::System& system_, std::shared_ptr<Nvnflinger::Nvnflinger> surface_flinger) 12 Core::System& system_, std::shared_ptr<Nvnflinger::Nvnflinger> surface_flinger,
13 std::shared_ptr<FbshareBufferManager> shared_buffer_manager)
14 : ServiceFramework{system_, "ISystemDisplayService"}, 14 : ServiceFramework{system_, "ISystemDisplayService"},
15 m_surface_flinger{std::move(surface_flinger)} { 15 m_surface_flinger{std::move(surface_flinger)},
16 m_shared_buffer_manager{std::move(shared_buffer_manager)} {
16 // clang-format off 17 // clang-format off
17 static const FunctionInfo functions[] = { 18 static const FunctionInfo functions[] = {
18 {1200, nullptr, "GetZOrderCountMin"}, 19 {1200, nullptr, "GetZOrderCountMin"},
@@ -101,11 +102,11 @@ Result ISystemDisplayService::GetDisplayMode(Out<u32> out_width, Out<u32> out_he
101 102
102Result ISystemDisplayService::GetSharedBufferMemoryHandleId( 103Result ISystemDisplayService::GetSharedBufferMemoryHandleId(
103 Out<s32> out_nvmap_handle, Out<u64> out_size, 104 Out<s32> out_nvmap_handle, Out<u64> out_size,
104 OutLargeData<Nvnflinger::SharedMemoryPoolLayout, BufferAttr_HipcMapAlias> out_pool_layout, 105 OutLargeData<SharedMemoryPoolLayout, BufferAttr_HipcMapAlias> out_pool_layout, u64 buffer_id,
105 u64 buffer_id, ClientAppletResourceUserId aruid) { 106 ClientAppletResourceUserId aruid) {
106 LOG_INFO(Service_VI, "called. buffer_id={}, aruid={:#x}", buffer_id, aruid.pid); 107 LOG_INFO(Service_VI, "called. buffer_id={}, aruid={:#x}", buffer_id, aruid.pid);
107 108
108 R_RETURN(m_surface_flinger->GetSystemBufferManager().GetSharedBufferMemoryHandleId( 109 R_RETURN(m_shared_buffer_manager->GetSharedBufferMemoryHandleId(
109 out_size, out_nvmap_handle, out_pool_layout, buffer_id, aruid.pid)); 110 out_size, out_nvmap_handle, out_pool_layout, buffer_id, aruid.pid));
110} 111}
111 112
@@ -123,8 +124,8 @@ Result ISystemDisplayService::AcquireSharedFrameBuffer(Out<android::Fence> out_f
123 Out<std::array<s32, 4>> out_slots, 124 Out<std::array<s32, 4>> out_slots,
124 Out<s64> out_target_slot, u64 layer_id) { 125 Out<s64> out_target_slot, u64 layer_id) {
125 LOG_DEBUG(Service_VI, "called"); 126 LOG_DEBUG(Service_VI, "called");
126 R_RETURN(m_surface_flinger->GetSystemBufferManager().AcquireSharedFrameBuffer( 127 R_RETURN(m_shared_buffer_manager->AcquireSharedFrameBuffer(out_fence, *out_slots,
127 out_fence, *out_slots, out_target_slot, layer_id)); 128 out_target_slot, layer_id));
128} 129}
129 130
130Result ISystemDisplayService::PresentSharedFrameBuffer(android::Fence fence, 131Result ISystemDisplayService::PresentSharedFrameBuffer(android::Fence fence,
@@ -132,15 +133,14 @@ Result ISystemDisplayService::PresentSharedFrameBuffer(android::Fence fence,
132 u32 window_transform, s32 swap_interval, 133 u32 window_transform, s32 swap_interval,
133 u64 layer_id, s64 surface_id) { 134 u64 layer_id, s64 surface_id) {
134 LOG_DEBUG(Service_VI, "called"); 135 LOG_DEBUG(Service_VI, "called");
135 R_RETURN(m_surface_flinger->GetSystemBufferManager().PresentSharedFrameBuffer( 136 R_RETURN(m_shared_buffer_manager->PresentSharedFrameBuffer(
136 fence, crop_region, window_transform, swap_interval, layer_id, surface_id)); 137 fence, crop_region, window_transform, swap_interval, layer_id, surface_id));
137} 138}
138 139
139Result ISystemDisplayService::GetSharedFrameBufferAcquirableEvent( 140Result ISystemDisplayService::GetSharedFrameBufferAcquirableEvent(
140 OutCopyHandle<Kernel::KReadableEvent> out_event, u64 layer_id) { 141 OutCopyHandle<Kernel::KReadableEvent> out_event, u64 layer_id) {
141 LOG_DEBUG(Service_VI, "called"); 142 LOG_DEBUG(Service_VI, "called");
142 R_RETURN(m_surface_flinger->GetSystemBufferManager().GetSharedFrameBufferAcquirableEvent( 143 R_RETURN(m_shared_buffer_manager->GetSharedFrameBufferAcquirableEvent(out_event, layer_id));
143 out_event, layer_id));
144} 144}
145 145
146} // namespace Service::VI 146} // namespace Service::VI
diff --git a/src/core/hle/service/vi/system_display_service.h b/src/core/hle/service/vi/system_display_service.h
index 6c3f57ad7..b84c9725f 100644
--- a/src/core/hle/service/vi/system_display_service.h
+++ b/src/core/hle/service/vi/system_display_service.h
@@ -5,18 +5,21 @@
5#include "core/hle/service/cmif_types.h" 5#include "core/hle/service/cmif_types.h"
6#include "core/hle/service/nvnflinger/ui/fence.h" 6#include "core/hle/service/nvnflinger/ui/fence.h"
7#include "core/hle/service/service.h" 7#include "core/hle/service/service.h"
8#include "core/hle/service/vi/fbshare_buffer_manager.h"
8 9
9namespace Service::Nvnflinger { 10namespace Service::Nvnflinger {
10class Nvnflinger; 11class Nvnflinger;
11struct SharedMemoryPoolLayout;
12} // namespace Service::Nvnflinger 12} // namespace Service::Nvnflinger
13 13
14namespace Service::VI { 14namespace Service::VI {
15 15
16class FbshareBufferManager;
17
16class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> { 18class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> {
17public: 19public:
18 explicit ISystemDisplayService(Core::System& system_, 20 explicit ISystemDisplayService(Core::System& system_,
19 std::shared_ptr<Nvnflinger::Nvnflinger> surface_flinger); 21 std::shared_ptr<Nvnflinger::Nvnflinger> surface_flinger,
22 std::shared_ptr<FbshareBufferManager> shared_buffer_manager);
20 ~ISystemDisplayService() override; 23 ~ISystemDisplayService() override;
21 24
22private: 25private:
@@ -27,7 +30,7 @@ private:
27 30
28 Result GetSharedBufferMemoryHandleId( 31 Result GetSharedBufferMemoryHandleId(
29 Out<s32> out_nvmap_handle, Out<u64> out_size, 32 Out<s32> out_nvmap_handle, Out<u64> out_size,
30 OutLargeData<Nvnflinger::SharedMemoryPoolLayout, BufferAttr_HipcMapAlias> out_pool_layout, 33 OutLargeData<SharedMemoryPoolLayout, BufferAttr_HipcMapAlias> out_pool_layout,
31 u64 buffer_id, ClientAppletResourceUserId aruid); 34 u64 buffer_id, ClientAppletResourceUserId aruid);
32 Result OpenSharedLayer(u64 layer_id); 35 Result OpenSharedLayer(u64 layer_id);
33 Result ConnectSharedLayer(u64 layer_id); 36 Result ConnectSharedLayer(u64 layer_id);
@@ -42,6 +45,7 @@ private:
42 45
43private: 46private:
44 const std::shared_ptr<Nvnflinger::Nvnflinger> m_surface_flinger; 47 const std::shared_ptr<Nvnflinger::Nvnflinger> m_surface_flinger;
48 const std::shared_ptr<FbshareBufferManager> m_shared_buffer_manager;
45}; 49};
46 50
47} // namespace Service::VI 51} // namespace Service::VI
diff --git a/src/core/hle/service/vi/system_root_service.cpp b/src/core/hle/service/vi/system_root_service.cpp
index 1d435ed6b..2254ed111 100644
--- a/src/core/hle/service/vi/system_root_service.cpp
+++ b/src/core/hle/service/vi/system_root_service.cpp
@@ -11,8 +11,10 @@
11namespace Service::VI { 11namespace Service::VI {
12 12
13ISystemRootService::ISystemRootService(Core::System& system_, 13ISystemRootService::ISystemRootService(Core::System& system_,
14 std::shared_ptr<Nvnflinger::IHOSBinderDriver> binder_service) 14 std::shared_ptr<Nvnflinger::IHOSBinderDriver> binder_service,
15 : ServiceFramework{system_, "vi:s"}, m_binder_service{std::move(binder_service)} { 15 std::shared_ptr<FbshareBufferManager> shared_buffer_manager)
16 : ServiceFramework{system_, "vi:s"}, m_binder_service{std::move(binder_service)},
17 m_shared_buffer_manager{std::move(shared_buffer_manager)} {
16 static const FunctionInfo functions[] = { 18 static const FunctionInfo functions[] = {
17 {1, C<&ISystemRootService::GetDisplayService>, "GetDisplayService"}, 19 {1, C<&ISystemRootService::GetDisplayService>, "GetDisplayService"},
18 {3, nullptr, "GetDisplayServiceWithProxyNameExchange"}, 20 {3, nullptr, "GetDisplayServiceWithProxyNameExchange"},
@@ -26,7 +28,7 @@ Result ISystemRootService::GetDisplayService(
26 Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, Policy policy) { 28 Out<SharedPointer<IApplicationDisplayService>> out_application_display_service, Policy policy) {
27 LOG_DEBUG(Service_VI, "called"); 29 LOG_DEBUG(Service_VI, "called");
28 R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_binder_service, 30 R_RETURN(GetApplicationDisplayService(out_application_display_service, system, m_binder_service,
29 Permission::System, policy)); 31 m_shared_buffer_manager, Permission::System, policy));
30} 32}
31 33
32} // namespace Service::VI 34} // namespace Service::VI
diff --git a/src/core/hle/service/vi/system_root_service.h b/src/core/hle/service/vi/system_root_service.h
index 6f07c39fd..16c997422 100644
--- a/src/core/hle/service/vi/system_root_service.h
+++ b/src/core/hle/service/vi/system_root_service.h
@@ -16,13 +16,15 @@ class IHOSBinderDriver;
16 16
17namespace Service::VI { 17namespace Service::VI {
18 18
19class FbshareBufferManager;
19class IApplicationDisplayService; 20class IApplicationDisplayService;
20enum class Policy : u32; 21enum class Policy : u32;
21 22
22class ISystemRootService final : public ServiceFramework<ISystemRootService> { 23class ISystemRootService final : public ServiceFramework<ISystemRootService> {
23public: 24public:
24 explicit ISystemRootService(Core::System& system_, 25 explicit ISystemRootService(Core::System& system_,
25 std::shared_ptr<Nvnflinger::IHOSBinderDriver> binder_service); 26 std::shared_ptr<Nvnflinger::IHOSBinderDriver> binder_service,
27 std::shared_ptr<FbshareBufferManager> shared_buffer_manager);
26 ~ISystemRootService() override; 28 ~ISystemRootService() override;
27 29
28private: 30private:
@@ -31,6 +33,7 @@ private:
31 Policy policy); 33 Policy policy);
32 34
33 const std::shared_ptr<Nvnflinger::IHOSBinderDriver> m_binder_service; 35 const std::shared_ptr<Nvnflinger::IHOSBinderDriver> m_binder_service;
36 const std::shared_ptr<FbshareBufferManager> m_shared_buffer_manager;
34}; 37};
35 38
36} // namespace Service::VI 39} // namespace Service::VI
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index d20f1fdea..f361b9f4c 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -2,11 +2,13 @@
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "core/core.h" 4#include "core/core.h"
5#include "core/hle/service/nvdrv/nvdrv_interface.h"
5#include "core/hle/service/nvnflinger/hos_binder_driver.h" 6#include "core/hle/service/nvnflinger/hos_binder_driver.h"
6#include "core/hle/service/server_manager.h" 7#include "core/hle/service/server_manager.h"
7#include "core/hle/service/sm/sm.h" 8#include "core/hle/service/sm/sm.h"
8#include "core/hle/service/vi/application_display_service.h" 9#include "core/hle/service/vi/application_display_service.h"
9#include "core/hle/service/vi/application_root_service.h" 10#include "core/hle/service/vi/application_root_service.h"
11#include "core/hle/service/vi/fbshare_buffer_manager.h"
10#include "core/hle/service/vi/manager_root_service.h" 12#include "core/hle/service/vi/manager_root_service.h"
11#include "core/hle/service/vi/system_root_service.h" 13#include "core/hle/service/vi/system_root_service.h"
12#include "core/hle/service/vi/vi.h" 14#include "core/hle/service/vi/vi.h"
@@ -16,14 +18,22 @@ namespace Service::VI {
16void LoopProcess(Core::System& system) { 18void LoopProcess(Core::System& system) {
17 const auto binder_service = 19 const auto binder_service =
18 system.ServiceManager().GetService<Nvnflinger::IHOSBinderDriver>("dispdrv", true); 20 system.ServiceManager().GetService<Nvnflinger::IHOSBinderDriver>("dispdrv", true);
21 const auto nvdrv =
22 system.ServiceManager().GetService<Nvidia::NVDRV>("nvdrv:s", true)->GetModule();
23 const auto shared_buffer_manager =
24 std::make_shared<FbshareBufferManager>(system, binder_service->GetSurfaceFlinger(), nvdrv);
25
19 auto server_manager = std::make_unique<ServerManager>(system); 26 auto server_manager = std::make_unique<ServerManager>(system);
20 27
21 server_manager->RegisterNamedService( 28 server_manager->RegisterNamedService(
22 "vi:m", std::make_shared<IManagerRootService>(system, binder_service)); 29 "vi:m",
30 std::make_shared<IManagerRootService>(system, binder_service, shared_buffer_manager));
23 server_manager->RegisterNamedService( 31 server_manager->RegisterNamedService(
24 "vi:s", std::make_shared<ISystemRootService>(system, binder_service)); 32 "vi:s",
33 std::make_shared<ISystemRootService>(system, binder_service, shared_buffer_manager));
25 server_manager->RegisterNamedService( 34 server_manager->RegisterNamedService(
26 "vi:u", std::make_shared<IApplicationRootService>(system, binder_service)); 35 "vi:u",
36 std::make_shared<IApplicationRootService>(system, binder_service, shared_buffer_manager));
27 ServerManager::RunServer(std::move(server_manager)); 37 ServerManager::RunServer(std::move(server_manager));
28} 38}
29 39