Display: Wait for vblank when setting mode.

Some games call this even when not needed, and it turns out to have an
important behavior.
This commit is contained in:
Unknown W. Brackets 2016-05-16 22:02:21 -07:00
parent 9ed604f9c8
commit d0dc03f359

View file

@ -729,16 +729,32 @@ static u32 sceDisplayIsVblank() {
return hleLogSuccessI(SCEDISPLAY, isVblank);
}
static int DisplayWaitForVblanks(const char *reason, int vblanks, bool callbacks = false) {
const s64 ticksIntoFrame = CoreTiming::GetTicks() - frameStartTicks;
const s64 cyclesToNextVblank = msToCycles(frameMs) - ticksIntoFrame;
// These syscalls take about 115 us, so if the next vblank is before then, we're waiting extra.
// At least, on real firmware a wait >= 16500 into the frame will wait two.
if (cyclesToNextVblank <= usToCycles(115)) {
++vblanks;
}
vblankWaitingThreads.push_back(WaitVBlankInfo(__KernelGetCurThread(), vblanks));
__KernelWaitCurThread(WAITTYPE_VBLANK, 1, 0, 0, callbacks, reason);
return hleLogSuccessVerboseI(SCEDISPLAY, 0, "waiting for %d vblanks", vblanks);
}
static u32 sceDisplaySetMode(int displayMode, int displayWidth, int displayHeight) {
if (displayMode != PSP_DISPLAY_MODE_LCD || displayWidth != 480 || displayHeight != 272) {
WARN_LOG_REPORT(SCEDISPLAY, "Video out requested, not supported: mode=%d size=%d,%d", displayMode, displayWidth, displayHeight);
}
if (displayWidth != 480 || displayHeight != 272) {
return hleLogWarning(SCEDISPLAY, SCE_KERNEL_ERROR_INVALID_SIZE, "invalid size");
}
if (displayMode != PSP_DISPLAY_MODE_LCD) {
return hleLogWarning(SCEDISPLAY, SCE_KERNEL_ERROR_INVALID_MODE, "invalid mode");
}
if (displayWidth != 480 || displayHeight != 272) {
return hleLogWarning(SCEDISPLAY, SCE_KERNEL_ERROR_INVALID_SIZE, "invalid size");
}
if (!hasSetMode) {
gpu->InitClear();
@ -747,7 +763,10 @@ static u32 sceDisplaySetMode(int displayMode, int displayWidth, int displayHeigh
mode = displayMode;
width = displayWidth;
height = displayHeight;
return hleLogSuccessI(SCEDISPLAY, 0);
hleLogSuccessI(SCEDISPLAY, 0);
// On success, this implicitly waits for a vblank start.
return DisplayWaitForVblanks("display mode", 1);
}
// Some games (GTA) never call this during gameplay, so bad place to put a framerate counter.
@ -860,22 +879,6 @@ static u32 sceDisplayGetFramebuf(u32 topaddrPtr, u32 linesizePtr, u32 pixelForma
return hleLogSuccessI(SCEDISPLAY, 0);
}
static int DisplayWaitForVblanks(const char *reason, int vblanks, bool callbacks = false) {
const s64 ticksIntoFrame = CoreTiming::GetTicks() - frameStartTicks;
const s64 cyclesToNextVblank = msToCycles(frameMs) - ticksIntoFrame;
// These syscalls take about 115 us, so if the next vblank is before then, we're waiting extra.
// At least, on real firmware a wait >= 16500 into the frame will wait two.
if (cyclesToNextVblank <= usToCycles(115)) {
++vblanks;
}
vblankWaitingThreads.push_back(WaitVBlankInfo(__KernelGetCurThread(), vblanks));
__KernelWaitCurThread(WAITTYPE_VBLANK, 1, 0, 0, callbacks, reason);
return hleLogSuccessVerboseI(SCEDISPLAY, 0, "waiting for %d vblanks", vblanks);
}
static int DisplayWaitForVblanksCB(const char *reason, int vblanks) {
return DisplayWaitForVblanks(reason, vblanks, true);
}