Bläddra i källkod

Merge pull request #1861 from Gillibald/Direct2D1LocatorRemoval

Direct2D1 cleanup
Steven Kirk 7 år sedan
förälder
incheckning
370001b3df

+ 150 - 128
samples/interop/Direct3DInteropSample/MainWindow.cs

@@ -1,81 +1,83 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+// Copyright (c) The Avalonia Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
+
 using Avalonia;
 using Avalonia.Controls;
+using Avalonia.Direct2D1;
 using Avalonia.Direct2D1.Media;
 using Avalonia.Markup.Xaml;
 using Avalonia.Platform;
 using Avalonia.Rendering;
+
 using SharpDX;
 using SharpDX.D3DCompiler;
 using SharpDX.Direct2D1;
 using SharpDX.Direct3D;
 using SharpDX.Direct3D11;
 using SharpDX.DXGI;
-using SharpDX.WIC;
-using SharpDX.Mathematics;
+
 using AlphaMode = SharpDX.Direct2D1.AlphaMode;
 using Buffer = SharpDX.Direct3D11.Buffer;
-using DeviceContext = SharpDX.Direct3D11.DeviceContext;
-using Factory1 = SharpDX.DXGI.Factory1;
+using DeviceContext = SharpDX.Direct2D1.DeviceContext;
+using Factory2 = SharpDX.DXGI.Factory2;
 using InputElement = SharpDX.Direct3D11.InputElement;
 using Matrix = SharpDX.Matrix;
 using PixelFormat = SharpDX.Direct2D1.PixelFormat;
+using Resource = SharpDX.Direct3D11.Resource;
 
 namespace Direct3DInteropSample
 {
-    class MainWindow : Window
+    public class MainWindow : Window
     {
-        private SharpDX.Direct3D11.Device _d3dDevice;
-        private SharpDX.DXGI.Device _dxgiDevice;
-        Texture2D backBuffer = null;
-        RenderTargetView renderView = null;
-        Texture2D depthBuffer = null;
-        DepthStencilView depthView = null;
+        Texture2D _backBuffer;
+        RenderTargetView _renderView;
+        Texture2D _depthBuffer;
+        DepthStencilView _depthView;
         private readonly SwapChain _swapChain;
-        private SwapChainDescription _desc;
+        private SwapChainDescription1 _desc;
         private Matrix _proj = Matrix.Identity;
-        private Matrix _view;
+        private readonly Matrix _view;
         private Buffer _contantBuffer;
-        private SharpDX.Direct2D1.Device _d2dDevice;
-        private SharpDX.Direct2D1.DeviceContext _d2dContext;
-        private RenderTarget _d2dRenderTarget;
-        private MainWindowViewModel _model;
+        private DeviceContext _deviceContext;
+        private readonly MainWindowViewModel _model;
 
         public MainWindow()
         {
-            _dxgiDevice = AvaloniaLocator.Current.GetService<SharpDX.DXGI.Device>();
-            _d3dDevice = _dxgiDevice.QueryInterface<SharpDX.Direct3D11.Device>();
-            _d2dDevice = AvaloniaLocator.Current.GetService<SharpDX.Direct2D1.Device>();
             DataContext = _model = new MainWindowViewModel();
-            _desc = new SwapChainDescription()
+
+            _desc = new SwapChainDescription1()
             {
                 BufferCount = 1,
-                ModeDescription =
-                   new ModeDescription((int)ClientSize.Width, (int)ClientSize.Height,
-                            new Rational(60, 1), Format.R8G8B8A8_UNorm),
-                IsWindowed = true,
-                OutputHandle = PlatformImpl?.Handle.Handle ?? IntPtr.Zero,
+                Width = (int)ClientSize.Width,
+                Height = (int)ClientSize.Height,
+                Format = Format.R8G8B8A8_UNorm,                
                 SampleDescription = new SampleDescription(1, 0),
                 SwapEffect = SwapEffect.Discard,
                 Usage = Usage.RenderTargetOutput
             };
 
-            _swapChain = new SwapChain(new Factory1(), _d3dDevice, _desc);
+            using (var factory = Direct2D1Platform.DxgiDevice.Adapter.GetParent<Factory2>())
+            {
+                _swapChain = new SwapChain1(factory, Direct2D1Platform.DxgiDevice, PlatformImpl?.Handle.Handle ?? IntPtr.Zero, ref _desc);
+            }              
 
-            _d2dContext = new SharpDX.Direct2D1.DeviceContext(_d2dDevice, DeviceContextOptions.None)
+            _deviceContext = new DeviceContext(Direct2D1Platform.Direct2D1Device, DeviceContextOptions.None)
             {
                 DotsPerInch = new Size2F(96, 96)
             };
 
             CreateMesh();
+
             _view = Matrix.LookAtLH(new Vector3(0, 0, -5), new Vector3(0, 0, 0), Vector3.UnitY);
+
             this.GetObservable(ClientSizeProperty).Subscribe(Resize);
+
             Resize(ClientSize);
+
             AvaloniaXamlLoader.Load(this);
+
             Background = Avalonia.Media.Brushes.Transparent;
         }
 
@@ -83,29 +85,32 @@ namespace Direct3DInteropSample
         protected override void HandlePaint(Rect rect)
         {
             var viewProj = Matrix.Multiply(_view, _proj);
-            var context = _d3dDevice.ImmediateContext;
+            var context = Direct2D1Platform.Direct3D11Device.ImmediateContext;
+
             // Clear views
-            context.ClearDepthStencilView(depthView, DepthStencilClearFlags.Depth, 1.0f, 0);
-            context.ClearRenderTargetView(renderView, Color.White);
+            context.ClearDepthStencilView(_depthView, DepthStencilClearFlags.Depth, 1.0f, 0);
+            context.ClearRenderTargetView(_renderView, Color.White);
 
             // Update WorldViewProj Matrix
-            var worldViewProj = Matrix.RotationX((float) _model.RotationX) * Matrix.RotationY((float) _model.RotationY) *
-                                Matrix.RotationZ((float) _model.RotationZ)
-                                * Matrix.Scaling((float) _model.Zoom) * viewProj;
+            var worldViewProj = Matrix.RotationX((float)_model.RotationX) * Matrix.RotationY((float)_model.RotationY)
+                                                                          * Matrix.RotationZ((float)_model.RotationZ)
+                                                                          * Matrix.Scaling((float)_model.Zoom)
+                                                                          * viewProj;
             worldViewProj.Transpose();
             context.UpdateSubresource(ref worldViewProj, _contantBuffer);
 
             // Draw the cube
             context.Draw(36, 0);
             base.HandlePaint(rect);
+
             // Present!
             _swapChain.Present(0, PresentFlags.None);
         }
 
-        
-        void CreateMesh()
+        private void CreateMesh()
         {
-            var device = _d3dDevice;
+            var device = Direct2D1Platform.Direct3D11Device;
+
             // Compile Vertex and Pixel shaders
             var vertexShaderByteCode = ShaderBytecode.CompileFromFile("MiniCube.fx", "VS", "vs_4_0");
             var vertexShader = new VertexShader(device, vertexShaderByteCode);
@@ -114,63 +119,72 @@ namespace Direct3DInteropSample
             var pixelShader = new PixelShader(device, pixelShaderByteCode);
 
             var signature = ShaderSignature.GetInputSignature(vertexShaderByteCode);
+
+            var inputElements = new[]
+                                {
+                                    new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0),
+                                    new InputElement("COLOR", 0, Format.R32G32B32A32_Float, 16, 0)
+                                };
+
             // Layout from VertexShader input signature
-            var layout = new InputLayout(device, signature, new[]
-                    {
-                        new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0),
-                        new InputElement("COLOR", 0, Format.R32G32B32A32_Float, 16, 0)
-                    });
-            
-            // Instantiate Vertex buiffer from vertex data
-            var vertices = Buffer.Create(device, BindFlags.VertexBuffer, new[]
-                                  {
-                                      new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), // Front
-                                      new Vector4(-1.0f,  1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
-                                      new Vector4( 1.0f,  1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
-                                      new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
-                                      new Vector4( 1.0f,  1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
-                                      new Vector4( 1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
-
-                                      new Vector4(-1.0f, -1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), // BACK
-                                      new Vector4( 1.0f,  1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
-                                      new Vector4(-1.0f,  1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
-                                      new Vector4(-1.0f, -1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
-                                      new Vector4( 1.0f, -1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
-                                      new Vector4( 1.0f,  1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
-
-                                      new Vector4(-1.0f, 1.0f, -1.0f,  1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), // Top
-                                      new Vector4(-1.0f, 1.0f,  1.0f,  1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
-                                      new Vector4( 1.0f, 1.0f,  1.0f,  1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
-                                      new Vector4(-1.0f, 1.0f, -1.0f,  1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
-                                      new Vector4( 1.0f, 1.0f,  1.0f,  1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
-                                      new Vector4( 1.0f, 1.0f, -1.0f,  1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
-
-                                      new Vector4(-1.0f,-1.0f, -1.0f,  1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), // Bottom
-                                      new Vector4( 1.0f,-1.0f,  1.0f,  1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
-                                      new Vector4(-1.0f,-1.0f,  1.0f,  1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
-                                      new Vector4(-1.0f,-1.0f, -1.0f,  1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
-                                      new Vector4( 1.0f,-1.0f, -1.0f,  1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
-                                      new Vector4( 1.0f,-1.0f,  1.0f,  1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
-
-                                      new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), // Left
-                                      new Vector4(-1.0f, -1.0f,  1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
-                                      new Vector4(-1.0f,  1.0f,  1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
-                                      new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
-                                      new Vector4(-1.0f,  1.0f,  1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
-                                      new Vector4(-1.0f,  1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
-
-                                      new Vector4( 1.0f, -1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), // Right
-                                      new Vector4( 1.0f,  1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
-                                      new Vector4( 1.0f, -1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
-                                      new Vector4( 1.0f, -1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
-                                      new Vector4( 1.0f,  1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
-                                      new Vector4( 1.0f,  1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
-                            });
+            var layout = new InputLayout(
+                device,
+                signature,
+                inputElements);
+
+            // Instantiate Vertex buffer from vertex data
+            var vertices = Buffer.Create(
+                device,
+                BindFlags.VertexBuffer,
+                new[]
+                {
+                    new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f), // Front
+                    new Vector4(-1.0f,  1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
+                    new Vector4( 1.0f,  1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
+                    new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
+                    new Vector4( 1.0f,  1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
+                    new Vector4( 1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
+
+                    new Vector4(-1.0f, -1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f), // BACK
+                    new Vector4( 1.0f,  1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
+                    new Vector4(-1.0f,  1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
+                    new Vector4(-1.0f, -1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
+                    new Vector4( 1.0f, -1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
+                    new Vector4( 1.0f,  1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
+
+                    new Vector4(-1.0f, 1.0f, -1.0f,  1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f), // Top
+                    new Vector4(-1.0f, 1.0f,  1.0f,  1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
+                    new Vector4( 1.0f, 1.0f,  1.0f,  1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
+                    new Vector4(-1.0f, 1.0f, -1.0f,  1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
+                    new Vector4( 1.0f, 1.0f,  1.0f,  1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
+                    new Vector4( 1.0f, 1.0f, -1.0f,  1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f),
+
+                    new Vector4(-1.0f, -1.0f, -1.0f,  1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f), // Bottom
+                    new Vector4( 1.0f, -1.0f,  1.0f,  1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
+                    new Vector4(-1.0f, -1.0f,  1.0f,  1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
+                    new Vector4(-1.0f, -1.0f, -1.0f,  1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
+                    new Vector4( 1.0f, -1.0f, -1.0f,  1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
+                    new Vector4( 1.0f, -1.0f,  1.0f,  1.0f), new Vector4(1.0f, 1.0f, 0.0f, 1.0f),
+
+                    new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f), // Left
+                    new Vector4(-1.0f, -1.0f,  1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
+                    new Vector4(-1.0f,  1.0f,  1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
+                    new Vector4(-1.0f, -1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
+                    new Vector4(-1.0f,  1.0f,  1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
+                    new Vector4(-1.0f,  1.0f, -1.0f, 1.0f), new Vector4(1.0f, 0.0f, 1.0f, 1.0f),
+
+                    new Vector4( 1.0f, -1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f), // Right
+                    new Vector4( 1.0f,  1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
+                    new Vector4( 1.0f, -1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
+                    new Vector4( 1.0f, -1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
+                    new Vector4( 1.0f,  1.0f, -1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
+                    new Vector4( 1.0f,  1.0f,  1.0f, 1.0f), new Vector4(0.0f, 1.0f, 1.0f, 1.0f),
+                });
 
             // Create Constant Buffer
             _contantBuffer = new Buffer(device, Utilities.SizeOf<Matrix>(), ResourceUsage.Default, BindFlags.ConstantBuffer, CpuAccessFlags.None, ResourceOptionFlags.None, 0);
 
-            var context = _d3dDevice.ImmediateContext;
+            var context = Direct2D1Platform.Direct3D11Device.ImmediateContext;
 
             // Prepare All the stages
             context.InputAssembler.InputLayout = layout;
@@ -181,63 +195,73 @@ namespace Direct3DInteropSample
             context.PixelShader.Set(pixelShader);
         }
 
-        void Resize(Size size)
+        private void Resize(Size size)
         {
-            Utilities.Dispose(ref _d2dRenderTarget);
-            Utilities.Dispose(ref backBuffer);
-            Utilities.Dispose(ref renderView);
-            Utilities.Dispose(ref depthBuffer);
-            Utilities.Dispose(ref depthView);
-            var context = _d3dDevice.ImmediateContext;
+            Utilities.Dispose(ref _deviceContext);
+            Utilities.Dispose(ref _backBuffer);
+            Utilities.Dispose(ref _renderView);
+            Utilities.Dispose(ref _depthBuffer);
+            Utilities.Dispose(ref _depthView);
+            var context = Direct2D1Platform.Direct3D11Device.ImmediateContext;
+
             // Resize the backbuffer
-            _swapChain.ResizeBuffers(_desc.BufferCount, (int)size.Width, (int)size.Height, Format.Unknown, SwapChainFlags.None);
+            _swapChain.ResizeBuffers(0, 0, 0, Format.Unknown, SwapChainFlags.None);
 
             // Get the backbuffer from the swapchain
-            backBuffer = Texture2D.FromSwapChain<Texture2D>(_swapChain, 0);
+            _backBuffer = Resource.FromSwapChain<Texture2D>(_swapChain, 0);
 
             // Renderview on the backbuffer
-            renderView = new RenderTargetView(_d3dDevice, backBuffer);
+            _renderView = new RenderTargetView(Direct2D1Platform.Direct3D11Device, _backBuffer);
 
             // Create the depth buffer
-            depthBuffer = new Texture2D(_d3dDevice, new Texture2DDescription()
-            {
-                Format = Format.D32_Float_S8X24_UInt,
-                ArraySize = 1,
-                MipLevels = 1,
-                Width = (int)size.Width,
-                Height = (int)size.Height,
-                SampleDescription = new SampleDescription(1, 0),
-                Usage = ResourceUsage.Default,
-                BindFlags = BindFlags.DepthStencil,
-                CpuAccessFlags = CpuAccessFlags.None,
-                OptionFlags = ResourceOptionFlags.None
-            });
+            _depthBuffer = new Texture2D(
+                Direct2D1Platform.Direct3D11Device,
+                new Texture2DDescription()
+                {
+                    Format = Format.D32_Float_S8X24_UInt,
+                    ArraySize = 1,
+                    MipLevels = 1,
+                    Width = (int)size.Width,
+                    Height = (int)size.Height,
+                    SampleDescription = new SampleDescription(1, 0),
+                    Usage = ResourceUsage.Default,
+                    BindFlags = BindFlags.DepthStencil,
+                    CpuAccessFlags = CpuAccessFlags.None,
+                    OptionFlags = ResourceOptionFlags.None
+                });
 
             // Create the depth buffer view
-            depthView = new DepthStencilView(_d3dDevice, depthBuffer);
+            _depthView = new DepthStencilView(Direct2D1Platform.Direct3D11Device, _depthBuffer);
 
             // Setup targets and viewport for rendering
             context.Rasterizer.SetViewport(new Viewport(0, 0, (int)size.Width, (int)size.Height, 0.0f, 1.0f));
-            context.OutputMerger.SetTargets(depthView, renderView);
+            context.OutputMerger.SetTargets(_depthView, _renderView);
 
             // Setup new projection matrix with correct aspect ratio
             _proj = Matrix.PerspectiveFovLH((float)Math.PI / 4.0f, (float)(size.Width / size.Height), 0.1f, 100.0f);
 
             using (var dxgiBackBuffer = _swapChain.GetBackBuffer<Surface>(0))
             {
-                _d2dRenderTarget = new RenderTarget(AvaloniaLocator.Current.GetService<SharpDX.Direct2D1.Factory>()
-                    , dxgiBackBuffer, new RenderTargetProperties
+                var renderTarget = new SharpDX.Direct2D1.RenderTarget(
+                    Direct2D1Platform.Direct2D1Factory,
+                    dxgiBackBuffer,
+                    new RenderTargetProperties
                     {
                         DpiX = 96,
                         DpiY = 96,
                         Type = RenderTargetType.Default,
-                        PixelFormat = new PixelFormat(Format.Unknown, AlphaMode.Premultiplied)
+                        PixelFormat = new PixelFormat(
+                            Format.Unknown,
+                            AlphaMode.Premultiplied)
                     });
-            }
 
+                _deviceContext = renderTarget.QueryInterface<DeviceContext>();
+
+                renderTarget.Dispose();
+            }
         }
 
-        class D3DRenderTarget: IRenderTarget
+        private class D3DRenderTarget : IRenderTarget
         {
             private readonly MainWindow _window;
 
@@ -245,16 +269,14 @@ namespace Direct3DInteropSample
             {
                 _window = window;
             }
+
             public void Dispose()
             {
-                
             }
 
             public IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer visualBrushRenderer)
             {
-                return new DrawingContextImpl(visualBrushRenderer, null, _window._d2dRenderTarget,
-                    AvaloniaLocator.Current.GetService<SharpDX.DirectWrite.Factory>(),
-                    AvaloniaLocator.Current.GetService<ImagingFactory>());
+                return new DrawingContextImpl(visualBrushRenderer, null, _window._deviceContext);
             }
         }
 

+ 47 - 45
src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs

@@ -29,15 +29,18 @@ namespace Avalonia.Direct2D1
     {
         private static readonly Direct2D1Platform s_instance = new Direct2D1Platform();
 
-        private static SharpDX.Direct2D1.Factory s_d2D1Factory;
+        public static SharpDX.Direct3D11.Device Direct3D11Device { get; private set; }
 
-        private static SharpDX.DirectWrite.Factory s_dwfactory;
+        public static SharpDX.Direct2D1.Factory1 Direct2D1Factory { get; private set; }
 
-        private static SharpDX.WIC.ImagingFactory s_imagingFactory;
+        public static SharpDX.Direct2D1.Device Direct2D1Device { get; private set; }
 
-        private static SharpDX.DXGI.Device s_dxgiDevice;
+        public static SharpDX.DirectWrite.Factory1 DirectWriteFactory { get; private set; }
+
+        public static SharpDX.WIC.ImagingFactory ImagingFactory { get; private set; }
+
+        public static SharpDX.DXGI.Device1 DxgiDevice { get; private set; }
 
-        private static SharpDX.Direct2D1.Device s_d2D1Device;
 
         private static readonly object s_initLock = new object();
         private static bool s_initialized = false;
@@ -47,13 +50,14 @@ namespace Avalonia.Direct2D1
             lock (s_initLock)
             {
                 if (s_initialized)
+                {
                     return;
+                }
 #if DEBUG
                 try
                 {
-                    s_d2D1Factory =
-
-                        new SharpDX.Direct2D1.Factory1(SharpDX.Direct2D1.FactoryType.MultiThreaded,
+                    Direct2D1Factory = new SharpDX.Direct2D1.Factory1(
+                        SharpDX.Direct2D1.FactoryType.MultiThreaded,
                             SharpDX.Direct2D1.DebugLevel.Error);
                 }
                 catch
@@ -61,12 +65,19 @@ namespace Avalonia.Direct2D1
                     //
                 }
 #endif
-                s_dwfactory = new SharpDX.DirectWrite.Factory();
-                s_imagingFactory = new SharpDX.WIC.ImagingFactory();
-                if (s_d2D1Factory == null)
-                    s_d2D1Factory = new SharpDX.Direct2D1.Factory1(SharpDX.Direct2D1.FactoryType.MultiThreaded,
+                if (Direct2D1Factory == null)
+                {
+                    Direct2D1Factory = new SharpDX.Direct2D1.Factory1(
+                        SharpDX.Direct2D1.FactoryType.MultiThreaded,
                         SharpDX.Direct2D1.DebugLevel.None);
+                }
 
+                using (var factory = new SharpDX.DirectWrite.Factory())
+                {
+                    DirectWriteFactory = factory.QueryInterface<SharpDX.DirectWrite.Factory1>();
+                }
+
+                ImagingFactory = new SharpDX.WIC.ImagingFactory();
 
                 var featureLevels = new[]
                 {
@@ -79,19 +90,15 @@ namespace Avalonia.Direct2D1
                     SharpDX.Direct3D.FeatureLevel.Level_9_1,
                 };
 
-                using (var d3dDevice = new SharpDX.Direct3D11.Device(
+                Direct3D11Device = new SharpDX.Direct3D11.Device(
                     SharpDX.Direct3D.DriverType.Hardware,
-                    SharpDX.Direct3D11.DeviceCreationFlags.BgraSupport |
-                    SharpDX.Direct3D11.DeviceCreationFlags.VideoSupport,
-                    featureLevels))
-                {
-                    s_dxgiDevice = d3dDevice.QueryInterface<SharpDX.DXGI.Device>();
-                }
+                    SharpDX.Direct3D11.DeviceCreationFlags.BgraSupport | SharpDX.Direct3D11.DeviceCreationFlags.VideoSupport,
+                    featureLevels);
+
+                DxgiDevice = Direct3D11Device.QueryInterface<SharpDX.DXGI.Device1>();
+
+                Direct2D1Device = new SharpDX.Direct2D1.Device(Direct2D1Factory, DxgiDevice);
 
-                using (var factory1 = s_d2D1Factory.QueryInterface<SharpDX.Direct2D1.Factory1>())
-                {
-                    s_d2D1Device = new SharpDX.Direct2D1.Device(factory1, s_dxgiDevice);
-                }
                 s_initialized = true;
             }
         }
@@ -99,19 +106,13 @@ namespace Avalonia.Direct2D1
         public static void Initialize()
         {
             InitializeDirect2D();
-            AvaloniaLocator.CurrentMutable
-                        .Bind<IPlatformRenderInterface>().ToConstant(s_instance)
-                        .BindToSelf(s_d2D1Factory)
-                        .BindToSelf(s_dwfactory)
-                        .BindToSelf(s_imagingFactory)
-                        .BindToSelf(s_dxgiDevice)
-                        .BindToSelf(s_d2D1Device);
+            AvaloniaLocator.CurrentMutable.Bind<IPlatformRenderInterface>().ToConstant(s_instance);
             SharpDX.Configuration.EnableReleaseOnFinalizer = true;
         }
 
         public IBitmapImpl CreateBitmap(int width, int height)
         {
-            return new WicBitmapImpl(s_imagingFactory, width, height);
+            return new WicBitmapImpl(width, height);
         }
 
         public IFormattedTextImpl CreateFormattedText(
@@ -138,14 +139,22 @@ namespace Avalonia.Direct2D1
                 if (s is IPlatformHandle nativeWindow)
                 {
                     if (nativeWindow.HandleDescriptor != "HWND")
+                    {
                         throw new NotSupportedException("Don't know how to create a Direct2D1 renderer from " +
                                                         nativeWindow.HandleDescriptor);
+                    }
+
                     return new HwndRenderTarget(nativeWindow);
                 }
                 if (s is IExternalDirect2DRenderTargetSurface external)
-                    return new ExternalRenderTarget(external, s_dwfactory, s_imagingFactory);
+                {
+                    return new ExternalRenderTarget(external);
+                }
+
                 if (s is IFramebufferPlatformSurface fb)
-                    return new FramebufferShimRenderTarget(fb, s_imagingFactory, s_d2D1Factory, s_dwfactory);
+                {
+                    return new FramebufferShimRenderTarget(fb);
+                }
             }
             throw new NotSupportedException("Don't know how to create a Direct2D1 renderer from any of provided surfaces");
         }
@@ -156,19 +165,12 @@ namespace Avalonia.Direct2D1
             double dpiX,
             double dpiY)
         {
-            return new WicRenderTargetBitmapImpl(
-                s_imagingFactory,
-                s_d2D1Factory,
-                s_dwfactory,
-                width,
-                height,
-                dpiX,
-                dpiY);
+            return new WicRenderTargetBitmapImpl(width, height, dpiX, dpiY);
         }
 
         public IWriteableBitmapImpl CreateWriteableBitmap(int width, int height, PixelFormat? format = null)
         {
-            return new WriteableWicBitmapImpl(s_imagingFactory, width, height, format);
+            return new WriteableWicBitmapImpl(width, height, format);
         }
 
         public IStreamGeometryImpl CreateStreamGeometry()
@@ -178,17 +180,17 @@ namespace Avalonia.Direct2D1
 
         public IBitmapImpl LoadBitmap(string fileName)
         {
-            return new WicBitmapImpl(s_imagingFactory, fileName);
+            return new WicBitmapImpl(fileName);
         }
 
         public IBitmapImpl LoadBitmap(Stream stream)
         {
-            return new WicBitmapImpl(s_imagingFactory, stream);
+            return new WicBitmapImpl(stream);
         }
 
         public IBitmapImpl LoadBitmap(PixelFormat format, IntPtr data, int width, int height, int stride)
         {
-            return new WicBitmapImpl(s_imagingFactory, format, data, width, height, stride);
+            return new WicBitmapImpl(format, data, width, height, stride);
         }
     }
 }

+ 4 - 15
src/Windows/Avalonia.Direct2D1/ExternalRenderTarget.cs

@@ -3,24 +3,17 @@ using Avalonia.Direct2D1.Media.Imaging;
 using Avalonia.Platform;
 using Avalonia.Rendering;
 using SharpDX;
-using DirectWriteFactory = SharpDX.DirectWrite.Factory;
 
 namespace Avalonia.Direct2D1
 {
     class ExternalRenderTarget : IRenderTarget, ILayerFactory
     {
         private readonly IExternalDirect2DRenderTargetSurface _externalRenderTargetProvider;
-        private readonly DirectWriteFactory _dwFactory;
-        private readonly SharpDX.WIC.ImagingFactory _wicFactory;
 
         public ExternalRenderTarget(
-            IExternalDirect2DRenderTargetSurface externalRenderTargetProvider,
-            DirectWriteFactory dwFactory,
-            SharpDX.WIC.ImagingFactory wicFactory)
+            IExternalDirect2DRenderTargetSurface externalRenderTargetProvider)
         {
             _externalRenderTargetProvider = externalRenderTargetProvider;
-            _dwFactory = dwFactory;
-            _wicFactory = wicFactory;
         }
 
         public void Dispose()
@@ -32,7 +25,7 @@ namespace Avalonia.Direct2D1
         {
             var target =  _externalRenderTargetProvider.GetOrCreateRenderTarget();
             _externalRenderTargetProvider.BeforeDrawing();
-            return new DrawingContextImpl(visualBrushRenderer, null, target, _dwFactory, _wicFactory, null, () =>
+            return new DrawingContextImpl(visualBrushRenderer, null, target, null, () =>
             {
                 try
                 {
@@ -47,12 +40,8 @@ namespace Avalonia.Direct2D1
 
         public IRenderTargetBitmapImpl CreateLayer(Size size)
         {
-            var target = _externalRenderTargetProvider.GetOrCreateRenderTarget();
-            return D2DRenderTargetBitmapImpl.CreateCompatible(
-                _wicFactory,
-                _dwFactory,
-                target,
-                size);
+            var renderTarget = _externalRenderTargetProvider.GetOrCreateRenderTarget();
+            return D2DRenderTargetBitmapImpl.CreateCompatible(renderTarget, size);
         }
     }
 }

+ 5 - 18
src/Windows/Avalonia.Direct2D1/FramebufferShimRenderTarget.cs

@@ -4,7 +4,6 @@ using Avalonia.Direct2D1.Media;
 using Avalonia.Platform;
 using Avalonia.Rendering;
 using Avalonia.Win32.Interop;
-using SharpDX.Direct2D1;
 using SharpDX.WIC;
 using PixelFormat = Avalonia.Platform.PixelFormat;
 
@@ -13,22 +12,14 @@ namespace Avalonia.Direct2D1
     class FramebufferShimRenderTarget : IRenderTarget
     {
         private readonly IFramebufferPlatformSurface _surface;
-        private readonly ImagingFactory _imagingFactory;
-        private readonly Factory _d2DFactory;
-        private readonly SharpDX.DirectWrite.Factory _dwriteFactory;
 
-        public FramebufferShimRenderTarget(IFramebufferPlatformSurface surface,
-            ImagingFactory imagingFactory, Factory d2dFactory, SharpDX.DirectWrite.Factory dwriteFactory)
+        public FramebufferShimRenderTarget(IFramebufferPlatformSurface surface)
         {
             _surface = surface;
-            _imagingFactory = imagingFactory;
-            _d2DFactory = d2dFactory;
-            _dwriteFactory = dwriteFactory;
         }
 
         public void Dispose()
-        {
-            
+        {            
         }
 
         public IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer visualBrushRenderer)
@@ -40,7 +31,7 @@ namespace Avalonia.Direct2D1
                 throw new ArgumentException("Unsupported pixel format: " + locked.Format);
             }
 
-            return new FramebufferShim(locked, _imagingFactory, _d2DFactory, _dwriteFactory)
+            return new FramebufferShim(locked)
                 .CreateDrawingContext(visualBrushRenderer);
         }
 
@@ -48,10 +39,8 @@ namespace Avalonia.Direct2D1
         {
             private readonly ILockedFramebuffer _target;
 
-            public FramebufferShim(ILockedFramebuffer target,
-                ImagingFactory imagingFactory, Factory d2dFactory, SharpDX.DirectWrite.Factory dwriteFactory
-                ) : base(imagingFactory, d2dFactory, dwriteFactory,
-                    target.Width, target.Height, target.Dpi.X, target.Dpi.Y, target.Format)
+            public FramebufferShim(ILockedFramebuffer target) : 
+                base(target.Width, target.Height, target.Dpi.X, target.Dpi.Y, target.Format)
             {
                 _target = target;
             }
@@ -72,10 +61,8 @@ namespace Avalonia.Direct2D1
                     }
                     Dispose();
                     _target.Dispose();
-
                 });
             }
         }
-
     }
 }

+ 1 - 1
src/Windows/Avalonia.Direct2D1/HwndRenderTarget.cs

@@ -16,7 +16,7 @@ namespace Avalonia.Direct2D1
 
         protected override SwapChain1 CreateSwapChain(Factory2 dxgiFactory, SwapChainDescription1 swapChainDesc)
         {
-            return new SwapChain1(dxgiFactory, DxgiDevice, _window.Handle, ref swapChainDesc);
+            return new SwapChain1(dxgiFactory, Direct2D1Platform.DxgiDevice, _window.Handle, ref swapChainDesc);
         }
 
         protected override Size2F GetWindowDpi()

+ 4 - 36
src/Windows/Avalonia.Direct2D1/Media/AvaloniaTextRenderer.cs

@@ -1,7 +1,6 @@
 // Copyright (c) The Avalonia Project. All rights reserved.
 // Licensed under the MIT license. See licence.md file in the project root for full license information.
 
-using System;
 using SharpDX;
 using SharpDX.Direct2D1;
 using SharpDX.DirectWrite;
@@ -9,7 +8,7 @@ using SharpDX.Mathematics.Interop;
 
 namespace Avalonia.Direct2D1.Media
 {
-    internal class AvaloniaTextRenderer : TextRenderer
+    internal class AvaloniaTextRenderer : TextRendererBase
     {
         private readonly DrawingContextImpl _context;
 
@@ -27,18 +26,7 @@ namespace Avalonia.Direct2D1.Media
             _foreground = foreground;
         }
 
-        public IDisposable Shadow
-        {
-            get;
-            set;
-        }
-
-        public void Dispose()
-        {
-            Shadow?.Dispose();
-        }
-
-        public Result DrawGlyphRun(
+        public override Result DrawGlyphRun(
             object clientDrawingContext,
             float baselineOriginX,
             float baselineOriginY,
@@ -68,34 +56,14 @@ namespace Avalonia.Direct2D1.Media
             return Result.Ok;
         }
 
-        public Result DrawInlineObject(object clientDrawingContext, float originX, float originY, InlineObject inlineObject, bool isSideways, bool isRightToLeft, ComObject clientDrawingEffect)
-        {
-            throw new NotImplementedException();
-        }
-
-        public Result DrawStrikethrough(object clientDrawingContext, float baselineOriginX, float baselineOriginY, ref Strikethrough strikethrough, ComObject clientDrawingEffect)
-        {
-            throw new NotImplementedException();
-        }
-
-        public Result DrawUnderline(object clientDrawingContext, float baselineOriginX, float baselineOriginY, ref Underline underline, ComObject clientDrawingEffect)
-        {
-            throw new NotImplementedException();
-        }
-
-        public RawMatrix3x2 GetCurrentTransform(object clientDrawingContext)
+        public override RawMatrix3x2 GetCurrentTransform(object clientDrawingContext)
         {
             return _renderTarget.Transform;
         }
 
-        public float GetPixelsPerDip(object clientDrawingContext)
+        public override float GetPixelsPerDip(object clientDrawingContext)
         {
             return _renderTarget.DotsPerInch.Width / 96;
         }
-
-        public bool IsPixelSnappingDisabled(object clientDrawingContext)
-        {
-            return false;
-        }
     }
 }

+ 5 - 8
src/Windows/Avalonia.Direct2D1/Media/Direct2D1FontCollectionCache.cs

@@ -7,16 +7,13 @@ namespace Avalonia.Direct2D1.Media
     internal static class Direct2D1FontCollectionCache
     {
         private static readonly ConcurrentDictionary<FontFamilyKey, SharpDX.DirectWrite.FontCollection> s_cachedCollections;
-        private static readonly SharpDX.DirectWrite.Factory s_factory;
         private static readonly SharpDX.DirectWrite.FontCollection s_installedFontCollection;
 
         static Direct2D1FontCollectionCache()
         {
             s_cachedCollections = new ConcurrentDictionary<FontFamilyKey, SharpDX.DirectWrite.FontCollection>();
 
-            s_factory = AvaloniaLocator.Current.GetService<SharpDX.DirectWrite.Factory>();
-
-            s_installedFontCollection = s_factory.GetSystemFontCollection(false);
+            s_installedFontCollection = Direct2D1Platform.DirectWriteFactory.GetSystemFontCollection(false);
         }
 
         public static SharpDX.DirectWrite.TextFormat GetTextFormat(Typeface typeface)
@@ -39,7 +36,7 @@ namespace Avalonia.Direct2D1.Media
             }
 
             return new SharpDX.DirectWrite.TextFormat(
-                s_factory, 
+                Direct2D1Platform.DirectWriteFactory, 
                 fontFamilyName, 
                 fontCollection, 
                 (SharpDX.DirectWrite.FontWeight)typeface.Weight,
@@ -57,9 +54,9 @@ namespace Avalonia.Direct2D1.Media
         {
             var assets = FontFamilyLoader.LoadFontAssets(key);
 
-            var fontLoader = new DWriteResourceFontLoader(s_factory, assets);
+            var fontLoader = new DWriteResourceFontLoader(Direct2D1Platform.DirectWriteFactory, assets);
 
-            return new SharpDX.DirectWrite.FontCollection(s_factory, fontLoader, fontLoader.Key);
+            return new SharpDX.DirectWrite.FontCollection(Direct2D1Platform.DirectWriteFactory, fontLoader, fontLoader.Key);
         }
     }
-}
+}

+ 61 - 52
src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs

@@ -22,10 +22,9 @@ namespace Avalonia.Direct2D1.Media
         private readonly IVisualBrushRenderer _visualBrushRenderer;
         private readonly ILayerFactory _layerFactory;
         private readonly SharpDX.Direct2D1.RenderTarget _renderTarget;
+        private readonly DeviceContext _deviceContext;
         private readonly SharpDX.DXGI.SwapChain1 _swapChain;
         private readonly Action _finishedCallback;
-        private readonly SharpDX.WIC.ImagingFactory _imagingFactory;
-        private SharpDX.DirectWrite.Factory _directWriteFactory;
 
         /// <summary>
         /// Initializes a new instance of the <see cref="DrawingContextImpl"/> class.
@@ -36,16 +35,12 @@ namespace Avalonia.Direct2D1.Media
         /// An object to use to create layers. May be null, in which case a
         /// <see cref="WicRenderTargetBitmapImpl"/> will created when a new layer is requested.
         /// </param>
-        /// <param name="directWriteFactory">The DirectWrite factory.</param>
-        /// <param name="imagingFactory">The WIC imaging factory.</param>
         /// <param name="swapChain">An optional swap chain associated with this drawing context.</param>
         /// <param name="finishedCallback">An optional delegate to be called when context is disposed.</param>
         public DrawingContextImpl(
             IVisualBrushRenderer visualBrushRenderer,
             ILayerFactory layerFactory,
             SharpDX.Direct2D1.RenderTarget renderTarget,
-            SharpDX.DirectWrite.Factory directWriteFactory,
-            SharpDX.WIC.ImagingFactory imagingFactory,
             SharpDX.DXGI.SwapChain1 swapChain = null,
             Action finishedCallback = null)
         {
@@ -54,9 +49,17 @@ namespace Avalonia.Direct2D1.Media
             _renderTarget = renderTarget;
             _swapChain = swapChain;
             _finishedCallback = finishedCallback;
-            _directWriteFactory = directWriteFactory;
-            _imagingFactory = imagingFactory;
-            _renderTarget.BeginDraw();
+
+            if (_renderTarget is DeviceContext deviceContext)
+            {
+                _deviceContext = deviceContext;
+            }
+            else
+            {
+                _deviceContext = _renderTarget.QueryInterface<DeviceContext>();
+            }
+
+            _deviceContext.BeginDraw();
         }
 
         /// <summary>
@@ -64,14 +67,14 @@ namespace Avalonia.Direct2D1.Media
         /// </summary>
         public Matrix Transform
         {
-            get { return _renderTarget.Transform.ToAvalonia(); }
-            set { _renderTarget.Transform = value.ToDirect2D(); }
+            get { return _deviceContext.Transform.ToAvalonia(); }
+            set { _deviceContext.Transform = value.ToDirect2D(); }
         }
 
         /// <inheritdoc/>
         public void Clear(Color color)
         {
-            _renderTarget.Clear(color.ToDirect2D());
+            _deviceContext.Clear(color.ToDirect2D());
         }
 
         /// <summary>
@@ -80,10 +83,13 @@ namespace Avalonia.Direct2D1.Media
         public void Dispose()
         {
             foreach (var layer in _layerPool)
+            {
                 layer.Dispose();
+            }
+
             try
             {
-                _renderTarget.EndDraw();
+                _deviceContext.EndDraw();
 
                 _swapChain?.Present(1, SharpDX.DXGI.PresentFlags.None);
                 _finishedCallback?.Invoke();
@@ -104,29 +110,32 @@ namespace Avalonia.Direct2D1.Media
         /// <param name="bitmapInterpolationMode">The bitmap interpolation mode.</param>
         public void DrawImage(IRef<IBitmapImpl> source, double opacity, Rect sourceRect, Rect destRect, BitmapInterpolationMode bitmapInterpolationMode)
         {
-            using (var d2d = ((BitmapImpl)source.Item).GetDirect2DBitmap(_renderTarget))
+            using (var d2d = ((BitmapImpl)source.Item).GetDirect2DBitmap(_deviceContext))
             {
                 var interpolationMode = GetInterpolationMode(bitmapInterpolationMode);
 
-                _renderTarget.DrawBitmap(
+                _deviceContext.DrawBitmap(
                     d2d.Value,
                     destRect.ToSharpDX(),
                     (float)opacity,
                     interpolationMode,
-                    sourceRect.ToSharpDX());
+                    sourceRect.ToSharpDX(),
+                    null);
             }
         }
 
-        private static SharpDX.Direct2D1.BitmapInterpolationMode GetInterpolationMode(BitmapInterpolationMode interpolationMode)
+        private static InterpolationMode GetInterpolationMode(BitmapInterpolationMode interpolationMode)
         {
             switch (interpolationMode)
             {
                 case BitmapInterpolationMode.LowQuality:
-                    return SharpDX.Direct2D1.BitmapInterpolationMode.NearestNeighbor;
+                    return InterpolationMode.NearestNeighbor;
                 case BitmapInterpolationMode.MediumQuality:
+                    return InterpolationMode.Linear;
                 case BitmapInterpolationMode.HighQuality:
+                    return InterpolationMode.HighQualityCubic;
                 case BitmapInterpolationMode.Default:
-                    return SharpDX.Direct2D1.BitmapInterpolationMode.Linear;
+                    return InterpolationMode.Linear;
                 default:
                     throw new ArgumentOutOfRangeException(nameof(interpolationMode), interpolationMode, null);
             }
@@ -141,17 +150,17 @@ namespace Avalonia.Direct2D1.Media
         /// <param name="destRect">The rect in the output to draw to.</param>
         public void DrawImage(IRef<IBitmapImpl> source, IBrush opacityMask, Rect opacityMaskRect, Rect destRect)
         {
-            using (var d2dSource = ((BitmapImpl)source.Item).GetDirect2DBitmap(_renderTarget))
-            using (var sourceBrush = new BitmapBrush(_renderTarget, d2dSource.Value))
+            using (var d2dSource = ((BitmapImpl)source.Item).GetDirect2DBitmap(_deviceContext))
+            using (var sourceBrush = new BitmapBrush(_deviceContext, d2dSource.Value))
             using (var d2dOpacityMask = CreateBrush(opacityMask, opacityMaskRect.Size))
-            using (var geometry = new SharpDX.Direct2D1.RectangleGeometry(_renderTarget.Factory, destRect.ToDirect2D()))
+            using (var geometry = new SharpDX.Direct2D1.RectangleGeometry(_deviceContext.Factory, destRect.ToDirect2D()))
             {
                 if (d2dOpacityMask.PlatformBrush != null)
                 {
                     d2dOpacityMask.PlatformBrush.Transform = Matrix.CreateTranslation(opacityMaskRect.Position).ToDirect2D();
                 }
 
-                _renderTarget.FillGeometry(
+                _deviceContext.FillGeometry(
                     geometry,
                     sourceBrush,
                     d2dOpacityMask.PlatformBrush);
@@ -171,11 +180,11 @@ namespace Avalonia.Direct2D1.Media
                 var size = new Rect(p1, p2).Size;
 
                 using (var d2dBrush = CreateBrush(pen.Brush, size))
-                using (var d2dStroke = pen.ToDirect2DStrokeStyle(_renderTarget))
+                using (var d2dStroke = pen.ToDirect2DStrokeStyle(_deviceContext))
                 {
                     if (d2dBrush.PlatformBrush != null)
                     {
-                        _renderTarget.DrawLine(
+                        _deviceContext.DrawLine(
                             p1.ToSharpDX(),
                             p2.ToSharpDX(),
                             d2dBrush.PlatformBrush,
@@ -201,7 +210,7 @@ namespace Avalonia.Direct2D1.Media
                     if (d2dBrush.PlatformBrush != null)
                     {
                         var impl = (GeometryImpl)geometry;
-                        _renderTarget.FillGeometry(impl.Geometry, d2dBrush.PlatformBrush);
+                        _deviceContext.FillGeometry(impl.Geometry, d2dBrush.PlatformBrush);
                     }
                 }
             }
@@ -209,12 +218,12 @@ namespace Avalonia.Direct2D1.Media
             if (pen != null)
             {
                 using (var d2dBrush = CreateBrush(pen.Brush, geometry.GetRenderBounds(pen).Size))
-                using (var d2dStroke = pen.ToDirect2DStrokeStyle(_renderTarget))
+                using (var d2dStroke = pen.ToDirect2DStrokeStyle(_deviceContext))
                 {
                     if (d2dBrush.PlatformBrush != null)
                     {
                         var impl = (GeometryImpl)geometry;
-                        _renderTarget.DrawGeometry(impl.Geometry, d2dBrush.PlatformBrush, (float)pen.Thickness, d2dStroke);
+                        _deviceContext.DrawGeometry(impl.Geometry, d2dBrush.PlatformBrush, (float)pen.Thickness, d2dStroke);
                     }
                 }
             }
@@ -229,13 +238,13 @@ namespace Avalonia.Direct2D1.Media
         public void DrawRectangle(Pen pen, Rect rect, float cornerRadius)
         {
             using (var brush = CreateBrush(pen.Brush, rect.Size))
-            using (var d2dStroke = pen.ToDirect2DStrokeStyle(_renderTarget))
+            using (var d2dStroke = pen.ToDirect2DStrokeStyle(_deviceContext))
             {
                 if (brush.PlatformBrush != null)
                 {
                     if (cornerRadius == 0)
                     {
-                        _renderTarget.DrawRectangle(
+                        _deviceContext.DrawRectangle(
                             rect.ToDirect2D(),
                             brush.PlatformBrush,
                             (float)pen.Thickness,
@@ -243,7 +252,7 @@ namespace Avalonia.Direct2D1.Media
                     }
                     else
                     {
-                        _renderTarget.DrawRoundedRectangle(
+                        _deviceContext.DrawRoundedRectangle(
                             new RoundedRectangle { Rect = rect.ToDirect2D(), RadiusX = cornerRadius, RadiusY = cornerRadius },
                             brush.PlatformBrush,
                             (float)pen.Thickness,
@@ -266,7 +275,7 @@ namespace Avalonia.Direct2D1.Media
                 var impl = (FormattedTextImpl)text;
 
                 using (var brush = CreateBrush(foreground, impl.Size))
-                using (var renderer = new AvaloniaTextRenderer(this, _renderTarget, brush.PlatformBrush))
+                using (var renderer = new AvaloniaTextRenderer(this, _deviceContext, brush.PlatformBrush))
                 {
                     if (brush.PlatformBrush != null)
                     {
@@ -290,11 +299,11 @@ namespace Avalonia.Direct2D1.Media
                 {
                     if (cornerRadius == 0)
                     {
-                        _renderTarget.FillRectangle(rect.ToDirect2D(), b.PlatformBrush);
+                        _deviceContext.FillRectangle(rect.ToDirect2D(), b.PlatformBrush);
                     }
                     else
                     {
-                        _renderTarget.FillRoundedRectangle(
+                        _deviceContext.FillRoundedRectangle(
                             new RoundedRectangle
                             {
                                 Rect = new RawRectangleF(
@@ -320,7 +329,7 @@ namespace Avalonia.Direct2D1.Media
             else
             {
                 var platform = AvaloniaLocator.Current.GetService<IPlatformRenderInterface>();
-                var dpi = new Vector(_renderTarget.DotsPerInch.Width, _renderTarget.DotsPerInch.Height);
+                var dpi = new Vector(_deviceContext.DotsPerInch.Width, _deviceContext.DotsPerInch.Height);
                 var pixelSize = size * (dpi / 96);
                 return platform.CreateRenderTargetBitmap(
                     (int)pixelSize.Width,
@@ -337,12 +346,12 @@ namespace Avalonia.Direct2D1.Media
         /// <returns>A disposable used to undo the clip rectangle.</returns>
         public void PushClip(Rect clip)
         {
-            _renderTarget.PushAxisAlignedClip(clip.ToSharpDX(), AntialiasMode.PerPrimitive);
+            _deviceContext.PushAxisAlignedClip(clip.ToSharpDX(), AntialiasMode.PerPrimitive);
         }
 
         public void PopClip()
         {
-            _renderTarget.PopAxisAlignedClip();
+            _deviceContext.PopAxisAlignedClip();
         }
 
         readonly Stack<Layer> _layers = new Stack<Layer>();
@@ -363,8 +372,8 @@ namespace Avalonia.Direct2D1.Media
                     Opacity = (float)opacity,
                 };
 
-                var layer = _layerPool.Count != 0 ? _layerPool.Pop() : new Layer(_renderTarget);
-                _renderTarget.PushLayer(ref parameters, layer);
+                var layer = _layerPool.Count != 0 ? _layerPool.Pop() : new Layer(_deviceContext);
+                _deviceContext.PushLayer(ref parameters, layer);
 
                 _layers.Push(layer);
             }
@@ -382,7 +391,7 @@ namespace Avalonia.Direct2D1.Media
             var layer = _layers.Pop();
             if (layer != null)
             {
-                _renderTarget.PopLayer();
+                _deviceContext.PopLayer();
                 _layerPool.Push(layer);
             }
         }
@@ -403,21 +412,21 @@ namespace Avalonia.Direct2D1.Media
 
             if (solidColorBrush != null)
             {
-                return new SolidColorBrushImpl(solidColorBrush, _renderTarget);
+                return new SolidColorBrushImpl(solidColorBrush, _deviceContext);
             }
             else if (linearGradientBrush != null)
             {
-                return new LinearGradientBrushImpl(linearGradientBrush, _renderTarget, destinationSize);
+                return new LinearGradientBrushImpl(linearGradientBrush, _deviceContext, destinationSize);
             }
             else if (radialGradientBrush != null)
             {
-                return new RadialGradientBrushImpl(radialGradientBrush, _renderTarget, destinationSize);
+                return new RadialGradientBrushImpl(radialGradientBrush, _deviceContext, destinationSize);
             }
             else if (imageBrush?.Source != null)
             {
                 return new ImageBrushImpl(
                     imageBrush,
-                    _renderTarget,
+                    _deviceContext,
                     (BitmapImpl)imageBrush.Source.PlatformImpl.Item,
                     destinationSize);
             }
@@ -430,7 +439,7 @@ namespace Avalonia.Direct2D1.Media
                     if (intermediateSize.Width >= 1 && intermediateSize.Height >= 1)
                     {
                         using (var intermediate = new BitmapRenderTarget(
-                            _renderTarget,
+                            _deviceContext,
                             CompatibleRenderTargetOptions.None,
                             intermediateSize.ToSharpDX()))
                         {
@@ -442,8 +451,8 @@ namespace Avalonia.Direct2D1.Media
 
                             return new ImageBrushImpl(
                                 visualBrush,
-                                _renderTarget,
-                                new D2DBitmapImpl(_imagingFactory, intermediate.Bitmap),
+                                _deviceContext,
+                                new D2DBitmapImpl(intermediate.Bitmap),
                                 destinationSize);
                         }
                     }
@@ -454,7 +463,7 @@ namespace Avalonia.Direct2D1.Media
                 }
             }
 
-            return new SolidColorBrushImpl(null, _renderTarget);
+            return new SolidColorBrushImpl(null, _deviceContext);
         }
 
         public void PushGeometryClip(IGeometryImpl clip)
@@ -466,8 +475,8 @@ namespace Avalonia.Direct2D1.Media
                 Opacity = 1,
                 GeometricMask = ((GeometryImpl)clip).Geometry
             };
-            var layer = _layerPool.Count != 0 ? _layerPool.Pop() : new Layer(_renderTarget);
-            _renderTarget.PushLayer(ref parameters, layer);
+            var layer = _layerPool.Count != 0 ? _layerPool.Pop() : new Layer(_deviceContext);
+            _deviceContext.PushLayer(ref parameters, layer);
 
             _layers.Push(layer);
 
@@ -487,8 +496,8 @@ namespace Avalonia.Direct2D1.Media
                 Opacity = 1,
                 OpacityBrush = CreateBrush(mask, bounds.Size).PlatformBrush
             };
-            var layer = _layerPool.Count != 0 ? _layerPool.Pop() : new Layer(_renderTarget);
-            _renderTarget.PushLayer(ref parameters, layer);
+            var layer = _layerPool.Count != 0 ? _layerPool.Pop() : new Layer(_deviceContext);
+            _deviceContext.PushLayer(ref parameters, layer);
 
             _layers.Push(layer);
         }

+ 15 - 17
src/Windows/Avalonia.Direct2D1/Media/FormattedTextImpl.cs

@@ -21,24 +21,21 @@ namespace Avalonia.Direct2D1.Media
         {
             Text = text;
 
-            var factory = AvaloniaLocator.Current.GetService<DWrite.Factory>();
-
-            var textFormat = Direct2D1FontCollectionCache.GetTextFormat(typeface);
-
-            textFormat.WordWrapping =
-                wrapping == TextWrapping.Wrap ? DWrite.WordWrapping.Wrap : DWrite.WordWrapping.NoWrap;
-
-            TextLayout = new DWrite.TextLayout(
-                             factory,
-                             Text ?? string.Empty,
-                             textFormat,
-                             (float)constraint.Width,
-                             (float)constraint.Height)
+            using (var textFormat = Direct2D1FontCollectionCache.GetTextFormat(typeface))
             {
-                TextAlignment = textAlignment.ToDirect2D()
-            };
-
-            textFormat.Dispose();
+                textFormat.WordWrapping =
+                    wrapping == TextWrapping.Wrap ? DWrite.WordWrapping.Wrap : DWrite.WordWrapping.NoWrap;
+
+                TextLayout = new DWrite.TextLayout(
+                                 Direct2D1Platform.DirectWriteFactory,
+                                 Text ?? string.Empty,
+                                 textFormat,
+                                 (float)constraint.Width,
+                                 (float)constraint.Height)
+                             {
+                                 TextAlignment = textAlignment.ToDirect2D()
+                             };
+            }
 
             if (spans != null)
             {
@@ -110,6 +107,7 @@ namespace Avalonia.Direct2D1.Media
         private Size Measure()
         {
             var metrics = TextLayout.Metrics;
+
             var width = metrics.WidthIncludingTrailingWhitespace;
 
             if (float.IsNaN(width))

+ 1 - 2
src/Windows/Avalonia.Direct2D1/Media/GeometryImpl.cs

@@ -53,10 +53,9 @@ namespace Avalonia.Direct2D1.Media
 
         public ITransformedGeometryImpl WithTransform(Matrix transform)
         {
-            var factory = AvaloniaLocator.Current.GetService<Factory>();
             return new TransformedGeometryImpl(
                 new TransformedGeometry(
-                    factory,
+                    Direct2D1Platform.Direct2D1Factory,
                     GetSourceGeometry(),
                     transform.ToDirect2D()),
                 this);

+ 0 - 7
src/Windows/Avalonia.Direct2D1/Media/Imaging/BitmapImpl.cs

@@ -1,19 +1,12 @@
 using System;
 using System.IO;
 using Avalonia.Platform;
-using SharpDX.WIC;
 using D2DBitmap = SharpDX.Direct2D1.Bitmap;
 
 namespace Avalonia.Direct2D1.Media
 {
     public abstract class BitmapImpl : IBitmapImpl, IDisposable
     {
-        public BitmapImpl(ImagingFactory imagingFactory)
-        {
-            WicImagingFactory = imagingFactory;
-        }
-
-        public ImagingFactory WicImagingFactory { get; }
         public abstract int PixelWidth { get; }
         public abstract int PixelHeight { get; }
 

+ 20 - 27
src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DBitmapImpl.cs

@@ -1,10 +1,10 @@
-using System;
+// Copyright (c) The Avalonia Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
 using System.IO;
-using SharpDX.Direct2D1;
-using ImageParameters = SharpDX.WIC.ImageParameters;
-using ImagingFactory2 = SharpDX.WIC.ImagingFactory2;
-using PngBitmapEncoder = SharpDX.WIC.PngBitmapEncoder;
-using WICFactory = SharpDX.WIC.ImagingFactory;
+using SharpDX.WIC;
+using Bitmap = SharpDX.Direct2D1.Bitmap;
 
 namespace Avalonia.Direct2D1.Media
 {
@@ -13,53 +13,46 @@ namespace Avalonia.Direct2D1.Media
     /// </summary>
     public class D2DBitmapImpl : BitmapImpl
     {
-        private Bitmap _direct2D;
+        private readonly Bitmap _direct2DBitmap;
 
         /// <summary>
         /// Initialize a new instance of the <see cref="BitmapImpl"/> class
         /// with a bitmap backed by GPU memory.
         /// </summary>
-        /// <param name="imagingFactory">The image factory to use when saving out this bitmap.</param>
         /// <param name="d2DBitmap">The GPU bitmap.</param>
         /// <remarks>
         /// This bitmap must be either from the same render target,
         /// or if the render target is a <see cref="SharpDX.Direct2D1.DeviceContext"/>,
         /// the device associated with this context, to be renderable.
         /// </remarks>
-        public D2DBitmapImpl(WICFactory imagingFactory, Bitmap d2DBitmap)
-            : base(imagingFactory)
+        public D2DBitmapImpl(Bitmap d2DBitmap)
         {
-            _direct2D = d2DBitmap ?? throw new ArgumentNullException(nameof(d2DBitmap));
+            _direct2DBitmap = d2DBitmap ?? throw new ArgumentNullException(nameof(d2DBitmap));
         }
-              
-        public override int PixelWidth => _direct2D.PixelSize.Width;
-        public override int PixelHeight => _direct2D.PixelSize.Height;
+
+        public override int PixelWidth => _direct2DBitmap.PixelSize.Width;
+        public override int PixelHeight => _direct2DBitmap.PixelSize.Height;
 
         public override void Dispose()
         {
             base.Dispose();
-            _direct2D.Dispose();
+            _direct2DBitmap.Dispose();
         }
 
         public override OptionalDispose<Bitmap> GetDirect2DBitmap(SharpDX.Direct2D1.RenderTarget target)
         {
-            return new OptionalDispose<Bitmap>(_direct2D, false);
+            return new OptionalDispose<Bitmap>(_direct2DBitmap, false);
         }
 
         public override void Save(Stream stream)
         {
-            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))
+            using (var encoder = new PngBitmapEncoder(Direct2D1Platform.ImagingFactory, stream))
+            using (var frame = new BitmapFrameEncode(encoder))
+            using (var bitmapSource = _direct2DBitmap.QueryInterface<BitmapSource>())
             {
-                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();
+                frame.Initialize();
+                frame.WriteSource(bitmapSource);
+                frame.Commit();
                 encoder.Commit();
             }
         }

+ 15 - 26
src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DRenderTargetBitmapImpl.cs

@@ -1,34 +1,28 @@
-using Avalonia.Platform;
+// Copyright (c) The Avalonia Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+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, ILayerFactory
     {
-        private readonly DirectWriteFactory _dwriteFactory;
-        private readonly BitmapRenderTarget _target;
+        private readonly BitmapRenderTarget _renderTarget;
 
-        public D2DRenderTargetBitmapImpl(
-            ImagingFactory imagingFactory,
-            DirectWriteFactory dwriteFactory,
-            BitmapRenderTarget target)
-            : base(imagingFactory, target.Bitmap)
+        public D2DRenderTargetBitmapImpl(BitmapRenderTarget renderTarget)
+            : base(renderTarget.Bitmap)
         {
-            _dwriteFactory = dwriteFactory;
-            _target = target;
+            _renderTarget = renderTarget;
         }
 
-        public override int PixelWidth => _target.PixelSize.Width;
-        public override int PixelHeight => _target.PixelSize.Height;
+        public override int PixelWidth => _renderTarget.PixelSize.Width;
+        public override int PixelHeight => _renderTarget.PixelSize.Height;
 
         public static D2DRenderTargetBitmapImpl CreateCompatible(
-            ImagingFactory imagingFactory,
-            DirectWriteFactory dwriteFactory,
             SharpDX.Direct2D1.RenderTarget renderTarget,
             Size size)
         {
@@ -36,32 +30,27 @@ namespace Avalonia.Direct2D1.Media.Imaging
                 renderTarget,
                 CompatibleRenderTargetOptions.None,
                 new Size2F((float)size.Width, (float)size.Height));
-            return new D2DRenderTargetBitmapImpl(imagingFactory, dwriteFactory, bitmapRenderTarget);
+            return new D2DRenderTargetBitmapImpl(bitmapRenderTarget);
         }
 
         public IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer visualBrushRenderer)
         {
-            return new DrawingContextImpl(
-                visualBrushRenderer,
-                this,
-                _target,
-                _dwriteFactory,
-                WicImagingFactory);
+            return new DrawingContextImpl(visualBrushRenderer, this, _renderTarget);
         }
 
         public IRenderTargetBitmapImpl CreateLayer(Size size)
         {
-            return CreateCompatible(WicImagingFactory, _dwriteFactory, _target, size);
+            return CreateCompatible(_renderTarget, size);
         }
 
         public override void Dispose()
         {
-            _target.Dispose();
+            _renderTarget.Dispose();
         }
 
         public override OptionalDispose<D2DBitmap> GetDirect2DBitmap(SharpDX.Direct2D1.RenderTarget target)
         {
-            return new OptionalDispose<D2DBitmap>(_target.Bitmap, false);
+            return new OptionalDispose<D2DBitmap>(_renderTarget.Bitmap, false);
         }
     }
 }

+ 14 - 19
src/Windows/Avalonia.Direct2D1/Media/Imaging/WicBitmapImpl.cs

@@ -18,57 +18,52 @@ namespace Avalonia.Direct2D1.Media
         /// <summary>
         /// Initializes a new instance of the <see cref="WicBitmapImpl"/> class.
         /// </summary>
-        /// <param name="factory">The WIC imaging factory to use.</param>
         /// <param name="fileName">The filename of the bitmap to load.</param>
-        public WicBitmapImpl(ImagingFactory factory, string fileName)
-            : base(factory)
+        public WicBitmapImpl(string fileName)
         {
-            using (BitmapDecoder decoder = new BitmapDecoder(factory, fileName, DecodeOptions.CacheOnDemand))
+            using (BitmapDecoder decoder = new BitmapDecoder(Direct2D1Platform.ImagingFactory, fileName, DecodeOptions.CacheOnDemand))
             {
-                WicImpl = new Bitmap(factory, decoder.GetFrame(0), BitmapCreateCacheOption.CacheOnDemand);
+                WicImpl = new Bitmap(Direct2D1Platform.ImagingFactory, decoder.GetFrame(0), BitmapCreateCacheOption.CacheOnDemand);
             }
         }
 
         /// <summary>
         /// Initializes a new instance of the <see cref="WicBitmapImpl"/> class.
         /// </summary>
-        /// <param name="factory">The WIC imaging factory to use.</param>
         /// <param name="stream">The stream to read the bitmap from.</param>
-        public WicBitmapImpl(ImagingFactory factory, Stream stream)
-            : base(factory)
+        public WicBitmapImpl(Stream stream)
         {
-            using (BitmapDecoder decoder = new BitmapDecoder(factory, stream, DecodeOptions.CacheOnLoad))
+            using (BitmapDecoder decoder = new BitmapDecoder(Direct2D1Platform.ImagingFactory, stream, DecodeOptions.CacheOnLoad))
             {
-                WicImpl = new Bitmap(factory, decoder.GetFrame(0), BitmapCreateCacheOption.CacheOnLoad);
+                WicImpl = new Bitmap(Direct2D1Platform.ImagingFactory, decoder.GetFrame(0), BitmapCreateCacheOption.CacheOnLoad);
             }
         }
 
         /// <summary>
         /// Initializes a new instance of the <see cref="WicBitmapImpl"/> class.
         /// </summary>
-        /// <param name="factory">The WIC imaging factory to use.</param>
         /// <param name="width">The width of the bitmap.</param>
         /// <param name="height">The height of the bitmap.</param>
         /// <param name="pixelFormat">Pixel format</param>
-        public WicBitmapImpl(ImagingFactory factory, int width, int height, APixelFormat? pixelFormat = null)
-            : base(factory)
+        public WicBitmapImpl(int width, int height, APixelFormat? pixelFormat = null)
         {
             if (!pixelFormat.HasValue)
+            {
                 pixelFormat = APixelFormat.Bgra8888;
+            }
 
             PixelFormat = pixelFormat;
             WicImpl = new Bitmap(
-                factory,
+                Direct2D1Platform.ImagingFactory,
                 width,
                 height,
                 pixelFormat.Value.ToWic(),
                 BitmapCreateCacheOption.CacheOnLoad);
         }
 
-        public WicBitmapImpl(ImagingFactory factory, APixelFormat format, IntPtr data, int width, int height, int stride)
-            : base(factory)
+        public WicBitmapImpl(APixelFormat format, IntPtr data, int width, int height, int stride)
         {
-            WicImpl = new Bitmap(factory, width, height, format.ToWic(), BitmapCreateCacheOption.CacheOnDemand);
+            WicImpl = new Bitmap(Direct2D1Platform.ImagingFactory, width, height, format.ToWic(), BitmapCreateCacheOption.CacheOnDemand);
             PixelFormat = format;
             using (var l = WicImpl.Lock(BitmapLockFlags.Write))
             {
@@ -111,14 +106,14 @@ namespace Avalonia.Direct2D1.Media
         /// <returns>The Direct2D bitmap.</returns>
         public override OptionalDispose<D2DBitmap> GetDirect2DBitmap(SharpDX.Direct2D1.RenderTarget renderTarget)
         {
-            FormatConverter converter = new FormatConverter(WicImagingFactory);
+            FormatConverter converter = new FormatConverter(Direct2D1Platform.ImagingFactory);
             converter.Initialize(WicImpl, SharpDX.WIC.PixelFormat.Format32bppPBGRA);
             return new OptionalDispose<D2DBitmap>(D2DBitmap.FromWicBitmap(renderTarget, converter), true);
         }
 
         public override void Save(Stream stream)
         {
-            using (var encoder = new PngBitmapEncoder(WicImagingFactory, stream))
+            using (var encoder = new PngBitmapEncoder(Direct2D1Platform.ImagingFactory, stream))
             using (var frame = new BitmapFrameEncode(encoder))
             {
                 frame.Initialize();

+ 7 - 15
src/Windows/Avalonia.Direct2D1/Media/Imaging/WicRenderTargetBitmapImpl.cs

@@ -5,26 +5,20 @@ using System;
 using Avalonia.Platform;
 using Avalonia.Rendering;
 using SharpDX.Direct2D1;
-using SharpDX.WIC;
-using DirectWriteFactory = SharpDX.DirectWrite.Factory;
 
 namespace Avalonia.Direct2D1.Media
 {
     public class WicRenderTargetBitmapImpl : WicBitmapImpl, IRenderTargetBitmapImpl
     {
-        private readonly DirectWriteFactory _dwriteFactory;
-        private readonly WicRenderTarget _target;
+        private readonly WicRenderTarget _renderTarget;
 
         public WicRenderTargetBitmapImpl(
-            ImagingFactory imagingFactory,
-            Factory d2dFactory,
-            DirectWriteFactory dwriteFactory,
             int width,
             int height,
             double dpiX,
             double dpiY,
             Platform.PixelFormat? pixelFormat = null)
-            : base(imagingFactory, width, height, pixelFormat)
+            : base(width, height, pixelFormat)
         {
             var props = new RenderTargetProperties
             {
@@ -32,17 +26,16 @@ namespace Avalonia.Direct2D1.Media
                 DpiY = (float)dpiY,
             };
 
-            _target = new WicRenderTarget(
-                d2dFactory,
+            _renderTarget = new WicRenderTarget(
+                Direct2D1Platform.Direct2D1Factory,
                 WicImpl,
                 props);
-
-            _dwriteFactory = dwriteFactory;
         }
 
         public override void Dispose()
         {
-            _target.Dispose();
+            _renderTarget.Dispose();
+
             base.Dispose();
         }
 
@@ -51,8 +44,7 @@ namespace Avalonia.Direct2D1.Media
 
         public IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer visualBrushRenderer, Action finishedCallback)
         {
-            return new DrawingContextImpl(visualBrushRenderer, null, _target, _dwriteFactory, WicImagingFactory,
-                finishedCallback: finishedCallback);
+            return new DrawingContextImpl(visualBrushRenderer, null, _renderTarget, finishedCallback: finishedCallback);
         }
     }
 }

+ 6 - 3
src/Windows/Avalonia.Direct2D1/Media/Imaging/WriteableWicBitmapImpl.cs

@@ -1,4 +1,7 @@
-using System;
+// Copyright (c) The Avalonia Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using System;
 using Avalonia.Platform;
 using SharpDX.WIC;
 using PixelFormat = Avalonia.Platform.PixelFormat;
@@ -7,8 +10,8 @@ namespace Avalonia.Direct2D1.Media.Imaging
 {
     class WriteableWicBitmapImpl : WicBitmapImpl, IWriteableBitmapImpl
     {
-        public WriteableWicBitmapImpl(ImagingFactory factory, int width, int height, PixelFormat? pixelFormat) 
-            : base(factory, width, height, pixelFormat)
+        public WriteableWicBitmapImpl(int width, int height, PixelFormat? pixelFormat) 
+            : base(width, height, pixelFormat)
         {
         }
 

+ 2 - 4
src/Windows/Avalonia.Direct2D1/Media/StreamGeometryImpl.cs

@@ -31,8 +31,7 @@ namespace Avalonia.Direct2D1.Media
         /// <inheritdoc/>
         public IStreamGeometryImpl Clone()
         {
-            Factory factory = AvaloniaLocator.Current.GetService<Factory>();
-            var result = new PathGeometry(factory);
+            var result = new PathGeometry(Direct2D1Platform.Direct2D1Factory);
             var sink = result.Open();
             ((PathGeometry)Geometry).Stream(sink);
             sink.Close();
@@ -47,8 +46,7 @@ namespace Avalonia.Direct2D1.Media
 
         private static Geometry CreateGeometry()
         {
-            Factory factory = AvaloniaLocator.Current.GetService<Factory>();
-            return new PathGeometry(factory);
+            return new PathGeometry(Direct2D1Platform.Direct2D1Factory);
         }
     }
 }

+ 2 - 16
src/Windows/Avalonia.Direct2D1/RenderTarget.cs

@@ -5,9 +5,6 @@ using Avalonia.Direct2D1.Media;
 using Avalonia.Direct2D1.Media.Imaging;
 using Avalonia.Platform;
 using Avalonia.Rendering;
-using SharpDX.Direct2D1;
-using DwFactory = SharpDX.DirectWrite.Factory;
-using WicFactory = SharpDX.WIC.ImagingFactory;
 
 namespace Avalonia.Direct2D1
 {
@@ -24,32 +21,21 @@ namespace Avalonia.Direct2D1
         /// <param name="renderTarget">The render target.</param>
         public RenderTarget(SharpDX.Direct2D1.RenderTarget renderTarget)
         {
-            Direct2DFactory = AvaloniaLocator.Current.GetService<Factory>();
-            DirectWriteFactory = AvaloniaLocator.Current.GetService<DwFactory>();
-            WicFactory = AvaloniaLocator.Current.GetService<WicFactory>();
             _renderTarget = renderTarget;
         }
 
-        public Factory Direct2DFactory { get; }
-        public DwFactory DirectWriteFactory { get; }
-        public WicFactory WicFactory { get; }
-
         /// <summary>
         /// Creates a drawing context for a rendering session.
         /// </summary>
         /// <returns>An <see cref="Avalonia.Platform.IDrawingContextImpl"/>.</returns>
         public IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer visualBrushRenderer)
         {
-            return new DrawingContextImpl(visualBrushRenderer, this, _renderTarget, DirectWriteFactory, WicFactory);
+            return new DrawingContextImpl(visualBrushRenderer, this, _renderTarget);
         }
 
         public IRenderTargetBitmapImpl CreateLayer(Size size)
         {
-            return D2DRenderTargetBitmapImpl.CreateCompatible(
-                WicFactory,
-                DirectWriteFactory,
-                _renderTarget,
-                size);
+            return D2DRenderTargetBitmapImpl.CreateCompatible(_renderTarget, size);
         }
 
         public void Dispose()

+ 64 - 78
src/Windows/Avalonia.Direct2D1/SwapChainRenderTarget.cs

@@ -1,18 +1,16 @@
-using Avalonia.Direct2D1.Media;
+// Copyright (c) The Avalonia Project. All rights reserved.
+// Licensed under the MIT license. See licence.md file in the project root for full license information.
+
+using Avalonia.Direct2D1.Media;
 using Avalonia.Direct2D1.Media.Imaging;
 using Avalonia.Platform;
 using Avalonia.Rendering;
 using SharpDX;
 using SharpDX.Direct2D1;
 using SharpDX.DXGI;
-using AlphaMode = SharpDX.Direct2D1.AlphaMode;
-using Device = SharpDX.Direct2D1.Device;
-using Factory = SharpDX.Direct2D1.Factory;
-using Factory2 = SharpDX.DXGI.Factory2;
-using PixelFormat = SharpDX.Direct2D1.PixelFormat;
 
 namespace Avalonia.Direct2D1
-{
+{   
     public abstract class SwapChainRenderTarget : IRenderTarget, ILayerFactory
     {
         private Size2 _savedSize;
@@ -20,23 +18,6 @@ namespace Avalonia.Direct2D1
         private DeviceContext _deviceContext;
         private SwapChain1 _swapChain;
 
-        protected SwapChainRenderTarget()
-        {
-            DxgiDevice = AvaloniaLocator.Current.GetService<SharpDX.DXGI.Device>();
-            D2DDevice = AvaloniaLocator.Current.GetService<Device>();
-            Direct2DFactory = AvaloniaLocator.Current.GetService<Factory>();
-            DirectWriteFactory = AvaloniaLocator.Current.GetService<SharpDX.DirectWrite.Factory>();
-            WicImagingFactory = AvaloniaLocator.Current.GetService<SharpDX.WIC.ImagingFactory>();
-        }
-
-        public Factory Direct2DFactory { get; }
-        public SharpDX.DirectWrite.Factory DirectWriteFactory { get; }
-        public SharpDX.WIC.ImagingFactory WicImagingFactory { get; }
-
-        protected SharpDX.DXGI.Device DxgiDevice { get; }
-        
-        public Device D2DDevice { get; }
-
         /// <summary>
         /// Creates a drawing context for a rendering session.
         /// </summary>
@@ -50,87 +31,92 @@ namespace Avalonia.Direct2D1
             {
                 _savedSize = size;
                 _savedDpi = dpi;
-                CreateSwapChain();
+
+                Resize();
             }
 
-            return new DrawingContextImpl(
-                visualBrushRenderer,
-                this,
-                _deviceContext,
-                DirectWriteFactory,
-                WicImagingFactory,
-                _swapChain);
+            return new DrawingContextImpl(visualBrushRenderer, this, _deviceContext, _swapChain);
         }
 
         public IRenderTargetBitmapImpl CreateLayer(Size size)
         {
             if (_deviceContext == null)
             {
-                CreateSwapChain();
+                CreateDeviceContext();
             }
 
-            return D2DRenderTargetBitmapImpl.CreateCompatible(
-                WicImagingFactory,
-                DirectWriteFactory,
-                _deviceContext,
-                size);
+            return D2DRenderTargetBitmapImpl.CreateCompatible(_deviceContext, size);
         }
 
         public void Dispose()
         {
             _deviceContext?.Dispose();
+
             _swapChain?.Dispose();
         }
 
+        private void Resize()
+        {
+            _deviceContext?.Dispose();
+            _deviceContext = null;
+
+            _swapChain?.ResizeBuffers(0, 0, 0, Format.Unknown, SwapChainFlags.None);
+
+            CreateDeviceContext();
+        }
+
         private void CreateSwapChain()
         {
-            using (var dxgiAdaptor = DxgiDevice.Adapter)
-            using (var dxgiFactory = dxgiAdaptor.GetParent<Factory2>())
+            var swapChainDescription = new SwapChainDescription1
             {
-                _deviceContext?.Dispose();
-                _deviceContext = new DeviceContext(D2DDevice, DeviceContextOptions.None) {DotsPerInch = _savedDpi};
-
-                var swapChainDesc = new SwapChainDescription1
+                Width = _savedSize.Width,
+                Height = _savedSize.Height,
+                Format = Format.B8G8R8A8_UNorm,
+                SampleDescription = new SampleDescription
                 {
-                    Width = _savedSize.Width,
-                    Height = _savedSize.Height,
-                    Format = Format.B8G8R8A8_UNorm,
-                    Stereo = false,
-                    SampleDescription = new SampleDescription
+                    Count = 1,
+                    Quality = 0,
+                },
+                Usage = Usage.RenderTargetOutput,
+                BufferCount = 1,
+                SwapEffect = SwapEffect.Discard,
+            };
+
+            using (var dxgiAdapter = Direct2D1Platform.DxgiDevice.Adapter)
+            using (var dxgiFactory = dxgiAdapter.GetParent<SharpDX.DXGI.Factory2>())
+            {
+                _swapChain = CreateSwapChain(dxgiFactory, swapChainDescription);
+            }
+        }
+
+        private void CreateDeviceContext()
+        {
+            _deviceContext = new DeviceContext(Direct2D1Platform.Direct2D1Device, DeviceContextOptions.None) { DotsPerInch = _savedDpi };
+
+            if (_swapChain == null)
+            {
+                CreateSwapChain();
+            }
+
+            using (var dxgiBackBuffer = _swapChain.GetBackBuffer<Surface>(0))
+            using (var d2dBackBuffer = new Bitmap1(
+                _deviceContext,
+                dxgiBackBuffer,
+                new BitmapProperties1(
+                    new SharpDX.Direct2D1.PixelFormat
                     {
-                        Count = 1,
-                        Quality = 0,
+                        AlphaMode = SharpDX.Direct2D1.AlphaMode.Premultiplied,
+                        Format = Format.B8G8R8A8_UNorm
                     },
-                    Usage = Usage.RenderTargetOutput,
-                    BufferCount = 1,
-                    Scaling = Scaling.Stretch,
-                    SwapEffect = SwapEffect.Discard,
-                    Flags = 0,
-                };
-
-                _swapChain?.Dispose();
-                _swapChain = CreateSwapChain(dxgiFactory, swapChainDesc);
-
-                using (var dxgiBackBuffer = _swapChain.GetBackBuffer<Surface>(0))
-                using (var d2dBackBuffer = new Bitmap1(
-                    _deviceContext,
-                    dxgiBackBuffer,
-                    new BitmapProperties1(
-                        new PixelFormat
-                        {
-                            AlphaMode = AlphaMode.Premultiplied,
-                            Format = Format.B8G8R8A8_UNorm
-                        },
-                        _savedDpi.Width,
-                        _savedDpi.Height,
-                        BitmapOptions.Target | BitmapOptions.CannotDraw)))
-                {
-                    _deviceContext.Target = d2dBackBuffer;
-                }
+                    _savedSize.Width,
+                    _savedSize.Height,
+                    BitmapOptions.Target | BitmapOptions.CannotDraw)))
+            {
+                _deviceContext.Target = d2dBackBuffer;
             }
         }
 
-        protected abstract SwapChain1 CreateSwapChain(Factory2 dxgiFactory, SwapChainDescription1 swapChainDesc);
+        protected abstract SwapChain1 CreateSwapChain(SharpDX.DXGI.Factory2 dxgiFactory, SwapChainDescription1 swapChainDesc);
 
         protected abstract Size2F GetWindowDpi();