diff options
Diffstat (limited to 'src/core/hw/gpu.cpp')
| -rw-r--r-- | src/core/hw/gpu.cpp | 69 |
1 files changed, 49 insertions, 20 deletions
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp index 3ccbc03b2..68ae38289 100644 --- a/src/core/hw/gpu.cpp +++ b/src/core/hw/gpu.cpp | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <cstring> | 5 | #include <cstring> |
| 6 | #include <numeric> | ||
| 6 | #include <type_traits> | 7 | #include <type_traits> |
| 7 | 8 | ||
| 8 | #include "common/color.h" | 9 | #include "common/color.h" |
| @@ -158,14 +159,59 @@ inline void Write(u32 addr, const T data) { | |||
| 158 | u8* src_pointer = Memory::GetPhysicalPointer(config.GetPhysicalInputAddress()); | 159 | u8* src_pointer = Memory::GetPhysicalPointer(config.GetPhysicalInputAddress()); |
| 159 | u8* dst_pointer = Memory::GetPhysicalPointer(config.GetPhysicalOutputAddress()); | 160 | u8* dst_pointer = Memory::GetPhysicalPointer(config.GetPhysicalOutputAddress()); |
| 160 | 161 | ||
| 162 | if (config.is_texture_copy) { | ||
| 163 | u32 input_width = config.texture_copy.input_width * 16; | ||
| 164 | u32 input_gap = config.texture_copy.input_gap * 16; | ||
| 165 | u32 output_width = config.texture_copy.output_width * 16; | ||
| 166 | u32 output_gap = config.texture_copy.output_gap * 16; | ||
| 167 | |||
| 168 | size_t contiguous_input_size = config.texture_copy.size / input_width * (input_width + input_gap); | ||
| 169 | VideoCore::g_renderer->hw_rasterizer->NotifyPreRead(config.GetPhysicalInputAddress(), contiguous_input_size); | ||
| 170 | |||
| 171 | u32 remaining_size = config.texture_copy.size; | ||
| 172 | u32 remaining_input = input_width; | ||
| 173 | u32 remaining_output = output_width; | ||
| 174 | while (remaining_size > 0) { | ||
| 175 | u32 copy_size = std::min({ remaining_input, remaining_output, remaining_size }); | ||
| 176 | |||
| 177 | std::memcpy(dst_pointer, src_pointer, copy_size); | ||
| 178 | src_pointer += copy_size; | ||
| 179 | dst_pointer += copy_size; | ||
| 180 | |||
| 181 | remaining_input -= copy_size; | ||
| 182 | remaining_output -= copy_size; | ||
| 183 | remaining_size -= copy_size; | ||
| 184 | |||
| 185 | if (remaining_input == 0) { | ||
| 186 | remaining_input = input_width; | ||
| 187 | src_pointer += input_gap; | ||
| 188 | } | ||
| 189 | if (remaining_output == 0) { | ||
| 190 | remaining_output = output_width; | ||
| 191 | dst_pointer += output_gap; | ||
| 192 | } | ||
| 193 | } | ||
| 194 | |||
| 195 | LOG_TRACE(HW_GPU, "TextureCopy: 0x%X bytes from 0x%08X(%u+%u)-> 0x%08X(%u+%u), flags 0x%08X", | ||
| 196 | config.texture_copy.size, | ||
| 197 | config.GetPhysicalInputAddress(), input_width, input_gap, | ||
| 198 | config.GetPhysicalOutputAddress(), output_width, output_gap, | ||
| 199 | config.flags); | ||
| 200 | |||
| 201 | size_t contiguous_output_size = config.texture_copy.size / output_width * (output_width + output_gap); | ||
| 202 | VideoCore::g_renderer->hw_rasterizer->NotifyFlush(config.GetPhysicalOutputAddress(), contiguous_output_size); | ||
| 203 | |||
| 204 | GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PPF); | ||
| 205 | break; | ||
| 206 | } | ||
| 207 | |||
| 161 | if (config.scaling > config.ScaleXY) { | 208 | if (config.scaling > config.ScaleXY) { |
| 162 | LOG_CRITICAL(HW_GPU, "Unimplemented display transfer scaling mode %u", config.scaling.Value()); | 209 | LOG_CRITICAL(HW_GPU, "Unimplemented display transfer scaling mode %u", config.scaling.Value()); |
| 163 | UNIMPLEMENTED(); | 210 | UNIMPLEMENTED(); |
| 164 | break; | 211 | break; |
| 165 | } | 212 | } |
| 166 | 213 | ||
| 167 | if (config.output_tiled && | 214 | if (config.input_linear && config.scaling != config.NoScale) { |
| 168 | (config.scaling == config.ScaleXY || config.scaling == config.ScaleX)) { | ||
| 169 | LOG_CRITICAL(HW_GPU, "Scaling is only implemented on tiled input"); | 215 | LOG_CRITICAL(HW_GPU, "Scaling is only implemented on tiled input"); |
| 170 | UNIMPLEMENTED(); | 216 | UNIMPLEMENTED(); |
| 171 | break; | 217 | break; |
| @@ -182,23 +228,6 @@ inline void Write(u32 addr, const T data) { | |||
| 182 | 228 | ||
| 183 | VideoCore::g_renderer->hw_rasterizer->NotifyPreRead(config.GetPhysicalInputAddress(), input_size); | 229 | VideoCore::g_renderer->hw_rasterizer->NotifyPreRead(config.GetPhysicalInputAddress(), input_size); |
| 184 | 230 | ||
| 185 | if (config.raw_copy) { | ||
| 186 | // Raw copies do not perform color conversion nor tiled->linear / linear->tiled conversions | ||
| 187 | // TODO(Subv): Verify if raw copies perform scaling | ||
| 188 | memcpy(dst_pointer, src_pointer, output_size); | ||
| 189 | |||
| 190 | LOG_TRACE(HW_GPU, "DisplayTriggerTransfer: 0x%08x bytes from 0x%08x(%ux%u)-> 0x%08x(%ux%u), output format: %x, flags 0x%08X, Raw copy", | ||
| 191 | output_size, | ||
| 192 | config.GetPhysicalInputAddress(), config.input_width.Value(), config.input_height.Value(), | ||
| 193 | config.GetPhysicalOutputAddress(), config.output_width.Value(), config.output_height.Value(), | ||
| 194 | config.output_format.Value(), config.flags); | ||
| 195 | |||
| 196 | GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PPF); | ||
| 197 | |||
| 198 | VideoCore::g_renderer->hw_rasterizer->NotifyFlush(config.GetPhysicalOutputAddress(), output_size); | ||
| 199 | break; | ||
| 200 | } | ||
| 201 | |||
| 202 | for (u32 y = 0; y < output_height; ++y) { | 231 | for (u32 y = 0; y < output_height; ++y) { |
| 203 | for (u32 x = 0; x < output_width; ++x) { | 232 | for (u32 x = 0; x < output_width; ++x) { |
| 204 | Math::Vec4<u8> src_color; | 233 | Math::Vec4<u8> src_color; |
| @@ -220,7 +249,7 @@ inline void Write(u32 addr, const T data) { | |||
| 220 | u32 src_offset; | 249 | u32 src_offset; |
| 221 | u32 dst_offset; | 250 | u32 dst_offset; |
| 222 | 251 | ||
| 223 | if (config.output_tiled) { | 252 | if (config.input_linear) { |
| 224 | if (!config.dont_swizzle) { | 253 | if (!config.dont_swizzle) { |
| 225 | // Interpret the input as linear and the output as tiled | 254 | // Interpret the input as linear and the output as tiled |
| 226 | u32 coarse_y = y & ~7; | 255 | u32 coarse_y = y & ~7; |