Browse Source

Fix various Direct2D resource leak issues, as well as an unclosed geometry stream.

pull/5275/head
Sebastian Hartte 6 years ago
parent
commit
1321c7996e
  1. 12
      src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs
  2. 6
      src/Windows/Avalonia.Direct2D1/Media/GeometryImpl.cs
  3. 6
      src/Windows/Avalonia.Direct2D1/Media/Imaging/WicBitmapImpl.cs
  4. 9
      src/Windows/Avalonia.Direct2D1/Media/StreamGeometryImpl.cs
  5. 2
      src/Windows/Avalonia.Direct2D1/PrimitiveExtensions.cs

12
src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs

@ -21,6 +21,7 @@ namespace Avalonia.Direct2D1.Media
private readonly ILayerFactory _layerFactory; private readonly ILayerFactory _layerFactory;
private readonly SharpDX.Direct2D1.RenderTarget _renderTarget; private readonly SharpDX.Direct2D1.RenderTarget _renderTarget;
private readonly DeviceContext _deviceContext; private readonly DeviceContext _deviceContext;
private readonly bool _ownsDeviceContext;
private readonly SharpDX.DXGI.SwapChain1 _swapChain; private readonly SharpDX.DXGI.SwapChain1 _swapChain;
private readonly Action _finishedCallback; private readonly Action _finishedCallback;
@ -51,10 +52,12 @@ namespace Avalonia.Direct2D1.Media
if (_renderTarget is DeviceContext deviceContext) if (_renderTarget is DeviceContext deviceContext)
{ {
_deviceContext = deviceContext; _deviceContext = deviceContext;
_ownsDeviceContext = false;
} }
else else
{ {
_deviceContext = _renderTarget.QueryInterface<DeviceContext>(); _deviceContext = _renderTarget.QueryInterface<DeviceContext>();
_ownsDeviceContext = true;
} }
_deviceContext.BeginDraw(); _deviceContext.BeginDraw();
@ -96,6 +99,13 @@ namespace Avalonia.Direct2D1.Media
{ {
throw new RenderTargetCorruptedException(ex); throw new RenderTargetCorruptedException(ex);
} }
finally
{
if (_ownsDeviceContext)
{
_deviceContext.Dispose();
}
}
} }
/// <summary> /// <summary>
@ -151,7 +161,7 @@ namespace Avalonia.Direct2D1.Media
using (var d2dSource = ((BitmapImpl)source.Item).GetDirect2DBitmap(_deviceContext)) using (var d2dSource = ((BitmapImpl)source.Item).GetDirect2DBitmap(_deviceContext))
using (var sourceBrush = new BitmapBrush(_deviceContext, d2dSource.Value)) using (var sourceBrush = new BitmapBrush(_deviceContext, d2dSource.Value))
using (var d2dOpacityMask = CreateBrush(opacityMask, opacityMaskRect.Size)) using (var d2dOpacityMask = CreateBrush(opacityMask, opacityMaskRect.Size))
using (var geometry = new SharpDX.Direct2D1.RectangleGeometry(_deviceContext.Factory, destRect.ToDirect2D())) using (var geometry = new SharpDX.Direct2D1.RectangleGeometry(Direct2D1Platform.Direct2D1Factory, destRect.ToDirect2D()))
{ {
if (d2dOpacityMask.PlatformBrush != null) if (d2dOpacityMask.PlatformBrush != null)
{ {

6
src/Windows/Avalonia.Direct2D1/Media/GeometryImpl.cs

@ -33,13 +33,13 @@ namespace Avalonia.Direct2D1.Media
/// <inheritdoc/> /// <inheritdoc/>
public IGeometryImpl Intersect(IGeometryImpl geometry) public IGeometryImpl Intersect(IGeometryImpl geometry)
{ {
var result = new PathGeometry(Geometry.Factory); var result = new PathGeometry(Direct2D1Platform.Direct2D1Factory);
using (var sink = result.Open()) using (var sink = result.Open())
{ {
Geometry.Combine(((GeometryImpl)geometry).Geometry, CombineMode.Intersect, sink); Geometry.Combine(((GeometryImpl)geometry).Geometry, CombineMode.Intersect, sink);
return new StreamGeometryImpl(result); sink.Close();
} }
return new StreamGeometryImpl(result);
} }
/// <inheritdoc/> /// <inheritdoc/>

6
src/Windows/Avalonia.Direct2D1/Media/Imaging/WicBitmapImpl.cs

@ -13,7 +13,7 @@ namespace Avalonia.Direct2D1.Media
/// </summary> /// </summary>
public class WicBitmapImpl : BitmapImpl public class WicBitmapImpl : BitmapImpl
{ {
private BitmapDecoder _decoder; private readonly BitmapDecoder _decoder;
private static BitmapInterpolationMode ConvertInterpolationMode(Avalonia.Visuals.Media.Imaging.BitmapInterpolationMode interpolationMode) private static BitmapInterpolationMode ConvertInterpolationMode(Avalonia.Visuals.Media.Imaging.BitmapInterpolationMode interpolationMode)
{ {
@ -41,7 +41,7 @@ namespace Avalonia.Direct2D1.Media
/// <param name="fileName">The filename of the bitmap to load.</param> /// <param name="fileName">The filename of the bitmap to load.</param>
public WicBitmapImpl(string fileName) public WicBitmapImpl(string fileName)
{ {
using (BitmapDecoder decoder = new BitmapDecoder(Direct2D1Platform.ImagingFactory, fileName, DecodeOptions.CacheOnDemand)) using (var decoder = new BitmapDecoder(Direct2D1Platform.ImagingFactory, fileName, DecodeOptions.CacheOnDemand))
{ {
WicImpl = new Bitmap(Direct2D1Platform.ImagingFactory, decoder.GetFrame(0), BitmapCreateCacheOption.CacheOnDemand); WicImpl = new Bitmap(Direct2D1Platform.ImagingFactory, decoder.GetFrame(0), BitmapCreateCacheOption.CacheOnDemand);
Dpi = new Vector(96, 96); Dpi = new Vector(96, 96);
@ -177,7 +177,7 @@ namespace Avalonia.Direct2D1.Media
/// <returns>The Direct2D bitmap.</returns> /// <returns>The Direct2D bitmap.</returns>
public override OptionalDispose<D2DBitmap> GetDirect2DBitmap(SharpDX.Direct2D1.RenderTarget renderTarget) public override OptionalDispose<D2DBitmap> GetDirect2DBitmap(SharpDX.Direct2D1.RenderTarget renderTarget)
{ {
FormatConverter converter = new FormatConverter(Direct2D1Platform.ImagingFactory); using var converter = new FormatConverter(Direct2D1Platform.ImagingFactory);
converter.Initialize(WicImpl, SharpDX.WIC.PixelFormat.Format32bppPBGRA); converter.Initialize(WicImpl, SharpDX.WIC.PixelFormat.Format32bppPBGRA);
return new OptionalDispose<D2DBitmap>(D2DBitmap.FromWicBitmap(renderTarget, converter), true); return new OptionalDispose<D2DBitmap>(D2DBitmap.FromWicBitmap(renderTarget, converter), true);
} }

9
src/Windows/Avalonia.Direct2D1/Media/StreamGeometryImpl.cs

@ -29,9 +29,12 @@ namespace Avalonia.Direct2D1.Media
public IStreamGeometryImpl Clone() public IStreamGeometryImpl Clone()
{ {
var result = new PathGeometry(Direct2D1Platform.Direct2D1Factory); var result = new PathGeometry(Direct2D1Platform.Direct2D1Factory);
var sink = result.Open(); using (var sink = result.Open())
((PathGeometry)Geometry).Stream(sink); {
sink.Close(); ((PathGeometry)Geometry).Stream(sink);
sink.Close();
}
return new StreamGeometryImpl(result); return new StreamGeometryImpl(result);
} }

2
src/Windows/Avalonia.Direct2D1/PrimitiveExtensions.cs

@ -111,7 +111,7 @@ namespace Avalonia.Direct2D1
/// <returns>The Direct2D brush.</returns> /// <returns>The Direct2D brush.</returns>
public static StrokeStyle ToDirect2DStrokeStyle(this Avalonia.Media.IPen pen, SharpDX.Direct2D1.RenderTarget renderTarget) public static StrokeStyle ToDirect2DStrokeStyle(this Avalonia.Media.IPen pen, SharpDX.Direct2D1.RenderTarget renderTarget)
{ {
return pen.ToDirect2DStrokeStyle(renderTarget.Factory); return pen.ToDirect2DStrokeStyle(Direct2D1Platform.Direct2D1Factory);
} }
/// <summary> /// <summary>

Loading…
Cancel
Save