| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207 |
- // Copyright 2014 Citra Emulator Project
- // Licensed under GPLv2 or any later version
- // Refer to the license.txt file included.
- #pragma once
- #include <cstddef>
- #include <string>
- #include "common/bit_field.h"
- #include "common/common_types.h"
- #include "core/hle/service/service.h"
- ////////////////////////////////////////////////////////////////////////////////////////////////////
- // Namespace GSP_GPU
- namespace GSP_GPU {
- /// GSP interrupt ID
- enum class InterruptId : u8 {
- PSC0 = 0x00,
- PSC1 = 0x01,
- PDC0 = 0x02, // Seems called every vertical screen line
- PDC1 = 0x03, // Seems called every frame
- PPF = 0x04,
- P3D = 0x05,
- DMA = 0x06,
- };
- /// GSP command ID
- enum class CommandId : u32 {
- REQUEST_DMA = 0x00,
- /// Submits a commandlist for execution by the GPU.
- SUBMIT_GPU_CMDLIST = 0x01,
- // Fills a given memory range with a particular value
- SET_MEMORY_FILL = 0x02,
- // Copies an image and optionally performs color-conversion or scaling.
- // This is highly similar to the GameCube's EFB copy feature
- SET_DISPLAY_TRANSFER = 0x03,
- // Conceptionally similar to SET_DISPLAY_TRANSFER and presumable uses the same hardware path
- SET_TEXTURE_COPY = 0x04,
- /// Flushes up to 3 cache regions in a single command.
- CACHE_FLUSH = 0x05,
- };
- /// GSP thread interrupt relay queue
- struct InterruptRelayQueue {
- // Index of last interrupt in the queue
- u8 index;
- // Number of interrupts remaining to be processed by the userland code
- u8 number_interrupts;
- // Error code - zero on success, otherwise an error has occurred
- u8 error_code;
- u8 padding1;
- u32 missed_PDC0;
- u32 missed_PDC1;
- InterruptId slot[0x34]; ///< Interrupt ID slots
- };
- static_assert(sizeof(InterruptRelayQueue) == 0x40,
- "InterruptRelayQueue struct has incorrect size");
- struct FrameBufferInfo {
- BitField<0, 1, u32> active_fb; // 0 = first, 1 = second
- u32 address_left;
- u32 address_right;
- u32 stride; // maps to 0x1EF00X90 ?
- u32 format; // maps to 0x1EF00X70 ?
- u32 shown_fb; // maps to 0x1EF00X78 ?
- u32 unknown;
- };
- static_assert(sizeof(FrameBufferInfo) == 0x1c, "Struct has incorrect size");
- struct FrameBufferUpdate {
- BitField<0, 1, u8> index; // Index used for GSP::SetBufferSwap
- BitField<0, 1, u8> is_dirty; // true if GSP should update GPU framebuffer registers
- u16 pad1;
- FrameBufferInfo framebuffer_info[2];
- u32 pad2;
- };
- static_assert(sizeof(FrameBufferUpdate) == 0x40, "Struct has incorrect size");
- // TODO: Not sure if this padding is correct.
- // Chances are the second block is stored at offset 0x24 rather than 0x20.
- #ifndef _MSC_VER
- static_assert(offsetof(FrameBufferUpdate, framebuffer_info[1]) == 0x20, "FrameBufferInfo element has incorrect alignment");
- #endif
- /// GSP command
- struct Command {
- BitField<0, 8, CommandId> id;
- union {
- struct {
- u32 source_address;
- u32 dest_address;
- u32 size;
- } dma_request;
- struct {
- u32 address;
- u32 size;
- u32 flags;
- u32 unused[3];
- u32 do_flush;
- } submit_gpu_cmdlist;
- struct {
- u32 start1;
- u32 value1;
- u32 end1;
- u32 start2;
- u32 value2;
- u32 end2;
- u16 control1;
- u16 control2;
- } memory_fill;
- struct {
- u32 in_buffer_address;
- u32 out_buffer_address;
- u32 in_buffer_size;
- u32 out_buffer_size;
- u32 flags;
- } display_transfer;
- struct {
- u32 in_buffer_address;
- u32 out_buffer_address;
- u32 size;
- u32 in_width_gap;
- u32 out_width_gap;
- u32 flags;
- } texture_copy;
- struct {
- struct {
- u32 address;
- u32 size;
- } regions[3];
- } cache_flush;
- u8 raw_data[0x1C];
- };
- };
- static_assert(sizeof(Command) == 0x20, "Command struct has incorrect size");
- /// GSP shared memory GX command buffer header
- struct CommandBuffer {
- union {
- u32 hex;
- // Current command index. This index is updated by GSP module after loading the command
- // data, right before the command is processed. When this index is updated by GSP module,
- // the total commands field is decreased by one as well.
- BitField<0,8,u32> index;
- // Total commands to process, must not be value 0 when GSP module handles commands. This
- // must be <=15 when writing a command to shared memory. This is incremented by the
- // application when writing a command to shared memory, after increasing this value
- // TriggerCmdReqQueue is only used if this field is value 1.
- BitField<8,8,u32> number_commands;
- };
- u32 unk[7];
- Command commands[0xF];
- };
- static_assert(sizeof(CommandBuffer) == 0x200, "CommandBuffer struct has incorrect size");
- /// Interface to "srv:" service
- class Interface : public Service::Interface {
- public:
- Interface();
- ~Interface() override;
- std::string GetPortName() const override {
- return "gsp::Gpu";
- }
- };
- /**
- * Signals that the specified interrupt type has occurred to userland code
- * @param interrupt_id ID of interrupt that is being signalled
- */
- void SignalInterrupt(InterruptId interrupt_id);
- void SetBufferSwap(u32 screen_id, const FrameBufferInfo& info);
- /**
- * Retrieves the framebuffer info stored in the GSP shared memory for the
- * specified screen index and thread id.
- * @param thread_id GSP thread id of the process that accesses the structure that we are requesting.
- * @param screen_index Index of the screen we are requesting (Top = 0, Bottom = 1).
- * @returns FramebufferUpdate Information about the specified framebuffer.
- */
- FrameBufferUpdate* GetFrameBufferInfo(u32 thread_id, u32 screen_index);
- } // namespace
|