Skip to content

Commit 9833352

Browse files
authored
Merge pull request #356 from winnerspiros/fix/surface-event-before-setformat
fix: set surface event before SetFormat to prevent draw thread deadlock
2 parents 947ceab + fb435de commit 9833352

1 file changed

Lines changed: 9 additions & 11 deletions

File tree

osu.Android/OsuGameActivity.cs

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -906,11 +906,6 @@ public void SurfaceChanged(ISurfaceHolder holder, global::Android.Graphics.Forma
906906
// to send a heartbeat (especially during startup when the runtime is under
907907
// heavy load), and the native watchdog (10s default) would fire, killing the
908908
// process and producing a black screen.
909-
//
910-
// Calling Heartbeat() here resets the watchdog timer from the UI thread,
911-
// giving SetFormat time to complete without triggering a false positive.
912-
// The native watchdog checks g_lastHeartbeatMonotonicSec which is updated
913-
// by a simple atomic store — safe to call from any thread.
914909
try
915910
{
916911
NativeWatchdog.Heartbeat();
@@ -921,6 +916,8 @@ public void SurfaceChanged(ISurfaceHolder holder, global::Android.Graphics.Forma
921916
Debug.WriteLine($"[osu!] NativeWatchdog.Heartbeat failed (non-fatal): {e.Message}");
922917
}
923918

919+
Debug.WriteLine("[osu!] Native surface format change requested (RGB565→RGBA8888)");
920+
924921
try
925922
{
926923
holder.SetFormat(global::Android.Graphics.Format.Rgba8888);
@@ -930,12 +927,13 @@ public void SurfaceChanged(ISurfaceHolder holder, global::Android.Graphics.Forma
930927
Debug.WriteLine($"[osu!] Failed to request RGBA8888 format change for Vulkan: {e.Message}");
931928
}
932929

933-
Debug.WriteLine("[osu!] Native surface format change requested (RGB565→RGBA8888)");
934-
935-
// Reset the surface event so GetSurfaceGlobalRef() does NOT unblock with the
936-
// old (about-to-be-invalidated) surface handle. The event will be re-set when
937-
// SurfaceChanged fires again for the new RGBA8888 surface.
938-
surfaceEvent.Reset();
930+
// After SetFormat returns, the synchronous SurfaceDestroyed→SurfaceCreated→SurfaceChanged
931+
// cycle has already completed and surfaceGlobalRef points to the new RGBA8888 surface.
932+
// Set the event now so GetSurfaceGlobalRef() returns the new valid surface.
933+
// This preserves the invariant that surfaceEvent is only set when surfaceGlobalRef
934+
// points to a safe-to-render surface, while the watchdog heartbeat above prevents
935+
// a false positive during the blocking SetFormat call.
936+
surfaceEvent.Set();
939937

940938
return;
941939
}

0 commit comments

Comments
 (0)