diff --git a/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs b/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs index bf1799bbdc..efcc555159 100644 --- a/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs +++ b/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs @@ -246,22 +246,7 @@ namespace Avalonia.Rendering { try { - IDrawingContextImpl GetContext() - { - if (context != null) - return context; - if ((RenderTarget as IRenderTargetWithCorruptionInfo)?.IsCorrupted == true) - { - RenderTarget.Dispose(); - RenderTarget = null; - } - if (RenderTarget == null) - RenderTarget = ((IRenderRoot)_root).CreateRenderTarget(); - return context = RenderTarget.CreateDrawingContext(this); - - } - - var (scene, updated) = UpdateRenderLayersAndConsumeSceneIfNeeded(GetContext); + var (scene, updated) = UpdateRenderLayersAndConsumeSceneIfNeeded(ref context); using (scene) { @@ -271,9 +256,9 @@ namespace Avalonia.Rendering if (DrawDirtyRects) _dirtyRectsDisplay.Tick(); if (overlay) - RenderOverlay(scene.Item, GetContext()); + RenderOverlay(scene.Item, ref context); if (updated || forceComposite || overlay) - RenderComposite(scene.Item, GetContext()); + RenderComposite(scene.Item, ref context); } } } @@ -291,7 +276,7 @@ namespace Avalonia.Rendering } } - private (IRef scene, bool updated) UpdateRenderLayersAndConsumeSceneIfNeeded(Func contextFactory, + private (IRef scene, bool updated) UpdateRenderLayersAndConsumeSceneIfNeeded(ref IDrawingContextImpl context, bool recursiveCall = false) { IRef sceneRef; @@ -304,7 +289,8 @@ namespace Avalonia.Rendering var scene = sceneRef.Item; if (scene.Generation != _lastSceneId) { - var context = contextFactory(); + EnsureDrawingContext(ref context); + Layers.Update(scene, context); RenderToLayers(scene); @@ -325,7 +311,7 @@ namespace Avalonia.Rendering if (!recursiveCall && Dispatcher.UIThread.CheckAccess() && NeedsUpdate) { UpdateScene(); - var (rs, _) = UpdateRenderLayersAndConsumeSceneIfNeeded(contextFactory, true); + var (rs, _) = UpdateRenderLayersAndConsumeSceneIfNeeded(ref context, true); return (rs, true); } @@ -432,8 +418,10 @@ namespace Avalonia.Rendering } - private void RenderOverlay(Scene scene, IDrawingContextImpl parentContent) + private void RenderOverlay(Scene scene, ref IDrawingContextImpl parentContent) { + EnsureDrawingContext(ref parentContent); + if (DrawDirtyRects) { var overlay = GetOverlay(parentContent, scene.Size, scene.Scaling); @@ -460,8 +448,10 @@ namespace Avalonia.Rendering } } - private void RenderComposite(Scene scene, IDrawingContextImpl context) + private void RenderComposite(Scene scene, ref IDrawingContextImpl context) { + EnsureDrawingContext(ref context); + context.Clear(Colors.Transparent); var clientRect = new Rect(scene.Size); @@ -503,6 +493,27 @@ namespace Avalonia.Rendering } } + private void EnsureDrawingContext(ref IDrawingContextImpl context) + { + if (context != null) + { + return; + } + + if ((RenderTarget as IRenderTargetWithCorruptionInfo)?.IsCorrupted == true) + { + RenderTarget.Dispose(); + RenderTarget = null; + } + + if (RenderTarget == null) + { + RenderTarget = ((IRenderRoot)_root).CreateRenderTarget(); + } + + context = RenderTarget.CreateDrawingContext(this); + } + private void UpdateScene() { Dispatcher.UIThread.VerifyAccess(); diff --git a/src/Avalonia.Visuals/Rendering/RenderLoop.cs b/src/Avalonia.Visuals/Rendering/RenderLoop.cs index 64a8427290..140688f8bc 100644 --- a/src/Avalonia.Visuals/Rendering/RenderLoop.cs +++ b/src/Avalonia.Visuals/Rendering/RenderLoop.cs @@ -91,7 +91,19 @@ namespace Avalonia.Rendering { try { - if (_items.Any(item => item.NeedsUpdate) && + bool needsUpdate = false; + + foreach (IRenderLoopTask item in _items) + { + if (item.NeedsUpdate) + { + needsUpdate = true; + + break; + } + } + + if (needsUpdate && Interlocked.CompareExchange(ref _inUpdate, 1, 0) == 0) { _dispatcher.Post(() =>