Browse Source

Merge branch 'master' into prs/layoutissue

Steven Kirk 6 years ago
parent
commit
63a133fd09
1 changed files with 26 additions and 11 deletions
  1. 26 11
      src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs

+ 26 - 11
src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs

@@ -322,36 +322,51 @@ namespace Avalonia.Rendering.SceneGraph
             }
         }
 
+        /// <summary>
+        /// Ensures that this node draw operations have been created and are mutable (in case we are using cloned operations).
+        /// </summary>
         private void EnsureDrawOperationsCreated()
         {
             if (_drawOperations == null)
             {
                 _drawOperations = new List<IRef<IDrawOperation>>();
-                _drawOperationsRefCounter = RefCountable.Create(Disposable.Create(DisposeDrawOperations));
+                _drawOperationsRefCounter = RefCountable.Create(CreateDisposeDrawOperations(_drawOperations));
                 _drawOperationsCloned = false;
             }
             else if (_drawOperationsCloned)
             {
                 _drawOperations = new List<IRef<IDrawOperation>>(_drawOperations.Select(op => op.Clone()));
                 _drawOperationsRefCounter.Dispose();
-                _drawOperationsRefCounter = RefCountable.Create(Disposable.Create(DisposeDrawOperations));
+                _drawOperationsRefCounter = RefCountable.Create(CreateDisposeDrawOperations(_drawOperations));
                 _drawOperationsCloned = false;
             }
         }
 
-        public bool Disposed { get; }
-        
-        public void Dispose()
+        /// <summary>
+        /// Creates disposable that will dispose all items in passed draw operations after being disposed.
+        /// It is crucial that we don't capture current <see cref="VisualNode"/> instance
+        /// as draw operations can be cloned and may persist across subsequent scenes.
+        /// </summary>
+        /// <param name="drawOperations">Draw operations that need to be disposed.</param>
+        /// <returns>Disposable for given draw operations.</returns>
+        private static IDisposable CreateDisposeDrawOperations(List<IRef<IDrawOperation>> drawOperations)
         {
-            _drawOperationsRefCounter?.Dispose();
+            return Disposable.Create(() =>
+            {
+                foreach (var operation in drawOperations)
+                {
+                    operation.Dispose();
+                }
+            });
         }
 
-        private void DisposeDrawOperations()
+        public bool Disposed { get; private set; }
+
+        public void Dispose()
         {
-            foreach (var operation in DrawOperations)
-            {
-                operation.Dispose();
-            }
+            _drawOperationsRefCounter?.Dispose();
+
+            Disposed = true;
         }
     }
 }