Browse Source

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
scenegraph-after-breakage
Steven Kirk 10 years ago
parent
commit
c9752d32d8
  1. 2
      samples/RenderTest/MainWindow.xaml.cs
  2. 45
      src/Avalonia.Visuals/Rendering/DeferredRenderer.cs
  3. 15
      src/Avalonia.Visuals/Rendering/DirtyRects.cs
  4. 7
      src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs

2
samples/RenderTest/MainWindow.xaml.cs

@ -67,7 +67,7 @@ namespace RenderTest
}; };
var start = Animate.Stopwatch.Elapsed; var start = Animate.Stopwatch.Elapsed;
var index = i; var index = i % (Count / 2);
var degrees = Animate.Timer var degrees = Animate.Timer
.Select(x => (x - start).TotalSeconds) .Select(x => (x - start).TotalSeconds)
.Where(x => (x % Count) >= index && (x % Count) < index + 1) .Where(x => (x % Count) >= index && (x % Count) < index + 1)

45
src/Avalonia.Visuals/Rendering/DeferredRenderer.cs

@ -17,7 +17,7 @@ namespace Avalonia.Rendering
private Scene _scene; private Scene _scene;
private IRenderTarget _renderTarget; private IRenderTarget _renderTarget;
private List<IVisual> _dirty = new List<IVisual>(); private List<IVisual> _dirty = new List<IVisual>();
private ConcurrentQueue<Rect> _renderQueue = new ConcurrentQueue<Rect>(); private DirtyRects _dirtyRects;
private bool _needsUpdate; private bool _needsUpdate;
private bool _updateQueued; private bool _updateQueued;
private bool _rendering; 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 now = _stopwatch.Elapsed;
var elapsed = now - _lastFpsUpdate; var elapsed = now - _lastFpsUpdate;
@ -115,7 +115,7 @@ namespace Avalonia.Rendering
var pt = new Point(40, 40); var pt = new Point(40, 40);
using ( 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, FontStyle.Normal,
TextAlignment.Left, TextAlignment.Left,
FontWeight.Normal, FontWeight.Normal,
@ -134,31 +134,30 @@ namespace Avalonia.Rendering
try try
{ {
var scene = _scene.Clone(); var scene = _scene.Clone();
var dirtyRects = new DirtyRects();
if (_dirty.Count > 0) if (_dirty.Count > 0)
{ {
var dirtyRects = new DirtyRects();
foreach (var visual in _dirty) foreach (var visual in _dirty)
{ {
SceneBuilder.Update(scene, visual, dirtyRects); SceneBuilder.Update(scene, visual, dirtyRects);
} }
foreach (var r in dirtyRects.Coalesce()) dirtyRects.Coalesce();
{
_renderQueue.Enqueue(r);
}
_dirty.Clear();
} }
else else
{ {
SceneBuilder.UpdateAll(scene); 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; _needsUpdate = false;
_root.Invalidate(new Rect(_root.ClientSize)); _root.Invalidate(new Rect(_root.ClientSize));
} }
@ -183,7 +182,16 @@ namespace Avalonia.Rendering
_rendering = true; _rendering = true;
if (!_renderQueue.IsEmpty) Scene scene;
DirtyRects dirtyRects;
lock (_scene)
{
scene = _scene;
dirtyRects = _dirtyRects;
}
if (dirtyRects != null)
{ {
if (_renderTarget == null) if (_renderTarget == null)
{ {
@ -194,20 +202,21 @@ namespace Avalonia.Rendering
{ {
_totalFrames++; _totalFrames++;
int count = 0;
using (var context = _renderTarget.CreateDrawingContext()) using (var context = _renderTarget.CreateDrawingContext())
{ {
Rect rect; foreach (var rect in dirtyRects)
while (_renderQueue.TryDequeue(out rect))
{ {
context.PushClip(rect); context.PushClip(rect);
Render(context, _scene.Root, rect); Render(context, _scene.Root, rect);
context.PopClip(); context.PopClip();
++count;
} }
if (DrawFps) if (DrawFps)
{ {
RenderFps(context); RenderFps(context, count);
} }
} }
} }

15
src/Avalonia.Visuals/Rendering/DirtyRects.cs

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

7
src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs

@ -183,13 +183,6 @@ namespace Avalonia.Rendering.SceneGraph
return node; 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) private static void Deindex(Scene scene, VisualNode node, DirtyRects dirty)
{ {
scene.Remove(node); scene.Remove(node);

Loading…
Cancel
Save