From e832bbe554e174694cb43d4fe86f31af283a10da Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Fri, 25 Jul 2014 11:22:40 +0200 Subject: GSP: Add a helper function for convenience. --- src/core/hle/service/gsp.cpp | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) (limited to 'src/core/hle/service/gsp.cpp') diff --git a/src/core/hle/service/gsp.cpp b/src/core/hle/service/gsp.cpp index 635f50a53..f793b592c 100644 --- a/src/core/hle/service/gsp.cpp +++ b/src/core/hle/service/gsp.cpp @@ -42,35 +42,40 @@ static inline InterruptRelayQueue* GetInterruptRelayQueue(u32 thread_id) { sizeof(InterruptRelayQueue) * thread_id); } -/// Write a GSP GPU hardware register -void WriteHWRegs(Service::Interface* self) { - u32* cmd_buff = Service::GetCommandBuffer(); - u32 reg_addr = cmd_buff[1]; - u32 size = cmd_buff[2]; - +void WriteHWRegs(u32 base_address, u32 size_in_bytes, const u32* data) { // TODO: Return proper error codes - if (reg_addr + size >= 0x420000) { - ERROR_LOG(GPU, "Write address out of range! (address=0x%08x, size=0x%08x)", reg_addr, size); + if (base_address + size_in_bytes >= 0x420000) { + ERROR_LOG(GPU, "Write address out of range! (address=0x%08x, size=0x%08x)", + base_address, size_in_bytes); return; } // size should be word-aligned - if ((size % 4) != 0) { - ERROR_LOG(GPU, "Invalid size 0x%08x", size); + if ((size_in_bytes % 4) != 0) { + ERROR_LOG(GPU, "Invalid size 0x%08x", size_in_bytes); return; } - u32* src = (u32*)Memory::GetPointer(cmd_buff[0x4]); - - while (size > 0) { - GPU::Write(reg_addr + 0x1EB00000, *src); + while (size_in_bytes > 0) { + GPU::Write(base_address + 0x1EB00000, *data); - size -= 4; - ++src; - reg_addr += 4; + size_in_bytes -= 4; + ++data; + base_address += 4; } } +/// Write a GSP GPU hardware register +void WriteHWRegs(Service::Interface* self) { + u32* cmd_buff = Service::GetCommandBuffer(); + u32 reg_addr = cmd_buff[1]; + u32 size = cmd_buff[2]; + + u32* src = (u32*)Memory::GetPointer(cmd_buff[0x4]); + + WriteHWRegs(reg_addr, size, src); +} + /// Read a GSP GPU hardware register void ReadHWRegs(Service::Interface* self) { u32* cmd_buff = Service::GetCommandBuffer(); -- cgit v1.2.3 From 590c206ac8836f0e4544d2cb84191d77d07b9f36 Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Fri, 25 Jul 2014 11:23:28 +0200 Subject: GSP: Implement SetBufferSwap. --- src/core/hle/service/gsp.cpp | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) (limited to 'src/core/hle/service/gsp.cpp') diff --git a/src/core/hle/service/gsp.cpp b/src/core/hle/service/gsp.cpp index f793b592c..417c01b83 100644 --- a/src/core/hle/service/gsp.cpp +++ b/src/core/hle/service/gsp.cpp @@ -105,6 +105,40 @@ void ReadHWRegs(Service::Interface* self) { } } +void SetBufferSwap(u32 screen_id, const FrameBufferInfo& info) { + u32 base_address = 0x400000; + if (info.active_fb == 0) { + WriteHWRegs(base_address + 4 * GPU_REG_INDEX(framebuffer_config[screen_id].address_left1), 4, &info.address_left); + WriteHWRegs(base_address + 4 * GPU_REG_INDEX(framebuffer_config[screen_id].address_right1), 4, &info.address_right); + } else { + WriteHWRegs(base_address + 4 * GPU_REG_INDEX(framebuffer_config[screen_id].address_left2), 4, &info.address_left); + WriteHWRegs(base_address + 4 * GPU_REG_INDEX(framebuffer_config[screen_id].address_right2), 4, &info.address_right); + } + WriteHWRegs(base_address + 4 * GPU_REG_INDEX(framebuffer_config[screen_id].stride), 4, &info.stride); + WriteHWRegs(base_address + 4 * GPU_REG_INDEX(framebuffer_config[screen_id].color_format), 4, &info.format); + WriteHWRegs(base_address + 4 * GPU_REG_INDEX(framebuffer_config[screen_id].active_fb), 4, &info.shown_fb); +} + +/** + * GSP_GPU::SetBufferSwap service function + * + * Updates GPU display framebuffer configuration using the specified parameters. + * + * Inputs: + * 1 : Screen ID (0 = top screen, 1 = bottom screen) + * 2-7 : FrameBufferInfo structure + * Outputs: + * 1: Result code + */ +void SetBufferSwap(Service::Interface* self) { + u32* cmd_buff = Service::GetCommandBuffer(); + u32 screen_id = cmd_buff[1]; + FrameBufferInfo* fb_info = (FrameBufferInfo*)&cmd_buff[2]; + SetBufferSwap(screen_id, *fb_info); + + cmd_buff[1] = 0; // No error +} + /** * GSP_GPU::RegisterInterruptRelayQueue service function * Inputs: @@ -283,7 +317,7 @@ const Interface::FunctionInfo FunctionTable[] = { {0x00020084, nullptr, "WriteHWRegsWithMask"}, {0x00030082, nullptr, "WriteHWRegRepeat"}, {0x00040080, ReadHWRegs, "ReadHWRegs"}, - {0x00050200, nullptr, "SetBufferSwap"}, + {0x00050200, SetBufferSwap, "SetBufferSwap"}, {0x00060082, nullptr, "SetCommandList"}, {0x000700C2, nullptr, "RequestDma"}, {0x00080082, nullptr, "FlushDataCache"}, -- cgit v1.2.3 From 14b24a75b37545faf49584864cb85555f22a0154 Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Tue, 19 Aug 2014 20:57:43 +0200 Subject: GSP: Update framebuffer information when necessary. --- src/core/hle/service/gsp.cpp | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'src/core/hle/service/gsp.cpp') 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) { 0x800 + (thread_id * sizeof(CommandBuffer))); } +static inline FrameBufferUpdate* GetFrameBufferInfo(u32 thread_id, u32 screen_index) { + if (0 == g_shared_memory) + return nullptr; + + _dbg_assert_msg_(GSP, screen_index < 2, "Invalid screen index"); + + // For each thread there are two FrameBufferUpdate fields + u32 offset = 0x200 + (2 * thread_id + screen_index) * sizeof(FrameBufferUpdate); + return (FrameBufferUpdate*)Kernel::GetSharedMemoryPointer(g_shared_memory, offset); +} + /// Gets a pointer to the interrupt relay queue for a given thread index static inline InterruptRelayQueue* GetInterruptRelayQueue(u32 thread_id) { return (InterruptRelayQueue*)Kernel::GetSharedMemoryPointer(g_shared_memory, @@ -166,6 +177,7 @@ void RegisterInterruptRelayQueue(Service::Interface* self) { /** * Signals that the specified interrupt type has occurred to userland code * @param interrupt_id ID of interrupt that is being signalled + * @todo This should probably take a thread_id parameter and only signal this thread? */ void SignalInterrupt(InterruptId interrupt_id) { if (0 == g_interrupt_event) { @@ -191,7 +203,7 @@ void SignalInterrupt(InterruptId interrupt_id) { } /// Executes the next GSP command -void ExecuteCommand(const Command& command) { +void ExecuteCommand(const Command& command, u32 thread_id) { // Utility function to convert register ID to address auto WriteGPURegister = [](u32 id, u32 data) { GPU::Write(0x1EF00000 + 4 * id, data); @@ -262,6 +274,15 @@ void ExecuteCommand(const Command& command) { SignalInterrupt(InterruptId::PPF); SignalInterrupt(InterruptId::P3D); SignalInterrupt(InterruptId::DMA); + + // Update framebuffer information if requested + for (int screen_id = 0; screen_id < 2; ++screen_id) { + FrameBufferUpdate* info = GetFrameBufferInfo(thread_id, screen_id); + if (info->is_dirty) + SetBufferSwap(screen_id, info->framebuffer_info[info->index]); + + info->is_dirty = false; + } break; } @@ -304,7 +325,7 @@ void TriggerCmdReqQueue(Service::Interface* self) { g_debugger.GXCommandProcessed((u8*)&command_buffer->commands[i]); // Decode and execute command - ExecuteCommand(command_buffer->commands[i]); + ExecuteCommand(command_buffer->commands[i], thread_id); // Indicates that command has completed command_buffer->number_commands = command_buffer->number_commands - 1; -- cgit v1.2.3 From 26ade98411c1d76540695f15378ff7f6b5388b1a Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Thu, 14 Aug 2014 19:21:55 +0200 Subject: Pica/citra-qt: Replace command list view and command list debugging code with something more sophisticated. --- src/core/hle/service/gsp.cpp | 5 ----- 1 file changed, 5 deletions(-) (limited to 'src/core/hle/service/gsp.cpp') diff --git a/src/core/hle/service/gsp.cpp b/src/core/hle/service/gsp.cpp index 027ba5a37..46c5a8ddd 100644 --- a/src/core/hle/service/gsp.cpp +++ b/src/core/hle/service/gsp.cpp @@ -230,11 +230,6 @@ void ExecuteCommand(const Command& command, u32 thread_id) { // TODO: Not sure if we are supposed to always write this .. seems to trigger processing though WriteGPURegister(GPU_REG_INDEX(command_processor_config.trigger), 1); - // TODO: Move this to GPU - // TODO: Not sure what units the size is measured in - g_debugger.CommandListCalled(params.address, - (u32*)Memory::GetPointer(params.address), - params.size); SignalInterrupt(InterruptId::P3D); break; } -- cgit v1.2.3