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());
}
}