diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/service/nvdrv/nvdrv.cpp | 8 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/nvdrv.h | 94 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/nvdrv_a.cpp | 290 | ||||
| -rw-r--r-- | src/core/hle/service/nvdrv/nvdrv_a.h | 14 | ||||
| -rw-r--r-- | src/core/hle/service/vi/vi.cpp | 15 | ||||
| -rw-r--r-- | src/core/hle/service/vi/vi.h | 3 |
6 files changed, 252 insertions, 172 deletions
diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp index a2d55eaee..7923e1c0d 100644 --- a/src/core/hle/service/nvdrv/nvdrv.cpp +++ b/src/core/hle/service/nvdrv/nvdrv.cpp | |||
| @@ -8,9 +8,13 @@ | |||
| 8 | namespace Service { | 8 | namespace Service { |
| 9 | namespace NVDRV { | 9 | namespace NVDRV { |
| 10 | 10 | ||
| 11 | std::weak_ptr<NVDRV_A> nvdrv_a; | ||
| 12 | |||
| 11 | void InstallInterfaces(SM::ServiceManager& service_manager) { | 13 | void InstallInterfaces(SM::ServiceManager& service_manager) { |
| 12 | std::make_shared<NVDRV_A>()->InstallAsService(service_manager); | 14 | auto nvdrv = std::make_shared<NVDRV_A>(); |
| 15 | nvdrv->InstallAsService(service_manager); | ||
| 16 | nvdrv_a = nvdrv; | ||
| 13 | } | 17 | } |
| 14 | 18 | ||
| 15 | } // namespace nvdrv | 19 | } // namespace NVDRV |
| 16 | } // namespace Service | 20 | } // namespace Service |
diff --git a/src/core/hle/service/nvdrv/nvdrv.h b/src/core/hle/service/nvdrv/nvdrv.h index a8f305d33..fd59c1dba 100644 --- a/src/core/hle/service/nvdrv/nvdrv.h +++ b/src/core/hle/service/nvdrv/nvdrv.h | |||
| @@ -4,6 +4,8 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <memory> | ||
| 8 | #include <unordered_map> | ||
| 7 | #include <vector> | 9 | #include <vector> |
| 8 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 9 | #include "core/hle/service/service.h" | 11 | #include "core/hle/service/service.h" |
| @@ -18,6 +20,98 @@ public: | |||
| 18 | virtual u32 ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) = 0; | 20 | virtual u32 ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) = 0; |
| 19 | }; | 21 | }; |
| 20 | 22 | ||
| 23 | class nvmap : public nvdevice { | ||
| 24 | public: | ||
| 25 | /// Returns the allocated address of an nvmap object given its handle. | ||
| 26 | VAddr GetObjectAddress(u32 handle) const; | ||
| 27 | |||
| 28 | u32 ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) override; | ||
| 29 | private: | ||
| 30 | // Represents an nvmap object. | ||
| 31 | struct Object { | ||
| 32 | enum class Status { Created, Allocated }; | ||
| 33 | u32 id; | ||
| 34 | u32 size; | ||
| 35 | u32 flags; | ||
| 36 | u32 align; | ||
| 37 | u8 kind; | ||
| 38 | VAddr addr; | ||
| 39 | Status status; | ||
| 40 | }; | ||
| 41 | |||
| 42 | u32 next_handle = 1; | ||
| 43 | u32 next_id = 1; | ||
| 44 | std::unordered_map<u32, std::shared_ptr<Object>> handles; | ||
| 45 | |||
| 46 | enum IoctlCommands { | ||
| 47 | IocCreateCommand = 0xC0080101, | ||
| 48 | IocFromIdCommand = 0xC0080103, | ||
| 49 | IocAllocCommand = 0xC0200104, | ||
| 50 | IocParamCommand = 0xC00C0109, | ||
| 51 | IocGetIdCommand = 0xC008010E | ||
| 52 | }; | ||
| 53 | |||
| 54 | struct IocCreateParams { | ||
| 55 | // Input | ||
| 56 | u32_le size; | ||
| 57 | // Output | ||
| 58 | u32_le handle; | ||
| 59 | }; | ||
| 60 | |||
| 61 | struct IocAllocParams { | ||
| 62 | // Input | ||
| 63 | u32_le handle; | ||
| 64 | u32_le heap_mask; | ||
| 65 | u32_le flags; | ||
| 66 | u32_le align; | ||
| 67 | u8 kind; | ||
| 68 | INSERT_PADDING_BYTES(7); | ||
| 69 | u64_le addr; | ||
| 70 | }; | ||
| 71 | |||
| 72 | struct IocGetIdParams { | ||
| 73 | // Output | ||
| 74 | u32_le id; | ||
| 75 | // Input | ||
| 76 | u32_le handle; | ||
| 77 | }; | ||
| 78 | |||
| 79 | struct IocFromIdParams { | ||
| 80 | // Input | ||
| 81 | u32_le id; | ||
| 82 | // Output | ||
| 83 | u32_le handle; | ||
| 84 | }; | ||
| 85 | |||
| 86 | struct IocParamParams { | ||
| 87 | // Input | ||
| 88 | u32_le handle; | ||
| 89 | u32_le type; | ||
| 90 | // Output | ||
| 91 | u32_le value; | ||
| 92 | }; | ||
| 93 | |||
| 94 | u32 IocCreate(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 95 | u32 IocAlloc(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 96 | u32 IocGetId(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 97 | u32 IocFromId(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 98 | u32 IocParam(const std::vector<u8>& input, std::vector<u8>& output); | ||
| 99 | }; | ||
| 100 | |||
| 101 | class nvdisp_disp0 : public nvdevice { | ||
| 102 | public: | ||
| 103 | nvdisp_disp0(std::shared_ptr<nvmap> nvmap_dev) : nvdevice(), nvmap_dev(std::move(nvmap_dev)) {} | ||
| 104 | ~nvdisp_disp0() = default; | ||
| 105 | |||
| 106 | u32 ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) override; | ||
| 107 | |||
| 108 | /// Performs a screen flip, drawing the buffer pointed to by the handle. | ||
| 109 | void flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height, u32 stride); | ||
| 110 | |||
| 111 | private: | ||
| 112 | std::shared_ptr<nvmap> nvmap_dev; | ||
| 113 | }; | ||
| 114 | |||
| 21 | /// Registers all NVDRV services with the specified service manager. | 115 | /// Registers all NVDRV services with the specified service manager. |
| 22 | void InstallInterfaces(SM::ServiceManager& service_manager); | 116 | void InstallInterfaces(SM::ServiceManager& service_manager); |
| 23 | 117 | ||
diff --git a/src/core/hle/service/nvdrv/nvdrv_a.cpp b/src/core/hle/service/nvdrv/nvdrv_a.cpp index af6b7f7aa..cede4a883 100644 --- a/src/core/hle/service/nvdrv/nvdrv_a.cpp +++ b/src/core/hle/service/nvdrv/nvdrv_a.cpp | |||
| @@ -18,202 +18,156 @@ public: | |||
| 18 | } | 18 | } |
| 19 | }; | 19 | }; |
| 20 | 20 | ||
| 21 | class nvmap : public nvdevice { | 21 | VAddr nvmap::GetObjectAddress(u32 handle) const { |
| 22 | public: | 22 | auto itr = handles.find(handle); |
| 23 | u32 ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) override { | 23 | ASSERT(itr != handles.end()); |
| 24 | switch (command) { | ||
| 25 | case IocCreateCommand: | ||
| 26 | return IocCreate(input, output); | ||
| 27 | case IocAllocCommand: | ||
| 28 | return IocAlloc(input, output); | ||
| 29 | case IocGetIdCommand: | ||
| 30 | return IocGetId(input, output); | ||
| 31 | case IocFromIdCommand: | ||
| 32 | return IocFromId(input, output); | ||
| 33 | case IocParamCommand: | ||
| 34 | return IocParam(input, output); | ||
| 35 | } | ||
| 36 | 24 | ||
| 37 | ASSERT(false, "Unimplemented"); | 25 | auto object = itr->second; |
| 26 | ASSERT(object->status == Object::Status::Allocated); | ||
| 27 | return object->addr; | ||
| 28 | } | ||
| 29 | |||
| 30 | u32 nvmap::ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) { | ||
| 31 | switch (command) { | ||
| 32 | case IocCreateCommand: | ||
| 33 | return IocCreate(input, output); | ||
| 34 | case IocAllocCommand: | ||
| 35 | return IocAlloc(input, output); | ||
| 36 | case IocGetIdCommand: | ||
| 37 | return IocGetId(input, output); | ||
| 38 | case IocFromIdCommand: | ||
| 39 | return IocFromId(input, output); | ||
| 40 | case IocParamCommand: | ||
| 41 | return IocParam(input, output); | ||
| 38 | } | 42 | } |
| 39 | 43 | ||
| 40 | private: | 44 | ASSERT(false, "Unimplemented"); |
| 41 | // Represents an nvmap object. | 45 | } |
| 42 | struct Object { | ||
| 43 | enum class Status { Created, Allocated }; | ||
| 44 | u32 id; | ||
| 45 | u32 size; | ||
| 46 | u32 flags; | ||
| 47 | u32 align; | ||
| 48 | u8 kind; | ||
| 49 | u64 addr; | ||
| 50 | Status status; | ||
| 51 | }; | ||
| 52 | 46 | ||
| 53 | u32 next_handle = 1; | 47 | u32 nvmap::IocCreate(const std::vector<u8>& input, std::vector<u8>& output) { |
| 54 | u32 next_id = 1; | 48 | IocCreateParams params; |
| 55 | std::unordered_map<u32, std::shared_ptr<Object>> handles; | 49 | std::memcpy(¶ms, input.data(), sizeof(params)); |
| 56 | 50 | ||
| 57 | enum IoctlCommands { | 51 | // Create a new nvmap object and obtain a handle to it. |
| 58 | IocCreateCommand = 0xC0080101, | 52 | auto object = std::make_shared<Object>(); |
| 59 | IocFromIdCommand = 0xC0080103, | 53 | object->id = next_id++; |
| 60 | IocAllocCommand = 0xC0200104, | 54 | object->size = params.size; |
| 61 | IocParamCommand = 0xC00C0109, | 55 | object->status = Object::Status::Created; |
| 62 | IocGetIdCommand = 0xC008010E | ||
| 63 | }; | ||
| 64 | 56 | ||
| 65 | struct IocCreateParams { | 57 | u32 handle = next_handle++; |
| 66 | // Input | 58 | handles[handle] = std::move(object); |
| 67 | u32_le size; | ||
| 68 | // Output | ||
| 69 | u32_le handle; | ||
| 70 | }; | ||
| 71 | 59 | ||
| 72 | struct IocAllocParams { | 60 | LOG_WARNING(Service, "(STUBBED) size 0x%08X", params.size); |
| 73 | // Input | ||
| 74 | u32_le handle; | ||
| 75 | u32_le heap_mask; | ||
| 76 | u32_le flags; | ||
| 77 | u32_le align; | ||
| 78 | u8 kind; | ||
| 79 | INSERT_PADDING_BYTES(7); | ||
| 80 | u64_le addr; | ||
| 81 | }; | ||
| 82 | 61 | ||
| 83 | struct IocGetIdParams { | 62 | params.handle = handle; |
| 84 | // Output | ||
| 85 | u32_le id; | ||
| 86 | // Input | ||
| 87 | u32_le handle; | ||
| 88 | }; | ||
| 89 | 63 | ||
| 90 | struct IocFromIdParams { | 64 | std::memcpy(output.data(), ¶ms, sizeof(params)); |
| 91 | // Input | 65 | return 0; |
| 92 | u32_le id; | 66 | } |
| 93 | // Output | ||
| 94 | u32_le handle; | ||
| 95 | }; | ||
| 96 | 67 | ||
| 97 | struct IocParamParams { | 68 | u32 nvmap::IocAlloc(const std::vector<u8>& input, std::vector<u8>& output) { |
| 98 | // Input | 69 | IocAllocParams params; |
| 99 | u32_le handle; | 70 | std::memcpy(¶ms, input.data(), sizeof(params)); |
| 100 | u32_le type; | ||
| 101 | // Output | ||
| 102 | u32_le value; | ||
| 103 | }; | ||
| 104 | 71 | ||
| 105 | u32 IocCreate(const std::vector<u8>& input, std::vector<u8>& output) { | 72 | auto itr = handles.find(params.handle); |
| 106 | IocCreateParams params; | 73 | ASSERT(itr != handles.end()); |
| 107 | std::memcpy(¶ms, input.data(), sizeof(params)); | ||
| 108 | 74 | ||
| 109 | // Create a new nvmap object and obtain a handle to it. | 75 | auto object = itr->second; |
| 110 | auto object = std::make_shared<Object>(); | 76 | object->flags = params.flags; |
| 111 | object->id = next_id++; | 77 | object->align = params.align; |
| 112 | object->size = params.size; | 78 | object->kind = params.kind; |
| 113 | object->status = Object::Status::Created; | 79 | object->addr = params.addr; |
| 80 | object->status = Object::Status::Allocated; | ||
| 114 | 81 | ||
| 115 | u32 handle = next_handle++; | 82 | LOG_WARNING(Service, "(STUBBED) Allocated address 0x%llx", params.addr); |
| 116 | handles[handle] = std::move(object); | ||
| 117 | 83 | ||
| 118 | LOG_WARNING(Service, "(STUBBED) size 0x%08X", params.size); | 84 | std::memcpy(output.data(), ¶ms, sizeof(params)); |
| 85 | return 0; | ||
| 86 | } | ||
| 119 | 87 | ||
| 120 | params.handle = handle; | 88 | u32 nvmap::IocGetId(const std::vector<u8>& input, std::vector<u8>& output) { |
| 89 | IocGetIdParams params; | ||
| 90 | std::memcpy(¶ms, input.data(), sizeof(params)); | ||
| 121 | 91 | ||
| 122 | std::memcpy(output.data(), ¶ms, sizeof(params)); | 92 | LOG_WARNING(Service, "called"); |
| 123 | return 0; | ||
| 124 | } | ||
| 125 | 93 | ||
| 126 | u32 IocAlloc(const std::vector<u8>& input, std::vector<u8>& output) { | 94 | auto itr = handles.find(params.handle); |
| 127 | IocAllocParams params; | 95 | ASSERT(itr != handles.end()); |
| 128 | std::memcpy(¶ms, input.data(), sizeof(params)); | ||
| 129 | 96 | ||
| 130 | auto itr = handles.find(params.handle); | 97 | params.id = itr->second->id; |
| 131 | ASSERT(itr != handles.end()); | ||
| 132 | 98 | ||
| 133 | auto object = itr->second; | 99 | std::memcpy(output.data(), ¶ms, sizeof(params)); |
| 134 | object->flags = params.flags; | 100 | return 0; |
| 135 | object->align = params.align; | 101 | } |
| 136 | object->kind = params.kind; | ||
| 137 | object->addr = params.addr; | ||
| 138 | object->status = Object::Status::Allocated; | ||
| 139 | 102 | ||
| 140 | LOG_WARNING(Service, "(STUBBED) Allocated address 0x%llx", params.addr); | 103 | u32 nvmap::IocFromId(const std::vector<u8>& input, std::vector<u8>& output) { |
| 104 | IocFromIdParams params; | ||
| 105 | std::memcpy(¶ms, input.data(), sizeof(params)); | ||
| 141 | 106 | ||
| 142 | std::memcpy(output.data(), ¶ms, sizeof(params)); | 107 | LOG_WARNING(Service, "(STUBBED) called"); |
| 143 | return 0; | ||
| 144 | } | ||
| 145 | 108 | ||
| 146 | u32 IocGetId(const std::vector<u8>& input, std::vector<u8>& output) { | 109 | auto itr = std::find_if(handles.begin(), handles.end(), |
| 147 | IocGetIdParams params; | 110 | [&](const auto& entry) { return entry.second->id == params.id; }); |
| 148 | std::memcpy(¶ms, input.data(), sizeof(params)); | 111 | ASSERT(itr != handles.end()); |
| 149 | 112 | ||
| 150 | LOG_WARNING(Service, "called"); | 113 | // Make a new handle for the object |
| 114 | u32 handle = next_handle++; | ||
| 115 | handles[handle] = itr->second; | ||
| 151 | 116 | ||
| 152 | auto itr = handles.find(params.handle); | 117 | params.handle = handle; |
| 153 | ASSERT(itr != handles.end()); | ||
| 154 | 118 | ||
| 155 | params.id = itr->second->id; | 119 | std::memcpy(output.data(), ¶ms, sizeof(params)); |
| 120 | return 0; | ||
| 121 | } | ||
| 156 | 122 | ||
| 157 | std::memcpy(output.data(), ¶ms, sizeof(params)); | 123 | u32 nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output) { |
| 158 | return 0; | 124 | enum class ParamTypes { Size = 1, Alignment = 2, Base = 3, Heap = 4, Kind = 5, Compr = 6 }; |
| 125 | |||
| 126 | IocParamParams params; | ||
| 127 | std::memcpy(¶ms, input.data(), sizeof(params)); | ||
| 128 | |||
| 129 | LOG_WARNING(Service, "(STUBBED) called type=%u", params.type); | ||
| 130 | |||
| 131 | auto itr = handles.find(params.handle); | ||
| 132 | ASSERT(itr != handles.end()); | ||
| 133 | |||
| 134 | auto object = itr->second; | ||
| 135 | ASSERT(object->status == Object::Status::Allocated); | ||
| 136 | |||
| 137 | switch (static_cast<ParamTypes>(params.type)) { | ||
| 138 | case ParamTypes::Size: | ||
| 139 | params.value = object->size; | ||
| 140 | break; | ||
| 141 | case ParamTypes::Alignment: | ||
| 142 | params.value = object->align; | ||
| 143 | break; | ||
| 144 | case ParamTypes::Heap: | ||
| 145 | // TODO(Subv): Seems to be a hardcoded value? | ||
| 146 | params.value = 0x40000000; | ||
| 147 | break; | ||
| 148 | case ParamTypes::Kind: | ||
| 149 | params.value = object->kind; | ||
| 150 | break; | ||
| 151 | default: | ||
| 152 | ASSERT(false, "Unimplemented"); | ||
| 159 | } | 153 | } |
| 160 | 154 | ||
| 161 | u32 IocFromId(const std::vector<u8>& input, std::vector<u8>& output) { | 155 | std::memcpy(output.data(), ¶ms, sizeof(params)); |
| 162 | IocFromIdParams params; | 156 | return 0; |
| 163 | std::memcpy(¶ms, input.data(), sizeof(params)); | 157 | } |
| 164 | |||
| 165 | LOG_WARNING(Service, "(STUBBED) called"); | ||
| 166 | |||
| 167 | auto itr = std::find_if(handles.begin(), handles.end(), | ||
| 168 | [&](const auto& entry) { return entry.second->id == params.id; }); | ||
| 169 | ASSERT(itr != handles.end()); | ||
| 170 | |||
| 171 | // Make a new handle for the object | ||
| 172 | u32 handle = next_handle++; | ||
| 173 | handles[handle] = itr->second; | ||
| 174 | |||
| 175 | params.handle = handle; | ||
| 176 | 158 | ||
| 177 | std::memcpy(output.data(), ¶ms, sizeof(params)); | 159 | u32 nvdisp_disp0::ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) { |
| 178 | return 0; | 160 | ASSERT(false, "Unimplemented"); |
| 179 | } | 161 | return 0; |
| 162 | } | ||
| 180 | 163 | ||
| 181 | u32 IocParam(const std::vector<u8>& input, std::vector<u8>& output) { | 164 | void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height, |
| 182 | enum class ParamTypes { Size = 1, Alignment = 2, Base = 3, Heap = 4, Kind = 5, Compr = 6 }; | 165 | u32 stride) { |
| 183 | 166 | VAddr addr = nvmap_dev->GetObjectAddress(buffer_handle); | |
| 184 | IocParamParams params; | 167 | LOG_WARNING(Service, |
| 185 | std::memcpy(¶ms, input.data(), sizeof(params)); | 168 | "Drawing from address %llx offset %08X Width %u Height %u Stride %u Format %u", |
| 186 | 169 | addr, offset, width, height, stride, format); | |
| 187 | LOG_WARNING(Service, "(STUBBED) called type=%u", params.type); | 170 | } |
| 188 | |||
| 189 | auto itr = handles.find(params.handle); | ||
| 190 | ASSERT(itr != handles.end()); | ||
| 191 | |||
| 192 | auto object = itr->second; | ||
| 193 | ASSERT(object->status == Object::Status::Allocated); | ||
| 194 | |||
| 195 | switch (static_cast<ParamTypes>(params.type)) { | ||
| 196 | case ParamTypes::Size: | ||
| 197 | params.value = object->size; | ||
| 198 | break; | ||
| 199 | case ParamTypes::Alignment: | ||
| 200 | params.value = object->align; | ||
| 201 | break; | ||
| 202 | case ParamTypes::Heap: | ||
| 203 | // TODO(Subv): Seems to be a hardcoded value? | ||
| 204 | params.value = 0x40000000; | ||
| 205 | break; | ||
| 206 | case ParamTypes::Kind: | ||
| 207 | params.value = object->kind; | ||
| 208 | break; | ||
| 209 | default: | ||
| 210 | ASSERT(false, "Unimplemented"); | ||
| 211 | } | ||
| 212 | |||
| 213 | std::memcpy(output.data(), ¶ms, sizeof(params)); | ||
| 214 | return 0; | ||
| 215 | } | ||
| 216 | }; | ||
| 217 | 171 | ||
| 218 | void NVDRV_A::Open(Kernel::HLERequestContext& ctx) { | 172 | void NVDRV_A::Open(Kernel::HLERequestContext& ctx) { |
| 219 | LOG_WARNING(Service, "(STUBBED) called"); | 173 | LOG_WARNING(Service, "(STUBBED) called"); |
| @@ -275,8 +229,10 @@ NVDRV_A::NVDRV_A() : ServiceFramework("nvdrv:a") { | |||
| 275 | }; | 229 | }; |
| 276 | RegisterHandlers(functions); | 230 | RegisterHandlers(functions); |
| 277 | 231 | ||
| 232 | auto nvmap_dev = std::make_shared<nvmap>(); | ||
| 278 | devices["/dev/nvhost-as-gpu"] = std::make_shared<nvhost_as_gpu>(); | 233 | devices["/dev/nvhost-as-gpu"] = std::make_shared<nvhost_as_gpu>(); |
| 279 | devices["/dev/nvmap"] = std::make_shared<nvmap>(); | 234 | devices["/dev/nvmap"] = nvmap_dev; |
| 235 | devices["/dev/nvdisp_disp0"] = std::make_shared<nvdisp_disp0>(nvmap_dev); | ||
| 280 | } | 236 | } |
| 281 | 237 | ||
| 282 | } // namespace NVDRV | 238 | } // namespace NVDRV |
diff --git a/src/core/hle/service/nvdrv/nvdrv_a.h b/src/core/hle/service/nvdrv/nvdrv_a.h index 09522a486..af1017881 100644 --- a/src/core/hle/service/nvdrv/nvdrv_a.h +++ b/src/core/hle/service/nvdrv/nvdrv_a.h | |||
| @@ -4,8 +4,9 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | #include <memory> | 7 | #include <memory> |
| 8 | #include "core/hle/service/service.h" | ||
| 9 | #include "core/hle/service/nvdrv/nvdrv.h" | ||
| 9 | 10 | ||
| 10 | namespace Service { | 11 | namespace Service { |
| 11 | namespace NVDRV { | 12 | namespace NVDRV { |
| @@ -15,6 +16,15 @@ public: | |||
| 15 | NVDRV_A(); | 16 | NVDRV_A(); |
| 16 | ~NVDRV_A() = default; | 17 | ~NVDRV_A() = default; |
| 17 | 18 | ||
| 19 | /// Returns a pointer to one of the available devices, identified by its name. | ||
| 20 | template <typename T> | ||
| 21 | std::shared_ptr<T> GetDevice(std::string name) { | ||
| 22 | auto itr = devices.find(name); | ||
| 23 | if (itr == devices.end()) | ||
| 24 | return nullptr; | ||
| 25 | return std::static_pointer_cast<T>(itr->second); | ||
| 26 | } | ||
| 27 | |||
| 18 | private: | 28 | private: |
| 19 | void Open(Kernel::HLERequestContext& ctx); | 29 | void Open(Kernel::HLERequestContext& ctx); |
| 20 | void Ioctl(Kernel::HLERequestContext& ctx); | 30 | void Ioctl(Kernel::HLERequestContext& ctx); |
| @@ -26,5 +36,7 @@ private: | |||
| 26 | std::unordered_map<std::string, std::shared_ptr<nvdevice>> devices; | 36 | std::unordered_map<std::string, std::shared_ptr<nvdevice>> devices; |
| 27 | }; | 37 | }; |
| 28 | 38 | ||
| 39 | extern std::weak_ptr<NVDRV_A> nvdrv_a; | ||
| 40 | |||
| 29 | } // namespace NVDRV | 41 | } // namespace NVDRV |
| 30 | } // namespace Service | 42 | } // namespace Service |
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp index 67d82c2bf..56aafe6bf 100644 --- a/src/core/hle/service/vi/vi.cpp +++ b/src/core/hle/service/vi/vi.cpp | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | #include "common/scope_exit.h" | 6 | #include "common/scope_exit.h" |
| 7 | #include "core/core_timing.h" | 7 | #include "core/core_timing.h" |
| 8 | #include "core/hle/ipc_helpers.h" | 8 | #include "core/hle/ipc_helpers.h" |
| 9 | #include "core/hle/service/nvdrv/nvdrv_a.h" | ||
| 9 | #include "core/hle/service/vi/vi.h" | 10 | #include "core/hle/service/vi/vi.h" |
| 10 | #include "core/hle/service/vi/vi_m.h" | 11 | #include "core/hle/service/vi/vi_m.h" |
| 11 | 12 | ||
| @@ -743,7 +744,19 @@ void NVFlinger::Compose() { | |||
| 743 | continue; | 744 | continue; |
| 744 | } | 745 | } |
| 745 | 746 | ||
| 746 | // TODO(Subv): Send the buffer to the GPU for drawing. | 747 | auto& igbp_buffer = buffer->igbp_buffer; |
| 748 | |||
| 749 | // Now send the buffer to the GPU for drawing. | ||
| 750 | auto nvdrv = NVDRV::nvdrv_a.lock(); | ||
| 751 | ASSERT(nvdrv); | ||
| 752 | |||
| 753 | // TODO(Subv): Support more than just disp0. The display device selection is probably based | ||
| 754 | // on which display we're drawing (Default, Internal, External, etc) | ||
| 755 | auto nvdisp = nvdrv->GetDevice<NVDRV::nvdisp_disp0>("/dev/nvdisp_disp0"); | ||
| 756 | ASSERT(nvdisp); | ||
| 757 | |||
| 758 | nvdisp->flip(igbp_buffer.gpu_buffer_id, igbp_buffer.offset, igbp_buffer.format, | ||
| 759 | igbp_buffer.width, igbp_buffer.height, igbp_buffer.stride); | ||
| 747 | 760 | ||
| 748 | buffer_queue->ReleaseBuffer(buffer->slot); | 761 | buffer_queue->ReleaseBuffer(buffer->slot); |
| 749 | } | 762 | } |
diff --git a/src/core/hle/service/vi/vi.h b/src/core/hle/service/vi/vi.h index 576c4ce32..9604bd1c2 100644 --- a/src/core/hle/service/vi/vi.h +++ b/src/core/hle/service/vi/vi.h | |||
| @@ -25,7 +25,8 @@ struct IGBPBuffer { | |||
| 25 | u32_le gpu_buffer_id; | 25 | u32_le gpu_buffer_id; |
| 26 | INSERT_PADDING_WORDS(17); | 26 | INSERT_PADDING_WORDS(17); |
| 27 | u32_le nvmap_handle; | 27 | u32_le nvmap_handle; |
| 28 | INSERT_PADDING_WORDS(61); | 28 | u32_le offset; |
| 29 | INSERT_PADDING_WORDS(60); | ||
| 29 | }; | 30 | }; |
| 30 | 31 | ||
| 31 | static_assert(sizeof(IGBPBuffer) == 0x16C, "IGBPBuffer has wrong size"); | 32 | static_assert(sizeof(IGBPBuffer) == 0x16C, "IGBPBuffer has wrong size"); |