diff --git a/src/Avalonia.Visuals/Rendering/DisplayDirtyRect.cs b/src/Avalonia.Visuals/Rendering/DisplayDirtyRect.cs index 41d8c45de7..cde5690585 100644 --- a/src/Avalonia.Visuals/Rendering/DisplayDirtyRect.cs +++ b/src/Avalonia.Visuals/Rendering/DisplayDirtyRect.cs @@ -4,7 +4,7 @@ namespace Avalonia.Rendering { public class DisplayDirtyRect { - public static readonly TimeSpan TimeToLive = TimeSpan.FromMilliseconds(500); + public static readonly TimeSpan TimeToLive = TimeSpan.FromMilliseconds(250); public DisplayDirtyRect(Rect rect) { diff --git a/src/Avalonia.Visuals/Rendering/RenderLayers.cs b/src/Avalonia.Visuals/Rendering/RenderLayers.cs index c26ff59486..6cc106ba30 100644 --- a/src/Avalonia.Visuals/Rendering/RenderLayers.cs +++ b/src/Avalonia.Visuals/Rendering/RenderLayers.cs @@ -47,7 +47,7 @@ namespace Avalonia.Rendering var layer = _inner[i]; var node = (VisualNode)scene.FindNode(layer.LayerRoot); - if (node == null || node.LayerRoot != layer.LayerRoot) + if (node == null || node.LayerRoot.VisualRoot == null || node.LayerRoot != layer.LayerRoot) { layer.Bitmap.Dispose(); _inner.RemoveAt(i); diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs index a94b8d0565..53d0ebfaa7 100644 --- a/src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs +++ b/src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs @@ -154,11 +154,11 @@ namespace Avalonia.Rendering.SceneGraph node.Opacity = opacity; node.OpacityMask = visual.OpacityMask; - if (opacity < 1) + if (opacity < 1 && node.LayerRoot != visual) { - SetLayer(node, node.Visual); + SetLayer(node, node.Visual, contextImpl.Dirty); } - else if (node.LayerRoot == node.Visual && node.Parent != null) + else if (opacity >= 1 && node.LayerRoot == node.Visual && node.Parent != null) { ClearLayer(node, contextImpl.Dirty); } @@ -185,10 +185,6 @@ namespace Avalonia.Rendering.SceneGraph node.SubTreeUpdated = true; contextImpl.TrimChildren(); } - else if (node.OpacityChanged) - { - AddSubtreeBounds(node, contextImpl.Dirty); - } } } } @@ -251,19 +247,28 @@ namespace Avalonia.Rendering.SceneGraph dirty.Remove(node.LayerRoot); - SetLayer(node, newLayerRoot); + SetLayer(node, newLayerRoot, dirty); } - private static void SetLayer(VisualNode node, IVisual layerRoot) + private static void SetLayer(VisualNode node, IVisual layerRoot, LayerDirtyRects dirty) { + if (node.LayerRoot == layerRoot) + { + throw new AvaloniaInternalException("Called SetLayer with unchanged LayerRoot."); + } + + var oldLayerRoot = node.LayerRoot; + node.LayerRoot = layerRoot; + dirty.Add(oldLayerRoot, node.Bounds); + dirty.Add(layerRoot, node.Bounds); foreach (VisualNode child in node.Children) { // If the child is not the start of a new layer, recurse. if (child.LayerRoot != child.Visual) { - SetLayer(child, layerRoot); + SetLayer(child, layerRoot, dirty); } } } diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs index d056b1fe48..6775afb178 100644 --- a/src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs +++ b/src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs @@ -220,12 +220,13 @@ namespace Avalonia.Rendering.SceneGraph /// public void BeginRender(IDrawingContextImpl context) { - context.Transform = Transform; - if (ClipToBounds) { - context.PushClip(ClipBounds * Transform.Invert()); + context.Transform = Matrix.Identity; + context.PushClip(ClipBounds); } + + context.Transform = Transform; } /// diff --git a/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests.cs b/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests.cs index 060cd1f05b..220b77e8b7 100644 --- a/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests.cs +++ b/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests.cs @@ -571,9 +571,13 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph Assert.Same(tree, borderNode.LayerRoot); Assert.Same(tree, canvasNode.LayerRoot); - Assert.Equal(1, dirty.Count()); - Assert.Equal(tree, dirty.Single().Key); - Assert.Equal(new Rect(21, 21, 58, 78), dirty.Single().Value.Single()); + var rootDirty = dirty[tree]; + var borderDirty = dirty[border]; + + Assert.Equal(1, rootDirty.Count()); + Assert.Equal(1, borderDirty.Count()); + Assert.Equal(new Rect(21, 21, 58, 78), rootDirty.Single()); + Assert.Equal(new Rect(21, 21, 58, 78), borderDirty.Single()); } }