Skip to content

Commit

Permalink
Move DirectDraw/Write code off of COM Interop
Browse files Browse the repository at this point in the history
Leverage TerraFX interop function pointer definitions to remove all usages of [ComImport] in the DirectX library.

To keep overhead low, wrappers are usually presented as structs. "Inheritance" is accomplished via conversion operators and internal interface hierarchies (kept internal to avoid accidental boxing).

Existing demos work, including custom text rendering. There is an initial manual CCW for that, which I'll undoubtably iterate on to try and simplify creation of these things.
  • Loading branch information
JeremyKuhne committed Nov 29, 2021
1 parent 1d70f40 commit bc3eef5
Show file tree
Hide file tree
Showing 151 changed files with 6,169 additions and 6,575 deletions.
4 changes: 2 additions & 2 deletions src/Performance/FunctionPointers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ namespace Performance
[MemoryDiagnoser]
public unsafe class FunctionPointers
{
private IUnknown* _punk;
private Unknown* _punk;
private string _path;

[GlobalSetup]
public void GlobalSetup()
{
_path = Path.Join(Path.GetTempPath(), Path.GetRandomFileName());
_punk = (IUnknown*)CreateStorage(_path, InterfaceIds.IID_IStorage);
_punk = (Unknown*)CreateStorage(_path, InterfaceIds.IID_IStorage);
}

[GlobalCleanup]
Expand Down
2 changes: 1 addition & 1 deletion src/Performance/Performance.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.12.1.1453" />
<PackageReference Include="BenchmarkDotNet" Version="0.13.1" />
<PackageReference Include="Microsoft.Win32.SystemEvents" Version="5.0.0" />
</ItemGroup>

Expand Down
94 changes: 94 additions & 0 deletions src/Samples/CoreWindows/Direct2dDemo/CombineGeometries.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// Copyright (c) Jeremy W. Kuhne. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Drawing;
using System.Numerics;
using WInterop.Direct2d;
using WInterop.DirectX;
using WInterop.Windows;

namespace Direct2dDemo
{
// https://docs.microsoft.com/windows/win32/direct2d/how-to-combine-geometries
public class CombineGeometries : DirectXWindowClass
{
private readonly EllipseGeometry _circleGeometry1;
private readonly EllipseGeometry _circleGeometry2;
private readonly PathGeometry _geometryUnion;
private readonly PathGeometry _geometryIntersect;
private readonly PathGeometry _geometryXOR;
private readonly PathGeometry _geometryExclude;
private SolidColorBrush _brush;
private SolidColorBrush _strokeBrush;
private SolidColorBrush _fillBrush;

public CombineGeometries() : base()
{
_circleGeometry1 = Direct2dFactory.CreateEllipseGeometry(new((75.0f, 75.0f), 50.0f, 50.0f));
_circleGeometry2 = Direct2dFactory.CreateEllipseGeometry(new((125.0f, 75.0f), 50.0f, 50.0f));
_geometryUnion = Direct2dFactory.CreatePathGeometry();
using (var sink = _geometryUnion.Open())
{
_circleGeometry1.CombineWithGeometry(_circleGeometry2, CombineMode.Union, sink);
}

_geometryIntersect = Direct2dFactory.CreatePathGeometry();
using (var sink = _geometryIntersect.Open())
{
_circleGeometry1.CombineWithGeometry(_circleGeometry2, CombineMode.Intersect, sink);
}

_geometryXOR = Direct2dFactory.CreatePathGeometry();
using (var sink = _geometryXOR.Open())
{
_circleGeometry1.CombineWithGeometry(_circleGeometry2, CombineMode.XOr, sink);
}

_geometryExclude = Direct2dFactory.CreatePathGeometry();
using (var sink = _geometryExclude.Open())
{
_circleGeometry1.CombineWithGeometry(_circleGeometry2, CombineMode.Exclude, sink);
}
}

protected override void CreateResources()
{
_brush = RenderTarget.CreateSolidColorBrush(Color.Black);
_strokeBrush = RenderTarget.CreateSolidColorBrush(Color.Blue);
_fillBrush = RenderTarget.CreateSolidColorBrush(new(Color.CornflowerBlue, 0.5f));
}

protected override void OnPaint(WindowHandle window)
{
RenderTarget.Transform = Matrix3x2.Identity;
RenderTarget.Clear(Color.White);

RenderTarget.Transform = Matrix3x2.CreateTranslation(new(20, 100));
RenderTarget.FillGeometry(_circleGeometry1, _fillBrush);
RenderTarget.DrawGeometry(_circleGeometry1, _strokeBrush);
RenderTarget.FillGeometry(_circleGeometry2, _fillBrush);
RenderTarget.DrawGeometry(_circleGeometry2, _strokeBrush);
RenderTarget.Transform = Matrix3x2.Identity;

RenderTarget.Transform = Matrix3x2.CreateTranslation(new(300, 0));
RenderTarget.FillGeometry(_geometryUnion, _fillBrush);
RenderTarget.DrawGeometry(_geometryUnion, _strokeBrush);
RenderTarget.Transform = Matrix3x2.Identity;

RenderTarget.Transform = Matrix3x2.CreateTranslation(new(550, 0));
RenderTarget.FillGeometry(_geometryIntersect, _fillBrush);
RenderTarget.DrawGeometry(_geometryIntersect, _strokeBrush);
RenderTarget.Transform = Matrix3x2.Identity;

RenderTarget.Transform = Matrix3x2.CreateTranslation(new(300, 200));
RenderTarget.FillGeometry(_geometryXOR, _fillBrush);
RenderTarget.DrawGeometry(_geometryXOR, _strokeBrush);
RenderTarget.Transform = Matrix3x2.Identity;

RenderTarget.Transform = Matrix3x2.CreateTranslation(new(550, 200));
RenderTarget.FillGeometry(_geometryExclude, _fillBrush);
RenderTarget.DrawGeometry(_geometryExclude, _strokeBrush);
RenderTarget.Transform = Matrix3x2.Identity;
}
}
}
18 changes: 10 additions & 8 deletions src/Samples/CoreWindows/Direct2dDemo/Direct2dDemo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,21 @@
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Drawing;
using System.Numerics;
using WInterop.Direct2d;
using WInterop.DirectX;
using WInterop.Windows;

namespace Direct2dDemo
{
// https://docs.microsoft.com/en-us/windows/desktop/Direct2D/direct2d-quickstart
/// <summary>
/// Implementation of the <see href="https://docs.microsoft.com/en-us/windows/win32/direct2d/direct2d-quickstart">
/// Simple Direct2D Application</see>.
/// </summary>
public class Direct2dDemo : DirectXWindowClass
{
private ISolidColorBrush _lightSlateGrayBrush;
private ISolidColorBrush _cornflowerBlueBrush;
private SolidColorBrush _lightSlateGrayBrush;
private SolidColorBrush _cornflowerBlueBrush;

protected override void CreateResources()
{
Expand All @@ -22,16 +26,14 @@ protected override void CreateResources()

protected override void OnPaint(WindowHandle window)
{
RenderTarget.SetTransform();
RenderTarget.Transform = Matrix3x2.Identity;
RenderTarget.Clear(Color.White);
Size size = RenderTarget.GetSize().ToSize();

_lightSlateGrayBrush.GetColor(out ColorF color);
Size size = RenderTarget.Size.ToSize();

for (int x = 0; x < size.Width; x += 10)
{
RenderTarget.DrawLine(
new Point(x, 0), new Point(x, size.Height),
(x, 0), (x, size.Height),
_lightSlateGrayBrush, 0.5f);
}

Expand Down
28 changes: 19 additions & 9 deletions src/Samples/CoreWindows/Direct2dDemo/DrawEllipse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,19 @@

namespace Direct2dDemo
{
// https://docs.microsoft.com/en-us/windows/desktop/Direct2D/how-to-draw-an-ellipse
// https://docs.microsoft.com/windows/desktop/Direct2D/how-to-draw-an-ellipse
public class DrawEllipse : DirectXWindowClass
{
private ISolidColorBrush _blackBrush;
private ISolidColorBrush _silverBrush;
private readonly IStrokeStyle _dashDotDotStyle;
private SolidColorBrush _blackBrush;
private SolidColorBrush _silverBrush;
private readonly StrokeStyle _dashDotDotStyle;

public DrawEllipse() : base()
{
StrokeStyleProperties style = new StrokeStyleProperties(dashCap: CapStyle.Triangle, miterLimit: 10.0f, dashStyle: DashStyle.DashDotDot);
StrokeStyleProperties style = new(
dashCap: CapStyle.Triangle,
miterLimit: 10.0f,
dashStyle: DashStyle.DashDotDot);
_dashDotDotStyle = Direct2dFactory.CreateStrokeStyle(style);
}

Expand All @@ -31,19 +34,26 @@ protected override void OnPaint(WindowHandle window)
{
RenderTarget.Clear(Color.White);

Ellipse ellipse = new Ellipse(new PointF(100.0f, 100.0f), 75.0f, 50.0f);
Ellipse ellipse = new((100.0f, 100.0f), 75.0f, 50.0f);
RenderTarget.DrawEllipse(ellipse, _blackBrush, 10.0f);

Ellipse ellipse2 = new Ellipse(new PointF(300.0f, 100.0f), 75.0f, 50.0f);
Ellipse ellipse2 = new((300.0f, 100.0f), 75.0f, 50.0f);
RenderTarget.DrawEllipse(ellipse2, _blackBrush, 10.0f, _dashDotDotStyle);

Ellipse ellipse3 = new Ellipse(new PointF(500.0f, 100.0f), 75.0f, 50.0f);
Ellipse ellipse3 = new((500.0f, 100.0f), 75.0f, 50.0f);
RenderTarget.DrawEllipse(ellipse3, _blackBrush, 10.0f, _dashDotDotStyle);
RenderTarget.FillEllipse(ellipse3, _silverBrush);

Ellipse ellipse4 = new Ellipse(new PointF(700.0f, 100.0f), 75.0f, 50.0f);
Ellipse ellipse4 = new((700.0f, 100.0f), 75.0f, 50.0f);
RenderTarget.FillEllipse(ellipse4, _silverBrush);
RenderTarget.DrawEllipse(ellipse4, _blackBrush, 10.0f, _dashDotDotStyle);
}

protected override void Dispose(bool disposing)
{
_blackBrush.Dispose();
_silverBrush.Dispose();
_dashDotDotStyle.Dispose();
}
}
}
Loading

0 comments on commit bc3eef5

Please sign in to comment.