diff --git a/.gitignore b/.gitignore
index a510c4e49f..d16287cfb4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,6 +9,7 @@
*.suo
*.user
*.sln.docstates
+.vs/
# Build results
diff --git a/Avalonia.sln.DotSettings b/Avalonia.sln.DotSettings
index bf98899847..ab21d6e50b 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,8 +28,9 @@
<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="s_" Suffix="" Style="aaBb" />
<Policy Inspect="True" Prefix="" Suffix="" Style="AaBb" />
<Policy Inspect="False" Prefix="T" Suffix="" Style="AaBb" />
<Policy Inspect="False" Prefix="" Suffix="" Style="AaBb" />
\ No newline at end of file
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..a073407a6c 100644
--- a/src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs
+++ b/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();
+ }
+
+ using (var factory1 = s_d2D1Factory.QueryInterface())
+ {
+ s_d2D1Device = new SharpDX.Direct2D1.Device(factory1, s_dxgiDevice);
+ }
+ }
+
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_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()
diff --git a/src/Windows/Avalonia.Direct2D1/HwndRenderTarget.cs b/src/Windows/Avalonia.Direct2D1/HwndRenderTarget.cs
new file mode 100644
index 0000000000..49d4c91c52
--- /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, 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);
+ }
+ }
+}
diff --git a/src/Windows/Avalonia.Direct2D1/Media/DrawingContext.cs b/src/Windows/Avalonia.Direct2D1/Media/DrawingContext.cs
index 75a0f43d9f..486116c27b 100644
--- a/src/Windows/Avalonia.Direct2D1/Media/DrawingContext.cs
+++ b/src/Windows/Avalonia.Direct2D1/Media/DrawingContext.cs
@@ -27,17 +27,22 @@ namespace Avalonia.Direct2D1.Media
///
private SharpDX.DirectWrite.Factory _directWriteFactory;
+ private SharpDX.DXGI.SwapChain1 _swapChain;
+
///
/// Initializes a new instance of the class.
///
/// The render target to draw to.
/// The DirectWrite factory.
+ /// An optional swap chain associated with this drawing context.
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
{
diff --git a/src/Windows/Avalonia.Direct2D1/RenderTarget.cs b/src/Windows/Avalonia.Direct2D1/RenderTarget.cs
index 180e1a7472..52146d77c1 100644
--- a/src/Windows/Avalonia.Direct2D1/RenderTarget.cs
+++ b/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;
-
///
/// The render target.
///
private readonly SharpDX.Direct2D1.RenderTarget _renderTarget;
- ///
- /// Initializes a new instance of the class.
- ///
- /// The window handle.
- public RenderTarget(IntPtr hwnd)
- {
- _hwnd = hwnd;
- Direct2DFactory = AvaloniaLocator.Current.GetService();
- DirectWriteFactory = AvaloniaLocator.Current.GetService();
-
- RenderTargetProperties renderTargetProperties = new RenderTargetProperties
- {
- };
-
- HwndRenderTargetProperties hwndProperties = new HwndRenderTargetProperties
- {
- Hwnd = hwnd,
- PixelSize = _savedSize = GetWindowSize(),
- PresentOptions = PresentOptions.Immediately,
- };
-
- _renderTarget = new WindowRenderTarget(
- Direct2DFactory,
- renderTargetProperties,
- hwndProperties);
- }
-
///
/// Initializes a new instance of the class.
///
@@ -82,24 +51,6 @@ namespace Avalonia.Direct2D1
/// An .
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);
- }
}
}
diff --git a/src/Windows/Avalonia.Direct2D1/SwapChainRenderTarget.cs b/src/Windows/Avalonia.Direct2D1/SwapChainRenderTarget.cs
new file mode 100644
index 0000000000..8362305b9f
--- /dev/null
+++ b/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();
+ D2DDevice = 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 DxgiDevice { get; }
+
+ public Device D2DDevice { 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 dxgiAdaptor = DxgiDevice.Adapter)
+ using (var dxgiFactory = dxgiAdaptor.GetParent())
+ {
+ _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(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