Synchronize the mainloop to the display end-of-frame on nonWindows

platforms.
This commit is contained in:
Henrik Rydgård 2012-11-19 14:16:37 +01:00
parent ec2cb15c38
commit fb25b7405c
6 changed files with 43 additions and 17 deletions

View File

@ -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

View File

@ -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;
}

View File

@ -20,3 +20,6 @@
void __DisplayInit();
void Register_sceDisplay();
// will return true once after every end-of-frame.
bool __DisplayFrameDone();

View File

@ -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)

View File

@ -143,7 +143,7 @@ public:
void Abort();
void SingleStep();
void RunLoopUntil(u64 globalTicks);
int RunLoopUntil(u64 globalTicks);
};

View File

@ -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)
{