Browse Source

Merge pull request #5012 from AvaloniaUI/winrt-interop

Use MicroCom for WinRT interop
pull/5051/head
Dan Walmsley 6 years ago
committed by GitHub
parent
commit
abca18ee95
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      NuGet.Config
  2. 8
      build/MicroCom.targets
  3. 1
      samples/Sandbox/MainWindow.axaml.cs
  4. 2
      src/Avalonia.MicroCom/MicroComProxyBase.cs
  5. 28
      src/Avalonia.MicroCom/MicroComRuntime.cs
  6. 8
      src/Avalonia.OpenGL/Egl/EglContext.cs
  7. 79
      src/Avalonia.Visuals/Rendering/DeferredRenderer.cs
  8. 7
      src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs
  9. 10
      src/Avalonia.X11/X11Window.cs
  10. 1
      src/Windows/Avalonia.Win32/.gitignore
  11. 4
      src/Windows/Avalonia.Win32/Avalonia.Win32.csproj
  12. 18
      src/Windows/Avalonia.Win32/Composition/CompositionBlurHost.cs
  13. 171
      src/Windows/Avalonia.Win32/Composition/CompositionConnector.cs
  14. 96
      src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs
  15. 91
      src/Windows/Avalonia.Win32/Composition/D2DEffects.cs
  16. 45
      src/Windows/Avalonia.Win32/Composition/EffectBase.cs
  17. 18
      src/Windows/Avalonia.Win32/Composition/GRAPHICS_EFFECT_PROPERTY_MAPPING.cs
  18. 57
      src/Windows/Avalonia.Win32/Composition/GaussianBlurEffect.cs
  19. 8
      src/Windows/Avalonia.Win32/Composition/IBlurHost.cs
  20. 152
      src/Windows/Avalonia.Win32/Composition/ICompositionDrawingSurfaceInterop.cs
  21. 14
      src/Windows/Avalonia.Win32/Composition/ICompositorDesktopInterop.cs
  22. 69
      src/Windows/Avalonia.Win32/Composition/ICompositorDesktopInterop1.cs
  23. 139
      src/Windows/Avalonia.Win32/Composition/ICompositorInterop.cs
  24. 24
      src/Windows/Avalonia.Win32/Composition/IGraphicsEffectD2D1Interop.cs
  25. 217
      src/Windows/Avalonia.Win32/Composition/IGraphicsEffectD2D1Interop1.cs
  26. 35
      src/Windows/Avalonia.Win32/Composition/SaturationEffect.cs
  27. 12
      src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs
  28. 10
      src/Windows/Avalonia.Win32/Win32GlManager.cs
  29. 130
      src/Windows/Avalonia.Win32/WinRT/Composition/D2DEffects.cs
  30. 99
      src/Windows/Avalonia.Win32/WinRT/Composition/WinUICompositedWindow.cs
  31. 238
      src/Windows/Avalonia.Win32/WinRT/Composition/WinUICompositorConnection.cs
  32. 135
      src/Windows/Avalonia.Win32/WinRT/Composition/WinUIEffectBase.cs
  33. 118
      src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs
  34. 7
      src/Windows/Avalonia.Win32/WinRT/IBlurHost.cs
  35. 140
      src/Windows/Avalonia.Win32/WinRT/NativeWinRTMethods.cs
  36. 18
      src/Windows/Avalonia.Win32/WinRT/WinRTColor.cs
  37. 38
      src/Windows/Avalonia.Win32/WinRT/WinRTInspectable.cs
  38. 89
      src/Windows/Avalonia.Win32/WinRT/WinRTPropertyValue.cs
  39. 718
      src/Windows/Avalonia.Win32/WinRT/winrt.idl
  40. 21
      src/Windows/Avalonia.Win32/WindowImpl.cs
  41. 7
      src/tools/MicroComGenerator/AstParser.cs
  42. 47
      src/tools/MicroComGenerator/CSharpGen.InterfaceGen.cs
  43. 9
      src/tools/MicroComGenerator/CSharpGen.Utils.cs
  44. 30
      src/tools/MicroComGenerator/CSharpGen.cs

2
NuGet.Config

@ -4,6 +4,6 @@
<packageSources>
<clear />
<add key="api.nuget.org" value="https://api.nuget.org/v3/index.json" />
<add key="dotnet-eng" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json" />
<add key="dotnet-eng" value="https://nuget.avaloniaui.net/repository/avalonia-devdeps/index.json" protocolVersion="3" />
</packageSources>
</configuration>

8
build/MicroCom.targets

@ -2,7 +2,7 @@
<!-- Ensure that code generator is actually built -->
<ItemGroup>
<ProjectReference Include="..\tools\MicroComGenerator\MicroComGenerator.csproj">
<ProjectReference Include="$(MSBuildThisFileDirectory)\..\src\tools\MicroComGenerator\MicroComGenerator.csproj">
<ReferenceOutputAssembly>false</ReferenceOutputAssembly>
<ExcludeAssets>all</ExcludeAssets>
<SkipGetTargetFrameworkProperties>true</SkipGetTargetFrameworkProperties>
@ -12,10 +12,10 @@
<Target Name="GenerateAvaloniaNativeComInterop"
BeforeTargets="CoreCompile"
DependsOnTargets="ResolveReferences"
Inputs="@(AvnComIdl);$(MSBuildThisFileDirectory)/../tools/MicroComGenerator/**/*.cs"
Inputs="@(AvnComIdl);$(MSBuildThisFileDirectory)../src/tools/MicroComGenerator/**/*.cs"
Outputs="%(AvnComIdl.OutputFile)">
<Message Importance="high" Text="Generating file %(AvnComIdl.OutputFile) from @(AvnComIdl)" />
<Exec Command="dotnet ../tools/MicroComGenerator/bin/$(Configuration)/netcoreapp3.1/MicroComGenerator.dll -i @(AvnComIdl) --cs %(AvnComIdl.OutputFile)" LogStandardErrorAsError="true" />
<Exec Command="dotnet $(MSBuildThisFileDirectory)../src/tools/MicroComGenerator/bin/$(Configuration)/netcoreapp3.1/MicroComGenerator.dll -i @(AvnComIdl) --cs %(AvnComIdl.OutputFile)" LogStandardErrorAsError="true" />
<ItemGroup>
<!-- Remove and re-add generated file, this is needed for the clean build -->
<Compile Remove="%(AvnComIdl.OutputFile)"/>
@ -24,7 +24,7 @@
</Target>
<ItemGroup>
<UpToDateCheckInput Include="@(AvnComIdl)"/>
<UpToDateCheckInput Include="$(MSBuildThisFileDirectory)/../tools/MicroComGenerator/**/*.cs"/>
<UpToDateCheckInput Include="$(MSBuildThisFileDirectory)/../src/tools/MicroComGenerator/**/*.cs"/>
</ItemGroup>
<PropertyGroup>
<_AvaloniaPatchComInterop>true</_AvaloniaPatchComInterop>

1
samples/Sandbox/MainWindow.axaml.cs

@ -1,6 +1,7 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.Win32.WinRT.Composition;
namespace Sandbox
{

2
src/Avalonia.MicroCom/MicroComProxyBase.cs

@ -56,7 +56,7 @@ namespace Avalonia.MicroCom
{
var guid = MicroComRuntime.GetGuidFor(typeof(T));
var rv = QueryInterface(guid, out var ppv);
if (rv != 0)
if (rv == 0)
return (T)MicroComRuntime.CreateProxyFor(typeof(T), ppv, true);
throw new COMException("QueryInterface failed", rv);
}

28
src/Avalonia.MicroCom/MicroComRuntime.cs

@ -38,13 +38,20 @@ namespace Avalonia.MicroCom
public static T CreateProxyFor<T>(IntPtr pObject, bool ownsHandle) => (T)CreateProxyFor(typeof(T), pObject, ownsHandle);
public static object CreateProxyFor(Type type, IntPtr pObject, bool ownsHandle) => _factories[type](pObject, ownsHandle);
public static IntPtr GetNativeIntPtr<T>(this T obj, bool owned = false) where T : IUnknown
=> new IntPtr(GetNativePointer(obj, owned));
public static void* GetNativePointer<T>(T obj, bool owned = false) where T : IUnknown
{
if (obj == null)
return null;
if (obj is MicroComProxyBase proxy)
{
if(owned)
proxy.AddRef();
return (void*)proxy.NativePointer;
}
if (obj is IMicroComShadowContainer container)
{
container.Shadow ??= new MicroComShadow(container);
@ -89,10 +96,27 @@ namespace Avalonia.MicroCom
}
public static T CloneReference<T>(T iface) where T : IUnknown
public static T CloneReference<T>(this T iface) where T : IUnknown
{
var proxy = (MicroComProxyBase)(object)iface;
var ownedPointer = GetNativePointer(iface, true);
return CreateProxyFor<T>(ownedPointer, true);
}
public static T QueryInterface<T>(this IUnknown unknown) where T : IUnknown
{
var proxy = (MicroComProxyBase)unknown;
return proxy.QueryInterface<T>();
}
public static void UnsafeAddRef(this IUnknown unknown)
{
((MicroComProxyBase)unknown).AddRef();
}
public static void UnsafeRelease(this IUnknown unknown)
{
((MicroComProxyBase)unknown).Release();
}
}
}

8
src/Avalonia.OpenGL/Egl/EglContext.cs

@ -93,6 +93,14 @@ namespace Avalonia.OpenGL.Egl
return MakeCurrent();
}
public IDisposable EnsureLocked()
{
if (IsCurrent)
return Disposable.Empty;
Monitor.Enter(_lock);
return Disposable.Create(() => Monitor.Exit(_lock));
}
public bool IsSharedWith(IGlContext context)
{
var c = (EglContext)context;

79
src/Avalonia.Visuals/Rendering/DeferredRenderer.cs

@ -99,6 +99,11 @@ namespace Avalonia.Rendering
/// </summary>
public string DebugFramesPath { get; set; }
/// <summary>
/// Forces the renderer to only draw frames on the render thread. Makes Paint to wait until frame is rendered
/// </summary>
public bool RenderOnlyOnRenderThread { get; set; }
/// <inheritdoc/>
public event EventHandler<SceneInvalidatedEventArgs> SceneInvalidated;
@ -180,11 +185,44 @@ namespace Avalonia.Rendering
/// <inheritdoc/>
public void Paint(Rect rect)
{
var t = (IRenderLoopTask)this;
if(t.NeedsUpdate)
UpdateScene();
if(_scene?.Item != null)
Render(true);
if (RenderOnlyOnRenderThread)
{
// Renderer is stopped and doesn't tick on the render thread
// This indicates a bug somewhere in our code
// (currently happens when a window gets minimized with Show desktop on Windows 10)
if(!_running)
return;
while (true)
{
Scene scene;
bool? updated;
lock (_sceneLock)
{
updated = UpdateScene();
scene = _scene?.Item;
}
// Renderer is in invalid state, skip drawing
if(updated == null)
return;
// Wait for the scene to be rendered or disposed
scene?.Rendered.Wait();
// That was an up-to-date scene, we can return immediately
if (updated == true)
return;
}
}
else
{
var t = (IRenderLoopTask)this;
if (t.NeedsUpdate)
UpdateScene();
if (_scene?.Item != null)
Render(true);
}
}
/// <inheritdoc/>
@ -270,13 +308,20 @@ namespace Avalonia.Rendering
{
if (scene?.Item != null)
{
var overlay = DrawDirtyRects || DrawFps;
if (DrawDirtyRects)
_dirtyRectsDisplay.Tick();
if (overlay)
RenderOverlay(scene.Item, ref context);
if (updated || forceComposite || overlay)
RenderComposite(scene.Item, ref context);
try
{
var overlay = DrawDirtyRects || DrawFps;
if (DrawDirtyRects)
_dirtyRectsDisplay.Tick();
if (overlay)
RenderOverlay(scene.Item, ref context);
if (updated || forceComposite || overlay)
RenderComposite(scene.Item, ref context);
}
finally
{
scene.Item.MarkAsRendered();
}
}
}
}
@ -559,15 +604,15 @@ namespace Avalonia.Rendering
UpdateScene();
}
private void UpdateScene()
private bool? UpdateScene()
{
Dispatcher.UIThread.VerifyAccess();
lock (_sceneLock)
{
if (_disposed)
return;
return null;
if (_scene?.Item.Generation > _lastSceneId)
return;
return false;
}
if (_root.IsVisible)
{
@ -619,6 +664,8 @@ namespace Avalonia.Rendering
SceneInvalidated(this, new SceneInvalidatedEventArgs((IRenderRoot)_root, rect));
}
return true;
}
else
{
@ -628,6 +675,8 @@ namespace Avalonia.Rendering
_scene = null;
oldScene?.Dispose();
}
return null;
}
}

7
src/Avalonia.Visuals/Rendering/SceneGraph/Scene.cs

@ -2,6 +2,7 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Avalonia.Collections.Pooled;
using Avalonia.VisualTree;
@ -13,6 +14,7 @@ namespace Avalonia.Rendering.SceneGraph
public class Scene : IDisposable
{
private readonly Dictionary<IVisual, IVisualNode> _index;
private readonly TaskCompletionSource<bool> _rendered = new TaskCompletionSource<bool>();
/// <summary>
/// Initializes a new instance of the <see cref="Scene"/> class.
@ -41,6 +43,8 @@ namespace Avalonia.Rendering.SceneGraph
root.LayerRoot = root.Visual;
}
public Task Rendered => _rendered.Task;
/// <summary>
/// Gets a value identifying the scene's generation. This is incremented each time the scene is cloned.
/// </summary>
@ -97,6 +101,7 @@ namespace Avalonia.Rendering.SceneGraph
public void Dispose()
{
_rendered.TrySetResult(false);
foreach (var node in _index.Values)
{
node.Dispose();
@ -340,5 +345,7 @@ namespace Avalonia.Rendering.SceneGraph
}
}
}
public void MarkAsRendered() => _rendered.TrySetResult(true);
}
}

10
src/Avalonia.X11/X11Window.cs

@ -189,6 +189,11 @@ namespace Avalonia.X11
if (platform.Options.UseDBusMenu)
NativeMenuExporter = DBusMenuExporter.TryCreate(_handle);
NativeControlHost = new X11NativeControlHost(_platform, this);
DispatcherTimer.Run(() =>
{
Paint?.Invoke(default);
return _handle != IntPtr.Zero;
}, TimeSpan.FromMilliseconds(100));
}
class SurfaceInfo : EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo
@ -338,7 +343,10 @@ namespace Avalonia.X11
return customRendererFactory.Create(root, loop);
return _platform.Options.UseDeferredRendering ?
new DeferredRenderer(root, loop) :
new DeferredRenderer(root, loop)
{
RenderOnlyOnRenderThread = true
} :
(IRenderer)new X11ImmediateRendererProxy(root, loop);
}

1
src/Windows/Avalonia.Win32/.gitignore

@ -0,0 +1 @@
*.Generated.cs

4
src/Windows/Avalonia.Win32/Avalonia.Win32.csproj

@ -5,9 +5,11 @@
<PackageId>Avalonia.Win32</PackageId>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
<ProjectReference Include="..\..\..\packages\Avalonia\Avalonia.csproj" />
<PackageReference Include="Avalonia.Angle.Windows.Natives" Version="2.1.0.2020091801" />
<PackageReference Include="Microsoft.Windows.SDK.NET" Version="10.0.18362.3-preview" />
<AvnComIdl Include="WinRT\winrt.idl" OutputFile="WinRT\WinRT.Generated.cs" />
</ItemGroup>
<Import Project="../../../build/MicroCom.targets" />
<Import Project="$(MSBuildThisFileDirectory)\..\..\..\build\System.Drawing.Common.props" />
</Project>

18
src/Windows/Avalonia.Win32/Composition/CompositionBlurHost.cs

@ -1,18 +0,0 @@
namespace Avalonia.Win32
{
internal class CompositionBlurHost : IBlurHost
{
Windows.UI.Composition.Visual _blurVisual;
public CompositionBlurHost(Windows.UI.Composition.Visual blurVisual)
{
_blurVisual = blurVisual;
}
public void SetBlur(bool enabled)
{
_blurVisual.IsVisible = enabled;
}
}
}

171
src/Windows/Avalonia.Win32/Composition/CompositionConnector.cs

@ -1,171 +0,0 @@
using System;
using System.Runtime.InteropServices;
using Avalonia.Logging;
using Avalonia.OpenGL;
using Avalonia.OpenGL.Angle;
using Avalonia.OpenGL.Egl;
using Windows.UI.Composition;
using Windows.UI.Composition.Interop;
using WinRT;
namespace Avalonia.Win32
{
internal class CompositionConnector
{
private Compositor _compositor;
private Windows.System.DispatcherQueueController _dispatcherQueueController;
private CompositionGraphicsDevice _graphicsDevice;
internal enum DISPATCHERQUEUE_THREAD_APARTMENTTYPE
{
DQTAT_COM_NONE = 0,
DQTAT_COM_ASTA = 1,
DQTAT_COM_STA = 2
};
internal enum DISPATCHERQUEUE_THREAD_TYPE
{
DQTYPE_THREAD_DEDICATED = 1,
DQTYPE_THREAD_CURRENT = 2,
};
[StructLayout(LayoutKind.Sequential)]
internal struct DispatcherQueueOptions
{
public int dwSize;
[MarshalAs(UnmanagedType.I4)]
public DISPATCHERQUEUE_THREAD_TYPE threadType;
[MarshalAs(UnmanagedType.I4)]
public DISPATCHERQUEUE_THREAD_APARTMENTTYPE apartmentType;
};
[DllImport("coremessaging.dll", EntryPoint = "CreateDispatcherQueueController", CharSet = CharSet.Unicode)]
internal static extern IntPtr CreateDispatcherQueueController(DispatcherQueueOptions options, out IntPtr dispatcherQueueController);
public static CompositionConnector TryCreate(EglPlatformOpenGlInterface egl)
{
const int majorRequired = 10;
const int buildRequired = 16299;
var majorInstalled = Win32Platform.WindowsVersion.Major;
var buildInstalled = Win32Platform.WindowsVersion.Build;
if (majorInstalled >= majorRequired &&
buildInstalled >= buildRequired)
{
try
{
return new CompositionConnector(egl);
}
catch (Exception e)
{
Logger.TryGet(LogEventLevel.Error, "WinUIComposition")?.Log(null, "Unable to initialize WinUI compositor: {0}", e);
return null;
}
}
var osVersionNotice = $"Windows {majorRequired} Build {buildRequired} is required. Your machine has Windows {majorInstalled} Build {buildInstalled} installed.";
Logger.TryGet(LogEventLevel.Warning, "WinUIComposition")?.Log(null,
$"Unable to initialize WinUI compositor: {osVersionNotice}");
return null;
}
public CompositionConnector(EglPlatformOpenGlInterface egl)
{
EnsureDispatcherQueue();
if (_dispatcherQueueController != null)
_compositor = new Compositor();
var interop = _compositor.As<ICompositorInterop>();
var display = egl.Display as AngleWin32EglDisplay;
_graphicsDevice = interop.CreateGraphicsDevice(display.GetDirect3DDevice());
}
public ICompositionDrawingSurfaceInterop InitialiseWindowCompositionTree(IntPtr hwnd, out Windows.UI.Composition.Visual surfaceVisual, out IBlurHost blurHost)
{
var target = CreateDesktopWindowTarget(hwnd);
var surface = _graphicsDevice.CreateDrawingSurface(new Windows.Foundation.Size(0, 0),
Windows.Graphics.DirectX.DirectXPixelFormat.B8G8R8A8UIntNormalized,
Windows.Graphics.DirectX.DirectXAlphaMode.Premultiplied);
var surfaceInterop = surface.As<ICompositionDrawingSurfaceInterop>();
var brush = _compositor.CreateSurfaceBrush(surface);
var visual = _compositor.CreateSpriteVisual();
visual.Brush = brush;
visual.RelativeSizeAdjustment = new System.Numerics.Vector2(1, 1);
var container = _compositor.CreateContainerVisual();
target.Root = container;
var blur = CreateBlur();
blurHost = new CompositionBlurHost(blur);
container.Children.InsertAtTop(blur);
container.Children.InsertAtTop(visual);
visual.CompositeMode = CompositionCompositeMode.SourceOver;
surfaceVisual = container;
return surfaceInterop;
}
private SpriteVisual CreateBlur()
{
var blurEffect = new GaussianBlurEffect(new CompositionEffectSourceParameter("backdrop"));
var backDropBrush = _compositor.CreateBackdropBrush();
var saturateEffect = new SaturationEffect(blurEffect);
var satEffectFactory = _compositor.CreateEffectFactory(saturateEffect);
var satBrush = satEffectFactory.CreateBrush();
satBrush.SetSourceParameter("backdrop", backDropBrush);
var visual = _compositor.CreateSpriteVisual();
visual.IsVisible = false;
visual.RelativeSizeAdjustment = new System.Numerics.Vector2(1.0f, 1.0f);
visual.Brush = satBrush;
return visual;
}
private CompositionTarget CreateDesktopWindowTarget(IntPtr window)
{
var interop = _compositor.As<global::Windows.UI.Composition.Desktop.ICompositorDesktopInterop>();
interop.CreateDesktopWindowTarget(window, false, out var windowTarget);
return Windows.UI.Composition.Desktop.DesktopWindowTarget.FromAbi(windowTarget);
}
private void EnsureDispatcherQueue()
{
if (_dispatcherQueueController == null)
{
DispatcherQueueOptions options = new DispatcherQueueOptions();
options.apartmentType = DISPATCHERQUEUE_THREAD_APARTMENTTYPE.DQTAT_COM_NONE;
options.threadType = DISPATCHERQUEUE_THREAD_TYPE.DQTYPE_THREAD_CURRENT;
options.dwSize = Marshal.SizeOf(typeof(DispatcherQueueOptions));
CreateDispatcherQueueController(options, out var queue);
_dispatcherQueueController = Windows.System.DispatcherQueueController.FromAbi(queue);
}
}
}
}

96
src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs

@ -1,96 +0,0 @@
using System;
using System.Runtime.InteropServices;
using Avalonia.OpenGL;
using Avalonia.OpenGL.Angle;
using Avalonia.OpenGL.Egl;
using Avalonia.OpenGL.Surfaces;
using Windows.UI.Composition.Interop;
namespace Avalonia.Win32
{
internal class CompositionEglGlPlatformSurface : EglGlPlatformSurfaceBase
{
private EglPlatformOpenGlInterface _egl;
private readonly IEglWindowGlPlatformSurfaceInfo _info;
private ICompositionDrawingSurfaceInterop _surfaceInterop;
private Windows.UI.Composition.Visual _surface;
public CompositionEglGlPlatformSurface(EglPlatformOpenGlInterface egl, IEglWindowGlPlatformSurfaceInfo info) : base()
{
_egl = egl;
_info = info;
}
public IBlurHost AttachToCompositionTree(CompositionConnector connector, IntPtr hwnd)
{
using (_egl.PrimaryContext.MakeCurrent())
{
_surfaceInterop = connector.InitialiseWindowCompositionTree(hwnd, out _surface, out var blurHost);
return blurHost;
}
}
public override IGlPlatformSurfaceRenderTarget CreateGlRenderTarget()
{
return new CompositionRenderTarget(_egl, _surface, _surfaceInterop, _info);
}
class CompositionRenderTarget : EglPlatformSurfaceRenderTargetBase
{
private readonly EglPlatformOpenGlInterface _egl;
private readonly IEglWindowGlPlatformSurfaceInfo _info;
private PixelSize _currentSize;
private readonly ICompositionDrawingSurfaceInterop _surfaceInterop;
private static Guid s_Iid = Guid.Parse("6f15aaf2-d208-4e89-9ab4-489535d34f9c");
private Windows.UI.Composition.Visual _compositionVisual;
public CompositionRenderTarget(EglPlatformOpenGlInterface egl,
Windows.UI.Composition.Visual compositionVisual,
ICompositionDrawingSurfaceInterop interopSurface,
IEglWindowGlPlatformSurfaceInfo info)
: base(egl)
{
_egl = egl;
_surfaceInterop = interopSurface;
_info = info;
_currentSize = info.Size;
_compositionVisual = compositionVisual;
using (_egl.PrimaryContext.MakeCurrent())
{
_surfaceInterop.Resize(new POINT { X = _info.Size.Width, Y = _info.Size.Height });
}
_compositionVisual.Size = new System.Numerics.Vector2(_info.Size.Width, _info.Size.Height);
}
public override IGlPlatformSurfaceRenderingSession BeginDraw()
{
IntPtr texture;
EglSurface surface;
using (_egl.PrimaryEglContext.EnsureCurrent())
{
if (_info.Size != _currentSize)
{
_surfaceInterop.Resize(new POINT { X = _info.Size.Width, Y = _info.Size.Height });
_compositionVisual.Size = new System.Numerics.Vector2(_info.Size.Width, _info.Size.Height);
_currentSize = _info.Size;
}
var offset = new POINT();
_surfaceInterop.BeginDraw(
IntPtr.Zero,
ref s_Iid,
out texture, ref offset);
surface = (_egl.Display as AngleWin32EglDisplay).WrapDirect3D11Texture(_egl, texture, offset.X, offset.Y, _info.Size.Width, _info.Size.Height);
}
return base.BeginDraw(surface, _info, () => { _surfaceInterop.EndDraw(); Marshal.Release(texture); surface.Dispose(); }, true);
}
}
}
}

91
src/Windows/Avalonia.Win32/Composition/D2DEffects.cs

@ -1,91 +0,0 @@
using System;
namespace Avalonia.Win32
{
class D2DEffects
{
public static readonly Guid CLSID_D2D12DAffineTransform = new Guid(0x6AA97485, 0x6354, 0x4CFC, 0x90, 0x8C, 0xE4, 0xA7, 0x4F, 0x62, 0xC9, 0x6C);
public static readonly Guid CLSID_D2D13DPerspectiveTransform = new Guid(0xC2844D0B, 0x3D86, 0x46E7, 0x85, 0xBA, 0x52, 0x6C, 0x92, 0x40, 0xF3, 0xFB);
public static readonly Guid CLSID_D2D13DTransform = new Guid(0xE8467B04, 0xEC61, 0x4B8A, 0xB5, 0xDE, 0xD4, 0xD7, 0x3D, 0xEB, 0xEA, 0x5A);
public static readonly Guid CLSID_D2D1ArithmeticComposite = new Guid(0xFC151437, 0x049A, 0x4784, 0xA2, 0x4A, 0xF1, 0xC4, 0xDA, 0xF2, 0x09, 0x87);
public static readonly Guid CLSID_D2D1Atlas = new Guid(0x913E2BE4, 0xFDCF, 0x4FE2, 0xA5, 0xF0, 0x24, 0x54, 0xF1, 0x4F, 0xF4, 0x08);
public static readonly Guid CLSID_D2D1BitmapSource = new Guid(0x5FB6C24D, 0xC6DD, 0x4231, 0x94, 0x4, 0x50, 0xF4, 0xD5, 0xC3, 0x25, 0x2D);
public static readonly Guid CLSID_D2D1Blend = new Guid(0x81C5B77B, 0x13F8, 0x4CDD, 0xAD, 0x20, 0xC8, 0x90, 0x54, 0x7A, 0xC6, 0x5D);
public static readonly Guid CLSID_D2D1Border = new Guid(0x2A2D49C0, 0x4ACF, 0x43C7, 0x8C, 0x6A, 0x7C, 0x4A, 0x27, 0x87, 0x4D, 0x27);
public static readonly Guid CLSID_D2D1Brightness = new Guid(0x8CEA8D1E, 0x77B0, 0x4986, 0xB3, 0xB9, 0x2F, 0x0C, 0x0E, 0xAE, 0x78, 0x87);
public static readonly Guid CLSID_D2D1ColorManagement = new Guid(0x1A28524C, 0xFDD6, 0x4AA4, 0xAE, 0x8F, 0x83, 0x7E, 0xB8, 0x26, 0x7B, 0x37);
public static readonly Guid CLSID_D2D1ColorMatrix = new Guid(0x921F03D6, 0x641C, 0x47DF, 0x85, 0x2D, 0xB4, 0xBB, 0x61, 0x53, 0xAE, 0x11);
public static readonly Guid CLSID_D2D1Composite = new Guid(0x48FC9F51, 0xF6AC, 0x48F1, 0x8B, 0x58, 0x3B, 0x28, 0xAC, 0x46, 0xF7, 0x6D);
public static readonly Guid CLSID_D2D1ConvolveMatrix = new Guid(0x407F8C08, 0x5533, 0x4331, 0xA3, 0x41, 0x23, 0xCC, 0x38, 0x77, 0x84, 0x3E);
public static readonly Guid CLSID_D2D1Crop = new Guid(0xE23F7110, 0x0E9A, 0x4324, 0xAF, 0x47, 0x6A, 0x2C, 0x0C, 0x46, 0xF3, 0x5B);
public static readonly Guid CLSID_D2D1DirectionalBlur = new Guid(0x174319A6, 0x58E9, 0x49B2, 0xBB, 0x63, 0xCA, 0xF2, 0xC8, 0x11, 0xA3, 0xDB);
public static readonly Guid CLSID_D2D1DiscreteTransfer = new Guid(0x90866FCD, 0x488E, 0x454B, 0xAF, 0x06, 0xE5, 0x04, 0x1B, 0x66, 0xC3, 0x6C);
public static readonly Guid CLSID_D2D1DisplacementMap = new Guid(0xEDC48364, 0x417, 0x4111, 0x94, 0x50, 0x43, 0x84, 0x5F, 0xA9, 0xF8, 0x90);
public static readonly Guid CLSID_D2D1DistantDiffuse = new Guid(0x3E7EFD62, 0xA32D, 0x46D4, 0xA8, 0x3C, 0x52, 0x78, 0x88, 0x9A, 0xC9, 0x54);
public static readonly Guid CLSID_D2D1DistantSpecular = new Guid(0x428C1EE5, 0x77B8, 0x4450, 0x8A, 0xB5, 0x72, 0x21, 0x9C, 0x21, 0xAB, 0xDA);
public static readonly Guid CLSID_D2D1DpiCompensation = new Guid(0x6C26C5C7, 0x34E0, 0x46FC, 0x9C, 0xFD, 0xE5, 0x82, 0x37, 0x6, 0xE2, 0x28);
public static readonly Guid CLSID_D2D1Flood = new Guid(0x61C23C20, 0xAE69, 0x4D8E, 0x94, 0xCF, 0x50, 0x07, 0x8D, 0xF6, 0x38, 0xF2);
public static readonly Guid CLSID_D2D1GammaTransfer = new Guid(0x409444C4, 0xC419, 0x41A0, 0xB0, 0xC1, 0x8C, 0xD0, 0xC0, 0xA1, 0x8E, 0x42);
public static readonly Guid CLSID_D2D1GaussianBlur = new Guid(0x1FEB6D69, 0x2FE6, 0x4AC9, 0x8C, 0x58, 0x1D, 0x7F, 0x93, 0xE7, 0xA6, 0xA5);
public static readonly Guid CLSID_D2D1Scale = new Guid(0x9DAF9369, 0x3846, 0x4D0E, 0xA4, 0x4E, 0xC, 0x60, 0x79, 0x34, 0xA5, 0xD7);
public static readonly Guid CLSID_D2D1Histogram = new Guid(0x881DB7D0, 0xF7EE, 0x4D4D, 0xA6, 0xD2, 0x46, 0x97, 0xAC, 0xC6, 0x6E, 0xE8);
public static readonly Guid CLSID_D2D1HueRotation = new Guid(0x0F4458EC, 0x4B32, 0x491B, 0x9E, 0x85, 0xBD, 0x73, 0xF4, 0x4D, 0x3E, 0xB6);
public static readonly Guid CLSID_D2D1LinearTransfer = new Guid(0xAD47C8FD, 0x63EF, 0x4ACC, 0x9B, 0x51, 0x67, 0x97, 0x9C, 0x03, 0x6C, 0x06);
public static readonly Guid CLSID_D2D1LuminanceToAlpha = new Guid(0x41251AB7, 0x0BEB, 0x46F8, 0x9D, 0xA7, 0x59, 0xE9, 0x3F, 0xCC, 0xE5, 0xDE);
public static readonly Guid CLSID_D2D1Morphology = new Guid(0xEAE6C40D, 0x626A, 0x4C2D, 0xBF, 0xCB, 0x39, 0x10, 0x01, 0xAB, 0xE2, 0x02);
public static readonly Guid CLSID_D2D1OpacityMetadata = new Guid(0x6C53006A, 0x4450, 0x4199, 0xAA, 0x5B, 0xAD, 0x16, 0x56, 0xFE, 0xCE, 0x5E);
public static readonly Guid CLSID_D2D1PointDiffuse = new Guid(0xB9E303C3, 0xC08C, 0x4F91, 0x8B, 0x7B, 0x38, 0x65, 0x6B, 0xC4, 0x8C, 0x20);
public static readonly Guid CLSID_D2D1PointSpecular = new Guid(0x09C3CA26, 0x3AE2, 0x4F09, 0x9E, 0xBC, 0xED, 0x38, 0x65, 0xD5, 0x3F, 0x22);
public static readonly Guid CLSID_D2D1Premultiply = new Guid(0x06EAB419, 0xDEED, 0x4018, 0x80, 0xD2, 0x3E, 0x1D, 0x47, 0x1A, 0xDE, 0xB2);
public static readonly Guid CLSID_D2D1Saturation = new Guid(0x5CB2D9CF, 0x327D, 0x459F, 0xA0, 0xCE, 0x40, 0xC0, 0xB2, 0x08, 0x6B, 0xF7);
public static readonly Guid CLSID_D2D1Shadow = new Guid(0xC67EA361, 0x1863, 0x4E69, 0x89, 0xDB, 0x69, 0x5D, 0x3E, 0x9A, 0x5B, 0x6B);
public static readonly Guid CLSID_D2D1SpotDiffuse = new Guid(0x818A1105, 0x7932, 0x44F4, 0xAA, 0x86, 0x08, 0xAE, 0x7B, 0x2F, 0x2C, 0x93);
public static readonly Guid CLSID_D2D1SpotSpecular = new Guid(0xEDAE421E, 0x7654, 0x4A37, 0x9D, 0xB8, 0x71, 0xAC, 0xC1, 0xBE, 0xB3, 0xC1);
public static readonly Guid CLSID_D2D1TableTransfer = new Guid(0x5BF818C3, 0x5E43, 0x48CB, 0xB6, 0x31, 0x86, 0x83, 0x96, 0xD6, 0xA1, 0xD4);
public static readonly Guid CLSID_D2D1Tile = new Guid(0xB0784138, 0x3B76, 0x4BC5, 0xB1, 0x3B, 0x0F, 0xA2, 0xAD, 0x02, 0x65, 0x9F);
public static readonly Guid CLSID_D2D1Turbulence = new Guid(0xCF2BB6AE, 0x889A, 0x4AD7, 0xBA, 0x29, 0xA2, 0xFD, 0x73, 0x2C, 0x9F, 0xC9);
public static readonly Guid CLSID_D2D1UnPremultiply = new Guid(0xFB9AC489, 0xAD8D, 0x41ED, 0x99, 0x99, 0xBB, 0x63, 0x47, 0xD1, 0x10, 0xF7);
}
}

45
src/Windows/Avalonia.Win32/Composition/EffectBase.cs

@ -1,45 +0,0 @@
using System;
using Windows.Graphics.Effects;
using Windows.Graphics.Effects.Interop;
namespace Avalonia.Win32
{
abstract class EffectBase : IGraphicsEffect, IGraphicsEffectSource, global::Windows.Graphics.Effects.Interop.IGraphicsEffectD2D1Interop
{
private IGraphicsEffectSource[] _sources;
public EffectBase(params IGraphicsEffectSource[] sources)
{
_sources = sources;
}
private IGraphicsEffectSource _source;
public virtual string Name { get; set; }
public abstract Guid EffectId { get; }
public abstract uint PropertyCount { get; }
public uint SourceCount => (uint)_sources.Length;
public IGraphicsEffectSource GetSource(uint index)
{
if(index < _sources.Length)
{
return _sources[index];
}
return null;
}
public uint GetNamedPropertyMapping(string name, out GRAPHICS_EFFECT_PROPERTY_MAPPING mapping)
{
throw new NotImplementedException();
}
public abstract object GetProperty(uint index);
}
}

18
src/Windows/Avalonia.Win32/Composition/GRAPHICS_EFFECT_PROPERTY_MAPPING.cs

@ -1,18 +0,0 @@
namespace Windows.Graphics.Effects.Interop
{
public enum GRAPHICS_EFFECT_PROPERTY_MAPPING
{
GRAPHICS_EFFECT_PROPERTY_MAPPING_UNKNOWN,
GRAPHICS_EFFECT_PROPERTY_MAPPING_DIRECT,
GRAPHICS_EFFECT_PROPERTY_MAPPING_VECTORX,
GRAPHICS_EFFECT_PROPERTY_MAPPING_VECTORY,
GRAPHICS_EFFECT_PROPERTY_MAPPING_VECTORZ,
GRAPHICS_EFFECT_PROPERTY_MAPPING_VECTORW,
GRAPHICS_EFFECT_PROPERTY_MAPPING_RECT_TO_VECTOR4,
GRAPHICS_EFFECT_PROPERTY_MAPPING_RADIANS_TO_DEGREES,
GRAPHICS_EFFECT_PROPERTY_MAPPING_COLORMATRIX_ALPHA_MODE,
GRAPHICS_EFFECT_PROPERTY_MAPPING_COLOR_TO_VECTOR3,
GRAPHICS_EFFECT_PROPERTY_MAPPING_COLOR_TO_VECTOR4
};
}

57
src/Windows/Avalonia.Win32/Composition/GaussianBlurEffect.cs

@ -1,57 +0,0 @@
using System;
using Windows.Graphics.Effects;
namespace Avalonia.Win32
{
class GaussianBlurEffect : EffectBase
{
public GaussianBlurEffect(IGraphicsEffectSource source) : base(source)
{
}
enum D2D1_GAUSSIANBLUR_OPTIMIZATION
{
D2D1_GAUSSIANBLUR_OPTIMIZATION_SPEED,
D2D1_GAUSSIANBLUR_OPTIMIZATION_BALANCED,
D2D1_GAUSSIANBLUR_OPTIMIZATION_QUALITY,
D2D1_GAUSSIANBLUR_OPTIMIZATION_FORCE_DWORD
};
enum D2D1_BORDER_MODE
{
D2D1_BORDER_MODE_SOFT,
D2D1_BORDER_MODE_HARD,
D2D1_BORDER_MODE_FORCE_DWORD
};
enum D2D1GaussianBlurProp
{
D2D1_GAUSSIANBLUR_PROP_STANDARD_DEVIATION,
D2D1_GAUSSIANBLUR_PROP_OPTIMIZATION,
D2D1_GAUSSIANBLUR_PROP_BORDER_MODE,
D2D1_GAUSSIANBLUR_PROP_FORCE_DWORD
};
public override Guid EffectId => D2DEffects.CLSID_D2D1GaussianBlur;
public override uint PropertyCount => 3;
public override object GetProperty(uint index)
{
switch ((D2D1GaussianBlurProp)index)
{
case D2D1GaussianBlurProp.D2D1_GAUSSIANBLUR_PROP_STANDARD_DEVIATION:
return 30.0f;
case D2D1GaussianBlurProp.D2D1_GAUSSIANBLUR_PROP_OPTIMIZATION:
return (uint)D2D1_GAUSSIANBLUR_OPTIMIZATION.D2D1_GAUSSIANBLUR_OPTIMIZATION_BALANCED;
case D2D1GaussianBlurProp.D2D1_GAUSSIANBLUR_PROP_BORDER_MODE:
return (uint)D2D1_BORDER_MODE.D2D1_BORDER_MODE_HARD;
}
return null;
}
}
}

8
src/Windows/Avalonia.Win32/Composition/IBlurHost.cs

@ -1,8 +0,0 @@
namespace Avalonia.Win32
{
internal interface IBlurHost
{
void SetBlur(bool enabled);
}
}

152
src/Windows/Avalonia.Win32/Composition/ICompositionDrawingSurfaceInterop.cs

@ -1,152 +0,0 @@
using System;
using System.Runtime.InteropServices;
using WinRT;
namespace Windows.UI.Composition.Interop
{
public struct POINT
{
public int X;
public int Y;
}
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
public int Width => right - left;
public int Height => bottom - top;
}
[WindowsRuntimeType]
[Guid("FD04E6E3-FE0C-4C3C-AB19-A07601A576EE")]
public interface ICompositionDrawingSurfaceInterop
{
void BeginDraw(IntPtr updateRect, ref Guid iid, out IntPtr updateObject, ref POINT point);
void EndDraw();
void Resize(POINT sizePixels);
void ResumeDraw();
void Scroll(RECT scrollRect, RECT clipRect, int offsetX, int offsetY);
void SuspendDraw();
}
}
namespace ABI.Windows.UI.Composition.Interop
{
using global::System;
using global::System.Runtime.InteropServices;
using global::Windows.UI.Composition;
using global::Windows.UI.Composition.Interop;
[Guid("FD04E6E3-FE0C-4C3C-AB19-A07601A576EE")]
internal class ICompositionDrawingSurfaceInterop : global::Windows.UI.Composition.Interop.ICompositionDrawingSurfaceInterop
{
[Guid("FD04E6E3-FE0C-4C3C-AB19-A07601A576EE")]
public unsafe struct Vftbl
{
public delegate int _BeginDraw(IntPtr ThisPtr, IntPtr updateRect, ref Guid iid, out IntPtr updateObject, ref POINT updateOffset);
public delegate int _EndDraw(IntPtr ThisPtr);
public delegate int _Resize(IntPtr ThisPtr, POINT sizePixels);
public delegate int _ResumeDraw(IntPtr ThisPtr);
public delegate int _Scroll(IntPtr ThisPtr, RECT scrollRect, RECT clipRect, int offsetX, int offsetY);
public delegate int _SuspendDraw(IntPtr ThisPtr);
internal global::WinRT.Interop.IUnknownVftbl IUnknownVftbl;
public _BeginDraw BeginDraw;
public _EndDraw EndDraw;
public _Resize Resize;
public _ResumeDraw ResumeDraw;
public _Scroll Scroll;
public _SuspendDraw SuspendDraw;
public static readonly Vftbl AbiToProjectionVftable;
public static readonly IntPtr AbiToProjectionVftablePtr;
static Vftbl()
{
AbiToProjectionVftable = new Vftbl
{
IUnknownVftbl = global::WinRT.Interop.IUnknownVftbl.AbiToProjectionVftbl,
BeginDraw = Do_Abi_BeginDraw,
EndDraw = Do_Abi_EndDraw,
Resize = Do_Abi_Resize
};
AbiToProjectionVftablePtr = Marshal.AllocHGlobal(Marshal.SizeOf<Vftbl>());
Marshal.StructureToPtr(AbiToProjectionVftable, AbiToProjectionVftablePtr, false);
}
private static int Do_Abi_BeginDraw(IntPtr ThisPtr, IntPtr updateRect, ref Guid iid, out IntPtr updateObject, ref POINT updateOffset)
{
updateObject = IntPtr.Zero;
return 0;
}
private static int Do_Abi_EndDraw(IntPtr ThisPtr)
{
return 0;
}
private static int Do_Abi_Resize(IntPtr ThisPtr, POINT sizePixels)
{
return 0;
}
}
internal static ObjectReference<Vftbl> FromAbi(IntPtr thisPtr) => ObjectReference<Vftbl>.FromAbi(thisPtr);
public static implicit operator ICompositionDrawingSurfaceInterop(IObjectReference obj) => (obj != null) ? new ICompositionDrawingSurfaceInterop(obj) : null;
protected readonly ObjectReference<Vftbl> _obj;
public IObjectReference ObjRef { get => _obj; }
public IntPtr ThisPtr => _obj.ThisPtr;
public ObjectReference<I> AsInterface<I>() => _obj.As<I>();
public A As<A>() => _obj.AsType<A>();
public ICompositionDrawingSurfaceInterop(IObjectReference obj) : this(obj.As<Vftbl>()) { }
internal ICompositionDrawingSurfaceInterop(ObjectReference<Vftbl> obj)
{
_obj = obj;
}
public void BeginDraw(IntPtr updateRect, ref Guid iid, out IntPtr updateObject, ref POINT point)
{
Marshal.ThrowExceptionForHR(_obj.Vftbl.BeginDraw(ThisPtr, updateRect, ref iid, out updateObject, ref point));
}
public void EndDraw()
{
Marshal.ThrowExceptionForHR(_obj.Vftbl.EndDraw(ThisPtr));
}
public void Resize(POINT sizePixels)
{
Marshal.ThrowExceptionForHR(_obj.Vftbl.Resize(ThisPtr, sizePixels));
}
public void ResumeDraw()
{
throw new NotImplementedException();
}
public void Scroll(RECT scrollRect, RECT clipRect, int offsetX, int offsetY)
{
throw new NotImplementedException();
}
public void SuspendDraw()
{
throw new NotImplementedException();
}
}
}

14
src/Windows/Avalonia.Win32/Composition/ICompositorDesktopInterop.cs

@ -1,14 +0,0 @@
using System;
using System.Runtime.InteropServices;
using WinRT;
namespace Windows.UI.Composition.Desktop
{
[WindowsRuntimeType]
[Guid("29E691FA-4567-4DCA-B319-D0F207EB6807")]
public interface ICompositorDesktopInterop
{
void CreateDesktopWindowTarget(IntPtr hwndTarget, bool isTopmost, out IntPtr test);
}
}

69
src/Windows/Avalonia.Win32/Composition/ICompositorDesktopInterop1.cs

@ -1,69 +0,0 @@
using WinRT;
namespace ABI.Windows.UI.Composition.Desktop
{
using global::System;
using global::System.Runtime.InteropServices;
[Guid("29E691FA-4567-4DCA-B319-D0F207EB6807")]
internal class ICompositorDesktopInterop : global::Windows.UI.Composition.Desktop.ICompositorDesktopInterop
{
[Guid("29E691FA-4567-4DCA-B319-D0F207EB6807")]
public struct Vftbl
{
public delegate int _CreateDesktopWindowTarget(IntPtr thisPtr, IntPtr hwndTarget, byte isTopMost, out IntPtr desktopWindowTarget);
internal global::WinRT.Interop.IUnknownVftbl IUnknownVftbl;
public _CreateDesktopWindowTarget CreateDesktopWindowTarget;
public static readonly Vftbl AbiToProjectionVftable;
public static readonly IntPtr AbiToProjectionVftablePtr;
static Vftbl()
{
AbiToProjectionVftable = new Vftbl
{
IUnknownVftbl = global::WinRT.Interop.IUnknownVftbl.AbiToProjectionVftbl,
CreateDesktopWindowTarget = Do_Abi_Create_Desktop_Window_Target
};
AbiToProjectionVftablePtr = Marshal.AllocHGlobal(Marshal.SizeOf<Vftbl>());
Marshal.StructureToPtr(AbiToProjectionVftable, AbiToProjectionVftablePtr, false);
}
private static int Do_Abi_Create_Desktop_Window_Target(IntPtr thisPtr, IntPtr hwndTarget, byte isTopMost, out IntPtr desktopWindowTarget)
{
try
{
ComWrappersSupport.FindObject<global::Windows.UI.Composition.Desktop.ICompositorDesktopInterop>(thisPtr).CreateDesktopWindowTarget(hwndTarget, isTopMost != 0, out desktopWindowTarget);
return 0;
}
catch (Exception ex)
{
desktopWindowTarget = IntPtr.Zero;
return Marshal.GetHRForException(ex);
}
}
}
internal static ObjectReference<Vftbl> FromAbi(IntPtr thisPtr) => ObjectReference<Vftbl>.FromAbi(thisPtr);
public static implicit operator ICompositorDesktopInterop(IObjectReference obj) => (obj != null) ? new ICompositorDesktopInterop(obj) : null;
protected readonly ObjectReference<Vftbl> _obj;
public IObjectReference ObjRef { get => _obj; }
public IntPtr ThisPtr => _obj.ThisPtr;
public ObjectReference<I> AsInterface<I>() => _obj.As<I>();
public A As<A>() => _obj.AsType<A>();
public ICompositorDesktopInterop(IObjectReference obj) : this(obj.As<Vftbl>()) { }
internal ICompositorDesktopInterop(ObjectReference<Vftbl> obj)
{
_obj = obj;
}
public void CreateDesktopWindowTarget(IntPtr hwndTarget, bool isTopmost, out IntPtr test)
{
Marshal.ThrowExceptionForHR(_obj.Vftbl.CreateDesktopWindowTarget(ThisPtr, hwndTarget, isTopmost ? (byte)1 : (byte)0, out test));
}
}
}

139
src/Windows/Avalonia.Win32/Composition/ICompositorInterop.cs

@ -1,139 +0,0 @@
using System;
using System.Runtime.InteropServices;
using WinRT;
namespace Windows.UI.Composition.Interop
{
[WindowsRuntimeType]
[Guid("25297D5C-3AD4-4C9C-B5CF-E36A38512330")]
public interface ICompositorInterop
{
ICompositionSurface CreateCompositionSurfaceForHandle(IntPtr swapChain);
ICompositionSurface CreateCompositionSurfaceForSwapChain(IntPtr swapChain);
CompositionGraphicsDevice CreateGraphicsDevice(IntPtr renderingDevice);
}
}
namespace ABI.Windows.UI.Composition.Interop
{
using global::System;
using global::System.Runtime.InteropServices;
using global::Windows.UI.Composition;
[Guid("25297D5C-3AD4-4C9C-B5CF-E36A38512330")]
internal class ICompositorInterop : global::Windows.UI.Composition.Interop.ICompositorInterop
{
[Guid("25297D5C-3AD4-4C9C-B5CF-E36A38512330")]
public struct Vftbl
{
public delegate int _CreateCompositionSurfaceForHandle(IntPtr ThisPtr, IntPtr swapChain, out IntPtr result);
public delegate int _CreateCompositionSurfaceForSwapChain(IntPtr ThisPtr, IntPtr swapChain, out IntPtr result);
public delegate int _CreateGraphicsDevice(IntPtr ThisPtr, IntPtr renderingDevice, out IntPtr result);
internal global::WinRT.Interop.IUnknownVftbl IUnknownVftbl;
public _CreateCompositionSurfaceForHandle CreateCompositionSurfaceForHandle;
public _CreateCompositionSurfaceForSwapChain CreateCompositionSurfaceForSwapChain;
public _CreateGraphicsDevice CreateGraphicsDevice;
public static readonly Vftbl AbiToProjectionVftable;
public static readonly IntPtr AbiToProjectionVftablePtr;
static Vftbl()
{
AbiToProjectionVftable = new Vftbl
{
IUnknownVftbl = global::WinRT.Interop.IUnknownVftbl.AbiToProjectionVftbl,
CreateCompositionSurfaceForHandle = Do_Abi_Create_Composition_Surface_For_Handle,
CreateCompositionSurfaceForSwapChain = Do_Abi_Create_Composition_Surface_For_SwapChain,
CreateGraphicsDevice= Do_Abi_Create_Graphics_Device
};
AbiToProjectionVftablePtr = Marshal.AllocHGlobal(Marshal.SizeOf<Vftbl>());
Marshal.StructureToPtr(AbiToProjectionVftable, AbiToProjectionVftablePtr, false);
}
private static int Do_Abi_Create_Composition_Surface_For_Handle(IntPtr thisPtr, IntPtr swapChain, out IntPtr surface)
{
try
{
surface = IntPtr.Zero;
//surface = ComWrappersSupport.FindObject<global::Windows.UI.Composition.Interop.ICompositorInterop>(thisPtr).CreateCompositionSurfaceForHandle(swapChain);
return 0;
}
catch (Exception ex)
{
surface = IntPtr.Zero;
return Marshal.GetHRForException(ex);
}
}
private static int Do_Abi_Create_Composition_Surface_For_SwapChain(IntPtr thisPtr, IntPtr swapChain, out IntPtr surface)
{
try
{
surface = IntPtr.Zero;
//surface = ComWrappersSupport.FindObject<global::Windows.UI.Composition.Interop.ICompositorInterop>(thisPtr).CreateCompositionSurfaceForSwapChain(swapChain);
return 0;
}
catch (Exception ex)
{
surface = IntPtr.Zero;
return Marshal.GetHRForException(ex);
}
}
private static int Do_Abi_Create_Graphics_Device(IntPtr thisPtr, IntPtr renderingDevice, out IntPtr graphicsDevice)
{
try
{
graphicsDevice = ComWrappersSupport.FindObject<global::Windows.UI.Composition.Interop.ICompositorInterop>(thisPtr).CreateGraphicsDevice(renderingDevice).ThisPtr;
return 0;
}
catch (Exception ex)
{
graphicsDevice = IntPtr.Zero;
return Marshal.GetHRForException(ex);
}
}
}
internal static ObjectReference<Vftbl> FromAbi(IntPtr thisPtr) => ObjectReference<Vftbl>.FromAbi(thisPtr);
public static implicit operator ICompositorInterop(IObjectReference obj) => (obj != null) ? new ICompositorInterop(obj) : null;
protected readonly ObjectReference<Vftbl> _obj;
public IObjectReference ObjRef { get => _obj; }
public IntPtr ThisPtr => _obj.ThisPtr;
public ObjectReference<I> AsInterface<I>() => _obj.As<I>();
public A As<A>() => _obj.AsType<A>();
public ICompositorInterop(IObjectReference obj) : this(obj.As<Vftbl>()) { }
internal ICompositorInterop(ObjectReference<Vftbl> obj)
{
_obj = obj;
}
public ICompositionSurface CreateCompositionSurfaceForHandle(IntPtr swapChain)
{
Marshal.ThrowExceptionForHR(_obj.Vftbl.CreateCompositionSurfaceForHandle(ThisPtr, swapChain, out var compositionSurface));
return null;
}
public ICompositionSurface CreateCompositionSurfaceForSwapChain(IntPtr swapChain)
{
Marshal.ThrowExceptionForHR(_obj.Vftbl.CreateCompositionSurfaceForSwapChain(ThisPtr, swapChain, out var compositionSurface));
return null;
}
public CompositionGraphicsDevice CreateGraphicsDevice(IntPtr renderingDevice)
{
Marshal.ThrowExceptionForHR(_obj.Vftbl.CreateGraphicsDevice(ThisPtr, renderingDevice, out var graphicsDevice));
return CompositionGraphicsDevice.FromAbi(graphicsDevice);
}
}
}

24
src/Windows/Avalonia.Win32/Composition/IGraphicsEffectD2D1Interop.cs

@ -1,24 +0,0 @@
using System;
using System.Runtime.InteropServices;
using WinRT;
namespace Windows.Graphics.Effects.Interop
{
[WindowsRuntimeType]
[Guid("2FC57384-A068-44D7-A331-30982FCF7177")]
public interface IGraphicsEffectD2D1Interop
{
Guid EffectId { get; }
uint GetNamedPropertyMapping(string name, out GRAPHICS_EFFECT_PROPERTY_MAPPING mapping);
object GetProperty(uint index);
uint PropertyCount { get; }
IGraphicsEffectSource GetSource(uint index);
uint SourceCount { get; }
}
}

217
src/Windows/Avalonia.Win32/Composition/IGraphicsEffectD2D1Interop1.cs

@ -1,217 +0,0 @@
using WinRT;
namespace ABI.Windows.Graphics.Effects.Interop
{
using global::System;
using global::System.Runtime.InteropServices;
[Guid("2FC57384-A068-44D7-A331-30982FCF7177")]
internal class IGraphicsEffectD2D1Interop : global::Windows.Graphics.Effects.Interop.IGraphicsEffectD2D1Interop
{
[Guid("2FC57384-A068-44D7-A331-30982FCF7177")]
public struct Vftbl
{
public delegate int _GetEffectId(IntPtr thisPtr, out Guid guid);
public delegate int _GetNamedPropertyMapping(IntPtr thisPtr, IntPtr name, IntPtr index, IntPtr mapping);
public delegate int _GetProperty(IntPtr thisPtr, uint index, out IntPtr value);
public unsafe delegate int _GetPropertyCount(IntPtr thisPtr, uint* count);
public delegate int _GetSource(IntPtr thisPtr, uint index, out IntPtr source);
public delegate int _GetSourceCount(IntPtr thisPtr, out uint count);
internal global::WinRT.Interop.IUnknownVftbl IUnknownVftbl;
public _GetEffectId GetEffectId;
public _GetNamedPropertyMapping GetNamedPropertyMapping;
public _GetPropertyCount GetPropertyCount;
public _GetProperty GetProperty;
public _GetSource GetSource;
public _GetSourceCount GetSourceCount;
public static readonly Vftbl AbiToProjectionVftable;
public static readonly IntPtr AbiToProjectionVftablePtr;
unsafe static Vftbl()
{
AbiToProjectionVftable = new Vftbl
{
IUnknownVftbl = global::WinRT.Interop.IUnknownVftbl.AbiToProjectionVftbl,
GetEffectId = Do_Abi_Get_Effect_Id,
GetNamedPropertyMapping = Do_Abi_Get_Property_Mapping,
GetPropertyCount = Do_Abi_Get_Property_Count,
GetProperty = Do_Abi_Get_Property,
GetSource = Do_Abi_Get_Source,
GetSourceCount = Do_Abi_Get_Source_Count
};
AbiToProjectionVftablePtr = Marshal.AllocHGlobal(Marshal.SizeOf<Vftbl>());
Marshal.StructureToPtr(AbiToProjectionVftable, AbiToProjectionVftablePtr, false);
}
private static int Do_Abi_Get_Effect_Id(IntPtr thisPtr, out Guid guid)
{
guid = default;
try
{
guid = ComWrappersSupport.FindObject<global::Windows.Graphics.Effects.Interop.IGraphicsEffectD2D1Interop>(thisPtr).EffectId;
}
catch (Exception ex)
{
return Marshal.GetHRForException(ex);
}
return 0;
}
private static int Do_Abi_Get_Property_Mapping(IntPtr thisPtr, IntPtr name, IntPtr index, IntPtr mapping)
{
try
{
ComWrappersSupport.FindObject<global::Windows.Graphics.Effects.Interop.IGraphicsEffectD2D1Interop>(thisPtr).GetNamedPropertyMapping(MarshalString.FromAbi(name), out var mappingResult);
}
catch (Exception ex)
{
return Marshal.GetHRForException(ex);
}
return 0;
}
private static int Do_Abi_Get_Property(IntPtr thisPtr, uint index, out IntPtr value)
{
value = default;
try
{
value = MarshalInspectable.CreateMarshaler(
ComWrappersSupport.FindObject<global::Windows.Graphics.Effects.Interop.IGraphicsEffectD2D1Interop>(thisPtr).GetProperty(index))
.As(Guid.Parse("4BD682DD-7554-40E9-9A9B-82654EDE7E62"))
.GetRef();
}
catch (Exception ex)
{
return Marshal.GetHRForException(ex);
}
return 0;
}
unsafe private static int Do_Abi_Get_Property_Count(IntPtr thisPtr, uint* count)
{
try
{
var res = ComWrappersSupport.FindObject<global::Windows.Graphics.Effects.Interop.IGraphicsEffectD2D1Interop>(thisPtr).PropertyCount;
if (count != null)
{
*count = res;
}
}
catch (Exception ex)
{
return Marshal.GetHRForException(ex);
}
return 0;
}
private static int Do_Abi_Get_Source(IntPtr thisPtr, uint index, out IntPtr value)
{
value = default;
try
{
var source = ComWrappersSupport.FindObject<global::Windows.Graphics.Effects.Interop.IGraphicsEffectD2D1Interop>(thisPtr).GetSource(index);
value = MarshalInterface<global::Windows.Graphics.Effects.IGraphicsEffectSource>.FromManaged(source);
}
catch (Exception ex)
{
return Marshal.GetHRForException(ex);
}
return 0;
}
private static int Do_Abi_Get_Source_Count(IntPtr thisPtr, out uint count)
{
count = default;
try
{
count = ComWrappersSupport.FindObject<global::Windows.Graphics.Effects.Interop.IGraphicsEffectD2D1Interop>(thisPtr).SourceCount;
}
catch (Exception ex)
{
return Marshal.GetHRForException(ex);
}
return 0;
}
}
internal static ObjectReference<Vftbl> FromAbi(IntPtr thisPtr) => ObjectReference<Vftbl>.FromAbi(thisPtr);
public static implicit operator IGraphicsEffectD2D1Interop(IObjectReference obj) => (obj != null) ? new IGraphicsEffectD2D1Interop(obj) : null;
protected readonly ObjectReference<Vftbl> _obj;
public IObjectReference ObjRef { get => _obj; }
public IntPtr ThisPtr => _obj.ThisPtr;
public ObjectReference<I> AsInterface<I>() => _obj.As<I>();
public A As<A>() => _obj.AsType<A>();
public IGraphicsEffectD2D1Interop(IObjectReference obj) : this(obj.As<Vftbl>()) { }
internal IGraphicsEffectD2D1Interop(ObjectReference<Vftbl> obj)
{
_obj = obj;
}
public Guid EffectId
{
get
{
Marshal.ThrowExceptionForHR(_obj.Vftbl.GetEffectId(ThisPtr, out Guid guid));
return guid;
}
}
public uint PropertyCount
{
get
{
unsafe
{
uint count = default;
Marshal.ThrowExceptionForHR(_obj.Vftbl.GetPropertyCount(ThisPtr, &count));
return count;
}
}
}
public uint SourceCount
{
get
{
Marshal.ThrowExceptionForHR(_obj.Vftbl.GetSourceCount(ThisPtr, out uint count));
return count;
}
}
public uint GetNamedPropertyMapping(string name, out global::Windows.Graphics.Effects.Interop.GRAPHICS_EFFECT_PROPERTY_MAPPING mapping)
{
throw new NotImplementedException();
}
public object GetProperty(uint index)
{
// Marshal.ThrowExceptionForHR(_obj.Vftbl.GetProperty(ThisPtr, index, out IntPtr value));
throw new NotImplementedException();
}
public global::Windows.Graphics.Effects.IGraphicsEffectSource GetSource(uint index)
{
throw new NotImplementedException();
}
}
}

35
src/Windows/Avalonia.Win32/Composition/SaturationEffect.cs

@ -1,35 +0,0 @@
using System;
using Windows.Graphics.Effects;
namespace Avalonia.Win32
{
class SaturationEffect : EffectBase
{
public SaturationEffect(IGraphicsEffectSource source) : base(source)
{
}
enum D2D1_SATURATION_PROP
{
D2D1_SATURATION_PROP_SATURATION,
D2D1_SATURATION_PROP_FORCE_DWORD
};
public override Guid EffectId => D2DEffects.CLSID_D2D1Saturation;
public override uint PropertyCount => 1;
public override object GetProperty(uint index)
{
switch ((D2D1_SATURATION_PROP)index)
{
case D2D1_SATURATION_PROP.D2D1_SATURATION_PROP_SATURATION:
return 2.0f;
}
return null;
}
}
}

12
src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs

@ -1225,6 +1225,9 @@ namespace Avalonia.Win32.Interop
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LoadLibrary(string fileName);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LoadLibraryEx(string fileName, IntPtr hFile, int flags);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
public static extern IntPtr GetProcAddress(IntPtr hModule, string lpProcName);
@ -1382,6 +1385,9 @@ namespace Avalonia.Win32.Interop
[DllImport("dwmapi.dll")]
public static extern int DwmIsCompositionEnabled(out bool enabled);
[DllImport("dwmapi.dll")]
public static extern void DwmFlush();
[DllImport("dwmapi.dll")]
public static extern bool DwmDefWindowProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam, ref IntPtr plResult);
@ -1613,6 +1619,12 @@ namespace Avalonia.Win32.Interop
public int X;
public int Y;
}
public struct SIZE
{
public int X;
public int Y;
}
public struct RECT
{

10
src/Windows/Avalonia.Win32/Win32GlManager.cs

@ -3,6 +3,7 @@ using Avalonia.OpenGL;
using Avalonia.OpenGL.Angle;
using Avalonia.OpenGL.Egl;
using Avalonia.Win32.OpenGl;
using Avalonia.Win32.WinRT.Composition;
namespace Avalonia.Win32
{
@ -24,13 +25,8 @@ namespace Avalonia.Win32
var egl = EglPlatformOpenGlInterface.TryCreate(() => new AngleWin32EglDisplay());
if (egl is { } &&
opts?.UseWindowsUIComposition == true)
{
var compositionConnector = CompositionConnector.TryCreate(egl);
if (compositionConnector != null)
AvaloniaLocator.CurrentMutable.BindToSelf(compositionConnector);
}
opts?.UseWindowsUIComposition == true)
WinUICompositorConnection.TryCreateAndRegister(egl);
return egl;
}

130
src/Windows/Avalonia.Win32/WinRT/Composition/D2DEffects.cs

@ -0,0 +1,130 @@
using System;
namespace Avalonia.Win32.WinRT.Composition
{
class D2DEffects
{
public static readonly Guid CLSID_D2D12DAffineTransform =
new Guid(0x6AA97485, 0x6354, 0x4CFC, 0x90, 0x8C, 0xE4, 0xA7, 0x4F, 0x62, 0xC9, 0x6C);
public static readonly Guid CLSID_D2D13DPerspectiveTransform =
new Guid(0xC2844D0B, 0x3D86, 0x46E7, 0x85, 0xBA, 0x52, 0x6C, 0x92, 0x40, 0xF3, 0xFB);
public static readonly Guid CLSID_D2D13DTransform =
new Guid(0xE8467B04, 0xEC61, 0x4B8A, 0xB5, 0xDE, 0xD4, 0xD7, 0x3D, 0xEB, 0xEA, 0x5A);
public static readonly Guid CLSID_D2D1ArithmeticComposite =
new Guid(0xFC151437, 0x049A, 0x4784, 0xA2, 0x4A, 0xF1, 0xC4, 0xDA, 0xF2, 0x09, 0x87);
public static readonly Guid CLSID_D2D1Atlas =
new Guid(0x913E2BE4, 0xFDCF, 0x4FE2, 0xA5, 0xF0, 0x24, 0x54, 0xF1, 0x4F, 0xF4, 0x08);
public static readonly Guid CLSID_D2D1BitmapSource =
new Guid(0x5FB6C24D, 0xC6DD, 0x4231, 0x94, 0x4, 0x50, 0xF4, 0xD5, 0xC3, 0x25, 0x2D);
public static readonly Guid CLSID_D2D1Blend =
new Guid(0x81C5B77B, 0x13F8, 0x4CDD, 0xAD, 0x20, 0xC8, 0x90, 0x54, 0x7A, 0xC6, 0x5D);
public static readonly Guid CLSID_D2D1Border =
new Guid(0x2A2D49C0, 0x4ACF, 0x43C7, 0x8C, 0x6A, 0x7C, 0x4A, 0x27, 0x87, 0x4D, 0x27);
public static readonly Guid CLSID_D2D1Brightness =
new Guid(0x8CEA8D1E, 0x77B0, 0x4986, 0xB3, 0xB9, 0x2F, 0x0C, 0x0E, 0xAE, 0x78, 0x87);
public static readonly Guid CLSID_D2D1ColorManagement =
new Guid(0x1A28524C, 0xFDD6, 0x4AA4, 0xAE, 0x8F, 0x83, 0x7E, 0xB8, 0x26, 0x7B, 0x37);
public static readonly Guid CLSID_D2D1ColorMatrix =
new Guid(0x921F03D6, 0x641C, 0x47DF, 0x85, 0x2D, 0xB4, 0xBB, 0x61, 0x53, 0xAE, 0x11);
public static readonly Guid CLSID_D2D1Composite =
new Guid(0x48FC9F51, 0xF6AC, 0x48F1, 0x8B, 0x58, 0x3B, 0x28, 0xAC, 0x46, 0xF7, 0x6D);
public static readonly Guid CLSID_D2D1ConvolveMatrix =
new Guid(0x407F8C08, 0x5533, 0x4331, 0xA3, 0x41, 0x23, 0xCC, 0x38, 0x77, 0x84, 0x3E);
public static readonly Guid CLSID_D2D1Crop =
new Guid(0xE23F7110, 0x0E9A, 0x4324, 0xAF, 0x47, 0x6A, 0x2C, 0x0C, 0x46, 0xF3, 0x5B);
public static readonly Guid CLSID_D2D1DirectionalBlur =
new Guid(0x174319A6, 0x58E9, 0x49B2, 0xBB, 0x63, 0xCA, 0xF2, 0xC8, 0x11, 0xA3, 0xDB);
public static readonly Guid CLSID_D2D1DiscreteTransfer =
new Guid(0x90866FCD, 0x488E, 0x454B, 0xAF, 0x06, 0xE5, 0x04, 0x1B, 0x66, 0xC3, 0x6C);
public static readonly Guid CLSID_D2D1DisplacementMap =
new Guid(0xEDC48364, 0x417, 0x4111, 0x94, 0x50, 0x43, 0x84, 0x5F, 0xA9, 0xF8, 0x90);
public static readonly Guid CLSID_D2D1DistantDiffuse =
new Guid(0x3E7EFD62, 0xA32D, 0x46D4, 0xA8, 0x3C, 0x52, 0x78, 0x88, 0x9A, 0xC9, 0x54);
public static readonly Guid CLSID_D2D1DistantSpecular =
new Guid(0x428C1EE5, 0x77B8, 0x4450, 0x8A, 0xB5, 0x72, 0x21, 0x9C, 0x21, 0xAB, 0xDA);
public static readonly Guid CLSID_D2D1DpiCompensation =
new Guid(0x6C26C5C7, 0x34E0, 0x46FC, 0x9C, 0xFD, 0xE5, 0x82, 0x37, 0x6, 0xE2, 0x28);
public static readonly Guid CLSID_D2D1Flood =
new Guid(0x61C23C20, 0xAE69, 0x4D8E, 0x94, 0xCF, 0x50, 0x07, 0x8D, 0xF6, 0x38, 0xF2);
public static readonly Guid CLSID_D2D1GammaTransfer =
new Guid(0x409444C4, 0xC419, 0x41A0, 0xB0, 0xC1, 0x8C, 0xD0, 0xC0, 0xA1, 0x8E, 0x42);
public static readonly Guid CLSID_D2D1GaussianBlur =
new Guid(0x1FEB6D69, 0x2FE6, 0x4AC9, 0x8C, 0x58, 0x1D, 0x7F, 0x93, 0xE7, 0xA6, 0xA5);
public static readonly Guid CLSID_D2D1Scale =
new Guid(0x9DAF9369, 0x3846, 0x4D0E, 0xA4, 0x4E, 0xC, 0x60, 0x79, 0x34, 0xA5, 0xD7);
public static readonly Guid CLSID_D2D1Histogram =
new Guid(0x881DB7D0, 0xF7EE, 0x4D4D, 0xA6, 0xD2, 0x46, 0x97, 0xAC, 0xC6, 0x6E, 0xE8);
public static readonly Guid CLSID_D2D1HueRotation =
new Guid(0x0F4458EC, 0x4B32, 0x491B, 0x9E, 0x85, 0xBD, 0x73, 0xF4, 0x4D, 0x3E, 0xB6);
public static readonly Guid CLSID_D2D1LinearTransfer =
new Guid(0xAD47C8FD, 0x63EF, 0x4ACC, 0x9B, 0x51, 0x67, 0x97, 0x9C, 0x03, 0x6C, 0x06);
public static readonly Guid CLSID_D2D1LuminanceToAlpha =
new Guid(0x41251AB7, 0x0BEB, 0x46F8, 0x9D, 0xA7, 0x59, 0xE9, 0x3F, 0xCC, 0xE5, 0xDE);
public static readonly Guid CLSID_D2D1Morphology =
new Guid(0xEAE6C40D, 0x626A, 0x4C2D, 0xBF, 0xCB, 0x39, 0x10, 0x01, 0xAB, 0xE2, 0x02);
public static readonly Guid CLSID_D2D1OpacityMetadata =
new Guid(0x6C53006A, 0x4450, 0x4199, 0xAA, 0x5B, 0xAD, 0x16, 0x56, 0xFE, 0xCE, 0x5E);
public static readonly Guid CLSID_D2D1PointDiffuse =
new Guid(0xB9E303C3, 0xC08C, 0x4F91, 0x8B, 0x7B, 0x38, 0x65, 0x6B, 0xC4, 0x8C, 0x20);
public static readonly Guid CLSID_D2D1PointSpecular =
new Guid(0x09C3CA26, 0x3AE2, 0x4F09, 0x9E, 0xBC, 0xED, 0x38, 0x65, 0xD5, 0x3F, 0x22);
public static readonly Guid CLSID_D2D1Premultiply =
new Guid(0x06EAB419, 0xDEED, 0x4018, 0x80, 0xD2, 0x3E, 0x1D, 0x47, 0x1A, 0xDE, 0xB2);
public static readonly Guid CLSID_D2D1Saturation =
new Guid(0x5CB2D9CF, 0x327D, 0x459F, 0xA0, 0xCE, 0x40, 0xC0, 0xB2, 0x08, 0x6B, 0xF7);
public static readonly Guid CLSID_D2D1Shadow =
new Guid(0xC67EA361, 0x1863, 0x4E69, 0x89, 0xDB, 0x69, 0x5D, 0x3E, 0x9A, 0x5B, 0x6B);
public static readonly Guid CLSID_D2D1SpotDiffuse =
new Guid(0x818A1105, 0x7932, 0x44F4, 0xAA, 0x86, 0x08, 0xAE, 0x7B, 0x2F, 0x2C, 0x93);
public static readonly Guid CLSID_D2D1SpotSpecular =
new Guid(0xEDAE421E, 0x7654, 0x4A37, 0x9D, 0xB8, 0x71, 0xAC, 0xC1, 0xBE, 0xB3, 0xC1);
public static readonly Guid CLSID_D2D1TableTransfer =
new Guid(0x5BF818C3, 0x5E43, 0x48CB, 0xB6, 0x31, 0x86, 0x83, 0x96, 0xD6, 0xA1, 0xD4);
public static readonly Guid CLSID_D2D1Tile =
new Guid(0xB0784138, 0x3B76, 0x4BC5, 0xB1, 0x3B, 0x0F, 0xA2, 0xAD, 0x02, 0x65, 0x9F);
public static readonly Guid CLSID_D2D1Turbulence =
new Guid(0xCF2BB6AE, 0x889A, 0x4AD7, 0xBA, 0x29, 0xA2, 0xFD, 0x73, 0x2C, 0x9F, 0xC9);
public static readonly Guid CLSID_D2D1UnPremultiply =
new Guid(0xFB9AC489, 0xAD8D, 0x41ED, 0x99, 0x99, 0xBB, 0x63, 0x47, 0xD1, 0x10, 0xF7);
}
}

99
src/Windows/Avalonia.Win32/WinRT/Composition/WinUICompositedWindow.cs

@ -0,0 +1,99 @@
using System;
using System.Numerics;
using System.Reactive.Disposables;
using System.Threading;
using Avalonia.MicroCom;
using Avalonia.OpenGL;
using Avalonia.OpenGL.Egl;
using Avalonia.Win32.Interop;
namespace Avalonia.Win32.WinRT.Composition
{
public class WinUICompositedWindow : IDisposable
{
private EglContext _syncContext;
private readonly object _pumpLock;
private readonly IVisual _blurVisual;
private ICompositionTarget _compositionTarget;
private IVisual _contentVisual;
private ICompositionDrawingSurfaceInterop _surfaceInterop;
private PixelSize _size;
private static Guid IID_ID3D11Texture2D = Guid.Parse("6f15aaf2-d208-4e89-9ab4-489535d34f9c");
private ICompositor _compositor;
internal WinUICompositedWindow(EglContext syncContext,
ICompositor compositor,
object pumpLock,
ICompositionTarget compositionTarget,
ICompositionDrawingSurfaceInterop surfaceInterop,
IVisual contentVisual, IVisual blurVisual)
{
_compositor = compositor.CloneReference();
_syncContext = syncContext;
_pumpLock = pumpLock;
_blurVisual = blurVisual.CloneReference();
_compositionTarget = compositionTarget.CloneReference();
_contentVisual = contentVisual.CloneReference();
_surfaceInterop = surfaceInterop.CloneReference();
}
public void ResizeIfNeeded(PixelSize size)
{
using (_syncContext.EnsureLocked())
{
if (_size != size)
{
_surfaceInterop.Resize(new UnmanagedMethods.POINT { X = size.Width, Y = size.Height });
_contentVisual.SetSize(new Vector2(size.Width, size.Height));
_size = size;
}
}
}
public unsafe IUnknown BeginDrawToTexture(out PixelPoint offset)
{
if (!_syncContext.IsCurrent)
throw new InvalidOperationException();
var iid = IID_ID3D11Texture2D;
void* pTexture;
var off = _surfaceInterop.BeginDraw(null, &iid, &pTexture);
offset = new PixelPoint(off.X, off.Y);
return MicroComRuntime.CreateProxyFor<IUnknown>(pTexture, true);
}
public void EndDraw()
{
if (!_syncContext.IsCurrent)
throw new InvalidOperationException();
_surfaceInterop.EndDraw();
}
public void SetBlur(bool enable)
{
using (_syncContext.EnsureLocked())
_blurVisual.SetIsVisible(enable ? 1 : 0);
}
public IDisposable BeginTransaction()
{
Monitor.Enter(_pumpLock);
return Disposable.Create(() => Monitor.Exit(_pumpLock));
}
public void Dispose()
{
if (_syncContext == null)
{
_compositor.Dispose();
_blurVisual.Dispose();
_contentVisual.Dispose();
_surfaceInterop.Dispose();
_compositionTarget.Dispose();
}
}
}
}

238
src/Windows/Avalonia.Win32/WinRT/Composition/WinUICompositorConnection.cs

@ -0,0 +1,238 @@
using System;
using System.Diagnostics;
using System.Numerics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using Avalonia.Logging;
using Avalonia.MicroCom;
using Avalonia.OpenGL;
using Avalonia.OpenGL.Angle;
using Avalonia.OpenGL.Egl;
using Avalonia.Rendering;
using Avalonia.Win32.Interop;
namespace Avalonia.Win32.WinRT.Composition
{
class WinUICompositorConnection : IRenderTimer
{
private readonly EglContext _syncContext;
private IntPtr _queue;
private ICompositor _compositor;
private ICompositor2 _compositor2;
private ICompositor5 _compositor5;
private ICompositorInterop _compositorInterop;
private AngleWin32EglDisplay _angle;
private ICompositionGraphicsDevice _device;
private EglPlatformOpenGlInterface _gl;
private ICompositorDesktopInterop _compositorDesktopInterop;
private ICompositionBrush _blurBrush;
private object _pumpLock = new object();
public WinUICompositorConnection(EglPlatformOpenGlInterface gl, object pumpLock)
{
_gl = gl;
_pumpLock = pumpLock;
_syncContext = _gl.PrimaryEglContext;
_angle = (AngleWin32EglDisplay)_gl.Display;
_compositor = NativeWinRTMethods.CreateInstance<ICompositor>("Windows.UI.Composition.Compositor");
_compositor2 = _compositor.QueryInterface<ICompositor2>();
_compositor5 = _compositor.QueryInterface<ICompositor5>();
_compositorInterop = _compositor.QueryInterface<ICompositorInterop>();
_compositorDesktopInterop = _compositor.QueryInterface<ICompositorDesktopInterop>();
using var device = MicroComRuntime.CreateProxyFor<IUnknown>(_angle.GetDirect3DDevice(), true);
_device = _compositorInterop.CreateGraphicsDevice(device);
_blurBrush = CreateBlurBrush();
}
public EglPlatformOpenGlInterface Egl => _gl;
static bool TryCreateAndRegisterCore(EglPlatformOpenGlInterface angle)
{
var tcs = new TaskCompletionSource<bool>();
var pumpLock = new object();
var th = new Thread(() =>
{
WinUICompositorConnection connect;
try
{
NativeWinRTMethods.CreateDispatcherQueueController(new NativeWinRTMethods.DispatcherQueueOptions
{
apartmentType = NativeWinRTMethods.DISPATCHERQUEUE_THREAD_APARTMENTTYPE.DQTAT_COM_NONE,
dwSize = Marshal.SizeOf<NativeWinRTMethods.DispatcherQueueOptions>(),
threadType = NativeWinRTMethods.DISPATCHERQUEUE_THREAD_TYPE.DQTYPE_THREAD_CURRENT
});
connect = new WinUICompositorConnection(angle, pumpLock);
AvaloniaLocator.CurrentMutable.BindToSelf(connect);
AvaloniaLocator.CurrentMutable.Bind<IRenderTimer>().ToConstant(connect);
tcs.SetResult(true);
}
catch (Exception e)
{
tcs.SetException(e);
return;
}
connect.RunLoop();
})
{
IsBackground = true
};
th.SetApartmentState(ApartmentState.STA);
th.Start();
return tcs.Task.Result;
}
class RunLoopHandler : IAsyncActionCompletedHandler, IMicroComShadowContainer
{
private readonly WinUICompositorConnection _parent;
private Stopwatch _st = Stopwatch.StartNew();
public RunLoopHandler(WinUICompositorConnection parent)
{
_parent = parent;
}
public void Dispose()
{
}
public void Invoke(IAsyncAction asyncInfo, AsyncStatus asyncStatus)
{
_parent.Tick?.Invoke(_st.Elapsed);
using var act = _parent._compositor5.RequestCommitAsync();
act.SetCompleted(this);
}
public MicroComShadow Shadow { get; set; }
public void OnReferencedFromNative()
{
}
public void OnUnreferencedFromNative()
{
}
}
private void RunLoop()
{
{
var st = Stopwatch.StartNew();
using (var act = _compositor5.RequestCommitAsync())
act.SetCompleted(new RunLoopHandler(this));
while (true)
{
UnmanagedMethods.GetMessage(out var msg, IntPtr.Zero, 0, 0);
lock (_pumpLock)
UnmanagedMethods.DispatchMessage(ref msg);
}
}
}
public static void TryCreateAndRegister(EglPlatformOpenGlInterface angle)
{
const int majorRequired = 10;
const int buildRequired = 16299;
var majorInstalled = Win32Platform.WindowsVersion.Major;
var buildInstalled = Win32Platform.WindowsVersion.Build;
if (majorInstalled >= majorRequired &&
buildInstalled >= buildRequired)
{
try
{
TryCreateAndRegisterCore(angle);
}
catch (Exception e)
{
Logger.TryGet(LogEventLevel.Error, "WinUIComposition")
?.Log(null, "Unable to initialize WinUI compositor: {0}", e);
}
}
var osVersionNotice =
$"Windows {majorRequired} Build {buildRequired} is required. Your machine has Windows {majorInstalled} Build {buildInstalled} installed.";
Logger.TryGet(LogEventLevel.Warning, "WinUIComposition")?.Log(null,
$"Unable to initialize WinUI compositor: {osVersionNotice}");
}
public WinUICompositedWindow CreateWindow(IntPtr hWnd)
{
using var sc = _syncContext.EnsureLocked();
using var desktopTarget = _compositorDesktopInterop.CreateDesktopWindowTarget(hWnd, 0);
using var target = desktopTarget.QueryInterface<ICompositionTarget>();
using var drawingSurface = _device.CreateDrawingSurface(new UnmanagedMethods.SIZE(), DirectXPixelFormat.B8G8R8A8UIntNormalized,
DirectXAlphaMode.Premultiplied);
using var surface = drawingSurface.QueryInterface<ICompositionSurface>();
using var surfaceInterop = drawingSurface.QueryInterface<ICompositionDrawingSurfaceInterop>();
using var surfaceBrush = _compositor.CreateSurfaceBrushWithSurface(surface);
using var brush = surfaceBrush.QueryInterface<ICompositionBrush>();
using var spriteVisual = _compositor.CreateSpriteVisual();
spriteVisual.SetBrush(brush);
using var visual = spriteVisual.QueryInterface<IVisual>();
using var visual2 = spriteVisual.QueryInterface<IVisual2>();
using var container = _compositor.CreateContainerVisual();
using var containerVisual = container.QueryInterface<IVisual>();
using var containerVisual2 = container.QueryInterface<IVisual2>();
containerVisual2.SetRelativeSizeAdjustment(new Vector2(1, 1));
using var containerChildren = container.Children;
target.SetRoot(containerVisual);
using var blur = CreateBlurVisual();
containerChildren.InsertAtTop(blur);
containerChildren.InsertAtTop(visual);
return new WinUICompositedWindow(_syncContext, _compositor, _pumpLock, target, surfaceInterop, visual, blur);
}
private unsafe ICompositionBrush CreateBlurBrush()
{
using var backDropParameterFactory = NativeWinRTMethods.CreateActivationFactory<ICompositionEffectSourceParameterFactory>(
"Windows.UI.Composition.CompositionEffectSourceParameter");
using var backdropString = new HStringInterop("backdrop");
using var backDropParameter =
backDropParameterFactory.Create(backdropString.Handle);
using var backDropParameterAsSource = backDropParameter.QueryInterface<IGraphicsEffectSource>();
var blurEffect = new WinUIGaussianBlurEffect(backDropParameterAsSource);
using var blurEffectFactory = _compositor.CreateEffectFactory(blurEffect);
using var backdrop = _compositor2.CreateBackdropBrush();
using var backdropBrush = backdrop.QueryInterface<ICompositionBrush>();
var saturateEffect = new SaturationEffect(blurEffect);
using var satEffectFactory = _compositor.CreateEffectFactory(saturateEffect);
using var sat = satEffectFactory.CreateBrush();
sat.SetSourceParameter(backdropString.Handle, backdropBrush);
return sat.QueryInterface<ICompositionBrush>();
}
private unsafe IVisual CreateBlurVisual()
{
using var spriteVisual = _compositor.CreateSpriteVisual();
using var visual = spriteVisual.QueryInterface<IVisual>();
using var visual2 = spriteVisual.QueryInterface<IVisual2>();
spriteVisual.SetBrush(_blurBrush);
visual.SetIsVisible(0);
visual2.SetRelativeSizeAdjustment(new Vector2(1.0f, 1.0f));
return visual.CloneReference();
}
public event Action<TimeSpan> Tick;
}
}

135
src/Windows/Avalonia.Win32/WinRT/Composition/WinUIEffectBase.cs

@ -0,0 +1,135 @@
using System;
using System.Linq;
using System.Runtime.InteropServices;
using Avalonia.MicroCom;
namespace Avalonia.Win32.WinRT.Composition
{
abstract class WinUIEffectBase : WinRTInspectable, IGraphicsEffect, IGraphicsEffectSource, IGraphicsEffectD2D1Interop
{
private IGraphicsEffectSource[] _sources;
public WinUIEffectBase(params IGraphicsEffectSource[] _sources)
{
this._sources = _sources.Select(e =>
{
if (e is WinUIEffectBase)
return e;
return e.CloneReference();
}).ToArray();
}
public IntPtr Name => IntPtr.Zero;
public void SetName(IntPtr name)
{
}
public abstract Guid EffectId { get; }
public unsafe void GetNamedPropertyMapping(IntPtr name, uint* index, GRAPHICS_EFFECT_PROPERTY_MAPPING* mapping) =>
throw new COMException("Not supported", unchecked((int)0x80004001));
public abstract uint PropertyCount { get; }
public abstract IPropertyValue GetProperty(uint index);
public IGraphicsEffectSource GetSource(uint index)
{
if (_sources == null || index> _sources.Length)
throw new COMException("Invalid index", unchecked((int)0x80070057));
return _sources[index];
}
public uint SourceCount => (uint)(_sources?.Length ?? 0);
public override void OnUnreferencedFromNative()
{
if (_sources == null)
return;
/*foreach(var s in _sources)
s.Dispose();*/
_sources = null;
}
}
class WinUIGaussianBlurEffect : WinUIEffectBase
{
public WinUIGaussianBlurEffect(IGraphicsEffectSource source) : base(source)
{
}
enum D2D1_GAUSSIANBLUR_OPTIMIZATION
{
D2D1_GAUSSIANBLUR_OPTIMIZATION_SPEED,
D2D1_GAUSSIANBLUR_OPTIMIZATION_BALANCED,
D2D1_GAUSSIANBLUR_OPTIMIZATION_QUALITY,
D2D1_GAUSSIANBLUR_OPTIMIZATION_FORCE_DWORD
};
enum D2D1_BORDER_MODE
{
D2D1_BORDER_MODE_SOFT,
D2D1_BORDER_MODE_HARD,
D2D1_BORDER_MODE_FORCE_DWORD
};
enum D2D1GaussianBlurProp
{
D2D1_GAUSSIANBLUR_PROP_STANDARD_DEVIATION,
D2D1_GAUSSIANBLUR_PROP_OPTIMIZATION,
D2D1_GAUSSIANBLUR_PROP_BORDER_MODE,
D2D1_GAUSSIANBLUR_PROP_FORCE_DWORD
};
public override Guid EffectId => D2DEffects.CLSID_D2D1GaussianBlur;
public override uint PropertyCount => 3;
public override IPropertyValue GetProperty(uint index)
{
switch ((D2D1GaussianBlurProp)index)
{
case D2D1GaussianBlurProp.D2D1_GAUSSIANBLUR_PROP_STANDARD_DEVIATION:
return new WinRTPropertyValue(30.0f);
case D2D1GaussianBlurProp.D2D1_GAUSSIANBLUR_PROP_OPTIMIZATION:
return new WinRTPropertyValue((uint)D2D1_GAUSSIANBLUR_OPTIMIZATION
.D2D1_GAUSSIANBLUR_OPTIMIZATION_BALANCED);
case D2D1GaussianBlurProp.D2D1_GAUSSIANBLUR_PROP_BORDER_MODE:
return new WinRTPropertyValue((uint)D2D1_BORDER_MODE.D2D1_BORDER_MODE_HARD);
}
return null;
}
}
class SaturationEffect : WinUIEffectBase
{
public SaturationEffect(IGraphicsEffectSource source) : base(source)
{
}
enum D2D1_SATURATION_PROP
{
D2D1_SATURATION_PROP_SATURATION,
D2D1_SATURATION_PROP_FORCE_DWORD
};
public override Guid EffectId => D2DEffects.CLSID_D2D1Saturation;
public override uint PropertyCount => 1;
public override IPropertyValue GetProperty(uint index)
{
switch ((D2D1_SATURATION_PROP)index)
{
case D2D1_SATURATION_PROP.D2D1_SATURATION_PROP_SATURATION:
return new WinRTPropertyValue(2.0f);
}
return null;
}
}
}

118
src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs

@ -0,0 +1,118 @@
using System;
using System.Runtime.InteropServices;
using Avalonia.MicroCom;
using Avalonia.OpenGL.Angle;
using Avalonia.OpenGL.Egl;
using Avalonia.OpenGL.Surfaces;
using Avalonia.Utilities;
using Avalonia.Win32.Interop;
namespace Avalonia.Win32.WinRT.Composition
{
internal class WinUiCompositedWindowSurface : EglGlPlatformSurfaceBase, IBlurHost, IDisposable
{
private readonly WinUICompositorConnection _connection;
private EglPlatformOpenGlInterface _egl;
private readonly EglGlPlatformSurfaceBase.IEglWindowGlPlatformSurfaceInfo _info;
private IRef<WinUICompositedWindow> _window;
private bool _enableBlur;
public WinUiCompositedWindowSurface(WinUICompositorConnection connection, IEglWindowGlPlatformSurfaceInfo info) : base()
{
_connection = connection;
_egl = connection.Egl;
_info = info;
}
public override IGlPlatformSurfaceRenderTarget CreateGlRenderTarget()
{
using (_egl.PrimaryContext.EnsureCurrent())
{
if (_window?.Item == null)
{
_window = RefCountable.Create(_connection.CreateWindow(_info.Handle));
_window.Item.SetBlur(_enableBlur);
}
return new CompositionRenderTarget(_egl, _window, _info);
}
}
class CompositionRenderTarget : EglPlatformSurfaceRenderTargetBase
{
private readonly EglPlatformOpenGlInterface _egl;
private readonly IRef<WinUICompositedWindow> _window;
private readonly IEglWindowGlPlatformSurfaceInfo _info;
public CompositionRenderTarget(EglPlatformOpenGlInterface egl,
IRef<WinUICompositedWindow> window,
IEglWindowGlPlatformSurfaceInfo info)
: base(egl)
{
_egl = egl;
_window = window.Clone();
_info = info;
_window.Item.ResizeIfNeeded(_info.Size);
}
public override IGlPlatformSurfaceRenderingSession BeginDraw()
{
var contextLock = _egl.PrimaryEglContext.EnsureCurrent();
IUnknown texture = null;
EglSurface surface = null;
IDisposable transaction = null;
var success = false;
try
{
if (_window?.Item == null)
throw new ObjectDisposedException(GetType().FullName);
var size = _info.Size;
transaction = _window.Item.BeginTransaction();
_window.Item.ResizeIfNeeded(size);
texture = _window.Item.BeginDrawToTexture(out var offset);
surface = ((AngleWin32EglDisplay) _egl.Display).WrapDirect3D11Texture(_egl,
texture.GetNativeIntPtr(),
offset.X, offset.Y, size.Width, size.Height);
var res = base.BeginDraw(surface, _info, () =>
{
surface?.Dispose();
texture?.Dispose();
_window.Item.EndDraw();
transaction?.Dispose();
contextLock?.Dispose();
}, true);
success = true;
return res;
}
finally
{
if (!success)
{
surface?.Dispose();
texture?.Dispose();
transaction?.Dispose();
contextLock.Dispose();
}
}
}
}
public void SetBlur(bool enable)
{
_enableBlur = enable;
_window?.Item?.SetBlur(enable);
}
public void Dispose()
{
using (_egl.PrimaryEglContext.EnsureLocked())
{
_window?.Dispose();
_window = null;
}
}
}
}

7
src/Windows/Avalonia.Win32/WinRT/IBlurHost.cs

@ -0,0 +1,7 @@
namespace Avalonia.Win32.WinRT
{
public interface IBlurHost
{
void SetBlur(bool enable);
}
}

140
src/Windows/Avalonia.Win32/WinRT/NativeWinRTMethods.cs

@ -0,0 +1,140 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading;
using Avalonia.MicroCom;
using Avalonia.Win32.Interop;
namespace Avalonia.Win32.WinRT
{
internal static class NativeWinRTMethods
{
[DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall,
PreserveSig = false)]
internal static extern unsafe IntPtr WindowsCreateString(
[MarshalAs(UnmanagedType.LPWStr)] string sourceString,
int length);
internal static IntPtr WindowsCreateString(string sourceString)
=> WindowsCreateString(sourceString, sourceString.Length);
[DllImport("api-ms-win-core-winrt-string-l1-1-0.dll",
CallingConvention = CallingConvention.StdCall, PreserveSig = false)]
internal static extern unsafe IntPtr WindowsDeleteString(IntPtr hString);
[DllImport("Windows.UI.Composition", EntryPoint = "DllGetActivationFactory",
CallingConvention = CallingConvention.StdCall, PreserveSig = false)]
private extern static IntPtr GetWindowsUICompositionActivationFactory(
IntPtr activatableClassId);
internal static IActivationFactory GetWindowsUICompositionActivationFactory(string className)
{//"Windows.UI.Composition.Compositor"
var s = WindowsCreateString(className);
var factory = GetWindowsUICompositionActivationFactory(s);
return MicroComRuntime.CreateProxyFor<IActivationFactory>(factory, true);
}
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
delegate int GetActivationFactoryDelegate(IntPtr classId, out IntPtr ppv);
internal static T CreateInstance<T>(string fullName) where T : IUnknown
{
var s = WindowsCreateString(fullName);
EnsureRoInitialized();
var pUnk = RoActivateInstance(s);
using var unk = MicroComRuntime.CreateProxyFor<IUnknown>(pUnk, true);
WindowsDeleteString(s);
return MicroComRuntime.QueryInterface<T>(unk);
}
internal static TFactory CreateActivationFactory<TFactory>(string fullName) where TFactory : IUnknown
{
var s = WindowsCreateString(fullName);
EnsureRoInitialized();
var guid = MicroComRuntime.GetGuidFor(typeof(TFactory));
var pUnk = RoGetActivationFactory(s, ref guid);
using var unk = MicroComRuntime.CreateProxyFor<IUnknown>(pUnk, true);
WindowsDeleteString(s);
return MicroComRuntime.QueryInterface<TFactory>(unk);
}
internal enum DISPATCHERQUEUE_THREAD_APARTMENTTYPE
{
DQTAT_COM_NONE = 0,
DQTAT_COM_ASTA = 1,
DQTAT_COM_STA = 2
};
internal enum DISPATCHERQUEUE_THREAD_TYPE
{
DQTYPE_THREAD_DEDICATED = 1,
DQTYPE_THREAD_CURRENT = 2,
};
[StructLayout(LayoutKind.Sequential)]
internal struct DispatcherQueueOptions
{
public int dwSize;
[MarshalAs(UnmanagedType.I4)]
public DISPATCHERQUEUE_THREAD_TYPE threadType;
[MarshalAs(UnmanagedType.I4)]
public DISPATCHERQUEUE_THREAD_APARTMENTTYPE apartmentType;
};
[DllImport("coremessaging.dll", PreserveSig = false)]
internal static extern IntPtr CreateDispatcherQueueController(DispatcherQueueOptions options);
internal enum RO_INIT_TYPE
{
RO_INIT_SINGLETHREADED = 0, // Single-threaded application
RO_INIT_MULTITHREADED = 1, // COM calls objects on any thread.
}
[DllImport("combase.dll", PreserveSig = false)]
private static extern void RoInitialize(RO_INIT_TYPE initType);
[DllImport("combase.dll", PreserveSig = false)]
private static extern IntPtr RoActivateInstance(IntPtr activatableClassId);
[DllImport("combase.dll", PreserveSig = false)]
private static extern IntPtr RoGetActivationFactory(IntPtr activatableClassId, ref Guid iid);
private static bool _initialized;
private static void EnsureRoInitialized()
{
if (_initialized)
return;
RoInitialize(Thread.CurrentThread.GetApartmentState() == ApartmentState.STA ?
RO_INIT_TYPE.RO_INIT_SINGLETHREADED :
RO_INIT_TYPE.RO_INIT_MULTITHREADED);
_initialized = true;
}
}
class HStringInterop : IDisposable
{
private IntPtr _s;
public HStringInterop(string s)
{
_s = s == null ? IntPtr.Zero : NativeWinRTMethods.WindowsCreateString(s);
}
public IntPtr Handle => _s;
public void Dispose()
{
if (_s != IntPtr.Zero)
{
NativeWinRTMethods.WindowsDeleteString(_s);
_s = IntPtr.Zero;
}
}
}
}

18
src/Windows/Avalonia.Win32/WinRT/WinRTColor.cs

@ -0,0 +1,18 @@
using System.Runtime.InteropServices;
namespace Avalonia.Win32.WinRT
{
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct WinRTColor
{
public byte A;
public byte R;
public byte G;
public byte B;
public static WinRTColor FromArgb(byte a, byte r, byte g, byte b) => new WinRTColor()
{
A = a, R = r, G = g, B = b
};
}
}

38
src/Windows/Avalonia.Win32/WinRT/WinRTInspectable.cs

@ -0,0 +1,38 @@
using System;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Avalonia.MicroCom;
namespace Avalonia.Win32.WinRT
{
class WinRTInspectable : IInspectable, IMicroComShadowContainer
{
public virtual void Dispose()
{
}
public unsafe void GetIids(ulong* iidCount, Guid** iids)
{
var interfaces = GetType().GetInterfaces().Where(typeof(IUnknown).IsAssignableFrom)
.Select(MicroComRuntime.GetGuidFor).ToArray();
var mem = (Guid*)Marshal.AllocCoTaskMem(Unsafe.SizeOf<Guid>() * interfaces.Length);
for (var c = 0; c < interfaces.Length; c++)
mem[c] = interfaces[c];
*iids = mem;
*iidCount = (ulong) interfaces.Length;
}
public IntPtr RuntimeClassName => NativeWinRTMethods.WindowsCreateString(GetType().FullName);
public TrustLevel TrustLevel => TrustLevel.BaseTrust;
public MicroComShadow Shadow { get; set; }
public virtual void OnReferencedFromNative()
{
}
public virtual void OnUnreferencedFromNative()
{
}
}
}

89
src/Windows/Avalonia.Win32/WinRT/WinRTPropertyValue.cs

@ -0,0 +1,89 @@
using System;
using System.Runtime.InteropServices;
namespace Avalonia.Win32.WinRT
{
class WinRTPropertyValue : WinRTInspectable, IPropertyValue
{
public WinRTPropertyValue(float f)
{
Type = PropertyType.Single;
Single = f;
}
public WinRTPropertyValue(uint u)
{
UInt32 = u;
Type = PropertyType.UInt32;
}
public PropertyType Type { get; }
public int IsNumericScalar { get; }
public byte UInt8 { get; }
public short Int16 { get; }
public ushort UInt16 { get; }
public int Int32 { get; }
public uint UInt32 { get; }
public long Int64 { get; }
public ulong UInt64 { get; }
public float Single { get; }
public double Double { get; }
public char Char16 { get; }
public int Boolean { get; }
public IntPtr String { get; }
public Guid Guid { get; }
private static COMException NotImplemented => new COMException("Not supported", unchecked((int)0x80004001));
public unsafe void GetDateTime(void* value) => throw NotImplemented;
public unsafe void GetTimeSpan(void* value) => throw NotImplemented;
public unsafe void GetPoint(void* value) => throw NotImplemented;
public unsafe void GetSize(void* value) => throw NotImplemented;
public unsafe void GetRect(void* value) => throw NotImplemented;
public unsafe byte* GetUInt8Array(uint* __valueSize) => throw NotImplemented;
public unsafe short* GetInt16Array(uint* __valueSize) => throw NotImplemented;
public unsafe ushort* GetUInt16Array(uint* __valueSize) => throw NotImplemented;
public unsafe int* GetInt32Array(uint* __valueSize)
{
throw NotImplemented;
}
public unsafe uint* GetUInt32Array(uint* __valueSize) => throw NotImplemented;
public unsafe long* GetInt64Array(uint* __valueSize) => throw NotImplemented;
public unsafe ulong* GetUInt64Array(uint* __valueSize) => throw NotImplemented;
public unsafe float* GetSingleArray(uint* __valueSize) => throw NotImplemented;
public unsafe double* GetDoubleArray(uint* __valueSize) => throw NotImplemented;
public unsafe char* GetChar16Array(uint* __valueSize) => throw NotImplemented;
public unsafe int* GetBooleanArray(uint* __valueSize) => throw NotImplemented;
public unsafe IntPtr* GetStringArray(uint* __valueSize) => throw NotImplemented;
public unsafe void** GetInspectableArray(uint* __valueSize) => throw NotImplemented;
public unsafe Guid* GetGuidArray(uint* __valueSize) => throw NotImplemented;
public unsafe void* GetDateTimeArray(uint* __valueSize) => throw NotImplemented;
public unsafe void* GetTimeSpanArray(uint* __valueSize) => throw NotImplemented;
public unsafe void* GetPointArray(uint* __valueSize) => throw NotImplemented;
public unsafe void* GetSizeArray(uint* __valueSize) => throw NotImplemented;
public unsafe void* GetRectArray(uint* __valueSize) => throw NotImplemented;
}
}

718
src/Windows/Avalonia.Win32/WinRT/winrt.idl

@ -0,0 +1,718 @@
@clr-namespace Avalonia.Win32.WinRT
@clr-access internal
@clr-map FLOAT float
@clr-map HSTRING IntPtr
@clr-map Vector2 System.Numerics.Vector2
@clr-map Vector3 System.Numerics.Vector3
@clr-map Quaternion System.Numerics.Quaternion
@clr-map Matrix4x4 System.Numerics.Matrix4x4
@clr-map RECT Avalonia.Win32.Interop.UnmanagedMethods.RECT
@clr-map SIZE Avalonia.Win32.Interop.UnmanagedMethods.SIZE
@clr-map POINT Avalonia.Win32.Interop.UnmanagedMethods.POINT
@clr-map HWND IntPtr
@clr-map BOOL int
@clr-map DWORD int
@clr-map boolean int
@clr-map BYTE byte
@clr-map INT16 short
@clr-map INT32 int
@clr-map INT64 long
@clr-map UINT16 ushort
@clr-map UINT32 uint
@clr-map UINT64 ulong
@clr-map DOUBLE double
@clr-map GUID System.Guid
@clr-map WCHAR System.Char
@clr-map Color Avalonia.Win32.WinRT.WinRTColor
enum TrustLevel
{
BaseTrust,
PartialTrust,
FullTrust
}
enum DirectXAlphaMode
{
Unspecified,
Premultiplied,
Straight,
Ignore
}
enum DirectXPixelFormat
{
Unknown = 0,
R32G32B32A32Typeless = 1,
R32G32B32A32Float = 2,
R32G32B32A32UInt = 3,
R32G32B32A32Int = 4,
R32G32B32Typeless = 5,
R32G32B32Float = 6,
R32G32B32UInt = 7,
R32G32B32Int = 8,
R16G16B16A16Typeless = 9,
R16G16B16A16Float = 10,
R16G16B16A16UIntNormalized = 11,
R16G16B16A16UInt = 12,
R16G16B16A16IntNormalized = 13,
R16G16B16A16Int = 14,
R32G32Typeless = 15,
R32G32Float = 16,
R32G32UInt = 17,
R32G32Int = 18,
R32G8X24Typeless = 19,
D32FloatS8X24UInt = 20,
R32FloatX8X24Typeless = 21,
X32TypelessG8X24UInt = 22,
R10G10B10A2Typeless = 23,
R10G10B10A2UIntNormalized = 24,
R10G10B10A2UInt = 25,
R11G11B10Float = 26,
R8G8B8A8Typeless = 27,
R8G8B8A8UIntNormalized = 28,
R8G8B8A8UIntNormalizedSrgb = 29,
R8G8B8A8UInt = 30,
R8G8B8A8IntNormalized = 31,
R8G8B8A8Int = 32,
R16G16Typeless = 33,
R16G16Float = 34,
R16G16UIntNormalized = 35,
R16G16UInt = 36,
R16G16IntNormalized = 37,
R16G16Int = 38,
R32Typeless = 39,
D32Float = 40,
R32Float = 41,
R32UInt = 42,
R32Int = 43,
R24G8Typeless = 44,
D24UIntNormalizedS8UInt = 45,
R24UIntNormalizedX8Typeless = 46,
X24TypelessG8UInt = 47,
R8G8Typeless = 48,
R8G8UIntNormalized = 49,
R8G8UInt = 50,
R8G8IntNormalized = 51,
R8G8Int = 52,
R16Typeless = 53,
R16Float = 54,
D16UIntNormalized = 55,
R16UIntNormalized = 56,
R16UInt = 57,
R16IntNormalized = 58,
R16Int = 59,
R8Typeless = 60,
R8UIntNormalized = 61,
R8UInt = 62,
R8IntNormalized = 63,
R8Int = 64,
A8UIntNormalized = 65,
R1UIntNormalized = 66,
R9G9B9E5SharedExponent = 67,
R8G8B8G8UIntNormalized = 68,
G8R8G8B8UIntNormalized = 69,
BC1Typeless = 70,
BC1UIntNormalized = 71,
BC1UIntNormalizedSrgb = 72,
BC2Typeless = 73,
BC2UIntNormalized = 74,
BC2UIntNormalizedSrgb = 75,
BC3Typeless = 76,
BC3UIntNormalized = 77,
BC3UIntNormalizedSrgb = 78,
BC4Typeless = 79,
BC4UIntNormalized = 80,
BC4IntNormalized = 81,
BC5Typeless = 82,
BC5UIntNormalized = 83,
BC5IntNormalized = 84,
B5G6R5UIntNormalized = 85,
B5G5R5A1UIntNormalized = 86,
B8G8R8A8UIntNormalized = 87,
B8G8R8X8UIntNormalized = 88,
R10G10B10XRBiasA2UIntNormalized = 89,
B8G8R8A8Typeless = 90,
B8G8R8A8UIntNormalizedSrgb = 91,
B8G8R8X8Typeless = 92,
B8G8R8X8UIntNormalizedSrgb = 93,
BC6HTypeless = 94,
BC6H16UnsignedFloat = 95,
BC6H16Float = 96,
BC7Typeless = 97,
BC7UIntNormalized = 98,
BC7UIntNormalizedSrgb = 99,
Ayuv = 100,
Y410 = 101,
Y416 = 102,
NV12 = 103,
P010 = 104,
P016 = 105,
Opaque420 = 106,
Yuy2 = 107,
Y210 = 108,
Y216 = 109,
NV11 = 110,
AI44 = 111,
IA44 = 112,
P8 = 113,
A8P8 = 114,
B4G4R4A4UIntNormalized = 115,
P208 = 130,
V208 = 131,
V408 = 132,
}
[uuid(AF86E2E0-B12D-4c6a-9C5A-D7AA65101E90)]
interface IInspectable : IUnknown
{
HRESULT GetIids(ulong * iidCount, Guid ** iids);
HRESULT GetRuntimeClassName( [out] IntPtr* className);
HRESULT GetTrustLevel([out] TrustLevel * trustLevel);
}
enum PropertyType
{
Empty = 0,
UInt8 = 1,
Int16 = 2,
UInt16 = 3,
Int32 = 4,
UInt32 = 5,
Int64 = 6,
UInt64 = 7,
Single = 8,
Double = 9,
Char16 = 10,
Boolean = 11,
String = 12,
Inspectable = 13,
DateTime = 14,
TimeSpan = 15,
Guid = 16,
Point = 17,
Size = 18,
Rect = 19,
OtherType = 20,
UInt8Array = 1025,
Int16Array = 1026,
UInt16Array = 1027,
Int32Array = 1028,
UInt32Array = 1029,
Int64Array = 1030,
UInt64Array = 1031,
SingleArray = 1032,
DoubleArray = 1033,
Char16Array = 1034,
BooleanArray = 1035,
StringArray = 1036,
InspectableArray = 1037,
DateTimeArray = 1038,
TimeSpanArray = 1039,
GuidArray = 1040,
PointArray = 1041,
SizeArray = 1042,
RectArray = 1043,
OtherTypeArray = 1044
}
[uuid(4BD682DD-7554-40E9-9A9B-82654EDE7E62)]
interface IPropertyValue : IInspectable
{
[propget] HRESULT Type([out] [retval] PropertyType* value);
[propget] HRESULT IsNumericScalar([out] [retval] boolean* value);
HRESULT GetUInt8([out] [retval] BYTE* value);
HRESULT GetInt16([out] [retval] INT16* value);
HRESULT GetUInt16([out] [retval] UINT16* value);
HRESULT GetInt32([out] [retval] INT32* value);
HRESULT GetUInt32([out] [retval] UINT32* value);
HRESULT GetInt64([out] [retval] INT64* value);
HRESULT GetUInt64([out] [retval] UINT64* value);
HRESULT GetSingle([out] [retval] FLOAT* value);
HRESULT GetDouble([out] [retval] DOUBLE* value);
HRESULT GetChar16([out] [retval] WCHAR* value);
HRESULT GetBoolean([out] [retval] boolean* value);
HRESULT GetString([out] [retval] HSTRING* value);
HRESULT GetGuid([out] [retval] GUID* value);
HRESULT GetDateTime( void* value);
HRESULT GetTimeSpan(void* value);
HRESULT GetPoint(void* value);
HRESULT GetSize(void* value);
HRESULT GetRect(void* value);
HRESULT GetUInt8Array([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] BYTE** value);
HRESULT GetInt16Array([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] INT16** value);
HRESULT GetUInt16Array([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] UINT16** value);
HRESULT GetInt32Array([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] INT32** value);
HRESULT GetUInt32Array([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] UINT32** value);
HRESULT GetInt64Array([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] INT64** value);
HRESULT GetUInt64Array([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] UINT64** value);
HRESULT GetSingleArray([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] FLOAT** value);
HRESULT GetDoubleArray([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] DOUBLE** value);
HRESULT GetChar16Array([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] WCHAR** value);
HRESULT GetBooleanArray([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] boolean** value);
HRESULT GetStringArray([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] HSTRING** value);
HRESULT GetInspectableArray([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] void*** value);
HRESULT GetGuidArray([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] GUID** value);
HRESULT GetDateTimeArray([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] void** value);
HRESULT GetTimeSpanArray([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] void** value);
HRESULT GetPointArray([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] void** value);
HRESULT GetSizeArray([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] void** value);
HRESULT GetRectArray([out] UINT32* __valueSize, [out] [size_is(, *__valueSize)] void** value);
}
enum AsyncStatus {
Started = 0,
Completed,
Canceled,
Error,
}
[uuid(A4ED5C81-76C9-40BD-8BE6-B1D90FB20AE7)]
interface IAsyncActionCompletedHandler : IUnknown
{
HRESULT Invoke([in] IAsyncAction* asyncInfo, [in] AsyncStatus asyncStatus);
}
[uuid(5A648006-843A-4DA9-865B-9D26E5DFAD7B)]
interface IAsyncAction : IInspectable
{
HRESULT SetCompleted([in] IAsyncActionCompletedHandler* handler);
HRESULT GetCompleted([out] [retval] IAsyncActionCompletedHandler** ppv);
HRESULT GetResults();
}
[uuid(603E88E4-A338-4FFE-A457-A5CFB9CEB899)]
interface IDispatcherQueue : IInspectable
{
//TODO
}
[uuid(22F34E66-50DB-4E36-A98D-61C01B384D20)]
interface IDispatcherQueueController : IInspectable
{
[propget] HRESULT DispatcherQueue([out] [retval] IDispatcherQueue** value);
HRESULT ShutdownQueueAsync([out] [retval] IAsyncAction** operation);
}
[uuid(00000035-0000-0000-C000-000000000046)]
interface IActivationFactory : IInspectable
{
HRESULT ActivateInstance([out, retval] IntPtr* instance);
}
[flags]
enum CompositionBatchTypes
{
None = 0x0,
Animation = 0x1,
Effect = 0x2,
InfiniteAnimation = 0x4,
AllAnimations = 0x5
}
[uuid(B403CA50-7F8C-4E83-985F-CC45060036D8)]
interface ICompositor : IInspectable
{
HRESULT CreateColorKeyFrameAnimation([out] [retval] void** result);
[overload("CreateColorBrush")] HRESULT CreateColorBrush([out] [retval]void** result);
[overload("CreateColorBrush")] HRESULT CreateColorBrushWithColor([in] Color* color, [out] [retval] ICompositionColorBrush** result);
HRESULT CreateContainerVisual([out] [retval] IContainerVisual** result);
HRESULT CreateCubicBezierEasingFunction([in] Vector2 controlPoint1, [in] Vector2 controlPoint2, [out] [retval] void** result);
[overload("CreateEffectFactory")] HRESULT CreateEffectFactory([in] IGraphicsEffect* graphicsEffect, [out] [retval] ICompositionEffectFactory** result);
[overload("CreateEffectFactory")] HRESULT CreateEffectFactoryWithProperties([in] void* graphicsEffect, [in] void* animatableProperties, [out] [retval] void** result);
[overload("CreateExpressionAnimation")] HRESULT CreateExpressionAnimation([out] [retval] void** result);
[overload("CreateExpressionAnimation")] HRESULT CreateExpressionAnimationWithExpression([in] HSTRING expression, [out] [retval] void** result);
[overload("CreateInsetClip")] HRESULT CreateInsetClip([out] [retval] void** result);
[overload("CreateInsetClip")] HRESULT CreateInsetClipWithInsets([in] FLOAT leftInset, [in] FLOAT topInset, [in] FLOAT rightInset, [in] FLOAT bottomInset, [out] [retval] void** result);
HRESULT CreateLinearEasingFunction([out] [retval] void** result);
HRESULT CreatePropertySet([out] [retval] void** result);
HRESULT CreateQuaternionKeyFrameAnimation([out] [retval] void** result);
HRESULT CreateScalarKeyFrameAnimation([out] [retval] void** result);
HRESULT CreateScopedBatch([in] CompositionBatchTypes batchType, [out] [retval] ICompositionScopedBatch** result);
HRESULT CreateSpriteVisual([out] [retval] ISpriteVisual** result);
HRESULT CreateSurfaceBrush([out] [retval] ICompositionSurfaceBrush** result);
HRESULT CreateSurfaceBrushWithSurface([in] ICompositionSurface* surface,
[out] [retval] ICompositionSurfaceBrush** result);
HRESULT CreateTargetForCurrentView([out] [retval] void** result);
HRESULT CreateVector2KeyFrameAnimation([out] [retval] void** result);
HRESULT CreateVector3KeyFrameAnimation([out] [retval] void** result);
HRESULT CreateVector4KeyFrameAnimation([out] [retval] void** result);
HRESULT GetCommitBatch([in] CompositionBatchTypes batchType, [out] [retval] void** result);
}
[uuid(735081DC-5E24-45DA-A38F-E32CC349A9A0)]
interface ICompositor2 : IInspectable
{
HRESULT CreateAmbientLight([out] [retval] void** result);
HRESULT CreateAnimationGroup([out] [retval] void** result);
HRESULT CreateBackdropBrush([out] [retval] ICompositionBackdropBrush** result);
HRESULT CreateDistantLight([out] [retval] void** result);
HRESULT CreateDropShadow([out] [retval] void** result);
HRESULT CreateImplicitAnimationCollection([out] [retval] void** result);
HRESULT CreateLayerVisual([out] [retval] void** result);
HRESULT CreateMaskBrush([out] [retval] void** result);
HRESULT CreateNineGridBrush([out] [retval] void** result);
HRESULT CreatePointLight([out] [retval] void** result);
HRESULT CreateSpotLight([out] [retval] void** result);
[overload("CreateStepEasingFunction")] HRESULT CreateStepEasingFunction([out] [retval] void** result);
[overload("CreateStepEasingFunction")] HRESULT CreateStepEasingFunctionWithStepCount([in] INT32 stepCount, [out] [retval] void** result);
}
[uuid(08E05581-1AD1-4F97-9757-402D76E4233B)]
interface ISpriteVisual : IInspectable
{
[propget] HRESULT GetBrush([out] [retval] ICompositionBrush** value);
[propput] HRESULT SetBrush([in] ICompositionBrush* value);
}
[uuid(FD04E6E3-FE0C-4C3C-AB19-A07601A576EE)]
interface ICompositionDrawingSurfaceInterop : IUnknown
{
HRESULT BeginDraw(RECT* updateRect, Guid* iid, void** updateObject, [out, retval]POINT* updateOffset);
HRESULT EndDraw();
HRESULT Resize(POINT sizePixels);
HRESULT Scroll(RECT * scrollRect, RECT * clipRect, int offsetX, int offsetY);
HRESULT ResumeDraw();
HRESULT SuspendDraw();
};
[uuid(A116FF71-F8BF-4C8A-9C98-70779A32A9C8)]
interface ICompositionGraphicsDeviceInterop : IUnknown
{
HRESULT GetRenderingDevice([out] IUnknown ** value);
HRESULT SetRenderingDevice([out] IUnknown * value);
};
[uuid(25297D5C-3AD4-4C9C-B5CF-E36A38512330)]
interface ICompositorInterop : IUnknown
{
HRESULT CreateCompositionSurfaceForHandle(IntPtr swapChain, [out] ICompositionSurface ** res);
HRESULT CreateCompositionSurfaceForSwapChain(IUnknown* swapChain, [out] ICompositionSurface ** result);
HRESULT CreateGraphicsDevice(IUnknown * renderingDevice, [out] ICompositionGraphicsDevice ** result);
};
[uuid(26f496a0-7f38-45fb-88f7-faaabe67dd59)]
interface ISwapChainInterop : IUnknown
{
HRESULT SetSwapChain(IUnknown * swapChain);
};
/*
[uuid(2C9DB356-E70D-4642-8298-BC4AA5B4865C)]
interface ICompositionCapabilitiesInteropFactory : IInspectable
{
HRESULT GetForWindow(IntPtr hwnd, [out] ICompositionCapabilities ** result);
}*/
[uuid(29E691FA-4567-4DCA-B319-D0F207EB6807)]
interface ICompositorDesktopInterop : IUnknown
{
HRESULT CreateDesktopWindowTarget(HWND hwndTarget, BOOL isTopmost, [out] IDesktopWindowTarget ** result);
HRESULT EnsureOnThread(DWORD threadId);
};
[uuid(35DBF59E-E3F9-45B0-81E7-FE75F4145DC9)]
interface IDesktopWindowTargetInterop : IUnknown
{
HRESULT GetHWnd([out] IntPtr* value);
};
[uuid(37642806-F421-4FD0-9F82-23AE7C776182)]
interface IDesktopWindowContentBridgeInterop : IUnknown
{
HRESULT Initialize(ICompositor* compositor, HWND parentHwnd);
HRESULT GetHWnd([out] IntPtr* value);
HRESULT GetAppliedScaleFactor([out] float* value);
};
[uuid(FB22C6E1-80A2-4667-9936-DBEAF6EEFE95)]
interface ICompositionGraphicsDevice : IInspectable
{
HRESULT CreateDrawingSurface([in] SIZE sizePixels, [in] DirectXPixelFormat pixelFormat,
[in] DirectXAlphaMode alphaMode, [out] [retval] ICompositionDrawingSurface** result);
HRESULT AddRenderingDeviceReplaced(void* handler, void* token);
HRESULT RemoveRenderingDeviceReplaced([in] int token);
}
[uuid(1527540D-42C7-47A6-A408-668F79A90DFB)]
interface ICompositionSurface : IInspectable
{
}
[uuid(6329D6CA-3366-490E-9DB3-25312929AC51)]
interface IDesktopWindowTarget : IInspectable
{
[propget] HRESULT IsTopmost([out] [retval] int* value);
}
[uuid(A166C300-FAD0-4D11-9E67-E433162FF49E)]
interface ICompositionDrawingSurface : IInspectable
{
[propget] HRESULT GetAlphaMode([out] [retval] DirectXAlphaMode* value);
[propget] HRESULT GetPixelFormat([out] [retval] DirectXPixelFormat* value);
[propget] HRESULT GetSize([out] [retval] POINT* value);
}
enum CompositionBitmapInterpolationMode
{
NearestNeighbor,
Linear,
MagLinearMinLinearMipLinear,
MagLinearMinLinearMipNearest,
MagLinearMinNearestMipLinear,
MagLinearMinNearestMipNearest,
MagNearestMinLinearMipLinear,
MagNearestMinLinearMipNearest,
MagNearestMinNearestMipLinear,
MagNearestMinNearestMipNearest,
}
enum CompositionStretch
{
None,
Fill,
Uniform,
UniformToFill,
}
[uuid(AD016D79-1E4C-4C0D-9C29-83338C87C162)]
interface ICompositionSurfaceBrush : IInspectable
{
[propget] HRESULT BitmapInterpolationMode([out] [retval] CompositionBitmapInterpolationMode* value);
[propput] HRESULT BitmapInterpolationMode([in] CompositionBitmapInterpolationMode value);
[propget] HRESULT HorizontalAlignmentRatio([out] [retval] FLOAT* value);
[propput] HRESULT HorizontalAlignmentRatio([in] FLOAT value);
[propget] HRESULT Stretch([out] [retval] CompositionStretch* value);
[propput] HRESULT Stretch([in] CompositionStretch value);
[propget] HRESULT Surface([out] [retval] ICompositionSurface** value);
[propput] HRESULT Surface([in] ICompositionSurface* value);
[propget] HRESULT VerticalAlignmentRatio([out] [retval] FLOAT* value);
[propput] HRESULT VerticalAlignmentRatio([in] FLOAT value);
}
[uuid(AB0D7608-30C0-40E9-B568-B60A6BD1FB46)]
interface ICompositionBrush : IInspectable
{
}
enum CompositionBackfaceVisibility
{
Inherit,
Visible,
Hidden
}
enum CompositionBorderMode
{
Inherit,
Soft,
Hard
}
enum CompositionCompositeMode
{
Inherit,
SourceOver,
DestinationInvert,
MinBlend,
}
[uuid(117E202D-A859-4C89-873B-C2AA566788E3)]
interface IVisual : IInspectable
{
[propget] HRESULT AnchorPoint([out] [retval] Vector2* value);
[propput] HRESULT AnchorPoint([in] Vector2 value);
[propget] HRESULT BackfaceVisibility([out] [retval] CompositionBackfaceVisibility* value);
[propput] HRESULT BackfaceVisibility([in] CompositionBackfaceVisibility value);
[propget] HRESULT BorderMode([out] [retval] CompositionBorderMode* value);
[propput] HRESULT BorderMode([in] CompositionBorderMode value);
[propget] HRESULT CenterPoint([out] [retval] Vector3* value);
[propput] HRESULT CenterPoint([in] Vector3 value);
[propget] HRESULT Clip([out] [retval]void** value);
[propput] HRESULT Clip([in] void* value);
[propget] HRESULT CompositeMode([out] [retval] CompositionCompositeMode* value);
[propput] HRESULT CompositeMode([in] CompositionCompositeMode value);
[propget] HRESULT IsVisible([out] [retval] boolean* value);
[propput] HRESULT IsVisible([in] boolean value);
[propget] HRESULT Offset([out] [retval] Vector3* value);
[propput] HRESULT Offset([in] Vector3 value);
[propget] HRESULT Opacity([out] [retval] FLOAT* value);
[propput] HRESULT Opacity([in] FLOAT value);
[propget] HRESULT Orientation([out] [retval] Quaternion* value);
[propput] HRESULT Orientation([in] Quaternion value);
[propget] HRESULT Parent([out] [retval] IContainerVisual** value);
[propget] HRESULT RotationAngle([out] [retval] FLOAT* value);
[propput] HRESULT RotationAngle([in] FLOAT value);
[propget] HRESULT RotationAngleInDegrees([out] [retval] FLOAT* value);
[propput] HRESULT RotationAngleInDegrees([in] FLOAT value);
[propget] HRESULT RotationAxis([out] [retval] Vector3* value);
[propput] HRESULT RotationAxis([in] Vector3 value);
[propget] HRESULT Scale([out] [retval] Vector3* value);
[propput] HRESULT Scale([in] Vector3 value);
[propget] HRESULT Size([out] [retval] Vector2* value);
[propput] HRESULT Size([in] Vector2 value);
[propget] HRESULT TransformMatrix([out] [retval] Matrix4x4* value);
[propput] HRESULT TransformMatrix([in] Matrix4x4 value);
}
[uuid(3052B611-56C3-4C3E-8BF3-F6E1AD473F06)]
interface IVisual2 : IInspectable
{
[propget] HRESULT ParentForTransform([out] [retval] IVisual** value);
[propput] HRESULT ParentForTransform([in] IVisual* value);
[propget] HRESULT RelativeOffsetAdjustment([out] [retval] Vector3* value);
[propput] HRESULT RelativeOffsetAdjustment([in] Vector3 value);
[propget] HRESULT RelativeSizeAdjustment([out] [retval] Vector2* value);
[propput] HRESULT RelativeSizeAdjustment([in] Vector2 value);
}
[uuid(02F6BC74-ED20-4773-AFE6-D49B4A93DB32)]
interface IContainerVisual : IInspectable
{
[propget] HRESULT GetChildren([out] [retval] IVisualCollection** value);
}
[uuid(8B745505-FD3E-4A98-84A8-E949468C6BCB)]
interface IVisualCollection : IInspectable
{
[propget] HRESULT GetCount([out] [retval] INT32* value);
HRESULT InsertAbove([in] IVisual* newChild, [in] IVisual* sibling);
HRESULT InsertAtBottom([in] IVisual* newChild);
HRESULT InsertAtTop([in] IVisual* newChild);
HRESULT InsertBelow([in] IVisual* newChild, [in] IVisual* sibling);
HRESULT Remove([in] IVisual* child);
HRESULT RemoveAll();
}
[uuid(A1BEA8BA-D726-4663-8129-6B5E7927FFA6)]
interface ICompositionTarget : IInspectable
{
[propget] HRESULT Root([out] [retval] IVisual** value);
[propput] HRESULT Root([in] IVisual* value);
}
[uuid(CB51C0CE-8FE6-4636-B202-861FAA07D8F3)]
interface IGraphicsEffect : IInspectable
{
[propget] HRESULT Name([out] [retval] HSTRING* name);
[propput] HRESULT Name([in] HSTRING name);
}
[uuid(2D8F9DDC-4339-4EB9-9216-F9DEB75658A2)]
interface IGraphicsEffectSource : IInspectable
{
}
enum GRAPHICS_EFFECT_PROPERTY_MAPPING
{
GRAPHICS_EFFECT_PROPERTY_MAPPING_UNKNOWN,
GRAPHICS_EFFECT_PROPERTY_MAPPING_DIRECT,
GRAPHICS_EFFECT_PROPERTY_MAPPING_VECTORX,
GRAPHICS_EFFECT_PROPERTY_MAPPING_VECTORY,
GRAPHICS_EFFECT_PROPERTY_MAPPING_VECTORZ,
GRAPHICS_EFFECT_PROPERTY_MAPPING_VECTORW,
GRAPHICS_EFFECT_PROPERTY_MAPPING_RECT_TO_VECTOR4,
GRAPHICS_EFFECT_PROPERTY_MAPPING_RADIANS_TO_DEGREES,
GRAPHICS_EFFECT_PROPERTY_MAPPING_COLORMATRIX_ALPHA_MODE,
GRAPHICS_EFFECT_PROPERTY_MAPPING_COLOR_TO_VECTOR3,
GRAPHICS_EFFECT_PROPERTY_MAPPING_COLOR_TO_VECTOR4
}
[uuid(2FC57384-A068-44D7-A331-30982FCF7177)]
interface IGraphicsEffectD2D1Interop : IUnknown
{
HRESULT GetEffectId([out] Guid* id);
HRESULT GetNamedPropertyMapping(IntPtr name, uint* index, GRAPHICS_EFFECT_PROPERTY_MAPPING* mapping);
HRESULT GetPropertyCount([out] uint* count);
HRESULT GetProperty(uint index, [out]IPropertyValue** value);
HRESULT GetSource(uint index, [out, retval] IGraphicsEffectSource** source);
HRESULT GetSourceCount([retval]uint *count);
};
[uuid(858AB13A-3292-4E4E-B3BB-2B6C6544A6EE)]
interface ICompositionEffectSourceParameter : IInspectable
{
[propget] HRESULT Name([out] [retval] HSTRING* value);
}
[uuid(B3D9F276-ABA3-4724-ACF3-D0397464DB1C)]
interface ICompositionEffectSourceParameterFactory : IInspectable
{
HRESULT Create([in] HSTRING name, [out] [retval] ICompositionEffectSourceParameter** instance);
}
enum CompositionEffectFactoryLoadStatus
{
Success = 0,
EffectTooComplex = 1,
Pending = 2,
Other = -1
}
[uuid(BE5624AF-BA7E-4510-9850-41C0B4FF74DF)]
interface ICompositionEffectFactory : IInspectable
{
HRESULT CreateBrush([out] [retval] ICompositionEffectBrush** result);
[propget] HRESULT ExtendedError([out] [retval] int* value);
[propget] HRESULT LoadStatus([out] [retval] CompositionEffectFactoryLoadStatus* value);
}
[uuid(BF7F795E-83CC-44BF-A447-3E3C071789EC)]
interface ICompositionEffectBrush : IInspectable
{
HRESULT GetSourceParameter([in] HSTRING name, [out] [retval] ICompositionBrush** result);
HRESULT SetSourceParameter([in] HSTRING name, [in] ICompositionBrush* source);
}
[uuid(C5ACAE58-3898-499E-8D7F-224E91286A5D)]
interface ICompositionBackdropBrush : IInspectable
{
}
[uuid(2B264C5E-BF35-4831-8642-CF70C20FFF2F)]
interface ICompositionColorBrush : IInspectable
{
[propget] HRESULT Color([out] [retval] Color* value);
[propput] HRESULT Color([in] Color value);
}
[uuid(0D00DAD0-FB07-46FD-8C72-6280D1A3D1DD)]
interface ICompositionScopedBatch : IInspectable
{
[propget] HRESULT IsActive([out] [retval] boolean* value);
[propget] HRESULT IsEnded([out] [retval] boolean* value);
HRESULT End();
HRESULT Resume();
HRESULT Suspend();
[eventadd] HRESULT AddCompleted([in] void* handler, [out] [retval] int* token);
[eventremove] HRESULT RemoveCompleted([in] int token);
}
[uuid(48EA31AD-7FCD-4076-A79C-90CC4B852C9B)]
interface ICompositor5 : IInspectable
{
[propget] HRESULT GetComment([out] [retval] HSTRING* value);
[propput] HRESULT SetComment([in] HSTRING value);
[propget] HRESULT GetGlobalPlaybackRate([out] [retval] FLOAT* value);
[propput] HRESULT SetGlobalPlaybackRate([in] FLOAT value);
HRESULT CreateBounceScalarAnimation([out] [retval] void** result);
HRESULT CreateBounceVector2Animation([out] [retval] void** result);
HRESULT CreateBounceVector3Animation([out] [retval] void** result);
HRESULT CreateContainerShape([out] [retval] void** result);
HRESULT CreateEllipseGeometry([out] [retval] void** result);
HRESULT CreateLineGeometry([out] [retval] void** result);
[overload("CreatePathGeometry")] HRESULT CreatePathGeometry([out] [retval] void** result);
[overload("CreatePathGeometry")] HRESULT CreatePathGeometryWithPath([in] void* path, [out] [retval] void** result);
HRESULT CreatePathKeyFrameAnimation([out] [retval] void** result);
HRESULT CreateRectangleGeometry([out] [retval] void** result);
HRESULT CreateRoundedRectangleGeometry([out] [retval] void** result);
HRESULT CreateShapeVisual([out] [retval] void** result);
[overload("CreateSpriteShape")] HRESULT CreateSpriteShape([out] [retval] void** result);
[overload("CreateSpriteShape")] HRESULT CreateSpriteShapeWithGeometry([in] void* geometry, [out] [retval] void** result);
HRESULT CreateViewBox([out] [retval] void** result);
HRESULT RequestCommitAsync([out] [retval] IAsyncAction** operation);
}

21
src/Windows/Avalonia.Win32/WindowImpl.cs

@ -15,6 +15,8 @@ using Avalonia.Rendering;
using Avalonia.Win32.Input;
using Avalonia.Win32.Interop;
using Avalonia.Win32.OpenGl;
using Avalonia.Win32.WinRT;
using Avalonia.Win32.WinRT.Composition;
using static Avalonia.Win32.Interop.UnmanagedMethods;
namespace Avalonia.Win32
@ -107,7 +109,7 @@ namespace Avalonia.Win32
var glPlatform = AvaloniaLocator.Current.GetService<IPlatformOpenGlInterface>();
var compositionConnector = AvaloniaLocator.Current.GetService<CompositionConnector>();
var compositionConnector = AvaloniaLocator.Current.GetService<WinUICompositorConnection>();
_isUsingComposition = compositionConnector is { } &&
glPlatform is EglPlatformOpenGlInterface egl &&
@ -121,8 +123,8 @@ namespace Avalonia.Win32
{
if (_isUsingComposition)
{
var cgl = new CompositionEglGlPlatformSurface(glPlatform as EglPlatformOpenGlInterface, this);
_blurHost = cgl.AttachToCompositionTree(compositionConnector, _hwnd);
var cgl = new WinUiCompositedWindowSurface(compositionConnector, this);
_blurHost = cgl;
_gl = cgl;
@ -452,9 +454,14 @@ namespace Avalonia.Win32
if (customRendererFactory != null)
return customRendererFactory.Create(root, loop);
return Win32Platform.UseDeferredRendering ?
(IRenderer)new DeferredRenderer(root, loop, rendererLock: _rendererLock) :
new ImmediateRenderer(root);
return Win32Platform.UseDeferredRendering
? _isUsingComposition
? new DeferredRenderer(root, loop)
{
RenderOnlyOnRenderThread = true
}
: (IRenderer)new DeferredRenderer(root, loop, rendererLock: _rendererLock)
: new ImmediateRenderer(root);
}
public void Resize(Size value)
@ -489,6 +496,8 @@ namespace Avalonia.Win32
public void Dispose()
{
(_gl as IDisposable)?.Dispose();
if (_dropTarget != null)
{
OleContext.Current?.UnregisterDragDrop(Handle);

7
src/tools/MicroComGenerator/AstParser.cs

@ -13,7 +13,8 @@ namespace MicroComGenerator
while (!parser.Eof)
{
var attrs = ParseLocalAttributes(ref parser);
if (parser.TryConsume(";"))
continue;
if (parser.TryParseKeyword("enum"))
idl.Enums.Add(ParseEnum(attrs, ref parser));
else if (parser.TryParseKeyword("struct"))
@ -64,7 +65,7 @@ namespace MicroComGenerator
static AstAttributes ParseLocalAttributes(ref TokenParser parser)
{
var rv = new AstAttributes();
if (parser.TryConsume("["))
while (parser.TryConsume("["))
{
while (!parser.TryConsume("]") && !parser.Eof)
{
@ -78,7 +79,7 @@ namespace MicroComGenerator
if (parser.TryConsume(']'))
{
rv.Add(new AstAttributeNode(ident, null));
return rv;
break;
}
// No value, next attribute
else if (parser.TryConsume(','))

47
src/tools/MicroComGenerator/CSharpGen.InterfaceGen.cs

@ -21,7 +21,7 @@ namespace MicroComGenerator
{
public string Name;
public string NativeType;
public AstAttributes Attributes { get; set; }
public virtual StatementSyntax CreateFixed(StatementSyntax inner) => inner;
public virtual void PreMarshal(List<StatementSyntax> body)
@ -161,6 +161,13 @@ namespace MicroComGenerator
return type;
}
Arg ConvertArg(AstInterfaceMemberArgumentNode node)
{
var arg = ConvertArg(node.Name, node.Type);
arg.Attributes = node.Attributes.Clone();
return arg;
}
Arg ConvertArg(string name, AstTypeNode type)
{
type = new AstTypeNode { Name = ConvertNativeType(type.Name), PointerLevel = type.PointerLevel };
@ -190,12 +197,19 @@ namespace MicroComGenerator
List<StatementSyntax> vtblCtor, int num)
{
// Prepare method information
var args = member.Select(a => ConvertArg(a.Name, a.Type)).ToList();
if (member.Name == "GetRenderingDevice")
Console.WriteLine();
var args = member.Select(ConvertArg).ToList();
var returnArg = ConvertArg("__result", member.ReturnType);
bool isHresult = member.ReturnType.Name == "HRESULT";
bool isHresultLastArgumentReturn = isHresult
&& args.Count > 0
&& (args.Last().Name == "ppv" || args.Last().Name == "retOut" || args.Last().Name == "ret")
&& (args.Last().Name == "ppv"
|| args.Last().Name == "retOut"
|| args.Last().Name == "ret"
|| args.Last().Attributes.HasAttribute("out")
|| args.Last().Attributes.HasAttribute("retval")
)
&& ((member.Last().Type.PointerLevel > 0
&& !IsInterface(member.Last().Type))
|| member.Last().Type.PointerLevel == 2);
@ -334,16 +348,27 @@ namespace MicroComGenerator
BlockSyntax backBodyBlock = Block().AddStatements(backPreMarshal.ToArray()).AddStatements(backCallStatement);
var exceptions = new List<CatchClauseSyntax>()
{
CatchClause(
CatchDeclaration(ParseTypeName("System.Exception"), Identifier("__exception__")), null,
Block(
ParseStatement(
"Avalonia.MicroCom.MicroComRuntime.UnhandledException(__target, __exception__);"),
isHresult ? ParseStatement("return unchecked((int)0x80004005u);")
: isVoidReturn ? EmptyStatement() : ParseStatement("return default;")
))
};
if (isHresult)
exceptions.Insert(0, CatchClause(
CatchDeclaration(ParseTypeName("System.Runtime.InteropServices.COMException"),
Identifier("__com_exception__")),
null, Block(ParseStatement("return __com_exception__.ErrorCode;"))));
backBodyBlock = Block(
TryStatement(
SingletonList(CatchClause(
CatchDeclaration(ParseTypeName("System.Exception"), Identifier("__exception__")), null,
Block(
ParseStatement(
"Avalonia.MicroCom.MicroComRuntime.UnhandledException(__target, __exception__);"),
isHresult ? ParseStatement("return unchecked((int)0x80004005u);")
: isVoidReturn ? EmptyStatement() : ParseStatement("return default;")
))))
List(exceptions))
.WithBlock(Block(backBodyBlock))
);
if (isHresult)

9
src/tools/MicroComGenerator/CSharpGen.Utils.cs

@ -68,10 +68,11 @@ namespace MicroComGenerator
bool IsPropertyRewriteCandidate(MethodDeclarationSyntax method)
{
if(method.Identifier.Text.Contains("GetScaling"))
Console.WriteLine();
return (method.Identifier.Text.StartsWith("Get") &&
method.ParameterList.Parameters.Count == 0);
return
method.ReturnType.ToFullString() != "void"
&& method.Identifier.Text.StartsWith("Get")
&& method.ParameterList.Parameters.Count == 0;
}
TypeDeclarationSyntax RewriteMethodsToProperties<T>(T decl) where T : TypeDeclarationSyntax

30
src/tools/MicroComGenerator/CSharpGen.cs

@ -22,7 +22,11 @@ namespace MicroComGenerator
public CSharpGen(AstIdlNode idl)
{
_idl = idl.Clone();
new AstRewriter().VisitAst(_idl);
new AstRewriter(_idl.Attributes.Where(a => a.Name == "clr-map")
.Select(x => x.Value.Trim().Split(' '))
.ToDictionary(x => x[0], x => x[1])
).VisitAst(_idl);
_extraUsings = _idl.Attributes.Where(u => u.Name == "clr-using").Select(u => u.Value).ToList();
_namespace = _idl.GetAttribute("clr-namespace");
var visibilityString = _idl.GetAttribute("clr-access");
@ -37,6 +41,13 @@ namespace MicroComGenerator
class AstRewriter : AstVisitor
{
private readonly Dictionary<string, string> _typeMap = new Dictionary<string, string>();
public AstRewriter(Dictionary<string, string> typeMap)
{
_typeMap = typeMap;
}
void ConvertIntPtr(AstTypeNode type)
{
if (type.Name == "void" && type.PointerLevel > 0)
@ -60,6 +71,9 @@ namespace MicroComGenerator
type.PointerLevel++;
type.IsLink = false;
}
if (_typeMap.TryGetValue(type.Name, out var mapped))
type.Name = mapped;
base.VisitType(type);
}
@ -80,6 +94,10 @@ namespace MicroComGenerator
{
if (member.HasAttribute("intptr"))
ConvertIntPtr(member.ReturnType);
if (member.HasAttribute("propget") && !member.Name.StartsWith("Get"))
member.Name = "Get" + member.Name;
if (member.HasAttribute("propput") && !member.Name.StartsWith("Set"))
member.Name = "Set" + member.Name;
base.VisitInterfaceMember(member);
}
}
@ -103,7 +121,8 @@ namespace MicroComGenerator
NamespaceDeclarationSyntax GenerateEnums(NamespaceDeclarationSyntax ns)
{
return ns.AddMembers(_idl.Enums.Select(e =>
EnumDeclaration(e.Name)
{
var dec = EnumDeclaration(e.Name)
.WithModifiers(TokenList(Token(_visibility)))
.WithMembers(SeparatedList(e.Select(m =>
{
@ -111,8 +130,11 @@ namespace MicroComGenerator
if (m.Value != null)
return member.WithEqualsValue(EqualsValueClause(ParseExpression(m.Value)));
return member;
})))
).ToArray());
})));
if (e.HasAttribute("flags"))
dec = dec.AddAttribute("System.Flags");
return dec;
}).ToArray());
}
NamespaceDeclarationSyntax GenerateStructs(NamespaceDeclarationSyntax ns)

Loading…
Cancel
Save