From 0f997e7a1d0872bc8be6478233d42785e70c5b9c Mon Sep 17 00:00:00 2001 From: walterlv Date: Tue, 3 Sep 2024 09:59:08 +0800 Subject: [PATCH] =?UTF-8?q?Adds=20an=20option=20that=20enables=20the=20ren?= =?UTF-8?q?dering=20runs=20instantly.=20Before=20this=20commit:=20UI=20->?= =?UTF-8?q?=20render=20->=20UI=20->=20render=20=EF=BC=88then=20it=20render?= =?UTF-8?q?ed)=20After=20this=20commit:=20UI=20->=20render=20(then=20it=20?= =?UTF-8?q?rendered)=20Yes,=20It=20reduced=20rendering=20delay=20at=20leas?= =?UTF-8?q?t=20one=20frame.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Avalonia.Base/Media/MediaContext.Compositor.cs | 13 ++++++++++--- src/Avalonia.Base/Media/MediaContext.cs | 8 +++++--- .../Rendering/Composition/Compositor.cs | 4 +++- src/Avalonia.Base/Threading/DispatcherOptions.cs | 6 ++++++ 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/Avalonia.Base/Media/MediaContext.Compositor.cs b/src/Avalonia.Base/Media/MediaContext.Compositor.cs index ff8c2b090ef..2ac395ca766 100644 --- a/src/Avalonia.Base/Media/MediaContext.Compositor.cs +++ b/src/Avalonia.Base/Media/MediaContext.Compositor.cs @@ -21,9 +21,16 @@ private CompositionBatch CommitCompositor(Compositor compositor) var commit = compositor.Commit(); _requestedCommits.Remove(compositor); _pendingCompositionBatches[compositor] = commit; - commit.Processed.ContinueWith(_ => - _dispatcher.Post(() => CompositionBatchFinished(compositor, commit), DispatcherPriority.Send), - TaskContinuationOptions.ExecuteSynchronously); + if (_dispatcherOptions.InstantRendering) + { + CompositionBatchFinished(compositor, commit); + } + else + { + commit.Processed.ContinueWith(_ => + _dispatcher.Post(() => CompositionBatchFinished(compositor, commit), DispatcherPriority.Send), + TaskContinuationOptions.ExecuteSynchronously); + } return commit; } diff --git a/src/Avalonia.Base/Media/MediaContext.cs b/src/Avalonia.Base/Media/MediaContext.cs index 9747d01c7ea..7ca129f64d4 100644 --- a/src/Avalonia.Base/Media/MediaContext.cs +++ b/src/Avalonia.Base/Media/MediaContext.cs @@ -26,6 +26,7 @@ private record TopLevelInfo(Compositor Compositor, CompositingRenderer Renderer private List? _invokeOnRenderCallbacks; private readonly Stack> _invokeOnRenderCallbackListPool = new(); + private readonly DispatcherOptions _dispatcherOptions; private readonly DispatcherTimer _animationsTimer = new(DispatcherPriority.Render) { @@ -37,13 +38,14 @@ private record TopLevelInfo(Compositor Compositor, CompositingRenderer Renderer private readonly Dictionary _topLevels = new(); - private MediaContext(Dispatcher dispatcher, TimeSpan inputStarvationTimeout) + private MediaContext(Dispatcher dispatcher, DispatcherOptions dispatcherOptions) { _render = Render; _inputMarkerHandler = InputMarkerHandler; _clock = new(this); _dispatcher = dispatcher; - MaxSecondsWithoutInput = inputStarvationTimeout.TotalSeconds; + _dispatcherOptions = dispatcherOptions; + MaxSecondsWithoutInput = dispatcherOptions.InputStarvationTimeout.TotalSeconds; _animationsTimer.Tick += (_, _) => { _animationsTimer.Stop(); @@ -62,7 +64,7 @@ public static MediaContext Instance if (context == null) { var opts = AvaloniaLocator.Current.GetService() ?? new(); - context = new MediaContext(Dispatcher.UIThread, opts.InputStarvationTimeout); + context = new MediaContext(Dispatcher.UIThread, opts); AvaloniaLocator.CurrentMutable.Bind().ToConstant(context); } diff --git a/src/Avalonia.Base/Rendering/Composition/Compositor.cs b/src/Avalonia.Base/Rendering/Composition/Compositor.cs index 6b7a2ab081d..967a76f1b23 100644 --- a/src/Avalonia.Base/Rendering/Composition/Compositor.cs +++ b/src/Avalonia.Base/Rendering/Composition/Compositor.cs @@ -38,6 +38,7 @@ public partial class Compositor private readonly List _pendingServerCompositorPostTargetJobs = new(); private DiagnosticTextRenderer? _diagnosticTextRenderer; private readonly Action _triggerCommitRequested; + private readonly DispatcherOptions _dispatcherOptions; internal IEasing DefaultEasing { get; } @@ -89,6 +90,7 @@ internal Compositor(IRenderLoop loop, IPlatformGraphics? gpu, _batchObjectPool = new(reclaimBuffersImmediately); _server = new ServerCompositor(loop, gpu, options, _batchObjectPool, _batchMemoryPool); _triggerCommitRequested = () => scheduler.CommitRequested(this); + _dispatcherOptions = AvaloniaLocator.Current.GetService() ?? new(); DefaultEasing = new SplineEasing(new KeySpline(0.25, 0.1, 0.25, 1.0)); } @@ -110,7 +112,7 @@ public CompositionBatch RequestCompositionBatchCommitAsync() { _nextCommit = new (); var pending = _pendingBatch; - if (pending != null) + if (pending != null && !_dispatcherOptions.InstantRendering) pending.Processed.ContinueWith( _ => Dispatcher.Post(_triggerCommitRequested, DispatcherPriority.Send), TaskContinuationOptions.ExecuteSynchronously); diff --git a/src/Avalonia.Base/Threading/DispatcherOptions.cs b/src/Avalonia.Base/Threading/DispatcherOptions.cs index e12497a5982..a92e6491ffd 100644 --- a/src/Avalonia.Base/Threading/DispatcherOptions.cs +++ b/src/Avalonia.Base/Threading/DispatcherOptions.cs @@ -18,4 +18,10 @@ public class DispatcherOptions /// the same thread as rendering. /// public TimeSpan InputStarvationTimeout { get; set; } = TimeSpan.FromSeconds(1); + + /// + /// Gets or sets a value indicating whether rendering should be performed synchronously.
+ /// Otherwise, rendering will be invoked from UI thread to the render thread, back to the UI thread and then back to the render thread. + ///
+ public bool InstantRendering { get; set; } = false; }