Browse Source

Made some classes internal and added docs.

scenegraph-after-breakage
Steven Kirk 9 years ago
parent
commit
f0e398960d
  1. 33
      src/Avalonia.Visuals/Rendering/DirtyRects.cs
  2. 31
      src/Avalonia.Visuals/Rendering/DirtyVisuals.cs
  3. 30
      src/Avalonia.Visuals/Rendering/DisplayDirtyRect.cs
  4. 23
      src/Avalonia.Visuals/Rendering/DisplayDirtyRects.cs
  5. 10
      src/Avalonia.Visuals/Rendering/SceneGraph/SceneLayer.cs

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

@ -7,12 +7,28 @@ using System.Collections.Generic;
namespace Avalonia.Rendering
{
public class DirtyRects : IEnumerable<Rect>
/// <summary>
/// Tracks dirty rectangles.
/// </summary>
internal class DirtyRects : IEnumerable<Rect>
{
private List<Rect> _rects = new List<Rect>();
public bool IsEmpty => _rects.Count == 0;
/// <summary>
/// Adds a dirty rectangle, extending an existing dirty rectangle if it intersects.
/// </summary>
/// <param name="rect">The dirt rectangle.</param>
/// <remarks>
/// We probably want to do this more intellegently because:
/// - Adding e.g. the top left quarter of a scene and the bottom left quarter of a scene
/// will cause the whole scene to be invalidated if they overlap by a single pixel
/// - Adding two adjacent rectangles that don't overlap will not cause them to be
/// coalesced
/// - It only coaleces the first intersecting rectangle found - one needs to
/// call <see cref="Coalesce"/> at the end of the draw cycle to coalesce the rest.
/// </remarks>
public void Add(Rect rect)
{
if (!rect.IsEmpty)
@ -32,6 +48,12 @@ namespace Avalonia.Rendering
}
}
/// <summary>
/// Works around our flimsy dirt-rect coalescing algorithm.
/// </summary>
/// <remarks>
/// See the comments in <see cref="Add(Rect)"/>.
/// </remarks>
public void Coalesce()
{
for (var i = _rects.Count - 1; i >= 0; --i)
@ -51,7 +73,16 @@ namespace Avalonia.Rendering
}
}
/// <summary>
/// Gets the dirty rectangles.
/// </summary>
/// <returns>A collection of dirty rectangles</returns>
public IEnumerator<Rect> GetEnumerator() => _rects.GetEnumerator();
/// <summary>
/// Gets the dirty rectangles.
/// </summary>
/// <returns>A collection of dirty rectangles</returns>
IEnumerator IEnumerable.GetEnumerator() => _rects.GetEnumerator();
}
}

31
src/Avalonia.Visuals/Rendering/DirtyVisuals.cs

@ -5,13 +5,28 @@ using Avalonia.VisualTree;
namespace Avalonia.Rendering
{
/// <summary>
/// Stores a list of dirty visuals for an <see cref="IRenderer"/>.
/// </summary>
/// <remarks>
/// This class stores the dirty visuals for a scene, ordered by their distance to the root
/// visual. TODO: We probably want to put an upper limit on the number of visuals that can be
/// stored and if we reach that limit, assume all visuals are dirty.
/// </remarks>
internal class DirtyVisuals : IEnumerable<IVisual>
{
private SortedDictionary<int, List<IVisual>> _inner = new SortedDictionary<int, List<IVisual>>();
private Dictionary<IVisual, int> _index = new Dictionary<IVisual, int>();
/// <summary>
/// Gets the number of dirty visuals.
/// </summary>
public int Count => _index.Count;
/// <summary>
/// Adds a visual to the dirty list.
/// </summary>
/// <param name="visual">The dirty visual.</param>
public void Add(IVisual visual)
{
var distance = visual.CalculateDistanceFromAncestor(visual.VisualRoot);
@ -40,12 +55,20 @@ namespace Avalonia.Rendering
_index.Add(visual, distance);
}
/// <summary>
/// Clears the list.
/// </summary>
public void Clear()
{
_inner.Clear();
_index.Clear();
}
/// <summary>
/// Removes a visual from the dirty list.
/// </summary>
/// <param name="visual">The visual.</param>
/// <returns>True if the visual was present in the list; otherwise false.</returns>
public bool Remove(IVisual visual)
{
int distance;
@ -60,6 +83,10 @@ namespace Avalonia.Rendering
return false;
}
/// <summary>
/// Gets the dirty visuals, in ascending order of distance to their root.
/// </summary>
/// <returns>A collection of visuals.</returns>
public IEnumerator<IVisual> GetEnumerator()
{
foreach (var i in _inner)
@ -71,6 +98,10 @@ namespace Avalonia.Rendering
}
}
/// <summary>
/// Gets the dirty visuals, in ascending order of distance to their root.
/// </summary>
/// <returns>A collection of visuals.</returns>
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}

30
src/Avalonia.Visuals/Rendering/DisplayDirtyRect.cs

@ -2,23 +2,47 @@
namespace Avalonia.Rendering
{
public class DisplayDirtyRect
/// <summary>
/// Holds the state for a dirty rect rendered when <see cref="IRenderer.DrawDirtyRects"/> is set.
/// </summary>
internal class DisplayDirtyRect
{
public static readonly TimeSpan TimeToLive = TimeSpan.FromMilliseconds(250);
/// <summary>
/// Initializes a new instance of the <see cref="DisplayDirtyRect"/> class.
/// </summary>
/// <param name="rect">The dirt rect.</param>
public DisplayDirtyRect(Rect rect)
{
Rect = rect;
ResetAge();
ResetLifetime();
}
/// <summary>
/// Gets the bounds of the dirty rectangle.
/// </summary>
public Rect Rect { get; }
/// <summary>
/// Gets the time at which the rectangle was made dirty.
/// </summary>
public DateTimeOffset Born { get; private set; }
/// <summary>
/// Gets the time at which the rectagle should no longer be displayed.
/// </summary>
public DateTimeOffset Dies { get; private set; }
/// <summary>
/// Gets the opacity at which to display the dirty rectangle.
/// </summary>
public double Opacity => (Dies - DateTimeOffset.UtcNow).TotalMilliseconds / TimeToLive.TotalMilliseconds;
public void ResetAge()
/// <summary>
/// Resets the rectangle's lifetime.
/// </summary>
public void ResetLifetime()
{
Born = DateTimeOffset.UtcNow;
Dies = Born + TimeToLive;

23
src/Avalonia.Visuals/Rendering/DisplayDirtyRects.cs

@ -4,17 +4,24 @@ using System.Collections.Generic;
namespace Avalonia.Rendering
{
public class DisplayDirtyRects : IEnumerable<DisplayDirtyRect>
/// <summary>
/// Holds a collection of <see cref="DisplayDirtyRect"/> objects and manages their aging.
/// </summary>
internal class DisplayDirtyRects : IEnumerable<DisplayDirtyRect>
{
private List<DisplayDirtyRect> _inner = new List<DisplayDirtyRect>();
/// <summary>
/// Adds new new dirty rect to the collection.
/// </summary>
/// <param name="rect"></param>
public void Add(Rect rect)
{
foreach (var r in _inner)
{
if (r.Rect == rect)
{
r.ResetAge();
r.ResetLifetime();
return;
}
}
@ -22,6 +29,9 @@ namespace Avalonia.Rendering
_inner.Add(new DisplayDirtyRect(rect));
}
/// <summary>
/// Removes dirty rects one they are no longer active.
/// </summary>
public void Tick()
{
var now = DateTimeOffset.UtcNow;
@ -37,7 +47,16 @@ namespace Avalonia.Rendering
}
}
/// <summary>
/// Gets the dirty rects.
/// </summary>
/// <returns>A collection of <see cref="DisplayDirtyRect"/> objects.</returns>
public IEnumerator<DisplayDirtyRect> GetEnumerator() => _inner.GetEnumerator();
/// <summary>
/// Gets the dirty rects.
/// </summary>
/// <returns>A collection of <see cref="DisplayDirtyRect"/> objects.</returns>
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}

10
src/Avalonia.Visuals/Rendering/SceneGraph/SceneLayer.cs

@ -42,11 +42,6 @@ namespace Avalonia.Rendering.SceneGraph
/// </summary>
public IVisual LayerRoot { get; }
/// <summary>
/// Gets the dirty rectangles for the layer.
/// </summary>
public DirtyRects Dirty { get; }
/// <summary>
/// Gets the distance of the layer root from the root of the scene.
/// </summary>
@ -71,5 +66,10 @@ namespace Avalonia.Rendering.SceneGraph
/// Gets the layer's geometry clip.
/// </summary>
public IGeometryImpl GeometryClip { get; set; }
/// <summary>
/// Gets the dirty rectangles for the layer.
/// </summary>
internal DirtyRects Dirty { get; }
}
}

Loading…
Cancel
Save