From c9752d32d8a96eda332fcc35b56cd67119640443 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Thu, 17 Nov 2016 23:51:38 +0100 Subject: [PATCH] Fixed a few things. - We don't need ConcurrentQueue in renderer - DirtyRects coalescing was wrong - Display number of updated rects for debug until we have dirty rect rendering - Animate 2 items at once in RenderTest --- samples/RenderTest/MainWindow.xaml.cs | 2 +- .../Rendering/DeferredRenderer.cs | 45 +++++++++++-------- src/Avalonia.Visuals/Rendering/DirtyRects.cs | 15 ++++--- .../Rendering/SceneGraph/SceneBuilder.cs | 7 --- 4 files changed, 36 insertions(+), 33 deletions(-) diff --git a/samples/RenderTest/MainWindow.xaml.cs b/samples/RenderTest/MainWindow.xaml.cs index b38415e5a4..9937a732cb 100644 --- a/samples/RenderTest/MainWindow.xaml.cs +++ b/samples/RenderTest/MainWindow.xaml.cs @@ -67,7 +67,7 @@ namespace RenderTest }; var start = Animate.Stopwatch.Elapsed; - var index = i; + var index = i % (Count / 2); var degrees = Animate.Timer .Select(x => (x - start).TotalSeconds) .Where(x => (x % Count) >= index && (x % Count) < index + 1) diff --git a/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs b/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs index 72897021ef..c49bd2acef 100644 --- a/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs +++ b/src/Avalonia.Visuals/Rendering/DeferredRenderer.cs @@ -17,7 +17,7 @@ namespace Avalonia.Rendering private Scene _scene; private IRenderTarget _renderTarget; private List _dirty = new List(); - private ConcurrentQueue _renderQueue = new ConcurrentQueue(); + private DirtyRects _dirtyRects; private bool _needsUpdate; private bool _updateQueued; private bool _rendering; @@ -99,7 +99,7 @@ namespace Avalonia.Rendering } } - private void RenderFps(IDrawingContextImpl context) + private void RenderFps(IDrawingContextImpl context, int count) { var now = _stopwatch.Elapsed; var elapsed = now - _lastFpsUpdate; @@ -115,7 +115,7 @@ namespace Avalonia.Rendering var pt = new Point(40, 40); using ( - var txt = new FormattedText("Frame #" + _totalFrames + " FPS: " + _fps, "Arial", 18, + var txt = new FormattedText($"Frame #{_totalFrames} FPS: {_fps} Updates: {count}", "Arial", 18, FontStyle.Normal, TextAlignment.Left, FontWeight.Normal, @@ -134,31 +134,30 @@ namespace Avalonia.Rendering try { var scene = _scene.Clone(); + var dirtyRects = new DirtyRects(); if (_dirty.Count > 0) { - var dirtyRects = new DirtyRects(); - foreach (var visual in _dirty) { SceneBuilder.Update(scene, visual, dirtyRects); } - foreach (var r in dirtyRects.Coalesce()) - { - _renderQueue.Enqueue(r); - } - - _dirty.Clear(); + dirtyRects.Coalesce(); } else { SceneBuilder.UpdateAll(scene); - _renderQueue.Enqueue(new Rect(_root.ClientSize)); + dirtyRects.Add(new Rect(_root.ClientSize)); } - _scene = scene; + lock (_scene) + { + _scene = scene; + _dirtyRects = dirtyRects; + } + _dirty.Clear(); _needsUpdate = false; _root.Invalidate(new Rect(_root.ClientSize)); } @@ -183,7 +182,16 @@ namespace Avalonia.Rendering _rendering = true; - if (!_renderQueue.IsEmpty) + Scene scene; + DirtyRects dirtyRects; + + lock (_scene) + { + scene = _scene; + dirtyRects = _dirtyRects; + } + + if (dirtyRects != null) { if (_renderTarget == null) { @@ -194,20 +202,21 @@ namespace Avalonia.Rendering { _totalFrames++; + int count = 0; + using (var context = _renderTarget.CreateDrawingContext()) { - Rect rect; - - while (_renderQueue.TryDequeue(out rect)) + foreach (var rect in dirtyRects) { context.PushClip(rect); Render(context, _scene.Root, rect); context.PopClip(); + ++count; } if (DrawFps) { - RenderFps(context); + RenderFps(context, count); } } } diff --git a/src/Avalonia.Visuals/Rendering/DirtyRects.cs b/src/Avalonia.Visuals/Rendering/DirtyRects.cs index 99c8fd4897..8b98f95d40 100644 --- a/src/Avalonia.Visuals/Rendering/DirtyRects.cs +++ b/src/Avalonia.Visuals/Rendering/DirtyRects.cs @@ -7,7 +7,7 @@ using System.Collections.Generic; namespace Avalonia.Rendering { - public class DirtyRects + public class DirtyRects : IEnumerable { private List _rects = new List(); @@ -17,11 +17,11 @@ namespace Avalonia.Rendering { for (var i = 0; i < _rects.Count; ++i) { - var union = _rects[i].Union(rect); + var r = _rects[i].Inflate(1); - if (union != Rect.Empty) + if (r.Intersects(rect)) { - _rects[i] = union; + _rects[i] = r.Union(rect); return; } } @@ -30,7 +30,7 @@ namespace Avalonia.Rendering } } - public IList Coalesce() + public void Coalesce() { for (var i = _rects.Count - 1; i >= 0; --i) { @@ -47,8 +47,9 @@ namespace Avalonia.Rendering } } } - - return _rects; } + + public IEnumerator GetEnumerator() => _rects.GetEnumerator(); + IEnumerator IEnumerable.GetEnumerator() => _rects.GetEnumerator(); } } diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs index 5dc00d87c2..35079f5cb3 100644 --- a/src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs +++ b/src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs @@ -183,13 +183,6 @@ namespace Avalonia.Rendering.SceneGraph return node; } - private static IList Deindex(Scene scene, VisualNode node) - { - var dirty = new DirtyRects(); - Deindex(scene, node, dirty); - return dirty.Coalesce(); - } - private static void Deindex(Scene scene, VisualNode node, DirtyRects dirty) { scene.Remove(node);