committed by
Dan Walmsley
55 changed files with 90 additions and 422 deletions
@ -1,7 +0,0 @@ |
|||
namespace Avalonia.Platform |
|||
{ |
|||
public interface IModuleEnvironmentChecker |
|||
{ |
|||
bool IsCompatible { get; } |
|||
} |
|||
} |
|||
@ -1,87 +0,0 @@ |
|||
using System.Collections; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Avalonia.Rendering |
|||
{ |
|||
/// <summary>
|
|||
/// Tracks dirty rectangles.
|
|||
/// </summary>
|
|||
internal class DirtyRects : IEnumerable<Rect> |
|||
{ |
|||
private List<Rect> _rects = new List<Rect>(); |
|||
|
|||
/// <summary>
|
|||
/// Gets a value indicating whether the collection of dirty rectangles is empty.
|
|||
/// </summary>
|
|||
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 intelligently 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 coalesces 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.Width != 0 || rect.Height != 0) |
|||
{ |
|||
for (var i = 0; i < _rects.Count; ++i) |
|||
{ |
|||
var r = _rects[i]; |
|||
|
|||
if (r.Intersects(rect)) |
|||
{ |
|||
_rects[i] = r.Union(rect); |
|||
return; |
|||
} |
|||
} |
|||
|
|||
_rects.Add(rect); |
|||
} |
|||
} |
|||
|
|||
/// <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) |
|||
{ |
|||
var a = _rects[i]; |
|||
|
|||
for (var j = 0; j < i; ++j) |
|||
{ |
|||
var b = _rects[j]; |
|||
|
|||
if (i < _rects.Count && a.Intersects(b)) |
|||
{ |
|||
_rects[i] = _rects[i].Union(b); |
|||
_rects.RemoveAt(i); |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <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(); |
|||
} |
|||
} |
|||
@ -1,104 +0,0 @@ |
|||
using System; |
|||
using System.Collections; |
|||
using System.Collections.Generic; |
|||
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<Visual> |
|||
{ |
|||
private SortedDictionary<int, List<Visual>> _inner = new SortedDictionary<int, List<Visual>>(); |
|||
private Dictionary<Visual, int> _index = new Dictionary<Visual, int>(); |
|||
private int _enumerating; |
|||
|
|||
/// <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(Visual visual) |
|||
{ |
|||
if (_enumerating > 0) |
|||
{ |
|||
throw new InvalidOperationException("Visual was invalidated during a render pass"); |
|||
} |
|||
|
|||
var distance = visual.CalculateDistanceFromAncestor((Visual?)visual.GetVisualRoot()); |
|||
|
|||
if (_index.TryGetValue(visual, out var existingDistance)) |
|||
{ |
|||
if (distance == existingDistance) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
_inner[existingDistance].Remove(visual); |
|||
_index.Remove(visual); |
|||
} |
|||
|
|||
if (!_inner.TryGetValue(distance, out var list)) |
|||
{ |
|||
list = new List<Visual>(); |
|||
_inner.Add(distance, list); |
|||
} |
|||
|
|||
list.Add(visual); |
|||
_index.Add(visual, distance); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Clears the list.
|
|||
/// </summary>
|
|||
public void Clear() |
|||
{ |
|||
if (_enumerating > 0) |
|||
{ |
|||
throw new InvalidOperationException("Cannot clear while enumerating"); |
|||
} |
|||
|
|||
_inner.Clear(); |
|||
_index.Clear(); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the dirty visuals, in ascending order of distance to their root.
|
|||
/// </summary>
|
|||
/// <returns>A collection of visuals.</returns>
|
|||
public IEnumerator<Visual> GetEnumerator() |
|||
{ |
|||
_enumerating++; |
|||
try |
|||
{ |
|||
foreach (var i in _inner) |
|||
{ |
|||
foreach (var j in i.Value) |
|||
{ |
|||
yield return j; |
|||
} |
|||
} |
|||
} |
|||
finally |
|||
{ |
|||
_enumerating--; |
|||
} |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Gets the dirty visuals, in ascending order of distance to their root.
|
|||
/// </summary>
|
|||
/// <returns>A collection of visuals.</returns>
|
|||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); |
|||
} |
|||
} |
|||
@ -1,51 +0,0 @@ |
|||
using System; |
|||
|
|||
namespace Avalonia.Rendering |
|||
{ |
|||
/// <summary>
|
|||
/// Holds the state for a dirty rect rendered when <see cref="IRenderer.SceneInvalidated"/> 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; |
|||
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 rectangle 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; |
|||
|
|||
/// <summary>
|
|||
/// Resets the rectangle's lifetime.
|
|||
/// </summary>
|
|||
public void ResetLifetime() |
|||
{ |
|||
Born = DateTimeOffset.UtcNow; |
|||
Dies = Born + TimeToLive; |
|||
} |
|||
} |
|||
} |
|||
@ -1,62 +0,0 @@ |
|||
using System; |
|||
using System.Collections; |
|||
using System.Collections.Generic; |
|||
|
|||
namespace Avalonia.Rendering |
|||
{ |
|||
/// <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.ResetLifetime(); |
|||
return; |
|||
} |
|||
} |
|||
|
|||
_inner.Add(new DisplayDirtyRect(rect)); |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Removes dirty rects one they are no longer active.
|
|||
/// </summary>
|
|||
public void Tick() |
|||
{ |
|||
var now = DateTimeOffset.UtcNow; |
|||
|
|||
for (var i = _inner.Count - 1; i >= 0; --i) |
|||
{ |
|||
var r = _inner[i]; |
|||
|
|||
if (now > r.Dies) |
|||
{ |
|||
_inner.RemoveAt(i); |
|||
} |
|||
} |
|||
} |
|||
|
|||
/// <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(); |
|||
} |
|||
} |
|||
@ -1,11 +0,0 @@ |
|||
using System; |
|||
using Avalonia.Metadata; |
|||
|
|||
namespace Avalonia.Rendering |
|||
{ |
|||
[Unstable] |
|||
public interface IDeferredRendererLock |
|||
{ |
|||
IDisposable? TryLock(); |
|||
} |
|||
} |
|||
@ -1,11 +0,0 @@ |
|||
using System; |
|||
using System.Threading; |
|||
using Avalonia.Utilities; |
|||
|
|||
namespace Avalonia.Rendering |
|||
{ |
|||
internal class ManagedDeferredRendererLock : DisposableLock, IDeferredRendererLock |
|||
{ |
|||
|
|||
} |
|||
} |
|||
@ -1,24 +0,0 @@ |
|||
using Avalonia.Platform; |
|||
|
|||
namespace Avalonia.Direct2D1 |
|||
{ |
|||
class Direct2DChecker : IModuleEnvironmentChecker |
|||
{ |
|||
//Direct2D backend doesn't work on some machines anymore
|
|||
public bool IsCompatible |
|||
{ |
|||
get |
|||
{ |
|||
try |
|||
{ |
|||
Direct2D1Platform.InitializeDirect2D(); |
|||
return true; |
|||
} |
|||
catch |
|||
{ |
|||
return false; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue