Browse Source

Merge pull request #1861 from Gillibald/Direct2D1LocatorRemoval

Direct2D1 cleanup
pull/1891/head
Steven Kirk 8 years ago
committed by GitHub
parent
commit
370001b3df
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 278
      samples/interop/Direct3DInteropSample/MainWindow.cs
  2. 92
      src/Windows/Avalonia.Direct2D1/Direct2D1Platform.cs
  3. 19
      src/Windows/Avalonia.Direct2D1/ExternalRenderTarget.cs
  4. 23
      src/Windows/Avalonia.Direct2D1/FramebufferShimRenderTarget.cs
  5. 2
      src/Windows/Avalonia.Direct2D1/HwndRenderTarget.cs
  6. 40
      src/Windows/Avalonia.Direct2D1/Media/AvaloniaTextRenderer.cs
  7. 13
      src/Windows/Avalonia.Direct2D1/Media/Direct2D1FontCollectionCache.cs
  8. 113
      src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs
  9. 32
      src/Windows/Avalonia.Direct2D1/Media/FormattedTextImpl.cs
  10. 3
      src/Windows/Avalonia.Direct2D1/Media/GeometryImpl.cs
  11. 7
      src/Windows/Avalonia.Direct2D1/Media/Imaging/BitmapImpl.cs
  12. 47
      src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DBitmapImpl.cs
  13. 41
      src/Windows/Avalonia.Direct2D1/Media/Imaging/D2DRenderTargetBitmapImpl.cs
  14. 33
      src/Windows/Avalonia.Direct2D1/Media/Imaging/WicBitmapImpl.cs
  15. 22
      src/Windows/Avalonia.Direct2D1/Media/Imaging/WicRenderTargetBitmapImpl.cs
  16. 9
      src/Windows/Avalonia.Direct2D1/Media/Imaging/WriteableWicBitmapImpl.cs
  17. 6
      src/Windows/Avalonia.Direct2D1/Media/StreamGeometryImpl.cs
  18. 18
      src/Windows/Avalonia.Direct2D1/RenderTarget.cs
  19. 142
      src/Windows/Avalonia.Direct2D1/SwapChainRenderTarget.cs

278
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);
}
}

92
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);
}
}
}

19
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);
}
}
}

23
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();
});
}
}
}
}

2
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()

40
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;
}
}
}

13
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);
}
}
}
}

113
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);
}

32
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))

3
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);

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; }

47
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();
}
}

41
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);
}
}
}

33
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();

22
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);
}
}
}

9
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)
{
}

6
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);
}
}
}

18
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()

142
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();

Loading…
Cancel
Save