Browse Source

Merge pull request #1365 from jkoritzinsky/refcount-scene

Add ref-counting for the scene instance in DeferredRenderer
pull/1373/head
Steven Kirk 9 years ago
committed by GitHub
parent
commit
11903bfe08
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 20
      src/Avalonia.Visuals/Rendering/DeferredRenderer.cs
  2. 2
      src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs
  3. 22
      tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests.cs
  4. 6
      tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests_Layers.cs
  5. 2
      tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneTests.cs

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

@ -28,7 +28,7 @@ namespace Avalonia.Rendering
private readonly ISceneBuilder _sceneBuilder;
private bool _running;
private Scene _scene;
private volatile IRef<Scene> _scene;
private DirtyVisuals _dirty;
private IRef<IRenderTargetBitmapImpl> _overlay;
private bool _updateQueued;
@ -128,7 +128,7 @@ namespace Avalonia.Rendering
UpdateScene();
}
return _scene?.HitTest(p, root, filter) ?? Enumerable.Empty<IVisual>();
return _scene?.Item.HitTest(p, root, filter) ?? Enumerable.Empty<IVisual>();
}
/// <inheritdoc/>
@ -180,7 +180,7 @@ namespace Avalonia.Rendering
internal void UnitTestUpdateScene() => UpdateScene();
internal void UnitTestRender() => Render(_scene);
internal void UnitTestRender() => Render(_scene.Item);
private void Render(Scene scene)
{
@ -381,7 +381,8 @@ namespace Avalonia.Rendering
{
if (_root.IsVisible)
{
var scene = _scene?.Clone() ?? new Scene(_root);
var sceneRef = RefCountable.Create(_scene?.Item.CloneScene() ?? new Scene(_root));
var scene = sceneRef.Item;
if (_dirty == null)
{
@ -396,7 +397,7 @@ namespace Avalonia.Rendering
}
}
var oldScene = Interlocked.Exchange(ref _scene, scene);
var oldScene = Interlocked.Exchange(ref _scene, sceneRef);
oldScene?.Dispose();
_dirty.Clear();
@ -425,10 +426,11 @@ namespace Avalonia.Rendering
_updateQueued = true;
_dispatcher.Post(UpdateScene, DispatcherPriority.Render);
}
Scene scene = null;
Interlocked.Exchange(ref scene, _scene);
Render(scene);
using (var scene = _scene?.Clone())
{
Render(scene?.Item);
}
}
catch { }
finally

2
src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs

@ -82,7 +82,7 @@ namespace Avalonia.Rendering.SceneGraph
/// Clones the scene.
/// </summary>
/// <returns>The cloned scene.</returns>
public Scene Clone()
public Scene CloneScene()
{
var index = new Dictionary<IVisual, IVisualNode>();
var root = Clone((VisualNode)Root, null, index);

22
tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests.cs

@ -99,7 +99,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
Assert.Equal(new Rect(10, 20, 160, 240), canvasNode.ClipBounds);
// Initial ClipBounds are correct, make sure they're still correct after updating canvas.
result = result.Clone();
result = result.CloneScene();
Assert.True(sceneBuilder.Update(result, canvas));
canvasNode = result.FindNode(canvas);
@ -197,7 +197,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
canvas.Arrange(new Rect(tree.DesiredSize));
// Initial ClipBounds are correct, make sure they're still correct after updating canvas.
scene = scene.Clone();
scene = scene.CloneScene();
Assert.True(sceneBuilder.Update(scene, canvas));
borderNode = scene.FindNode(border);
@ -309,7 +309,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
var borderNode = scene.FindNode(border);
Assert.Equal(expectedTransform, borderNode.Transform);
scene = scene.Clone();
scene = scene.CloneScene();
Assert.True(sceneBuilder.Update(scene, border));
borderNode = scene.FindNode(border);
@ -354,7 +354,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
border.Background = Brushes.Green;
var result = initial.Clone();
var result = initial.CloneScene();
sceneBuilder.Update(result, border);
var borderNode = (VisualNode)result.Root.Children[0];
@ -402,7 +402,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
sceneBuilder.UpdateAll(initial);
border.Child = decorator;
var result = initial.Clone();
var result = initial.CloneScene();
Assert.True(sceneBuilder.Update(result, decorator));
@ -457,7 +457,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
sceneBuilder.UpdateAll(initial);
border.Child = null;
var result = initial.Clone();
var result = initial.CloneScene();
Assert.True(sceneBuilder.Update(result, decorator));
Assert.False(sceneBuilder.Update(result, canvas));
@ -501,7 +501,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
sceneBuilder.UpdateAll(initial);
border.IsVisible = false;
var result = initial.Clone();
var result = initial.CloneScene();
Assert.True(sceneBuilder.Update(result, border));
Assert.False(sceneBuilder.Update(result, canvas));
@ -552,7 +552,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
decorator.Margin = new Thickness(0, 20, 0, 0);
layout.ExecuteLayoutPass();
scene = scene.Clone();
scene = scene.CloneScene();
sceneBuilder.Update(scene, decorator);
borderNode = scene.FindNode(border);
@ -600,7 +600,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
decorator.Margin = new Thickness(0, 20, 0, 0);
layout.ExecuteLayoutPass();
scene = scene.Clone();
scene = scene.CloneScene();
sceneBuilder.Update(scene, decorator);
@ -640,7 +640,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
Assert.Equal(new Size(100, 100), scene.Size);
tree.ClientSize = new Size(110, 120);
scene = scene.Clone();
scene = scene.CloneScene();
sceneBuilder.Update(scene, tree);
Assert.Equal(new Size(110, 120), scene.Size);
@ -735,7 +735,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
tree.Child = new Decorator();
using (var result = scene.Clone())
using (var result = scene.CloneScene())
{
sceneBuilder.Update(result, img);
scene.Dispose();

6
tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests_Layers.cs

@ -62,7 +62,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
Assert.Empty(scene.Layers.Select(x => x.LayerRoot).Except(new IVisual[] { tree, border }));
animation.OnCompleted();
scene = scene.Clone();
scene = scene.CloneScene();
sceneBuilder.Update(scene, border);
@ -160,7 +160,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
Assert.Equal(3, scene.Layers.Count);
decorator.Child = null;
scene = scene.Clone();
scene = scene.CloneScene();
sceneBuilder.Update(scene, border);
@ -210,7 +210,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
Assert.Equal(3, scene.Layers.Count);
border.IsVisible = false;
scene = scene.Clone();
scene = scene.CloneScene();
sceneBuilder.Update(scene, border);

2
tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneTests.cs

@ -25,7 +25,7 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph
scene.Layers[tree].Dirty.Add(new Rect(0, 0, 100, 100));
scene.Layers[decorator].Dirty.Add(new Rect(0, 0, 50, 100));
scene = scene.Clone();
scene = scene.CloneScene();
Assert.Equal(2, scene.Layers.Count());
Assert.Empty(scene.Layers[0].Dirty);
Assert.Empty(scene.Layers[1].Dirty);

Loading…
Cancel
Save