Browse Source

Merge branch 'master' into WindowIcon-MatchPattern

Steven Kirk 9 years ago
parent
commit
a19b33af30

+ 1 - 0
.gitignore

@@ -9,6 +9,7 @@
 *.suo
 *.user
 *.sln.docstates
+.vs/
 
 # Build results
 

+ 20 - 1
Avalonia.sln.DotSettings

@@ -2,6 +2,24 @@
 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=6417B24E_002D49C2_002D4985_002D8DB2_002D3AB9D898EC91/@EntryIndexedValue">ExplicitlyExcluded</s:String>
 	<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=E3A1060B_002D50D0_002D44E8_002D88B6_002DF44EF2E5BD72_002Ff_003Ahtml_002Ehtm/@EntryIndexedValue">ExplicitlyExcluded</s:String>
 	<s:String x:Key="/Default/CodeInspection/Highlighting/InspectionSeverities/=RedundantUsingDirective/@EntryIndexedValue">HINT</s:String>
+	<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=DECLSPEC_005FPROPERTY/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
+	<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=ENUM/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /&gt;</s:String>
+	<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=ENUMERATOR/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /&gt;</s:String>
+	<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=GETTER/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /&gt;</s:String>
+	<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=GLOBAL_005FFUNCTION/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /&gt;</s:String>
+	<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=GLOBAL_005FVARIABLE/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /&gt;</s:String>
+	<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=LOCAL_005FTYPEDEF/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /&gt;</s:String>
+	<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=LOCAL_005FVARIABLE/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /&gt;</s:String>
+	<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=NAMESPACE/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /&gt;</s:String>
+	<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=PARAMETER/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /&gt;</s:String>
+	<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=SETTER/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="set_" Suffix="" Style="aa_bb" /&gt;</s:String>
+	<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=STRUCT/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /&gt;</s:String>
+	<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=STRUCT_005FFIELD/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="_" Style="aa_bb" /&gt;</s:String>
+	<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=STRUCT_005FMETHODS/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /&gt;</s:String>
+	<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=TEMPLATE_005FPARAMETER/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /&gt;</s:String>
+	<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=TYPEDEF/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /&gt;</s:String>
+	<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=UNION/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /&gt;</s:String>
+	<s:String x:Key="/Default/CodeStyle/Naming/CppNaming/UserRules/=UNION_005FMEMBER/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" /&gt;</s:String>
 	<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Constants/@EntryIndexedValue">&lt;Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
 	<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=EnumMember/@EntryIndexedValue">&lt;Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
 	<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Interfaces/@EntryIndexedValue">&lt;Policy Inspect="False" Prefix="I" Suffix="" Style="AaBb" /&gt;</s:String>
@@ -10,8 +28,9 @@
 	<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Other/@EntryIndexedValue">&lt;Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
 	<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=Parameters/@EntryIndexedValue">&lt;Policy Inspect="False" Prefix="" Suffix="" Style="aaBb" /&gt;</s:String>
 	<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateConstants/@EntryIndexedValue">&lt;Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
+	<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateInstanceFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" /&gt;</s:String>
 	<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticFields/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="s_" Suffix="" Style="aaBb" /&gt;</s:String>
-	<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"&gt;&lt;ExtraRule Prefix="s_" Suffix="" Style="aaBb" /&gt;&lt;/Policy&gt;</s:String>
+	<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=PrivateStaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="s_" Suffix="" Style="aaBb" /&gt;</s:String>
 	<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=StaticReadonly/@EntryIndexedValue">&lt;Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String>
 	<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=TypeParameters/@EntryIndexedValue">&lt;Policy Inspect="False" Prefix="T" Suffix="" Style="AaBb" /&gt;</s:String>
 	<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/PredefinedNamingRules/=TypesAndNamespaces/@EntryIndexedValue">&lt;Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" /&gt;</s:String></wpf:ResourceDictionary>

+ 11 - 9
src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj

@@ -37,17 +37,17 @@
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
   </PropertyGroup>
   <ItemGroup>
-    <Reference Include="SharpDX, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
-      <HintPath>..\..\..\packages\SharpDX.3.1.0\lib\net45\SharpDX.dll</HintPath>
-      <Private>True</Private>
+    <Reference Include="SharpDX, Version=3.1.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
+      <HintPath>..\..\..\packages\SharpDX.3.1.1\lib\net45\SharpDX.dll</HintPath>
     </Reference>
-    <Reference Include="SharpDX.Direct2D1, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
-      <HintPath>..\..\..\packages\SharpDX.Direct2D1.3.1.0\lib\net45\SharpDX.Direct2D1.dll</HintPath>
-      <Private>True</Private>
+    <Reference Include="SharpDX.Direct2D1, Version=3.1.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
+      <HintPath>..\..\..\packages\SharpDX.Direct2D1.3.1.1\lib\net45\SharpDX.Direct2D1.dll</HintPath>
     </Reference>
-    <Reference Include="SharpDX.DXGI, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
-      <HintPath>..\..\..\packages\SharpDX.DXGI.3.1.0\lib\net45\SharpDX.DXGI.dll</HintPath>
-      <Private>True</Private>
+    <Reference Include="SharpDX.Direct3D11, Version=3.1.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
+      <HintPath>..\..\..\packages\SharpDX.Direct3D11.3.1.1\lib\net45\SharpDX.Direct3D11.dll</HintPath>
+    </Reference>
+    <Reference Include="SharpDX.DXGI, Version=3.1.1.0, Culture=neutral, PublicKeyToken=b4dcf0f35e5521f1, processorArchitecture=MSIL">
+      <HintPath>..\..\..\packages\SharpDX.DXGI.3.1.1\lib\net45\SharpDX.DXGI.dll</HintPath>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Core" />
@@ -62,6 +62,7 @@
     </Compile>
     <Compile Include="Direct2D1Platform.cs" />
     <Compile Include="Disposable.cs" />
+    <Compile Include="HwndRenderTarget.cs" />
     <Compile Include="Media\BrushImpl.cs" />
     <Compile Include="Media\BrushWrapper.cs" />
     <Compile Include="Media\DrawingContext.cs" />
@@ -79,6 +80,7 @@
     <Compile Include="PrimitiveExtensions.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="RenderTarget.cs" />
+    <Compile Include="SwapChainRenderTarget.cs" />
   </ItemGroup>
   <ItemGroup>
     <None Include="app.config" />

+ 38 - 5
src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs

@@ -29,20 +29,53 @@ namespace Avalonia.Direct2D1
 
         private static readonly SharpDX.Direct2D1.Factory s_d2D1Factory =
 #if DEBUG
-            new SharpDX.Direct2D1.Factory(SharpDX.Direct2D1.FactoryType.SingleThreaded, SharpDX.Direct2D1.DebugLevel.Error);
+            new SharpDX.Direct2D1.Factory1(SharpDX.Direct2D1.FactoryType.MultiThreaded, SharpDX.Direct2D1.DebugLevel.Error);
 #else
-            new SharpDX.Direct2D1.Factory(SharpDX.Direct2D1.FactoryType.SingleThreaded, SharpDX.Direct2D1.DebugLevel.None);
+            new SharpDX.Direct2D1.Factory1(SharpDX.Direct2D1.FactoryType.MultiThreaded, SharpDX.Direct2D1.DebugLevel.None);
 #endif
         private static readonly SharpDX.DirectWrite.Factory s_dwfactory = new SharpDX.DirectWrite.Factory();
 
         private static readonly SharpDX.WIC.ImagingFactory s_imagingFactory = new SharpDX.WIC.ImagingFactory();
 
+        private static readonly SharpDX.DXGI.Device s_dxgiDevice;
+
+        private static readonly SharpDX.Direct2D1.Device s_d2D1Device;
+
+        static Direct2D1Platform()
+        {
+            var featureLevels = new[]
+            {
+                SharpDX.Direct3D.FeatureLevel.Level_11_1,
+                SharpDX.Direct3D.FeatureLevel.Level_11_0,
+                SharpDX.Direct3D.FeatureLevel.Level_10_1,
+                SharpDX.Direct3D.FeatureLevel.Level_10_0,
+                SharpDX.Direct3D.FeatureLevel.Level_9_3,
+                SharpDX.Direct3D.FeatureLevel.Level_9_2,
+                SharpDX.Direct3D.FeatureLevel.Level_9_1,
+            };
+
+            using (var d3dDevice = new SharpDX.Direct3D11.Device(
+                SharpDX.Direct3D.DriverType.Hardware,
+                SharpDX.Direct3D11.DeviceCreationFlags.BgraSupport | SharpDX.Direct3D11.DeviceCreationFlags.VideoSupport,
+                featureLevels))
+            {
+                s_dxgiDevice = d3dDevice.QueryInterface<SharpDX.DXGI.Device>();
+            }
+
+            using (var factory1 = s_d2D1Factory.QueryInterface<SharpDX.Direct2D1.Factory1>())
+            {
+                s_d2D1Device = new SharpDX.Direct2D1.Device(factory1, s_dxgiDevice);
+            }
+        }
+
         public static void Initialize() => AvaloniaLocator.CurrentMutable
             .Bind<IPlatformRenderInterface>().ToConstant(s_instance)
             .Bind<IRendererFactory>().ToConstant(s_instance)
             .BindToSelf(s_d2D1Factory)
             .BindToSelf(s_dwfactory)
-            .BindToSelf(s_imagingFactory);
+            .BindToSelf(s_imagingFactory)
+            .BindToSelf(s_dxgiDevice)
+            .BindToSelf(s_d2D1Device);
 
         public IBitmapImpl CreateBitmap(int width, int height)
         {
@@ -70,7 +103,7 @@ namespace Avalonia.Direct2D1
         {
             if (handle.HandleDescriptor == "HWND")
             {
-                return new RenderTarget(handle.Handle);
+                return new HwndRenderTarget(handle.Handle);
             }
             else
             {
@@ -82,7 +115,7 @@ namespace Avalonia.Direct2D1
 
         public IRenderTargetBitmapImpl CreateRenderTargetBitmap(int width, int height)
         {
-            return new RenderTargetBitmapImpl(s_imagingFactory, s_d2D1Factory, width, height);
+            return new RenderTargetBitmapImpl(s_imagingFactory, s_d2D1Device.Factory, width, height);
         }
 
         public IStreamGeometryImpl CreateStreamGeometry()

+ 56 - 0
src/Windows/Avalonia.Direct2D1/HwndRenderTarget.cs

@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Avalonia.Win32.Interop;
+using SharpDX;
+using SharpDX.DXGI;
+
+namespace Avalonia.Direct2D1
+{
+    class HwndRenderTarget : SwapChainRenderTarget
+    {
+        private readonly IntPtr _hwnd;
+
+        public HwndRenderTarget(IntPtr hwnd)
+        {
+            _hwnd = hwnd;
+        }
+
+        protected override SwapChain1 CreateSwapChain(Factory2 dxgiFactory, SwapChainDescription1 swapChainDesc)
+        {
+            return new SwapChain1(dxgiFactory, DxgiDevice, _hwnd, ref swapChainDesc);
+        }
+
+        protected override Size2F GetWindowDpi()
+        {
+            if (UnmanagedMethods.ShCoreAvailable)
+            {
+                uint dpix, dpiy;
+
+                var monitor = UnmanagedMethods.MonitorFromWindow(
+                    _hwnd,
+                    UnmanagedMethods.MONITOR.MONITOR_DEFAULTTONEAREST);
+
+                if (UnmanagedMethods.GetDpiForMonitor(
+                        monitor,
+                        UnmanagedMethods.MONITOR_DPI_TYPE.MDT_EFFECTIVE_DPI,
+                        out dpix,
+                        out dpiy) == 0)
+                {
+                    return new Size2F(dpix, dpiy);
+                }
+            }
+
+            return new Size2F(96, 96);
+        }
+
+        protected override Size2 GetWindowSize()
+        {
+            UnmanagedMethods.RECT rc;
+            UnmanagedMethods.GetClientRect(_hwnd, out rc);
+            return new Size2(rc.right - rc.left, rc.bottom - rc.top);
+        }
+    }
+}

+ 8 - 1
src/Windows/Avalonia.Direct2D1/Media/DrawingContext.cs

@@ -27,17 +27,22 @@ namespace Avalonia.Direct2D1.Media
         /// </summary>
         private SharpDX.DirectWrite.Factory _directWriteFactory;
 
+        private SharpDX.DXGI.SwapChain1 _swapChain;
+
         /// <summary>
         /// Initializes a new instance of the <see cref="DrawingContext"/> class.
         /// </summary>
         /// <param name="renderTarget">The render target to draw to.</param>
         /// <param name="directWriteFactory">The DirectWrite factory.</param>
+        /// <param name="swapChain">An optional swap chain associated with this drawing context.</param>
         public DrawingContext(
             SharpDX.Direct2D1.RenderTarget renderTarget,
-            SharpDX.DirectWrite.Factory directWriteFactory)
+            SharpDX.DirectWrite.Factory directWriteFactory,
+            SharpDX.DXGI.SwapChain1 swapChain = null)
         {
             _renderTarget = renderTarget;
             _directWriteFactory = directWriteFactory;
+            _swapChain = swapChain;
             _renderTarget.BeginDraw();
         }
 
@@ -60,6 +65,8 @@ namespace Avalonia.Direct2D1.Media
             try
             {
                 _renderTarget.EndDraw();
+                
+                _swapChain?.Present(1, SharpDX.DXGI.PresentFlags.None);
             }
             catch (SharpDXException ex) when((uint)ex.HResult == 0x8899000C) // D2DERR_RECREATE_TARGET
             {

+ 0 - 79
src/Windows/Avalonia.Direct2D1/RenderTarget.cs

@@ -13,42 +13,11 @@ namespace Avalonia.Direct2D1
 {
     public class RenderTarget : IRenderTarget
     {
-        private readonly IntPtr _hwnd;
-        private Size2 _savedSize;
-        private Size2F _savedDpi;
-
         /// <summary>
         /// The render target.
         /// </summary>
         private readonly SharpDX.Direct2D1.RenderTarget _renderTarget;
 
-        /// <summary>
-        /// Initializes a new instance of the <see cref="RenderTarget"/> class.
-        /// </summary>
-        /// <param name="hwnd">The window handle.</param>
-        public RenderTarget(IntPtr hwnd)
-        {
-            _hwnd = hwnd;
-            Direct2DFactory = AvaloniaLocator.Current.GetService<Factory>();
-            DirectWriteFactory = AvaloniaLocator.Current.GetService<DwFactory>();
-
-            RenderTargetProperties renderTargetProperties = new RenderTargetProperties
-            {
-            };
-
-            HwndRenderTargetProperties hwndProperties = new HwndRenderTargetProperties
-            {
-                Hwnd = hwnd,
-                PixelSize = _savedSize = GetWindowSize(),
-                PresentOptions = PresentOptions.Immediately,
-            };
-
-            _renderTarget = new WindowRenderTarget(
-                Direct2DFactory,
-                renderTargetProperties,
-                hwndProperties);
-        }
-
         /// <summary>
         /// Initializes a new instance of the <see cref="RenderTarget"/> class.
         /// </summary>
@@ -82,24 +51,6 @@ namespace Avalonia.Direct2D1
         /// <returns>An <see cref="Avalonia.Media.DrawingContext"/>.</returns>
         public DrawingContext CreateDrawingContext()
         {
-            var window = _renderTarget as WindowRenderTarget;
-
-            if (window != null)
-            {
-                var size = GetWindowSize();
-                var dpi = GetWindowDpi();
-
-                if (size != _savedSize)
-                {
-                    window.Resize(_savedSize = size);
-                }
-
-                if (dpi != _savedDpi)
-                {
-                    window.DotsPerInch = _savedDpi = dpi;
-                }
-            }
-
             return new DrawingContext(new Media.DrawingContext(_renderTarget, DirectWriteFactory));
         }
 
@@ -107,35 +58,5 @@ namespace Avalonia.Direct2D1
         {
             _renderTarget.Dispose();
         }
-
-        private Size2F GetWindowDpi()
-        {
-            if (UnmanagedMethods.ShCoreAvailable)
-            {
-                uint dpix, dpiy;
-
-                var monitor = UnmanagedMethods.MonitorFromWindow(
-                    _hwnd,
-                    UnmanagedMethods.MONITOR.MONITOR_DEFAULTTONEAREST);
-
-                if (UnmanagedMethods.GetDpiForMonitor(
-                        monitor,
-                        UnmanagedMethods.MONITOR_DPI_TYPE.MDT_EFFECTIVE_DPI,
-                        out dpix,
-                        out dpiy) == 0)
-                {
-                    return new Size2F(dpix, dpiy);
-                }
-            }
-
-            return new Size2F(96, 96);
-        }
-
-        private Size2 GetWindowSize()
-        {
-            UnmanagedMethods.RECT rc;
-            UnmanagedMethods.GetClientRect(_hwnd, out rc);
-            return new Size2(rc.right - rc.left, rc.bottom - rc.top);
-        }
     }
 }

+ 135 - 0
src/Windows/Avalonia.Direct2D1/SwapChainRenderTarget.cs

@@ -0,0 +1,135 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Avalonia.Media;
+using Avalonia.Platform;
+using Avalonia.Win32.Interop;
+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;
+
+namespace Avalonia.Direct2D1
+{
+    public abstract class SwapChainRenderTarget : IRenderTarget
+    {
+        private Size2 _savedSize;
+        private Size2F _savedDpi;
+        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>();
+        }
+
+
+        /// <summary>
+        /// Gets the Direct2D factory.
+        /// </summary>
+        public Factory Direct2DFactory
+        {
+            get;
+        }
+
+        /// <summary>
+        /// Gets the DirectWrite factory.
+        /// </summary>
+        public SharpDX.DirectWrite.Factory DirectWriteFactory
+        {
+            get;
+        }
+
+        protected SharpDX.DXGI.Device DxgiDevice { get; }
+        
+        public Device D2DDevice { get; }
+
+        /// <summary>
+        /// Creates a drawing context for a rendering session.
+        /// </summary>
+        /// <returns>An <see cref="Avalonia.Media.DrawingContext"/>.</returns>
+        public DrawingContext CreateDrawingContext()
+        {
+            var size = GetWindowSize();
+            var dpi = GetWindowDpi();
+
+            if (size != _savedSize || dpi != _savedDpi)
+            {
+                _savedSize = size;
+                _savedDpi = dpi;
+                CreateSwapChain();
+            }
+
+            return new DrawingContext(new Media.DrawingContext(_deviceContext, DirectWriteFactory, _swapChain));
+        }
+
+        public void Dispose()
+        {
+            _deviceContext?.Dispose();
+            _swapChain?.Dispose();
+        }
+
+        private void CreateSwapChain()
+        {
+            using (var dxgiAdaptor = DxgiDevice.Adapter)
+            using (var dxgiFactory = dxgiAdaptor.GetParent<Factory2>())
+            {
+                _deviceContext?.Dispose();
+                _deviceContext = new DeviceContext(D2DDevice, DeviceContextOptions.None) {DotsPerInch = _savedDpi};
+
+
+                var swapChainDesc = new SwapChainDescription1
+                {
+                    Width = _savedSize.Width,
+                    Height = _savedSize.Height,
+                    Format = Format.B8G8R8A8_UNorm,
+                    Stereo = false,
+                    SampleDescription = new SampleDescription
+                    {
+                        Count = 1,
+                        Quality = 0,
+                    },
+                    Usage = Usage.RenderTargetOutput,
+                    BufferCount = 2,
+                    Scaling = Scaling.None,
+                    SwapEffect = SwapEffect.FlipSequential,
+                    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.Ignore,
+                            Format = Format.B8G8R8A8_UNorm
+                        },
+                        _savedDpi.Width,
+                        _savedDpi.Height,
+                        BitmapOptions.Target | BitmapOptions.CannotDraw)))
+                {
+                    _deviceContext.Target = d2dBackBuffer;
+                }
+            }
+        }
+
+        protected abstract SwapChain1 CreateSwapChain(Factory2 dxgiFactory, SwapChainDescription1 swapChainDesc);
+
+        protected abstract Size2F GetWindowDpi();
+
+        protected abstract Size2 GetWindowSize();
+    }
+}

+ 2 - 2
src/Windows/Avalonia.Direct2D1/app.config

@@ -8,11 +8,11 @@
       </dependentAssembly>
       <dependentAssembly>
         <assemblyIdentity name="SharpDX" publicKeyToken="b4dcf0f35e5521f1" culture="neutral" />
-        <bindingRedirect oldVersion="0.0.0.0-3.0.2.0" newVersion="3.0.2.0" />
+        <bindingRedirect oldVersion="0.0.0.0-3.1.1.0" newVersion="3.1.1.0" />
       </dependentAssembly>
       <dependentAssembly>
         <assemblyIdentity name="SharpDX.DXGI" publicKeyToken="b4dcf0f35e5521f1" culture="neutral" />
-        <bindingRedirect oldVersion="0.0.0.0-3.0.2.0" newVersion="3.0.2.0" />
+        <bindingRedirect oldVersion="0.0.0.0-3.1.1.0" newVersion="3.1.1.0" />
       </dependentAssembly>
     </assemblyBinding>
   </runtime>

+ 4 - 3
src/Windows/Avalonia.Direct2D1/packages.config

@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-  <package id="SharpDX" version="3.1.0" targetFramework="net45" />
-  <package id="SharpDX.Direct2D1" version="3.1.0" targetFramework="net45" />
-  <package id="SharpDX.DXGI" version="3.1.0" targetFramework="net45" />
+  <package id="SharpDX" version="3.1.1" targetFramework="net45" />
+  <package id="SharpDX.Direct2D1" version="3.1.1" targetFramework="net45" />
+  <package id="SharpDX.Direct3D11" version="3.1.1" targetFramework="net45" />
+  <package id="SharpDX.DXGI" version="3.1.1" targetFramework="net45" />
 </packages>