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.cpp33
1 files changed, 18 insertions, 15 deletions
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp
index 3b730a0de..ad39fdc49 100644
--- a/src/core/hw/gpu.cpp
+++ b/src/core/hw/gpu.cpp
@@ -27,8 +27,6 @@ Regs g_regs;
27bool g_skip_frame = false; ///< True if the current frame was skipped 27bool g_skip_frame = false; ///< True if the current frame was skipped
28 28
29static u64 frame_ticks = 0; ///< 268MHz / gpu_refresh_rate frames per second 29static u64 frame_ticks = 0; ///< 268MHz / gpu_refresh_rate frames per second
30static u64 line_ticks = 0; ///< Number of ticks for a screen line
31static u32 cur_line = 0; ///< Current screen line
32static u64 last_update_tick = 0; ///< CPU ticl count from last GPU update 30static u64 last_update_tick = 0; ///< CPU ticl count from last GPU update
33static u64 frame_count = 0; ///< Number of frames drawn 31static u64 frame_count = 0; ///< Number of frames drawn
34static bool last_skip_frame = false; ///< True if the last frame was skipped 32static bool last_skip_frame = false; ///< True if the last frame was skipped
@@ -79,6 +77,12 @@ inline void Write(u32 addr, const T data) {
79 *ptr = bswap32(config.value); // TODO: This is just a workaround to missing framebuffer format emulation 77 *ptr = bswap32(config.value); // TODO: This is just a workaround to missing framebuffer format emulation
80 78
81 LOG_TRACE(HW_GPU, "MemoryFill from 0x%08x to 0x%08x", config.GetStartAddress(), config.GetEndAddress()); 79 LOG_TRACE(HW_GPU, "MemoryFill from 0x%08x to 0x%08x", config.GetStartAddress(), config.GetEndAddress());
80
81 if (!is_second_filler) {
82 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PSC0);
83 } else {
84 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PSC1);
85 }
82 } 86 }
83 break; 87 break;
84 } 88 }
@@ -152,6 +156,8 @@ inline void Write(u32 addr, const T data) {
152 config.GetPhysicalInputAddress(), (u32)config.input_width, (u32)config.input_height, 156 config.GetPhysicalInputAddress(), (u32)config.input_width, (u32)config.input_height,
153 config.GetPhysicalOutputAddress(), (u32)config.output_width, (u32)config.output_height, 157 config.GetPhysicalOutputAddress(), (u32)config.output_width, (u32)config.output_height,
154 config.output_format.Value()); 158 config.output_format.Value());
159
160 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PPF);
155 } 161 }
156 break; 162 break;
157 } 163 }
@@ -193,20 +199,14 @@ void Update() {
193 // blank, we need to simulate it. Based on testing, it seems that retail applications work more 199 // blank, we need to simulate it. Based on testing, it seems that retail applications work more
194 // accurately when this is signalled between thread switches. 200 // accurately when this is signalled between thread switches.
195 201
196 if (HLE::g_reschedule) { 202 u64 current_ticks = Core::g_app_core->GetTicks();
197 u64 current_ticks = Core::g_app_core->GetTicks();
198 u32 num_lines = static_cast<u32>((current_ticks - last_update_tick) / line_ticks);
199 203
200 // Synchronize line... 204
201 if (num_lines > 0) { 205 if (HLE::g_reschedule) {
202 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PDC0);
203 cur_line += num_lines;
204 last_update_tick += (num_lines * line_ticks);
205 }
206 206
207 // Synchronize frame... 207 // Synchronize frame...
208 if (cur_line >= framebuffer_top.height) { 208 if ((current_ticks - last_update_tick) >= frame_ticks) {
209 cur_line = 0; 209 last_update_tick += frame_ticks;
210 frame_count++; 210 frame_count++;
211 last_skip_frame = g_skip_frame; 211 last_skip_frame = g_skip_frame;
212 g_skip_frame = (frame_count & Settings::values.frame_skip) != 0; 212 g_skip_frame = (frame_count & Settings::values.frame_skip) != 0;
@@ -223,6 +223,11 @@ void Update() {
223 } 223 }
224 224
225 // Signal to GSP that GPU interrupt has occurred 225 // Signal to GSP that GPU interrupt has occurred
226 // TODO(yuriks): hwtest to determine if PDC0 is for the Top screen and PDC1 for the Sub
227 // screen, or if both use the same interrupts and these two instead determine the
228 // beginning and end of the VBlank period. If needed, split the interrupt firing into
229 // two different intervals.
230 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PDC0);
226 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PDC1); 231 GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PDC1);
227 232
228 // TODO(bunnei): Fake a DSP interrupt on each frame. This does not belong here, but 233 // TODO(bunnei): Fake a DSP interrupt on each frame. This does not belong here, but
@@ -264,8 +269,6 @@ void Init() {
264 framebuffer_sub.active_fb = 0; 269 framebuffer_sub.active_fb = 0;
265 270
266 frame_ticks = 268123480 / Settings::values.gpu_refresh_rate; 271 frame_ticks = 268123480 / Settings::values.gpu_refresh_rate;
267 line_ticks = (GPU::frame_ticks / framebuffer_top.height);
268 cur_line = 0;
269 last_update_tick = Core::g_app_core->GetTicks(); 272 last_update_tick = Core::g_app_core->GetTicks();
270 last_skip_frame = false; 273 last_skip_frame = false;
271 g_skip_frame = false; 274 g_skip_frame = false;