|
|
@@ -22,6 +22,7 @@ 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;
|
|
|
|
|
|
@@ -48,7 +49,17 @@ namespace Avalonia.Direct2D1.Media
|
|
|
_renderTarget = renderTarget;
|
|
|
_swapChain = swapChain;
|
|
|
_finishedCallback = finishedCallback;
|
|
|
- _renderTarget.BeginDraw();
|
|
|
+
|
|
|
+ if (_renderTarget is DeviceContext deviceContext)
|
|
|
+ {
|
|
|
+ _deviceContext = deviceContext;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ _deviceContext = _renderTarget.QueryInterface<DeviceContext>();
|
|
|
+ }
|
|
|
+
|
|
|
+ _deviceContext.BeginDraw();
|
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
|
@@ -56,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>
|
|
|
@@ -72,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();
|
|
|
@@ -96,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);
|
|
|
}
|
|
|
@@ -133,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);
|
|
|
@@ -163,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,
|
|
|
@@ -193,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);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -201,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);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
@@ -221,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,
|
|
|
@@ -235,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,
|
|
|
@@ -258,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)
|
|
|
{
|
|
|
@@ -282,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(
|
|
|
@@ -312,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,
|
|
|
@@ -329,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>();
|
|
|
@@ -355,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);
|
|
|
}
|
|
|
@@ -374,7 +391,7 @@ namespace Avalonia.Direct2D1.Media
|
|
|
var layer = _layers.Pop();
|
|
|
if (layer != null)
|
|
|
{
|
|
|
- _renderTarget.PopLayer();
|
|
|
+ _deviceContext.PopLayer();
|
|
|
_layerPool.Push(layer);
|
|
|
}
|
|
|
}
|
|
|
@@ -395,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);
|
|
|
}
|
|
|
@@ -422,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()))
|
|
|
{
|
|
|
@@ -434,7 +451,7 @@ namespace Avalonia.Direct2D1.Media
|
|
|
|
|
|
return new ImageBrushImpl(
|
|
|
visualBrush,
|
|
|
- _renderTarget,
|
|
|
+ _deviceContext,
|
|
|
new D2DBitmapImpl(intermediate.Bitmap),
|
|
|
destinationSize);
|
|
|
}
|
|
|
@@ -446,7 +463,7 @@ namespace Avalonia.Direct2D1.Media
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- return new SolidColorBrushImpl(null, _renderTarget);
|
|
|
+ return new SolidColorBrushImpl(null, _deviceContext);
|
|
|
}
|
|
|
|
|
|
public void PushGeometryClip(IGeometryImpl clip)
|
|
|
@@ -458,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);
|
|
|
|
|
|
@@ -479,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);
|
|
|
}
|