diff options
| author | 2014-08-19 20:57:43 +0200 | |
|---|---|---|
| committer | 2014-08-25 22:03:18 +0200 | |
| commit | 14b24a75b37545faf49584864cb85555f22a0154 (patch) | |
| tree | df4350faa6f2856b876abe6707e856dfa2e10f83 /src | |
| parent | GSP: Implement SetBufferSwap. (diff) | |
| download | yuzu-14b24a75b37545faf49584864cb85555f22a0154.tar.gz yuzu-14b24a75b37545faf49584864cb85555f22a0154.tar.xz yuzu-14b24a75b37545faf49584864cb85555f22a0154.zip | |
GSP: Update framebuffer information when necessary.
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/service/gsp.cpp | 25 | ||||
| -rw-r--r-- | src/core/hle/service/gsp.h | 18 |
2 files changed, 41 insertions, 2 deletions
diff --git a/src/core/hle/service/gsp.cpp b/src/core/hle/service/gsp.cpp index 417c01b83..027ba5a37 100644 --- a/src/core/hle/service/gsp.cpp +++ b/src/core/hle/service/gsp.cpp | |||
| @@ -36,6 +36,17 @@ static inline u8* GetCommandBuffer(u32 thread_id) { | |||
| 36 | 0x800 + (thread_id * sizeof(CommandBuffer))); | 36 | 0x800 + (thread_id * sizeof(CommandBuffer))); |
| 37 | } | 37 | } |
| 38 | 38 | ||
| 39 | static inline FrameBufferUpdate* GetFrameBufferInfo(u32 thread_id, u32 screen_index) { | ||
| 40 | if (0 == g_shared_memory) | ||
| 41 | return nullptr; | ||
| 42 | |||
| 43 | _dbg_assert_msg_(GSP, screen_index < 2, "Invalid screen index"); | ||
| 44 | |||
| 45 | // For each thread there are two FrameBufferUpdate fields | ||
| 46 | u32 offset = 0x200 + (2 * thread_id + screen_index) * sizeof(FrameBufferUpdate); | ||
| 47 | return (FrameBufferUpdate*)Kernel::GetSharedMemoryPointer(g_shared_memory, offset); | ||
| 48 | } | ||
| 49 | |||
| 39 | /// Gets a pointer to the interrupt relay queue for a given thread index | 50 | /// Gets a pointer to the interrupt relay queue for a given thread index |
| 40 | static inline InterruptRelayQueue* GetInterruptRelayQueue(u32 thread_id) { | 51 | static inline InterruptRelayQueue* GetInterruptRelayQueue(u32 thread_id) { |
| 41 | return (InterruptRelayQueue*)Kernel::GetSharedMemoryPointer(g_shared_memory, | 52 | return (InterruptRelayQueue*)Kernel::GetSharedMemoryPointer(g_shared_memory, |
| @@ -166,6 +177,7 @@ void RegisterInterruptRelayQueue(Service::Interface* self) { | |||
| 166 | /** | 177 | /** |
| 167 | * Signals that the specified interrupt type has occurred to userland code | 178 | * Signals that the specified interrupt type has occurred to userland code |
| 168 | * @param interrupt_id ID of interrupt that is being signalled | 179 | * @param interrupt_id ID of interrupt that is being signalled |
| 180 | * @todo This should probably take a thread_id parameter and only signal this thread? | ||
| 169 | */ | 181 | */ |
| 170 | void SignalInterrupt(InterruptId interrupt_id) { | 182 | void SignalInterrupt(InterruptId interrupt_id) { |
| 171 | if (0 == g_interrupt_event) { | 183 | if (0 == g_interrupt_event) { |
| @@ -191,7 +203,7 @@ void SignalInterrupt(InterruptId interrupt_id) { | |||
| 191 | } | 203 | } |
| 192 | 204 | ||
| 193 | /// Executes the next GSP command | 205 | /// Executes the next GSP command |
| 194 | void ExecuteCommand(const Command& command) { | 206 | void ExecuteCommand(const Command& command, u32 thread_id) { |
| 195 | // Utility function to convert register ID to address | 207 | // Utility function to convert register ID to address |
| 196 | auto WriteGPURegister = [](u32 id, u32 data) { | 208 | auto WriteGPURegister = [](u32 id, u32 data) { |
| 197 | GPU::Write<u32>(0x1EF00000 + 4 * id, data); | 209 | GPU::Write<u32>(0x1EF00000 + 4 * id, data); |
| @@ -262,6 +274,15 @@ void ExecuteCommand(const Command& command) { | |||
| 262 | SignalInterrupt(InterruptId::PPF); | 274 | SignalInterrupt(InterruptId::PPF); |
| 263 | SignalInterrupt(InterruptId::P3D); | 275 | SignalInterrupt(InterruptId::P3D); |
| 264 | SignalInterrupt(InterruptId::DMA); | 276 | SignalInterrupt(InterruptId::DMA); |
| 277 | |||
| 278 | // Update framebuffer information if requested | ||
| 279 | for (int screen_id = 0; screen_id < 2; ++screen_id) { | ||
| 280 | FrameBufferUpdate* info = GetFrameBufferInfo(thread_id, screen_id); | ||
| 281 | if (info->is_dirty) | ||
| 282 | SetBufferSwap(screen_id, info->framebuffer_info[info->index]); | ||
| 283 | |||
| 284 | info->is_dirty = false; | ||
| 285 | } | ||
| 265 | break; | 286 | break; |
| 266 | } | 287 | } |
| 267 | 288 | ||
| @@ -304,7 +325,7 @@ void TriggerCmdReqQueue(Service::Interface* self) { | |||
| 304 | g_debugger.GXCommandProcessed((u8*)&command_buffer->commands[i]); | 325 | g_debugger.GXCommandProcessed((u8*)&command_buffer->commands[i]); |
| 305 | 326 | ||
| 306 | // Decode and execute command | 327 | // Decode and execute command |
| 307 | ExecuteCommand(command_buffer->commands[i]); | 328 | ExecuteCommand(command_buffer->commands[i], thread_id); |
| 308 | 329 | ||
| 309 | // Indicates that command has completed | 330 | // Indicates that command has completed |
| 310 | command_buffer->number_commands = command_buffer->number_commands - 1; | 331 | command_buffer->number_commands = command_buffer->number_commands - 1; |
diff --git a/src/core/hle/service/gsp.h b/src/core/hle/service/gsp.h index 884cfd65a..a09d59dbb 100644 --- a/src/core/hle/service/gsp.h +++ b/src/core/hle/service/gsp.h | |||
| @@ -4,6 +4,8 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <cstddef> | ||
| 8 | |||
| 7 | #include "common/bit_field.h" | 9 | #include "common/bit_field.h" |
| 8 | #include "core/hle/service/service.h" | 10 | #include "core/hle/service/service.h" |
| 9 | 11 | ||
| @@ -76,6 +78,22 @@ struct FrameBufferInfo { | |||
| 76 | }; | 78 | }; |
| 77 | static_assert(sizeof(FrameBufferInfo) == 0x1c, "Struct has incorrect size"); | 79 | static_assert(sizeof(FrameBufferInfo) == 0x1c, "Struct has incorrect size"); |
| 78 | 80 | ||
| 81 | struct FrameBufferUpdate { | ||
| 82 | BitField<0, 1, u8> index; // Index used for GSP::SetBufferSwap | ||
| 83 | BitField<0, 1, u8> is_dirty; // true if GSP should update GPU framebuffer registers | ||
| 84 | u16 pad1; | ||
| 85 | |||
| 86 | FrameBufferInfo framebuffer_info[2]; | ||
| 87 | |||
| 88 | u32 pad2; | ||
| 89 | }; | ||
| 90 | static_assert(sizeof(FrameBufferUpdate) == 0x40, "Struct has incorrect size"); | ||
| 91 | // TODO: Not sure if this padding is correct. | ||
| 92 | // Chances are the second block is stored at offset 0x24 rather than 0x20. | ||
| 93 | #ifndef _MSC_VER | ||
| 94 | static_assert(offsetof(FrameBufferUpdate, framebuffer_info[1]) == 0x20, "FrameBufferInfo element has incorrect alignment"); | ||
| 95 | #endif | ||
| 96 | |||
| 79 | /// GSP command | 97 | /// GSP command |
| 80 | struct Command { | 98 | struct Command { |
| 81 | BitField<0, 8, CommandId> id; | 99 | BitField<0, 8, CommandId> id; |