// Copyright (c) 2012- PPSSPP Project. // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, version 2.0 or later versions. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License 2.0 for more details. // A copy of the GPL 2.0 should have been included with the program. // If not, see http://www.gnu.org/licenses/ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #pragma once #include #include #include #include "GPU/GPU.h" #include "Core/MemMap.h" #include "GPU/ge_constants.h" #include "GPU/Common/ShaderCommon.h" struct PspGeListArgs; struct GPUgstate; class PointerWrap; enum DisplayListStatus { // The list has been completed PSP_GE_LIST_COMPLETED = 0, // The list is queued but not executed yet PSP_GE_LIST_QUEUED = 1, // The list is currently being executed PSP_GE_LIST_DRAWING = 2, // The list was stopped because it encountered stall address PSP_GE_LIST_STALLING = 3, // The list is paused because of a signal or sceGeBreak PSP_GE_LIST_PAUSED = 4, }; enum DisplayListState { // No state assigned, the list is empty PSP_GE_DL_STATE_NONE = 0, // The list has been queued PSP_GE_DL_STATE_QUEUED = 1, // The list is being executed PSP_GE_DL_STATE_RUNNING = 2, // The list was completed and will be removed PSP_GE_DL_STATE_COMPLETED = 3, // The list has been paused by a signal PSP_GE_DL_STATE_PAUSED = 4, }; enum SignalBehavior { PSP_GE_SIGNAL_NONE = 0x00, PSP_GE_SIGNAL_HANDLER_SUSPEND = 0x01, PSP_GE_SIGNAL_HANDLER_CONTINUE = 0x02, PSP_GE_SIGNAL_HANDLER_PAUSE = 0x03, PSP_GE_SIGNAL_SYNC = 0x08, PSP_GE_SIGNAL_JUMP = 0x10, PSP_GE_SIGNAL_CALL = 0x11, PSP_GE_SIGNAL_RET = 0x12, PSP_GE_SIGNAL_RJUMP = 0x13, PSP_GE_SIGNAL_RCALL = 0x14, PSP_GE_SIGNAL_OJUMP = 0x15, PSP_GE_SIGNAL_OCALL = 0x16, PSP_GE_SIGNAL_RTBP0 = 0x20, PSP_GE_SIGNAL_RTBP1 = 0x21, PSP_GE_SIGNAL_RTBP2 = 0x22, PSP_GE_SIGNAL_RTBP3 = 0x23, PSP_GE_SIGNAL_RTBP4 = 0x24, PSP_GE_SIGNAL_RTBP5 = 0x25, PSP_GE_SIGNAL_RTBP6 = 0x26, PSP_GE_SIGNAL_RTBP7 = 0x27, PSP_GE_SIGNAL_OTBP0 = 0x28, PSP_GE_SIGNAL_OTBP1 = 0x29, PSP_GE_SIGNAL_OTBP2 = 0x2A, PSP_GE_SIGNAL_OTBP3 = 0x2B, PSP_GE_SIGNAL_OTBP4 = 0x2C, PSP_GE_SIGNAL_OTBP5 = 0x2D, PSP_GE_SIGNAL_OTBP6 = 0x2E, PSP_GE_SIGNAL_OTBP7 = 0x2F, PSP_GE_SIGNAL_RCBP = 0x30, PSP_GE_SIGNAL_OCBP = 0x38, PSP_GE_SIGNAL_BREAK1 = 0xF0, PSP_GE_SIGNAL_BREAK2 = 0xFF, }; enum GPURunState { GPUSTATE_RUNNING = 0, GPUSTATE_DONE = 1, GPUSTATE_STALL = 2, GPUSTATE_INTERRUPT = 3, GPUSTATE_ERROR = 4, }; enum GPUSyncType { GPU_SYNC_DRAW, GPU_SYNC_LIST, }; // Used for debug struct FramebufferInfo { u32 fb_address; u32 z_address; int format; u32 width; u32 height; void* fbo; }; struct DisplayListStackEntry { u32 pc; u32 offsetAddr; u32 baseAddr; }; struct DisplayList { int id; u32 startpc; u32 pc; u32 stall; DisplayListState state; SignalBehavior signal; int subIntrBase; u16 subIntrToken; DisplayListStackEntry stack[32]; int stackptr; bool interrupted; u64 waitTicks; bool interruptsEnabled; bool pendingInterrupt; bool started; PSPPointer context; u32 offsetAddr; bool bboxResult; u32 stackAddr; u32 padding; // Android x86-32 does not round the structure size up to the closest multiple of 8 like the other platforms. }; enum GPUInvalidationType { // Affects all memory. Not considered highly. GPU_INVALIDATE_ALL, // Indicates some memory may have changed. GPU_INVALIDATE_HINT, // Reliable invalidation (where any hashing, etc. is unneeded, it'll always invalidate.) GPU_INVALIDATE_SAFE, }; enum GPUEventType { GPU_EVENT_INVALID, GPU_EVENT_PROCESS_QUEUE, GPU_EVENT_INIT_CLEAR, GPU_EVENT_BEGIN_FRAME, GPU_EVENT_COPY_DISPLAY_TO_OUTPUT, GPU_EVENT_REAPPLY_GFX_STATE, GPU_EVENT_INVALIDATE_CACHE, GPU_EVENT_FINISH_EVENT_LOOP, GPU_EVENT_SYNC_THREAD, GPU_EVENT_FB_MEMCPY, GPU_EVENT_FB_MEMSET, GPU_EVENT_FB_STENCIL_UPLOAD, GPU_EVENT_REINITIALIZE, }; struct GPUEvent { GPUEvent(GPUEventType t) : type(t) {} GPUEventType type; union { // GPU_EVENT_INVALIDATE_CACHE struct { u32 addr; int size; GPUInvalidationType type; } invalidate_cache; // GPU_EVENT_FB_MEMCPY struct { u32 dst; u32 src; int size; } fb_memcpy; // GPU_EVENT_FB_MEMSET struct { u32 dst; u8 v; int size; } fb_memset; // GPU_EVENT_FB_STENCIL_UPLOAD struct { u32 dst; int size; } fb_stencil_upload; }; operator GPUEventType() const { return type; } }; class GPUInterface { public: virtual ~GPUInterface() {} static const int DisplayListMaxCount = 64; // Initialization virtual void InitClear() = 0; virtual void Reinitialize() = 0; // Frame managment virtual void BeginHostFrame() = 0; virtual void EndHostFrame() = 0; // Events virtual void RunEventsUntil(u64 globalticks) = 0; virtual void FinishEventLoop() = 0; // Draw queue management virtual DisplayList* getList(int listid) = 0; // TODO: Much of this should probably be shared between the different GPU implementations. virtual u32 EnqueueList(u32 listpc, u32 stall, int subIntrBase, PSPPointer args, bool head) = 0; virtual u32 DequeueList(int listid) = 0; virtual u32 UpdateStall(int listid, u32 newstall) = 0; virtual u32 DrawSync(int mode) = 0; virtual int ListSync(int listid, int mode) = 0; virtual u32 Continue() = 0; virtual u32 Break(int mode) = 0; virtual int GetStack(int index, u32 stackPtr) = 0; virtual void InterruptStart(int listid) = 0; virtual void InterruptEnd(int listid) = 0; virtual void SyncEnd(GPUSyncType waitType, int listid, bool wokeThreads) = 0; virtual void PreExecuteOp(u32 op, u32 diff) = 0; virtual void ExecuteOp(u32 op, u32 diff) = 0; virtual bool InterpretList(DisplayList& list) = 0; // Framebuffer management virtual void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) = 0; virtual void BeginFrame() = 0; // Can be a good place to draw the "memory" framebuffer for accelerated plugins virtual void CopyDisplayToOutput() = 0; // Tells the GPU to update the gpuStats structure. virtual void GetStats(char *buffer, size_t bufsize) = 0; // Invalidate any cached content sourced from the specified range. // If size = -1, invalidate everything. virtual void InvalidateCache(u32 addr, int size, GPUInvalidationType type) = 0; virtual void NotifyVideoUpload(u32 addr, int size, int width, int format) = 0; // Update either RAM from VRAM, or VRAM from RAM... or even VRAM from VRAM. virtual bool PerformMemoryCopy(u32 dest, u32 src, int size) = 0; virtual bool PerformMemorySet(u32 dest, u8 v, int size) = 0; virtual bool PerformMemoryDownload(u32 dest, int size) = 0; virtual bool PerformMemoryUpload(u32 dest, int size) = 0; virtual bool PerformStencilUpload(u32 dest, int size) = 0; // Will cause the texture cache to be cleared at the start of the next frame. virtual void ClearCacheNextFrame() = 0; // Internal hack to avoid interrupts from "PPGe" drawing (utility UI, etc) virtual void EnableInterrupts(bool enable) = 0; virtual void DeviceLost() = 0; virtual void DeviceRestore() = 0; virtual void ReapplyGfxState() = 0; virtual void SyncThread(bool force = false) = 0; virtual void SyncBeginFrame() = 0; virtual u64 GetTickEstimate() = 0; virtual void DoState(PointerWrap &p) = 0; // Called by the window system if the window size changed. This will be reflected in PSPCoreParam.pixel*. virtual void Resized() = 0; virtual void ClearShaderCache() = 0; virtual void CleanupBeforeUI() = 0; virtual bool FramebufferDirty() = 0; virtual bool FramebufferReallyDirty() = 0; virtual bool BusyDrawing() = 0; virtual void SetThreadEnabled(bool threadEnabled) = 0; // If any jit is being used inside the GPU. virtual bool DescribeCodePtr(const u8 *ptr, std::string &name) = 0; // Debugging virtual void DumpNextFrame() = 0; virtual void GetReportingInfo(std::string &primaryInfo, std::string &fullInfo) = 0; virtual const std::list& GetDisplayLists() = 0; virtual bool DecodeTexture(u8* dest, const GPUgstate &state) = 0; virtual std::vector GetFramebufferList() = 0; // For debugging. The IDs returned are opaque, do not poke in them or display them in any way. virtual std::vector DebugGetShaderIDs(DebugShaderType type) = 0; virtual std::string DebugGetShaderString(std::string id, DebugShaderType type, DebugShaderStringType stringType) = 0; };