diff options
author | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> | 2016-09-18 02:38:01 +0200 |
---|---|---|
committer | Emmanuel Gil Peyrot <linkmauve@linkmauve.fr> | 2016-09-18 02:38:01 +0200 |
commit | dc8479928c5aee4c6ad6fe4f59006fb604cee701 (patch) | |
tree | 569a7f13128450bbab973236615587ff00bced5f /src/core/hw | |
parent | Travis: Import Dolphin’s clang-format hook. (diff) | |
download | yuzu-dc8479928c5aee4c6ad6fe4f59006fb604cee701.tar yuzu-dc8479928c5aee4c6ad6fe4f59006fb604cee701.tar.gz yuzu-dc8479928c5aee4c6ad6fe4f59006fb604cee701.tar.bz2 yuzu-dc8479928c5aee4c6ad6fe4f59006fb604cee701.tar.lz yuzu-dc8479928c5aee4c6ad6fe4f59006fb604cee701.tar.xz yuzu-dc8479928c5aee4c6ad6fe4f59006fb604cee701.tar.zst yuzu-dc8479928c5aee4c6ad6fe4f59006fb604cee701.zip |
Diffstat (limited to 'src/core/hw')
-rw-r--r-- | src/core/hw/gpu.cpp | 142 | ||||
-rw-r--r-- | src/core/hw/gpu.h | 84 | ||||
-rw-r--r-- | src/core/hw/hw.cpp | 13 | ||||
-rw-r--r-- | src/core/hw/hw.h | 42 | ||||
-rw-r--r-- | src/core/hw/lcd.cpp | 13 | ||||
-rw-r--r-- | src/core/hw/lcd.h | 19 | ||||
-rw-r--r-- | src/core/hw/y2r.cpp | 77 | ||||
-rw-r--r-- | src/core/hw/y2r.h | 3 |
8 files changed, 209 insertions, 184 deletions
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp index a4dfb7e43..bf2c066f4 100644 --- a/src/core/hw/gpu.cpp +++ b/src/core/hw/gpu.cpp @@ -12,15 +12,15 @@ #include "common/microprofile.h" #include "common/vector_math.h" -#include "core/settings.h" -#include "core/memory.h" #include "core/core_timing.h" +#include "core/memory.h" +#include "core/settings.h" #include "core/hle/service/gsp_gpu.h" #include "core/hle/service/hid/hid.h" -#include "core/hw/hw.h" #include "core/hw/gpu.h" +#include "core/hw/hw.h" #include "core/tracer/recorder.h" @@ -32,7 +32,6 @@ #include "video_core/debug_utils/debug_utils.h" - namespace GPU { Regs g_regs; @@ -49,7 +48,7 @@ static u64 frame_count; static bool last_skip_frame; template <typename T> -inline void Read(T &var, const u32 raw_addr) { +inline void Read(T& var, const u32 raw_addr) { u32 addr = raw_addr - HW::VADDR_GPU; u32 index = addr / 4; @@ -105,8 +104,7 @@ inline void Write(u32 addr, const T data) { // Memory fills are triggered once the fill value is written. case GPU_REG_INDEX_WORKAROUND(memory_fill_config[0].trigger, 0x00004 + 0x3): - case GPU_REG_INDEX_WORKAROUND(memory_fill_config[1].trigger, 0x00008 + 0x3): - { + case GPU_REG_INDEX_WORKAROUND(memory_fill_config[1].trigger, 0x00008 + 0x3): { const bool is_second_filler = (index != GPU_REG_INDEX(memory_fill_config[0].trigger)); auto& config = g_regs.memory_fill_config[is_second_filler]; @@ -125,7 +123,9 @@ inline void Write(u32 addr, const T data) { // regions that were between surfaces or within the touching // ones for cpu to manually fill here. if (!VideoCore::g_renderer->Rasterizer()->AccelerateFill(config)) { - Memory::RasterizerFlushAndInvalidateRegion(config.GetStartAddress(), config.GetEndAddress() - config.GetStartAddress()); + Memory::RasterizerFlushAndInvalidateRegion(config.GetStartAddress(), + config.GetEndAddress() - + config.GetStartAddress()); if (config.fill_24bit) { // fill with 24-bit values @@ -150,7 +150,8 @@ inline void Write(u32 addr, const T data) { } } - LOG_TRACE(HW_GPU, "MemoryFill from 0x%08x to 0x%08x", config.GetStartAddress(), config.GetEndAddress()); + LOG_TRACE(HW_GPU, "MemoryFill from 0x%08x to 0x%08x", config.GetStartAddress(), + config.GetEndAddress()); if (!is_second_filler) { GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PSC0); @@ -167,15 +168,15 @@ inline void Write(u32 addr, const T data) { break; } - case GPU_REG_INDEX(display_transfer_config.trigger): - { + case GPU_REG_INDEX(display_transfer_config.trigger): { MICROPROFILE_SCOPE(GPU_DisplayTransfer); const auto& config = g_regs.display_transfer_config; if (config.trigger & 1) { if (Pica::g_debug_context) - Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::IncomingDisplayTransfer, nullptr); + Pica::g_debug_context->OnEvent(Pica::DebugContext::Event::IncomingDisplayTransfer, + nullptr); if (!VideoCore::g_renderer->Rasterizer()->AccelerateDisplayTransfer(config)) { u8* src_pointer = Memory::GetPhysicalPointer(config.GetPhysicalInputAddress()); @@ -187,17 +188,23 @@ inline void Write(u32 addr, const T data) { u32 output_width = config.texture_copy.output_width * 16; u32 output_gap = config.texture_copy.output_gap * 16; - size_t contiguous_input_size = config.texture_copy.size / input_width * (input_width + input_gap); - Memory::RasterizerFlushRegion(config.GetPhysicalInputAddress(), static_cast<u32>(contiguous_input_size)); + size_t contiguous_input_size = + config.texture_copy.size / input_width * (input_width + input_gap); + Memory::RasterizerFlushRegion(config.GetPhysicalInputAddress(), + static_cast<u32>(contiguous_input_size)); - size_t contiguous_output_size = config.texture_copy.size / output_width * (output_width + output_gap); - Memory::RasterizerFlushAndInvalidateRegion(config.GetPhysicalOutputAddress(), static_cast<u32>(contiguous_output_size)); + size_t contiguous_output_size = + config.texture_copy.size / output_width * (output_width + output_gap); + Memory::RasterizerFlushAndInvalidateRegion( + config.GetPhysicalOutputAddress(), + static_cast<u32>(contiguous_output_size)); u32 remaining_size = config.texture_copy.size; u32 remaining_input = input_width; u32 remaining_output = output_width; while (remaining_size > 0) { - u32 copy_size = std::min({ remaining_input, remaining_output, remaining_size }); + u32 copy_size = + std::min({remaining_input, remaining_output, remaining_size}); std::memcpy(dst_pointer, src_pointer, copy_size); src_pointer += copy_size; @@ -217,10 +224,11 @@ inline void Write(u32 addr, const T data) { } } - LOG_TRACE(HW_GPU, "TextureCopy: 0x%X bytes from 0x%08X(%u+%u)-> 0x%08X(%u+%u), flags 0x%08X", - config.texture_copy.size, - config.GetPhysicalInputAddress(), input_width, input_gap, - config.GetPhysicalOutputAddress(), output_width, output_gap, + LOG_TRACE( + HW_GPU, + "TextureCopy: 0x%X bytes from 0x%08X(%u+%u)-> 0x%08X(%u+%u), flags 0x%08X", + config.texture_copy.size, config.GetPhysicalInputAddress(), input_width, + input_gap, config.GetPhysicalOutputAddress(), output_width, output_gap, config.flags); GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PPF); @@ -228,7 +236,8 @@ inline void Write(u32 addr, const T data) { } if (config.scaling > config.ScaleXY) { - LOG_CRITICAL(HW_GPU, "Unimplemented display transfer scaling mode %u", config.scaling.Value()); + LOG_CRITICAL(HW_GPU, "Unimplemented display transfer scaling mode %u", + config.scaling.Value()); UNIMPLEMENTED(); break; } @@ -245,11 +254,14 @@ inline void Write(u32 addr, const T data) { u32 output_width = config.output_width >> horizontal_scale; u32 output_height = config.output_height >> vertical_scale; - u32 input_size = config.input_width * config.input_height * GPU::Regs::BytesPerPixel(config.input_format); - u32 output_size = output_width * output_height * GPU::Regs::BytesPerPixel(config.output_format); + u32 input_size = config.input_width * config.input_height * + GPU::Regs::BytesPerPixel(config.input_format); + u32 output_size = + output_width * output_height * GPU::Regs::BytesPerPixel(config.output_format); Memory::RasterizerFlushRegion(config.GetPhysicalInputAddress(), input_size); - Memory::RasterizerFlushAndInvalidateRegion(config.GetPhysicalOutputAddress(), output_size); + Memory::RasterizerFlushAndInvalidateRegion(config.GetPhysicalOutputAddress(), + output_size); for (u32 y = 0; y < output_height; ++y) { for (u32 x = 0; x < output_width; ++x) { @@ -278,11 +290,14 @@ inline void Write(u32 addr, const T data) { u32 coarse_y = y & ~7; u32 stride = output_width * dst_bytes_per_pixel; - src_offset = (input_x + input_y * config.input_width) * src_bytes_per_pixel; - dst_offset = VideoCore::GetMortonOffset(x, y, dst_bytes_per_pixel) + coarse_y * stride; + src_offset = + (input_x + input_y * config.input_width) * src_bytes_per_pixel; + dst_offset = VideoCore::GetMortonOffset(x, y, dst_bytes_per_pixel) + + coarse_y * stride; } else { // Both input and output are linear - src_offset = (input_x + input_y * config.input_width) * src_bytes_per_pixel; + src_offset = + (input_x + input_y * config.input_width) * src_bytes_per_pixel; dst_offset = (x + y * output_width) * dst_bytes_per_pixel; } } else { @@ -291,7 +306,9 @@ inline void Write(u32 addr, const T data) { u32 coarse_y = input_y & ~7; u32 stride = config.input_width * src_bytes_per_pixel; - src_offset = VideoCore::GetMortonOffset(input_x, input_y, src_bytes_per_pixel) + coarse_y * stride; + src_offset = VideoCore::GetMortonOffset(input_x, input_y, + src_bytes_per_pixel) + + coarse_y * stride; dst_offset = (x + y * output_width) * dst_bytes_per_pixel; } else { // Both input and output are tiled @@ -301,20 +318,27 @@ inline void Write(u32 addr, const T data) { u32 in_coarse_y = input_y & ~7; u32 in_stride = config.input_width * src_bytes_per_pixel; - src_offset = VideoCore::GetMortonOffset(input_x, input_y, src_bytes_per_pixel) + in_coarse_y * in_stride; - dst_offset = VideoCore::GetMortonOffset(x, y, dst_bytes_per_pixel) + out_coarse_y * out_stride; + src_offset = VideoCore::GetMortonOffset(input_x, input_y, + src_bytes_per_pixel) + + in_coarse_y * in_stride; + dst_offset = VideoCore::GetMortonOffset(x, y, dst_bytes_per_pixel) + + out_coarse_y * out_stride; } } const u8* src_pixel = src_pointer + src_offset; src_color = DecodePixel(config.input_format, src_pixel); if (config.scaling == config.ScaleX) { - Math::Vec4<u8> pixel = DecodePixel(config.input_format, src_pixel + src_bytes_per_pixel); + Math::Vec4<u8> pixel = + DecodePixel(config.input_format, src_pixel + src_bytes_per_pixel); src_color = ((src_color + pixel) / 2).Cast<u8>(); } else if (config.scaling == config.ScaleXY) { - Math::Vec4<u8> pixel1 = DecodePixel(config.input_format, src_pixel + 1 * src_bytes_per_pixel); - Math::Vec4<u8> pixel2 = DecodePixel(config.input_format, src_pixel + 2 * src_bytes_per_pixel); - Math::Vec4<u8> pixel3 = DecodePixel(config.input_format, src_pixel + 3 * src_bytes_per_pixel); + Math::Vec4<u8> pixel1 = DecodePixel( + config.input_format, src_pixel + 1 * src_bytes_per_pixel); + Math::Vec4<u8> pixel2 = DecodePixel( + config.input_format, src_pixel + 2 * src_bytes_per_pixel); + Math::Vec4<u8> pixel3 = DecodePixel( + config.input_format, src_pixel + 3 * src_bytes_per_pixel); src_color = (((src_color + pixel1) + (pixel2 + pixel3)) / 4).Cast<u8>(); } @@ -341,17 +365,20 @@ inline void Write(u32 addr, const T data) { break; default: - LOG_ERROR(HW_GPU, "Unknown destination framebuffer format %x", config.output_format.Value()); + LOG_ERROR(HW_GPU, "Unknown destination framebuffer format %x", + config.output_format.Value()); break; } } } - LOG_TRACE(HW_GPU, "DisplayTriggerTransfer: 0x%08x bytes from 0x%08x(%ux%u)-> 0x%08x(%ux%u), dst format %x, flags 0x%08X", - config.output_height * output_width * GPU::Regs::BytesPerPixel(config.output_format), - config.GetPhysicalInputAddress(), config.input_width.Value(), config.input_height.Value(), - config.GetPhysicalOutputAddress(), output_width, output_height, - config.output_format.Value(), config.flags); + LOG_TRACE(HW_GPU, "DisplayTriggerTransfer: 0x%08x bytes from 0x%08x(%ux%u)-> " + "0x%08x(%ux%u), dst format %x, flags 0x%08X", + config.output_height * output_width * + GPU::Regs::BytesPerPixel(config.output_format), + config.GetPhysicalInputAddress(), config.input_width.Value(), + config.input_height.Value(), config.GetPhysicalOutputAddress(), + output_width, output_height, config.output_format.Value(), config.flags); } g_regs.display_transfer_config.trigger = 0; @@ -361,17 +388,16 @@ inline void Write(u32 addr, const T data) { } // Seems like writing to this register triggers processing - case GPU_REG_INDEX(command_processor_config.trigger): - { + case GPU_REG_INDEX(command_processor_config.trigger): { const auto& config = g_regs.command_processor_config; - if (config.trigger & 1) - { + if (config.trigger & 1) { MICROPROFILE_SCOPE(GPU_CmdlistProcessing); u32* buffer = (u32*)Memory::GetPhysicalPointer(config.GetPhysicalAddress()); if (Pica::g_debug_context && Pica::g_debug_context->recorder) { - Pica::g_debug_context->recorder->MemoryAccessed((u8*)buffer, config.size * sizeof(u32), config.GetPhysicalAddress()); + Pica::g_debug_context->recorder->MemoryAccessed( + (u8*)buffer, config.size * sizeof(u32), config.GetPhysicalAddress()); } Pica::CommandProcessor::ProcessCommandList(buffer, config.size); @@ -389,16 +415,17 @@ inline void Write(u32 addr, const T data) { // This is happening *after* handling the write to make sure we properly catch all memory reads. if (Pica::g_debug_context && Pica::g_debug_context->recorder) { // addr + GPU VBase - IO VBase + IO PBase - Pica::g_debug_context->recorder->RegisterWritten<T>(addr + 0x1EF00000 - 0x1EC00000 + 0x10100000, data); + Pica::g_debug_context->recorder->RegisterWritten<T>( + addr + 0x1EF00000 - 0x1EC00000 + 0x10100000, data); } } // Explicitly instantiate template functions because we aren't defining this in the header: -template void Read<u64>(u64 &var, const u32 addr); -template void Read<u32>(u32 &var, const u32 addr); -template void Read<u16>(u16 &var, const u32 addr); -template void Read<u8>(u8 &var, const u32 addr); +template void Read<u64>(u64& var, const u32 addr); +template void Read<u32>(u32& var, const u32 addr); +template void Read<u16>(u16& var, const u32 addr); +template void Read<u8>(u8& var, const u32 addr); template void Write<u64>(u32 addr, const u64 data); template void Write<u32>(u32 addr, const u32 data); @@ -417,8 +444,9 @@ static void VBlankCallback(u64 userdata, int cycles_late) { // - If frameskip == 0 (disabled), always swap buffers // - If frameskip == 1, swap buffers every other frame (starting from the first frame) // - If frameskip > 1, swap buffers every frameskip^n frames (starting from the second frame) - if ((((Settings::values.frame_skip != 1) ^ last_skip_frame) && last_skip_frame != g_skip_frame) || - Settings::values.frame_skip == 0) { + if ((((Settings::values.frame_skip != 1) ^ last_skip_frame) && + last_skip_frame != g_skip_frame) || + Settings::values.frame_skip == 0) { VideoCore::g_renderer->SwapBuffers(); } @@ -448,12 +476,12 @@ void Init() { // .. or at least these are the ones used by system applets. // There's probably a smarter way to come up with addresses // like this which does not require hardcoding. - framebuffer_top.address_left1 = 0x181E6000; - framebuffer_top.address_left2 = 0x1822C800; + framebuffer_top.address_left1 = 0x181E6000; + framebuffer_top.address_left2 = 0x1822C800; framebuffer_top.address_right1 = 0x18273000; framebuffer_top.address_right2 = 0x182B9800; - framebuffer_sub.address_left1 = 0x1848F000; - framebuffer_sub.address_left2 = 0x184C7800; + framebuffer_sub.address_left1 = 0x1848F000; + framebuffer_sub.address_left2 = 0x184C7800; framebuffer_top.width.Assign(240); framebuffer_top.height.Assign(400); diff --git a/src/core/hw/gpu.h b/src/core/hw/gpu.h index da4c345b4..077b6255f 100644 --- a/src/core/hw/gpu.h +++ b/src/core/hw/gpu.h @@ -17,7 +17,8 @@ namespace GPU { // Returns index corresponding to the Regs member labeled by field_name // TODO: Due to Visual studio bug 209229, offsetof does not return constant expressions // when used with array elements (e.g. GPU_REG_INDEX(memory_fill_config[0])). -// For details cf. https://connect.microsoft.com/VisualStudio/feedback/details/209229/offsetof-does-not-produce-a-constant-expression-for-array-members +// For details cf. +// https://connect.microsoft.com/VisualStudio/feedback/details/209229/offsetof-does-not-produce-a-constant-expression-for-array-members // Hopefully, this will be fixed sometime in the future. // For lack of better alternatives, we currently hardcode the offsets when constant // expressions are needed via GPU_REG_INDEX_WORKAROUND (on sane compilers, static_asserts @@ -30,8 +31,9 @@ namespace GPU { // really is this annoying. This macro just forwards its first argument to GPU_REG_INDEX // and then performs a (no-op) cast to size_t iff the second argument matches the expected // field offset. Otherwise, the compiler will fail to compile this code. -#define GPU_REG_INDEX_WORKAROUND(field_name, backup_workaround_index) \ - ((typename std::enable_if<backup_workaround_index == GPU_REG_INDEX(field_name), size_t>::type)GPU_REG_INDEX(field_name)) +#define GPU_REG_INDEX_WORKAROUND(field_name, backup_workaround_index) \ + ((typename std::enable_if<backup_workaround_index == GPU_REG_INDEX(field_name), size_t>::type) \ + GPU_REG_INDEX(field_name)) #endif // MMIO region 0x1EFxxxxx @@ -44,18 +46,18 @@ struct Regs { // support for that. #define ASSERT_MEMBER_SIZE(name, size_in_bytes) #else -#define ASSERT_MEMBER_SIZE(name, size_in_bytes) \ - static_assert(sizeof(name) == size_in_bytes, \ +#define ASSERT_MEMBER_SIZE(name, size_in_bytes) \ + static_assert(sizeof(name) == size_in_bytes, \ "Structure size and register block length don't match") #endif // Components are laid out in reverse byte order, most significant bits first. enum class PixelFormat : u32 { - RGBA8 = 0, - RGB8 = 1, + RGBA8 = 0, + RGB8 = 1, RGB565 = 2, RGB5A1 = 3, - RGBA4 = 4, + RGBA4 = 4, }; /** @@ -88,8 +90,8 @@ struct Regs { BitField<0, 16, u32> value_16bit; // TODO: Verify component order - BitField< 0, 8, u32> value_24bit_r; - BitField< 8, 8, u32> value_24bit_g; + BitField<0, 8, u32> value_24bit_r; + BitField<8, 8, u32> value_24bit_g; BitField<16, 8, u32> value_24bit_b; }; @@ -126,7 +128,7 @@ struct Regs { union { u32 size; - BitField< 0, 16, u32> width; + BitField<0, 16, u32> width; BitField<16, 16, u32> height; }; @@ -138,7 +140,7 @@ struct Regs { union { u32 format; - BitField< 0, 3, PixelFormat> color_format; + BitField<0, 3, PixelFormat> color_format; }; INSERT_PADDING_WORDS(0x1); @@ -180,35 +182,37 @@ struct Regs { union { u32 output_size; - BitField< 0, 16, u32> output_width; + BitField<0, 16, u32> output_width; BitField<16, 16, u32> output_height; }; union { u32 input_size; - BitField< 0, 16, u32> input_width; + BitField<0, 16, u32> input_width; BitField<16, 16, u32> input_height; }; enum ScalingMode : u32 { - NoScale = 0, // Doesn't scale the image - ScaleX = 1, // Downscales the image in half in the X axis and applies a box filter - ScaleXY = 2, // Downscales the image in half in both the X and Y axes and applies a box filter + NoScale = 0, // Doesn't scale the image + ScaleX = 1, // Downscales the image in half in the X axis and applies a box filter + ScaleXY = + 2, // Downscales the image in half in both the X and Y axes and applies a box filter }; union { u32 flags; - BitField< 0, 1, u32> flip_vertically; // flips input data vertically - BitField< 1, 1, u32> input_linear; // Converts from linear to tiled format - BitField< 2, 1, u32> crop_input_lines; - BitField< 3, 1, u32> is_texture_copy; // Copies the data without performing any processing and respecting texture copy fields - BitField< 5, 1, u32> dont_swizzle; - BitField< 8, 3, PixelFormat> input_format; + BitField<0, 1, u32> flip_vertically; // flips input data vertically + BitField<1, 1, u32> input_linear; // Converts from linear to tiled format + BitField<2, 1, u32> crop_input_lines; + BitField<3, 1, u32> is_texture_copy; // Copies the data without performing any + // processing and respecting texture copy fields + BitField<5, 1, u32> dont_swizzle; + BitField<8, 3, PixelFormat> input_format; BitField<12, 3, PixelFormat> output_format; /// Uses some kind of 32x32 block swizzling mode, instead of the usual 8x8 one. - BitField<16, 1, u32> block_32; // TODO(yuriks): unimplemented + BitField<16, 1, u32> block_32; // TODO(yuriks): unimplemented BitField<24, 2, ScalingMode> scaling; // Determines the scaling mode of the transfer }; @@ -225,14 +229,14 @@ struct Regs { union { u32 input_size; - BitField< 0, 16, u32> input_width; + BitField<0, 16, u32> input_width; BitField<16, 16, u32> input_gap; }; union { u32 output_size; - BitField< 0, 16, u32> output_width; + BitField<0, 16, u32> output_width; BitField<16, 16, u32> output_gap; }; } texture_copy; @@ -267,12 +271,12 @@ struct Regs { return sizeof(Regs) / sizeof(u32); } - const u32& operator [] (int index) const { + const u32& operator[](int index) const { const u32* content = reinterpret_cast<const u32*>(this); return content[index]; } - u32& operator [] (int index) { + u32& operator[](int index) { u32* content = reinterpret_cast<u32*>(this); return content[index]; } @@ -294,28 +298,29 @@ static_assert(std::is_standard_layout<Regs>::value, "Structure does not use stan // is technically allowed since C++11. This macro should be enabled once MSVC adds // support for that. #ifndef _MSC_VER -#define ASSERT_REG_POSITION(field_name, position) \ - static_assert(offsetof(Regs, field_name) == position * 4, \ - "Field "#field_name" has invalid position") - -ASSERT_REG_POSITION(memory_fill_config[0], 0x00004); -ASSERT_REG_POSITION(memory_fill_config[1], 0x00008); -ASSERT_REG_POSITION(framebuffer_config[0], 0x00117); -ASSERT_REG_POSITION(framebuffer_config[1], 0x00157); -ASSERT_REG_POSITION(display_transfer_config, 0x00300); +#define ASSERT_REG_POSITION(field_name, position) \ + static_assert(offsetof(Regs, field_name) == position * 4, \ + "Field " #field_name " has invalid position") + +ASSERT_REG_POSITION(memory_fill_config[0], 0x00004); +ASSERT_REG_POSITION(memory_fill_config[1], 0x00008); +ASSERT_REG_POSITION(framebuffer_config[0], 0x00117); +ASSERT_REG_POSITION(framebuffer_config[1], 0x00157); +ASSERT_REG_POSITION(display_transfer_config, 0x00300); ASSERT_REG_POSITION(command_processor_config, 0x00638); #undef ASSERT_REG_POSITION #endif // !defined(_MSC_VER) -// The total number of registers is chosen arbitrarily, but let's make sure it's not some odd value anyway. +// The total number of registers is chosen arbitrarily, but let's make sure it's not some odd value +// anyway. static_assert(sizeof(Regs) == 0x1000 * sizeof(u32), "Invalid total size of register set"); extern Regs g_regs; extern bool g_skip_frame; template <typename T> -void Read(T &var, const u32 addr); +void Read(T& var, const u32 addr); template <typename T> void Write(u32 addr, const T data); @@ -326,5 +331,4 @@ void Init(); /// Shutdown hardware void Shutdown(); - } // namespace diff --git a/src/core/hw/hw.cpp b/src/core/hw/hw.cpp index b5fdbf9c1..db224c9aa 100644 --- a/src/core/hw/hw.cpp +++ b/src/core/hw/hw.cpp @@ -5,14 +5,14 @@ #include "common/common_types.h" #include "common/logging/log.h" -#include "core/hw/hw.h" #include "core/hw/gpu.h" +#include "core/hw/hw.h" #include "core/hw/lcd.h" namespace HW { template <typename T> -inline void Read(T &var, const u32 addr) { +inline void Read(T& var, const u32 addr) { switch (addr & 0xFFFFF000) { case VADDR_GPU: case VADDR_GPU + 0x1000: @@ -71,10 +71,10 @@ inline void Write(u32 addr, const T data) { // Explicitly instantiate template functions because we aren't defining this in the header: -template void Read<u64>(u64 &var, const u32 addr); -template void Read<u32>(u32 &var, const u32 addr); -template void Read<u16>(u16 &var, const u32 addr); -template void Read<u8>(u8 &var, const u32 addr); +template void Read<u64>(u64& var, const u32 addr); +template void Read<u32>(u32& var, const u32 addr); +template void Read<u16>(u16& var, const u32 addr); +template void Read<u8>(u8& var, const u32 addr); template void Write<u64>(u32 addr, const u64 data); template void Write<u32>(u32 addr, const u32 data); @@ -98,5 +98,4 @@ void Shutdown() { LCD::Shutdown(); LOG_DEBUG(HW, "shutdown OK"); } - } diff --git a/src/core/hw/hw.h b/src/core/hw/hw.h index d65608910..a3c5d2ea3 100644 --- a/src/core/hw/hw.h +++ b/src/core/hw/hw.h @@ -10,30 +10,30 @@ namespace HW { /// Beginnings of IO register regions, in the user VA space. enum : u32 { - VADDR_HASH = 0x1EC01000, - VADDR_CSND = 0x1EC03000, - VADDR_DSP = 0x1EC40000, - VADDR_PDN = 0x1EC41000, - VADDR_CODEC = 0x1EC41000, - VADDR_SPI = 0x1EC42000, - VADDR_SPI_2 = 0x1EC43000, // Only used under TWL_FIRM? - VADDR_I2C = 0x1EC44000, - VADDR_CODEC_2 = 0x1EC45000, - VADDR_HID = 0x1EC46000, - VADDR_GPIO = 0x1EC47000, - VADDR_I2C_2 = 0x1EC48000, - VADDR_SPI_3 = 0x1EC60000, - VADDR_I2C_3 = 0x1EC61000, - VADDR_MIC = 0x1EC62000, - VADDR_PXI = 0x1EC63000, - VADDR_LCD = 0x1ED02000, - VADDR_DSP_2 = 0x1ED03000, - VADDR_HASH_2 = 0x1EE01000, - VADDR_GPU = 0x1EF00000, + VADDR_HASH = 0x1EC01000, + VADDR_CSND = 0x1EC03000, + VADDR_DSP = 0x1EC40000, + VADDR_PDN = 0x1EC41000, + VADDR_CODEC = 0x1EC41000, + VADDR_SPI = 0x1EC42000, + VADDR_SPI_2 = 0x1EC43000, // Only used under TWL_FIRM? + VADDR_I2C = 0x1EC44000, + VADDR_CODEC_2 = 0x1EC45000, + VADDR_HID = 0x1EC46000, + VADDR_GPIO = 0x1EC47000, + VADDR_I2C_2 = 0x1EC48000, + VADDR_SPI_3 = 0x1EC60000, + VADDR_I2C_3 = 0x1EC61000, + VADDR_MIC = 0x1EC62000, + VADDR_PXI = 0x1EC63000, + VADDR_LCD = 0x1ED02000, + VADDR_DSP_2 = 0x1ED03000, + VADDR_HASH_2 = 0x1EE01000, + VADDR_GPU = 0x1EF00000, }; template <typename T> -void Read(T &var, const u32 addr); +void Read(T& var, const u32 addr); template <typename T> void Write(u32 addr, const T data); diff --git a/src/core/hw/lcd.cpp b/src/core/hw/lcd.cpp index 6f93709e3..0e3aa7cfd 100644 --- a/src/core/hw/lcd.cpp +++ b/src/core/hw/lcd.cpp @@ -18,7 +18,7 @@ namespace LCD { Regs g_regs; template <typename T> -inline void Read(T &var, const u32 raw_addr) { +inline void Read(T& var, const u32 raw_addr) { u32 addr = raw_addr - HW::VADDR_LCD; u32 index = addr / 4; @@ -48,16 +48,17 @@ inline void Write(u32 addr, const T data) { // This is happening *after* handling the write to make sure we properly catch all memory reads. if (Pica::g_debug_context && Pica::g_debug_context->recorder) { // addr + GPU VBase - IO VBase + IO PBase - Pica::g_debug_context->recorder->RegisterWritten<T>(addr + HW::VADDR_LCD - 0x1EC00000 + 0x10100000, data); + Pica::g_debug_context->recorder->RegisterWritten<T>( + addr + HW::VADDR_LCD - 0x1EC00000 + 0x10100000, data); } } // Explicitly instantiate template functions because we aren't defining this in the header: -template void Read<u64>(u64 &var, const u32 addr); -template void Read<u32>(u32 &var, const u32 addr); -template void Read<u16>(u16 &var, const u32 addr); -template void Read<u8>(u8 &var, const u32 addr); +template void Read<u64>(u64& var, const u32 addr); +template void Read<u32>(u32& var, const u32 addr); +template void Read<u16>(u16& var, const u32 addr); +template void Read<u8>(u8& var, const u32 addr); template void Write<u64>(u32 addr, const u64 data); template void Write<u32>(u32 addr, const u32 data); diff --git a/src/core/hw/lcd.h b/src/core/hw/lcd.h index 57029c5e8..404833165 100644 --- a/src/core/hw/lcd.h +++ b/src/core/hw/lcd.h @@ -42,16 +42,15 @@ struct Regs { return sizeof(Regs) / sizeof(u32); } - const u32& operator [] (int index) const { + const u32& operator[](int index) const { const u32* content = reinterpret_cast<const u32*>(this); return content[index]; } - u32& operator [] (int index) { + u32& operator[](int index) { u32* content = reinterpret_cast<u32*>(this); return content[index]; } - }; static_assert(std::is_standard_layout<Regs>::value, "Structure does not use standard layout"); @@ -59,14 +58,14 @@ static_assert(std::is_standard_layout<Regs>::value, "Structure does not use stan // is technically allowed since C++11. This macro should be enabled once MSVC adds // support for that. #ifndef _MSC_VER -#define ASSERT_REG_POSITION(field_name, position) \ - static_assert(offsetof(Regs, field_name) == position * 4, \ - "Field "#field_name" has invalid position") +#define ASSERT_REG_POSITION(field_name, position) \ + static_assert(offsetof(Regs, field_name) == position * 4, \ + "Field " #field_name " has invalid position") -ASSERT_REG_POSITION(color_fill_top, 0x81); -ASSERT_REG_POSITION(backlight_top, 0x90); +ASSERT_REG_POSITION(color_fill_top, 0x81); +ASSERT_REG_POSITION(backlight_top, 0x90); ASSERT_REG_POSITION(color_fill_bottom, 0x281); -ASSERT_REG_POSITION(backlight_bottom, 0x290); +ASSERT_REG_POSITION(backlight_bottom, 0x290); #undef ASSERT_REG_POSITION #endif // !defined(_MSC_VER) @@ -74,7 +73,7 @@ ASSERT_REG_POSITION(backlight_bottom, 0x290); extern Regs g_regs; template <typename T> -void Read(T &var, const u32 addr); +void Read(T& var, const u32 addr); template <typename T> void Write(u32 addr, const T data); diff --git a/src/core/hw/y2r.cpp b/src/core/hw/y2r.cpp index 083391e83..5a68d7e65 100644 --- a/src/core/hw/y2r.cpp +++ b/src/core/hw/y2r.cpp @@ -27,9 +27,9 @@ static const size_t TILE_SIZE = 8 * 8; using ImageTile = std::array<u32, TILE_SIZE>; /// Converts a image strip from the source YUV format into individual 8x8 RGB32 tiles. -static void ConvertYUVToRGB(InputFormat input_format, - const u8* input_Y, const u8* input_U, const u8* input_V, ImageTile output[], - unsigned int width, unsigned int height, const CoefficientSet& coefficients) { +static void ConvertYUVToRGB(InputFormat input_format, const u8* input_Y, const u8* input_U, + const u8* input_V, ImageTile output[], unsigned int width, + unsigned int height, const CoefficientSet& coefficients) { for (unsigned int y = 0; y < height; ++y) { for (unsigned int x = 0; x < width; ++x) { @@ -58,11 +58,11 @@ static void ConvertYUVToRGB(InputFormat input_format, // This conversion process is bit-exact with hardware, as far as could be tested. auto& c = coefficients; - s32 cY = c[0]*Y; + s32 cY = c[0] * Y; - s32 r = cY + c[1]*V; - s32 g = cY - c[3]*U - c[2]*V; - s32 b = cY + c[4]*U; + s32 r = cY + c[1] * V; + s32 g = cY - c[3] * U - c[2] * V; + s32 b = cY + c[4] * U; const s32 rounding_offset = 0x18; r = (r >> 3) + c[5] + rounding_offset; @@ -74,14 +74,14 @@ static void ConvertYUVToRGB(InputFormat input_format, u32* out = &output[tile][y * 8 + tile_x]; using MathUtil::Clamp; - *out = ((u32)Clamp(r >> 5, 0, 0xFF) << 24) | - ((u32)Clamp(g >> 5, 0, 0xFF) << 16) | + *out = ((u32)Clamp(r >> 5, 0, 0xFF) << 24) | ((u32)Clamp(g >> 5, 0, 0xFF) << 16) | ((u32)Clamp(b >> 5, 0, 0xFF) << 8); } } } -/// Simulates an incoming CDMA transfer. The N parameter is used to automatically convert 16-bit formats to 8-bit. +/// Simulates an incoming CDMA transfer. The N parameter is used to automatically convert 16-bit +/// formats to 8-bit. template <size_t N> static void ReceiveData(u8* output, ConversionBuffer& buf, size_t amount_of_data) { const u8* input = Memory::GetPointer(buf.address); @@ -103,9 +103,10 @@ static void ReceiveData(u8* output, ConversionBuffer& buf, size_t amount_of_data } } -/// Convert intermediate RGB32 format to the final output format while simulating an outgoing CDMA transfer. +/// Convert intermediate RGB32 format to the final output format while simulating an outgoing CDMA +/// transfer. static void SendData(const u32* input, ConversionBuffer& buf, int amount_of_data, - OutputFormat output_format, u8 alpha) { + OutputFormat output_format, u8 alpha) { u8* output = Memory::GetPointer(buf.address); @@ -113,9 +114,7 @@ static void SendData(const u32* input, ConversionBuffer& buf, int amount_of_data u8* unit_end = output + buf.transfer_unit; while (output < unit_end) { u32 color = *input++; - Math::Vec4<u8> col_vec{ - (u8)(color >> 24), (u8)(color >> 16), (u8)(color >> 8), alpha - }; + Math::Vec4<u8> col_vec{(u8)(color >> 24), (u8)(color >> 16), (u8)(color >> 8), alpha}; switch (output_format) { case OutputFormat::RGBA8: @@ -146,34 +145,26 @@ static void SendData(const u32* input, ConversionBuffer& buf, int amount_of_data } static const u8 linear_lut[64] = { - 0, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, 28, 29, 30, 31, - 32, 33, 34, 35, 36, 37, 38, 39, - 40, 41, 42, 43, 44, 45, 46, 47, - 48, 49, 50, 51, 52, 53, 54, 55, - 56, 57, 58, 59, 60, 61, 62, 63, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, }; static const u8 morton_lut[64] = { - 0, 1, 4, 5, 16, 17, 20, 21, - 2, 3, 6, 7, 18, 19, 22, 23, - 8, 9, 12, 13, 24, 25, 28, 29, - 10, 11, 14, 15, 26, 27, 30, 31, - 32, 33, 36, 37, 48, 49, 52, 53, - 34, 35, 38, 39, 50, 51, 54, 55, - 40, 41, 44, 45, 56, 57, 60, 61, - 42, 43, 46, 47, 58, 59, 62, 63, + 0, 1, 4, 5, 16, 17, 20, 21, 2, 3, 6, 7, 18, 19, 22, 23, 8, 9, 12, 13, 24, 25, + 28, 29, 10, 11, 14, 15, 26, 27, 30, 31, 32, 33, 36, 37, 48, 49, 52, 53, 34, 35, 38, 39, + 50, 51, 54, 55, 40, 41, 44, 45, 56, 57, 60, 61, 42, 43, 46, 47, 58, 59, 62, 63, }; -static void RotateTile0(const ImageTile& input, ImageTile& output, int height, const u8 out_map[64]) { +static void RotateTile0(const ImageTile& input, ImageTile& output, int height, + const u8 out_map[64]) { for (int i = 0; i < height * 8; ++i) { output[out_map[i]] = input[i]; } } -static void RotateTile90(const ImageTile& input, ImageTile& output, int height, const u8 out_map[64]) { +static void RotateTile90(const ImageTile& input, ImageTile& output, int height, + const u8 out_map[64]) { int out_i = 0; for (int x = 0; x < 8; ++x) { for (int y = height - 1; y >= 0; --y) { @@ -182,16 +173,18 @@ static void RotateTile90(const ImageTile& input, ImageTile& output, int height, } } -static void RotateTile180(const ImageTile& input, ImageTile& output, int height, const u8 out_map[64]) { +static void RotateTile180(const ImageTile& input, ImageTile& output, int height, + const u8 out_map[64]) { int out_i = 0; for (int i = height * 8 - 1; i >= 0; --i) { output[out_map[out_i++]] = input[i]; } } -static void RotateTile270(const ImageTile& input, ImageTile& output, int height, const u8 out_map[64]) { +static void RotateTile270(const ImageTile& input, ImageTile& output, int height, + const u8 out_map[64]) { int out_i = 0; - for (int x = 8-1; x >= 0; --x) { + for (int x = 8 - 1; x >= 0; --x) { for (int y = 0; y < height; ++y) { output[out_map[out_i++]] = input[y * 8 + x]; } @@ -274,9 +267,11 @@ void PerformConversion(ConversionConfiguration& cvt) { const u8* tile_remap = nullptr; switch (cvt.block_alignment) { case BlockAlignment::Linear: - tile_remap = linear_lut; break; + tile_remap = linear_lut; + break; case BlockAlignment::Block8x8: - tile_remap = morton_lut; break; + tile_remap = morton_lut; + break; } for (unsigned int y = 0; y < cvt.input_lines; y += 8) { @@ -320,7 +315,7 @@ void PerformConversion(ConversionConfiguration& cvt) { // Note(yuriks): If additional optimization is required, input_format can be moved to a // template parameter, so that its dispatch can be moved to outside the inner loop. ConvertYUVToRGB(cvt.input_format, input_Y, input_U, input_V, tiles.get(), - cvt.input_line_width, row_height, cvt.coefficients); + cvt.input_line_width, row_height, cvt.coefficients); u32* output_buffer = reinterpret_cast<u32*>(data_buffer.get()); @@ -367,9 +362,9 @@ void PerformConversion(ConversionConfiguration& cvt) { // Note(yuriks): If additional optimization is required, output_format can be moved to a // template parameter, so that its dispatch can be moved to outside the inner loop. - SendData(reinterpret_cast<u32*>(data_buffer.get()), cvt.dst, (int)row_data_size, cvt.output_format, (u8)cvt.alpha); + SendData(reinterpret_cast<u32*>(data_buffer.get()), cvt.dst, (int)row_data_size, + cvt.output_format, (u8)cvt.alpha); } } - } } diff --git a/src/core/hw/y2r.h b/src/core/hw/y2r.h index 729e1eee3..6b6e71bec 100644 --- a/src/core/hw/y2r.h +++ b/src/core/hw/y2r.h @@ -3,13 +3,12 @@ // Refer to the license.txt file included. namespace Y2R_U { - struct ConversionConfiguration; +struct ConversionConfiguration; } namespace HW { namespace Y2R { void PerformConversion(Y2R_U::ConversionConfiguration& cvt); - } } |