[Scummvm-git-logs] scummvm master -> b84bc71c25899bd9f11fd1667de15cce27fc72f2
spleen1981
noreply at scummvm.org
Fri May 5 02:51:31 UTC 2023
This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
b71a9808a6 LIBRETRO: add libretro timer
b84bc71c25 LIBRETRO: rework delayMillis
Commit: b71a9808a6d660f72212c3d9b2417562cfc73abc
https://github.com/scummvm/scummvm/commit/b71a9808a6d660f72212c3d9b2417562cfc73abc
Author: Giovanni Cascione (ing.cascione at gmail.com)
Date: 2023-05-05T04:50:25+02:00
Commit Message:
LIBRETRO: add libretro timer
Changed paths:
A backends/platform/libretro/include/libretro-timer.h
A backends/platform/libretro/src/libretro-timer.cpp
backends/platform/libretro/Makefile.common
backends/platform/libretro/src/libretro-os.cpp
backends/platform/libretro/src/libretro.cpp
diff --git a/backends/platform/libretro/Makefile.common b/backends/platform/libretro/Makefile.common
index 7a1772591d1..398c089d15a 100644
--- a/backends/platform/libretro/Makefile.common
+++ b/backends/platform/libretro/Makefile.common
@@ -118,7 +118,8 @@ LIBRETRO_OBJS := $(CORE_PATH)/libretro-os.o \
$(CORE_PATH)/libretro-fs.o \
$(CORE_PATH)/libretro-fs-factory.o \
$(CORE_PATH)/libretro.o \
- $(CORE_PATH)/libretro-threads.o
+ $(CORE_PATH)/libretro-threads.o \
+ $(CORE_PATH)/libretro-timer.o
OBJS += $(LIBRETRO_OBJS)
diff --git a/backends/platform/libretro/include/libretro-timer.h b/backends/platform/libretro/include/libretro-timer.h
new file mode 100644
index 00000000000..4500d4d75bd
--- /dev/null
+++ b/backends/platform/libretro/include/libretro-timer.h
@@ -0,0 +1,39 @@
+/* Copyright (C) 2022 Giovanni Cascione <ing.cascione at gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef LIBRETRO_TIMER_H
+#define LIBRETRO_TIMER_H
+
+#define EMU_THREAD_MIN_TIME 10
+
+#include "backends/timer/default/default-timer.h"
+#include "backends/platform/libretro/include/os.h"
+
+class LibretroTimerManager : public DefaultTimerManager {
+ uint32 _interval;
+ uint32 _nextSwitchTime;
+ uint32 _spentOnMainThread;
+public:
+ LibretroTimerManager(uint32 refresh_rate = REFRESH_RATE);
+ ~LibretroTimerManager(void) {};
+ void switchThread(void);
+ void checkThread(void);
+ uint32 timeToNextSwitch(void);
+ uint32 spentOnMainThread(void);
+};
+
+#endif // LIBRETRO_TIMER_H
diff --git a/backends/platform/libretro/src/libretro-os.cpp b/backends/platform/libretro/src/libretro-os.cpp
index 16f3be99550..a13beadedbc 100644
--- a/backends/platform/libretro/src/libretro-os.cpp
+++ b/backends/platform/libretro/src/libretro-os.cpp
@@ -46,7 +46,7 @@
#endif
#include "backends/saves/default/default-saves.h"
-#include "backends/timer/default/default-timer.h"
+#include "backends/platform/libretro/include/libretro-timer.h"
#include "graphics/colormasks.h"
#include "graphics/palette.h"
#include "graphics/surface.h"
@@ -322,6 +322,7 @@ Common::List<Common::Event> _events;
extern bool timing_inaccuracies_is_enabled(void);
extern bool consecutive_screen_updates_is_enabled(void);
extern void reset_performance_tuner(void);
+extern float frame_rate;
class OSystem_RETRO : public EventsBaseBackend, public PaletteManager {
public:
@@ -360,12 +361,11 @@ public:
bool _ptrmouseButton;
uint32 _startTime;
- uint32 _threadExitTime;
uint8 _threadSwitchCaller;
Audio::MixerImpl *_mixer;
- OSystem_RETRO() : _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) {
+ OSystem_RETRO() : _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), _threadSwitchCaller(0) {
_fsFactory = new FS_SYSTEM_FACTORY();
memset(_mouseButtons, 0, sizeof(_mouseButtons));
memset(_joypadmouseButtons, 0, sizeof(_joypadmouseButtons));
@@ -397,7 +397,8 @@ public:
_overlay.create(RES_W_OVERLAY, RES_H_OVERLAY, Graphics::PixelFormat(2, 5, 5, 5, 1, 10, 5, 0, 15));
#endif
_mixer = new Audio::MixerImpl(SAMPLE_RATE);
- _timerManager = new DefaultTimerManager();
+
+ _timerManager = new LibretroTimerManager(frame_rate);
_mixer->setReady(true);
@@ -550,7 +551,7 @@ public:
Non consecutive updateScreen are covered by thread switches triggered by pollEvent or delayMillis. */
if (! timing_inaccuracies_is_enabled() && consecutive_screen_updates_is_enabled()) {
if (_threadSwitchCaller & THREAD_SWITCH_UPDATE) {
- retro_switch_to_main_thread();
+ ((LibretroTimerManager *)_timerManager)->switchThread();
} else {
_threadSwitchCaller = THREAD_SWITCH_UPDATE;
}
@@ -643,23 +644,13 @@ public:
_mousePaletteEnabled = true;
}
- void retroCheckThread(uint32 offset = 0) {
- /* Limit the thread switches triggered by pollEvent or delayMillis to one each 10ms. */
- if (_threadExitTime <= (getMillis() + offset)) {
- retro_switch_to_main_thread();
- _threadExitTime = getMillis() + 10;
- }
-
- ((DefaultTimerManager *)_timerManager)->handler();
- }
-
uint8 getThreadSwitchCaller(){
return _threadSwitchCaller;
}
virtual bool pollEvent(Common::Event &event) {
_threadSwitchCaller = THREAD_SWITCH_POLL;
- retroCheckThread();
+ ((LibretroTimerManager *)_timerManager)->checkThread();
if (!_events.empty()) {
event = _events.front();
_events.pop_front();
@@ -687,6 +678,7 @@ public:
virtual void delayMillis(uint msecs) {
// Implement 'non-blocking' sleep...
uint32 start_time = getMillis();
+ _threadSwitchCaller = THREAD_SWITCH_DELAY;
if (timing_inaccuracies_is_enabled()) {
// Use janky inaccurate method...
@@ -697,12 +689,11 @@ 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);
+ ((LibretroTimerManager *)_timerManager)->checkThread(time_remaining);
// Check how much delay time remains...
elapsed_time = getMillis() - start_time;
if (time_remaining > elapsed_time) {
- time_remaining = time_remaining - elapsed_time;
+ time_remaining -= elapsed_time;
usleep(1000);
} else {
time_remaining = 0;
@@ -711,9 +702,8 @@ public:
} else {
// Use accurate method...
while (getMillis() < start_time + msecs) {
+ ((LibretroTimerManager *)_timerManager)->checkThread();
usleep(1000);
- _threadSwitchCaller = THREAD_SWITCH_DELAY;
- retroCheckThread();
}
}
}
diff --git a/backends/platform/libretro/src/libretro-timer.cpp b/backends/platform/libretro/src/libretro-timer.cpp
new file mode 100644
index 00000000000..25a400d707b
--- /dev/null
+++ b/backends/platform/libretro/src/libretro-timer.cpp
@@ -0,0 +1,58 @@
+/* Copyright (C) 2022 Giovanni Cascione <ing.cascione at gmail.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#if defined(__LIBRETRO__)
+#include "common/scummsys.h"
+#include "common/timer.h"
+#include "backends/platform/libretro/include/libretro-threads.h"
+#include "backends/platform/libretro/include/libretro-timer.h"
+#include "backends/platform/libretro/include/os.h"
+
+LibretroTimerManager::LibretroTimerManager(uint32 refresh_rate) {
+ if (! refresh_rate > 0)
+ refresh_rate = REFRESH_RATE;
+ _interval = 1000 / refresh_rate;
+ _nextSwitchTime = _interval + g_system->getMillis();
+}
+
+void LibretroTimerManager::switchThread(void) {
+ _nextSwitchTime = g_system->getMillis() + _interval;
+ retro_switch_to_main_thread();
+ _spentOnMainThread = g_system->getMillis() - _nextSwitchTime + _interval;
+
+ if (_interval - _spentOnMainThread < EMU_THREAD_MIN_TIME) {
+ _nextSwitchTime = _nextSwitchTime + _spentOnMainThread + EMU_THREAD_MIN_TIME;
+ _spentOnMainThread = _interval - EMU_THREAD_MIN_TIME;
+ }
+}
+
+void LibretroTimerManager::checkThread(void) {
+ if (g_system->getMillis() >= _nextSwitchTime) {
+ switchThread();
+ handler();
+ }
+}
+
+uint32 LibretroTimerManager::timeToNextSwitch(void) {
+ uint32 now = g_system->getMillis();
+ return _nextSwitchTime > now ? _nextSwitchTime - now : 0;
+}
+
+uint32 LibretroTimerManager::spentOnMainThread(void) {
+ return _spentOnMainThread;
+}
+#endif
diff --git a/backends/platform/libretro/src/libretro.cpp b/backends/platform/libretro/src/libretro.cpp
index a4924f0745d..17d2d33feee 100644
--- a/backends/platform/libretro/src/libretro.cpp
+++ b/backends/platform/libretro/src/libretro.cpp
@@ -803,7 +803,6 @@ void retro_run(void) {
frameskip_events = 0;
}
}
-
/* Switch to ScummVM thread, unless frameskipping is ongoing */
if (!skip_frame)
retro_switch_to_emu_thread();
Commit: b84bc71c25899bd9f11fd1667de15cce27fc72f2
https://github.com/scummvm/scummvm/commit/b84bc71c25899bd9f11fd1667de15cce27fc72f2
Author: Giovanni Cascione (ing.cascione at gmail.com)
Date: 2023-05-05T04:50:43+02:00
Commit Message:
LIBRETRO: rework delayMillis
Changed paths:
backends/platform/libretro/src/libretro-os.cpp
diff --git a/backends/platform/libretro/src/libretro-os.cpp b/backends/platform/libretro/src/libretro-os.cpp
index a13beadedbc..51f16ece38f 100644
--- a/backends/platform/libretro/src/libretro-os.cpp
+++ b/backends/platform/libretro/src/libretro-os.cpp
@@ -651,6 +651,7 @@ public:
virtual bool pollEvent(Common::Event &event) {
_threadSwitchCaller = THREAD_SWITCH_POLL;
((LibretroTimerManager *)_timerManager)->checkThread();
+
if (!_events.empty()) {
event = _events.front();
_events.pop_front();
@@ -676,35 +677,27 @@ public:
}
virtual void delayMillis(uint msecs) {
- // Implement 'non-blocking' sleep...
uint32 start_time = getMillis();
_threadSwitchCaller = THREAD_SWITCH_DELAY;
- if (timing_inaccuracies_is_enabled()) {
- // Use janky inaccurate method...
- uint32 elapsed_time = 0;
- uint32 time_remaining = msecs;
- while (time_remaining > 0) {
- // If delay would take us past the next
- // thread exit time, exit the thread immediately
- // (i.e. start burning delay time in the main RetroArch
- // thread as soon as possible...)
- ((LibretroTimerManager *)_timerManager)->checkThread(time_remaining);
- // Check how much delay time remains...
- elapsed_time = getMillis() - start_time;
- if (time_remaining > elapsed_time) {
- time_remaining -= elapsed_time;
- usleep(1000);
- } else {
- time_remaining = 0;
- }
- }
- } else {
- // Use accurate method...
- while (getMillis() < start_time + msecs) {
- ((LibretroTimerManager *)_timerManager)->checkThread();
+ uint32 elapsed_time = 0;
+ uint32 time_remaining = msecs;
+ while (time_remaining > 0) {
+ /* if remaining delay is lower than last amount of time spent on main thread, burn it in emu thread
+ to improve accuracy */
+ if (time_remaining >= ((LibretroTimerManager *)_timerManager)->spentOnMainThread()) {
+ /* If timing inaccuracies is enabled, when remaining delay would take us past the next
+ thread switch time, we switch immediately in order to burn as much as possible delay time in the main RetroArch
+ thread as soon as possible. */
+ if (timing_inaccuracies_is_enabled() && time_remaining >= ((LibretroTimerManager *)_timerManager)->timeToNextSwitch())
+ ((LibretroTimerManager *)_timerManager)->switchThread();
+ else
+ ((LibretroTimerManager *)_timerManager)->checkThread();
+ } else
usleep(1000);
- }
+
+ elapsed_time = getMillis() - start_time;
+ time_remaining = time_remaining > elapsed_time ? time_remaining - elapsed_time : 0;
}
}
More information about the Scummvm-git-logs
mailing list