mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-02-01 11:12:49 +00:00
Synchronize the mainloop to the display end-of-frame on nonWindows
platforms.
This commit is contained in:
parent
ec2cb15c38
commit
fb25b7405c
@ -41,7 +41,7 @@ private:
|
||||
u32 id;
|
||||
public:
|
||||
virtual void SingleStep() = 0;
|
||||
virtual void RunLoopUntil(u64 globalTicks) = 0;
|
||||
virtual int RunLoopUntil(u64 globalTicks) = 0;
|
||||
};
|
||||
|
||||
#define MAX_NUM_CPU 2
|
||||
|
@ -60,14 +60,16 @@ static int hCount = 0;
|
||||
static int hCountTotal = 0; //unused
|
||||
static int vCount = 0;
|
||||
static int isVblank = 0;
|
||||
|
||||
static bool frameDone;
|
||||
// STATE END
|
||||
|
||||
|
||||
// The vblank period is 731.5 us (0.7315 ms)
|
||||
const double vblankMs = 0.7315;
|
||||
const double frameMs = 1000.0 / 60.0;
|
||||
|
||||
enum {
|
||||
PSP_DISPLAY_SETBUF_IMMEDIATE = 0,
|
||||
PSP_DISPLAY_SETBUF_IMMEDIATE = 0,
|
||||
PSP_DISPLAY_SETBUF_NEXTFRAME = 1
|
||||
};
|
||||
|
||||
@ -85,6 +87,7 @@ void hleLeaveVblank(u64 userdata, int cyclesLate);
|
||||
void __DisplayInit()
|
||||
{
|
||||
framebufIsLatched = false;
|
||||
frameDone = false;
|
||||
framebuf.topaddr = 0x04000000;
|
||||
framebuf.pspframebuf = Memory::GetPointer(0x04000000);
|
||||
framebuf.pspFramebufFormat = PSP_DISPLAY_PIXEL_FORMAT_8888;
|
||||
@ -105,6 +108,14 @@ void __DisplayShutdown()
|
||||
ShutdownGfxState();
|
||||
}
|
||||
|
||||
// will return true once after every end-of-frame.
|
||||
bool __DisplayFrameDone()
|
||||
{
|
||||
bool retVal = frameDone;
|
||||
frameDone = false;
|
||||
return retVal;
|
||||
}
|
||||
|
||||
void hleEnterVblank(u64 userdata, int cyclesLate)
|
||||
{
|
||||
int vbCount = userdata;
|
||||
@ -149,7 +160,6 @@ void hleEnterVblank(u64 userdata, int cyclesLate)
|
||||
// an initial hack could be to NOT end the frame if the buffer didn't change? that should work okay.
|
||||
{
|
||||
host->EndFrame();
|
||||
|
||||
host->BeginFrame();
|
||||
if (g_Config.bDisplayFramebuffer)
|
||||
{
|
||||
@ -161,7 +171,8 @@ void hleEnterVblank(u64 userdata, int cyclesLate)
|
||||
shaderManager.DirtyUniform(DIRTY_ALL);
|
||||
}
|
||||
|
||||
// TODO: Find a way to tell the CPU core to stop emulating here, when running on Android.
|
||||
// Tell the emu core that it's time to stop emulating
|
||||
frameDone = true;
|
||||
}
|
||||
|
||||
|
||||
|
@ -20,3 +20,6 @@
|
||||
void __DisplayInit();
|
||||
|
||||
void Register_sceDisplay();
|
||||
|
||||
// will return true once after every end-of-frame.
|
||||
bool __DisplayFrameDone();
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include "MIPSVFPUUtils.h"
|
||||
#include "../System.h"
|
||||
#include "../Debugger/Breakpoints.h"
|
||||
#include "../HLE/sceDisplay.h"
|
||||
|
||||
#if defined(ANDROID) || defined(BLACKBERRY)
|
||||
#include "ARM/JitCache.h"
|
||||
@ -105,7 +106,8 @@ void MIPSState::SingleStep()
|
||||
CoreTiming::Advance();
|
||||
}
|
||||
|
||||
void MIPSState::RunLoopUntil(u64 globalTicks)
|
||||
// returns 1 if reached ticks limit
|
||||
int MIPSState::RunLoopUntil(u64 globalTicks)
|
||||
{
|
||||
// Don't subvert this by setting useJIT to true - other places also check the coreparameter
|
||||
bool useJIT = PSP_CoreParameter().cpuCore == CPU_JIT;
|
||||
@ -189,19 +191,21 @@ void MIPSState::RunLoopUntil(u64 globalTicks)
|
||||
CoreTiming::downcount -= 1;
|
||||
if (CoreTiming::GetTicks() > globalTicks)
|
||||
{
|
||||
DEBUG_LOG(CPU, "Hit the max ticks, bailing : %llu, %llu", globalTicks, CoreTiming::GetTicks());
|
||||
break;
|
||||
// DEBUG_LOG(CPU, "Hit the max ticks, bailing 1 : %llu, %llu", globalTicks, CoreTiming::GetTicks());
|
||||
return 1;
|
||||
}
|
||||
#ifndef _WIN32 // Windows simply keeps running and control the refresh from sceDisplay
|
||||
if (__DisplayFrameDone()) {
|
||||
// End of frame! Need to quit the CPU loop temporarily.
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
CoreTiming::Advance();
|
||||
if (CoreTiming::GetTicks() > globalTicks)
|
||||
{
|
||||
DEBUG_LOG(CPU, "Hit the max ticks, bailing : %llu, %llu", globalTicks, CoreTiming::GetTicks());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void MIPSState::WriteFCR(int reg, int value)
|
||||
|
@ -143,7 +143,7 @@ public:
|
||||
void Abort();
|
||||
|
||||
void SingleStep();
|
||||
void RunLoopUntil(u64 globalTicks);
|
||||
int RunLoopUntil(u64 globalTicks);
|
||||
};
|
||||
|
||||
|
||||
|
@ -145,9 +145,17 @@ void EmuScreen::render()
|
||||
// I think we need to allocate FBOs per framebuffer and just blit the displayed one here at the end of the frame.
|
||||
// Also - we should add another option to the core that lets us run it until a vblank event happens or the N cycles have passed
|
||||
// - then the synchronization would at least not be able to drift off.
|
||||
u64 nowTicks = CoreTiming::GetTicks();
|
||||
u64 frameTicks = usToCycles(1000000 / 60);
|
||||
mipsr4k.RunLoopUntil(nowTicks + frameTicks); // should really be relative to the last frame but whatever
|
||||
int retval = 1;
|
||||
|
||||
// Let's do 120 "blocks" per second just to try it
|
||||
int blockTicks = usToCycles(1000000 / 120);
|
||||
|
||||
while (retval == 1) {
|
||||
u64 nowTicks = CoreTiming::GetTicks();
|
||||
retval = mipsr4k.RunLoopUntil(nowTicks + blockTicks);
|
||||
// If exited because of cycles, try again.
|
||||
// If exited because of end of frame, great!
|
||||
}
|
||||
|
||||
//if (hasRendered)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user