[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