committed by
GitHub
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