diff --git a/samples/interop/Direct3DInteropSample/MainWindow.cs b/samples/interop/Direct3DInteropSample/MainWindow.cs index ad40e81895..3fe3b896f6 100644 --- a/samples/interop/Direct3DInteropSample/MainWindow.cs +++ b/samples/interop/Direct3DInteropSample/MainWindow.cs @@ -254,7 +254,8 @@ namespace Direct3DInteropSample public IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer visualBrushRenderer) { return new DrawingContextImpl(visualBrushRenderer, _window._d2dRenderTarget, - AvaloniaLocator.Current.GetService()); + AvaloniaLocator.Current.GetService(), + AvaloniaLocator.Current.GetService()); } } diff --git a/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs b/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs index fd8364c03b..eedb8a0c4e 100644 --- a/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs +++ b/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs @@ -145,7 +145,7 @@ namespace Avalonia.Direct2D1 return new HwndRenderTarget(nativeWindow); } if (s is IExternalDirect2DRenderTargetSurface external) - return new ExternalRenderTarget(external, s_dwfactory); + return new ExternalRenderTarget(external, s_dwfactory, s_imagingFactory); } throw new NotSupportedException("Don't know how to create a Direct2D1 renderer from any of provided surfaces"); } @@ -156,7 +156,7 @@ namespace Avalonia.Direct2D1 double dpiX, double dpiY) { - return new RenderTargetBitmapImpl( + return new WicRenderTargetBitmapImpl( s_imagingFactory, s_d2D1Factory, s_dwfactory, diff --git a/src/Windows/Avalonia.Direct2D1/ExternalRenderTarget.cs b/src/Windows/Avalonia.Direct2D1/ExternalRenderTarget.cs index 307048f7b4..d735c5f8bb 100644 --- a/src/Windows/Avalonia.Direct2D1/ExternalRenderTarget.cs +++ b/src/Windows/Avalonia.Direct2D1/ExternalRenderTarget.cs @@ -1,8 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Avalonia.Direct2D1.Media; using Avalonia.Platform; using Avalonia.Rendering; @@ -15,11 +11,16 @@ namespace Avalonia.Direct2D1 { private readonly IExternalDirect2DRenderTargetSurface _externalRenderTargetProvider; private readonly DirectWriteFactory _dwFactory; - public ExternalRenderTarget(IExternalDirect2DRenderTargetSurface externalRenderTargetProvider, - DirectWriteFactory dwFactory) + private readonly SharpDX.WIC.ImagingFactory _wicFactory; + + public ExternalRenderTarget( + IExternalDirect2DRenderTargetSurface externalRenderTargetProvider, + DirectWriteFactory dwFactory, + SharpDX.WIC.ImagingFactory wicFactory) { _externalRenderTargetProvider = externalRenderTargetProvider; _dwFactory = dwFactory; + _wicFactory = wicFactory; } public void Dispose() @@ -31,7 +32,7 @@ namespace Avalonia.Direct2D1 { var target = _externalRenderTargetProvider.GetOrCreateRenderTarget(); _externalRenderTargetProvider.BeforeDrawing(); - return new DrawingContextImpl(visualBrushRenderer, target, _dwFactory, null, () => + return new DrawingContextImpl(visualBrushRenderer, target, _dwFactory, _wicFactory, null, () => { try { diff --git a/src/Windows/Avalonia.Direct2D1/ICreateLayer.cs b/src/Windows/Avalonia.Direct2D1/ICreateLayer.cs new file mode 100644 index 0000000000..9214377e6f --- /dev/null +++ b/src/Windows/Avalonia.Direct2D1/ICreateLayer.cs @@ -0,0 +1,10 @@ +using System; +using Avalonia.Platform; + +namespace Avalonia.Direct2D1 +{ + internal interface ICreateLayer + { + IRenderTargetBitmapImpl CreateLayer(int pixelWidth, int pixelHeight); + } +} diff --git a/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs index 69b582b009..a7bb73e19f 100644 --- a/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs +++ b/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs @@ -2,16 +2,13 @@ // Licensed under the MIT license. See licence.md file in the project root for full license information. using System; -using System.Collections; using System.Collections.Generic; using Avalonia.Media; using Avalonia.Platform; -using Avalonia.RenderHelpers; using Avalonia.Rendering; using SharpDX; using SharpDX.Direct2D1; using SharpDX.Mathematics.Interop; -using IBitmap = Avalonia.Media.Imaging.IBitmap; namespace Avalonia.Direct2D1.Media { @@ -24,6 +21,7 @@ namespace Avalonia.Direct2D1.Media private readonly SharpDX.Direct2D1.RenderTarget _renderTarget; private readonly SharpDX.DXGI.SwapChain1 _swapChain; private readonly Action _finishedCallback; + private readonly SharpDX.WIC.ImagingFactory _imagingFactory; private SharpDX.DirectWrite.Factory _directWriteFactory; /// @@ -32,12 +30,14 @@ namespace Avalonia.Direct2D1.Media /// The visual brush renderer. /// The render target to draw to. /// The DirectWrite factory. + /// The WIC imaging factory. /// An optional swap chain associated with this drawing context. /// An optional delegate to be called when context is disposed. public DrawingContextImpl( IVisualBrushRenderer visualBrushRenderer, SharpDX.Direct2D1.RenderTarget renderTarget, SharpDX.DirectWrite.Factory directWriteFactory, + SharpDX.WIC.ImagingFactory imagingFactory, SharpDX.DXGI.SwapChain1 swapChain = null, Action finishedCallback = null) { @@ -46,6 +46,7 @@ namespace Avalonia.Direct2D1.Media _swapChain = swapChain; _finishedCallback = finishedCallback; _directWriteFactory = directWriteFactory; + _imagingFactory = imagingFactory; _swapChain = swapChain; _renderTarget.BeginDraw(); } @@ -97,7 +98,7 @@ namespace Avalonia.Direct2D1.Media using (var d2d = ((BitmapImpl)source).GetDirect2DBitmap(_renderTarget)) { _renderTarget.DrawBitmap( - d2d, + d2d.Value, destRect.ToSharpDX(), (float)opacity, BitmapInterpolationMode.Linear, @@ -115,7 +116,7 @@ namespace Avalonia.Direct2D1.Media public void DrawImage(IBitmapImpl source, IBrush opacityMask, Rect opacityMaskRect, Rect destRect) { using (var d2dSource = ((BitmapImpl)source).GetDirect2DBitmap(_renderTarget)) - using (var sourceBrush = new BitmapBrush(_renderTarget, d2dSource)) + using (var sourceBrush = new BitmapBrush(_renderTarget, d2dSource.Value)) using (var d2dOpacityMask = CreateBrush(opacityMask, opacityMaskRect.Size)) using (var geometry = new SharpDX.Direct2D1.RectangleGeometry(_renderTarget.Factory, destRect.ToDirect2D())) { @@ -397,7 +398,7 @@ namespace Avalonia.Direct2D1.Media return new ImageBrushImpl( visualBrush, _renderTarget, - new D2DBitmapImpl(intermediate.Bitmap), + new D2DBitmapImpl(_imagingFactory, intermediate.Bitmap), destinationSize); } } diff --git a/src/Windows/Avalonia.Direct2D1/Media/ImageBrushImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/ImageBrushImpl.cs index ed3d78b4fd..08cfed2ace 100644 --- a/src/Windows/Avalonia.Direct2D1/Media/ImageBrushImpl.cs +++ b/src/Windows/Avalonia.Direct2D1/Media/ImageBrushImpl.cs @@ -10,6 +10,8 @@ namespace Avalonia.Direct2D1.Media { public sealed class ImageBrushImpl : BrushImpl { + OptionalDispose _bitmap; + public ImageBrushImpl( ITileBrush brush, SharpDX.Direct2D1.RenderTarget target, @@ -20,9 +22,10 @@ namespace Avalonia.Direct2D1.Media if (!calc.NeedsIntermediate) { + _bitmap = bitmap.GetDirect2DBitmap(target); PlatformBrush = new BitmapBrush( target, - bitmap.GetDirect2DBitmap(target), + _bitmap.Value, GetBitmapBrushProperties(brush), GetBrushProperties(brush, calc.DestinationRect)); } @@ -41,7 +44,7 @@ namespace Avalonia.Direct2D1.Media public override void Dispose() { - ((BitmapBrush)PlatformBrush)?.Bitmap.Dispose(); + _bitmap.Dispose(); base.Dispose(); } diff --git a/src/Windows/Avalonia.Direct2D1/Media/Imaging/BitmapImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/Imaging/BitmapImpl.cs index 63596bdf54..d58f023391 100644 --- a/src/Windows/Avalonia.Direct2D1/Media/Imaging/BitmapImpl.cs +++ b/src/Windows/Avalonia.Direct2D1/Media/Imaging/BitmapImpl.cs @@ -1,20 +1,38 @@ using System; -using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; using Avalonia.Platform; -using SharpDX.Direct2D1; +using SharpDX.WIC; +using D2DBitmap = SharpDX.Direct2D1.Bitmap; namespace Avalonia.Direct2D1.Media { public abstract class BitmapImpl : IBitmapImpl, IDisposable { - public abstract Bitmap GetDirect2DBitmap(SharpDX.Direct2D1.RenderTarget target); + public BitmapImpl(ImagingFactory imagingFactory) + { + WicImagingFactory = imagingFactory; + } + + public ImagingFactory WicImagingFactory { get; } public abstract int PixelWidth { get; } public abstract int PixelHeight { get; } - public abstract void Save(string fileName); + + public abstract OptionalDispose GetDirect2DBitmap(SharpDX.Direct2D1.RenderTarget target); + + public void Save(string fileName) + { + if (Path.GetExtension(fileName) != ".png") + { + // Yeah, we need to support other formats. + throw new NotSupportedException("Use PNG, stoopid."); + } + + using (FileStream s = new FileStream(fileName, FileMode.Create)) + { + Save(s); + } + } + public abstract void Save(Stream stream); public virtual void Dispose() diff --git a/src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DBitmapImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DBitmapImpl.cs index 5378ae3257..b03e022674 100644 --- a/src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DBitmapImpl.cs +++ b/src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DBitmapImpl.cs @@ -1,11 +1,10 @@ using System; -using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Avalonia.Platform; using SharpDX.Direct2D1; +using WICFactory = SharpDX.WIC.ImagingFactory; +using ImagingFactory2 = SharpDX.WIC.ImagingFactory2; +using ImageParameters = SharpDX.WIC.ImageParameters; +using PngBitmapEncoder = SharpDX.WIC.PngBitmapEncoder; namespace Avalonia.Direct2D1.Media { @@ -26,32 +25,42 @@ namespace Avalonia.Direct2D1.Media /// or if the render target is a , /// the device associated with this context, to be renderable. /// - public D2DBitmapImpl(Bitmap d2DBitmap) + public D2DBitmapImpl(WICFactory imagingFactory, Bitmap d2DBitmap) + : base(imagingFactory) { - if (d2DBitmap == null) throw new ArgumentNullException(nameof(d2DBitmap)); - - _direct2D = d2DBitmap; + _direct2D = d2DBitmap ?? throw new ArgumentNullException(nameof(d2DBitmap)); } - - public override Bitmap GetDirect2DBitmap(SharpDX.Direct2D1.RenderTarget target) => _direct2D; - + public override int PixelWidth => _direct2D.PixelSize.Width; public override int PixelHeight => _direct2D.PixelSize.Height; - public override void Save(string fileName) + public override void Dispose() { - throw new NotImplementedException(); + base.Dispose(); + _direct2D.Dispose(); } - public override void Save(Stream stream) + public override OptionalDispose GetDirect2DBitmap(SharpDX.Direct2D1.RenderTarget target) { - throw new NotImplementedException(); + return new OptionalDispose(_direct2D, false); } - public override void Dispose() + public override void Save(Stream stream) { - base.Dispose(); - _direct2D.Dispose(); + using (var encoder = new PngBitmapEncoder(WicImagingFactory, stream)) + using (var frameEncode = new SharpDX.WIC.BitmapFrameEncode(encoder)) + using (var imageEncoder = new SharpDX.WIC.ImageEncoder((ImagingFactory2)WicImagingFactory, null)) + { + var parameters = new ImageParameters( + new PixelFormat(SharpDX.DXGI.Format.R8G8B8A8_UNorm, AlphaMode.Premultiplied), + _direct2D.DotsPerInch.Width, + _direct2D.DotsPerInch.Height, + 0, 0, PixelWidth, PixelHeight); + + imageEncoder.WriteFrame(_direct2D, frameEncode, parameters); + frameEncode.Commit(); + encoder.Commit(); + } } } } diff --git a/src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DRenderTargetBitmapImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DRenderTargetBitmapImpl.cs new file mode 100644 index 0000000000..6162d57bad --- /dev/null +++ b/src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DRenderTargetBitmapImpl.cs @@ -0,0 +1,68 @@ +using System; +using Avalonia.Platform; +using Avalonia.Rendering; +using SharpDX; +using SharpDX.Direct2D1; +using SharpDX.WIC; +using D2DBitmap = SharpDX.Direct2D1.Bitmap; +using DirectWriteFactory = SharpDX.DirectWrite.Factory; + +namespace Avalonia.Direct2D1.Media.Imaging +{ + public class D2DRenderTargetBitmapImpl : D2DBitmapImpl, IRenderTargetBitmapImpl, ICreateLayer + { + private readonly DirectWriteFactory _dwriteFactory; + private readonly BitmapRenderTarget _target; + + public D2DRenderTargetBitmapImpl( + ImagingFactory imagingFactory, + DirectWriteFactory dwriteFactory, + BitmapRenderTarget target) + : base(imagingFactory, target.Bitmap) + { + _dwriteFactory = dwriteFactory; + _target = target; + } + + public override int PixelWidth => _target.PixelSize.Width; + public override int PixelHeight => _target.PixelSize.Height; + + public static D2DRenderTargetBitmapImpl CreateCompatible( + ImagingFactory imagingFactory, + DirectWriteFactory dwriteFactory, + SharpDX.Direct2D1.RenderTarget renderTarget, + int pixelWidth, + int pixelHeight) + { + var bitmapRenderTarget = new BitmapRenderTarget( + renderTarget, + CompatibleRenderTargetOptions.None, + new Size2F(pixelWidth, pixelHeight)); + return new D2DRenderTargetBitmapImpl(imagingFactory, dwriteFactory, bitmapRenderTarget); + } + + public IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer visualBrushRenderer) + { + return new DrawingContextImpl( + visualBrushRenderer, + _target, + _dwriteFactory, + WicImagingFactory); + } + + public IRenderTargetBitmapImpl CreateLayer(int pixelWidth, int pixelHeight) + { + return CreateCompatible(WicImagingFactory, _dwriteFactory, _target, pixelWidth, pixelHeight); + } + + public override void Dispose() + { + _target.Dispose(); + } + + public override OptionalDispose GetDirect2DBitmap(SharpDX.Direct2D1.RenderTarget target) + { + return new OptionalDispose(_target.Bitmap, false); + } + } +} diff --git a/src/Windows/Avalonia.Direct2D1/Media/Imaging/WicBitmapImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/Imaging/WicBitmapImpl.cs index e817dd4812..9b99b4c40a 100644 --- a/src/Windows/Avalonia.Direct2D1/Media/Imaging/WicBitmapImpl.cs +++ b/src/Windows/Avalonia.Direct2D1/Media/Imaging/WicBitmapImpl.cs @@ -3,11 +3,10 @@ using System; using System.IO; -using Avalonia.Platform; using Avalonia.Win32.Interop; -using PixelFormat = SharpDX.WIC.PixelFormat; -using APixelFormat = Avalonia.Platform.PixelFormat; using SharpDX.WIC; +using APixelFormat = Avalonia.Platform.PixelFormat; +using D2DBitmap = SharpDX.Direct2D1.Bitmap; namespace Avalonia.Direct2D1.Media { @@ -16,18 +15,14 @@ namespace Avalonia.Direct2D1.Media /// public class WicBitmapImpl : BitmapImpl { - private readonly ImagingFactory _factory; - - /// /// Initializes a new instance of the class. /// /// The WIC imaging factory to use. /// The filename of the bitmap to load. public WicBitmapImpl(ImagingFactory factory, string fileName) + : base(factory) { - _factory = factory; - using (BitmapDecoder decoder = new BitmapDecoder(factory, fileName, DecodeOptions.CacheOnDemand)) { WicImpl = new Bitmap(factory, decoder.GetFrame(0), BitmapCreateCacheOption.CacheOnDemand); @@ -40,9 +35,8 @@ namespace Avalonia.Direct2D1.Media /// The WIC imaging factory to use. /// The stream to read the bitmap from. public WicBitmapImpl(ImagingFactory factory, Stream stream) + : base(factory) { - _factory = factory; - using (BitmapDecoder decoder = new BitmapDecoder(factory, stream, DecodeOptions.CacheOnLoad)) { WicImpl = new Bitmap(factory, decoder.GetFrame(0), BitmapCreateCacheOption.CacheOnLoad); @@ -57,11 +51,11 @@ namespace Avalonia.Direct2D1.Media /// The height of the bitmap. /// Pixel format public WicBitmapImpl(ImagingFactory factory, int width, int height, APixelFormat? pixelFormat = null) + : base(factory) { if (!pixelFormat.HasValue) pixelFormat = APixelFormat.Bgra8888; - _factory = factory; PixelFormat = pixelFormat; WicImpl = new Bitmap( factory, @@ -71,7 +65,8 @@ namespace Avalonia.Direct2D1.Media BitmapCreateCacheOption.CacheOnLoad); } - public WicBitmapImpl(ImagingFactory factory, Platform.PixelFormat format, IntPtr data, int width, int height, int stride) + public WicBitmapImpl(ImagingFactory factory, APixelFormat format, IntPtr data, int width, int height, int stride) + : base(factory) { WicImpl = new Bitmap(factory, width, height, format.ToWic(), BitmapCreateCacheOption.CacheOnDemand); PixelFormat = format; @@ -112,41 +107,23 @@ namespace Avalonia.Direct2D1.Media /// /// The render target. /// The Direct2D bitmap. - public override SharpDX.Direct2D1.Bitmap GetDirect2DBitmap(SharpDX.Direct2D1.RenderTarget renderTarget) + public override OptionalDispose GetDirect2DBitmap(SharpDX.Direct2D1.RenderTarget renderTarget) { - FormatConverter converter = new FormatConverter(_factory); + FormatConverter converter = new FormatConverter(WicImagingFactory); converter.Initialize(WicImpl, SharpDX.WIC.PixelFormat.Format32bppPBGRA); - return SharpDX.Direct2D1.Bitmap.FromWicBitmap(renderTarget, converter); + return new OptionalDispose(D2DBitmap.FromWicBitmap(renderTarget, converter), true); } - /// - /// Saves the bitmap to a file. - /// - /// The filename. - public override void Save(string fileName) + public override void Save(Stream stream) { - if (Path.GetExtension(fileName) != ".png") - { - // Yeah, we need to support other formats. - throw new NotSupportedException("Use PNG, stoopid."); - } - - using (FileStream s = new FileStream(fileName, FileMode.Create)) + using (var encoder = new PngBitmapEncoder(WicImagingFactory, stream)) + using (var frame = new BitmapFrameEncode(encoder)) { - Save(s); + frame.Initialize(); + frame.WriteSource(WicImpl); + frame.Commit(); + encoder.Commit(); } } - - public override void Save(Stream stream) - { - PngBitmapEncoder encoder = new PngBitmapEncoder(_factory); - encoder.Initialize(stream); - - BitmapFrameEncode frame = new BitmapFrameEncode(encoder); - frame.Initialize(); - frame.WriteSource(WicImpl); - frame.Commit(); - encoder.Commit(); - } } } diff --git a/src/Windows/Avalonia.Direct2D1/Media/Imaging/RenderTargetBitmapImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/Imaging/WicRenderTargetBitmapImpl.cs similarity index 89% rename from src/Windows/Avalonia.Direct2D1/Media/Imaging/RenderTargetBitmapImpl.cs rename to src/Windows/Avalonia.Direct2D1/Media/Imaging/WicRenderTargetBitmapImpl.cs index 33736b02cb..1540ee333a 100644 --- a/src/Windows/Avalonia.Direct2D1/Media/Imaging/RenderTargetBitmapImpl.cs +++ b/src/Windows/Avalonia.Direct2D1/Media/Imaging/WicRenderTargetBitmapImpl.cs @@ -10,12 +10,12 @@ using DirectWriteFactory = SharpDX.DirectWrite.Factory; namespace Avalonia.Direct2D1.Media { - public class RenderTargetBitmapImpl : WicBitmapImpl, IRenderTargetBitmapImpl + public class WicRenderTargetBitmapImpl : WicBitmapImpl, IRenderTargetBitmapImpl { private readonly DirectWriteFactory _dwriteFactory; private readonly WicRenderTarget _target; - public RenderTargetBitmapImpl( + public WicRenderTargetBitmapImpl( ImagingFactory imagingFactory, Factory d2dFactory, DirectWriteFactory dwriteFactory, @@ -47,7 +47,7 @@ namespace Avalonia.Direct2D1.Media public IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer visualBrushRenderer) { - return new DrawingContextImpl(visualBrushRenderer, _target, _dwriteFactory); + return new DrawingContextImpl(visualBrushRenderer, _target, _dwriteFactory, WicImagingFactory); } } } diff --git a/src/Windows/Avalonia.Direct2D1/OptionalDispose.cs b/src/Windows/Avalonia.Direct2D1/OptionalDispose.cs new file mode 100644 index 0000000000..cd3eee8d25 --- /dev/null +++ b/src/Windows/Avalonia.Direct2D1/OptionalDispose.cs @@ -0,0 +1,22 @@ +using System; + +namespace Avalonia.Direct2D1 +{ + public struct OptionalDispose : IDisposable where T : IDisposable + { + private readonly bool _dispose; + + public OptionalDispose(T value, bool dispose) + { + Value = value; + _dispose = dispose; + } + + public T Value { get; } + + public void Dispose() + { + if (_dispose) Value?.Dispose(); + } + } +} diff --git a/src/Windows/Avalonia.Direct2D1/RenderTarget.cs b/src/Windows/Avalonia.Direct2D1/RenderTarget.cs index b4c9b49e3f..cbeff8b2f1 100644 --- a/src/Windows/Avalonia.Direct2D1/RenderTarget.cs +++ b/src/Windows/Avalonia.Direct2D1/RenderTarget.cs @@ -7,6 +7,7 @@ using Avalonia.Platform; using Avalonia.Rendering; using SharpDX.Direct2D1; using DwFactory = SharpDX.DirectWrite.Factory; +using WicFactory = SharpDX.WIC.ImagingFactory; namespace Avalonia.Direct2D1 { @@ -25,24 +26,13 @@ namespace Avalonia.Direct2D1 { Direct2DFactory = AvaloniaLocator.Current.GetService(); DirectWriteFactory = AvaloniaLocator.Current.GetService(); + WicFactory = AvaloniaLocator.Current.GetService(); _renderTarget = renderTarget; } - /// - /// Gets the Direct2D factory. - /// - public Factory Direct2DFactory - { - get; - } - - /// - /// Gets the DirectWrite factory. - /// - public DwFactory DirectWriteFactory - { - get; - } + public Factory Direct2DFactory { get; } + public DwFactory DirectWriteFactory { get; } + public WicFactory WicFactory { get; } /// /// Creates a drawing context for a rendering session. @@ -50,7 +40,7 @@ namespace Avalonia.Direct2D1 /// An . public IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer visualBrushRenderer) { - return new DrawingContextImpl(visualBrushRenderer, _renderTarget, DirectWriteFactory); + return new DrawingContextImpl(visualBrushRenderer, _renderTarget, DirectWriteFactory, WicFactory); } public void Dispose() diff --git a/src/Windows/Avalonia.Direct2D1/SwapChainRenderTarget.cs b/src/Windows/Avalonia.Direct2D1/SwapChainRenderTarget.cs index 3c1024e73a..bd6555159c 100644 --- a/src/Windows/Avalonia.Direct2D1/SwapChainRenderTarget.cs +++ b/src/Windows/Avalonia.Direct2D1/SwapChainRenderTarget.cs @@ -10,10 +10,11 @@ using Factory = SharpDX.Direct2D1.Factory; using Factory2 = SharpDX.DXGI.Factory2; using Avalonia.Rendering; using Avalonia.Direct2D1.Media; +using Avalonia.Direct2D1.Media.Imaging; namespace Avalonia.Direct2D1 { - public abstract class SwapChainRenderTarget : IRenderTarget + public abstract class SwapChainRenderTarget : IRenderTarget, ICreateLayer { private Size2 _savedSize; private Size2F _savedDpi; @@ -26,24 +27,12 @@ namespace Avalonia.Direct2D1 D2DDevice = AvaloniaLocator.Current.GetService(); Direct2DFactory = AvaloniaLocator.Current.GetService(); DirectWriteFactory = AvaloniaLocator.Current.GetService(); + WicImagingFactory = AvaloniaLocator.Current.GetService(); } - - /// - /// Gets the Direct2D factory. - /// - public Factory Direct2DFactory - { - get; - } - - /// - /// Gets the DirectWrite factory. - /// - public SharpDX.DirectWrite.Factory DirectWriteFactory - { - get; - } + public Factory Direct2DFactory { get; } + public SharpDX.DirectWrite.Factory DirectWriteFactory { get; } + public SharpDX.WIC.ImagingFactory WicImagingFactory { get; } protected SharpDX.DXGI.Device DxgiDevice { get; } @@ -69,9 +58,25 @@ namespace Avalonia.Direct2D1 visualBrushRenderer, _deviceContext, DirectWriteFactory, + WicImagingFactory, _swapChain); } + public IRenderTargetBitmapImpl CreateLayer(int pixelWidth, int pixelHeight) + { + if (_deviceContext == null) + { + CreateSwapChain(); + } + + return D2DRenderTargetBitmapImpl.CreateCompatible( + WicImagingFactory, + DirectWriteFactory, + _deviceContext, + pixelWidth, + pixelHeight); + } + public void Dispose() { _deviceContext?.Dispose(); @@ -86,7 +91,6 @@ namespace Avalonia.Direct2D1 _deviceContext?.Dispose(); _deviceContext = new DeviceContext(D2DDevice, DeviceContextOptions.None) {DotsPerInch = _savedDpi}; - var swapChainDesc = new SwapChainDescription1 { Width = _savedSize.Width,