diff options
| -rw-r--r-- | src/core/hw/gpu.cpp | 41 | ||||
| -rw-r--r-- | src/core/hw/gpu.h | 2 |
2 files changed, 24 insertions, 19 deletions
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp index 42809c731..6838e449c 100644 --- a/src/core/hw/gpu.cpp +++ b/src/core/hw/gpu.cpp | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include <cstring> | 5 | #include <cstring> |
| 6 | #include <numeric> | 6 | #include <numeric> |
| 7 | #include <type_traits> | 7 | #include <type_traits> |
| 8 | #include "common/alignment.h" | ||
| 8 | #include "common/color.h" | 9 | #include "common/color.h" |
| 9 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 10 | #include "common/logging/log.h" | 11 | #include "common/logging/log.h" |
| @@ -313,7 +314,7 @@ static void TextureCopy(const Regs::DisplayTransferConfig& config) { | |||
| 313 | const PAddr src_addr = config.GetPhysicalInputAddress(); | 314 | const PAddr src_addr = config.GetPhysicalInputAddress(); |
| 314 | const PAddr dst_addr = config.GetPhysicalOutputAddress(); | 315 | const PAddr dst_addr = config.GetPhysicalOutputAddress(); |
| 315 | 316 | ||
| 316 | // TODO: do hwtest with these cases | 317 | // TODO: do hwtest with invalid addresses |
| 317 | if (!Memory::IsValidPhysicalAddress(src_addr)) { | 318 | if (!Memory::IsValidPhysicalAddress(src_addr)) { |
| 318 | LOG_CRITICAL(HW_GPU, "invalid input address 0x%08X", src_addr); | 319 | LOG_CRITICAL(HW_GPU, "invalid input address 0x%08X", src_addr); |
| 319 | return; | 320 | return; |
| @@ -324,31 +325,36 @@ static void TextureCopy(const Regs::DisplayTransferConfig& config) { | |||
| 324 | return; | 325 | return; |
| 325 | } | 326 | } |
| 326 | 327 | ||
| 327 | if (config.texture_copy.input_width == 0) { | 328 | if (VideoCore::g_renderer->Rasterizer()->AccelerateTextureCopy(config)) |
| 328 | LOG_CRITICAL(HW_GPU, "zero input width"); | ||
| 329 | return; | 329 | return; |
| 330 | } | ||
| 331 | 330 | ||
| 332 | if (config.texture_copy.output_width == 0) { | 331 | u8* src_pointer = Memory::GetPhysicalPointer(src_addr); |
| 333 | LOG_CRITICAL(HW_GPU, "zero output width"); | 332 | u8* dst_pointer = Memory::GetPhysicalPointer(dst_addr); |
| 333 | |||
| 334 | u32 remaining_size = Common::AlignDown(config.texture_copy.size, 16); | ||
| 335 | |||
| 336 | if (remaining_size == 0) { | ||
| 337 | LOG_CRITICAL(HW_GPU, "zero size. Real hardware freezes on this."); | ||
| 334 | return; | 338 | return; |
| 335 | } | 339 | } |
| 336 | 340 | ||
| 337 | if (config.texture_copy.size == 0) { | 341 | u32 input_gap = config.texture_copy.input_gap * 16; |
| 338 | LOG_CRITICAL(HW_GPU, "zero size"); | 342 | u32 output_gap = config.texture_copy.output_gap * 16; |
| 343 | |||
| 344 | // Zero gap means contiguous input/output even if width = 0. To avoid infinite loop below, width | ||
| 345 | // is assigned with the total size if gap = 0. | ||
| 346 | u32 input_width = input_gap == 0 ? remaining_size : config.texture_copy.input_width * 16; | ||
| 347 | u32 output_width = output_gap == 0 ? remaining_size : config.texture_copy.output_width * 16; | ||
| 348 | |||
| 349 | if (input_width == 0) { | ||
| 350 | LOG_CRITICAL(HW_GPU, "zero input width. Real hardware freezes on this."); | ||
| 339 | return; | 351 | return; |
| 340 | } | 352 | } |
| 341 | 353 | ||
| 342 | if (VideoCore::g_renderer->Rasterizer()->AccelerateTextureCopy(config)) | 354 | if (output_width == 0) { |
| 355 | LOG_CRITICAL(HW_GPU, "zero output width. Real hardware freezes on this."); | ||
| 343 | return; | 356 | return; |
| 344 | 357 | } | |
| 345 | u8* src_pointer = Memory::GetPhysicalPointer(src_addr); | ||
| 346 | u8* dst_pointer = Memory::GetPhysicalPointer(dst_addr); | ||
| 347 | |||
| 348 | u32 input_width = config.texture_copy.input_width * 16; | ||
| 349 | u32 input_gap = config.texture_copy.input_gap * 16; | ||
| 350 | u32 output_width = config.texture_copy.output_width * 16; | ||
| 351 | u32 output_gap = config.texture_copy.output_gap * 16; | ||
| 352 | 358 | ||
| 353 | size_t contiguous_input_size = | 359 | size_t contiguous_input_size = |
| 354 | config.texture_copy.size / input_width * (input_width + input_gap); | 360 | config.texture_copy.size / input_width * (input_width + input_gap); |
| @@ -360,7 +366,6 @@ static void TextureCopy(const Regs::DisplayTransferConfig& config) { | |||
| 360 | Memory::RasterizerFlushAndInvalidateRegion(config.GetPhysicalOutputAddress(), | 366 | Memory::RasterizerFlushAndInvalidateRegion(config.GetPhysicalOutputAddress(), |
| 361 | static_cast<u32>(contiguous_output_size)); | 367 | static_cast<u32>(contiguous_output_size)); |
| 362 | 368 | ||
| 363 | u32 remaining_size = config.texture_copy.size; | ||
| 364 | u32 remaining_input = input_width; | 369 | u32 remaining_input = input_width; |
| 365 | u32 remaining_output = output_width; | 370 | u32 remaining_output = output_width; |
| 366 | while (remaining_size > 0) { | 371 | while (remaining_size > 0) { |
diff --git a/src/core/hw/gpu.h b/src/core/hw/gpu.h index bdd997b2a..21b127fee 100644 --- a/src/core/hw/gpu.h +++ b/src/core/hw/gpu.h | |||
| @@ -225,7 +225,7 @@ struct Regs { | |||
| 225 | INSERT_PADDING_WORDS(0x1); | 225 | INSERT_PADDING_WORDS(0x1); |
| 226 | 226 | ||
| 227 | struct { | 227 | struct { |
| 228 | u32 size; | 228 | u32 size; // The lower 4 bits are ignored |
| 229 | 229 | ||
| 230 | union { | 230 | union { |
| 231 | u32 input_size; | 231 | u32 input_size; |