Browse Source
- Renamed `RenderLoop` to `RenderTimer` - Added new `RenderLoop` which `DeferredRenderer`s register themselves with for updatespull/1715/head
committed by
Jeremy Koritzinsky
18 changed files with 191 additions and 62 deletions
@ -1,19 +1,8 @@ |
|||
using System; |
|||
|
|||
namespace Avalonia.Rendering |
|||
namespace Avalonia.Rendering |
|||
{ |
|||
/// <summary>
|
|||
/// Defines the interface implemented by an application render loop.
|
|||
/// </summary>
|
|||
public interface IRenderLoop |
|||
{ |
|||
/// <summary>
|
|||
/// Raised when the render loop ticks to signal a new frame should be drawn.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// This event can be raised on any thread; it is the responsibility of the subscriber to
|
|||
/// switch execution to the right thread.
|
|||
/// </remarks>
|
|||
event EventHandler<EventArgs> Tick; |
|||
void Add(IRenderLoopTask i); |
|||
void Remove(IRenderLoopTask i); |
|||
} |
|||
} |
|||
@ -0,0 +1,12 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Avalonia.Rendering |
|||
{ |
|||
public interface IRenderLoopTask |
|||
{ |
|||
bool NeedsUpdate { get; } |
|||
void Update(); |
|||
void Render(); |
|||
} |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
using System; |
|||
using System.Threading.Tasks; |
|||
|
|||
namespace Avalonia.Rendering |
|||
{ |
|||
/// <summary>
|
|||
/// Defines the interface implemented by an application render timer.
|
|||
/// </summary>
|
|||
public interface IRenderTimer |
|||
{ |
|||
/// <summary>
|
|||
/// Raised when the render timer ticks to signal a new frame should be drawn.
|
|||
/// </summary>
|
|||
/// <remarks>
|
|||
/// This event can be raised on any thread; it is the responsibility of the subscriber to
|
|||
/// switch execution to the right thread.
|
|||
/// </remarks>
|
|||
event EventHandler<EventArgs> Tick; |
|||
} |
|||
} |
|||
@ -0,0 +1,111 @@ |
|||
using System; |
|||
using System.Collections.Generic; |
|||
using Avalonia.Logging; |
|||
using Avalonia.Threading; |
|||
|
|||
namespace Avalonia.Rendering |
|||
{ |
|||
public class RenderLoop : IRenderLoop |
|||
{ |
|||
private readonly IDispatcher _dispatcher; |
|||
private List<IRenderLoopTask> _items = new List<IRenderLoopTask>(); |
|||
private IRenderTimer _timer; |
|||
private volatile bool inTick; |
|||
|
|||
public RenderLoop() |
|||
{ |
|||
_dispatcher = Dispatcher.UIThread; |
|||
} |
|||
|
|||
public RenderLoop(IRenderTimer timer, IDispatcher dispatcher) |
|||
{ |
|||
_timer = timer; |
|||
_dispatcher = dispatcher; |
|||
} |
|||
|
|||
protected IRenderTimer Timer |
|||
{ |
|||
get |
|||
{ |
|||
if (_timer == null) |
|||
{ |
|||
_timer = AvaloniaLocator.Current.GetService<IRenderTimer>(); |
|||
} |
|||
|
|||
return _timer; |
|||
} |
|||
} |
|||
|
|||
public void Add(IRenderLoopTask i) |
|||
{ |
|||
Contract.Requires<ArgumentNullException>(i != null); |
|||
Dispatcher.UIThread.VerifyAccess(); |
|||
|
|||
_items.Add(i); |
|||
|
|||
if (_items.Count == 1) |
|||
{ |
|||
Timer.Tick += TimerTick; |
|||
} |
|||
} |
|||
|
|||
public void Remove(IRenderLoopTask i) |
|||
{ |
|||
Contract.Requires<ArgumentNullException>(i != null); |
|||
Dispatcher.UIThread.VerifyAccess(); |
|||
|
|||
_items.Remove(i); |
|||
|
|||
if (_items.Count == 0) |
|||
{ |
|||
Timer.Tick -= TimerTick; |
|||
} |
|||
} |
|||
|
|||
private async void TimerTick(object sender, EventArgs e) |
|||
{ |
|||
if (!inTick) |
|||
{ |
|||
inTick = true; |
|||
|
|||
try |
|||
{ |
|||
var needsUpdate = false; |
|||
|
|||
foreach (var i in _items) |
|||
{ |
|||
if (i.NeedsUpdate) |
|||
{ |
|||
needsUpdate = true; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
if (needsUpdate) |
|||
{ |
|||
await _dispatcher.InvokeAsync(() => |
|||
{ |
|||
foreach (var i in _items) |
|||
{ |
|||
i.Update(); |
|||
} |
|||
}); |
|||
} |
|||
|
|||
foreach (var i in _items) |
|||
{ |
|||
i.Render(); |
|||
} |
|||
} |
|||
catch (Exception ex) |
|||
{ |
|||
Logger.Error(LogArea.Visual, this, "Exception in render loop: {Error}", ex); |
|||
} |
|||
finally |
|||
{ |
|||
inTick = false; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue