summaryrefslogtreecommitdiff
path: root/src/core/hw/gpu.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hw/gpu.cpp')
-rw-r--r--src/core/hw/gpu.cpp69
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;