diff --git a/src/Avalonia.Base/Media/MediaContext.Compositor.cs b/src/Avalonia.Base/Media/MediaContext.Compositor.cs index 32ee1ab932..85f7df2587 100644 --- a/src/Avalonia.Base/Media/MediaContext.Compositor.cs +++ b/src/Avalonia.Base/Media/MediaContext.Compositor.cs @@ -1,4 +1,7 @@ +using System; +using System.Diagnostics; using System.Linq; +using System.Threading; using System.Threading.Tasks; using Avalonia.Platform; @@ -11,16 +14,20 @@ namespace Avalonia.Media; partial class MediaContext { - private bool _scheduleCommitOnLastCompositionBatchCompletion; - /// /// Actually sends the current batch to the compositor and does the required housekeeping /// This is the only place that should be allowed to call Commit /// private CompositionBatch CommitCompositor(Compositor compositor) { - var commit = compositor.Commit(); + // Compositor is allowed to schedule the next batch during Commit procedure if update + // was requested while it was doing an update + // This can e. g. happen if InvalidateVisual is called from Visual.OnRender which is currently separate + // from our FireInvokeOnRenderCallbacks loop, so we clean the commit request flag before rendering so + // it can be set again _requestedCommits.Remove(compositor); + var commit = compositor.Commit(); + _pendingCompositionBatches[compositor] = commit; commit.Processed.ContinueWith(_ => _dispatcher.Post(() => CompositionBatchFinished(compositor, commit), DispatcherPriority.Send), @@ -43,9 +50,8 @@ partial class MediaContext _animationsAreWaitingForComposition = false; // Check if we have uncommited changes - if (_scheduleCommitOnLastCompositionBatchCompletion) + if (_requestedCommits.Count != 0) { - _scheduleCommitOnLastCompositionBatchCompletion = false; if (!CommitCompositorsWithThrottling()) ScheduleRenderForAnimationsIfNeeded(); @@ -69,10 +75,10 @@ partial class MediaContext /// true if there are pending commits in-flight and there will be a "all-done" callback later private bool CommitCompositorsWithThrottling() { + Dispatcher.UIThread.VerifyAccess(); // Check if we are still waiting for previous composition batches if (_pendingCompositionBatches.Count > 0) { - _scheduleCommitOnLastCompositionBatchCompletion = true; // Previous commit isn't handled yet return true; } @@ -84,7 +90,6 @@ partial class MediaContext foreach (var c in _requestedCommits.ToArray()) CommitCompositor(c); - _requestedCommits.Clear(); return true; }