Browse Source

Fixed rare soft-"freezes" with OnRender(c) { ...; InvalidateVisual(); } pattern (#18901)

release/11.3.1
Nikita Tsukanov 9 months ago
committed by Julien Lebosquain
parent
commit
90416f3639
  1. 19
      src/Avalonia.Base/Media/MediaContext.Compositor.cs

19
src/Avalonia.Base/Media/MediaContext.Compositor.cs

@ -1,4 +1,7 @@
using System;
using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Avalonia.Platform; using Avalonia.Platform;
@ -11,16 +14,20 @@ namespace Avalonia.Media;
partial class MediaContext partial class MediaContext
{ {
private bool _scheduleCommitOnLastCompositionBatchCompletion;
/// <summary> /// <summary>
/// Actually sends the current batch to the compositor and does the required housekeeping /// 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 /// This is the only place that should be allowed to call Commit
/// </summary> /// </summary>
private CompositionBatch CommitCompositor(Compositor compositor) 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); _requestedCommits.Remove(compositor);
var commit = compositor.Commit();
_pendingCompositionBatches[compositor] = commit; _pendingCompositionBatches[compositor] = commit;
commit.Processed.ContinueWith(_ => commit.Processed.ContinueWith(_ =>
_dispatcher.Post(() => CompositionBatchFinished(compositor, commit), DispatcherPriority.Send), _dispatcher.Post(() => CompositionBatchFinished(compositor, commit), DispatcherPriority.Send),
@ -43,9 +50,8 @@ partial class MediaContext
_animationsAreWaitingForComposition = false; _animationsAreWaitingForComposition = false;
// Check if we have uncommited changes // Check if we have uncommited changes
if (_scheduleCommitOnLastCompositionBatchCompletion) if (_requestedCommits.Count != 0)
{ {
_scheduleCommitOnLastCompositionBatchCompletion = false;
if (!CommitCompositorsWithThrottling()) if (!CommitCompositorsWithThrottling())
ScheduleRenderForAnimationsIfNeeded(); ScheduleRenderForAnimationsIfNeeded();
@ -69,10 +75,10 @@ partial class MediaContext
/// <returns>true if there are pending commits in-flight and there will be a "all-done" callback later</returns> /// <returns>true if there are pending commits in-flight and there will be a "all-done" callback later</returns>
private bool CommitCompositorsWithThrottling() private bool CommitCompositorsWithThrottling()
{ {
Dispatcher.UIThread.VerifyAccess();
// Check if we are still waiting for previous composition batches // Check if we are still waiting for previous composition batches
if (_pendingCompositionBatches.Count > 0) if (_pendingCompositionBatches.Count > 0)
{ {
_scheduleCommitOnLastCompositionBatchCompletion = true;
// Previous commit isn't handled yet // Previous commit isn't handled yet
return true; return true;
} }
@ -84,7 +90,6 @@ partial class MediaContext
foreach (var c in _requestedCommits.ToArray()) foreach (var c in _requestedCommits.ToArray())
CommitCompositor(c); CommitCompositor(c);
_requestedCommits.Clear();
return true; return true;
} }

Loading…
Cancel
Save