[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