[Scummvm-git-logs] scummvm master -> 73fed809d039419189bee49caf367881d99654bb
spleen1981
noreply at scummvm.org
Wed Mar 22 20:11:10 UTC 2023
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
73fed809d0 LIBRETRO: improve timing
Commit: 73fed809d039419189bee49caf367881d99654bb
https://github.com/scummvm/scummvm/commit/73fed809d039419189bee49caf367881d99654bb
Author: Giovanni Cascione (ing.cascione at gmail.com)
Date: 2023-03-22T21:10:47+01:00
Commit Message:
LIBRETRO: improve timing
Changed paths:
backends/platform/libretro/include/os.h
backends/platform/libretro/src/libretro-os.cpp
diff --git a/backends/platform/libretro/include/os.h b/backends/platform/libretro/include/os.h
index df245d1447c..87acb8694cb 100644
--- a/backends/platform/libretro/include/os.h
+++ b/backends/platform/libretro/include/os.h
@@ -33,6 +33,12 @@
#define AUDIO_STATUS_BUFFER_UNDERRUN (1 << 3)
#define AUDIO_STATUS_UPDATE_LATENCY (1 << 4)
+// Thread switch caller
+#define THREAD_SWITCH_POLL (1 << 0)
+#define THREAD_SWITCH_DELAY (1 << 1)
+#define THREAD_SWITCH_UPDATE (1 << 2)
+#define THREAD_SWITCH_RECT (1 << 3)
+
// Preliminary scan results
#define TEST_GAME_OK_TARGET_FOUND 0
#define TEST_GAME_OK_ID_FOUND 1
diff --git a/backends/platform/libretro/src/libretro-os.cpp b/backends/platform/libretro/src/libretro-os.cpp
index dc820a7c0de..aa9811eb399 100644
--- a/backends/platform/libretro/src/libretro-os.cpp
+++ b/backends/platform/libretro/src/libretro-os.cpp
@@ -357,12 +357,13 @@ public:
uint32 _startTime;
uint32 _threadExitTime;
+ uint8 _threadSwitchCaller;
bool _speed_hack_enabled;
Audio::MixerImpl *_mixer;
- OSystem_RETRO(bool aEnableSpeedHack) : _mousePaletteEnabled(false), _mouseVisible(false), _mouseX(0), _mouseY(0), _mouseXAcc(0.0), _mouseYAcc(0.0), _mouseHotspotX(0), _mouseHotspotY(0), _dpadXAcc(0.0), _dpadYAcc(0.0), _dpadXVel(0.0f), _dpadYVel(0.0f), _mouseKeyColor(0), _mouseDontScale(false), _joypadnumpadLast(8), _joypadnumpadActive(false), _mixer(0), _startTime(0), _threadExitTime(10), _speed_hack_enabled(aEnableSpeedHack) {
+ OSystem_RETRO(bool aEnableSpeedHack) : _mousePaletteEnabled(false), _mouseVisible(false), _mouseX(0), _mouseY(0), _mouseXAcc(0.0), _mouseYAcc(0.0), _mouseHotspotX(0), _mouseHotspotY(0), _dpadXAcc(0.0), _dpadYAcc(0.0), _dpadXVel(0.0f), _dpadYVel(0.0f), _mouseKeyColor(0), _mouseDontScale(false), _joypadnumpadLast(8), _joypadnumpadActive(false), _mixer(0), _startTime(0), _threadExitTime(0), _threadSwitchCaller(0), _speed_hack_enabled(aEnableSpeedHack) {
_fsFactory = new FS_SYSTEM_FACTORY();
memset(_mouseButtons, 0, sizeof(_mouseButtons));
memset(_joypadmouseButtons, 0, sizeof(_joypadmouseButtons));
@@ -496,6 +497,16 @@ public:
const uint8_t *src = (const uint8_t *)buf;
uint8_t *pix = (uint8_t *)_gameScreen.getPixels();
copyRectToSurface(pix, _gameScreen.pitch, src, pitch, x, y, w, h, _gameScreen.format.bytesPerPixel);
+
+ /* In case of consecutive updateScreen calls, additionally switch to main thread when (and if) first copyRectToScreen is called
+ between two updateScreen. This reduces crackling.
+ Consecutive copyRectToScreen other than first are covered by thread switch triggered by pollEvent or delayMillis. */
+ if (! _speed_hack_enabled) {
+ if (!(_threadSwitchCaller & THREAD_SWITCH_RECT) && (_threadSwitchCaller & THREAD_SWITCH_UPDATE)) {
+ retroCheckThread();
+ _threadSwitchCaller |= THREAD_SWITCH_RECT;
+ }
+ }
}
virtual void updateScreen() {
@@ -533,6 +544,15 @@ public:
break;
}
}
+
+ /* Switch to main thread in case of consecutive updateScreen, to avoid losing frames.
+ Non consecutive updateScreen are covered by thread switches triggered by pollEvent or delayMillis. */
+ if (! _speed_hack_enabled && (_threadSwitchCaller & THREAD_SWITCH_UPDATE)) {
+ retroCheckThread();
+ _threadSwitchCaller &= ~THREAD_SWITCH_RECT;
+ } else {
+ _threadSwitchCaller = THREAD_SWITCH_UPDATE;
+ }
}
virtual Graphics::Surface *lockScreen() {
@@ -622,17 +642,23 @@ public:
}
void retroCheckThread(uint32 offset = 0) {
- if (_threadExitTime <= (getMillis() + offset)) {
+ uint32 now = getMillis();
+
+ /* Limit the thread switches triggered by pollEvent or delayMillis to one each 10ms.
+ Do not limit thread switches due to consecutive updateScreen to avoid losing frames. */
+ if (_threadExitTime <= (now + offset)) {
+ _threadExitTime = now + 10;
+ retro_switch_to_main_thread();
+ } else if (_threadSwitchCaller & THREAD_SWITCH_UPDATE){
retro_switch_to_main_thread();
- _threadExitTime = getMillis() + 10;
}
+
+ ((DefaultTimerManager *)_timerManager)->handler();
}
virtual bool pollEvent(Common::Event &event) {
+ _threadSwitchCaller = THREAD_SWITCH_POLL;
retroCheckThread();
-
- ((DefaultTimerManager *)_timerManager)->handler();
-
if (!_events.empty()) {
event = _events.front();
_events.pop_front();
@@ -660,6 +686,7 @@ public:
virtual void delayMillis(uint msecs) {
// Implement 'non-blocking' sleep...
uint32 start_time = getMillis();
+
if (_speed_hack_enabled) {
// Use janky inaccurate method...
uint32 elapsed_time = 0;
@@ -669,6 +696,7 @@ public:
// thread exit time, exit the thread immediately
// (i.e. start burning delay time in the main RetroArch
// thread as soon as possible...)
+ _threadSwitchCaller = THREAD_SWITCH_DELAY;
retroCheckThread(time_remaining);
// Check how much delay time remains...
elapsed_time = getMillis() - start_time;
@@ -678,20 +706,13 @@ public:
} else {
time_remaining = 0;
}
- // Have to handle the timer manager here, since some engines
- // (e.g. dreamweb) sit in a delayMillis() loop waiting for a
- // timer callback...
- ((DefaultTimerManager *)_timerManager)->handler();
}
} else {
// Use accurate method...
while (getMillis() < start_time + msecs) {
usleep(1000);
+ _threadSwitchCaller = THREAD_SWITCH_DELAY;
retroCheckThread();
- // Have to handle the timer manager here, since some engines
- // (e.g. dreamweb) sit in a delayMillis() loop waiting for a
- // timer callback...
- ((DefaultTimerManager *)_timerManager)->handler();
}
}
}
@@ -750,8 +771,6 @@ public:
log_cb(RETRO_LOG_INFO, "%s\n", message);
}
- //
-
const Graphics::Surface &getScreen() {
const Graphics::Surface &srcSurface = (_overlayInGUI) ? _overlay : _gameScreen;
@@ -795,7 +814,6 @@ public:
*cumulativeXYAcc -= (float)cumulativeXYAcc_int;
}
*relMouseXY = (int)deltaAcc;
-
}
void processMouse(retro_input_state_t aCallback, int device, float gampad_cursor_speed, float gamepad_acceleration_time, bool analog_response_is_quadratic, int analog_deadzone, float mouse_speed) {
More information about the Scummvm-git-logs
mailing list