Quellcode durchsuchen

Simplified DeferredRendererTests,

Steven Kirk vor 8 Jahren
Ursprung
Commit
e6b5df8d08

+ 11 - 7
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);

+ 15 - 3
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)
         {

+ 37 - 103
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)