diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index ed552dcbaa..9ec7d75303 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -86,6 +86,7 @@ static int hCount; static int hCountTotal; //unused static int vCount; static int isVblank; +static int numSkippedFrames; static bool hasSetMode; // Don't include this in the state, time increases regardless of state. static double lastFrameTime; @@ -113,6 +114,7 @@ void hleAfterFlip(u64 userdata, int cyclesLate); void __DisplayInit() { gpuStats.reset(); hasSetMode = false; + numSkippedFrames = 0; framebufIsLatched = false; framebuf.topaddr = 0x04000000; framebuf.pspFramebufFormat = PSP_DISPLAY_PIXEL_FORMAT_8888; @@ -264,12 +266,15 @@ void DebugStats() } // Let's collect all the throttling and frameskipping logic here. -void DoFrameTiming(bool &throttle) { +void DoFrameTiming(bool &throttle, bool &skipFrame, bool &skipFlip) { #ifdef _WIN32 throttle = !GetAsyncKeyState(VK_TAB); #else throttle = false; #endif + skipFlip = false; + skipFrame = false; + if (PSP_CoreParameter().headLess) throttle = false; @@ -353,16 +358,26 @@ void hleEnterVblank(u64 userdata, int cyclesLate) { // Yeah, this has to be the right moment to end the frame. Give the graphics backend opportunity // to blit the framebuffer, in order to support half-framerate games that otherwise wouldn't have // anything to draw here. - gpu->CopyDisplayToOutput(); + gstate_c.skipDrawReason &= ~SKIPDRAW_SKIPFRAME; - bool throttle; + bool throttle, skipFrame, skipFlip; - DoFrameTiming(throttle); + DoFrameTiming(throttle, skipFrame, skipFlip); // Setting CORE_NEXTFRAME causes a swap. - coreState = CORE_NEXTFRAME; - - CoreTiming::ScheduleEvent(0 - cyclesLate, afterFlipEvent, 0); + if (skipFrame) { + gstate_c.skipDrawReason |= SKIPDRAW_SKIPFRAME; + numSkippedFrames++; + } else { + numSkippedFrames = 0; + } + + if (!skipFlip) { + coreState = CORE_NEXTFRAME; + CoreTiming::ScheduleEvent(0 - cyclesLate, afterFlipEvent, 0); + + gpu->CopyDisplayToOutput(); + } // Returning here with coreState == CORE_NEXTFRAME causes a buffer flip to happen (next frame). // Right after, we regain control for a little bit in hleAfterFlip. I think that's a great diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index 6bf4220d86..cde737fedd 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -330,6 +330,9 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) { case GE_CMD_PRIM: { + if (gstate_c.skipDrawReason) + return; + framebufferManager_.SetRenderFrameBuffer(); u32 count = data & 0xFFFF; diff --git a/GPU/GLES/DisplayListInterpreter.h b/GPU/GLES/DisplayListInterpreter.h index 52e1883730..048aab400b 100644 --- a/GPU/GLES/DisplayListInterpreter.h +++ b/GPU/GLES/DisplayListInterpreter.h @@ -64,7 +64,6 @@ public: return textureCache_.DecodeTexture(dest, state); } - std::vector GetFramebufferList(); private: diff --git a/GPU/GPUState.h b/GPU/GPUState.h index ca036b2506..8f12c7d045 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -224,7 +224,11 @@ struct GPUgstate // Real data in the context ends here }; - + +enum SkipDrawReasonFlags { + SKIPDRAW_SKIPFRAME = 1, +}; + // The rest is cached simplified/converted data for fast access. // Does not need to be saved when saving/restoring context. struct GPUStateCache @@ -236,6 +240,8 @@ struct GPUStateCache bool textureChanged; + int skipDrawReason; + float uScale,vScale; float uOff,vOff; bool flipTexture;