[Scummvm-git-logs] scummvm master -> f0211ad3d072bde418b221bf7e0a14ad6842b283
spleen1981
noreply at scummvm.org
Sat Mar 25 01:49:33 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:
f0211ad3d0 LIBRETRO: add consecutive updateScreen short loop
Commit: f0211ad3d072bde418b221bf7e0a14ad6842b283
https://github.com/scummvm/scummvm/commit/f0211ad3d072bde418b221bf7e0a14ad6842b283
Author: Giovanni Cascione (ing.cascione at gmail.com)
Date: 2023-03-25T02:49:17+01:00
Commit Message:
LIBRETRO: add consecutive updateScreen short loop
Changed paths:
backends/platform/libretro/include/os.h
backends/platform/libretro/src/libretro-os.cpp
backends/platform/libretro/src/libretro.cpp
diff --git a/backends/platform/libretro/include/os.h b/backends/platform/libretro/include/os.h
index 87acb8694cb..32a53deef81 100644
--- a/backends/platform/libretro/include/os.h
+++ b/backends/platform/libretro/include/os.h
@@ -84,4 +84,6 @@ void retroSetSaveDir(const char *aPath);
void retroKeyEvent(bool down, unsigned keycode, uint32_t character, uint16_t key_modifiers);
+uint8 getThreadSwitchCaller(void);
+
#endif
diff --git a/backends/platform/libretro/src/libretro-os.cpp b/backends/platform/libretro/src/libretro-os.cpp
index a9d05691c58..03364cfdcc9 100644
--- a/backends/platform/libretro/src/libretro-os.cpp
+++ b/backends/platform/libretro/src/libretro-os.cpp
@@ -498,12 +498,12 @@ public:
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.
+ /* In a series of consecutive updateScreen calls, additionally switch directly to main thread when
+ (and if) first copyRectToScreen is called between two updateScreen. This reduces audio 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();
+ retro_switch_to_main_thread();
_threadSwitchCaller |= THREAD_SWITCH_RECT;
}
}
@@ -545,10 +545,10 @@ public:
}
}
- /* Switch to main thread in case of consecutive updateScreen, to avoid losing frames.
+ /* Switch directly 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();
+ retro_switch_to_main_thread();
_threadSwitchCaller &= ~THREAD_SWITCH_RECT;
} else {
_threadSwitchCaller = THREAD_SWITCH_UPDATE;
@@ -642,18 +642,19 @@ public:
}
void retroCheckThread(uint32 offset = 0) {
- /* 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. */
+ /* 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;
- } else if (_threadSwitchCaller & THREAD_SWITCH_UPDATE){
- retro_switch_to_main_thread();
}
((DefaultTimerManager *)_timerManager)->handler();
}
+ uint8 getThreadSwitchCaller(){
+ return _threadSwitchCaller;
+ }
+
virtual bool pollEvent(Common::Event &event) {
_threadSwitchCaller = THREAD_SWITCH_POLL;
retroCheckThread();
@@ -1323,3 +1324,7 @@ void retroKeyEvent(bool down, unsigned keycode, uint32_t character, uint16_t key
void retroReset() {
dynamic_cast<OSystem_RETRO *>(g_system)->Reset();
}
+
+uint8 getThreadSwitchCaller(){
+ return dynamic_cast<OSystem_RETRO *>(g_system)->getThreadSwitchCaller();
+}
diff --git a/backends/platform/libretro/src/libretro.cpp b/backends/platform/libretro/src/libretro.cpp
index 4e5f8d54355..3055f34b484 100644
--- a/backends/platform/libretro/src/libretro.cpp
+++ b/backends/platform/libretro/src/libretro.cpp
@@ -596,60 +596,71 @@ void retro_run(void) {
poll_cb();
retroProcessMouse(input_cb, retro_device, gampad_cursor_speed, gamepad_acceleration_time, analog_response_is_quadratic, analog_deadzone, mouse_speed);
- if (frameskip_type && can_dupe) {
- if (audio_status & (AUDIO_STATUS_BUFFER_SUPPORT | AUDIO_STATUS_BUFFER_ACTIVE)){
- switch (frameskip_type) {
- case 1:
+ /* ScummVM is not based on fixed framerate like libretro, and engines/scripts
+ can call multiple screen updates between two retro_run calls. Hence if consecutive screen updates
+ are detected we will loop within the same retro_run call until next pollEvent or
+ delayMillis call in ScummVM thread.
+ */
+ do {
+ if (frameskip_type && can_dupe) {
+ if (audio_status & (AUDIO_STATUS_BUFFER_SUPPORT | AUDIO_STATUS_BUFFER_ACTIVE)){
+ switch (frameskip_type) {
+ case 1:
+ skip_frame = !(current_frame % frameskip_no == 0);
+ break;
+ case 2:
+ skip_frame = (audio_status & AUDIO_STATUS_BUFFER_UNDERRUN);
+ break;
+ case 3:
+ skip_frame = (retro_audio_buff_occupancy < frameskip_threshold);
+ break;
+ }
+ } else
skip_frame = !(current_frame % frameskip_no == 0);
- break;
- case 2:
- skip_frame = (audio_status & AUDIO_STATUS_BUFFER_UNDERRUN);
- break;
- case 3:
- skip_frame = (retro_audio_buff_occupancy < frameskip_threshold);
- break;
- }
- } else
- skip_frame = !(current_frame % frameskip_no == 0);
- }
- /* Upload audio */
- size_t count = 0;
- if (audio_video_enable & 2) {
- count = ((Audio::MixerImpl *)g_system->getMixer())->mixCallback((byte *) sound_buffer, samples_per_frame_buffer_size);
- }
- audio_status = count ? (audio_status & ~AUDIO_STATUS_MUTE) : (audio_status | AUDIO_STATUS_MUTE);
-
- /* No frame skipping if there is no incoming audio (e.g. GUI) */
- skip_frame = skip_frame && ! (audio_status & AUDIO_STATUS_MUTE);
-
- if ((!skip_frame && frameskip_counter) || frameskip_counter >= FRAMESKIP_MAX) {
- if (frameskip_counter)
- log_cb(RETRO_LOG_WARN, "%d frame(s) skipped\n",frameskip_counter);
- skip_frame = false;
- frameskip_counter = 0;
- } else if (skip_frame)
- frameskip_counter++;
-
- if ((audio_video_enable & 1) && !skip_frame) {
- const Graphics::Surface &screen = getScreen();
- video_cb(screen.getPixels(), screen.w, screen.h, screen.pitch);
- } else {
- video_cb(NULL, 0, 0, 0); // Set to NULL to skip frame rendering
- }
+ }
+ /* Upload audio */
+ size_t count = 0;
+ if (audio_video_enable & 2) {
+ count = ((Audio::MixerImpl *)g_system->getMixer())->mixCallback((byte *) sound_buffer, samples_per_frame_buffer_size);
+ }
+ audio_status = count ? (audio_status & ~AUDIO_STATUS_MUTE) : (audio_status | AUDIO_STATUS_MUTE);
+
+ /* No frame skipping if there is no incoming audio (e.g. GUI) */
+ skip_frame = skip_frame && ! (audio_status & AUDIO_STATUS_MUTE);
+
+ if ((!skip_frame && frameskip_counter) || frameskip_counter >= FRAMESKIP_MAX) {
+ if (frameskip_counter)
+ log_cb(RETRO_LOG_WARN, "%d frame(s) skipped\n",frameskip_counter);
+ skip_frame = false;
+ frameskip_counter = 0;
+ } else if (skip_frame)
+ frameskip_counter++;
+
+ if ((audio_video_enable & 1) && !skip_frame) {
+ const Graphics::Surface &screen = getScreen();
+ video_cb(screen.getPixels(), screen.w, screen.h, screen.pitch);
+ } else {
+ video_cb(NULL, 0, 0, 0); // Set to NULL to skip frame rendering
+ }
#if defined(_3DS)
- /* Hack: 3DS will produce static noise
- * unless we manually send a zeroed
- * audio buffer when no samples are
- * available (i.e. when the overlay
- * is shown) */
- if (audio_status & AUDIO_STATUS_MUTE) {
- audio_buffer_init(SAMPLE_RATE, (uint16) frame_rate);
- }
+ /* Hack: 3DS will produce static noise
+ * unless we manually send a zeroed
+ * audio buffer when no samples are
+ * available (i.e. when the overlay
+ * is shown) */
+ if (audio_status & AUDIO_STATUS_MUTE) {
+ audio_buffer_init(SAMPLE_RATE, (uint16) frame_rate);
+ }
#endif
- audio_batch_cb((audio_status & AUDIO_STATUS_MUTE) ? NULL : (int16_t *) sound_buffer, count); // Set to NULL to skip sound rendering
+ audio_batch_cb((audio_status & AUDIO_STATUS_MUTE) ? NULL : (int16_t *) sound_buffer, count); // Set to NULL to skip sound rendering
+
+ current_frame++;
+
+ if (getThreadSwitchCaller() & THREAD_SWITCH_UPDATE)
+ retro_switch_to_emu_thread();
- current_frame++;
+ } while (getThreadSwitchCaller() & THREAD_SWITCH_UPDATE);
}
bool updated = false;
More information about the Scummvm-git-logs
mailing list