From 43a0f50866a9a2b45fc1a34b9a0b6f2de9a03a46 Mon Sep 17 00:00:00 2001 From: Dariusz Komosinski Date: Thu, 23 Apr 2020 23:34:07 +0200 Subject: [PATCH 1/5] Limit reallocations in the deferred renderer. --- .../Rendering/SceneGraph/Scene.cs | 18 ++++++++++--- .../Rendering/SceneGraph/SceneLayers.cs | 20 ++++++++++++--- .../Rendering/SceneGraph/VisualNode.cs | 25 ++++++++++++++----- 3 files changed, 49 insertions(+), 14 deletions(-) diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs index b4bf4c799a..0f6001516d 100644 --- a/src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs +++ b/src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs @@ -12,7 +12,7 @@ namespace Avalonia.Rendering.SceneGraph /// public class Scene : IDisposable { - private Dictionary _index; + private readonly Dictionary _index; /// /// Initializes a new instance of the class. @@ -83,7 +83,7 @@ namespace Avalonia.Rendering.SceneGraph /// The cloned scene. public Scene CloneScene() { - var index = new Dictionary(); + var index = new Dictionary(_index.Count); var root = Clone((VisualNode)Root, null, index); var result = new Scene(root, index, Layers.Clone(), Generation + 1) @@ -162,9 +162,19 @@ namespace Avalonia.Rendering.SceneGraph index.Add(result.Visual, result); - foreach (var child in source.Children) + var children = source.Children; + var childrenCount = children.Count; + + if (childrenCount > 0) { - result.AddChild(Clone((VisualNode)child, result, index)); + result.TryPreallocateChildren(childrenCount); + + for (var i = 0; i < childrenCount; i++) + { + var child = children[i]; + + result.AddChild(Clone((VisualNode)child, result, index)); + } } return result; diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/SceneLayers.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/SceneLayers.cs index 5960b4f560..25f7383a1a 100644 --- a/src/Avalonia.Visuals/Rendering/SceneGraph/SceneLayers.cs +++ b/src/Avalonia.Visuals/Rendering/SceneGraph/SceneLayers.cs @@ -11,16 +11,28 @@ namespace Avalonia.Rendering.SceneGraph public class SceneLayers : IEnumerable { private readonly IVisual _root; - private readonly List _inner = new List(); - private readonly Dictionary _index = new Dictionary(); + private readonly List _inner; + private readonly Dictionary _index; /// /// Initializes a new instance of the class. /// /// The scene's root visual. - public SceneLayers(IVisual root) + public SceneLayers(IVisual root) : this(root, 0) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The scene's root visual. + /// Initial layer capacity. + public SceneLayers(IVisual root, int capacity) { _root = root; + + _inner = new List(capacity); + _index = new Dictionary(capacity); } /// @@ -84,7 +96,7 @@ namespace Avalonia.Rendering.SceneGraph /// The cloned layers. public SceneLayers Clone() { - var result = new SceneLayers(_root); + var result = new SceneLayers(_root, Count); foreach (var src in _inner) { diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs index 82444a0c29..6f566ff6d6 100644 --- a/src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs +++ b/src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Reactive.Disposables; +using Avalonia.Collections; using Avalonia.Media; using Avalonia.Platform; using Avalonia.Utilities; @@ -349,6 +349,11 @@ namespace Avalonia.Rendering.SceneGraph context.Transform = transformRestore; } + internal void TryPreallocateChildren(int count) + { + EnsureChildrenCreated(count); + } + private Rect CalculateBounds() { var result = new Rect(); @@ -362,11 +367,11 @@ namespace Avalonia.Rendering.SceneGraph return result; } - private void EnsureChildrenCreated() + private void EnsureChildrenCreated(int capacity = 0) { if (_children == null) { - _children = new List(); + _children = new List(capacity); } } @@ -383,7 +388,15 @@ namespace Avalonia.Rendering.SceneGraph } else if (_drawOperationsCloned) { - _drawOperations = new List>(_drawOperations.Select(op => op.Clone())); + var oldDrawOperations = _drawOperations; + + _drawOperations = new List>(oldDrawOperations.Count); + + foreach (var drawOperation in oldDrawOperations) + { + _drawOperations.Add(drawOperation.Clone()); + } + _drawOperationsRefCounter.Dispose(); _drawOperationsRefCounter = RefCountable.Create(CreateDisposeDrawOperations(_drawOperations)); _drawOperationsCloned = false; @@ -399,9 +412,9 @@ namespace Avalonia.Rendering.SceneGraph /// Disposable for given draw operations. private static IDisposable CreateDisposeDrawOperations(List> drawOperations) { - return Disposable.Create(() => + return Disposable.Create(drawOperations, operations => { - foreach (var operation in drawOperations) + foreach (var operation in operations) { operation.Dispose(); } From ef9bb42252601e50dd55de32b212115f1953474b Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Sat, 2 May 2020 20:24:25 +0300 Subject: [PATCH 2/5] Trigger repaint on VisibilityNotify events --- src/Avalonia.X11/X11Window.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.X11/X11Window.cs b/src/Avalonia.X11/X11Window.cs index 3a919e2bc4..60b739f43a 100644 --- a/src/Avalonia.X11/X11Window.cs +++ b/src/Avalonia.X11/X11Window.cs @@ -333,7 +333,9 @@ namespace Avalonia.X11 } else if (ev.type == XEventName.UnmapNotify) _mapped = false; - else if (ev.type == XEventName.Expose) + else if (ev.type == XEventName.Expose || + (ev.type == XEventName.VisibilityNotify && + ev.VisibilityEvent.state < 2)) { if (!_triggeredExpose) { From 2d80a0e29341f54e4b71d4c9f0069079bf0b55c1 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Tue, 5 May 2020 15:04:52 +0300 Subject: [PATCH 3/5] Allow extra options for managed file dialogs --- samples/ControlCatalog/Pages/DialogsPage.xaml | 1 + .../ControlCatalog/Pages/DialogsPage.xaml.cs | 14 ++++++++++++++ .../ManagedFileChooserViewModel.cs | 12 ++++++++---- .../ManagedFileDialogExtensions.cs | 19 +++++++++++++++++-- .../ManagedFileDialogOptions.cs | 7 +++++++ 5 files changed, 47 insertions(+), 6 deletions(-) create mode 100644 src/Avalonia.Dialogs/ManagedFileDialogOptions.cs diff --git a/samples/ControlCatalog/Pages/DialogsPage.xaml b/samples/ControlCatalog/Pages/DialogsPage.xaml index 1ed5c0cbfd..0834e829d8 100644 --- a/samples/ControlCatalog/Pages/DialogsPage.xaml +++ b/samples/ControlCatalog/Pages/DialogsPage.xaml @@ -6,6 +6,7 @@ + diff --git a/samples/ControlCatalog/Pages/DialogsPage.xaml.cs b/samples/ControlCatalog/Pages/DialogsPage.xaml.cs index ba1921a185..dcb94a89e7 100644 --- a/samples/ControlCatalog/Pages/DialogsPage.xaml.cs +++ b/samples/ControlCatalog/Pages/DialogsPage.xaml.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Reflection; using Avalonia.Controls; +using Avalonia.Dialogs; using Avalonia.Markup.Xaml; #pragma warning disable 4014 @@ -58,6 +59,19 @@ namespace ControlCatalog.Pages Title = "Select folder", }.ShowAsync(GetWindow()); }; + this.FindControl