8 changed files with 265 additions and 19 deletions
@ -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); |
|||
} |
|||
} |
|||
} |
|||
@ -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<SharpDX.DXGI.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 Device { 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 d2dDevice = new Device(Device)) |
|||
using (var dxgiAdaptor = Device.Adapter) |
|||
using (var dxgiFactory = dxgiAdaptor.GetParent<Factory2>()) |
|||
{ |
|||
_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<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(); |
|||
} |
|||
} |
|||
@ -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> |
|||
Loading…
Reference in new issue