diff options
| author | 2023-09-28 23:45:49 -0600 | |
|---|---|---|
| committer | 2023-10-01 11:38:30 -0600 | |
| commit | 35f25882e027fd3c466edd44db1fc1c5bec75bde (patch) | |
| tree | 8f7be0d40cc8ebb2bbbb8fec4113293bc72f5071 | |
| parent | service: ldn: Implement lp2p:m and stub IMonitorService (diff) | |
| download | yuzu-35f25882e027fd3c466edd44db1fc1c5bec75bde.tar.gz yuzu-35f25882e027fd3c466edd44db1fc1c5bec75bde.tar.xz yuzu-35f25882e027fd3c466edd44db1fc1c5bec75bde.zip | |
service: nvnflinger: Implement shared buffer
Co-authored-by: Liam <byteslice@airmail.cc>
| -rw-r--r-- | src/core/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/devices/nvmap.h | 14 | ||||
| -rw-r--r-- | src/core/hle/service/nvnflinger/buffer_item.h | 2 | ||||
| -rw-r--r-- | src/core/hle/service/nvnflinger/buffer_slot.h | 2 | ||||
| -rw-r--r-- | src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp | 351 | ||||
| -rw-r--r-- | src/core/hle/service/nvnflinger/fb_share_buffer_manager.h | 65 | ||||
| -rw-r--r-- | src/core/hle/service/nvnflinger/graphic_buffer_producer.h | 2 | ||||
| -rw-r--r-- | src/core/hle/service/nvnflinger/nvnflinger.cpp | 11 | ||||
| -rw-r--r-- | src/core/hle/service/nvnflinger/nvnflinger.h | 9 | ||||
| -rw-r--r-- | src/core/hle/service/nvnflinger/ui/fence.h | 3 | ||||
| -rw-r--r-- | src/core/hle/service/nvnflinger/ui/graphic_buffer.h | 4 | ||||
| -rw-r--r-- | src/core/hle/service/vi/vi.cpp | 129 |
12 files changed, 572 insertions, 22 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index d0f76e57e..e02ededfc 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -698,6 +698,8 @@ add_library(core STATIC | |||
| 698 | hle/service/nvnflinger/consumer_base.cpp | 698 | hle/service/nvnflinger/consumer_base.cpp |
| 699 | hle/service/nvnflinger/consumer_base.h | 699 | hle/service/nvnflinger/consumer_base.h |
| 700 | hle/service/nvnflinger/consumer_listener.h | 700 | hle/service/nvnflinger/consumer_listener.h |
| 701 | hle/service/nvnflinger/fb_share_buffer_manager.cpp | ||
| 702 | hle/service/nvnflinger/fb_share_buffer_manager.h | ||
| 701 | hle/service/nvnflinger/graphic_buffer_producer.cpp | 703 | hle/service/nvnflinger/graphic_buffer_producer.cpp |
| 702 | hle/service/nvnflinger/graphic_buffer_producer.h | 704 | hle/service/nvnflinger/graphic_buffer_producer.h |
| 703 | hle/service/nvnflinger/hos_binder_driver_server.cpp | 705 | hle/service/nvnflinger/hos_binder_driver_server.cpp |
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.h b/src/core/hle/service/nvdrv/devices/nvmap.h index 40c65b430..4c0cc71cd 100644 --- a/src/core/hle/service/nvdrv/devices/nvmap.h +++ b/src/core/hle/service/nvdrv/devices/nvmap.h | |||
| @@ -45,13 +45,6 @@ public: | |||
| 45 | IsSharedMemMapped = 6 | 45 | IsSharedMemMapped = 6 |
| 46 | }; | 46 | }; |
| 47 | 47 | ||
| 48 | private: | ||
| 49 | /// Id to use for the next handle that is created. | ||
| 50 | u32 next_handle = 0; | ||
| 51 | |||
| 52 | /// Id to use for the next object that is created. | ||
| 53 | u32 next_id = 0; | ||
| 54 | |||
| 55 | struct IocCreateParams { | 48 | struct IocCreateParams { |
| 56 | // Input | 49 | // Input |
| 57 | u32_le size{}; | 50 | u32_le size{}; |
| @@ -113,6 +106,13 @@ private: | |||
| 113 | NvResult IocParam(std::span<const u8> input, std::span<u8> output); | 106 | NvResult IocParam(std::span<const u8> input, std::span<u8> output); |
| 114 | NvResult IocFree(std::span<const u8> input, std::span<u8> output); | 107 | NvResult IocFree(std::span<const u8> input, std::span<u8> output); |
| 115 | 108 | ||
| 109 | private: | ||
| 110 | /// Id to use for the next handle that is created. | ||
| 111 | u32 next_handle = 0; | ||
| 112 | |||
| 113 | /// Id to use for the next object that is created. | ||
| 114 | u32 next_id = 0; | ||
| 115 | |||
| 116 | NvCore::Container& container; | 116 | NvCore::Container& container; |
| 117 | NvCore::NvMap& file; | 117 | NvCore::NvMap& file; |
| 118 | }; | 118 | }; |
diff --git a/src/core/hle/service/nvnflinger/buffer_item.h b/src/core/hle/service/nvnflinger/buffer_item.h index 7fd808f54..3da8cc3aa 100644 --- a/src/core/hle/service/nvnflinger/buffer_item.h +++ b/src/core/hle/service/nvnflinger/buffer_item.h | |||
| @@ -15,7 +15,7 @@ | |||
| 15 | 15 | ||
| 16 | namespace Service::android { | 16 | namespace Service::android { |
| 17 | 17 | ||
| 18 | class GraphicBuffer; | 18 | struct GraphicBuffer; |
| 19 | 19 | ||
| 20 | class BufferItem final { | 20 | class BufferItem final { |
| 21 | public: | 21 | public: |
diff --git a/src/core/hle/service/nvnflinger/buffer_slot.h b/src/core/hle/service/nvnflinger/buffer_slot.h index d25bca049..d8c9dec3b 100644 --- a/src/core/hle/service/nvnflinger/buffer_slot.h +++ b/src/core/hle/service/nvnflinger/buffer_slot.h | |||
| @@ -13,7 +13,7 @@ | |||
| 13 | 13 | ||
| 14 | namespace Service::android { | 14 | namespace Service::android { |
| 15 | 15 | ||
| 16 | class GraphicBuffer; | 16 | struct GraphicBuffer; |
| 17 | 17 | ||
| 18 | enum class BufferState : u32 { | 18 | enum class BufferState : u32 { |
| 19 | Free = 0, | 19 | Free = 0, |
diff --git a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp new file mode 100644 index 000000000..469a53244 --- /dev/null +++ b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.cpp | |||
| @@ -0,0 +1,351 @@ | |||
| 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/fb_share_buffer_manager.h" | ||
| 13 | #include "core/hle/service/nvnflinger/pixel_format.h" | ||
| 14 | #include "core/hle/service/nvnflinger/ui/graphic_buffer.h" | ||
| 15 | #include "core/hle/service/vi/layer/vi_layer.h" | ||
| 16 | #include "core/hle/service/vi/vi_results.h" | ||
| 17 | |||
| 18 | namespace Service::Nvnflinger { | ||
| 19 | |||
| 20 | namespace { | ||
| 21 | |||
| 22 | Result AllocateIoForProcessAddressSpace(Common::ProcessAddress* out_map_address, | ||
| 23 | std::unique_ptr<Kernel::KPageGroup>* out_page_group, | ||
| 24 | Core::System& system, u32 size) { | ||
| 25 | using Core::Memory::YUZU_PAGESIZE; | ||
| 26 | |||
| 27 | // Allocate memory for the system shared buffer. | ||
| 28 | // FIXME: Because the gmmu can only point to cpu addresses, we need | ||
| 29 | // to map this in the application space to allow it to be used. | ||
| 30 | // FIXME: Add proper smmu emulation. | ||
| 31 | // FIXME: This memory belongs to vi's .data section. | ||
| 32 | auto& kernel = system.Kernel(); | ||
| 33 | auto* process = system.ApplicationProcess(); | ||
| 34 | auto& page_table = process->GetPageTable(); | ||
| 35 | |||
| 36 | // Hold a temporary page group reference while we try to map it. | ||
| 37 | auto pg = std::make_unique<Kernel::KPageGroup>( | ||
| 38 | kernel, std::addressof(kernel.GetSystemSystemResource().GetBlockInfoManager())); | ||
| 39 | |||
| 40 | // Allocate memory from secure pool. | ||
| 41 | R_TRY(kernel.MemoryManager().AllocateAndOpen( | ||
| 42 | pg.get(), size / YUZU_PAGESIZE, | ||
| 43 | Kernel::KMemoryManager::EncodeOption(Kernel::KMemoryManager::Pool::Secure, | ||
| 44 | Kernel::KMemoryManager::Direction::FromBack))); | ||
| 45 | |||
| 46 | // Get bounds of where mapping is possible. | ||
| 47 | const VAddr alias_code_begin = GetInteger(page_table.GetAliasCodeRegionStart()); | ||
| 48 | const VAddr alias_code_size = page_table.GetAliasCodeRegionSize() / YUZU_PAGESIZE; | ||
| 49 | const auto state = Kernel::KMemoryState::Io; | ||
| 50 | const auto perm = Kernel::KMemoryPermission::UserReadWrite; | ||
| 51 | std::mt19937_64 rng{process->GetRandomEntropy(0)}; | ||
| 52 | |||
| 53 | // Retry up to 64 times to map into alias code range. | ||
| 54 | Result res = ResultSuccess; | ||
| 55 | int i; | ||
| 56 | for (i = 0; i < 64; i++) { | ||
| 57 | *out_map_address = alias_code_begin + ((rng() % alias_code_size) * YUZU_PAGESIZE); | ||
| 58 | res = page_table.MapPageGroup(*out_map_address, *pg, state, perm); | ||
| 59 | if (R_SUCCEEDED(res)) { | ||
| 60 | break; | ||
| 61 | } | ||
| 62 | } | ||
| 63 | |||
| 64 | // Return failure, if necessary | ||
| 65 | R_UNLESS(i < 64, res); | ||
| 66 | |||
| 67 | // Return the mapped page group. | ||
| 68 | *out_page_group = std::move(pg); | ||
| 69 | |||
| 70 | // We succeeded. | ||
| 71 | R_SUCCEED(); | ||
| 72 | } | ||
| 73 | |||
| 74 | template <typename T> | ||
| 75 | std::span<u8> SerializeIoc(T& params) { | ||
| 76 | return std::span(reinterpret_cast<u8*>(std::addressof(params)), sizeof(T)); | ||
| 77 | } | ||
| 78 | |||
| 79 | Result CreateNvMapHandle(u32* out_nv_map_handle, Nvidia::Devices::nvmap& nvmap, u32 size) { | ||
| 80 | // Create a handle. | ||
| 81 | Nvidia::Devices::nvmap::IocCreateParams create_in_params{ | ||
| 82 | .size = size, | ||
| 83 | .handle = 0, | ||
| 84 | }; | ||
| 85 | Nvidia::Devices::nvmap::IocCreateParams create_out_params{}; | ||
| 86 | R_UNLESS(nvmap.IocCreate(SerializeIoc(create_in_params), SerializeIoc(create_out_params)) == | ||
| 87 | Nvidia::NvResult::Success, | ||
| 88 | VI::ResultOperationFailed); | ||
| 89 | |||
| 90 | // Assign the output handle. | ||
| 91 | *out_nv_map_handle = create_out_params.handle; | ||
| 92 | |||
| 93 | // We succeeded. | ||
| 94 | R_SUCCEED(); | ||
| 95 | } | ||
| 96 | |||
| 97 | Result FreeNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle) { | ||
| 98 | // Free the handle. | ||
| 99 | Nvidia::Devices::nvmap::IocFreeParams free_in_params{ | ||
| 100 | .handle = handle, | ||
| 101 | }; | ||
| 102 | Nvidia::Devices::nvmap::IocFreeParams free_out_params{}; | ||
| 103 | R_UNLESS(nvmap.IocFree(SerializeIoc(free_in_params), SerializeIoc(free_out_params)) == | ||
| 104 | Nvidia::NvResult::Success, | ||
| 105 | VI::ResultOperationFailed); | ||
| 106 | |||
| 107 | // We succeeded. | ||
| 108 | R_SUCCEED(); | ||
| 109 | } | ||
| 110 | |||
| 111 | Result AllocNvMapHandle(Nvidia::Devices::nvmap& nvmap, u32 handle, Common::ProcessAddress buffer, | ||
| 112 | u32 size) { | ||
| 113 | // Assign the allocated memory to the handle. | ||
| 114 | Nvidia::Devices::nvmap::IocAllocParams alloc_in_params{ | ||
| 115 | .handle = handle, | ||
| 116 | .heap_mask = 0, | ||
| 117 | .flags = {}, | ||
| 118 | .align = 0, | ||
| 119 | .kind = 0, | ||
| 120 | .address = GetInteger(buffer), | ||
| 121 | }; | ||
| 122 | Nvidia::Devices::nvmap::IocAllocParams alloc_out_params{}; | ||
| 123 | R_UNLESS(nvmap.IocAlloc(SerializeIoc(alloc_in_params), SerializeIoc(alloc_out_params)) == | ||
| 124 | Nvidia::NvResult::Success, | ||
| 125 | VI::ResultOperationFailed); | ||
| 126 | |||
| 127 | // We succeeded. | ||
| 128 | R_SUCCEED(); | ||
| 129 | } | ||
| 130 | |||
| 131 | Result AllocateHandleForBuffer(u32* out_handle, Nvidia::Module& nvdrv, | ||
| 132 | Common::ProcessAddress buffer, u32 size) { | ||
| 133 | // Get the nvmap device. | ||
| 134 | auto nvmap_fd = nvdrv.Open("/dev/nvmap"); | ||
| 135 | auto nvmap = nvdrv.GetDevice<Nvidia::Devices::nvmap>(nvmap_fd); | ||
| 136 | ASSERT(nvmap != nullptr); | ||
| 137 | |||
| 138 | // Create a handle. | ||
| 139 | R_TRY(CreateNvMapHandle(out_handle, *nvmap, size)); | ||
| 140 | |||
| 141 | // Ensure we maintain a clean state on failure. | ||
| 142 | ON_RESULT_FAILURE { | ||
| 143 | ASSERT(R_SUCCEEDED(FreeNvMapHandle(*nvmap, *out_handle))); | ||
| 144 | }; | ||
| 145 | |||
| 146 | // Assign the allocated memory to the handle. | ||
| 147 | R_RETURN(AllocNvMapHandle(*nvmap, *out_handle, buffer, size)); | ||
| 148 | } | ||
| 149 | |||
| 150 | constexpr auto SharedBufferBlockLinearFormat = android::PixelFormat::Rgba8888; | ||
| 151 | constexpr u32 SharedBufferBlockLinearBpp = 4; | ||
| 152 | |||
| 153 | constexpr u32 SharedBufferBlockLinearWidth = 1280; | ||
| 154 | constexpr u32 SharedBufferBlockLinearHeight = 768; | ||
| 155 | constexpr u32 SharedBufferBlockLinearStride = | ||
| 156 | SharedBufferBlockLinearWidth * SharedBufferBlockLinearBpp; | ||
| 157 | constexpr u32 SharedBufferNumSlots = 7; | ||
| 158 | |||
| 159 | constexpr u32 SharedBufferWidth = 1280; | ||
| 160 | constexpr u32 SharedBufferHeight = 720; | ||
| 161 | constexpr u32 SharedBufferAsync = false; | ||
| 162 | |||
| 163 | constexpr u32 SharedBufferSlotSize = | ||
| 164 | SharedBufferBlockLinearWidth * SharedBufferBlockLinearHeight * SharedBufferBlockLinearBpp; | ||
| 165 | constexpr u32 SharedBufferSize = SharedBufferSlotSize * SharedBufferNumSlots; | ||
| 166 | |||
| 167 | constexpr SharedMemoryPoolLayout SharedBufferPoolLayout = [] { | ||
| 168 | SharedMemoryPoolLayout layout{}; | ||
| 169 | layout.num_slots = SharedBufferNumSlots; | ||
| 170 | |||
| 171 | for (u32 i = 0; i < SharedBufferNumSlots; i++) { | ||
| 172 | layout.slots[i].buffer_offset = i * SharedBufferSlotSize; | ||
| 173 | layout.slots[i].size = SharedBufferSlotSize; | ||
| 174 | layout.slots[i].width = SharedBufferWidth; | ||
| 175 | layout.slots[i].height = SharedBufferHeight; | ||
| 176 | } | ||
| 177 | |||
| 178 | return layout; | ||
| 179 | }(); | ||
| 180 | |||
| 181 | void MakeGraphicBuffer(android::BufferQueueProducer& producer, u32 slot, u32 handle) { | ||
| 182 | auto buffer = std::make_shared<android::GraphicBuffer>(); | ||
| 183 | buffer->width = SharedBufferWidth; | ||
| 184 | buffer->height = SharedBufferHeight; | ||
| 185 | buffer->stride = SharedBufferBlockLinearStride; | ||
| 186 | buffer->format = SharedBufferBlockLinearFormat; | ||
| 187 | buffer->buffer_id = handle; | ||
| 188 | buffer->offset = slot * SharedBufferSlotSize; | ||
| 189 | ASSERT(producer.SetPreallocatedBuffer(slot, buffer) == android::Status::NoError); | ||
| 190 | } | ||
| 191 | |||
| 192 | } // namespace | ||
| 193 | |||
| 194 | FbShareBufferManager::FbShareBufferManager(Core::System& system, Nvnflinger& flinger, | ||
| 195 | std::shared_ptr<Nvidia::Module> nvdrv) | ||
| 196 | : m_system(system), m_flinger(flinger), m_nvdrv(std::move(nvdrv)) {} | ||
| 197 | |||
| 198 | FbShareBufferManager::~FbShareBufferManager() = default; | ||
| 199 | |||
| 200 | Result FbShareBufferManager::Initialize(u64* out_buffer_id, u64* out_layer_id, u64 display_id) { | ||
| 201 | std::scoped_lock lk{m_guard}; | ||
| 202 | |||
| 203 | // Ensure we have not already created a buffer. | ||
| 204 | R_UNLESS(m_buffer_id == 0, VI::ResultOperationFailed); | ||
| 205 | |||
| 206 | // Allocate memory and space for the shared buffer. | ||
| 207 | Common::ProcessAddress map_address; | ||
| 208 | R_TRY(AllocateIoForProcessAddressSpace(std::addressof(map_address), | ||
| 209 | std::addressof(m_buffer_page_group), m_system, | ||
| 210 | SharedBufferSize)); | ||
| 211 | |||
| 212 | // Create an nvmap handle for the buffer and assign the memory to it. | ||
| 213 | R_TRY(AllocateHandleForBuffer(std::addressof(m_buffer_nvmap_handle), *m_nvdrv, map_address, | ||
| 214 | SharedBufferSize)); | ||
| 215 | |||
| 216 | // Record the display id. | ||
| 217 | m_display_id = display_id; | ||
| 218 | |||
| 219 | // Create a layer for the display. | ||
| 220 | m_layer_id = m_flinger.CreateLayer(m_display_id).value(); | ||
| 221 | |||
| 222 | // Set up the buffer. | ||
| 223 | m_buffer_id = m_next_buffer_id++; | ||
| 224 | |||
| 225 | // Get the layer. | ||
| 226 | VI::Layer* layer = m_flinger.FindLayer(m_display_id, m_layer_id); | ||
| 227 | ASSERT(layer != nullptr); | ||
| 228 | |||
| 229 | // Get the producer and set preallocated buffers. | ||
| 230 | auto& producer = layer->GetBufferQueue(); | ||
| 231 | MakeGraphicBuffer(producer, 0, m_buffer_nvmap_handle); | ||
| 232 | MakeGraphicBuffer(producer, 1, m_buffer_nvmap_handle); | ||
| 233 | |||
| 234 | // Assign outputs. | ||
| 235 | *out_buffer_id = m_buffer_id; | ||
| 236 | *out_layer_id = m_layer_id; | ||
| 237 | |||
| 238 | // We succeeded. | ||
| 239 | R_SUCCEED(); | ||
| 240 | } | ||
| 241 | |||
| 242 | Result FbShareBufferManager::GetSharedBufferMemoryHandleId(u64* out_buffer_size, | ||
| 243 | s32* out_nvmap_handle, | ||
| 244 | SharedMemoryPoolLayout* out_pool_layout, | ||
| 245 | u64 buffer_id, | ||
| 246 | u64 applet_resource_user_id) { | ||
| 247 | std::scoped_lock lk{m_guard}; | ||
| 248 | |||
| 249 | R_UNLESS(m_buffer_id > 0, VI::ResultNotFound); | ||
| 250 | R_UNLESS(buffer_id == m_buffer_id, VI::ResultNotFound); | ||
| 251 | |||
| 252 | *out_pool_layout = SharedBufferPoolLayout; | ||
| 253 | *out_buffer_size = SharedBufferSize; | ||
| 254 | *out_nvmap_handle = m_buffer_nvmap_handle; | ||
| 255 | |||
| 256 | R_SUCCEED(); | ||
| 257 | } | ||
| 258 | |||
| 259 | Result FbShareBufferManager::GetLayerFromId(VI::Layer** out_layer, u64 layer_id) { | ||
| 260 | // Ensure the layer id is valid. | ||
| 261 | R_UNLESS(m_layer_id > 0 && layer_id == m_layer_id, VI::ResultNotFound); | ||
| 262 | |||
| 263 | // Get the layer. | ||
| 264 | VI::Layer* layer = m_flinger.FindLayer(m_display_id, layer_id); | ||
| 265 | R_UNLESS(layer != nullptr, VI::ResultNotFound); | ||
| 266 | |||
| 267 | // We succeeded. | ||
| 268 | *out_layer = layer; | ||
| 269 | R_SUCCEED(); | ||
| 270 | } | ||
| 271 | |||
| 272 | Result FbShareBufferManager::AcquireSharedFrameBuffer(android::Fence* out_fence, | ||
| 273 | std::array<s32, 4>& out_slot_indexes, | ||
| 274 | s64* out_target_slot, u64 layer_id) { | ||
| 275 | std::scoped_lock lk{m_guard}; | ||
| 276 | |||
| 277 | // Get the layer. | ||
| 278 | VI::Layer* layer; | ||
| 279 | R_TRY(this->GetLayerFromId(std::addressof(layer), layer_id)); | ||
| 280 | |||
| 281 | // Get the producer. | ||
| 282 | auto& producer = layer->GetBufferQueue(); | ||
| 283 | |||
| 284 | // Get the next buffer from the producer. | ||
| 285 | s32 slot; | ||
| 286 | R_UNLESS(producer.DequeueBuffer(std::addressof(slot), out_fence, SharedBufferAsync != 0, | ||
| 287 | SharedBufferWidth, SharedBufferHeight, | ||
| 288 | SharedBufferBlockLinearFormat, 0) == android::Status::NoError, | ||
| 289 | VI::ResultOperationFailed); | ||
| 290 | |||
| 291 | // Assign remaining outputs. | ||
| 292 | *out_target_slot = slot; | ||
| 293 | out_slot_indexes = {0, 1, -1, -1}; | ||
| 294 | |||
| 295 | // We succeeded. | ||
| 296 | R_SUCCEED(); | ||
| 297 | } | ||
| 298 | |||
| 299 | Result FbShareBufferManager::PresentSharedFrameBuffer(android::Fence fence, | ||
| 300 | Common::Rectangle<s32> crop_region, | ||
| 301 | u32 transform, s32 swap_interval, | ||
| 302 | u64 layer_id, s64 slot) { | ||
| 303 | std::scoped_lock lk{m_guard}; | ||
| 304 | |||
| 305 | // Get the layer. | ||
| 306 | VI::Layer* layer; | ||
| 307 | R_TRY(this->GetLayerFromId(std::addressof(layer), layer_id)); | ||
| 308 | |||
| 309 | // Get the producer. | ||
| 310 | auto& producer = layer->GetBufferQueue(); | ||
| 311 | |||
| 312 | // Request to queue the buffer. | ||
| 313 | std::shared_ptr<android::GraphicBuffer> buffer; | ||
| 314 | R_UNLESS(producer.RequestBuffer(static_cast<s32>(slot), std::addressof(buffer)) == | ||
| 315 | android::Status::NoError, | ||
| 316 | VI::ResultOperationFailed); | ||
| 317 | |||
| 318 | // Queue the buffer to the producer. | ||
| 319 | android::QueueBufferInput input{}; | ||
| 320 | android::QueueBufferOutput output{}; | ||
| 321 | input.crop = crop_region; | ||
| 322 | input.fence = fence; | ||
| 323 | input.transform = static_cast<android::NativeWindowTransform>(transform); | ||
| 324 | input.swap_interval = swap_interval; | ||
| 325 | R_UNLESS(producer.QueueBuffer(static_cast<s32>(slot), input, std::addressof(output)) == | ||
| 326 | android::Status::NoError, | ||
| 327 | VI::ResultOperationFailed); | ||
| 328 | |||
| 329 | // We succeeded. | ||
| 330 | R_SUCCEED(); | ||
| 331 | } | ||
| 332 | |||
| 333 | Result FbShareBufferManager::GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event, | ||
| 334 | u64 layer_id) { | ||
| 335 | std::scoped_lock lk{m_guard}; | ||
| 336 | |||
| 337 | // Get the layer. | ||
| 338 | VI::Layer* layer; | ||
| 339 | R_TRY(this->GetLayerFromId(std::addressof(layer), layer_id)); | ||
| 340 | |||
| 341 | // Get the producer. | ||
| 342 | auto& producer = layer->GetBufferQueue(); | ||
| 343 | |||
| 344 | // Set the event. | ||
| 345 | *out_event = std::addressof(producer.GetNativeHandle()); | ||
| 346 | |||
| 347 | // We succeeded. | ||
| 348 | R_SUCCEED(); | ||
| 349 | } | ||
| 350 | |||
| 351 | } // namespace Service::Nvnflinger | ||
diff --git a/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h new file mode 100644 index 000000000..c809c01b4 --- /dev/null +++ b/src/core/hle/service/nvnflinger/fb_share_buffer_manager.h | |||
| @@ -0,0 +1,65 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | ||
| 3 | |||
| 4 | #pragma once | ||
| 5 | |||
| 6 | #include "common/math_util.h" | ||
| 7 | #include "core/hle/service/nvnflinger/nvnflinger.h" | ||
| 8 | #include "core/hle/service/nvnflinger/ui/fence.h" | ||
| 9 | |||
| 10 | namespace Kernel { | ||
| 11 | class KPageGroup; | ||
| 12 | } | ||
| 13 | |||
| 14 | namespace Service::Nvnflinger { | ||
| 15 | |||
| 16 | struct SharedMemorySlot { | ||
| 17 | u64 buffer_offset; | ||
| 18 | u64 size; | ||
| 19 | s32 width; | ||
| 20 | s32 height; | ||
| 21 | }; | ||
| 22 | static_assert(sizeof(SharedMemorySlot) == 0x18, "SharedMemorySlot has wrong size"); | ||
| 23 | |||
| 24 | struct SharedMemoryPoolLayout { | ||
| 25 | s32 num_slots; | ||
| 26 | std::array<SharedMemorySlot, 0x10> slots; | ||
| 27 | }; | ||
| 28 | static_assert(sizeof(SharedMemoryPoolLayout) == 0x188, "SharedMemoryPoolLayout has wrong size"); | ||
| 29 | |||
| 30 | class FbShareBufferManager final { | ||
| 31 | public: | ||
| 32 | explicit FbShareBufferManager(Core::System& system, Nvnflinger& flinger, | ||
| 33 | std::shared_ptr<Nvidia::Module> nvdrv); | ||
| 34 | ~FbShareBufferManager(); | ||
| 35 | |||
| 36 | Result Initialize(u64* out_buffer_id, u64* out_layer_handle, u64 display_id); | ||
| 37 | Result GetSharedBufferMemoryHandleId(u64* out_buffer_size, s32* out_nvmap_handle, | ||
| 38 | SharedMemoryPoolLayout* out_pool_layout, u64 buffer_id, | ||
| 39 | u64 applet_resource_user_id); | ||
| 40 | Result AcquireSharedFrameBuffer(android::Fence* out_fence, std::array<s32, 4>& out_slots, | ||
| 41 | s64* out_target_slot, u64 layer_id); | ||
| 42 | Result PresentSharedFrameBuffer(android::Fence fence, Common::Rectangle<s32> crop_region, | ||
| 43 | u32 transform, s32 swap_interval, u64 layer_id, s64 slot); | ||
| 44 | Result GetSharedFrameBufferAcquirableEvent(Kernel::KReadableEvent** out_event, u64 layer_id); | ||
| 45 | |||
| 46 | private: | ||
| 47 | Result GetLayerFromId(VI::Layer** out_layer, u64 layer_id); | ||
| 48 | |||
| 49 | private: | ||
| 50 | u64 m_next_buffer_id = 1; | ||
| 51 | u64 m_display_id = 0; | ||
| 52 | u64 m_buffer_id = 0; | ||
| 53 | u64 m_layer_id = 0; | ||
| 54 | u32 m_buffer_nvmap_handle = 0; | ||
| 55 | SharedMemoryPoolLayout m_pool_layout = {}; | ||
| 56 | |||
| 57 | std::unique_ptr<Kernel::KPageGroup> m_buffer_page_group; | ||
| 58 | |||
| 59 | std::mutex m_guard; | ||
| 60 | Core::System& m_system; | ||
| 61 | Nvnflinger& m_flinger; | ||
| 62 | std::shared_ptr<Nvidia::Module> m_nvdrv; | ||
| 63 | }; | ||
| 64 | |||
| 65 | } // namespace Service::Nvnflinger | ||
diff --git a/src/core/hle/service/nvnflinger/graphic_buffer_producer.h b/src/core/hle/service/nvnflinger/graphic_buffer_producer.h index 21d7b31f3..5d7cff7d3 100644 --- a/src/core/hle/service/nvnflinger/graphic_buffer_producer.h +++ b/src/core/hle/service/nvnflinger/graphic_buffer_producer.h | |||
| @@ -19,6 +19,7 @@ class InputParcel; | |||
| 19 | #pragma pack(push, 1) | 19 | #pragma pack(push, 1) |
| 20 | struct QueueBufferInput final { | 20 | struct QueueBufferInput final { |
| 21 | explicit QueueBufferInput(InputParcel& parcel); | 21 | explicit QueueBufferInput(InputParcel& parcel); |
| 22 | explicit QueueBufferInput() = default; | ||
| 22 | 23 | ||
| 23 | void Deflate(s64* timestamp_, bool* is_auto_timestamp_, Common::Rectangle<s32>* crop_, | 24 | void Deflate(s64* timestamp_, bool* is_auto_timestamp_, Common::Rectangle<s32>* crop_, |
| 24 | NativeWindowScalingMode* scaling_mode_, NativeWindowTransform* transform_, | 25 | NativeWindowScalingMode* scaling_mode_, NativeWindowTransform* transform_, |
| @@ -34,7 +35,6 @@ struct QueueBufferInput final { | |||
| 34 | *fence_ = fence; | 35 | *fence_ = fence; |
| 35 | } | 36 | } |
| 36 | 37 | ||
| 37 | private: | ||
| 38 | s64 timestamp{}; | 38 | s64 timestamp{}; |
| 39 | s32 is_auto_timestamp{}; | 39 | s32 is_auto_timestamp{}; |
| 40 | Common::Rectangle<s32> crop{}; | 40 | Common::Rectangle<s32> crop{}; |
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.cpp b/src/core/hle/service/nvnflinger/nvnflinger.cpp index 21f31f7a0..a07c621d9 100644 --- a/src/core/hle/service/nvnflinger/nvnflinger.cpp +++ b/src/core/hle/service/nvnflinger/nvnflinger.cpp | |||
| @@ -17,6 +17,7 @@ | |||
| 17 | #include "core/hle/service/nvdrv/nvdrv.h" | 17 | #include "core/hle/service/nvdrv/nvdrv.h" |
| 18 | #include "core/hle/service/nvnflinger/buffer_item_consumer.h" | 18 | #include "core/hle/service/nvnflinger/buffer_item_consumer.h" |
| 19 | #include "core/hle/service/nvnflinger/buffer_queue_core.h" | 19 | #include "core/hle/service/nvnflinger/buffer_queue_core.h" |
| 20 | #include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" | ||
| 20 | #include "core/hle/service/nvnflinger/hos_binder_driver_server.h" | 21 | #include "core/hle/service/nvnflinger/hos_binder_driver_server.h" |
| 21 | #include "core/hle/service/nvnflinger/nvnflinger.h" | 22 | #include "core/hle/service/nvnflinger/nvnflinger.h" |
| 22 | #include "core/hle/service/nvnflinger/ui/graphic_buffer.h" | 23 | #include "core/hle/service/nvnflinger/ui/graphic_buffer.h" |
| @@ -331,4 +332,14 @@ s64 Nvnflinger::GetNextTicks() const { | |||
| 331 | return static_cast<s64>(speed_scale * (1000000000.f / effective_fps)); | 332 | return static_cast<s64>(speed_scale * (1000000000.f / effective_fps)); |
| 332 | } | 333 | } |
| 333 | 334 | ||
| 335 | FbShareBufferManager& Nvnflinger::GetSystemBufferManager() { | ||
| 336 | const auto lock_guard = Lock(); | ||
| 337 | |||
| 338 | if (!system_buffer_manager) { | ||
| 339 | system_buffer_manager = std::make_unique<FbShareBufferManager>(system, *this, nvdrv); | ||
| 340 | } | ||
| 341 | |||
| 342 | return *system_buffer_manager; | ||
| 343 | } | ||
| 344 | |||
| 334 | } // namespace Service::Nvnflinger | 345 | } // namespace Service::Nvnflinger |
diff --git a/src/core/hle/service/nvnflinger/nvnflinger.h b/src/core/hle/service/nvnflinger/nvnflinger.h index f478c2bc6..14c783582 100644 --- a/src/core/hle/service/nvnflinger/nvnflinger.h +++ b/src/core/hle/service/nvnflinger/nvnflinger.h | |||
| @@ -45,6 +45,9 @@ class BufferQueueProducer; | |||
| 45 | 45 | ||
| 46 | namespace Service::Nvnflinger { | 46 | namespace Service::Nvnflinger { |
| 47 | 47 | ||
| 48 | class FbShareBufferManager; | ||
| 49 | class HosBinderDriverServer; | ||
| 50 | |||
| 48 | class Nvnflinger final { | 51 | class Nvnflinger final { |
| 49 | public: | 52 | public: |
| 50 | explicit Nvnflinger(Core::System& system_, HosBinderDriverServer& hos_binder_driver_server_); | 53 | explicit Nvnflinger(Core::System& system_, HosBinderDriverServer& hos_binder_driver_server_); |
| @@ -90,12 +93,16 @@ public: | |||
| 90 | 93 | ||
| 91 | [[nodiscard]] s64 GetNextTicks() const; | 94 | [[nodiscard]] s64 GetNextTicks() const; |
| 92 | 95 | ||
| 96 | FbShareBufferManager& GetSystemBufferManager(); | ||
| 97 | |||
| 93 | private: | 98 | private: |
| 94 | struct Layer { | 99 | struct Layer { |
| 95 | std::unique_ptr<android::BufferQueueCore> core; | 100 | std::unique_ptr<android::BufferQueueCore> core; |
| 96 | std::unique_ptr<android::BufferQueueProducer> producer; | 101 | std::unique_ptr<android::BufferQueueProducer> producer; |
| 97 | }; | 102 | }; |
| 98 | 103 | ||
| 104 | friend class FbShareBufferManager; | ||
| 105 | |||
| 99 | private: | 106 | private: |
| 100 | [[nodiscard]] std::unique_lock<std::mutex> Lock() const { | 107 | [[nodiscard]] std::unique_lock<std::mutex> Lock() const { |
| 101 | return std::unique_lock{*guard}; | 108 | return std::unique_lock{*guard}; |
| @@ -140,6 +147,8 @@ private: | |||
| 140 | std::shared_ptr<Core::Timing::EventType> multi_composition_event; | 147 | std::shared_ptr<Core::Timing::EventType> multi_composition_event; |
| 141 | std::shared_ptr<Core::Timing::EventType> single_composition_event; | 148 | std::shared_ptr<Core::Timing::EventType> single_composition_event; |
| 142 | 149 | ||
| 150 | std::unique_ptr<FbShareBufferManager> system_buffer_manager; | ||
| 151 | |||
| 143 | std::shared_ptr<std::mutex> guard; | 152 | std::shared_ptr<std::mutex> guard; |
| 144 | 153 | ||
| 145 | Core::System& system; | 154 | Core::System& system; |
diff --git a/src/core/hle/service/nvnflinger/ui/fence.h b/src/core/hle/service/nvnflinger/ui/fence.h index 536e8156d..177aed758 100644 --- a/src/core/hle/service/nvnflinger/ui/fence.h +++ b/src/core/hle/service/nvnflinger/ui/fence.h | |||
| @@ -20,6 +20,9 @@ public: | |||
| 20 | static constexpr Fence NoFence() { | 20 | static constexpr Fence NoFence() { |
| 21 | Fence fence; | 21 | Fence fence; |
| 22 | fence.fences[0].id = -1; | 22 | fence.fences[0].id = -1; |
| 23 | fence.fences[1].id = -1; | ||
| 24 | fence.fences[2].id = -1; | ||
| 25 | fence.fences[3].id = -1; | ||
| 23 | return fence; | 26 | return fence; |
| 24 | } | 27 | } |
| 25 | 28 | ||
diff --git a/src/core/hle/service/nvnflinger/ui/graphic_buffer.h b/src/core/hle/service/nvnflinger/ui/graphic_buffer.h index 75d1705a8..3eac5cedd 100644 --- a/src/core/hle/service/nvnflinger/ui/graphic_buffer.h +++ b/src/core/hle/service/nvnflinger/ui/graphic_buffer.h | |||
| @@ -12,8 +12,7 @@ | |||
| 12 | 12 | ||
| 13 | namespace Service::android { | 13 | namespace Service::android { |
| 14 | 14 | ||
| 15 | class GraphicBuffer final { | 15 | struct GraphicBuffer final { |
| 16 | public: | ||
| 17 | constexpr GraphicBuffer() = default; | 16 | constexpr GraphicBuffer() = default; |
| 18 | 17 | ||
| 19 | constexpr GraphicBuffer(u32 width_, u32 height_, PixelFormat format_, u32 usage_) | 18 | constexpr GraphicBuffer(u32 width_, u32 height_, PixelFormat format_, u32 usage_) |
| @@ -77,7 +76,6 @@ public: | |||
| 77 | return false; | 76 | return false; |
| 78 | } | 77 | } |
| 79 | 78 | ||
| 80 | private: | ||
| 81 | u32 magic{}; | 79 | u32 magic{}; |
| 82 | s32 width{}; | 80 | s32 width{}; |
| 83 | s32 height{}; | 81 | s32 height{}; |
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 2eb978379..b1bfb9898 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp | |||
| @@ -20,9 +20,12 @@ | |||
| 20 | #include "core/hle/kernel/k_readable_event.h" | 20 | #include "core/hle/kernel/k_readable_event.h" |
| 21 | #include "core/hle/kernel/k_thread.h" | 21 | #include "core/hle/kernel/k_thread.h" |
| 22 | #include "core/hle/service/ipc_helpers.h" | 22 | #include "core/hle/service/ipc_helpers.h" |
| 23 | #include "core/hle/service/nvdrv/devices/nvmap.h" | ||
| 23 | #include "core/hle/service/nvdrv/nvdata.h" | 24 | #include "core/hle/service/nvdrv/nvdata.h" |
| 25 | #include "core/hle/service/nvdrv/nvdrv.h" | ||
| 24 | #include "core/hle/service/nvnflinger/binder.h" | 26 | #include "core/hle/service/nvnflinger/binder.h" |
| 25 | #include "core/hle/service/nvnflinger/buffer_queue_producer.h" | 27 | #include "core/hle/service/nvnflinger/buffer_queue_producer.h" |
| 28 | #include "core/hle/service/nvnflinger/fb_share_buffer_manager.h" | ||
| 26 | #include "core/hle/service/nvnflinger/hos_binder_driver_server.h" | 29 | #include "core/hle/service/nvnflinger/hos_binder_driver_server.h" |
| 27 | #include "core/hle/service/nvnflinger/nvnflinger.h" | 30 | #include "core/hle/service/nvnflinger/nvnflinger.h" |
| 28 | #include "core/hle/service/nvnflinger/parcel.h" | 31 | #include "core/hle/service/nvnflinger/parcel.h" |
| @@ -131,8 +134,9 @@ private: | |||
| 131 | 134 | ||
| 132 | class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> { | 135 | class ISystemDisplayService final : public ServiceFramework<ISystemDisplayService> { |
| 133 | public: | 136 | public: |
| 134 | explicit ISystemDisplayService(Core::System& system_) | 137 | explicit ISystemDisplayService(Core::System& system_, Nvnflinger::Nvnflinger& nvnflinger_) |
| 135 | : ServiceFramework{system_, "ISystemDisplayService"} { | 138 | : ServiceFramework{system_, "ISystemDisplayService"}, nvnflinger{nvnflinger_} { |
| 139 | // clang-format off | ||
| 136 | static const FunctionInfo functions[] = { | 140 | static const FunctionInfo functions[] = { |
| 137 | {1200, nullptr, "GetZOrderCountMin"}, | 141 | {1200, nullptr, "GetZOrderCountMin"}, |
| 138 | {1202, nullptr, "GetZOrderCountMax"}, | 142 | {1202, nullptr, "GetZOrderCountMax"}, |
| @@ -170,22 +174,126 @@ public: | |||
| 170 | {3217, nullptr, "SetDisplayCmuLuma"}, | 174 | {3217, nullptr, "SetDisplayCmuLuma"}, |
| 171 | {3218, nullptr, "SetDisplayCrcMode"}, | 175 | {3218, nullptr, "SetDisplayCrcMode"}, |
| 172 | {6013, nullptr, "GetLayerPresentationSubmissionTimestamps"}, | 176 | {6013, nullptr, "GetLayerPresentationSubmissionTimestamps"}, |
| 173 | {8225, nullptr, "GetSharedBufferMemoryHandleId"}, | 177 | {8225, &ISystemDisplayService::GetSharedBufferMemoryHandleId, "GetSharedBufferMemoryHandleId"}, |
| 174 | {8250, nullptr, "OpenSharedLayer"}, | 178 | {8250, &ISystemDisplayService::OpenSharedLayer, "OpenSharedLayer"}, |
| 175 | {8251, nullptr, "CloseSharedLayer"}, | 179 | {8251, nullptr, "CloseSharedLayer"}, |
| 176 | {8252, nullptr, "ConnectSharedLayer"}, | 180 | {8252, &ISystemDisplayService::ConnectSharedLayer, "ConnectSharedLayer"}, |
| 177 | {8253, nullptr, "DisconnectSharedLayer"}, | 181 | {8253, nullptr, "DisconnectSharedLayer"}, |
| 178 | {8254, nullptr, "AcquireSharedFrameBuffer"}, | 182 | {8254, &ISystemDisplayService::AcquireSharedFrameBuffer, "AcquireSharedFrameBuffer"}, |
| 179 | {8255, nullptr, "PresentSharedFrameBuffer"}, | 183 | {8255, &ISystemDisplayService::PresentSharedFrameBuffer, "PresentSharedFrameBuffer"}, |
| 180 | {8256, nullptr, "GetSharedFrameBufferAcquirableEvent"}, | 184 | {8256, &ISystemDisplayService::GetSharedFrameBufferAcquirableEvent, "GetSharedFrameBufferAcquirableEvent"}, |
| 181 | {8257, nullptr, "FillSharedFrameBufferColor"}, | 185 | {8257, nullptr, "FillSharedFrameBufferColor"}, |
| 182 | {8258, nullptr, "CancelSharedFrameBuffer"}, | 186 | {8258, nullptr, "CancelSharedFrameBuffer"}, |
| 183 | {9000, nullptr, "GetDp2hdmiController"}, | 187 | {9000, nullptr, "GetDp2hdmiController"}, |
| 184 | }; | 188 | }; |
| 189 | // clang-format on | ||
| 185 | RegisterHandlers(functions); | 190 | RegisterHandlers(functions); |
| 186 | } | 191 | } |
| 187 | 192 | ||
| 188 | private: | 193 | private: |
| 194 | void GetSharedBufferMemoryHandleId(HLERequestContext& ctx) { | ||
| 195 | IPC::RequestParser rp{ctx}; | ||
| 196 | const u64 buffer_id = rp.PopRaw<u64>(); | ||
| 197 | |||
| 198 | LOG_INFO(Service_VI, "called. buffer_id={:#x}", buffer_id); | ||
| 199 | |||
| 200 | struct OutputParameters { | ||
| 201 | s32 nvmap_handle; | ||
| 202 | u64 size; | ||
| 203 | }; | ||
| 204 | |||
| 205 | OutputParameters out{}; | ||
| 206 | Nvnflinger::SharedMemoryPoolLayout layout{}; | ||
| 207 | const auto result = nvnflinger.GetSystemBufferManager().GetSharedBufferMemoryHandleId( | ||
| 208 | &out.size, &out.nvmap_handle, &layout, buffer_id, 0); | ||
| 209 | |||
| 210 | ctx.WriteBuffer(&layout, sizeof(layout)); | ||
| 211 | |||
| 212 | IPC::ResponseBuilder rb{ctx, 6}; | ||
| 213 | rb.Push(result); | ||
| 214 | rb.PushRaw(out); | ||
| 215 | } | ||
| 216 | |||
| 217 | void OpenSharedLayer(HLERequestContext& ctx) { | ||
| 218 | IPC::RequestParser rp{ctx}; | ||
| 219 | const u64 layer_id = rp.PopRaw<u64>(); | ||
| 220 | |||
| 221 | LOG_INFO(Service_VI, "(STUBBED) called. layer_id={:#x}", layer_id); | ||
| 222 | |||
| 223 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 224 | rb.Push(ResultSuccess); | ||
| 225 | } | ||
| 226 | |||
| 227 | void ConnectSharedLayer(HLERequestContext& ctx) { | ||
| 228 | IPC::RequestParser rp{ctx}; | ||
| 229 | const u64 layer_id = rp.PopRaw<u64>(); | ||
| 230 | |||
| 231 | LOG_INFO(Service_VI, "(STUBBED) called. layer_id={:#x}", layer_id); | ||
| 232 | |||
| 233 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 234 | rb.Push(ResultSuccess); | ||
| 235 | } | ||
| 236 | |||
| 237 | void GetSharedFrameBufferAcquirableEvent(HLERequestContext& ctx) { | ||
| 238 | LOG_DEBUG(Service_VI, "called"); | ||
| 239 | |||
| 240 | IPC::RequestParser rp{ctx}; | ||
| 241 | const u64 layer_id = rp.PopRaw<u64>(); | ||
| 242 | |||
| 243 | Kernel::KReadableEvent* event{}; | ||
| 244 | const auto result = nvnflinger.GetSystemBufferManager().GetSharedFrameBufferAcquirableEvent( | ||
| 245 | &event, layer_id); | ||
| 246 | |||
| 247 | IPC::ResponseBuilder rb{ctx, 2, 1}; | ||
| 248 | rb.Push(result); | ||
| 249 | rb.PushCopyObjects(event); | ||
| 250 | } | ||
| 251 | |||
| 252 | void AcquireSharedFrameBuffer(HLERequestContext& ctx) { | ||
| 253 | LOG_DEBUG(Service_VI, "called"); | ||
| 254 | |||
| 255 | IPC::RequestParser rp{ctx}; | ||
| 256 | const u64 layer_id = rp.PopRaw<u64>(); | ||
| 257 | |||
| 258 | struct OutputParameters { | ||
| 259 | android::Fence fence; | ||
| 260 | std::array<s32, 4> slots; | ||
| 261 | s64 target_slot; | ||
| 262 | }; | ||
| 263 | static_assert(sizeof(OutputParameters) == 0x40, "OutputParameters has wrong size"); | ||
| 264 | |||
| 265 | OutputParameters out{}; | ||
| 266 | const auto result = nvnflinger.GetSystemBufferManager().AcquireSharedFrameBuffer( | ||
| 267 | &out.fence, out.slots, &out.target_slot, layer_id); | ||
| 268 | |||
| 269 | IPC::ResponseBuilder rb{ctx, 18}; | ||
| 270 | rb.Push(result); | ||
| 271 | rb.PushRaw(out); | ||
| 272 | } | ||
| 273 | |||
| 274 | void PresentSharedFrameBuffer(HLERequestContext& ctx) { | ||
| 275 | LOG_DEBUG(Service_VI, "called"); | ||
| 276 | |||
| 277 | struct InputParameters { | ||
| 278 | android::Fence fence; | ||
| 279 | Common::Rectangle<s32> crop_region; | ||
| 280 | u32 window_transform; | ||
| 281 | s32 swap_interval; | ||
| 282 | u64 layer_id; | ||
| 283 | s64 surface_id; | ||
| 284 | }; | ||
| 285 | static_assert(sizeof(InputParameters) == 0x50, "InputParameters has wrong size"); | ||
| 286 | |||
| 287 | IPC::RequestParser rp{ctx}; | ||
| 288 | auto input = rp.PopRaw<InputParameters>(); | ||
| 289 | |||
| 290 | const auto result = nvnflinger.GetSystemBufferManager().PresentSharedFrameBuffer( | ||
| 291 | input.fence, input.crop_region, input.window_transform, input.swap_interval, | ||
| 292 | input.layer_id, input.surface_id); | ||
| 293 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 294 | rb.Push(result); | ||
| 295 | } | ||
| 296 | |||
| 189 | void SetLayerZ(HLERequestContext& ctx) { | 297 | void SetLayerZ(HLERequestContext& ctx) { |
| 190 | IPC::RequestParser rp{ctx}; | 298 | IPC::RequestParser rp{ctx}; |
| 191 | const u64 layer_id = rp.Pop<u64>(); | 299 | const u64 layer_id = rp.Pop<u64>(); |
| @@ -228,6 +336,9 @@ private: | |||
| 228 | rb.PushRaw<float>(60.0f); // This wouldn't seem to be correct for 30 fps games. | 336 | rb.PushRaw<float>(60.0f); // This wouldn't seem to be correct for 30 fps games. |
| 229 | rb.Push<u32>(0); | 337 | rb.Push<u32>(0); |
| 230 | } | 338 | } |
| 339 | |||
| 340 | private: | ||
| 341 | Nvnflinger::Nvnflinger& nvnflinger; | ||
| 231 | }; | 342 | }; |
| 232 | 343 | ||
| 233 | class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> { | 344 | class IManagerDisplayService final : public ServiceFramework<IManagerDisplayService> { |
| @@ -453,7 +564,7 @@ private: | |||
| 453 | 564 | ||
| 454 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 565 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 455 | rb.Push(ResultSuccess); | 566 | rb.Push(ResultSuccess); |
| 456 | rb.PushIpcInterface<ISystemDisplayService>(system); | 567 | rb.PushIpcInterface<ISystemDisplayService>(system, nv_flinger); |
| 457 | } | 568 | } |
| 458 | 569 | ||
| 459 | void GetManagerDisplayService(HLERequestContext& ctx) { | 570 | void GetManagerDisplayService(HLERequestContext& ctx) { |