From 6b11334f8f6c1bb05fcdbe36cd7d00341107e09a Mon Sep 17 00:00:00 2001 From: pineappleEA Date: Fri, 15 Jan 2021 21:03:50 +0100 Subject: [PATCH] early-access version 1324 --- README.md | 2 +- src/CMakeLists.txt | 1 - src/common/CMakeLists.txt | 3 - src/common/alignment.h | 33 +- src/common/bit_util.h | 76 ---- src/core/hle/kernel/k_priority_queue.h | 4 +- src/core/hle/kernel/k_scheduler.cpp | 8 +- src/core/hle/kernel/memory/page_heap.h | 4 +- src/core/hle/kernel/process_capability.cpp | 4 +- .../service/nvdrv/devices/nvhost_nvdec.cpp | 3 +- .../hle/service/nvdrv/devices/nvhost_vic.cpp | 7 +- src/tests/CMakeLists.txt | 1 - src/video_core/cdma_pusher.cpp | 67 +-- src/video_core/cdma_pusher.h | 33 +- .../command_classes/codecs/codec.cpp | 7 +- .../command_classes/codecs/h264.cpp | 4 +- src/video_core/command_classes/nvdec.cpp | 8 +- src/video_core/command_classes/nvdec.h | 2 +- src/video_core/command_classes/vic.cpp | 45 ++- src/video_core/command_classes/vic.h | 51 ++- src/video_core/gpu.cpp | 6 +- src/video_core/gpu_thread.cpp | 3 +- .../texture_cache/accelerated_swizzle.cpp | 4 +- src/video_core/texture_cache/util.cpp | 10 +- src/video_core/textures/decoders.cpp | 8 +- .../vulkan_common/vulkan_memory_allocator.cpp | 2 +- .../configure_input_player_widget.cpp | 381 ++++++++++++++---- .../configure_input_player_widget.h | 14 +- 28 files changed, 504 insertions(+), 287 deletions(-) diff --git a/README.md b/README.md index 86dddf94e..bc7f38352 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 1322. +This is the source code for early-access 1324. ## Legal Notice diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 4daec5350..478246b6f 100755 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -130,7 +130,6 @@ add_subdirectory(tests) if (ENABLE_SDL2) add_subdirectory(yuzu_cmd) - add_subdirectory(yuzu_tester) endif() if (ENABLE_QT) diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 75fe30686..f77575a00 100755 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -107,7 +107,6 @@ add_library(common STATIC bit_util.h cityhash.cpp cityhash.h - color.h common_funcs.h common_paths.h common_types.h @@ -166,8 +165,6 @@ add_library(common STATIC threadsafe_queue.h time_zone.cpp time_zone.h - timer.cpp - timer.h tree.h uint128.cpp uint128.h diff --git a/src/common/alignment.h b/src/common/alignment.h index 5040043de..fb81f10d8 100755 --- a/src/common/alignment.h +++ b/src/common/alignment.h @@ -9,50 +9,45 @@ namespace Common { template -[[nodiscard]] constexpr T AlignUp(T value, std::size_t size) { - static_assert(std::is_unsigned_v, "T must be an unsigned value."); +requires std::is_unsigned_v[[nodiscard]] constexpr T AlignUp(T value, size_t size) { auto mod{static_cast(value % size)}; value -= mod; return static_cast(mod == T{0} ? value : value + size); } template -[[nodiscard]] constexpr T AlignDown(T value, std::size_t size) { - static_assert(std::is_unsigned_v, "T must be an unsigned value."); +requires std::is_unsigned_v[[nodiscard]] constexpr T AlignUpLog2(T value, size_t align_log2) { + return static_cast((value + ((1ULL << align_log2) - 1)) >> align_log2 << align_log2); +} + +template +requires std::is_unsigned_v[[nodiscard]] constexpr T AlignDown(T value, size_t size) { return static_cast(value - value % size); } template -[[nodiscard]] constexpr T AlignBits(T value, std::size_t align) { - static_assert(std::is_unsigned_v, "T must be an unsigned value."); - return static_cast((value + ((1ULL << align) - 1)) >> align << align); -} - -template -[[nodiscard]] constexpr bool Is4KBAligned(T value) { - static_assert(std::is_unsigned_v, "T must be an unsigned value."); +requires std::is_unsigned_v[[nodiscard]] constexpr bool Is4KBAligned(T value) { return (value & 0xFFF) == 0; } template -[[nodiscard]] constexpr bool IsWordAligned(T value) { - static_assert(std::is_unsigned_v, "T must be an unsigned value."); +requires std::is_unsigned_v[[nodiscard]] constexpr bool IsWordAligned(T value) { return (value & 0b11) == 0; } template -[[nodiscard]] constexpr bool IsAligned(T value, std::size_t alignment) { - using U = typename std::make_unsigned::type; +requires std::is_integral_v[[nodiscard]] constexpr bool IsAligned(T value, size_t alignment) { + using U = typename std::make_unsigned_t; const U mask = static_cast(alignment - 1); return (value & mask) == 0; } -template +template class AlignmentAllocator { public: using value_type = T; - using size_type = std::size_t; - using difference_type = std::ptrdiff_t; + using size_type = size_t; + using difference_type = ptrdiff_t; using propagate_on_container_copy_assignment = std::true_type; using propagate_on_container_move_assignment = std::true_type; diff --git a/src/common/bit_util.h b/src/common/bit_util.h index 29f59a9a3..685e7fc9b 100755 --- a/src/common/bit_util.h +++ b/src/common/bit_util.h @@ -21,82 +21,6 @@ template return sizeof(T) * CHAR_BIT; } -#ifdef _MSC_VER -[[nodiscard]] inline u32 CountLeadingZeroes32(u32 value) { - unsigned long leading_zero = 0; - - if (_BitScanReverse(&leading_zero, value) != 0) { - return 31 - leading_zero; - } - - return 32; -} - -[[nodiscard]] inline u32 CountLeadingZeroes64(u64 value) { - unsigned long leading_zero = 0; - - if (_BitScanReverse64(&leading_zero, value) != 0) { - return 63 - leading_zero; - } - - return 64; -} -#else -[[nodiscard]] inline u32 CountLeadingZeroes32(u32 value) { - if (value == 0) { - return 32; - } - - return static_cast(__builtin_clz(value)); -} - -[[nodiscard]] inline u32 CountLeadingZeroes64(u64 value) { - if (value == 0) { - return 64; - } - - return static_cast(__builtin_clzll(value)); -} -#endif - -#ifdef _MSC_VER -[[nodiscard]] inline u32 CountTrailingZeroes32(u32 value) { - unsigned long trailing_zero = 0; - - if (_BitScanForward(&trailing_zero, value) != 0) { - return trailing_zero; - } - - return 32; -} - -[[nodiscard]] inline u32 CountTrailingZeroes64(u64 value) { - unsigned long trailing_zero = 0; - - if (_BitScanForward64(&trailing_zero, value) != 0) { - return trailing_zero; - } - - return 64; -} -#else -[[nodiscard]] inline u32 CountTrailingZeroes32(u32 value) { - if (value == 0) { - return 32; - } - - return static_cast(__builtin_ctz(value)); -} - -[[nodiscard]] inline u32 CountTrailingZeroes64(u64 value) { - if (value == 0) { - return 64; - } - - return static_cast(__builtin_ctzll(value)); -} -#endif - #ifdef _MSC_VER [[nodiscard]] inline u32 MostSignificantBit32(const u32 value) { diff --git a/src/core/hle/kernel/k_priority_queue.h b/src/core/hle/kernel/k_priority_queue.h index 99fb8fe93..0dc929040 100755 --- a/src/core/hle/kernel/k_priority_queue.h +++ b/src/core/hle/kernel/k_priority_queue.h @@ -8,11 +8,11 @@ #pragma once #include +#include #include #include "common/assert.h" #include "common/bit_set.h" -#include "common/bit_util.h" #include "common/common_types.h" #include "common/concepts.h" @@ -268,7 +268,7 @@ private: } constexpr s32 GetNextCore(u64& affinity) { - const s32 core = Common::CountTrailingZeroes64(affinity); + const s32 core = std::countr_zero(affinity); ClearAffinityBit(affinity, core); return core; } diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp index 42f0ea483..12b5619fb 100755 --- a/src/core/hle/kernel/k_scheduler.cpp +++ b/src/core/hle/kernel/k_scheduler.cpp @@ -5,6 +5,8 @@ // This file references various implementation details from Atmosphere, an open-source firmware for // the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX. +#include + #include "common/assert.h" #include "common/bit_util.h" #include "common/fiber.h" @@ -31,12 +33,12 @@ static void IncrementScheduledCount(Kernel::Thread* thread) { void KScheduler::RescheduleCores(KernelCore& kernel, u64 cores_pending_reschedule, Core::EmuThreadHandle global_thread) { - u32 current_core = global_thread.host_handle; + const u32 current_core = global_thread.host_handle; bool must_context_switch = global_thread.guest_handle != InvalidHandle && (current_core < Core::Hardware::NUM_CPU_CORES); while (cores_pending_reschedule != 0) { - u32 core = Common::CountTrailingZeroes64(cores_pending_reschedule); + const auto core = static_cast(std::countr_zero(cores_pending_reschedule)); ASSERT(core < Core::Hardware::NUM_CPU_CORES); if (!must_context_switch || core != current_core) { auto& phys_core = kernel.PhysicalCore(core); @@ -109,7 +111,7 @@ u64 KScheduler::UpdateHighestPriorityThreadsImpl(KernelCore& kernel) { // Idle cores are bad. We're going to try to migrate threads to each idle core in turn. while (idle_cores != 0) { - u32 core_id = Common::CountTrailingZeroes64(idle_cores); + const auto core_id = static_cast(std::countr_zero(idle_cores)); if (Thread* suggested = priority_queue.GetSuggestedFront(core_id); suggested != nullptr) { s32 migration_candidates[Core::Hardware::NUM_CPU_CORES]; size_t num_candidates = 0; diff --git a/src/core/hle/kernel/memory/page_heap.h b/src/core/hle/kernel/memory/page_heap.h index 22b0de860..131093284 100755 --- a/src/core/hle/kernel/memory/page_heap.h +++ b/src/core/hle/kernel/memory/page_heap.h @@ -8,11 +8,11 @@ #pragma once #include +#include #include #include "common/alignment.h" #include "common/assert.h" -#include "common/bit_util.h" #include "common/common_funcs.h" #include "common/common_types.h" #include "core/hle/kernel/memory/memory_types.h" @@ -105,7 +105,7 @@ private: ASSERT(depth == 0); return -1; } - offset = offset * 64 + Common::CountTrailingZeroes64(v); + offset = offset * 64 + static_cast(std::countr_zero(v)); ++depth; } while (depth < static_cast(used_depths)); diff --git a/src/core/hle/kernel/process_capability.cpp b/src/core/hle/kernel/process_capability.cpp index 0f128c586..0566311b6 100755 --- a/src/core/hle/kernel/process_capability.cpp +++ b/src/core/hle/kernel/process_capability.cpp @@ -2,6 +2,8 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include + #include "common/bit_util.h" #include "common/logging/log.h" #include "core/hle/kernel/errors.h" @@ -60,7 +62,7 @@ constexpr CapabilityType GetCapabilityType(u32 value) { u32 GetFlagBitOffset(CapabilityType type) { const auto value = static_cast(type); - return static_cast(Common::BitSize() - Common::CountLeadingZeroes32(value)); + return static_cast(Common::BitSize() - static_cast(std::countl_zero(value))); } } // Anonymous namespace diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp index 644e7a209..0ac5fc6ae 100755 --- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp @@ -34,7 +34,8 @@ NvResult nvhost_nvdec::Ioctl1(Ioctl command, const std::vector& input, case 0xa: { if (command.length == 0x1c) { LOG_INFO(Service_NVDRV, "NVDEC video stream ended"); - Tegra::ChCommandHeaderList cmdlist{{0xDEADB33F}}; + Tegra::ChCommandHeaderList cmdlist(1); + cmdlist[0] = Tegra::ChCommandHeader{0xDEADB33F}; system.GPU().PushCommandBuffer(cmdlist); system.GPU().MemoryManager().InvalidateQueuedCaches(); } diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp index a2a08af42..9118ab254 100755 --- a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp +++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp @@ -29,13 +29,8 @@ NvResult nvhost_vic::Ioctl1(Ioctl command, const std::vector& input, std::ve return GetWaitbase(input, output); case 0x9: return MapBuffer(input, output); - case 0xa: { - if (command.length == 0x1c) { - Tegra::ChCommandHeaderList cmdlist{{0xDEADB33F}}; - system.GPU().PushCommandBuffer(cmdlist); - } + case 0xa: return UnmapBuffer(input, output); - } default: break; } diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index 5b637f3c5..6a5c18945 100755 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -1,6 +1,5 @@ add_executable(tests common/bit_field.cpp - common/bit_utils.cpp common/fibers.cpp common/param_package.cpp common/ring_buffer.cpp diff --git a/src/video_core/cdma_pusher.cpp b/src/video_core/cdma_pusher.cpp index 1228d38c8..33b3c060b 100755 --- a/src/video_core/cdma_pusher.cpp +++ b/src/video_core/cdma_pusher.cpp @@ -18,10 +18,10 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // +#include #include "command_classes/host1x.h" #include "command_classes/nvdec.h" #include "command_classes/vic.h" -#include "common/bit_util.h" #include "video_core/cdma_pusher.h" #include "video_core/command_classes/nvdec_common.h" #include "video_core/engines/maxwell_3d.h" @@ -37,43 +37,59 @@ CDmaPusher::CDmaPusher(GPU& gpu_) CDmaPusher::~CDmaPusher() = default; -void CDmaPusher::ProcessEntries(ChCommandHeaderList&& entries) { - for (const auto& value : entries) { +void CDmaPusher::Push(ChCommandHeaderList&& entries) { + cdma_queue.push(std::move(entries)); +} + +void CDmaPusher::DispatchCalls() { + while (!cdma_queue.empty()) { + Step(); + } +} + +void CDmaPusher::Step() { + const auto entries{cdma_queue.front()}; + cdma_queue.pop(); + + std::vector values(entries.size()); + std::memcpy(values.data(), entries.data(), entries.size() * sizeof(u32)); + + for (const u32 value : values) { if (mask != 0) { - const u32 lbs = Common::CountTrailingZeroes32(mask); + const auto lbs = static_cast(std::countr_zero(mask)); mask &= ~(1U << lbs); - ExecuteCommand(offset + lbs, value.raw); + ExecuteCommand(static_cast(offset + lbs), value); continue; } else if (count != 0) { --count; - ExecuteCommand(offset, value.raw); + ExecuteCommand(static_cast(offset), value); if (incrementing) { ++offset; } continue; } - const auto mode = value.submission_mode.Value(); + const auto mode = static_cast((value >> 28) & 0xf); switch (mode) { case ChSubmissionMode::SetClass: { - mask = value.value & 0x3f; - offset = value.method_offset; - current_class = static_cast((value.value >> 6) & 0x3ff); + mask = value & 0x3f; + offset = (value >> 16) & 0xfff; + current_class = static_cast((value >> 6) & 0x3ff); break; } case ChSubmissionMode::Incrementing: case ChSubmissionMode::NonIncrementing: - count = value.value; - offset = value.method_offset; + count = value & 0xffff; + offset = (value >> 16) & 0xfff; incrementing = mode == ChSubmissionMode::Incrementing; break; case ChSubmissionMode::Mask: - mask = value.value; - offset = value.method_offset; + mask = value & 0xffff; + offset = (value >> 16) & 0xfff; break; case ChSubmissionMode::Immediate: { - const u32 data = value.value & 0xfff; - offset = value.method_offset; - ExecuteCommand(offset, data); + const u32 data = value & 0xfff; + offset = (value >> 16) & 0xfff; + ExecuteCommand(static_cast(offset), data); break; } default: @@ -86,8 +102,8 @@ void CDmaPusher::ProcessEntries(ChCommandHeaderList&& entries) { void CDmaPusher::ExecuteCommand(u32 state_offset, u32 data) { switch (current_class) { case ChClassId::NvDec: - ThiStateWrite(nvdec_thi_state, offset, data); - switch (static_cast(offset)) { + ThiStateWrite(nvdec_thi_state, state_offset, {data}); + switch (static_cast(state_offset)) { case ThiMethod::IncSyncpt: { LOG_DEBUG(Service_NVDRV, "NVDEC Class IncSyncpt Method"); const auto syncpoint_id = static_cast(data & 0xFF); @@ -104,7 +120,7 @@ void CDmaPusher::ExecuteCommand(u32 state_offset, u32 data) { LOG_DEBUG(Service_NVDRV, "NVDEC method 0x{:X}", static_cast(nvdec_thi_state.method_0)); nvdec_processor->ProcessMethod(static_cast(nvdec_thi_state.method_0), - data); + {data}); break; default: break; @@ -128,7 +144,7 @@ void CDmaPusher::ExecuteCommand(u32 state_offset, u32 data) { case ThiMethod::SetMethod1: LOG_DEBUG(Service_NVDRV, "VIC method 0x{:X}, Args=({})", static_cast(vic_thi_state.method_0), data); - vic_processor->ProcessMethod(static_cast(vic_thi_state.method_0), data); + vic_processor->ProcessMethod(static_cast(vic_thi_state.method_0), {data}); break; default: break; @@ -137,7 +153,7 @@ void CDmaPusher::ExecuteCommand(u32 state_offset, u32 data) { case ChClassId::Host1x: // This device is mainly for syncpoint synchronization LOG_DEBUG(Service_NVDRV, "Host1X Class Method"); - host1x_processor->ProcessMethod(static_cast(offset), data); + host1x_processor->ProcessMethod(static_cast(state_offset), {data}); break; default: UNIMPLEMENTED_MSG("Current class not implemented {:X}", static_cast(current_class)); @@ -145,9 +161,10 @@ void CDmaPusher::ExecuteCommand(u32 state_offset, u32 data) { } } -void CDmaPusher::ThiStateWrite(ThiRegisters& state, u32 state_offset, u32 argument) { - u8* const offset_ptr = reinterpret_cast(&state) + sizeof(u32) * state_offset; - std::memcpy(offset_ptr, &argument, sizeof(u32)); +void CDmaPusher::ThiStateWrite(ThiRegisters& state, u32 state_offset, + const std::vector& arguments) { + u8* const state_offset_ptr = reinterpret_cast(&state) + sizeof(u32) * state_offset; + std::memcpy(state_offset_ptr, arguments.data(), sizeof(u32) * arguments.size()); } } // namespace Tegra diff --git a/src/video_core/cdma_pusher.h b/src/video_core/cdma_pusher.h index 1bada44dd..e5f212c1a 100755 --- a/src/video_core/cdma_pusher.h +++ b/src/video_core/cdma_pusher.h @@ -5,7 +5,9 @@ #pragma once #include +#include #include +#include #include "common/bit_field.h" #include "common/common_types.h" @@ -14,9 +16,9 @@ namespace Tegra { class GPU; -class Host1x; class Nvdec; class Vic; +class Host1x; enum class ChSubmissionMode : u32 { SetClass = 0, @@ -46,10 +48,16 @@ enum class ChClassId : u32 { NvDec = 0xf0 }; +enum class ChMethod : u32 { + Empty = 0, + SetMethod = 0x10, + SetData = 0x11, +}; + union ChCommandHeader { u32 raw; BitField<0, 16, u32> value; - BitField<16, 12, u32> method_offset; + BitField<16, 12, ChMethod> method_offset; BitField<28, 4, ChSubmissionMode> submission_mode; }; static_assert(sizeof(ChCommandHeader) == sizeof(u32), "ChCommand header is an invalid size"); @@ -91,15 +99,21 @@ public: explicit CDmaPusher(GPU& gpu_); ~CDmaPusher(); - /// Process the command entry - void ProcessEntries(ChCommandHeaderList&& entries); + /// Push NVDEC command buffer entries into queue + void Push(ChCommandHeaderList&& entries); + + /// Process queued command buffer entries + void DispatchCalls(); + + /// Process one queue element + void Step(); -private: /// Invoke command class devices to execute the command based on the current state void ExecuteCommand(u32 state_offset, u32 data); +private: /// Write arguments value to the ThiRegisters member at the specified offset - void ThiStateWrite(ThiRegisters& state, u32 offset, u32 argument); + void ThiStateWrite(ThiRegisters& state, u32 state_offset, const std::vector& arguments); GPU& gpu; std::shared_ptr nvdec_processor; @@ -110,10 +124,13 @@ private: ThiRegisters vic_thi_state{}; ThiRegisters nvdec_thi_state{}; - u32 count{}; - u32 offset{}; + s32 count{}; + s32 offset{}; u32 mask{}; bool incrementing{}; + + // Queue of command lists to be processed + std::queue cdma_queue; }; } // namespace Tegra diff --git a/src/video_core/command_classes/codecs/codec.cpp b/src/video_core/command_classes/codecs/codec.cpp index d02dc6260..39bc923a5 100755 --- a/src/video_core/command_classes/codecs/codec.cpp +++ b/src/video_core/command_classes/codecs/codec.cpp @@ -44,10 +44,8 @@ Codec::~Codec() { } void Codec::SetTargetCodec(NvdecCommon::VideoCodec codec) { - if (current_codec != codec) { - LOG_INFO(Service_NVDRV, "NVDEC video codec initialized to {}", static_cast(codec)); - current_codec = codec; - } + LOG_INFO(Service_NVDRV, "NVDEC video codec initialized to {}", codec); + current_codec = codec; } void Codec::StateWrite(u32 offset, u64 arguments) { @@ -57,6 +55,7 @@ void Codec::StateWrite(u32 offset, u64 arguments) { void Codec::Decode() { bool is_first_frame = false; + if (!initialized) { if (current_codec == NvdecCommon::VideoCodec::H264) { av_codec = avcodec_find_decoder(AV_CODEC_ID_H264); diff --git a/src/video_core/command_classes/codecs/h264.cpp b/src/video_core/command_classes/codecs/h264.cpp index 65bbeac78..fea6aed98 100755 --- a/src/video_core/command_classes/codecs/h264.cpp +++ b/src/video_core/command_classes/codecs/h264.cpp @@ -19,7 +19,7 @@ // #include -#include "common/bit_util.h" +#include #include "video_core/command_classes/codecs/h264.h" #include "video_core/gpu.h" #include "video_core/memory_manager.h" @@ -266,7 +266,7 @@ void H264BitWriter::WriteExpGolombCodedInt(s32 value) { } void H264BitWriter::WriteExpGolombCodedUInt(u32 value) { - const s32 size = 32 - Common::CountLeadingZeroes32(static_cast(value + 1)); + const s32 size = 32 - std::countl_zero(value + 1); WriteBits(1, size); value -= (1U << (size - 1)) - 1; diff --git a/src/video_core/command_classes/nvdec.cpp b/src/video_core/command_classes/nvdec.cpp index e4f919afd..79e1f4e13 100755 --- a/src/video_core/command_classes/nvdec.cpp +++ b/src/video_core/command_classes/nvdec.cpp @@ -12,16 +12,16 @@ Nvdec::Nvdec(GPU& gpu_) : gpu(gpu_), codec(std::make_unique(gpu)) {} Nvdec::~Nvdec() = default; -void Nvdec::ProcessMethod(Method method, u32 argument) { +void Nvdec::ProcessMethod(Method method, const std::vector& arguments) { if (method == Method::SetVideoCodec) { - codec->StateWrite(static_cast(method), argument); + codec->StateWrite(static_cast(method), arguments[0]); } else { - codec->StateWrite(static_cast(method), static_cast(argument) << 8); + codec->StateWrite(static_cast(method), static_cast(arguments[0]) << 8); } switch (method) { case Method::SetVideoCodec: - codec->SetTargetCodec(static_cast(argument)); + codec->SetTargetCodec(static_cast(arguments[0])); break; case Method::Execute: Execute(); diff --git a/src/video_core/command_classes/nvdec.h b/src/video_core/command_classes/nvdec.h index e66be80b8..e4877c533 100755 --- a/src/video_core/command_classes/nvdec.h +++ b/src/video_core/command_classes/nvdec.h @@ -23,7 +23,7 @@ public: ~Nvdec(); /// Writes the method into the state, Invoke Execute() if encountered - void ProcessMethod(Method method, u32 argument); + void ProcessMethod(Method method, const std::vector& arguments); /// Return most recently decoded frame [[nodiscard]] AVFramePtr GetFrame(); diff --git a/src/video_core/command_classes/vic.cpp b/src/video_core/command_classes/vic.cpp index 26ff755d0..55e632346 100755 --- a/src/video_core/command_classes/vic.cpp +++ b/src/video_core/command_classes/vic.cpp @@ -18,14 +18,18 @@ extern "C" { namespace Tegra { Vic::Vic(GPU& gpu_, std::shared_ptr nvdec_processor_) - : gpu(gpu_), - nvdec_processor(std::move(nvdec_processor_)), converted_frame_buffer{nullptr, av_free} {} - + : gpu(gpu_), nvdec_processor(std::move(nvdec_processor_)) {} Vic::~Vic() = default; -void Vic::ProcessMethod(Method method, u32 argument) { - LOG_DEBUG(HW_GPU, "Vic method 0x{:X}", static_cast(method)); - const u64 arg = static_cast(argument) << 8; +void Vic::VicStateWrite(u32 offset, u32 arguments) { + u8* const state_offset = reinterpret_cast(&vic_state) + offset * sizeof(u32); + std::memcpy(state_offset, &arguments, sizeof(u32)); +} + +void Vic::ProcessMethod(Method method, const std::vector& arguments) { + LOG_DEBUG(HW_GPU, "Vic method 0x{:X}", method); + VicStateWrite(static_cast(method), arguments[0]); + const u64 arg = static_cast(arguments[0]) << 8; switch (method) { case Method::Execute: Execute(); @@ -49,7 +53,8 @@ void Vic::ProcessMethod(Method method, u32 argument) { void Vic::Execute() { if (output_surface_luma_address == 0) { - LOG_ERROR(Service_NVDRV, "VIC Luma address not set."); + LOG_ERROR(Service_NVDRV, "VIC Luma address not set. Received 0x{:X}", + vic_state.output_surface.luma_offset); return; } const VicConfig config{gpu.MemoryManager().Read(config_struct_address + 0x20)}; @@ -84,10 +89,8 @@ void Vic::Execute() { // Get Converted frame const std::size_t linear_size = frame->width * frame->height * 4; - // Only allocate frame_buffer once per stream, as the size is not expected to change - if (!converted_frame_buffer) { - converted_frame_buffer = AVMallocPtr{static_cast(av_malloc(linear_size)), av_free}; - } + using AVMallocPtr = std::unique_ptr; + AVMallocPtr converted_frame_buffer{static_cast(av_malloc(linear_size)), av_free}; const int converted_stride{frame->width * 4}; u8* const converted_frame_buf_addr{converted_frame_buffer.get()}; @@ -101,12 +104,12 @@ void Vic::Execute() { const u32 block_height = static_cast(config.block_linear_height_log2); const auto size = Tegra::Texture::CalculateSize(true, 4, frame->width, frame->height, 1, block_height, 0); - luma_buffer.resize(size); + std::vector swizzled_data(size); Tegra::Texture::SwizzleSubrect(frame->width, frame->height, frame->width * 4, - frame->width, 4, luma_buffer.data(), + frame->width, 4, swizzled_data.data(), converted_frame_buffer.get(), block_height, 0, 0); - gpu.MemoryManager().WriteBlock(output_surface_luma_address, luma_buffer.data(), size); + gpu.MemoryManager().WriteBlock(output_surface_luma_address, swizzled_data.data(), size); gpu.Maxwell3D().OnMemoryWrite(); } else { // send pitch linear frame @@ -131,15 +134,15 @@ void Vic::Execute() { const auto stride = frame->linesize[0]; const auto half_stride = frame->linesize[1]; - luma_buffer.resize(aligned_width * surface_height); - chroma_buffer.resize(aligned_width * half_height); + std::vector luma_buffer(aligned_width * surface_height); + std::vector chroma_buffer(aligned_width * half_height); // Populate luma buffer for (std::size_t y = 0; y < surface_height - 1; ++y) { - const std::size_t src = y * stride; - const std::size_t dst = y * aligned_width; + std::size_t src = y * stride; + std::size_t dst = y * aligned_width; - const std::size_t size = surface_width; + std::size_t size = surface_width; for (std::size_t offset = 0; offset < size; ++offset) { luma_buffer[dst + offset] = luma_ptr[src + offset]; @@ -150,8 +153,8 @@ void Vic::Execute() { // Populate chroma buffer from both channels with interleaving. for (std::size_t y = 0; y < half_height; ++y) { - const std::size_t src = y * half_stride; - const std::size_t dst = y * aligned_width; + std::size_t src = y * half_stride; + std::size_t dst = y * aligned_width; for (std::size_t x = 0; x < half_width; ++x) { chroma_buffer[dst + x * 2] = chroma_b_ptr[src + x]; diff --git a/src/video_core/command_classes/vic.h b/src/video_core/command_classes/vic.h index f5a2ed100..8c4e284a1 100755 --- a/src/video_core/command_classes/vic.h +++ b/src/video_core/command_classes/vic.h @@ -15,6 +15,43 @@ namespace Tegra { class GPU; class Nvdec; +struct PlaneOffsets { + u32 luma_offset{}; + u32 chroma_u_offset{}; + u32 chroma_v_offset{}; +}; + +struct VicRegisters { + INSERT_PADDING_WORDS(64); + u32 nop{}; + INSERT_PADDING_WORDS(15); + u32 pm_trigger{}; + INSERT_PADDING_WORDS(47); + u32 set_application_id{}; + u32 set_watchdog_timer{}; + INSERT_PADDING_WORDS(17); + u32 context_save_area{}; + u32 context_switch{}; + INSERT_PADDING_WORDS(43); + u32 execute{}; + INSERT_PADDING_WORDS(63); + std::array, 8> surfacex_slots{}; + u32 picture_index{}; + u32 control_params{}; + u32 config_struct_offset{}; + u32 filter_struct_offset{}; + u32 palette_offset{}; + u32 hist_offset{}; + u32 context_id{}; + u32 fce_ucode_size{}; + PlaneOffsets output_surface{}; + u32 fce_ucode_offset{}; + INSERT_PADDING_WORDS(4); + std::array slot_context_id{}; + INSERT_PADDING_WORDS(16); +}; +static_assert(sizeof(VicRegisters) == 0x7A0, "VicRegisters is an invalid size"); + class Vic { public: enum class Method : u32 { @@ -30,11 +67,14 @@ public: ~Vic(); /// Write to the device state. - void ProcessMethod(Method method, u32 argument); + void ProcessMethod(Method method, const std::vector& arguments); private: void Execute(); + void VicStateWrite(u32 offset, u32 arguments); + VicRegisters vic_state{}; + enum class VideoPixelFormat : u64_le { RGBA8 = 0x1f, BGRA8 = 0x20, @@ -48,6 +88,8 @@ private: BitField<9, 2, u64_le> chroma_loc_vert; BitField<11, 4, u64_le> block_linear_kind; BitField<15, 4, u64_le> block_linear_height_log2; + BitField<19, 3, u64_le> reserved0; + BitField<22, 10, u64_le> reserved1; BitField<32, 14, u64_le> surface_width_minus1; BitField<46, 14, u64_le> surface_height_minus1; }; @@ -55,13 +97,6 @@ private: GPU& gpu; std::shared_ptr nvdec_processor; - /// Avoid reallocation of the following buffers every frame, as their - /// size does not change during a stream - using AVMallocPtr = std::unique_ptr; - AVMallocPtr converted_frame_buffer; - std::vector luma_buffer; - std::vector chroma_buffer; - GPUVAddr config_struct_address{}; GPUVAddr output_surface_luma_address{}; GPUVAddr output_surface_chroma_u_address{}; diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 23bd793bb..6ab06775f 100755 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -30,7 +30,8 @@ MICROPROFILE_DEFINE(GPU_wait, "GPU", "Wait for the GPU", MP_RGB(128, 128, 192)); GPU::GPU(Core::System& system_, bool is_async_, bool use_nvdec_) : system{system_}, memory_manager{std::make_unique(system)}, - dma_pusher{std::make_unique(system, *this)}, use_nvdec{use_nvdec_}, + dma_pusher{std::make_unique(system, *this)}, + cdma_pusher{std::make_unique(*this)}, use_nvdec{use_nvdec_}, maxwell_3d{std::make_unique(system, *memory_manager)}, fermi_2d{std::make_unique()}, kepler_compute{std::make_unique(system, *memory_manager)}, @@ -493,7 +494,8 @@ void GPU::PushCommandBuffer(Tegra::ChCommandHeaderList& entries) { // TODO(ameerj): RE proper async nvdec operation // gpu_thread.SubmitCommandBuffer(std::move(entries)); - cdma_pusher->ProcessEntries(std::move(entries)); + cdma_pusher->Push(std::move(entries)); + cdma_pusher->DispatchCalls(); } void GPU::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp index a43f725f3..7e490bcc3 100755 --- a/src/video_core/gpu_thread.cpp +++ b/src/video_core/gpu_thread.cpp @@ -47,7 +47,8 @@ static void RunThread(Core::System& system, VideoCore::RendererBase& renderer, dma_pusher.DispatchCalls(); } else if (auto* command_list = std::get_if(&next.data)) { // NVDEC - cdma_pusher.ProcessEntries(std::move(command_list->entries)); + cdma_pusher.Push(std::move(command_list->entries)); + cdma_pusher.DispatchCalls(); } else if (const auto* data = std::get_if(&next.data)) { renderer.SwapBuffers(data->framebuffer ? &*data->framebuffer : nullptr); } else if (std::holds_alternative(next.data)) { diff --git a/src/video_core/texture_cache/accelerated_swizzle.cpp b/src/video_core/texture_cache/accelerated_swizzle.cpp index a4fc1184b..15585caeb 100755 --- a/src/video_core/texture_cache/accelerated_swizzle.cpp +++ b/src/video_core/texture_cache/accelerated_swizzle.cpp @@ -27,7 +27,7 @@ BlockLinearSwizzle2DParams MakeBlockLinearSwizzle2DParams(const SwizzleParameter const Extent3D num_tiles = swizzle.num_tiles; const u32 bytes_per_block = BytesPerBlock(info.format); const u32 stride_alignment = CalculateLevelStrideAlignment(info, swizzle.level); - const u32 stride = Common::AlignBits(num_tiles.width, stride_alignment) * bytes_per_block; + const u32 stride = Common::AlignUpLog2(num_tiles.width, stride_alignment) * bytes_per_block; const u32 gobs_in_x = Common::DivCeilLog2(stride, GOB_SIZE_X_SHIFT); return BlockLinearSwizzle2DParams{ .origin{0, 0, 0}, @@ -47,7 +47,7 @@ BlockLinearSwizzle3DParams MakeBlockLinearSwizzle3DParams(const SwizzleParameter const Extent3D num_tiles = swizzle.num_tiles; const u32 bytes_per_block = BytesPerBlock(info.format); const u32 stride_alignment = CalculateLevelStrideAlignment(info, swizzle.level); - const u32 stride = Common::AlignBits(num_tiles.width, stride_alignment) * bytes_per_block; + const u32 stride = Common::AlignUpLog2(num_tiles.width, stride_alignment) * bytes_per_block; const u32 gobs_in_x = (stride + GOB_SIZE_X - 1) >> GOB_SIZE_X_SHIFT; const u32 block_size = gobs_in_x << (GOB_SIZE_SHIFT + block.height + block.depth); diff --git a/src/video_core/texture_cache/util.cpp b/src/video_core/texture_cache/util.cpp index 279932778..ce8fcfe0a 100755 --- a/src/video_core/texture_cache/util.cpp +++ b/src/video_core/texture_cache/util.cpp @@ -279,7 +279,7 @@ template const bool is_small = IsSmallerThanGobSize(blocks, gob, info.block.depth); const u32 alignment = is_small ? 0 : info.tile_width_spacing; return Extent2D{ - .width = Common::AlignBits(gobs.width, alignment), + .width = Common::AlignUpLog2(gobs.width, alignment), .height = gobs.height, }; } @@ -352,7 +352,7 @@ template // https://github.com/Ryujinx/Ryujinx/blob/1c9aba6de1520aea5480c032e0ff5664ac1bb36f/Ryujinx.Graphics.Texture/SizeCalculator.cs#L134 if (tile_width_spacing > 0) { const u32 alignment_log2 = GOB_SIZE_SHIFT + tile_width_spacing + block.height + block.depth; - return Common::AlignBits(size_bytes, alignment_log2); + return Common::AlignUpLog2(size_bytes, alignment_log2); } const u32 aligned_height = Common::AlignUp(size.height, tile_size_y); while (block.height != 0 && aligned_height <= (1U << (block.height - 1)) * GOB_SIZE_Y) { @@ -528,9 +528,9 @@ template const u32 alignment = StrideAlignment(num_tiles, info.block, bpp_log2, info.tile_width_spacing); const Extent3D mip_block = AdjustMipBlockSize(num_tiles, info.block, 0); return Extent3D{ - .width = Common::AlignBits(num_tiles.width, alignment), - .height = Common::AlignBits(num_tiles.height, GOB_SIZE_Y_SHIFT + mip_block.height), - .depth = Common::AlignBits(num_tiles.depth, GOB_SIZE_Z_SHIFT + mip_block.depth), + .width = Common::AlignUpLog2(num_tiles.width, alignment), + .height = Common::AlignUpLog2(num_tiles.height, GOB_SIZE_Y_SHIFT + mip_block.height), + .depth = Common::AlignUpLog2(num_tiles.depth, GOB_SIZE_Z_SHIFT + mip_block.depth), }; } diff --git a/src/video_core/textures/decoders.cpp b/src/video_core/textures/decoders.cpp index 9f5181318..62685a183 100755 --- a/src/video_core/textures/decoders.cpp +++ b/src/video_core/textures/decoders.cpp @@ -49,7 +49,7 @@ void Swizzle(std::span output, std::span input, u32 bytes_per_pixe // We can configure here a custom pitch // As it's not exposed 'width * bpp' will be the expected pitch. const u32 pitch = width * bytes_per_pixel; - const u32 stride = Common::AlignBits(width, stride_alignment) * bytes_per_pixel; + const u32 stride = Common::AlignUpLog2(width, stride_alignment) * bytes_per_pixel; const u32 gobs_in_x = Common::DivCeilLog2(stride, GOB_SIZE_X_SHIFT); const u32 block_size = gobs_in_x << (GOB_SIZE_SHIFT + block_height + block_depth); @@ -217,9 +217,9 @@ void SwizzleKepler(const u32 width, const u32 height, const u32 dst_x, const u32 std::size_t CalculateSize(bool tiled, u32 bytes_per_pixel, u32 width, u32 height, u32 depth, u32 block_height, u32 block_depth) { if (tiled) { - const u32 aligned_width = Common::AlignBits(width * bytes_per_pixel, GOB_SIZE_X_SHIFT); - const u32 aligned_height = Common::AlignBits(height, GOB_SIZE_Y_SHIFT + block_height); - const u32 aligned_depth = Common::AlignBits(depth, GOB_SIZE_Z_SHIFT + block_depth); + const u32 aligned_width = Common::AlignUpLog2(width * bytes_per_pixel, GOB_SIZE_X_SHIFT); + const u32 aligned_height = Common::AlignUpLog2(height, GOB_SIZE_Y_SHIFT + block_height); + const u32 aligned_depth = Common::AlignUpLog2(depth, GOB_SIZE_Z_SHIFT + block_depth); return aligned_width * aligned_height * aligned_depth; } else { return width * height * depth * bytes_per_pixel; diff --git a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp index ecdefbb66..d6eb3af31 100755 --- a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp +++ b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp @@ -112,7 +112,7 @@ private: if (commit->Contains(*candidate, size)) { candidate = std::nullopt; } - iterator = Common::AlignBits(commit->end, alignment_log2); + iterator = Common::AlignUpLog2(commit->end, alignment_log2); ++commit; } return candidate; diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp index 016066533..ac522fc68 100755 --- a/src/yuzu/configuration/configure_input_player_widget.cpp +++ b/src/yuzu/configuration/configure_input_player_widget.cpp @@ -250,9 +250,9 @@ void PlayerControlPreview::DrawLeftController(QPainter& p, const QPointF center) // D-pad constants const QPointF dpad_center = center + QPoint(9, 14); - const int dpad_distance = 23; - const int dpad_radius = 11; - const float dpad_arrow_size = 1.2f; + constexpr int dpad_distance = 23; + constexpr int dpad_radius = 11; + constexpr float dpad_arrow_size = 1.2f; // D-pad buttons p.setPen(colors.outline); @@ -344,8 +344,9 @@ void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center // Face buttons constants const QPointF face_center = center + QPoint(-9, -73); - const int face_distance = 23; - const int face_radius = 11; + constexpr int face_distance = 23; + constexpr int face_radius = 11; + constexpr float text_size = 1.1f; // Face buttons p.setPen(colors.outline); @@ -356,11 +357,12 @@ void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center DrawCircleButton(p, face_center + QPoint(-face_distance, 0), button_values[Y], face_radius); // Face buttons text - p.setPen(colors.font); - DrawText(p, face_center + QPoint(face_distance, 0), 10, QStringLiteral("A")); - DrawText(p, face_center + QPoint(0, face_distance), 10, QStringLiteral("B")); - DrawText(p, face_center + QPoint(0, -face_distance), 10, QStringLiteral("X")); - DrawText(p, face_center + QPoint(-face_distance + 1, 1), 10, QStringLiteral("Y")); + p.setPen(colors.transparent); + p.setBrush(colors.font); + DrawSymbol(p, face_center + QPoint(face_distance, 0), Symbol::A, text_size); + DrawSymbol(p, face_center + QPoint(0, face_distance), Symbol::B, text_size); + DrawSymbol(p, face_center + QPoint(0, -face_distance), Symbol::X, text_size); + DrawSymbol(p, face_center + QPoint(-face_distance, 1), Symbol::Y, text_size); // SR and SL buttons p.setPen(colors.outline); @@ -385,7 +387,9 @@ void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center DrawCircleButton(p, center + QPoint(-26, 66), button_values[Home], 12); button_color = colors.button; DrawCircleButton(p, center + QPoint(-26, 66), button_values[Home], 9); - DrawHouseIcon(p, center + QPoint(-26, 66), 5); + p.setPen(colors.transparent); + p.setBrush(colors.font2); + DrawSymbol(p, center + QPoint(-26, 66), Symbol::House, 5); } void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center) { @@ -457,9 +461,9 @@ void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center) // Face buttons constants const QPointF face_center = center + QPoint(65, -65); - const int face_distance = 20; - const int face_radius = 10; - const int text_size = 10; + constexpr int face_distance = 20; + constexpr int face_radius = 10; + constexpr float text_size = 1.0f; // Face buttons p.setPen(colors.outline); @@ -470,17 +474,18 @@ void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center) DrawCircleButton(p, face_center + QPoint(-face_distance, 0), button_values[Y], face_radius); // Face buttons text - p.setPen(colors.font); - DrawText(p, face_center + QPoint(face_distance, 0), text_size, QStringLiteral("A")); - DrawText(p, face_center + QPoint(0, face_distance), text_size, QStringLiteral("B")); - DrawText(p, face_center + QPoint(0, -face_distance), text_size, QStringLiteral("X")); - DrawText(p, face_center + QPointF(-face_distance + 0.5f, 1), text_size, QStringLiteral("Y")); + p.setPen(colors.transparent); + p.setBrush(colors.font); + DrawSymbol(p, face_center + QPoint(face_distance, 0), Symbol::A, text_size); + DrawSymbol(p, face_center + QPoint(0, face_distance), Symbol::B, text_size); + DrawSymbol(p, face_center + QPoint(0, -face_distance), Symbol::X, text_size); + DrawSymbol(p, face_center + QPoint(-face_distance, 1), Symbol::Y, text_size); // D-pad constants const QPointF dpad_center = center + QPoint(-65, 12); - const int dpad_distance = 20; - const int dpad_radius = 10; - const float dpad_arrow_size = 1.1f; + constexpr int dpad_distance = 20; + constexpr int dpad_radius = 10; + constexpr float dpad_arrow_size = 1.1f; // D-pad buttons p.setPen(colors.outline); @@ -516,7 +521,9 @@ void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center) DrawCircleButton(p, center + QPoint(50, 60), button_values[Home], 11); button_color = colors.button; DrawCircleButton(p, center + QPoint(50, 60), button_values[Home], 8.5f); - DrawHouseIcon(p, center + QPoint(50, 60), 4.2f); + p.setPen(colors.transparent); + p.setBrush(colors.font2); + DrawSymbol(p, center + QPoint(50, 60), Symbol::House, 4.2f); } void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF center) { @@ -539,9 +546,9 @@ void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF cen // Face buttons constants const QPointF face_center = center + QPoint(171, -41); - const int face_distance = 12; - const int face_radius = 6; - const float text_size = 5.5f; + constexpr int face_distance = 12; + constexpr int face_radius = 6; + constexpr float text_size = 0.6f; // Face buttons p.setPen(colors.outline); @@ -552,17 +559,18 @@ void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF cen DrawCircleButton(p, face_center + QPoint(-face_distance, 0), button_values[Y], face_radius); // Face buttons text - p.setPen(colors.font); - DrawText(p, face_center + QPointF(face_distance + 0.2f, 0), text_size, QStringLiteral("A")); - DrawText(p, face_center + QPoint(0, face_distance), text_size, QStringLiteral("B")); - DrawText(p, face_center + QPoint(0, -face_distance), text_size, QStringLiteral("X")); - DrawText(p, face_center + QPointF(-face_distance + 0.2f, 0), text_size, QStringLiteral("Y")); + p.setPen(colors.transparent); + p.setBrush(colors.font); + DrawSymbol(p, face_center + QPoint(face_distance, 0), Symbol::A, text_size); + DrawSymbol(p, face_center + QPoint(0, face_distance), Symbol::B, text_size); + DrawSymbol(p, face_center + QPoint(0, -face_distance), Symbol::X, text_size); + DrawSymbol(p, face_center + QPoint(-face_distance, 1), Symbol::Y, text_size); // D-pad constants const QPointF dpad_center = center + QPoint(-171, 8); - const int dpad_distance = 12; - const int dpad_radius = 6; - const float dpad_arrow_size = 0.68f; + constexpr int dpad_distance = 12; + constexpr int dpad_radius = 6; + constexpr float dpad_arrow_size = 0.68f; // D-pad buttons p.setPen(colors.outline); @@ -582,11 +590,12 @@ void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF cen // ZL and ZR buttons p.setPen(colors.outline); - DrawCircleButton(p, center + QPoint(-175, -120), button_values[ZL], 15); - DrawCircleButton(p, center + QPoint(175, -120), button_values[ZR], 15); - p.setPen(colors.font); - DrawText(p, center + QPoint(-175, -120), 9, QStringLiteral("ZL")); - DrawText(p, center + QPoint(175, -120), 9, QStringLiteral("ZR")); + DrawTriggerButton(p, center + QPoint(-210, -130), Direction::Left, button_values[ZL]); + DrawTriggerButton(p, center + QPoint(210, -130), Direction::Right, button_values[ZR]); + p.setPen(colors.transparent); + p.setBrush(colors.font); + DrawSymbol(p, center + QPoint(-210, -130), Symbol::ZL, 1.5f); + DrawSymbol(p, center + QPoint(210, -130), Symbol::ZR, 1.5f); // Minus and Plus button p.setPen(colors.outline); @@ -607,7 +616,9 @@ void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF cen DrawCircleButton(p, center + QPoint(161, 37), button_values[Home], 7); button_color = colors.button; DrawCircleButton(p, center + QPoint(161, 37), button_values[Home], 5); - DrawHouseIcon(p, center + QPoint(161, 37), 2.75f); + p.setPen(colors.transparent); + p.setBrush(colors.font2); + DrawSymbol(p, center + QPoint(161, 37), Symbol::House, 2.75f); } void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center) { @@ -630,9 +641,9 @@ void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center) // Face buttons constants const QPointF face_center = center + QPoint(105, -56); - const int face_distance = 31; - const int face_radius = 15; - const int text_size = 13; + constexpr int face_distance = 31; + constexpr int face_radius = 15; + constexpr float text_size = 1.5f; // Face buttons p.setPen(colors.outline); @@ -643,11 +654,12 @@ void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center) DrawCircleButton(p, face_center + QPoint(-face_distance, 0), button_values[Y], face_radius); // Face buttons text - p.setPen(colors.font); - DrawText(p, face_center + QPoint(face_distance, 0), text_size, QStringLiteral("A")); - DrawText(p, face_center + QPoint(0, face_distance), text_size, QStringLiteral("B")); - DrawText(p, face_center + QPoint(0, -face_distance), text_size, QStringLiteral("X")); - DrawText(p, face_center + QPoint(-face_distance, 1), text_size, QStringLiteral("Y")); + p.setPen(colors.transparent); + p.setBrush(colors.font); + DrawSymbol(p, face_center + QPoint(face_distance, 0), Symbol::A, text_size); + DrawSymbol(p, face_center + QPoint(0, face_distance), Symbol::B, text_size); + DrawSymbol(p, face_center + QPoint(0, -face_distance), Symbol::X, text_size); + DrawSymbol(p, face_center + QPoint(-face_distance, 1), Symbol::Y, text_size); // D-pad buttons const QPointF dpad_postion = center + QPoint(-61, 0); @@ -655,23 +667,28 @@ void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center) DrawArrowButton(p, dpad_postion, Direction::Left, button_values[DLeft]); DrawArrowButton(p, dpad_postion, Direction::Right, button_values[DRight]); DrawArrowButton(p, dpad_postion, Direction::Down, button_values[DDown]); + DrawArrowButtonOutline(p, dpad_postion); // ZL and ZR buttons p.setPen(colors.outline); - DrawCircleButton(p, center + QPoint(-175, -120), button_values[ZL], 15); - DrawCircleButton(p, center + QPoint(175, -120), button_values[ZR], 15); - p.setPen(colors.font); - DrawText(p, center + QPoint(-175, -120), 9, QStringLiteral("ZL")); - DrawText(p, center + QPoint(175, -120), 9, QStringLiteral("ZR")); + DrawTriggerButton(p, center + QPoint(-210, -130), Direction::Left, button_values[ZL]); + DrawTriggerButton(p, center + QPoint(210, -130), Direction::Right, button_values[ZR]); + p.setPen(colors.transparent); + p.setBrush(colors.font); + DrawSymbol(p, center + QPoint(-210, -130), Symbol::ZL, 1.5f); + DrawSymbol(p, center + QPoint(210, -130), Symbol::ZR, 1.5f); // Minus and Plus buttons p.setPen(colors.outline); DrawCircleButton(p, center + QPoint(-50, -86), button_values[Minus], 9); - DrawCircleButton(p, center + QPoint(49, -86), button_values[Plus], 9); + DrawCircleButton(p, center + QPoint(50, -86), button_values[Plus], 9); + + // Minus and Plus symbols p.setPen(colors.font2); p.setBrush(colors.font2); - DrawRectangle(p, center + QPoint(-50, -86), 8, 2); - DrawText(p, center + QPointF(49.5f, -86), 12, QStringLiteral("+")); + DrawRectangle(p, center + QPoint(-50, -86), 9, 1.5f); + DrawRectangle(p, center + QPoint(50, -86), 9, 1.5f); + DrawRectangle(p, center + QPoint(50, -86), 1.5f, 9); // Screenshot button p.setPen(colors.outline); @@ -683,21 +700,96 @@ void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center) // Home Button p.setPen(colors.outline); button_color = colors.slider_button; - DrawCircleButton(p, center + QPoint(29, -56), button_values[Home], 9); + DrawCircleButton(p, center + QPoint(29, -56), button_values[Home], 10.0f); button_color = colors.button; DrawCircleButton(p, center + QPoint(29, -56), button_values[Home], 7.1f); - DrawHouseIcon(p, center + QPoint(29, -56), 3.9f); + p.setPen(colors.transparent); + p.setBrush(colors.font2); + DrawSymbol(p, center + QPoint(29, -56), Symbol::House, 3.9f); } +constexpr std::array symbol_a = { + -1.085f, -5.2f, 1.085f, -5.2f, 5.085f, 5.0f, 2.785f, 5.0f, 1.785f, + 2.65f, -1.785f, 2.65f, -2.785f, 5.0f, -5.085f, 5.0f, -1.4f, 1.0f, + 0.0f, -2.8f, 1.4f, 1.0f, -1.4f, 1.0f, -5.085f, 5.0f, +}; +constexpr std::array symbol_b = { + -4.0f, 0.0f, -4.0f, 0.0f, -4.0f, -0.1f, -3.8f, -5.1f, 1.8f, -5.0f, 2.3f, -4.9f, 2.6f, + -4.8f, 2.8f, -4.7f, 2.9f, -4.6f, 3.1f, -4.5f, 3.2f, -4.4f, 3.4f, -4.3f, 3.4f, -4.2f, + 3.5f, -4.1f, 3.7f, -4.0f, 3.7f, -3.9f, 3.8f, -3.8f, 3.8f, -3.7f, 3.9f, -3.6f, 3.9f, + -3.5f, 4.0f, -3.4f, 4.0f, -3.3f, 4.1f, -3.1f, 4.1f, -3.0f, 4.0f, -2.0f, 4.0f, -1.9f, + 3.9f, -1.7f, 3.9f, -1.6f, 3.8f, -1.5f, 3.8f, -1.4f, 3.7f, -1.3f, 3.7f, -1.2f, 3.6f, + -1.1f, 3.6f, -1.0f, 3.5f, -0.9f, 3.3f, -0.8f, 3.3f, -0.7f, 3.2f, -0.6f, 3.0f, -0.5f, + 2.9f, -0.4f, 2.7f, -0.3f, 2.9f, -0.2f, 3.2f, -0.1f, 3.3f, 0.0f, 3.5f, 0.1f, 3.6f, + 0.2f, 3.8f, 0.3f, 3.9f, 0.4f, 4.0f, 0.6f, 4.1f, 0.7f, 4.3f, 0.8f, 4.3f, 0.9f, + 4.4f, 1.0f, 4.4f, 1.1f, 4.5f, 1.3f, 4.5f, 1.4f, 4.6f, 1.6f, 4.6f, 1.7f, 4.5f, + 2.8f, 4.5f, 2.9f, 4.4f, 3.1f, 4.4f, 3.2f, 4.3f, 3.4f, 4.3f, 3.5f, 4.2f, 3.6f, + 4.2f, 3.7f, 4.1f, 3.8f, 4.1f, 3.9f, 4.0f, 4.0f, 3.9f, 4.2f, 3.8f, 4.3f, 3.6f, + 4.4f, 3.6f, 4.5f, 3.4f, 4.6f, 3.3f, 4.7f, 3.1f, 4.8f, 2.8f, 4.9f, 2.6f, 5.0f, + 2.1f, 5.1f, -4.0f, 5.0f, -4.0f, 4.9f, + + -4.0f, 0.0f, 1.1f, 3.4f, 1.1f, 3.4f, 1.5f, 3.3f, 1.8f, 3.2f, 2.0f, 3.1f, 2.1f, + 3.0f, 2.3f, 2.9f, 2.3f, 2.8f, 2.4f, 2.7f, 2.4f, 2.6f, 2.5f, 2.3f, 2.5f, 2.2f, + 2.4f, 1.7f, 2.4f, 1.6f, 2.3f, 1.4f, 2.3f, 1.3f, 2.2f, 1.2f, 2.2f, 1.1f, 2.1f, + 1.0f, 1.9f, 0.9f, 1.6f, 0.8f, 1.4f, 0.7f, -1.9f, 0.6f, -1.9f, 0.7f, -1.8f, 3.4f, + 1.1f, 3.4f, -4.0f, 0.0f, + + 0.3f, -1.1f, 0.3f, -1.1f, 1.3f, -1.2f, 1.5f, -1.3f, 1.8f, -1.4f, 1.8f, -1.5f, 1.9f, + -1.6f, 2.0f, -1.8f, 2.0f, -1.9f, 2.1f, -2.0f, 2.1f, -2.1f, 2.0f, -2.7f, 2.0f, -2.8f, + 1.9f, -2.9f, 1.9f, -3.0f, 1.8f, -3.1f, 1.6f, -3.2f, 1.6f, -3.3f, 1.3f, -3.4f, -1.9f, + -3.3f, -1.9f, -3.2f, -1.8f, -1.0f, 0.2f, -1.1f, 0.3f, -1.1f, -4.0f, 0.0f, +}; + +constexpr std::array symbol_y = { + -4.79f, -4.9f, -2.44f, -4.9f, 0.0f, -0.9f, 2.44f, -4.9f, 4.79f, + -4.9f, 1.05f, 1.0f, 1.05f, 5.31f, -1.05f, 5.31f, -1.05f, 1.0f, + +}; + +constexpr std::array symbol_x = { + -4.4f, -5.0f, -2.0f, -5.0f, 0.0f, -1.7f, 2.0f, -5.0f, 4.4f, -5.0f, 1.2f, 0.0f, + 4.4f, 5.0f, 2.0f, 5.0f, 0.0f, 1.7f, -2.0f, 5.0f, -4.4f, 5.0f, -1.2f, 0.0f, + +}; + +constexpr std::array symbol_zl = { + -2.6f, -2.13f, -5.6f, -2.13f, -5.6f, -3.23f, -0.8f, -3.23f, -0.8f, -2.13f, -4.4f, 2.12f, + -0.7f, 2.12f, -0.7f, 3.22f, -6.0f, 3.22f, -6.0f, 2.12f, 2.4f, -3.23f, 2.4f, 2.1f, + 5.43f, 2.1f, 5.43f, 3.22f, 0.98f, 3.22f, 0.98f, -3.23f, 2.4f, -3.23f, -6.0f, 2.12f, +}; + +constexpr std::array symbol_zr = { + -2.6f, -2.13f, -5.6f, -2.13f, -5.6f, -3.23f, -0.8f, -3.23f, -0.8f, -2.13f, -4.4f, 2.12f, -0.7f, + 2.12f, -0.7f, 3.22f, -6.0f, 3.22f, -6.0f, 2.12f, + + 1.0f, 0.0f, 1.0f, -0.1f, 1.1f, -3.3f, 4.3f, -3.2f, 5.1f, -3.1f, 5.4f, -3.0f, 5.6f, + -2.9f, 5.7f, -2.8f, 5.9f, -2.7f, 5.9f, -2.6f, 6.0f, -2.5f, 6.1f, -2.3f, 6.2f, -2.2f, + 6.2f, -2.1f, 6.3f, -2.0f, 6.3f, -1.9f, 6.2f, -0.8f, 6.2f, -0.7f, 6.1f, -0.6f, 6.1f, + -0.5f, 6.0f, -0.4f, 6.0f, -0.3f, 5.9f, -0.2f, 5.7f, -0.1f, 5.7f, 0.0f, 5.6f, 0.1f, + 5.4f, 0.2f, 5.1f, 0.3f, 4.7f, 0.4f, 4.7f, 0.5f, 4.9f, 0.6f, 5.0f, 0.7f, 5.2f, + 0.8f, 5.2f, 0.9f, 5.3f, 1.0f, 5.5f, 1.1f, 5.5f, 1.2f, 5.6f, 1.3f, 5.7f, 1.5f, + 5.8f, 1.6f, 5.9f, 1.8f, 6.0f, 1.9f, 6.1f, 2.1f, 6.2f, 2.2f, 6.2f, 2.3f, 6.3f, + 2.4f, 6.4f, 2.6f, 6.5f, 2.7f, 6.6f, 2.9f, 6.7f, 3.0f, 6.7f, 3.1f, 6.8f, 3.2f, + 6.8f, 3.3f, 5.3f, 3.2f, 5.2f, 3.1f, 5.2f, 3.0f, 5.1f, 2.9f, 5.0f, 2.7f, 4.9f, + 2.6f, 4.8f, 2.4f, 4.7f, 2.3f, 4.6f, 2.1f, 4.5f, 2.0f, 4.4f, 1.8f, 4.3f, 1.7f, + 4.1f, 1.4f, 4.0f, 1.3f, 3.9f, 1.1f, 3.8f, 1.0f, 3.6f, 0.9f, 3.6f, 0.8f, 3.5f, + 0.7f, 3.3f, 0.6f, 2.9f, 0.5f, 2.3f, 0.6f, 2.3f, 0.7f, 2.2f, 3.3f, 1.0f, 3.2f, + 1.0f, 3.1f, 1.0f, 0.0f, + + 4.2f, -0.5f, 4.2f, -0.5f, 4.4f, -0.6f, 4.7f, -0.7f, 4.8f, -0.8f, 4.9f, -1.0f, 5.0f, + -1.1f, 5.0f, -1.2f, 4.9f, -1.7f, 4.9f, -1.8f, 4.8f, -1.9f, 4.8f, -2.0f, 4.6f, -2.1f, + 4.3f, -2.2f, 2.3f, -2.1f, 2.3f, -2.0f, 2.4f, -0.5f, 4.2f, -0.5f, 1.0f, 0.0f, -6.0f, + 2.12f, +}; + constexpr std::array house = { -1.3f, 0.0f, -0.93f, 0.0f, -0.93f, 1.15f, 0.93f, 1.15f, 0.93f, 0.0f, 1.3f, 0.0f, 0.0f, -1.2f, -1.3f, 0.0f, -0.43f, 0.0f, -0.43f, .73f, 0.43f, .73f, 0.43f, 0.0f, }; -constexpr std::array up_arrow_button = { - -8.6f, -30.0f, -9.0f, -29.8f, -9.3f, -29.5f, -9.5f, -29.1f, -9.5f, -28.7f, - -9.1f, -9.1f, -8.8f, -8.8f, 0.3f, -0.3f, 0.6f, -0.6f, 9.4f, -9.8f, - 9.4f, -10.2f, 8.9f, -29.8f, 8.5f, -30.0f, 8.1f, -30.1f, 7.7f, -30.1f, +constexpr std::array up_arrow_button = { + 9.1f, -9.1f, 9.1f, -30.0f, 8.1f, -30.1f, 7.7f, -30.1f, -8.6f, -30.0f, -9.0f, + -29.8f, -9.3f, -29.5f, -9.5f, -29.1f, -9.1f, -28.7f, -9.1f, -9.1f, 0.0f, 0.6f, }; constexpr std::array up_arrow_symbol = { @@ -710,6 +802,20 @@ constexpr std::array up_arrow = { -9.5f, -29.1f, -9.5f, -28.7f, -9.1f, -9.1f, -8.8f, -8.8f, }; +constexpr std::array trigger_button = { + 5.5f, -12.6f, 5.8f, -12.6f, 6.7f, -12.5f, 8.1f, -12.3f, 8.6f, -12.2f, 9.2f, -12.0f, + 9.5f, -11.9f, 9.9f, -11.8f, 10.6f, -11.5f, 11.0f, -11.3f, 11.2f, -11.2f, 11.4f, -11.1f, + 11.8f, -10.9f, 12.0f, -10.8f, 12.2f, -10.7f, 12.4f, -10.5f, 12.6f, -10.4f, 12.8f, -10.3f, + 13.6f, -9.7f, 13.8f, -9.6f, 13.9f, -9.4f, 14.1f, -9.3f, 14.8f, -8.6f, 15.0f, -8.5f, + 15.1f, -8.3f, 15.6f, -7.8f, 15.7f, -7.6f, 16.1f, -7.0f, 16.3f, -6.8f, 16.4f, -6.6f, + 16.5f, -6.4f, 16.8f, -6.0f, 16.9f, -5.8f, 17.0f, -5.6f, 17.1f, -5.4f, 17.2f, -5.2f, + 17.3f, -5.0f, 17.4f, -4.8f, 17.5f, -4.6f, 17.6f, -4.4f, 17.7f, -4.1f, 17.8f, -3.9f, + 17.9f, -3.5f, 18.0f, -3.3f, 18.1f, -3.0f, 18.2f, -2.6f, 18.2f, -2.3f, 18.3f, -2.1f, + 18.3f, -1.9f, 18.4f, -1.4f, 18.5f, -1.2f, 18.6f, -0.3f, 18.6f, 0.0f, 18.3f, 13.9f, + -17.0f, 13.8f, -17.0f, 13.6f, -16.4f, -11.4f, -16.3f, -11.6f, -16.1f, -11.8f, -15.7f, -12.0f, + -15.5f, -12.1f, -15.1f, -12.3f, -14.6f, -12.4f, -13.4f, -12.5f, +}; + constexpr std::array pro_left_trigger = { -65.2f, -132.6f, -68.2f, -134.1f, -71.3f, -135.5f, -74.4f, -136.7f, -77.6f, -137.6f, -80.9f, -138.1f, -84.3f, -138.3f, -87.6f, -138.3f, -91.0f, -138.1f, @@ -1660,9 +1766,29 @@ void PlayerControlPreview::DrawCircleButton(QPainter& p, const QPointF center, b } p.drawEllipse(center, button_size, button_size); } + +void PlayerControlPreview::DrawArrowButtonOutline(QPainter& p, const QPointF center) { + const std::size_t arrow_points = up_arrow_button.size() / 2; + std::array arrow_button_outline; + + for (std::size_t point = 0; point < arrow_points - 1; ++point) { + arrow_button_outline[point] = + center + QPointF(up_arrow_button[point * 2], up_arrow_button[point * 2 + 1]); + arrow_button_outline[(arrow_points - 1) * 2 - point - 1] = + center + QPointF(up_arrow_button[point * 2 + 1], up_arrow_button[point * 2]); + arrow_button_outline[(arrow_points - 1) * 2 + point] = + center + QPointF(-up_arrow_button[point * 2], -up_arrow_button[point * 2 + 1]); + arrow_button_outline[(arrow_points - 1) * 4 - point - 1] = + center + QPointF(-up_arrow_button[point * 2 + 1], -up_arrow_button[point * 2]); + } + // Draw arrow button outline + p.setPen(colors.outline); + p.setBrush(colors.transparent); + DrawPolygon(p, arrow_button_outline); +} + void PlayerControlPreview::DrawArrowButton(QPainter& p, const QPointF center, const Direction direction, bool pressed) { - std::array arrow_button; QPoint offset; @@ -1671,50 +1797,141 @@ void PlayerControlPreview::DrawArrowButton(QPainter& p, const QPointF center, case Direction::Up: arrow_button[point] = center + QPointF(up_arrow_button[point * 2], up_arrow_button[point * 2 + 1]); - offset = QPoint(0, -20); break; case Direction::Left: arrow_button[point] = center + QPointF(up_arrow_button[point * 2 + 1], up_arrow_button[point * 2]); - offset = QPoint(-20, 0); break; case Direction::Right: arrow_button[point] = center + QPointF(-up_arrow_button[point * 2 + 1], up_arrow_button[point * 2]); - offset = QPoint(20, 0); break; case Direction::Down: arrow_button[point] = center + QPointF(up_arrow_button[point * 2], -up_arrow_button[point * 2 + 1]); - offset = QPoint(0, 20); break; case Direction::None: break; } } + // Draw arrow button + p.setPen(pressed ? colors.highlight : colors.button); + p.setBrush(pressed ? colors.highlight : colors.button); + DrawPolygon(p, arrow_button); + + switch (direction) { + case Direction::Up: + offset = QPoint(0, -20); + break; + case Direction::Left: + offset = QPoint(-20, 0); + break; + case Direction::Right: + offset = QPoint(20, 0); + break; + case Direction::Down: + offset = QPoint(0, 20); + break; + case Direction::None: + offset = QPoint(0, 0); + break; + } + + // Draw arrow icon + p.setPen(colors.font2); + p.setBrush(colors.font2); + DrawArrow(p, center + offset, direction, 1.0f); +} + +void PlayerControlPreview::DrawTriggerButton(QPainter& p, const QPointF center, + const Direction direction, bool pressed) { + std::array qtrigger_button; + QPoint offset; + + for (std::size_t point = 0; point < trigger_button.size() / 2; ++point) { + switch (direction) { + case Direction::Left: + qtrigger_button[point] = + center + QPointF(-trigger_button[point * 2], trigger_button[point * 2 + 1]); + break; + case Direction::Right: + qtrigger_button[point] = + center + QPointF(trigger_button[point * 2], trigger_button[point * 2 + 1]); + break; + case Direction::Up: + case Direction::Down: + case Direction::None: + break; + } + } + // Draw arrow button p.setPen(colors.outline); p.setBrush(pressed ? colors.highlight : colors.button); - DrawPolygon(p, arrow_button); - - // Draw arrow icon - p.setPen(colors.font2); - p.setBrush(colors.font2); - DrawArrow(p, center + offset, direction, 1.0f); + DrawPolygon(p, qtrigger_button); } -void PlayerControlPreview::DrawHouseIcon(QPainter& p, const QPointF center, float icon_size) { +void PlayerControlPreview::DrawSymbol(QPainter& p, const QPointF center, Symbol symbol, + float icon_size) { std::array house_icon; - - for (std::size_t point = 0; point < house.size() / 2; ++point) { - house_icon[point] = center + QPointF(house[point * 2] * icon_size, - (house[point * 2 + 1] - 0.025f) * icon_size); + std::array a_icon; + std::array b_icon; + std::array x_icon; + std::array y_icon; + std::array zl_icon; + std::array zr_icon; + switch (symbol) { + case Symbol::House: + for (std::size_t point = 0; point < house.size() / 2; ++point) { + house_icon[point] = center + QPointF(house[point * 2] * icon_size, + (house[point * 2 + 1] - 0.025f) * icon_size); + } + p.drawPolygon(house_icon.data(), static_cast(house_icon.size())); + break; + case Symbol::A: + for (std::size_t point = 0; point < symbol_a.size() / 2; ++point) { + a_icon[point] = center + QPointF(symbol_a[point * 2] * icon_size, + symbol_a[point * 2 + 1] * icon_size); + } + p.drawPolygon(a_icon.data(), static_cast(a_icon.size())); + break; + case Symbol::B: + for (std::size_t point = 0; point < symbol_b.size() / 2; ++point) { + b_icon[point] = center + QPointF(symbol_b[point * 2] * icon_size, + symbol_b[point * 2 + 1] * icon_size); + } + p.drawPolygon(b_icon.data(), static_cast(b_icon.size())); + break; + case Symbol::X: + for (std::size_t point = 0; point < symbol_x.size() / 2; ++point) { + x_icon[point] = center + QPointF(symbol_x[point * 2] * icon_size, + symbol_x[point * 2 + 1] * icon_size); + } + p.drawPolygon(x_icon.data(), static_cast(x_icon.size())); + break; + case Symbol::Y: + for (std::size_t point = 0; point < symbol_y.size() / 2; ++point) { + y_icon[point] = center + QPointF(symbol_y[point * 2] * icon_size, + (symbol_y[point * 2 + 1] - 1.0f) * icon_size); + } + p.drawPolygon(y_icon.data(), static_cast(y_icon.size())); + break; + case Symbol::ZL: + for (std::size_t point = 0; point < symbol_zl.size() / 2; ++point) { + zl_icon[point] = center + QPointF(symbol_zl[point * 2] * icon_size, + symbol_zl[point * 2 + 1] * icon_size); + } + p.drawPolygon(zl_icon.data(), static_cast(zl_icon.size())); + break; + case Symbol::ZR: + for (std::size_t point = 0; point < symbol_zr.size() / 2; ++point) { + zr_icon[point] = center + QPointF(symbol_zr[point * 2] * icon_size, + symbol_zr[point * 2 + 1] * icon_size); + } + p.drawPolygon(zr_icon.data(), static_cast(zr_icon.size())); + break; } - - p.setPen(colors.transparent); - p.setBrush(colors.font2); - p.drawPolygon(house_icon.data(), static_cast(house_icon.size())); } void PlayerControlPreview::DrawArrow(QPainter& p, const QPointF center, const Direction direction, diff --git a/src/yuzu/configuration/configure_input_player_widget.h b/src/yuzu/configuration/configure_input_player_widget.h index 4122e3abd..785d37924 100755 --- a/src/yuzu/configuration/configure_input_player_widget.h +++ b/src/yuzu/configuration/configure_input_player_widget.h @@ -43,6 +43,16 @@ private: Left, }; + enum class Symbol { + House, + A, + B, + X, + Y, + ZL, + ZR, + }; + struct AxisValue { QPointF value{}; QPointF raw_value{}; @@ -120,10 +130,12 @@ private: Direction direction = Direction::None, float radius = 2); void DrawMinusButton(QPainter& p, QPointF center, bool pressed, int button_size); void DrawPlusButton(QPainter& p, QPointF center, bool pressed, int button_size); + void DrawArrowButtonOutline(QPainter& p, const QPointF center); void DrawArrowButton(QPainter& p, QPointF center, Direction direction, bool pressed); + void DrawTriggerButton(QPainter& p, QPointF center, Direction direction, bool pressed); // Draw icon functions - void DrawHouseIcon(QPainter& p, QPointF center, float icon_size); + void DrawSymbol(QPainter& p, QPointF center, Symbol symbol, float icon_size); void DrawArrow(QPainter& p, QPointF center, Direction direction, float size); // Draw primitive types