diff --git a/Avalonia.sln.DotSettings b/Avalonia.sln.DotSettings
index bf98899847..16c9218a7e 100644
--- a/Avalonia.sln.DotSettings
+++ b/Avalonia.sln.DotSettings
@@ -2,6 +2,24 @@
ExplicitlyExcluded
ExplicitlyExcluded
HINT
+ <Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
+ <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" />
+ <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" />
+ <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" />
+ <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" />
+ <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" />
+ <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" />
+ <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" />
+ <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" />
+ <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" />
+ <Policy Inspect="True" Prefix="set_" Suffix="" Style="aa_bb" />
+ <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" />
+ <Policy Inspect="True" Prefix="" Suffix="_" Style="aa_bb" />
+ <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" />
+ <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" />
+ <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" />
+ <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" />
+ <Policy Inspect="True" Prefix="" Suffix="" Style="aa_bb" />
<Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" />
<Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" />
<Policy Inspect="False" Prefix="I" Suffix="" Style="AaBb" />
@@ -10,6 +28,7 @@
<Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" />
<Policy Inspect="False" Prefix="" Suffix="" Style="aaBb" />
<Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" />
+ <Policy Inspect="True" Prefix="_" Suffix="" Style="aaBb" />
<Policy Inspect="True" Prefix="s_" Suffix="" Style="aaBb" />
<Policy Inspect="True" Prefix="" Suffix="" Style="AaBb"><ExtraRule Prefix="s_" Suffix="" Style="aaBb" /></Policy>
<Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
diff --git a/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj b/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj
index 9f9558ff76..95ccc98692 100644
--- a/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj
+++ b/src/Windows/Avalonia.Direct2D1/Avalonia.Direct2D1.csproj
@@ -37,17 +37,17 @@
true
-
- ..\..\..\packages\SharpDX.3.1.0\lib\net45\SharpDX.dll
- True
+
+ ..\..\..\packages\SharpDX.3.1.1\lib\net45\SharpDX.dll
-
- ..\..\..\packages\SharpDX.Direct2D1.3.1.0\lib\net45\SharpDX.Direct2D1.dll
- True
+
+ ..\..\..\packages\SharpDX.Direct2D1.3.1.1\lib\net45\SharpDX.Direct2D1.dll
-
- ..\..\..\packages\SharpDX.DXGI.3.1.0\lib\net45\SharpDX.DXGI.dll
- True
+
+ ..\..\..\packages\SharpDX.Direct3D11.3.1.1\lib\net45\SharpDX.Direct3D11.dll
+
+
+ ..\..\..\packages\SharpDX.DXGI.3.1.1\lib\net45\SharpDX.DXGI.dll
@@ -62,6 +62,7 @@
+
@@ -79,6 +80,7 @@
+
diff --git a/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs b/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs
index b43eef2fa9..f86fa0b93a 100644
--- a/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs
+++ b/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs
@@ -8,6 +8,7 @@ using Avalonia.Media;
using Avalonia.Platform;
using Avalonia.Controls;
using Avalonia.Rendering;
+using SharpDX.Direct3D11;
namespace Avalonia
{
@@ -29,20 +30,47 @@ 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.Factory(SharpDX.Direct2D1.FactoryType.MultiThreaded, SharpDX.Direct2D1.DebugLevel.Error);
#else
- new SharpDX.Direct2D1.Factory(SharpDX.Direct2D1.FactoryType.SingleThreaded, SharpDX.Direct2D1.DebugLevel.None);
+ new SharpDX.Direct2D1.Factory(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_device;
+
+ static Direct2D1Platform()
+ {
+ var featureLevels = new[]
+ {
+ SharpDX.Direct3D.FeatureLevel.Level_12_1,
+ SharpDX.Direct3D.FeatureLevel.Level_12_0,
+ 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_device = d3dDevice.QueryInterface();
+ }
+ }
+
public static void Initialize() => AvaloniaLocator.CurrentMutable
.Bind().ToConstant(s_instance)
.Bind().ToConstant(s_instance)
.BindToSelf(s_d2D1Factory)
.BindToSelf(s_dwfactory)
- .BindToSelf(s_imagingFactory);
+ .BindToSelf(s_imagingFactory)
+ .BindToSelf(s_device);
public IBitmapImpl CreateBitmap(int width, int height)
{
@@ -70,7 +98,7 @@ namespace Avalonia.Direct2D1
{
if (handle.HandleDescriptor == "HWND")
{
- return new RenderTarget(handle.Handle);
+ return new HwndRenderTarget(handle.Handle);
}
else
{
diff --git a/src/Windows/Avalonia.Direct2D1/HwndRenderTarget.cs b/src/Windows/Avalonia.Direct2D1/HwndRenderTarget.cs
new file mode 100644
index 0000000000..5c0c460dcb
--- /dev/null
+++ b/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, Device, _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);
+ }
+ }
+}
diff --git a/src/Windows/Avalonia.Direct2D1/Media/DrawingContext.cs b/src/Windows/Avalonia.Direct2D1/Media/DrawingContext.cs
index 75a0f43d9f..decf3c6fc6 100644
--- a/src/Windows/Avalonia.Direct2D1/Media/DrawingContext.cs
+++ b/src/Windows/Avalonia.Direct2D1/Media/DrawingContext.cs
@@ -27,6 +27,8 @@ namespace Avalonia.Direct2D1.Media
///
private SharpDX.DirectWrite.Factory _directWriteFactory;
+ private SharpDX.DXGI.SwapChain1 _swapChain;
+
///
/// Initializes a new instance of the class.
///
@@ -34,10 +36,12 @@ namespace Avalonia.Direct2D1.Media
/// The DirectWrite factory.
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 +64,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
{
diff --git a/src/Windows/Avalonia.Direct2D1/SwapChainRenderTarget.cs b/src/Windows/Avalonia.Direct2D1/SwapChainRenderTarget.cs
new file mode 100644
index 0000000000..a7b2f532c2
--- /dev/null
+++ b/src/Windows/Avalonia.Direct2D1/SwapChainRenderTarget.cs
@@ -0,0 +1,134 @@
+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()
+ {
+ Device = AvaloniaLocator.Current.GetService();
+ Direct2DFactory = AvaloniaLocator.Current.GetService();
+ DirectWriteFactory = AvaloniaLocator.Current.GetService();
+ }
+
+
+ ///
+ /// Gets the Direct2D factory.
+ ///
+ public Factory Direct2DFactory
+ {
+ get;
+ }
+
+ ///
+ /// Gets the DirectWrite factory.
+ ///
+ public SharpDX.DirectWrite.Factory DirectWriteFactory
+ {
+ get;
+ }
+
+ protected SharpDX.DXGI.Device Device { get; }
+
+ ///
+ /// Creates a drawing context for a rendering session.
+ ///
+ /// An .
+ 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 d2dDevice = new Device(Device))
+ using (var dxgiAdaptor = Device.Adapter)
+ using (var dxgiFactory = dxgiAdaptor.GetParent())
+ {
+ _deviceContext?.Dispose();
+ _deviceContext = new DeviceContext(d2dDevice, DeviceContextOptions.None);
+
+ 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,
+ };
+
+ var dpi = Direct2DFactory.DesktopDpi;
+
+ _swapChain?.Dispose();
+ _swapChain = CreateSwapChain(dxgiFactory, swapChainDesc);
+
+ using (var dxgiBackBuffer = _swapChain.GetBackBuffer(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();
+ }
+}
diff --git a/src/Windows/Avalonia.Direct2D1/app.config b/src/Windows/Avalonia.Direct2D1/app.config
index 743de168f3..60a1012655 100644
--- a/src/Windows/Avalonia.Direct2D1/app.config
+++ b/src/Windows/Avalonia.Direct2D1/app.config
@@ -8,11 +8,11 @@
-
+
-
+
diff --git a/src/Windows/Avalonia.Direct2D1/packages.config b/src/Windows/Avalonia.Direct2D1/packages.config
index 57031c2b9d..780e6014e5 100644
--- a/src/Windows/Avalonia.Direct2D1/packages.config
+++ b/src/Windows/Avalonia.Direct2D1/packages.config
@@ -1,6 +1,7 @@
-
-
-
+
+
+
+
\ No newline at end of file