浏览代码

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
Steven Kirk 9 年之前
父节点
当前提交
c9752d32d8

+ 1 - 1
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)

+ 27 - 18
src/Avalonia.Visuals/Rendering/DeferredRenderer.cs

@@ -17,7 +17,7 @@ namespace Avalonia.Rendering
         private Scene _scene;
         private IRenderTarget _renderTarget;
         private List<IVisual> _dirty = new List<IVisual>();
-        private ConcurrentQueue<Rect> _renderQueue = new ConcurrentQueue<Rect>();
+        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);
                         }
                     }
                 }

+ 8 - 7
src/Avalonia.Visuals/Rendering/DirtyRects.cs

@@ -7,7 +7,7 @@ using System.Collections.Generic;
 
 namespace Avalonia.Rendering
 {
-    public class DirtyRects
+    public class DirtyRects : IEnumerable<Rect>
     {
         private List<Rect> _rects = new List<Rect>();
 
@@ -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<Rect> Coalesce()
+        public void Coalesce()
         {
             for (var i = _rects.Count - 1; i >= 0; --i)
             {
@@ -47,8 +47,9 @@ namespace Avalonia.Rendering
                     }
                 }
             }
-
-            return _rects;
         }
+
+        public IEnumerator<Rect> GetEnumerator() => _rects.GetEnumerator();
+        IEnumerator IEnumerable.GetEnumerator() => _rects.GetEnumerator();
     }
 }

+ 0 - 7
src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs

@@ -183,13 +183,6 @@ namespace Avalonia.Rendering.SceneGraph
             return node;
         }
 
-        private static IList<Rect> 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);