Browse Source

Simplified DeferredRendererTests,

pull/1306/head
Steven Kirk 8 years ago
parent
commit
e6b5df8d08
  1. 18
      src/Avalonia.Visuals/Rendering/DeferredRenderer.cs
  2. 18
      tests/Avalonia.UnitTests/TestRoot.cs
  3. 140
      tests/Avalonia.Visuals.UnitTests/Rendering/DeferredRendererTests.cs

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

@ -25,7 +25,6 @@ namespace Avalonia.Rendering
private readonly IRenderLoop _renderLoop;
private readonly IVisual _root;
private readonly ISceneBuilder _sceneBuilder;
private readonly RenderLayers _layers;
private bool _running;
private Scene _scene;
@ -56,7 +55,7 @@ namespace Avalonia.Rendering
_dispatcher = dispatcher ?? Dispatcher.UIThread;
_root = root;
_sceneBuilder = sceneBuilder ?? new SceneBuilder();
_layers = new RenderLayers();
Layers = new RenderLayers();
_renderLoop = renderLoop;
}
@ -80,7 +79,7 @@ namespace Avalonia.Rendering
_root = root;
_renderTarget = renderTarget;
_sceneBuilder = sceneBuilder ?? new SceneBuilder();
_layers = new RenderLayers();
Layers = new RenderLayers();
}
/// <inheritdoc/>
@ -94,6 +93,11 @@ namespace Avalonia.Rendering
/// </summary>
public string DebugFramesPath { get; set; }
/// <summary>
/// Gets the render layers.
/// </summary>
internal RenderLayers Layers { get; }
/// <inheritdoc/>
public void AddDirty(IVisual visual)
{
@ -192,7 +196,7 @@ namespace Avalonia.Rendering
if (scene.Generation != _lastSceneId)
{
context = _renderTarget.CreateDrawingContext(this);
_layers.Update(scene, context);
Layers.Update(scene, context);
RenderToLayers(scene);
@ -262,7 +266,7 @@ namespace Avalonia.Rendering
{
foreach (var layer in scene.Layers)
{
var renderTarget = _layers[layer.LayerRoot].Bitmap;
var renderTarget = Layers[layer.LayerRoot].Bitmap;
var node = (VisualNode)scene.FindNode(layer.LayerRoot);
if (node != null)
@ -322,7 +326,7 @@ namespace Avalonia.Rendering
foreach (var layer in scene.Layers)
{
var bitmap = _layers[layer.LayerRoot].Bitmap;
var bitmap = Layers[layer.LayerRoot].Bitmap;
var sourceRect = new Rect(0, 0, bitmap.PixelWidth, bitmap.PixelHeight);
if (layer.GeometryClip != null)
@ -442,7 +446,7 @@ namespace Avalonia.Rendering
{
var index = 0;
foreach (var layer in _layers)
foreach (var layer in Layers)
{
var fileName = Path.Combine(DebugFramesPath, $"frame-{id}-layer-{index++}.png");
layer.Bitmap.Save(fileName);

18
tests/Avalonia.UnitTests/TestRoot.cs

@ -16,8 +16,6 @@ namespace Avalonia.UnitTests
public class TestRoot : Decorator, IFocusScope, ILayoutRoot, IInputRoot, INameScope, IRenderRoot, IStyleRoot
{
private readonly NameScope _nameScope = new NameScope();
private readonly IRenderTarget _renderTarget = Mock.Of<IRenderTarget>(
x => x.CreateDrawingContext(It.IsAny<IVisualBrushRenderer>()) == Mock.Of<IDrawingContextImpl>());
public TestRoot()
{
@ -65,7 +63,21 @@ namespace Avalonia.UnitTests
IStyleHost IStyleHost.StylingParent => StylingParent;
public IRenderTarget CreateRenderTarget() => _renderTarget;
public IRenderTarget CreateRenderTarget()
{
var dc = new Mock<IDrawingContextImpl>();
dc.Setup(x => x.CreateLayer(It.IsAny<Size>())).Returns(() =>
{
var layerDc = new Mock<IDrawingContextImpl>();
var layer = new Mock<IRenderTargetBitmapImpl>();
layer.Setup(x => x.CreateDrawingContext(It.IsAny<IVisualBrushRenderer>())).Returns(layerDc.Object);
return layer.Object;
});
var result = new Mock<IRenderTarget>();
result.Setup(x => x.CreateDrawingContext(It.IsAny<IVisualBrushRenderer>())).Returns(dc.Object);
return result.Object;
}
public void Invalidate(Rect rect)
{

140
tests/Avalonia.Visuals.UnitTests/Rendering/DeferredRendererTests.cs

@ -21,28 +21,18 @@ namespace Avalonia.Visuals.UnitTests.Rendering
[Fact]
public void First_Frame_Calls_UpdateScene_On_Dispatcher()
{
var loop = new Mock<IRenderLoop>();
var root = new TestRoot();
var dispatcher = new Mock<IDispatcher>();
dispatcher.Setup(x => x.InvokeAsync(It.IsAny<Action>(), DispatcherPriority.Render))
.Callback<Action, DispatcherPriority>((a, p) => a());
var target = new DeferredRenderer(
root,
loop.Object,
sceneBuilder: MockSceneBuilder(root).Object,
dispatcher: dispatcher.Object);
CreateTargetAndRunFrame(root, dispatcher: dispatcher.Object);
target.Start();
RunFrame(loop);
#if !NETCOREAPP1_1 // Delegate.Method is not available in netcoreapp1.1
dispatcher.Verify(x =>
x.InvokeAsync(
It.Is<Action>(a => a.Method.Name == "UpdateScene"),
DispatcherPriority.Render));
#endif
}
[Fact]
@ -51,15 +41,8 @@ namespace Avalonia.Visuals.UnitTests.Rendering
var loop = new Mock<IRenderLoop>();
var root = new TestRoot();
var sceneBuilder = MockSceneBuilder(root);
var dispatcher = new ImmediateDispatcher();
var target = new DeferredRenderer(
root,
loop.Object,
sceneBuilder: sceneBuilder.Object,
dispatcher: dispatcher);
target.Start();
RunFrame(loop);
CreateTargetAndRunFrame(root, sceneBuilder: sceneBuilder.Object);
sceneBuilder.Verify(x => x.UpdateAll(It.IsAny<Scene>()));
}
@ -70,12 +53,10 @@ namespace Avalonia.Visuals.UnitTests.Rendering
var loop = new Mock<IRenderLoop>();
var root = new TestRoot();
var sceneBuilder = MockSceneBuilder(root);
var dispatcher = new ImmediateDispatcher();
var target = new DeferredRenderer(
root,
loop.Object,
sceneBuilder: sceneBuilder.Object,
dispatcher: dispatcher);
sceneBuilder: sceneBuilder.Object);
target.Start();
IgnoreFirstFrame(loop, sceneBuilder);
@ -145,24 +126,8 @@ namespace Avalonia.Visuals.UnitTests.Rendering
root.Measure(Size.Infinity);
root.Arrange(new Rect(root.DesiredSize));
var rootLayer = CreateLayer();
var borderLayer = CreateLayer();
var renderTargetContext = Mock.Get(root.CreateRenderTarget().CreateDrawingContext(null));
renderTargetContext.SetupSequence(x => x.CreateLayer(It.IsAny<Size>()))
.Returns(rootLayer)
.Returns(borderLayer);
var loop = new Mock<IRenderLoop>();
var target = new DeferredRenderer(
root,
loop.Object,
dispatcher: new ImmediateDispatcher());
root.Renderer = target;
target.Start();
RunFrame(loop);
var context = Mock.Get(rootLayer.CreateDrawingContext(null));
var target = CreateTargetAndRunFrame(root);
var context = GetLayerContext(target, root);
var animation = new BehaviorSubject<double>(0.5);
context.Verify(x => x.PushOpacity(0.5), Times.Once);
@ -191,24 +156,8 @@ namespace Avalonia.Visuals.UnitTests.Rendering
root.Measure(Size.Infinity);
root.Arrange(new Rect(root.DesiredSize));
var rootLayer = CreateLayer();
var borderLayer = CreateLayer();
var renderTargetContext = Mock.Get(root.CreateRenderTarget().CreateDrawingContext(null));
renderTargetContext.SetupSequence(x => x.CreateLayer(It.IsAny<Size>()))
.Returns(rootLayer)
.Returns(borderLayer);
var loop = new Mock<IRenderLoop>();
var target = new DeferredRenderer(
root,
loop.Object,
dispatcher: new ImmediateDispatcher());
root.Renderer = target;
target.Start();
RunFrame(loop);
var context = Mock.Get(rootLayer.CreateDrawingContext(null));
var target = CreateTargetAndRunFrame(root);
var context = GetLayerContext(target, root);
var animation = new BehaviorSubject<double>(0.5);
context.Verify(x => x.PushOpacity(0.5), Times.Never);
@ -217,12 +166,11 @@ namespace Avalonia.Visuals.UnitTests.Rendering
}
[Fact]
public void Frame_Should_Create_Layer_For_Root()
public void Should_Create_Layer_For_Root()
{
var loop = new Mock<IRenderLoop>();
var root = new TestRoot();
var rootLayer = new Mock<IRenderTargetBitmapImpl>();
var dispatcher = new ImmediateDispatcher();
var sceneBuilder = new Mock<ISceneBuilder>();
sceneBuilder.Setup(x => x.UpdateAll(It.IsAny<Scene>()))
@ -233,18 +181,9 @@ namespace Avalonia.Visuals.UnitTests.Rendering
});
var renderInterface = new Mock<IPlatformRenderInterface>();
var target = CreateTargetAndRunFrame(root, sceneBuilder: sceneBuilder.Object);
var target = new DeferredRenderer(
root,
loop.Object,
sceneBuilder: sceneBuilder.Object,
dispatcher: dispatcher);
target.Start();
RunFrame(loop);
var context = Mock.Get(root.CreateRenderTarget().CreateDrawingContext(null));
context.Verify(x => x.CreateLayer(root.ClientSize));
Assert.Single(target.Layers);
}
[Fact]
@ -269,49 +208,44 @@ namespace Avalonia.Visuals.UnitTests.Rendering
root.Measure(Size.Infinity);
root.Arrange(new Rect(root.DesiredSize));
var rootLayer = CreateLayer();
var borderLayer = CreateLayer();
var renderTargetContext = Mock.Get(root.CreateRenderTarget().CreateDrawingContext(null));
renderTargetContext.SetupSequence(x => x.CreateLayer(It.IsAny<Size>()))
.Returns(rootLayer)
.Returns(borderLayer);
var loop = new Mock<IRenderLoop>();
var target = new DeferredRenderer(
root,
loop.Object,
dispatcher: new ImmediateDispatcher());
root.Renderer = target;
var target = CreateTargetAndRunFrame(root, loop: loop);
target.Start();
RunFrame(loop);
Assert.Equal(new[] { root }, target.Layers.Select(x => x.LayerRoot));
var rootContext = Mock.Get(rootLayer.CreateDrawingContext(null));
var borderContext = Mock.Get(borderLayer.CreateDrawingContext(null));
var animation = new BehaviorSubject<double>(0.5);
rootContext.Verify(x => x.FillRectangle(Brushes.Red, new Rect(0, 0, 100, 100), 0), Times.Once);
rootContext.Verify(x => x.FillRectangle(Brushes.Green, new Rect(0, 0, 100, 100), 0), Times.Once);
borderContext.Verify(x => x.FillRectangle(It.IsAny<IBrush>(), It.IsAny<Rect>(), It.IsAny<float>()), Times.Never);
rootContext.ResetCalls();
borderContext.ResetCalls();
border.Bind(Border.OpacityProperty, animation, BindingPriority.Animation);
RunFrame(loop);
rootContext.Verify(x => x.FillRectangle(Brushes.Red, new Rect(0, 0, 100, 100), 0), Times.Once);
rootContext.Verify(x => x.FillRectangle(Brushes.Green, new Rect(0, 0, 100, 100), 0), Times.Never);
borderContext.Verify(x => x.FillRectangle(Brushes.Green, new Rect(0, 0, 100, 100), 0), Times.Once);
Assert.Equal(new IVisual[] { root, border }, target.Layers.Select(x => x.LayerRoot));
rootContext.ResetCalls();
borderContext.ResetCalls();
animation.OnCompleted();
RunFrame(loop);
Mock.Get(borderLayer).Verify(x => x.Dispose());
rootContext.Verify(x => x.FillRectangle(Brushes.Red, new Rect(0, 0, 100, 100), 0), Times.Once);
rootContext.Verify(x => x.FillRectangle(Brushes.Green, new Rect(0, 0, 100, 100), 0), Times.Once);
borderContext.Verify(x => x.FillRectangle(It.IsAny<IBrush>(), It.IsAny<Rect>(), It.IsAny<float>()), Times.Never);
Assert.Equal(new[] { root }, target.Layers.Select(x => x.LayerRoot));
}
private DeferredRenderer CreateTargetAndRunFrame(
TestRoot root,
Mock<IRenderLoop> loop = null,
ISceneBuilder sceneBuilder = null,
IDispatcher dispatcher = null)
{
loop = loop ?? new Mock<IRenderLoop>();
var target = new DeferredRenderer(
root,
loop.Object,
sceneBuilder: sceneBuilder,
dispatcher: dispatcher ?? new ImmediateDispatcher());
root.Renderer = target;
target.Start();
RunFrame(loop);
return target;
}
private Mock<IDrawingContextImpl> GetLayerContext(DeferredRenderer renderer, IControl layerRoot)
{
return Mock.Get(renderer.Layers[layerRoot].Bitmap.CreateDrawingContext(null));
}
private void IgnoreFirstFrame(Mock<IRenderLoop> loop, Mock<ISceneBuilder> sceneBuilder)

Loading…
Cancel
Save