diff options
author | Subv <subv2112@gmail.com> | 2018-01-09 16:41:13 +0100 |
---|---|---|
committer | bunnei <bunneidev@gmail.com> | 2018-01-11 05:28:40 +0100 |
commit | 1ca800cceecd3f37ad874e12fd657f6145ae13c7 (patch) | |
tree | d5c935b854585739970c9a7c2a6b9981e31fdeca /src/core/hle/service/nvdrv | |
parent | VI: Use a Pulse event instead of OneShot for the vblank events. (diff) | |
download | yuzu-1ca800cceecd3f37ad874e12fd657f6145ae13c7.tar yuzu-1ca800cceecd3f37ad874e12fd657f6145ae13c7.tar.gz yuzu-1ca800cceecd3f37ad874e12fd657f6145ae13c7.tar.bz2 yuzu-1ca800cceecd3f37ad874e12fd657f6145ae13c7.tar.lz yuzu-1ca800cceecd3f37ad874e12fd657f6145ae13c7.tar.xz yuzu-1ca800cceecd3f37ad874e12fd657f6145ae13c7.tar.zst yuzu-1ca800cceecd3f37ad874e12fd657f6145ae13c7.zip |
Diffstat (limited to 'src/core/hle/service/nvdrv')
-rw-r--r-- | src/core/hle/service/nvdrv/devices/nvdevice.h | 33 | ||||
-rw-r--r-- | src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp | 29 | ||||
-rw-r--r-- | src/core/hle/service/nvdrv/devices/nvdisp_disp0.h | 34 | ||||
-rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp | 20 | ||||
-rw-r--r-- | src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h | 25 | ||||
-rw-r--r-- | src/core/hle/service/nvdrv/devices/nvmap.cpp | 153 | ||||
-rw-r--r-- | src/core/hle/service/nvdrv/devices/nvmap.h | 108 | ||||
-rw-r--r-- | src/core/hle/service/nvdrv/nvdrv_a.cpp | 169 | ||||
-rw-r--r-- | src/core/hle/service/nvdrv/nvdrv_a.h | 15 |
9 files changed, 421 insertions, 165 deletions
diff --git a/src/core/hle/service/nvdrv/devices/nvdevice.h b/src/core/hle/service/nvdrv/devices/nvdevice.h new file mode 100644 index 000000000..b4efce3a1 --- /dev/null +++ b/src/core/hle/service/nvdrv/devices/nvdevice.h @@ -0,0 +1,33 @@ +// Copyright 2018 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <vector> +#include "common/common_types.h" + +namespace Service { +namespace NVDRV { +namespace Devices { + +/// Represents an abstract nvidia device node. It is to be subclassed by concrete device nodes to +/// implement the ioctl interface. +class nvdevice { +public: + nvdevice() = default; + virtual ~nvdevice() = default; + + /** + * Handles an ioctl request. + * @param command The ioctl command id. + * @param input A buffer containing the input data for the ioctl. + * @param output A buffer where the output data will be written to. + * @returns The result code of the ioctl. + */ + virtual u32 ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) = 0; +}; + +} // namespace Devices +} // namespace NVDRV +} // namespace Service diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp new file mode 100644 index 000000000..faed626ba --- /dev/null +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp @@ -0,0 +1,29 @@ +// Copyright 2018 Yuzu Emulator Team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/assert.h" +#include "common/logging/log.h" +#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" +#include "core/hle/service/nvdrv/devices/nvmap.h" + +namespace Service { +namespace NVDRV { +namespace Devices { + +u32 nvdisp_disp0::ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) { + ASSERT(false, "Unimplemented"); + return 0; +} + +void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height, + u32 stride) { + VAddr addr = nvmap_dev->GetObjectAddress(buffer_handle); + LOG_WARNING(Service, + "Drawing from address %llx offset %08X Width %u Height %u Stride %u Format %u", + addr, offset, width, height, stride, format); +} + +} // namespace Devices +} // namespace NVDRV +} // namespace Service diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h new file mode 100644 index 000000000..54725917f --- /dev/null +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.h @@ -0,0 +1,34 @@ +// Copyright 2018 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <memory> +#include <vector> +#include "common/common_types.h" +#include "core/hle/service/nvdrv/devices/nvdevice.h" + +namespace Service { +namespace NVDRV { +namespace Devices { + +class nvmap; + +class nvdisp_disp0 final : public nvdevice { +public: + nvdisp_disp0(std::shared_ptr<nvmap> nvmap_dev) : nvdevice(), nvmap_dev(std::move(nvmap_dev)) {} + ~nvdisp_disp0() = default; + + u32 ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) override; + + /// Performs a screen flip, drawing the buffer pointed to by the handle. + void flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height, u32 stride); + +private: + std::shared_ptr<nvmap> nvmap_dev; +}; + +} // namespace Devices +} // namespace NVDRV +} // namespace Service diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp new file mode 100644 index 000000000..50fee8f46 --- /dev/null +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp @@ -0,0 +1,20 @@ +// Copyright 2018 Yuzu Emulator Team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/assert.h" +#include "common/logging/log.h" +#include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h" + +namespace Service { +namespace NVDRV { +namespace Devices { + +u32 nvhost_as_gpu::ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) { + ASSERT(false, "Unimplemented"); + return 0; +} + +} // namespace Devices +} // namespace NVDRV +} // namespace Service diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h new file mode 100644 index 000000000..411275922 --- /dev/null +++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.h @@ -0,0 +1,25 @@ +// Copyright 2018 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <vector> +#include "common/common_types.h" +#include "core/hle/service/nvdrv/devices/nvdevice.h" + +namespace Service { +namespace NVDRV { +namespace Devices { + +class nvhost_as_gpu final : public nvdevice { +public: + nvhost_as_gpu() = default; + ~nvhost_as_gpu() override = default; + + u32 ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) override; +}; + +} // namespace Devices +} // namespace NVDRV +} // namespace Service diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp new file mode 100644 index 000000000..fdf2f7be5 --- /dev/null +++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp @@ -0,0 +1,153 @@ +// Copyright 2018 Yuzu Emulator Team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "common/assert.h" +#include "common/logging/log.h" +#include "core/hle/service/nvdrv/devices/nvmap.h" + +namespace Service { +namespace NVDRV { +namespace Devices { + +VAddr nvmap::GetObjectAddress(u32 handle) const { + auto itr = handles.find(handle); + ASSERT(itr != handles.end()); + + auto object = itr->second; + ASSERT(object->status == Object::Status::Allocated); + return object->addr; +} + +u32 nvmap::ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) { + switch (command) { + case IocCreateCommand: + return IocCreate(input, output); + case IocAllocCommand: + return IocAlloc(input, output); + case IocGetIdCommand: + return IocGetId(input, output); + case IocFromIdCommand: + return IocFromId(input, output); + case IocParamCommand: + return IocParam(input, output); + } + + ASSERT(false, "Unimplemented"); +} + +u32 nvmap::IocCreate(const std::vector<u8>& input, std::vector<u8>& output) { + IocCreateParams params; + std::memcpy(¶ms, input.data(), sizeof(params)); + + // Create a new nvmap object and obtain a handle to it. + auto object = std::make_shared<Object>(); + object->id = next_id++; + object->size = params.size; + object->status = Object::Status::Created; + + u32 handle = next_handle++; + handles[handle] = std::move(object); + + LOG_WARNING(Service, "(STUBBED) size 0x%08X", params.size); + + params.handle = handle; + + std::memcpy(output.data(), ¶ms, sizeof(params)); + return 0; +} + +u32 nvmap::IocAlloc(const std::vector<u8>& input, std::vector<u8>& output) { + IocAllocParams params; + std::memcpy(¶ms, input.data(), sizeof(params)); + + auto itr = handles.find(params.handle); + ASSERT(itr != handles.end()); + + auto object = itr->second; + object->flags = params.flags; + object->align = params.align; + object->kind = params.kind; + object->addr = params.addr; + object->status = Object::Status::Allocated; + + LOG_WARNING(Service, "(STUBBED) Allocated address 0x%llx", params.addr); + + std::memcpy(output.data(), ¶ms, sizeof(params)); + return 0; +} + +u32 nvmap::IocGetId(const std::vector<u8>& input, std::vector<u8>& output) { + IocGetIdParams params; + std::memcpy(¶ms, input.data(), sizeof(params)); + + LOG_WARNING(Service, "called"); + + auto itr = handles.find(params.handle); + ASSERT(itr != handles.end()); + + params.id = itr->second->id; + + std::memcpy(output.data(), ¶ms, sizeof(params)); + return 0; +} + +u32 nvmap::IocFromId(const std::vector<u8>& input, std::vector<u8>& output) { + IocFromIdParams params; + std::memcpy(¶ms, input.data(), sizeof(params)); + + LOG_WARNING(Service, "(STUBBED) called"); + + auto itr = std::find_if(handles.begin(), handles.end(), + [&](const auto& entry) { return entry.second->id == params.id; }); + ASSERT(itr != handles.end()); + + // Make a new handle for the object + u32 handle = next_handle++; + handles[handle] = itr->second; + + params.handle = handle; + + std::memcpy(output.data(), ¶ms, sizeof(params)); + return 0; +} + +u32 nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output) { + enum class ParamTypes { Size = 1, Alignment = 2, Base = 3, Heap = 4, Kind = 5, Compr = 6 }; + + IocParamParams params; + std::memcpy(¶ms, input.data(), sizeof(params)); + + LOG_WARNING(Service, "(STUBBED) called type=%u", params.type); + + auto itr = handles.find(params.handle); + ASSERT(itr != handles.end()); + + auto object = itr->second; + ASSERT(object->status == Object::Status::Allocated); + + switch (static_cast<ParamTypes>(params.type)) { + case ParamTypes::Size: + params.value = object->size; + break; + case ParamTypes::Alignment: + params.value = object->align; + break; + case ParamTypes::Heap: + // TODO(Subv): Seems to be a hardcoded value? + params.value = 0x40000000; + break; + case ParamTypes::Kind: + params.value = object->kind; + break; + default: + ASSERT(false, "Unimplemented"); + } + + std::memcpy(output.data(), ¶ms, sizeof(params)); + return 0; +} + +} // namespace Devices +} // namespace NVDRV +} // namespace Service diff --git a/src/core/hle/service/nvdrv/devices/nvmap.h b/src/core/hle/service/nvdrv/devices/nvmap.h new file mode 100644 index 000000000..e8b08f3fb --- /dev/null +++ b/src/core/hle/service/nvdrv/devices/nvmap.h @@ -0,0 +1,108 @@ +// Copyright 2018 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <memory> +#include <unordered_map> +#include <vector> +#include "common/common_funcs.h" +#include "common/common_types.h" +#include "common/swap.h" +#include "core/hle/service/nvdrv/devices/nvdevice.h" + +namespace Service { +namespace NVDRV { +namespace Devices { + +class nvmap final : public nvdevice { +public: + nvmap() = default; + ~nvmap() override = default; + + /// Returns the allocated address of an nvmap object given its handle. + VAddr GetObjectAddress(u32 handle) const; + + u32 ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) override; + +private: + // Represents an nvmap object. + struct Object { + enum class Status { Created, Allocated }; + u32 id; + u32 size; + u32 flags; + u32 align; + u8 kind; + VAddr addr; + Status status; + }; + + /// Id to use for the next handle that is created. + u32 next_handle = 1; + + // Id to use for the next object that is created. + u32 next_id = 1; + + /// Mapping of currently allocated handles to the objects they represent. + std::unordered_map<u32, std::shared_ptr<Object>> handles; + + enum IoctlCommands { + IocCreateCommand = 0xC0080101, + IocFromIdCommand = 0xC0080103, + IocAllocCommand = 0xC0200104, + IocParamCommand = 0xC00C0109, + IocGetIdCommand = 0xC008010E + }; + + struct IocCreateParams { + // Input + u32_le size; + // Output + u32_le handle; + }; + + struct IocAllocParams { + // Input + u32_le handle; + u32_le heap_mask; + u32_le flags; + u32_le align; + u8 kind; + INSERT_PADDING_BYTES(7); + u64_le addr; + }; + + struct IocGetIdParams { + // Output + u32_le id; + // Input + u32_le handle; + }; + + struct IocFromIdParams { + // Input + u32_le id; + // Output + u32_le handle; + }; + + struct IocParamParams { + // Input + u32_le handle; + u32_le type; + // Output + u32_le value; + }; + + u32 IocCreate(const std::vector<u8>& input, std::vector<u8>& output); + u32 IocAlloc(const std::vector<u8>& input, std::vector<u8>& output); + u32 IocGetId(const std::vector<u8>& input, std::vector<u8>& output); + u32 IocFromId(const std::vector<u8>& input, std::vector<u8>& output); + u32 IocParam(const std::vector<u8>& input, std::vector<u8>& output); +}; + +} // namespace Devices +} // namespace NVDRV +} // namespace Service diff --git a/src/core/hle/service/nvdrv/nvdrv_a.cpp b/src/core/hle/service/nvdrv/nvdrv_a.cpp index cede4a883..cfecea924 100644 --- a/src/core/hle/service/nvdrv/nvdrv_a.cpp +++ b/src/core/hle/service/nvdrv/nvdrv_a.cpp @@ -4,171 +4,16 @@ #include "common/logging/log.h" #include "core/hle/ipc_helpers.h" +#include "core/hle/service/nvdrv/devices/nvdevice.h" +#include "core/hle/service/nvdrv/devices/nvdisp_disp0.h" +#include "core/hle/service/nvdrv/devices/nvhost_as_gpu.h" +#include "core/hle/service/nvdrv/devices/nvmap.h" #include "core/hle/service/nvdrv/nvdrv.h" #include "core/hle/service/nvdrv/nvdrv_a.h" namespace Service { namespace NVDRV { -class nvhost_as_gpu : public nvdevice { -public: - u32 ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) override { - ASSERT(false, "Unimplemented"); - return 0; - } -}; - -VAddr nvmap::GetObjectAddress(u32 handle) const { - auto itr = handles.find(handle); - ASSERT(itr != handles.end()); - - auto object = itr->second; - ASSERT(object->status == Object::Status::Allocated); - return object->addr; -} - -u32 nvmap::ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) { - switch (command) { - case IocCreateCommand: - return IocCreate(input, output); - case IocAllocCommand: - return IocAlloc(input, output); - case IocGetIdCommand: - return IocGetId(input, output); - case IocFromIdCommand: - return IocFromId(input, output); - case IocParamCommand: - return IocParam(input, output); - } - - ASSERT(false, "Unimplemented"); -} - -u32 nvmap::IocCreate(const std::vector<u8>& input, std::vector<u8>& output) { - IocCreateParams params; - std::memcpy(¶ms, input.data(), sizeof(params)); - - // Create a new nvmap object and obtain a handle to it. - auto object = std::make_shared<Object>(); - object->id = next_id++; - object->size = params.size; - object->status = Object::Status::Created; - - u32 handle = next_handle++; - handles[handle] = std::move(object); - - LOG_WARNING(Service, "(STUBBED) size 0x%08X", params.size); - - params.handle = handle; - - std::memcpy(output.data(), ¶ms, sizeof(params)); - return 0; -} - -u32 nvmap::IocAlloc(const std::vector<u8>& input, std::vector<u8>& output) { - IocAllocParams params; - std::memcpy(¶ms, input.data(), sizeof(params)); - - auto itr = handles.find(params.handle); - ASSERT(itr != handles.end()); - - auto object = itr->second; - object->flags = params.flags; - object->align = params.align; - object->kind = params.kind; - object->addr = params.addr; - object->status = Object::Status::Allocated; - - LOG_WARNING(Service, "(STUBBED) Allocated address 0x%llx", params.addr); - - std::memcpy(output.data(), ¶ms, sizeof(params)); - return 0; -} - -u32 nvmap::IocGetId(const std::vector<u8>& input, std::vector<u8>& output) { - IocGetIdParams params; - std::memcpy(¶ms, input.data(), sizeof(params)); - - LOG_WARNING(Service, "called"); - - auto itr = handles.find(params.handle); - ASSERT(itr != handles.end()); - - params.id = itr->second->id; - - std::memcpy(output.data(), ¶ms, sizeof(params)); - return 0; -} - -u32 nvmap::IocFromId(const std::vector<u8>& input, std::vector<u8>& output) { - IocFromIdParams params; - std::memcpy(¶ms, input.data(), sizeof(params)); - - LOG_WARNING(Service, "(STUBBED) called"); - - auto itr = std::find_if(handles.begin(), handles.end(), - [&](const auto& entry) { return entry.second->id == params.id; }); - ASSERT(itr != handles.end()); - - // Make a new handle for the object - u32 handle = next_handle++; - handles[handle] = itr->second; - - params.handle = handle; - - std::memcpy(output.data(), ¶ms, sizeof(params)); - return 0; -} - -u32 nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output) { - enum class ParamTypes { Size = 1, Alignment = 2, Base = 3, Heap = 4, Kind = 5, Compr = 6 }; - - IocParamParams params; - std::memcpy(¶ms, input.data(), sizeof(params)); - - LOG_WARNING(Service, "(STUBBED) called type=%u", params.type); - - auto itr = handles.find(params.handle); - ASSERT(itr != handles.end()); - - auto object = itr->second; - ASSERT(object->status == Object::Status::Allocated); - - switch (static_cast<ParamTypes>(params.type)) { - case ParamTypes::Size: - params.value = object->size; - break; - case ParamTypes::Alignment: - params.value = object->align; - break; - case ParamTypes::Heap: - // TODO(Subv): Seems to be a hardcoded value? - params.value = 0x40000000; - break; - case ParamTypes::Kind: - params.value = object->kind; - break; - default: - ASSERT(false, "Unimplemented"); - } - - std::memcpy(output.data(), ¶ms, sizeof(params)); - return 0; -} - -u32 nvdisp_disp0::ioctl(u32 command, const std::vector<u8>& input, std::vector<u8>& output) { - ASSERT(false, "Unimplemented"); - return 0; -} - -void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u32 height, - u32 stride) { - VAddr addr = nvmap_dev->GetObjectAddress(buffer_handle); - LOG_WARNING(Service, - "Drawing from address %llx offset %08X Width %u Height %u Stride %u Format %u", - addr, offset, width, height, stride, format); -} - void NVDRV_A::Open(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service, "(STUBBED) called"); @@ -229,10 +74,10 @@ NVDRV_A::NVDRV_A() : ServiceFramework("nvdrv:a") { }; RegisterHandlers(functions); - auto nvmap_dev = std::make_shared<nvmap>(); - devices["/dev/nvhost-as-gpu"] = std::make_shared<nvhost_as_gpu>(); + auto nvmap_dev = std::make_shared<Devices::nvmap>(); + devices["/dev/nvhost-as-gpu"] = std::make_shared<Devices::nvhost_as_gpu>(); devices["/dev/nvmap"] = nvmap_dev; - devices["/dev/nvdisp_disp0"] = std::make_shared<nvdisp_disp0>(nvmap_dev); + devices["/dev/nvdisp_disp0"] = std::make_shared<Devices::nvdisp_disp0>(nvmap_dev); } } // namespace NVDRV diff --git a/src/core/hle/service/nvdrv/nvdrv_a.h b/src/core/hle/service/nvdrv/nvdrv_a.h index af1017881..4cd04adea 100644 --- a/src/core/hle/service/nvdrv/nvdrv_a.h +++ b/src/core/hle/service/nvdrv/nvdrv_a.h @@ -5,12 +5,17 @@ #pragma once #include <memory> -#include "core/hle/service/service.h" +#include <string> #include "core/hle/service/nvdrv/nvdrv.h" +#include "core/hle/service/service.h" namespace Service { namespace NVDRV { +namespace Devices { +class nvdevice; +} + class NVDRV_A final : public ServiceFramework<NVDRV_A> { public: NVDRV_A(); @@ -30,10 +35,14 @@ private: void Ioctl(Kernel::HLERequestContext& ctx); void Initialize(Kernel::HLERequestContext& ctx); + /// Id to use for the next open file descriptor. u32 next_fd = 1; - std::unordered_map<u32, std::shared_ptr<nvdevice>> open_files; - std::unordered_map<std::string, std::shared_ptr<nvdevice>> devices; + /// Mapping of file descriptors to the devices they reference. + std::unordered_map<u32, std::shared_ptr<Devices::nvdevice>> open_files; + + /// Mapping of device node names to their implementation. + std::unordered_map<std::string, std::shared_ptr<Devices::nvdevice>> devices; }; extern std::weak_ptr<NVDRV_A> nvdrv_a; |