Browse Source

Merge pull request #2189 from kekekeks/ported-fixes

Ported bugfixes from critical time visuals PR
Nikita Tsukanov 6 years ago
parent
commit
04745d8eff

+ 29 - 0
src/Avalonia.Base/Threading/ThreadSafeObjectPool.cs

@@ -0,0 +1,29 @@
+using System.Collections.Generic;
+
+namespace Avalonia.Threading
+{
+    public class ThreadSafeObjectPool<T> where T : class, new()
+    {
+        private Stack<T> _stack = new Stack<T>();
+        private object _lock = new object();
+        public static ThreadSafeObjectPool<T> Default { get; } = new ThreadSafeObjectPool<T>();
+
+        public T Get()
+        {
+            lock (_lock)
+            {
+                if(_stack.Count == 0)
+                    return new T();
+                return _stack.Pop();
+            }
+        }
+
+        public void Return(T obj)
+        {
+            lock (_stack)
+            {
+                _stack.Push(obj);
+            }
+        }
+    }
+}

+ 22 - 9
src/Avalonia.Visuals/Media/DrawingContext.cs

@@ -2,23 +2,26 @@ using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using Avalonia.Media.Imaging;
 using Avalonia.Media.Imaging;
 using Avalonia.Platform;
 using Avalonia.Platform;
+using Avalonia.Threading;
 using Avalonia.Visuals.Media.Imaging;
 using Avalonia.Visuals.Media.Imaging;
 
 
 namespace Avalonia.Media
 namespace Avalonia.Media
 {
 {
     public sealed class DrawingContext : IDisposable
     public sealed class DrawingContext : IDisposable
     {
     {
+        private readonly bool _ownsImpl;
         private int _currentLevel;
         private int _currentLevel;
 
 
 
 
-        static readonly Stack<Stack<PushedState>> StateStackPool = new Stack<Stack<PushedState>>();
-        static readonly Stack<Stack<TransformContainer>> TransformStackPool = new Stack<Stack<TransformContainer>>();
+        private static ThreadSafeObjectPool<Stack<PushedState>> StateStackPool { get; } =
+            ThreadSafeObjectPool<Stack<PushedState>>.Default;
 
 
-        private Stack<PushedState> _states = StateStackPool.Count == 0 ? new Stack<PushedState>() : StateStackPool.Pop();
+        private static ThreadSafeObjectPool<Stack<TransformContainer>> TransformStackPool { get; } =
+            ThreadSafeObjectPool<Stack<TransformContainer>>.Default;
 
 
-        private Stack<TransformContainer> _transformContainers = TransformStackPool.Count == 0
-            ? new Stack<TransformContainer>()
-            : TransformStackPool.Pop();
+        private Stack<PushedState> _states = StateStackPool.Get();
+
+        private Stack<TransformContainer> _transformContainers = TransformStackPool.Get();
 
 
         readonly struct TransformContainer
         readonly struct TransformContainer
         {
         {
@@ -35,6 +38,13 @@ namespace Avalonia.Media
         public DrawingContext(IDrawingContextImpl impl)
         public DrawingContext(IDrawingContextImpl impl)
         {
         {
             PlatformImpl = impl;
             PlatformImpl = impl;
+            _ownsImpl = true;
+        }
+        
+        public DrawingContext(IDrawingContextImpl impl, bool ownsImpl)
+        {
+            _ownsImpl = ownsImpl;
+            PlatformImpl = impl;
         }
         }
 
 
         public IDrawingContextImpl PlatformImpl { get; }
         public IDrawingContextImpl PlatformImpl { get; }
@@ -299,11 +309,14 @@ namespace Avalonia.Media
         {
         {
             while (_states.Count != 0)
             while (_states.Count != 0)
                 _states.Peek().Dispose();
                 _states.Peek().Dispose();
-            StateStackPool.Push(_states);
+            StateStackPool.Return(_states);
             _states = null;
             _states = null;
-            TransformStackPool.Push(_transformContainers);
+            if (_transformContainers.Count != 0)
+                throw new InvalidOperationException("Transform container stack is non-empty");
+            TransformStackPool.Return(_transformContainers);
             _transformContainers = null;
             _transformContainers = null;
-            PlatformImpl.Dispose();
+            if (_ownsImpl)
+                PlatformImpl.Dispose();
         }
         }
 
 
         private static bool PenIsVisible(Pen pen)
         private static bool PenIsVisible(Pen pen)

+ 1 - 0
src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs

@@ -220,6 +220,7 @@ namespace Avalonia.Rendering.SceneGraph
                 Transform = Transform,
                 Transform = Transform,
                 ClipBounds = ClipBounds,
                 ClipBounds = ClipBounds,
                 ClipToBounds = ClipToBounds,
                 ClipToBounds = ClipToBounds,
+                LayoutBounds = LayoutBounds,
                 GeometryClip = GeometryClip,
                 GeometryClip = GeometryClip,
                 _opacity = Opacity,
                 _opacity = Opacity,
                 OpacityMask = OpacityMask,
                 OpacityMask = OpacityMask,

+ 1 - 0
src/Skia/Avalonia.Skia/GlRenderTarget.cs

@@ -35,6 +35,7 @@ namespace Avalonia.Skia
             gl.ClearStencil(0);
             gl.ClearStencil(0);
             gl.ClearColor(0, 0, 0, 0);
             gl.ClearColor(0, 0, 0, 0);
             gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
             gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+            _grContext.ResetContext();
 
 
             GRBackendRenderTarget renderTarget =
             GRBackendRenderTarget renderTarget =
                 new GRBackendRenderTarget(size.Width, size.Height, disp.SampleCount, disp.StencilSize,
                 new GRBackendRenderTarget(size.Width, size.Height, disp.SampleCount, disp.StencilSize,