#include "ppsspp_config.h"
#include "Common/Profiler/Profiler.h"
#include "Common/Log.h"
#include "Common/TimeUtil.h"
#include "Core/RetroAchievements.h"
#include "Core/CoreParameter.h"
#include "Core/Core.h"
#include "Core/System.h"
#include "Core/Config.h"
#include "Core/HW/Display.h"
#include "Core/HLE/sceNet.h"
#include "Core/FrameTiming.h"
FrameTiming g_frameTiming;
void WaitUntil(double now, double timestamp, const char *reason) {
#if 1
sleep_precise(timestamp - now);
#else
#if PPSSPP_PLATFORM(WINDOWS)
while (time_now_d() < timestamp) {
sleep_ms(1, reason);
}
#else
const double left = timestamp - now;
if (left > 0.0 && left < 3.0) {
usleep((long)(left * 1000000));
}
#endif
#endif
}
inline Draw::PresentMode GetBestImmediateMode(Draw::PresentMode supportedModes) {
if (supportedModes & Draw::PresentMode::MAILBOX) {
return Draw::PresentMode::MAILBOX;
} else {
return Draw::PresentMode::IMMEDIATE;
}
}
void FrameTiming::Reset(Draw::DrawContext *draw) {
if (g_Config.bVSync || !(draw->GetDeviceCaps().presentModesSupported & (Draw::PresentMode::MAILBOX | Draw::PresentMode::IMMEDIATE))) {
presentMode = Draw::PresentMode::FIFO;
presentInterval = 1;
} else {
presentMode = GetBestImmediateMode(draw->GetDeviceCaps().presentModesSupported);
presentInterval = 0;
}
}
void FrameTiming::DeferWaitUntil(double until, double *curTimePtr) {
_dbg_assert_(until > 0.0);
waitUntil_ = until;
curTimePtr_ = curTimePtr;
}
void FrameTiming::PostSubmit() {
if (waitUntil_ != 0.0) {
WaitUntil(time_now_d(), waitUntil_, "post-submit");
if (curTimePtr_) {
*curTimePtr_ = waitUntil_;
curTimePtr_ = nullptr;
}
waitUntil_ = 0.0;
}
}
Draw::PresentMode ComputePresentMode(Draw::DrawContext *draw, int *interval) {
_assert_(draw);
Draw::PresentMode mode = Draw::PresentMode::FIFO;
if (draw->GetDeviceCaps().presentModesSupported & (Draw::PresentMode::IMMEDIATE | Draw::PresentMode::MAILBOX)) {
bool wantInstant = false;
if (!g_Config.bVSync) {
wantInstant = true;
}
if (PSP_CoreParameter().fastForward && NetworkAllowSpeedControl()) {
wantInstant = true;
}
FPSLimit limit = PSP_CoreParameter().fpsLimit;
if (!NetworkAllowSpeedControl()) {
limit = FPSLimit::NORMAL;
}
if (limit != FPSLimit::NORMAL) {
int limit;
if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM1)
limit = g_Config.iFpsLimit1;
else if (PSP_CoreParameter().fpsLimit == FPSLimit::CUSTOM2)
limit = g_Config.iFpsLimit2;
else
limit = PSP_CoreParameter().analogFpsLimit;
if (limit == 0 || (limit >= 0 && limit != 15 && limit != 30 && limit != 60)) {
wantInstant = true;
}
}
if (wantInstant && g_Config.bVSync && !draw->GetDeviceCaps().presentInstantModeChange) {
wantInstant = false;
}
if (wantInstant) {
mode = GetBestImmediateMode(draw->GetDeviceCaps().presentModesSupported);
}
}
*interval = (mode == Draw::PresentMode::FIFO) ? 1 : 0;
return mode;
}