diff --git a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs index 99ab60d1ac..e3957747bd 100644 --- a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs +++ b/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); } /// @@ -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(); } diff --git a/src/Skia/Avalonia.Skia/GeometryImpl.cs b/src/Skia/Avalonia.Skia/GeometryImpl.cs index 19dbcf9713..0e95b5d139 100644 --- a/src/Skia/Avalonia.Skia/GeometryImpl.cs +++ b/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()); } } diff --git a/src/Skia/Avalonia.Skia/SKPaintCache.cs b/src/Skia/Avalonia.Skia/SKPaintCache.cs new file mode 100644 index 0000000000..79f9575591 --- /dev/null +++ b/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 s_cachedPaints; + + static SKPaintCache() + { + s_cachedPaints = new ConcurrentBag(); + } + + 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(); + } + } + + } +}