From d95dbca9bef2b7b919bd5cfa68499b5906ab5dd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 25 Dec 2012 15:28:34 +0100 Subject: [PATCH] Cleanup GPU init/shutdown a bit --- CMakeLists.txt | 2 - Core/HLE/sceDisplay.cpp | 122 +-- Core/HLE/sceDisplay.h | 1 + Core/HLE/sceKernel.cpp | 1 + Core/HLE/sceUtility.cpp | 14 +- Core/System.cpp | 5 - GPU/GLES/DisplayListInterpreter.cpp | 23 +- GPU/GLES/DisplayListInterpreter.h | 1 + GPU/GLES/TransformPipeline.cpp | 4 +- GPU/GLES/TransformPipeline.h | 5 +- GPU/GPUInterface.h | 1 + GPU/GPUState.cpp | 4 +- GPU/Null/NullDisplayListInterpreter.cpp | 997 ------------------------ GPU/Null/NullDisplayListInterpreter.h | 31 - GPU/Null/NullGpu.h | 2 + android/jni/EmuScreen.cpp | 8 +- 16 files changed, 80 insertions(+), 1141 deletions(-) delete mode 100644 GPU/Null/NullDisplayListInterpreter.cpp delete mode 100644 GPU/Null/NullDisplayListInterpreter.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 51caab7186..d5ce06a75f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -806,8 +806,6 @@ add_library(GPU OBJECT GPU/GPUState.h GPU/Math3D.cpp GPU/Math3D.h -# GPU/Null/NullDisplayListInterpreter.cpp -# GPU/Null/NullDisplayListInterpreter.h GPU/Null/NullGpu.cpp GPU/Null/NullGpu.h GPU/ge_constants.h) diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index cf28865a48..d8d323cc58 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -46,10 +46,7 @@ // Internal drawing library #include "../Util/PPGeDraw.h" -extern ShaderManager shaderManager; - -struct FrameBufferState -{ +struct FrameBufferState { u32 topaddr; PspDisplayPixelFormat pspFramebufFormat; int pspFramebufLinesize; @@ -95,8 +92,7 @@ std::vector vblankWaitingThreads; void hleEnterVblank(u64 userdata, int cyclesLate); void hleLeaveVblank(u64 userdata, int cyclesLate); -void __DisplayInit() -{ +void __DisplayInit() { gpuStats.reset(); hasSetMode = false; framebufIsLatched = false; @@ -118,29 +114,24 @@ void __DisplayInit() InitGfxState(); } -void __DisplayShutdown() -{ +void __DisplayShutdown() { vblankListeners.clear(); vblankWaitingThreads.clear(); ShutdownGfxState(); } -void __DisplayListenVblank(VblankCallback callback) -{ +void __DisplayListenVblank(VblankCallback callback) { vblankListeners.push_back(callback); } -void __DisplayFireVblank() -{ - for (std::vector::iterator iter = vblankListeners.begin(), end = vblankListeners.end(); iter != end; ++iter) - { +void __DisplayFireVblank() { + for (std::vector::iterator iter = vblankListeners.begin(), end = vblankListeners.end(); iter != end; ++iter) { VblankCallback cb = *iter; cb(); } } -void hleEnterVblank(u64 userdata, int cyclesLate) -{ +void hleEnterVblank(u64 userdata, int cyclesLate) { int vbCount = userdata; DEBUG_LOG(HLE, "Enter VBlank %i", vbCount); @@ -162,8 +153,7 @@ void hleEnterVblank(u64 userdata, int cyclesLate) CoreTiming::ScheduleEvent(msToCycles(vblankMs) - cyclesLate, leaveVblankEvent, vbCount+1); // TODO: Should this be done here or in hleLeaveVblank? - if (framebufIsLatched) - { + if (framebufIsLatched) { DEBUG_LOG(HLE, "Setting latched framebuffer %08x (prev: %08x)", latchedFramebuf.topaddr, framebuf.topaddr); framebuf = latchedFramebuf; framebufIsLatched = false; @@ -181,8 +171,7 @@ void hleEnterVblank(u64 userdata, int cyclesLate) // Now we can subvert the Ge engine in order to draw custom overlays like stat counters etc. // Here we will be drawing to the non buffered front surface. - if (g_Config.bShowDebugStats) - { + if (g_Config.bShowDebugStats) { gpu->UpdateStats(); char stats[512]; sprintf(stats, @@ -205,12 +194,12 @@ void hleEnterVblank(u64 userdata, int cyclesLate) gpuStats.numFragmentShaders, gpuStats.numShaders ); - + float zoom = 0.7f; /// g_Config.iWindowZoom; PPGeBegin(); PPGeDrawText(stats, 0, 0, 0, zoom, 0xFFc0c0c0); PPGeEnd(); - + gpuStats.resetFrame(); } @@ -240,9 +229,6 @@ void hleEnterVblank(u64 userdata, int cyclesLate) host->BeginFrame(); gpu->BeginFrame(); - shaderManager.DirtyShader(); - shaderManager.DirtyUniform(DIRTY_ALL); - // Tell the emu core that it's time to stop emulating // Win32 doesn't need this. #ifndef _WIN32 @@ -250,9 +236,7 @@ void hleEnterVblank(u64 userdata, int cyclesLate) #endif } - -void hleLeaveVblank(u64 userdata, int cyclesLate) -{ +void hleLeaveVblank(u64 userdata, int cyclesLate) { isVblank = 0; DEBUG_LOG(HLE,"Leave VBlank %i", (int)userdata - 1); vCount++; @@ -260,19 +244,16 @@ void hleLeaveVblank(u64 userdata, int cyclesLate) CoreTiming::ScheduleEvent(msToCycles(frameMs - vblankMs) - cyclesLate, enterVblankEvent, userdata); } -void sceDisplayIsVblank() -{ +void sceDisplayIsVblank() { DEBUG_LOG(HLE,"%i=sceDisplayIsVblank()",isVblank); RETURN(isVblank); } -u32 sceDisplaySetMode(u32 unknown, u32 xres, u32 yres) -{ +u32 sceDisplaySetMode(u32 unknown, u32 xres, u32 yres) { DEBUG_LOG(HLE,"sceDisplaySetMode(%d,%d,%d)",unknown,xres,yres); host->BeginFrame(); - if (!hasSetMode) - { + if (!hasSetMode) { gpu->InitClear(); hasSetMode = true; } @@ -280,9 +261,7 @@ u32 sceDisplaySetMode(u32 unknown, u32 xres, u32 yres) return 0; } -u32 sceDisplaySetFramebuf() -{ - //host->EndFrame(); +u32 sceDisplaySetFramebuf() { u32 topaddr = PARAM(0); int linesize = PARAM(1); int pixelformat = PARAM(2); @@ -290,19 +269,15 @@ u32 sceDisplaySetFramebuf() FrameBufferState fbstate; DEBUG_LOG(HLE,"sceDisplaySetFramebuf(topaddr=%08x,linesize=%d,pixelsize=%d,sync=%d)",topaddr,linesize,pixelformat,sync); - if (topaddr == 0) - { + if (topaddr == 0) { DEBUG_LOG(HLE,"- screen off"); - } - else - { + } else { fbstate.topaddr = topaddr; fbstate.pspFramebufFormat = (PspDisplayPixelFormat)pixelformat; fbstate.pspFramebufLinesize = linesize; } - if (sync == PSP_DISPLAY_SETBUF_IMMEDIATE) - { + if (sync == PSP_DISPLAY_SETBUF_IMMEDIATE) { // Write immediately to the current framebuffer parameters if (topaddr != 0) { @@ -311,9 +286,7 @@ u32 sceDisplaySetFramebuf() } else WARN_LOG(HLE, "%s: PSP_DISPLAY_SETBUF_IMMEDIATE without topaddr?", __FUNCTION__); - } - else if (topaddr != 0) - { + } else if (topaddr != 0) { // Delay the write until vblank latchedFramebuf = fbstate; framebufIsLatched = true; @@ -321,12 +294,11 @@ u32 sceDisplaySetFramebuf() return 0; } -u32 sceDisplayGetFramebuf(u32 topaddrPtr, u32 linesizePtr, u32 pixelFormatPtr, int mode) -{ +u32 sceDisplayGetFramebuf(u32 topaddrPtr, u32 linesizePtr, u32 pixelFormatPtr, int mode) { const FrameBufferState &fbState = mode == 1 ? latchedFramebuf : framebuf; DEBUG_LOG(HLE,"sceDisplayGetFramebuf(*%08x = %08x, *%08x = %08x, *%08x = %08x, %i)", topaddrPtr, fbState.topaddr, linesizePtr, fbState.pspFramebufLinesize, pixelFormatPtr, fbState.pspFramebufFormat, mode); - + if (Memory::IsValidAddress(topaddrPtr)) Memory::Write_U32(fbState.topaddr, topaddrPtr); if (Memory::IsValidAddress(linesizePtr)) @@ -337,52 +309,45 @@ u32 sceDisplayGetFramebuf(u32 topaddrPtr, u32 linesizePtr, u32 pixelFormatPtr, i return 0; } -void sceDisplayWaitVblankStart() -{ +void sceDisplayWaitVblankStart() { DEBUG_LOG(HLE,"sceDisplayWaitVblankStart()"); vblankWaitingThreads.push_back(WaitVBlankInfo(__KernelGetCurThread())); __KernelWaitCurThread(WAITTYPE_VBLANK, 0, 0, 0, false); } -void sceDisplayWaitVblank() -{ +void sceDisplayWaitVblank() { DEBUG_LOG(HLE,"sceDisplayWaitVblank()"); vblankWaitingThreads.push_back(WaitVBlankInfo(__KernelGetCurThread())); __KernelWaitCurThread(WAITTYPE_VBLANK, 0, 0, 0, false); } -void sceDisplayWaitVblankStartMulti() -{ +void sceDisplayWaitVblankStartMulti() { DEBUG_LOG(HLE,"sceDisplayWaitVblankStartMulti()"); vblankWaitingThreads.push_back(WaitVBlankInfo(__KernelGetCurThread())); __KernelWaitCurThread(WAITTYPE_VBLANK, 0, 0, 0, false); } -void sceDisplayWaitVblankCB() -{ - DEBUG_LOG(HLE,"sceDisplayWaitVblankCB()"); +void sceDisplayWaitVblankCB() { + DEBUG_LOG(HLE,"sceDisplayWaitVblankCB()"); vblankWaitingThreads.push_back(WaitVBlankInfo(__KernelGetCurThread())); __KernelWaitCurThread(WAITTYPE_VBLANK, 0, 0, 0, true); } -void sceDisplayWaitVblankStartCB() -{ - DEBUG_LOG(HLE,"sceDisplayWaitVblankStartCB()"); +void sceDisplayWaitVblankStartCB() { + DEBUG_LOG(HLE,"sceDisplayWaitVblankStartCB()"); vblankWaitingThreads.push_back(WaitVBlankInfo(__KernelGetCurThread())); __KernelWaitCurThread(WAITTYPE_VBLANK, 0, 0, 0, true); } -void sceDisplayWaitVblankStartMultiCB() -{ - DEBUG_LOG(HLE,"sceDisplayWaitVblankStartMultiCB()"); +void sceDisplayWaitVblankStartMultiCB() { + DEBUG_LOG(HLE,"sceDisplayWaitVblankStartMultiCB()"); vblankWaitingThreads.push_back(WaitVBlankInfo(__KernelGetCurThread())); __KernelWaitCurThread(WAITTYPE_VBLANK, 0, 0, 0, true); } -u32 sceDisplayGetVcount() -{ +u32 sceDisplayGetVcount() { // Too spammy - // DEBUG_LOG(HLE,"%i=sceDisplayGetVcount()", vCount); + // DEBUG_LOG(HLE,"%i=sceDisplayGetVcount()", vCount); // Puyo Puyo Fever polls this as a substitute for waiting for vblank. // As a result, the game never gets to reschedule so it doesn't mix audio and things break. @@ -393,29 +358,24 @@ u32 sceDisplayGetVcount() return vCount; } -void sceDisplayGetCurrentHcount() -{ +void sceDisplayGetCurrentHcount() { RETURN(hCount++); } - -void sceDisplayGetAccumulatedHcount() -{ +void sceDisplayGetAccumulatedHcount() { // Just do an estimate u32 accumHCount = CoreTiming::GetTicks() / (222000000 / 60 / 272); - DEBUG_LOG(HLE,"%i=sceDisplayGetAccumulatedHcount()", accumHCount); + DEBUG_LOG(HLE,"%i=sceDisplayGetAccumulatedHcount()", accumHCount); RETURN(accumHCount); } -float sceDisplayGetFramePerSec() -{ +float sceDisplayGetFramePerSec() { float fps = 59.9400599f; DEBUG_LOG(HLE,"%f=sceDisplayGetFramePerSec()", fps); - return fps; // (9MHz * 1)/(525 * 286) + return fps; // (9MHz * 1)/(525 * 286) } -const HLEFunction sceDisplay[] = -{ +const HLEFunction sceDisplay[] = { {0x0E20F177,WrapU_UUU, "sceDisplaySetMode"}, {0x289D82FE,WrapU_V, "sceDisplaySetFramebuf"}, {0xEEDA2E54,WrapU_UUUI,"sceDisplayGetFrameBuf"}, @@ -435,10 +395,8 @@ const HLEFunction sceDisplay[] = {0xB4F378FA,0,"sceDisplayIsForeground"}, {0x31C4BAA8,0,"sceDisplayGetBrightness"}, {0x4D4E10EC,sceDisplayIsVblank,"sceDisplayIsVblank"}, - }; -void Register_sceDisplay() -{ +void Register_sceDisplay() { RegisterModule("sceDisplay", ARRAY_SIZE(sceDisplay), sceDisplay); } diff --git a/Core/HLE/sceDisplay.h b/Core/HLE/sceDisplay.h index 003b3164b9..c7b1afc8ff 100644 --- a/Core/HLE/sceDisplay.h +++ b/Core/HLE/sceDisplay.h @@ -18,6 +18,7 @@ #pragma once void __DisplayInit(); +void __DisplayShutdown(); void Register_sceDisplay(); diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 3197c11107..27d8464fb4 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -122,6 +122,7 @@ void __KernelShutdown() __UtilityShutdown(); __GeShutdown(); __SasShutdown(); + __DisplayShutdown(); __AudioShutdown(); __IoShutdown(); __InterruptsShutdown(); diff --git a/Core/HLE/sceUtility.cpp b/Core/HLE/sceUtility.cpp index 0d2340e0da..bebd56436d 100644 --- a/Core/HLE/sceUtility.cpp +++ b/Core/HLE/sceUtility.cpp @@ -103,7 +103,7 @@ int sceUtilityMsgDialogInitStart(u32 structAddr) int sceUtilityMsgDialogShutdownStart(u32 unknown) { - DEBUG_LOG(HLE,"FAKE sceUtilityMsgDialogShutdownStart(%i)", unknown); + DEBUG_LOG(HLE,"sceUtilityMsgDialogShutdownStart(%i)", unknown); return msgDialog.Shutdown(); } @@ -124,25 +124,25 @@ int sceUtilityMsgDialogGetStatus() int sceUtilityOskInitStart(u32 oskPtr) { - ERROR_LOG(HLE,"FAKE sceUtilityOskInitStart(%i)", PARAM(0)); + DEBUG_LOG(HLE,"sceUtilityOskInitStart(%i)", PARAM(0)); return oskDialog.Init(oskPtr); } int sceUtilityOskShutdownStart() { - ERROR_LOG(HLE,"FAKE sceUtilityOskShutdownStart(%i)", PARAM(0)); + DEBUG_LOG(HLE,"sceUtilityOskShutdownStart(%i)", PARAM(0)); return oskDialog.Shutdown(); } int sceUtilityOskUpdate(unsigned int unknown) { - ERROR_LOG(HLE,"FAKE sceUtilityOskUpdate(%i)", unknown); + DEBUG_LOG(HLE,"FAKE sceUtilityOskUpdate(%i)", unknown); return oskDialog.Update(); } int sceUtilityOskGetStatus() { - int status = oskDialog.GetStatus(); + int status = oskDialog.GetStatus(); // Seems that 4 is the cancelled status for OSK? if (status == 4) { @@ -185,13 +185,13 @@ int sceUtilityScreenshotGetStatus() void sceUtilityGamedataInstallInitStart(u32 unkown) { - DEBUG_LOG(HLE,"FAKE sceUtilityGamedataInstallInitStart(%i)", unkown); + DEBUG_LOG(HLE,"UNIMPL sceUtilityGamedataInstallInitStart(%i)", unkown); } int sceUtilityGamedataInstallGetStatus() { u32 retval = 0;//__UtilityGetStatus(); - DEBUG_LOG(HLE,"%i=sceUtilityGamedataInstallGetStatus()", retval); + DEBUG_LOG(HLE,"UNIMPL %i=sceUtilityGamedataInstallGetStatus()", retval); return retval; } diff --git a/Core/System.cpp b/Core/System.cpp index 18c2b94687..9110dcc245 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -42,7 +42,6 @@ MetaFileSystem pspFileSystem; static CoreParameter coreParameter; -extern ShaderManager shaderManager; bool PSP_Init(const CoreParameter &coreParam, std::string *error_string) { @@ -76,9 +75,6 @@ bool PSP_Init(const CoreParameter &coreParam, std::string *error_string) return false; } - shaderManager.DirtyShader(); - shaderManager.DirtyUniform(DIRTY_ALL); - // Setup JIT here. if (coreParameter.startPaused) coreState = CORE_STEPPING; @@ -97,7 +93,6 @@ void PSP_Shutdown() pspFileSystem.UnmountAll(); TextureCache_Clear(true); - shaderManager.ClearCache(true); CoreTiming::ClearPendingEvents(); CoreTiming::UnregisterAllEvents(); diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index 226e091540..bf70ae40e2 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -33,8 +33,6 @@ #include "../../Core/HLE/sceKernelThread.h" #include "../../Core/HLE/sceKernelInterrupt.h" -ShaderManager shaderManager; - extern u32 curTextureWidth; extern u32 curTextureHeight; @@ -157,11 +155,11 @@ GLES_GPU::GLES_GPU(int renderWidth, int renderHeight) displayFramebufPtr_(0), renderWidth_(renderWidth), renderHeight_(renderHeight), - dlIdGenerator(1), - transformDraw_(&shaderManager) { + dlIdGenerator(1) { renderWidthFactor_ = (float)renderWidth / 480.0f; renderHeightFactor_ = (float)renderHeight / 272.0f; - shaderManager_ = &shaderManager; + shaderManager_ = new ShaderManager(); + transformDraw_.SetShaderManager(shaderManager_); TextureCache_Init(); // Sanity check gstate if ((int *)&gstate.transferstart - (int *)&gstate != 0xEA) { @@ -183,10 +181,18 @@ GLES_GPU::~GLES_GPU() { delete (*iter); } vfbs_.clear(); - + shaderManager_->ClearCache(true); + delete shaderManager_; delete [] flushBeforeCommand_; } +void GLES_GPU::DeviceLost() { + // Simply drop all caches and textures. + // FBO:s appear to survive? Or no? + shaderManager_->ClearCache(false); + TextureCache_Clear(false); +} + void GLES_GPU::InitClear() { if (!g_Config.bBufferedRendering) { glClearColor(0,0,0,1); @@ -199,6 +205,11 @@ void GLES_GPU::InitClear() { void GLES_GPU::BeginFrame() { TextureCache_Decimate(); + shaderManager_->DirtyShader(); + + // Not sure if this is really needed. + shaderManager_->DirtyUniform(DIRTY_ALL); + // NOTE - this is all wrong. At the beginning of the frame is a TERRIBLE time to draw the fb. if (g_Config.bDisplayFramebuffer && displayFramebufPtr_) { INFO_LOG(HLE, "Drawing the framebuffer"); diff --git a/GPU/GLES/DisplayListInterpreter.h b/GPU/GLES/DisplayListInterpreter.h index 18b75f8d1d..9d9a7f8733 100644 --- a/GPU/GLES/DisplayListInterpreter.h +++ b/GPU/GLES/DisplayListInterpreter.h @@ -51,6 +51,7 @@ public: virtual void BeginFrame(); virtual void UpdateStats(); virtual void InvalidateCache(u32 addr, int size); + virtual void DeviceLost(); // Only happens on Android. Drop all textures and shaders. virtual void Flush(); private: diff --git a/GPU/GLES/TransformPipeline.cpp b/GPU/GLES/TransformPipeline.cpp index 5c0178dfa7..63df7e64b6 100644 --- a/GPU/GLES/TransformPipeline.cpp +++ b/GPU/GLES/TransformPipeline.cpp @@ -41,10 +41,10 @@ const GLuint glprim[8] = { GL_TRIANGLES, // With OpenGL ES we have to expand sprites into triangles, tripling the data instead of doubling. sigh. OpenGL ES, Y U NO SUPPORT GL_QUADS? }; -TransformDrawEngine::TransformDrawEngine(ShaderManager *shaderManager) +TransformDrawEngine::TransformDrawEngine() : numVerts(0), lastVType(-1), - shaderManager_(shaderManager) { + shaderManager_(0) { decoded = new u8[65536 * 48]; decIndex = new u16[65536]; transformed = new TransformedVertex[65536]; diff --git a/GPU/GLES/TransformPipeline.h b/GPU/GLES/TransformPipeline.h index 9e95457c7e..393f0dce12 100644 --- a/GPU/GLES/TransformPipeline.h +++ b/GPU/GLES/TransformPipeline.h @@ -27,11 +27,14 @@ struct DecVtxFormat; // Handles transform, lighting and drawing. class TransformDrawEngine { public: - TransformDrawEngine(ShaderManager *shaderManager); + TransformDrawEngine(); ~TransformDrawEngine(); void SubmitPrim(void *verts, void *inds, int prim, int vertexCount, float *customUV, int forceIndexType, int *bytesRead); void DrawBezier(int ucount, int vcount); void Flush(); + void SetShaderManager(ShaderManager *shaderManager) { + shaderManager_ = shaderManager; + } private: void SoftwareTransformAndDraw(int prim, u8 *decoded, LinkedShader *program, int vertexCount, void *inds, int indexType, const DecVtxFormat &decVtxFormat, int maxIndex); diff --git a/GPU/GPUInterface.h b/GPU/GPUInterface.h index 2198b782ab..cad06fe3bf 100644 --- a/GPU/GPUInterface.h +++ b/GPU/GPUInterface.h @@ -52,5 +52,6 @@ public: // Internal hack to avoid interrupts from "PPGe" drawing (utility UI, etc) virtual void EnableInterrupts(bool enable) = 0; + virtual void DeviceLost() = 0; virtual void Flush() = 0; }; diff --git a/GPU/GPUState.cpp b/GPU/GPUState.cpp index 6540620a36..c45d65ae88 100644 --- a/GPU/GPUState.cpp +++ b/GPU/GPUState.cpp @@ -102,14 +102,14 @@ void ReapplyGfxState() for (int i = GE_CMD_MORPHWEIGHT0; i < GE_CMD_PATCHFACING; i++) { - gpu->ExecuteOp(gstate.cmdmem[i], 0xFFFFFFFF); + gpu->ExecuteOp(gstate.cmdmem[i], 0xFFFFFFFF); } // There are a few here in the middle that we shouldn't execute... for (int i = GE_CMD_VIEWPORTX1; i < GE_CMD_TRANSFERSTART; i++) { - gpu->ExecuteOp(gstate.cmdmem[i], 0xFFFFFFFF); + gpu->ExecuteOp(gstate.cmdmem[i], 0xFFFFFFFF); } // TODO: there's more... diff --git a/GPU/Null/NullDisplayListInterpreter.cpp b/GPU/Null/NullDisplayListInterpreter.cpp deleted file mode 100644 index ef00c7a373..0000000000 --- a/GPU/Null/NullDisplayListInterpreter.cpp +++ /dev/null @@ -1,997 +0,0 @@ -// 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/. - -#include "../../Core/MemMap.h" -#include "../../Core/Host.h" - -#include "../GPUState.h" -#include "../ge_constants.h" - -#include "ShaderManager.h" -#include "DisplayListInterpreter.h" -#include "TransformPipeline.h" - -#include "../../Core/HLE/sceKernelThread.h" -#include "../../Core/HLE/sceKernelInterrupt.h" - -inline void glEnDis(GLuint cmd, int value) -{ - (value ? glEnable : glDisable)(cmd); -} - -struct DisplayState -{ - u32 pc; - u32 stallAddr; -}; - -static DisplayState dcontext; -ShaderManager shaderManager; - -extern u32 curTextureWidth; -extern u32 curTextureHeight; - -int dlIdGenerator = 1; - -struct DisplayList -{ - int id; - u32 listpc; - u32 stall; -}; - -std::vector dlQueue; - -static u32 prev; -u32 stack[2]; -u32 stackptr = 0; -bool finished; - -u8 bezierBuf[16000]; - -bool ProcessDLQueue() -{ - std::vector::iterator iter = dlQueue.begin(); - while (!(iter == dlQueue.end())) - { - DisplayList &l = *iter; - dcontext.pc = l.listpc; - dcontext.stallAddr = l.stall; -// DEBUG_LOG(G3D,"Okay, starting DL execution at %08 - stall = %08x", context.pc, stallAddr); - if (!GPU::InterpretList()) - { - l.listpc = dcontext.pc; - l.stall = dcontext.stallAddr; - return false; - } - else - { - //At the end, we can remove it from the queue and continue - dlQueue.erase(iter); - //this invalidated the iterator, let's fix it - iter = dlQueue.begin(); - } - } - return true; //no more lists! -} - -u32 GPU::EnqueueList(u32 listpc, u32 stall) -{ - DisplayList dl; - dl.id = dlIdGenerator++; - dl.listpc = listpc&0xFFFFFFF; - dl.stall = stall&0xFFFFFFF; - dlQueue.push_back(dl); - if (!ProcessDLQueue()) - return dl.id; - else - return 0; -} - -void GPU::UpdateStall(int listid, u32 newstall) -{ - // this needs improvement.... - for (std::vector::iterator iter = dlQueue.begin(); iter != dlQueue.end(); iter++) - { - DisplayList &l = *iter; - if (l.id == listid) - { - l.stall = newstall & 0xFFFFFFF; - } - } - - ProcessDLQueue(); -} - -// Just to get something on the screen, we'll just not subdivide correctly. -void drawBezier(int ucount, int vcount) -{ - u16 indices[3 * 3 * 6]; - float customUV[32]; - int c = 0; - for (int y = 0; y < 3; y++) { - for (int x = 0; x < 3; x++) { - indices[c++] = y * 4 + x; - indices[c++] = y * 4 + x + 1; - indices[c++] = (y + 1) * 4 + x + 1; - indices[c++] = (y + 1) * 4 + x + 1; - indices[c++] = (y + 1) * 4 + x; - indices[c++] = y * 4 + x; - } - } - - for (int y = 0; y < 4; y++) { - for (int x = 0; x < 4; x++) { - customUV[(y * 4 + x) * 2 + 0] = (float)x/3.0f; - customUV[(y * 4 + x) * 2 + 1] = (float)y/3.0f; - } - } - - LinkedShader *linkedShader = shaderManager.ApplyShader(); - TransformAndDrawPrim(Memory::GetPointer(gstate.vertexAddr), &indices[0], GE_PRIM_TRIANGLES, 3 * 3 * 6, linkedShader, customUV, GE_VTYPE_IDX_16BIT); -} - - -void EnterClearMode(u32 data) -{ - bool colMask = (data >> 8) & 1; - bool alphaMask = (data >> 9) & 1; - bool updateZ = (data >> 10) & 1; - glColorMask(colMask, colMask, colMask, alphaMask); - glDepthMask(updateZ); // Update Z or not - // Note that depth test must be enabled for depth writes to go through! So we use GL_ALWAYS - glEnable(GL_DEPTH_TEST); - glDepthFunc(GL_ALWAYS); - glDisable(GL_CULL_FACE); // ?? -} - -void LeaveClearMode() -{ - // We have to reset the following state as per the state of the command registers: - // Back face culling - // Texture map enable (meh) - // Fogging - // Antialiasing - // Alpha test - glDepthMask(1); - glColorMask(1,1,1,1); - glEnDis(GL_DEPTH_TEST, gstate.zTestEnable & 1); - glDepthFunc(GL_LEQUAL); // TODO - - // dirtyshader? -} - -void SetBlendModePSP(u32 data) -{ - // This can't be done exactly as there are several PSP blend modes that are impossible to do on OpenGL ES 2.0, and some even on regular OpenGL for desktop. - - // HOWEVER - we should be able to approximate the 2x modes in the shader, although they will clip wrongly. - - const GLint aLookup[] = { - GL_DST_COLOR, - GL_ONE_MINUS_DST_COLOR, - GL_SRC_ALPHA, - GL_ONE_MINUS_SRC_ALPHA, - GL_DST_ALPHA, - GL_ONE_MINUS_DST_ALPHA, - GL_SRC_ALPHA, // should be 2x - GL_ONE_MINUS_SRC_ALPHA, // should be 2x - GL_DST_ALPHA, // should be 2x - GL_ONE_MINUS_DST_ALPHA, // should be 2x - and COLOR? - GL_SRC_ALPHA, // should be FIXA - }; - const GLint bLookup[] = { - GL_SRC_COLOR, - GL_ONE_MINUS_SRC_COLOR, - GL_SRC_ALPHA, - GL_ONE_MINUS_SRC_ALPHA, - GL_DST_ALPHA, - GL_ONE_MINUS_DST_ALPHA, - GL_SRC_ALPHA, // should be 2x - GL_ONE_MINUS_SRC_ALPHA, // should be 2x - GL_DST_ALPHA, // should be 2x - GL_ONE_MINUS_DST_ALPHA, // should be 2x - GL_SRC_ALPHA, // should be FIXB - }; - const GLint eqLookup[] = { - GL_FUNC_ADD, - GL_FUNC_SUBTRACT, - GL_FUNC_REVERSE_SUBTRACT, -#if defined(USING_GLES2) - GL_FUNC_ADD, - GL_FUNC_ADD, -#else - GL_MIN, - GL_MAX, -#endif - GL_FUNC_ADD, // should be abs(diff) - }; - int a = data & 0xF; - int b = (data >> 4) & 0xF; - int eq = (data >> 8) & 0x7; - glBlendFunc(aLookup[a], bLookup[b]); - glBlendEquation(eqLookup[eq]); -} - - -void GPU::ExecuteOp(u32 op, u32 diff) -{ - u32 cmd = op >> 24; - u32 data = op & 0xFFFFFF; - - // Handle control and drawing commands here directly. The others we delegate. - switch (cmd) - { - case GE_CMD_BASE: - DEBUG_LOG(G3D,"DL BASE: %06x", data); - break; - - case GE_CMD_VADDR: /// <<8???? - gstate.vertexAddr = (gstate.base<<8)|data; - DEBUG_LOG(G3D,"DL VADDR: %06x", gstate.vertexAddr); - break; - - case GE_CMD_IADDR: - gstate.indexAddr = (gstate.base<<8)|data; - DEBUG_LOG(G3D,"DL IADDR: %06x", gstate.indexAddr); - break; - - case GE_CMD_PRIM: - { - u32 count = data & 0xFFFF; - u32 type = data >> 16; - static const char* types[7] = { - "POINTS=0,", - "LINES=1,", - "LINE_STRIP=2,", - "TRIANGLES=3,", - "TRIANGLE_STRIP=4,", - "TRIANGLE_FAN=5,", - "RECTANGLES=6,", - }; - DEBUG_LOG(G3D, "DL DrawPrim type: %s count: %i vaddr= %08x, iaddr= %08x", type<7 ? types[type] : "INVALID", count, gstate.vertexAddr, gstate.indexAddr); - - LinkedShader *linkedShader = shaderManager.ApplyShader(); - // TODO: Split this so that we can collect sequences of primitives, can greatly speed things up - // on platforms where draw calls are expensive like mobile and D3D - void *verts = Memory::GetPointer(gstate.vertexAddr); - void *inds = 0; - if ((gstate.vertType & GE_VTYPE_IDX_MASK) != GE_VTYPE_IDX_NONE) - inds = Memory::GetPointer(gstate.indexAddr); - TransformAndDrawPrim(verts, inds, type, count, linkedShader); - } - break; - - // The arrow and other rotary items in Puzbob are bezier patches, strangely enough. - case GE_CMD_BEZIER: - { - int bz_ucount = data & 0xFF; - int bz_vcount = (data >> 8) & 0xFF; - drawBezier(bz_ucount, bz_vcount); - DEBUG_LOG(G3D,"DL DRAW BEZIER: %i x %i", bz_ucount, bz_vcount); - } - break; - - case GE_CMD_SPLINE: - { - int sp_ucount = data & 0xFF; - int sp_vcount = (data >> 8) & 0xFF; - int sp_utype = (data >> 16) & 0x3; - int sp_vtype = (data >> 18) & 0x3; - //drawSpline(sp_ucount, sp_vcount, sp_utype, sp_vtype); - DEBUG_LOG(G3D,"DL DRAW SPLINE: %i x %i, %i x %i", sp_ucount, sp_vcount, sp_utype, sp_vtype); - } - break; - - case GE_CMD_JUMP: - { - u32 target = ((gstate.base << 8) | (op & 0xFFFFFC)) & 0x0FFFFFFF; - DEBUG_LOG(G3D,"DL CMD JUMP - %08x to %08x", dcontext.pc, target); - dcontext.pc = target - 4; // pc will be increased after we return, counteract that - } - break; - - case GE_CMD_CALL: - { - u32 retval = dcontext.pc + 4; - stack[stackptr++] = retval; - u32 target = ((gstate.base << 8) | (op & 0xFFFFFC)) & 0xFFFFFFF; - DEBUG_LOG(G3D,"DL CMD CALL - %08x to %08x, ret=%08x", dcontext.pc, target, retval); - dcontext.pc = target - 4; // pc will be increased after we return, counteract that - } - break; - - case GE_CMD_RET: - //TODO : debug! - { - u32 target = stack[--stackptr] & 0xFFFFFFF; - DEBUG_LOG(G3D,"DL CMD RET - from %08x to %08x", dcontext.pc, target); - dcontext.pc = target - 4; - } - break; - - case GE_CMD_SIGNAL: - ERROR_LOG(G3D, "DL GE_CMD_SIGNAL %08x", data & 0xFFFFFF); - { - // int behaviour = (data >> 16) & 0xFF; - // int signal = data & 0xFFFF; - } - - // This should generate a GE Interrupt - // __TriggerInterrupt(PSP_GE_INTR); - - // Apparently, these callbacks should be done in a special interrupt way. - //for (size_t i = 0; i < signalCallbacks.size(); i++) - //{ - // __KernelNotifyCallback(-1, signalCallbacks[i].first, signal); - //} - - break; - - case GE_CMD_BJUMP: - // bounding box jump. Let's just not jump, for now. - DEBUG_LOG(G3D,"DL BBOX JUMP - unimplemented"); - break; - - case GE_CMD_BOUNDINGBOX: - // bounding box test. Let's do nothing. - DEBUG_LOG(G3D,"DL BBOX TEST - unimplemented"); - break; - - case GE_CMD_ORIGIN: - gstate.offsetAddr = dcontext.pc & 0xFFFFFF; - break; - - case GE_CMD_VERTEXTYPE: - DEBUG_LOG(G3D,"DL SetVertexType: %06x", data); - if (diff & GE_VTYPE_THROUGH) { - // Throughmode changed, let's make the proj matrix dirty. - shaderManager.DirtyUniform(DIRTY_PROJMATRIX); - } - if (data & GE_VTYPE_THROUGH) { - glDisable(GL_CULL_FACE); - } - // This sets through-mode or not, as well. - break; - - case GE_CMD_OFFSETADDR: - // offsetAddr = data<<8; - break; - - - case GE_CMD_FINISH: - DEBUG_LOG(G3D,"DL CMD FINISH"); - // Trigger the finish callbacks - { - // Apparently, these callbacks should be done in a special interrupt way. - - //for (size_t i = 0; i < finishCallbacks.size(); i++) - //{ - // __KernelNotifyCallback(-1, finishCallbacks[i].first, 0); - //} - } - break; - - case GE_CMD_END: - DEBUG_LOG(G3D,"DL CMD END"); - { - switch (prev >> 24) - { - case GE_CMD_FINISH: - finished = true; - break; - default: - DEBUG_LOG(G3D,"Ah, not finished: %06x", prev & 0xFFFFFF); - break; - } - } - - // This should generate a Reading Ended interrupt - // __TriggerInterrupt(PSP_GE_INTR); - - break; - - case GE_CMD_REGION1: - { - int x1 = data & 0x3ff; - int y1 = data >> 10; - //topleft - DEBUG_LOG(G3D,"DL Region TL: %d %d", x1, y1); - } - break; - - case GE_CMD_REGION2: - { - int x2 = data & 0x3ff; - int y2 = data >> 10; - DEBUG_LOG(G3D,"DL Region BR: %d %d", x2, y2); - } - break; - - case GE_CMD_CLIPENABLE: - DEBUG_LOG(G3D, "DL Clip Enable: %i (ignoring)", data); - //we always clip, this is opengl - break; - - case GE_CMD_CULLFACEENABLE: - DEBUG_LOG(G3D, "DL CullFace Enable: %i (ignoring)", data); - glEnDis(GL_CULL_FACE, data&1); - break; - - case GE_CMD_TEXTUREMAPENABLE: - DEBUG_LOG(G3D, "DL Texture map enable: %i", data); - glEnDis(GL_TEXTURE_2D, data&1); - break; - - case GE_CMD_LIGHTINGENABLE: - DEBUG_LOG(G3D, "DL Lighting enable: %i", data); - data += 1; - //We don't use OpenGL lighting - break; - - case GE_CMD_FOGENABLE: - DEBUG_LOG(G3D, "DL Fog Enable: %i", gstate.fogEnable); - break; - - case GE_CMD_DITHERENABLE: - DEBUG_LOG(G3D, "DL Dither Enable: %i", gstate.ditherEnable); - break; - - case GE_CMD_OFFSETX: - DEBUG_LOG(G3D, "DL Offset X: %i", gstate.offsetx); - break; - - case GE_CMD_OFFSETY: - DEBUG_LOG(G3D, "DL Offset Y: %i", gstate.offsety); - break; - - case GE_CMD_TEXSCALEU: - gstate.uScale = getFloat24(data); - DEBUG_LOG(G3D, "DL Texture U Scale: %f", gstate.uScale); - break; - - case GE_CMD_TEXSCALEV: - gstate.vScale = getFloat24(data); - DEBUG_LOG(G3D, "DL Texture V Scale: %f", gstate.vScale); - break; - - case GE_CMD_TEXOFFSETU: - gstate.uOff = getFloat24(data); - DEBUG_LOG(G3D, "DL Texture U Offset: %f", gstate.uOff); - break; - - case GE_CMD_TEXOFFSETV: - gstate.vOff = getFloat24(data); - DEBUG_LOG(G3D, "DL Texture V Offset: %f", gstate.vOff); - break; - - case GE_CMD_SCISSOR1: - { - int x1 = data & 0x3ff; - int y1 = data >> 10; - DEBUG_LOG(G3D, "DL Scissor TL: %i, %i", x1,y1); - } - break; - case GE_CMD_SCISSOR2: - { - int x2 = data & 0x3ff; - int y2 = data >> 10; - DEBUG_LOG(G3D, "DL Scissor BR: %i, %i", x2, y2); - } - break; - - case GE_CMD_MINZ: - DEBUG_LOG(G3D, "DL MinZ: %i", data); - break; - - case GE_CMD_MAXZ: - DEBUG_LOG(G3D, "DL MaxZ: %i", data); - break; - - case GE_CMD_FRAMEBUFPTR: - { - u32 ptr = op & 0xFFE000; - DEBUG_LOG(G3D, "DL FramebufPtr: %08x", ptr); - } - break; - - case GE_CMD_FRAMEBUFWIDTH: - { - u32 w = data & 0xFFFFFF; - DEBUG_LOG(G3D, "DL FramebufWidth: %i", w); - } - break; - - case GE_CMD_FRAMEBUFPIXFORMAT: - break; - - case GE_CMD_TEXADDR0: - gstate.textureChanged=true; - case GE_CMD_TEXADDR1: - case GE_CMD_TEXADDR2: - case GE_CMD_TEXADDR3: - case GE_CMD_TEXADDR4: - case GE_CMD_TEXADDR5: - case GE_CMD_TEXADDR6: - case GE_CMD_TEXADDR7: - DEBUG_LOG(G3D,"DL Texture address %i: %06x", cmd-GE_CMD_TEXADDR0, data); - break; - - case GE_CMD_TEXBUFWIDTH0: - gstate.textureChanged=true; - case GE_CMD_TEXBUFWIDTH1: - case GE_CMD_TEXBUFWIDTH2: - case GE_CMD_TEXBUFWIDTH3: - case GE_CMD_TEXBUFWIDTH4: - case GE_CMD_TEXBUFWIDTH5: - case GE_CMD_TEXBUFWIDTH6: - case GE_CMD_TEXBUFWIDTH7: - DEBUG_LOG(G3D,"DL Texture BUFWIDTHess %i: %06x", cmd-GE_CMD_TEXBUFWIDTH0, data); - break; - - case GE_CMD_CLUTADDR: - //DEBUG_LOG(G3D,"CLUT base addr: %06x", data); - break; - - case GE_CMD_CLUTADDRUPPER: - DEBUG_LOG(G3D,"DL CLUT addr: %08x", ((gstate.clutaddrupper & 0xFF0000)<<8) | (gstate.clutaddr & 0xFFFFFF)); - break; - - case GE_CMD_LOADCLUT: - { - u32 clutAttr = ((gstate.clutaddrupper & 0xFF0000)<<8) | (gstate.clutaddr & 0xFFFFFF); - if (clutAttr) - { - u16 *clut = (u16*)Memory::GetPointer(clutAttr); - if (clut) { - int numColors = 16 * (data&0x3F); - memcpy(&gstate.paletteMem[0], clut, numColors * 2); - } - DEBUG_LOG(G3D,"DL Clut load: %i palettes", data); - } - else - { - DEBUG_LOG(G3D,"DL Empty Clut load"); - } - // Should hash and invalidate all paletted textures on use - } - break; - -// case GE_CMD_TRANSFERSRC: - - case GE_CMD_TRANSFERSRCW: - { - u32 xferSrc = gstate.transfersrc | ((data&0xFF0000)<<8); - u32 xferSrcW = gstate.transfersrcw & 1023; - DEBUG_LOG(G3D,"Block Transfer Src: %08x W: %i", xferSrc, xferSrcW); - break; - } -// case GE_CMD_TRANSFERDST: - - case GE_CMD_TRANSFERDSTW: - { - u32 xferDst= gstate.transferdst | ((data&0xFF0000)<<8); - u32 xferDstW = gstate.transferdstw & 1023; - DEBUG_LOG(G3D,"Block Transfer Dest: %08x W: %i", xferDst, xferDstW); - break; - } - - case GE_CMD_TRANSFERSRCPOS: - { - u32 x = (data & 1023)+1; - u32 y = ((data>>10) & 1023)+1; - DEBUG_LOG(G3D, "DL Block Transfer Src Rect TL: %i, %i", x, y); - break; - } - - case GE_CMD_TRANSFERDSTPOS: - { - u32 x = (data & 1023)+1; - u32 y = ((data>>10) & 1023)+1; - DEBUG_LOG(G3D, "DL Block Transfer Dest Rect TL: %i, %i", x, y); - break; - } - - case GE_CMD_TRANSFERSIZE: - { - u32 w = (data & 1023)+1; - u32 h = ((data>>10) & 1023)+1; - DEBUG_LOG(G3D, "DL Block Transfer Rect Size: %i x %i", w, h); - break; - } - - case GE_CMD_TRANSFERSTART: - { - DEBUG_LOG(G3D, "DL Texture Transfer Start: PixFormat %i", data); - // TODO: Here we should check if the transfer overlaps a framebuffer or any textures, - // and take appropriate action. If not, this should just be a block transfer within - // GPU memory which could be implemented by a copy loop. - break; - } - - case GE_CMD_TEXSIZE0: - gstate.textureChanged=true; - gstate.curTextureWidth = 1 << (gstate.texsize[0] & 0xf); - gstate.curTextureHeight = 1 << ((gstate.texsize[0]>>8) & 0xf); - //fall thru - ignoring the mipmap sizes for now - case GE_CMD_TEXSIZE1: - case GE_CMD_TEXSIZE2: - case GE_CMD_TEXSIZE3: - case GE_CMD_TEXSIZE4: - case GE_CMD_TEXSIZE5: - case GE_CMD_TEXSIZE6: - case GE_CMD_TEXSIZE7: - DEBUG_LOG(G3D,"DL Texture Size: %06x", data); - break; - - case GE_CMD_ZBUFPTR: - { - u32 ptr = op & 0xFFE000; - DEBUG_LOG(G3D,"Zbuf Ptr: %06x", ptr); - } - break; - - case GE_CMD_ZBUFWIDTH: - { - u32 w = data & 0xFFFFFF; - DEBUG_LOG(G3D,"Zbuf Width: %i", w); - } - break; - - case GE_CMD_AMBIENTCOLOR: - DEBUG_LOG(G3D,"DL Ambient Color: %06x", data); - break; - - case GE_CMD_AMBIENTALPHA: - DEBUG_LOG(G3D,"DL Ambient Alpha: %06x", data); - break; - - case GE_CMD_MATERIALAMBIENT: - DEBUG_LOG(G3D,"DL Material Ambient Color: %06x", data); - break; - - case GE_CMD_MATERIALDIFFUSE: - DEBUG_LOG(G3D,"DL Material Diffuse Color: %06x", data); - break; - - case GE_CMD_MATERIALEMISSIVE: - DEBUG_LOG(G3D,"DL Material Emissive Color: %06x", data); - break; - - case GE_CMD_MATERIALSPECULAR: - DEBUG_LOG(G3D,"DL Material Specular Color: %06x", data); - break; - - case GE_CMD_MATERIALALPHA: - DEBUG_LOG(G3D,"DL Material Alpha Color: %06x", data); - break; - - case GE_CMD_MATERIALSPECULARCOEF: - DEBUG_LOG(G3D,"DL Material specular coef: %f", getFloat24(data)); - break; - - case GE_CMD_LIGHTTYPE0: - case GE_CMD_LIGHTTYPE1: - case GE_CMD_LIGHTTYPE2: - case GE_CMD_LIGHTTYPE3: - DEBUG_LOG(G3D,"DL Light %i type: %06x", cmd-GE_CMD_LIGHTTYPE0, data); - break; - - case GE_CMD_LX0:case GE_CMD_LY0:case GE_CMD_LZ0: - case GE_CMD_LX1:case GE_CMD_LY1:case GE_CMD_LZ1: - case GE_CMD_LX2:case GE_CMD_LY2:case GE_CMD_LZ2: - case GE_CMD_LX3:case GE_CMD_LY3:case GE_CMD_LZ3: - { - int n = cmd - GE_CMD_LX0; - int l = n / 3; - int c = n % 3; - float val = getFloat24(data); - DEBUG_LOG(G3D,"DL Light %i %c pos: %f", l, c+'X', val); - gstate.lightpos[l][c] = val; - } - break; - - case GE_CMD_LDX0:case GE_CMD_LDY0:case GE_CMD_LDZ0: - case GE_CMD_LDX1:case GE_CMD_LDY1:case GE_CMD_LDZ1: - case GE_CMD_LDX2:case GE_CMD_LDY2:case GE_CMD_LDZ2: - case GE_CMD_LDX3:case GE_CMD_LDY3:case GE_CMD_LDZ3: - { - int n = cmd - GE_CMD_LDX0; - int l = n / 3; - int c = n % 3; - float val = getFloat24(data); - DEBUG_LOG(G3D,"DL Light %i %c dir: %f", l, c+'X', val); - gstate.lightdir[l][c] = val; - } - break; - - case GE_CMD_LKA0:case GE_CMD_LKB0:case GE_CMD_LKC0: - case GE_CMD_LKA1:case GE_CMD_LKB1:case GE_CMD_LKC1: - case GE_CMD_LKA2:case GE_CMD_LKB2:case GE_CMD_LKC2: - case GE_CMD_LKA3:case GE_CMD_LKB3:case GE_CMD_LKC3: - { - int n = cmd - GE_CMD_LKA0; - int l = n / 3; - int c = n % 3; - float val = getFloat24(data); - DEBUG_LOG(G3D,"DL Light %i %c att: %f", l, c+'X', val); - gstate.lightatt[l][c] = val; - } - break; - - - case GE_CMD_LAC0:case GE_CMD_LAC1:case GE_CMD_LAC2:case GE_CMD_LAC3: - case GE_CMD_LDC0:case GE_CMD_LDC1:case GE_CMD_LDC2:case GE_CMD_LDC3: - case GE_CMD_LSC0:case GE_CMD_LSC1:case GE_CMD_LSC2:case GE_CMD_LSC3: - { - float r = (float)(data>>16)/255.0f; - float g = (float)((data>>8) & 0xff)/255.0f; - float b = (float)(data & 0xff)/255.0f; - - int l = (cmd - GE_CMD_LAC0) / 3; - int t = (cmd - GE_CMD_LAC0) % 3; - gstate.lightColor[t][l].r = r; - gstate.lightColor[t][l].g = g; - gstate.lightColor[t][l].b = b; - } - break; - - case GE_CMD_VIEWPORTX1: - case GE_CMD_VIEWPORTY1: - case GE_CMD_VIEWPORTZ1: - case GE_CMD_VIEWPORTX2: - case GE_CMD_VIEWPORTY2: - case GE_CMD_VIEWPORTZ2: - DEBUG_LOG(G3D,"DL Viewport param %i: %f", cmd-GE_CMD_VIEWPORTX1, getFloat24(data)); - break; - case GE_CMD_LIGHTENABLE0: - case GE_CMD_LIGHTENABLE1: - case GE_CMD_LIGHTENABLE2: - case GE_CMD_LIGHTENABLE3: - DEBUG_LOG(G3D,"DL Light %i enable: %d", cmd-GE_CMD_LIGHTENABLE0, data); - break; - case GE_CMD_CULL: - DEBUG_LOG(G3D,"DL cull: %06x", data); - glCullFace(data ? GL_BACK : GL_FRONT); - break; - - case GE_CMD_LMODE: - DEBUG_LOG(G3D,"DL Shade mode: %06x", data); - break; - - case GE_CMD_PATCHDIVISION: - gstate.patch_div_s = data & 0xFF; - gstate.patch_div_t = (data >> 8) & 0xFF; - DEBUG_LOG(G3D, "DL Patch subdivision: %i x %i", gstate.patch_div_s, gstate.patch_div_t); - break; - - case GE_CMD_MATERIALUPDATE: - DEBUG_LOG(G3D,"DL Material Update: %d", data); - break; - - - ////////////////////////////////////////////////////////////////// - // CLEARING - ////////////////////////////////////////////////////////////////// - case GE_CMD_CLEARMODE: - // If it becomes a performance problem, check diff&1 - if (data & 1) - EnterClearMode(data); - else - LeaveClearMode(); - DEBUG_LOG(G3D,"DL Clear mode: %06x", data); - break; - - - ////////////////////////////////////////////////////////////////// - // ALPHA BLENDING - ////////////////////////////////////////////////////////////////// - case GE_CMD_ALPHABLENDENABLE: - DEBUG_LOG(G3D,"DL Alpha blend enable: %d", data); - glEnDis(GL_BLEND, data); - break; - - case GE_CMD_BLENDMODE: - DEBUG_LOG(G3D,"DL Blend mode: %06x", data); - SetBlendModePSP(data); - break; - - case GE_CMD_BLENDFIXEDA: - DEBUG_LOG(G3D,"DL Blend fix A: %06x", data); - break; - - case GE_CMD_BLENDFIXEDB: - DEBUG_LOG(G3D,"DL Blend fix B: %06x", data); - break; - - case GE_CMD_ALPHATESTENABLE: - DEBUG_LOG(G3D,"DL Alpha test enable: %d", data); - // This is done in the shader. - break; - - case GE_CMD_ALPHATEST: - DEBUG_LOG(G3D,"DL Alpha test settings"); - shaderManager.DirtyUniform(DIRTY_ALPHAREF); - break; - - case GE_CMD_TEXFUNC: - { - DEBUG_LOG(G3D,"DL TexFunc %i", data&7); - /* - int m=GL_MODULATE; - switch (data & 7) - { - case 0: m=GL_MODULATE; break; - case 1: m=GL_DECAL; break; - case 2: m=GL_BLEND; break; - case 3: m=GL_REPLACE; break; - case 4: m=GL_ADD; break; - }*/ - - /* - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB, GL_MODULATE); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB, GL_CONSTANT); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB, GL_SRC_COLOR); - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_RGB, GL_TEXTURE); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_RGB, GL_SRC_COLOR); - glTexEnvi(GL_TEXTURE_ENV, GL_RGB_SCALE, 1); - - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, m); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_MODULATE);*/ - break; - } - case GE_CMD_TEXFILTER: - { - int min = data & 7; - int mag = (data >> 8) & 1; - DEBUG_LOG(G3D,"DL TexFilter min: %i mag: %i", min, mag); - } - - break; - ////////////////////////////////////////////////////////////////// - // Z/STENCIL TESTING - ////////////////////////////////////////////////////////////////// - - case GE_CMD_ZTESTENABLE: - glEnDis(GL_DEPTH_TEST, data & 1); - DEBUG_LOG(G3D,"DL Z test enable: %d", data & 1); - break; - - case GE_CMD_STENCILTESTENABLE: - DEBUG_LOG(G3D,"DL Stencil test enable: %d", data); - break; - - case GE_CMD_ZTEST: - { - static const GLuint ztests[8] = - { - GL_NEVER, GL_ALWAYS, GL_EQUAL, GL_NOTEQUAL, - GL_LESS, GL_LEQUAL, GL_GREATER, GL_GEQUAL - }; - //glDepthFunc(ztests[data&7]); - glDepthFunc(GL_LEQUAL); - DEBUG_LOG(G3D,"DL Z test mode: %i", data); - } - break; - - case GE_CMD_MORPHWEIGHT0: - case GE_CMD_MORPHWEIGHT1: - case GE_CMD_MORPHWEIGHT2: - case GE_CMD_MORPHWEIGHT3: - case GE_CMD_MORPHWEIGHT4: - case GE_CMD_MORPHWEIGHT5: - case GE_CMD_MORPHWEIGHT6: - case GE_CMD_MORPHWEIGHT7: - { - int index = cmd - GE_CMD_MORPHWEIGHT0; - float weight = getFloat24(data); - DEBUG_LOG(G3D,"DL MorphWeight %i = %f", index, weight); - gstate.morphWeights[index] = weight; - } - break; - - case GE_CMD_DITH0: - case GE_CMD_DITH1: - case GE_CMD_DITH2: - case GE_CMD_DITH3: - DEBUG_LOG(G3D,"DL DitherMatrix %i = %06x",cmd-GE_CMD_DITH0,data); - break; - - case GE_CMD_WORLDMATRIXNUMBER: - DEBUG_LOG(G3D,"DL World matrix # %i", data); - gstate.worldmtxnum = data&0xF; - break; - - case GE_CMD_WORLDMATRIXDATA: - DEBUG_LOG(G3D,"DL World matrix data # %f", getFloat24(data)); - gstate.worldMatrix[gstate.worldmtxnum++] = getFloat24(data); - break; - - case GE_CMD_VIEWMATRIXNUMBER: - DEBUG_LOG(G3D,"DL VIEW matrix # %i", data); - gstate.viewmtxnum = data&0xF; - break; - - case GE_CMD_VIEWMATRIXDATA: - DEBUG_LOG(G3D,"DL VIEW matrix data # %f", getFloat24(data)); - gstate.viewMatrix[gstate.viewmtxnum++] = getFloat24(data); - break; - - case GE_CMD_PROJMATRIXNUMBER: - DEBUG_LOG(G3D,"DL PROJECTION matrix # %i", data); - gstate.projmtxnum = data&0xF; - break; - - case GE_CMD_PROJMATRIXDATA: - DEBUG_LOG(G3D,"DL PROJECTION matrix data # %f", getFloat24(data)); - gstate.projMatrix[gstate.projmtxnum++] = getFloat24(data); - shaderManager.DirtyUniform(DIRTY_PROJMATRIX); - break; - - case GE_CMD_TGENMATRIXNUMBER: - DEBUG_LOG(G3D,"DL TGEN matrix # %i", data); - gstate.texmtxnum = data&0xF; - break; - - case GE_CMD_TGENMATRIXDATA: - DEBUG_LOG(G3D,"DL TGEN matrix data # %f", getFloat24(data)); - gstate.tgenMatrix[gstate.texmtxnum++] = getFloat24(data); - break; - - case GE_CMD_BONEMATRIXNUMBER: - DEBUG_LOG(G3D,"DL BONE matrix #%i", data); - gstate.boneMatrixNumber = data; - break; - - case GE_CMD_BONEMATRIXDATA: - DEBUG_LOG(G3D,"DL BONE matrix data #%i %f", gstate.boneMatrixNumber, getFloat24(data)); - gstate.boneMatrix[gstate.boneMatrixNumber++] = getFloat24(data); - break; - - default: - DEBUG_LOG(G3D,"DL Unknown: %08x @ %08x", op, dcontext.pc); - break; - - //ETC... - } -} - -bool GPU::InterpretList() -{ - // Reset stackptr for safety - stackptr = 0; - u32 op = 0; - prev = 0; - finished = false; - while (!finished) - { - if (dcontext.pc == dcontext.stallAddr) - return false; - - op = Memory::ReadUnchecked_U32(dcontext.pc); //read from memory - u32 cmd = op >> 24; - u32 diff = op ^ gstate.cmdmem[cmd]; - gstate.cmdmem[cmd] = op; // crashes if I try to put the whole op there?? - - ExecuteOp(op, diff); - - dcontext.pc += 4; - prev = op; - } - return true; -} diff --git a/GPU/Null/NullDisplayListInterpreter.h b/GPU/Null/NullDisplayListInterpreter.h deleted file mode 100644 index dc83dacb59..0000000000 --- a/GPU/Null/NullDisplayListInterpreter.h +++ /dev/null @@ -1,31 +0,0 @@ -// 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 "../../Globals.h" - -class ShaderManager; - -class GPU -{ -public: - static u32 EnqueueList(u32 listpc, u32 stall); - static void UpdateStall(int listid, u32 newstall); - static void ExecuteOp(u32 op, u32 diff); - static bool InterpretList(); -}; diff --git a/GPU/Null/NullGpu.h b/GPU/Null/NullGpu.h index 199ad07e04..05b98aa851 100644 --- a/GPU/Null/NullGpu.h +++ b/GPU/Null/NullGpu.h @@ -44,6 +44,8 @@ public: virtual void InvalidateCache(u32 addr, int size); virtual void Flush() {} + virtual void DeviceLost() {} + private: bool ProcessDLQueue(); bool interruptsEnabled_; diff --git a/android/jni/EmuScreen.cpp b/android/jni/EmuScreen.cpp index 62db3b03f1..da9d1a8fa6 100644 --- a/android/jni/EmuScreen.cpp +++ b/android/jni/EmuScreen.cpp @@ -29,9 +29,8 @@ #include "../../Core/Host.h" #include "../../Core/System.h" #include "../../Core/MIPS/MIPS.h" -#include "../../GPU/GLES/TextureCache.h" -#include "../../GPU/GLES/ShaderManager.h" #include "../../GPU/GPUState.h" +#include "../../GPU/GPUInterface.h" #include "../../Core/HLE/sceCtrl.h" #include "GamepadEmu.h" @@ -40,8 +39,6 @@ #include "MenuScreens.h" #include "EmuScreen.h" -extern ShaderManager shaderManager; - EmuScreen::EmuScreen(const std::string &filename) : invalid_(true) { std::string fileToStart = filename; @@ -200,6 +197,5 @@ void EmuScreen::render() void EmuScreen::deviceLost() { - TextureCache_Clear(false); // This doesn't seem to help? - shaderManager.ClearCache(false); + gpu->DeviceLost(); }