浏览代码

Added SKPaintCache.
Cached all SKPaint usages in the DrawingContextImpl to reduce disposals.

DJGosnell 3 年之前
父节点
当前提交
b51ba178c9

+ 23 - 20
src/Skia/Avalonia.Skia/DrawingContextImpl.cs

@@ -35,9 +35,9 @@ namespace Avalonia.Skia
         private GRContext _grContext;
         public GRContext GrContext => _grContext;
         private ISkiaGpu _gpu;
-        private readonly SKPaint _strokePaint = new SKPaint();
-        private readonly SKPaint _fillPaint = new SKPaint();
-        private readonly SKPaint _boxShadowPaint = new SKPaint();
+        private readonly SKPaint _strokePaint = SKPaintCache.Get();
+        private readonly SKPaint _fillPaint = SKPaintCache.Get();
+        private readonly SKPaint _boxShadowPaint = SKPaintCache.Get();
         private static SKShader s_acrylicNoiseShader;
         private readonly ISkiaGpuRenderSession _session;
         private bool _leased = false;
@@ -187,17 +187,13 @@ namespace Avalonia.Skia
             var s = sourceRect.ToSKRect();
             var d = destRect.ToSKRect();
 
-            using (var paint =
-                new SKPaint
-                {
-                    Color = new SKColor(255, 255, 255, (byte)(255 * opacity * _currentOpacity))
-                })
-            {
-                paint.FilterQuality = bitmapInterpolationMode.ToSKFilterQuality();
-                paint.BlendMode = _currentBlendingMode.ToSKBlendMode();
+            var paint = SKPaintCache.Get();
+            paint.Color = new SKColor(255, 255, 255, (byte)(255 * opacity * _currentOpacity));
+            paint.FilterQuality = bitmapInterpolationMode.ToSKFilterQuality();
+            paint.BlendMode = _currentBlendingMode.ToSKBlendMode();
 
-                drawableImage.Draw(this, s, d, paint);
-            }
+            drawableImage.Draw(this, s, d, paint);
+            SKPaintCache.Return(paint);
         }
 
         /// <inheritdoc />
@@ -561,6 +557,11 @@ namespace Avalonia.Skia
             CheckLease();
             try
             {
+                // Return leased paints.
+                SKPaintCache.Return(_strokePaint);
+                SKPaintCache.Return(_fillPaint);
+                SKPaintCache.Return(_boxShadowPaint);
+
                 if (_grContext != null)
                 {
                     Monitor.Exit(_grContext);
@@ -631,15 +632,17 @@ namespace Avalonia.Skia
         public void PopOpacityMask()
         {
             CheckLease();
-            using (var paint = new SKPaint { BlendMode = SKBlendMode.DstIn })
+
+            var paint = SKPaintCache.Get();
+            paint.BlendMode = SKBlendMode.DstIn;
+            
+            Canvas.SaveLayer(paint);
+            SKPaintCache.Return(paint);
+            using (var paintWrapper = _maskStack.Pop())
             {
-                Canvas.SaveLayer(paint);
-                using (var paintWrapper = _maskStack.Pop())
-                {
-                    Canvas.DrawPaint(paintWrapper.Paint);
-                }
-                Canvas.Restore();
+                Canvas.DrawPaint(paintWrapper.Paint);
             }
+            Canvas.Restore();
 
             Canvas.Restore();
         }

+ 6 - 7
src/Skia/Avalonia.Skia/GeometryImpl.cs

@@ -81,15 +81,14 @@ namespace Avalonia.Skia
             }
             else
             {
-                using (var paint = new SKPaint())
-                {
-                    paint.IsStroke = true;
-                    paint.StrokeWidth = strokeWidth;
+                var paint = SKPaintCache.Get();
+                paint.IsStroke = true;
+                paint.StrokeWidth = strokeWidth;
+                paint.GetFillPath(EffectivePath, strokePath);
 
-                    paint.GetFillPath(EffectivePath, strokePath);
+                SKPaintCache.Return(paint);
 
-                    _pathCache.Cache(strokePath, strokeWidth, strokePath.TightBounds.ToAvaloniaRect());
-                }
+                _pathCache.Cache(strokePath, strokeWidth, strokePath.TightBounds.ToAvaloniaRect());
             }
         }
 

+ 45 - 0
src/Skia/Avalonia.Skia/SKPaintCache.cs

@@ -0,0 +1,45 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using SkiaSharp;
+
+namespace Avalonia.Skia
+{
+    internal static class SKPaintCache
+    {
+        private static ConcurrentBag<SKPaint> s_cachedPaints;
+
+        static SKPaintCache()
+        {
+            s_cachedPaints = new ConcurrentBag<SKPaint>();
+        }
+
+        public static SKPaint Get()
+        {
+            if (!s_cachedPaints.TryTake(out var paint))
+            {
+                paint = new SKPaint();
+            }
+
+            return paint;
+        }
+
+        public static void Return(SKPaint paint)
+        {
+            paint.Reset();
+            s_cachedPaints.Add(paint);
+        }
+
+        public static void Clear()
+        {
+            while (s_cachedPaints.TryTake(out var paint))
+            {
+                paint.Dispose();
+            }
+        }
+
+    }
+}