diff options
| author | 2014-08-12 13:55:41 +0200 | |
|---|---|---|
| committer | 2014-08-12 13:55:41 +0200 | |
| commit | 36cabe35cc15a6590f5d18be695ae505a946cb06 (patch) | |
| tree | 241e6d8b36e6ab9921ef7afb71e7350e52862e2a /src/core/hw/gpu.cpp | |
| parent | Merge pull request #38 from neobrain/replace_registerset (diff) | |
| parent | Pica: Add basic rasterizer. (diff) | |
| download | yuzu-36cabe35cc15a6590f5d18be695ae505a946cb06.tar.gz yuzu-36cabe35cc15a6590f5d18be695ae505a946cb06.tar.xz yuzu-36cabe35cc15a6590f5d18be695ae505a946cb06.zip | |
Merge pull request #37 from neobrain/pica
Initial work on Pica rendering.
Diffstat (limited to 'src/core/hw/gpu.cpp')
| -rw-r--r-- | src/core/hw/gpu.cpp | 110 |
1 files changed, 23 insertions, 87 deletions
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp index fd40f8ac0..87cf93bac 100644 --- a/src/core/hw/gpu.cpp +++ b/src/core/hw/gpu.cpp | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | 14 | ||
| 15 | #include "core/hw/gpu.h" | 15 | #include "core/hw/gpu.h" |
| 16 | 16 | ||
| 17 | #include "video_core/command_processor.h" | ||
| 17 | #include "video_core/video_core.h" | 18 | #include "video_core/video_core.h" |
| 18 | 19 | ||
| 19 | 20 | ||
| @@ -24,83 +25,6 @@ Regs g_regs; | |||
| 24 | u32 g_cur_line = 0; ///< Current vertical screen line | 25 | u32 g_cur_line = 0; ///< Current vertical screen line |
| 25 | u64 g_last_line_ticks = 0; ///< CPU tick count from last vertical screen line | 26 | u64 g_last_line_ticks = 0; ///< CPU tick count from last vertical screen line |
| 26 | 27 | ||
| 27 | /** | ||
| 28 | * Sets whether the framebuffers are in the GSP heap (FCRAM) or VRAM | ||
| 29 | * @param | ||
| 30 | */ | ||
| 31 | void SetFramebufferLocation(const FramebufferLocation mode) { | ||
| 32 | switch (mode) { | ||
| 33 | case FRAMEBUFFER_LOCATION_FCRAM: | ||
| 34 | { | ||
| 35 | auto& framebuffer_top = g_regs.framebuffer_config[0]; | ||
| 36 | auto& framebuffer_sub = g_regs.framebuffer_config[1]; | ||
| 37 | |||
| 38 | framebuffer_top.address_left1 = PADDR_TOP_LEFT_FRAME1; | ||
| 39 | framebuffer_top.address_left2 = PADDR_TOP_LEFT_FRAME2; | ||
| 40 | framebuffer_top.address_right1 = PADDR_TOP_RIGHT_FRAME1; | ||
| 41 | framebuffer_top.address_right2 = PADDR_TOP_RIGHT_FRAME2; | ||
| 42 | framebuffer_sub.address_left1 = PADDR_SUB_FRAME1; | ||
| 43 | //framebuffer_sub.address_left2 = unknown; | ||
| 44 | framebuffer_sub.address_right1 = PADDR_SUB_FRAME2; | ||
| 45 | //framebuffer_sub.address_right2 = unknown; | ||
| 46 | break; | ||
| 47 | } | ||
| 48 | |||
| 49 | case FRAMEBUFFER_LOCATION_VRAM: | ||
| 50 | { | ||
| 51 | auto& framebuffer_top = g_regs.framebuffer_config[0]; | ||
| 52 | auto& framebuffer_sub = g_regs.framebuffer_config[1]; | ||
| 53 | |||
| 54 | framebuffer_top.address_left1 = PADDR_VRAM_TOP_LEFT_FRAME1; | ||
| 55 | framebuffer_top.address_left2 = PADDR_VRAM_TOP_LEFT_FRAME2; | ||
| 56 | framebuffer_top.address_right1 = PADDR_VRAM_TOP_RIGHT_FRAME1; | ||
| 57 | framebuffer_top.address_right2 = PADDR_VRAM_TOP_RIGHT_FRAME2; | ||
| 58 | framebuffer_sub.address_left1 = PADDR_VRAM_SUB_FRAME1; | ||
| 59 | //framebuffer_sub.address_left2 = unknown; | ||
| 60 | framebuffer_sub.address_right1 = PADDR_VRAM_SUB_FRAME2; | ||
| 61 | //framebuffer_sub.address_right2 = unknown; | ||
| 62 | break; | ||
| 63 | } | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | /** | ||
| 68 | * Gets the location of the framebuffers | ||
| 69 | * @return Location of framebuffers as FramebufferLocation enum | ||
| 70 | */ | ||
| 71 | FramebufferLocation GetFramebufferLocation(u32 address) { | ||
| 72 | if ((address & ~Memory::VRAM_MASK) == Memory::VRAM_PADDR) { | ||
| 73 | return FRAMEBUFFER_LOCATION_VRAM; | ||
| 74 | } else if ((address & ~Memory::FCRAM_MASK) == Memory::FCRAM_PADDR) { | ||
| 75 | return FRAMEBUFFER_LOCATION_FCRAM; | ||
| 76 | } else { | ||
| 77 | ERROR_LOG(GPU, "unknown framebuffer location!"); | ||
| 78 | } | ||
| 79 | return FRAMEBUFFER_LOCATION_UNKNOWN; | ||
| 80 | } | ||
| 81 | |||
| 82 | u32 GetFramebufferAddr(const u32 address) { | ||
| 83 | switch (GetFramebufferLocation(address)) { | ||
| 84 | case FRAMEBUFFER_LOCATION_FCRAM: | ||
| 85 | return Memory::VirtualAddressFromPhysical_FCRAM(address); | ||
| 86 | case FRAMEBUFFER_LOCATION_VRAM: | ||
| 87 | return Memory::VirtualAddressFromPhysical_VRAM(address); | ||
| 88 | default: | ||
| 89 | ERROR_LOG(GPU, "unknown framebuffer location"); | ||
| 90 | } | ||
| 91 | return 0; | ||
| 92 | } | ||
| 93 | |||
| 94 | /** | ||
| 95 | * Gets a read-only pointer to a framebuffer in memory | ||
| 96 | * @param address Physical address of framebuffer | ||
| 97 | * @return Returns const pointer to raw framebuffer | ||
| 98 | */ | ||
| 99 | const u8* GetFramebufferPointer(const u32 address) { | ||
| 100 | u32 addr = GetFramebufferAddr(address); | ||
| 101 | return (addr != 0) ? Memory::GetPointer(addr) : nullptr; | ||
| 102 | } | ||
| 103 | |||
| 104 | template <typename T> | 28 | template <typename T> |
| 105 | inline void Read(T &var, const u32 raw_addr) { | 29 | inline void Read(T &var, const u32 raw_addr) { |
| 106 | u32 addr = raw_addr - 0x1EF00000; | 30 | u32 addr = raw_addr - 0x1EF00000; |
| @@ -141,8 +65,8 @@ inline void Write(u32 addr, const T data) { | |||
| 141 | // TODO: Not sure if this check should be done at GSP level instead | 65 | // TODO: Not sure if this check should be done at GSP level instead |
| 142 | if (config.address_start) { | 66 | if (config.address_start) { |
| 143 | // TODO: Not sure if this algorithm is correct, particularly because it doesn't use the size member at all | 67 | // TODO: Not sure if this algorithm is correct, particularly because it doesn't use the size member at all |
| 144 | u32* start = (u32*)Memory::GetPointer(config.GetStartAddress()); | 68 | u32* start = (u32*)Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetStartAddress())); |
| 145 | u32* end = (u32*)Memory::GetPointer(config.GetEndAddress()); | 69 | u32* end = (u32*)Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetEndAddress())); |
| 146 | for (u32* ptr = start; ptr < end; ++ptr) | 70 | for (u32* ptr = start; ptr < end; ++ptr) |
| 147 | *ptr = bswap32(config.value); // TODO: This is just a workaround to missing framebuffer format emulation | 71 | *ptr = bswap32(config.value); // TODO: This is just a workaround to missing framebuffer format emulation |
| 148 | 72 | ||
| @@ -155,8 +79,8 @@ inline void Write(u32 addr, const T data) { | |||
| 155 | { | 79 | { |
| 156 | const auto& config = g_regs.display_transfer_config; | 80 | const auto& config = g_regs.display_transfer_config; |
| 157 | if (config.trigger & 1) { | 81 | if (config.trigger & 1) { |
| 158 | u8* source_pointer = Memory::GetPointer(config.GetPhysicalInputAddress()); | 82 | u8* source_pointer = Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetPhysicalInputAddress())); |
| 159 | u8* dest_pointer = Memory::GetPointer(config.GetPhysicalOutputAddress()); | 83 | u8* dest_pointer = Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetPhysicalOutputAddress())); |
| 160 | 84 | ||
| 161 | for (int y = 0; y < config.output_height; ++y) { | 85 | for (int y = 0; y < config.output_height; ++y) { |
| 162 | // TODO: Why does the register seem to hold twice the framebuffer width? | 86 | // TODO: Why does the register seem to hold twice the framebuffer width? |
| @@ -220,14 +144,15 @@ inline void Write(u32 addr, const T data) { | |||
| 220 | break; | 144 | break; |
| 221 | } | 145 | } |
| 222 | 146 | ||
| 147 | // Seems like writing to this register triggers processing | ||
| 223 | case GPU_REG_INDEX(command_processor_config.trigger): | 148 | case GPU_REG_INDEX(command_processor_config.trigger): |
| 224 | { | 149 | { |
| 225 | const auto& config = g_regs.command_processor_config; | 150 | const auto& config = g_regs.command_processor_config; |
| 226 | if (config.trigger & 1) | 151 | if (config.trigger & 1) |
| 227 | { | 152 | { |
| 228 | // u32* buffer = (u32*)Memory::GetPointer(config.GetPhysicalAddress()); | 153 | u32* buffer = (u32*)Memory::GetPointer(Memory::PhysicalToVirtualAddress(config.GetPhysicalAddress())); |
| 229 | ERROR_LOG(GPU, "Beginning 0x%08x bytes of commands from address 0x%08x", config.size, config.GetPhysicalAddress()); | 154 | u32 size = config.size << 3; |
| 230 | // TODO: Process command list! | 155 | Pica::CommandProcessor::ProcessCommandList(buffer, size); |
| 231 | } | 156 | } |
| 232 | break; | 157 | break; |
| 233 | } | 158 | } |
| @@ -276,11 +201,22 @@ void Init() { | |||
| 276 | g_cur_line = 0; | 201 | g_cur_line = 0; |
| 277 | g_last_line_ticks = Core::g_app_core->GetTicks(); | 202 | g_last_line_ticks = Core::g_app_core->GetTicks(); |
| 278 | 203 | ||
| 279 | // SetFramebufferLocation(FRAMEBUFFER_LOCATION_FCRAM); | ||
| 280 | SetFramebufferLocation(FRAMEBUFFER_LOCATION_VRAM); | ||
| 281 | |||
| 282 | auto& framebuffer_top = g_regs.framebuffer_config[0]; | 204 | auto& framebuffer_top = g_regs.framebuffer_config[0]; |
| 283 | auto& framebuffer_sub = g_regs.framebuffer_config[1]; | 205 | auto& framebuffer_sub = g_regs.framebuffer_config[1]; |
| 206 | |||
| 207 | // Setup default framebuffer addresses (located in VRAM) | ||
| 208 | // .. or at least these are the ones used by system applets. | ||
| 209 | // There's probably a smarter way to come up with addresses | ||
| 210 | // like this which does not require hardcoding. | ||
| 211 | framebuffer_top.address_left1 = 0x181E6000; | ||
| 212 | framebuffer_top.address_left2 = 0x1822C800; | ||
| 213 | framebuffer_top.address_right1 = 0x18273000; | ||
| 214 | framebuffer_top.address_right2 = 0x182B9800; | ||
| 215 | framebuffer_sub.address_left1 = 0x1848F000; | ||
| 216 | //framebuffer_sub.address_left2 = unknown; | ||
| 217 | framebuffer_sub.address_right1 = 0x184C7800; | ||
| 218 | //framebuffer_sub.address_right2 = unknown; | ||
| 219 | |||
| 284 | // TODO: Width should be 240 instead? | 220 | // TODO: Width should be 240 instead? |
| 285 | framebuffer_top.width = 480; | 221 | framebuffer_top.width = 480; |
| 286 | framebuffer_top.height = 400; | 222 | framebuffer_top.height = 400; |