From 92880f6d037de3a5e62f770a32bda4a33edc92bc Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 25 Jun 2020 17:32:02 -0300 Subject: [PATCH 01/75] force dx11 --- samples/ControlCatalog.NetCore/Program.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/samples/ControlCatalog.NetCore/Program.cs b/samples/ControlCatalog.NetCore/Program.cs index 5df8c1be64..06cf3e6b61 100644 --- a/samples/ControlCatalog.NetCore/Program.cs +++ b/samples/ControlCatalog.NetCore/Program.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Threading; using Avalonia; using Avalonia.Dialogs; +using Avalonia.OpenGL; using Avalonia.ReactiveUI; namespace ControlCatalog.NetCore @@ -65,6 +66,10 @@ namespace ControlCatalog.NetCore EnableMultitouch = true, AllowEglInitialization = true }) + .With(new AngleOptions + { + AllowedPlatformApis = new System.Collections.Generic.List { AngleOptions.PlatformApi.DirectX11} + }) .UseSkia() .UseReactiveUI() .UseManagedSystemDialogs() From 459e9db2fb04a05abbf830363db5fed73eed64c3 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 25 Jun 2020 17:35:43 -0300 Subject: [PATCH 02/75] add Composition interfaces. --- .../Avalonia.Win32/Avalonia.Win32.csproj | 1 + .../Composition/CompositionHost.cs | 145 ++++++++++++ .../Avalonia.Win32/Composition/D2DEffects.cs | 91 ++++++++ .../GRAPHICS_EFFECT_PROPERTY_MAPPING.cs | 18 ++ .../Composition/GaussianBlurEffect.cs | 79 +++++++ .../Composition/ICompositorDesktopInterop.cs | 14 ++ .../Composition/ICompositorDesktopInterop1.cs | 69 ++++++ .../Composition/ICompositorInterop.cs | 139 +++++++++++ .../Composition/IGraphicsEffectD2D1Interop.cs | 24 ++ .../IGraphicsEffectD2D1Interop1.cs | 217 ++++++++++++++++++ src/Windows/Avalonia.Win32/WindowImpl.cs | 2 + 11 files changed, 799 insertions(+) create mode 100644 src/Windows/Avalonia.Win32/Composition/CompositionHost.cs create mode 100644 src/Windows/Avalonia.Win32/Composition/D2DEffects.cs create mode 100644 src/Windows/Avalonia.Win32/Composition/GRAPHICS_EFFECT_PROPERTY_MAPPING.cs create mode 100644 src/Windows/Avalonia.Win32/Composition/GaussianBlurEffect.cs create mode 100644 src/Windows/Avalonia.Win32/Composition/ICompositorDesktopInterop.cs create mode 100644 src/Windows/Avalonia.Win32/Composition/ICompositorDesktopInterop1.cs create mode 100644 src/Windows/Avalonia.Win32/Composition/ICompositorInterop.cs create mode 100644 src/Windows/Avalonia.Win32/Composition/IGraphicsEffectD2D1Interop.cs create mode 100644 src/Windows/Avalonia.Win32/Composition/IGraphicsEffectD2D1Interop1.cs diff --git a/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj b/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj index 49700710e9..34f71daf52 100644 --- a/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj +++ b/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj @@ -7,6 +7,7 @@ + diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs new file mode 100644 index 0000000000..223c208829 --- /dev/null +++ b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs @@ -0,0 +1,145 @@ +using System; +using System.Runtime.InteropServices; +using Avalonia.OpenGL.Angle; +using Windows.UI.Composition; +using WinRT; + +namespace Avalonia.Win32 +{ + class CompositionHost + { + 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 CompositionHost Instance { get; } = new CompositionHost(); + + private Compositor _compositor; + private Windows.System.DispatcherQueueController _dispatcherQueueController; + private Windows.UI.Composition.Desktop.DesktopWindowTarget _target; + + private CompositionHost() + { + } + + public void AddElement(float size, float x, float y) + { + if (_target.Root != null) + { + var visuals = _target.Root.As().Children; + + var visual = _compositor.CreateSpriteVisual(); + + var element = _compositor.CreateSpriteVisual(); + var rand = new Random(); + + element.Brush = _compositor.CreateColorBrush(new Windows.UI.Color { A = 255, R = (byte)(rand.NextDouble() * 255), G = (byte)(rand.NextDouble() * 255), B = (byte)(rand.NextDouble() * 255) }); + element.Size = new System.Numerics.Vector2(size, size); + element.Offset = new System.Numerics.Vector3(x, y, 0.0f); + + var animation = _compositor.CreateVector3KeyFrameAnimation(); + var bottom = (float)600 - element.Size.Y; + animation.InsertKeyFrame(1, new System.Numerics.Vector3(element.Offset.X, bottom, 0)); + + animation.Duration = TimeSpan.FromSeconds(2); + animation.DelayTime = TimeSpan.FromSeconds(3); + element.StartAnimation("Offset", animation); + visuals.InsertAtTop(element); + + visuals.InsertAtTop(visual); + } + } + + public void Initialize(IntPtr hwnd) + { + EnsureDispatcherQueue(); + if (_dispatcherQueueController != null) + _compositor = new Windows.UI.Composition.Compositor(); + + CreateDesktopWindowTarget(hwnd); + CreateCompositionRoot(); + + var interop = _compositor.As(); + + var display = Win32GlManager.EglFeature.Display as AngleWin32EglDisplay; + + var gDevice = interop.CreateGraphicsDevice(display.GetDirect3DDevice()); + + gDevice.CreateDrawingSurface(new Windows.Foundation.Size(100,100), Windows.Graphics.DirectX.DirectXPixelFormat.B8G8R8A8UIntNormalized, Windows.Graphics.DirectX.DirectXAlphaMode.Premultiplied); + + } + + public void CreateBlur() + { + var effect = new GaussianBlurEffect(); + var effectFactory = _compositor.CreateEffectFactory(effect); + var blurBrush = effectFactory.CreateBrush(); + + var backDropBrush = _compositor.CreateBackdropBrush(); + + blurBrush.SetSourceParameter("backdrop", backDropBrush); + + var visual = _compositor.CreateSpriteVisual(); + + visual.RelativeSizeAdjustment = new System.Numerics.Vector2(1.0f, 1.0f); + visual.Brush = blurBrush; + + _target.Root = visual; + } + + void CreateCompositionRoot() + { + var root = _compositor.CreateContainerVisual(); + root.RelativeSizeAdjustment = new System.Numerics.Vector2(1.0f, 1.0f); + //root.Offset = new System.Numerics.Vector3(0, 0, 0); + _target.Root = root; + } + + void CreateDesktopWindowTarget(IntPtr window) + { + var interop = _compositor.As(); + + interop.CreateDesktopWindowTarget(window, false, out var windowTarget); + _target = Windows.UI.Composition.Desktop.DesktopWindowTarget.FromAbi(windowTarget); + } + + void EnsureDispatcherQueue() + { + if (_dispatcherQueueController == null) + { + DispatcherQueueOptions options = new DispatcherQueueOptions(); + options.apartmentType = DISPATCHERQUEUE_THREAD_APARTMENTTYPE.DQTAT_COM_STA; + 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); + } + } + } +} + diff --git a/src/Windows/Avalonia.Win32/Composition/D2DEffects.cs b/src/Windows/Avalonia.Win32/Composition/D2DEffects.cs new file mode 100644 index 0000000000..1c761ee082 --- /dev/null +++ b/src/Windows/Avalonia.Win32/Composition/D2DEffects.cs @@ -0,0 +1,91 @@ +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); + } +} + diff --git a/src/Windows/Avalonia.Win32/Composition/GRAPHICS_EFFECT_PROPERTY_MAPPING.cs b/src/Windows/Avalonia.Win32/Composition/GRAPHICS_EFFECT_PROPERTY_MAPPING.cs new file mode 100644 index 0000000000..f5d5fc4ad3 --- /dev/null +++ b/src/Windows/Avalonia.Win32/Composition/GRAPHICS_EFFECT_PROPERTY_MAPPING.cs @@ -0,0 +1,18 @@ +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 + }; +} + diff --git a/src/Windows/Avalonia.Win32/Composition/GaussianBlurEffect.cs b/src/Windows/Avalonia.Win32/Composition/GaussianBlurEffect.cs new file mode 100644 index 0000000000..19595e8977 --- /dev/null +++ b/src/Windows/Avalonia.Win32/Composition/GaussianBlurEffect.cs @@ -0,0 +1,79 @@ +using System; +using Windows.Graphics.Effects; +using Windows.Graphics.Effects.Interop; +using Windows.UI.Composition; + + +namespace Avalonia.Win32 +{ + class GaussianBlurEffect : IGraphicsEffect, IGraphicsEffectSource, global::Windows.Graphics.Effects.Interop.IGraphicsEffectD2D1Interop + { + 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 string Name { get; set; } + + public Guid EffectId => D2DEffects.CLSID_D2D1GaussianBlur; + + public uint PropertyCount => 3; + + public uint SourceCount => 1; + + public uint GetNamedPropertyMapping(string name, out GRAPHICS_EFFECT_PROPERTY_MAPPING mapping) + { + throw new NotImplementedException(); + } + + public object GetProperty(uint index) + { + switch ((D2D1GaussianBlurProp)index) + { + case D2D1GaussianBlurProp.D2D1_GAUSSIANBLUR_PROP_STANDARD_DEVIATION: + return 30.0f; + + case D2D1GaussianBlurProp.D2D1_GAUSSIANBLUR_PROP_OPTIMIZATION: + return (UInt32)D2D1_GAUSSIANBLUR_OPTIMIZATION.D2D1_GAUSSIANBLUR_OPTIMIZATION_SPEED; + + case D2D1GaussianBlurProp.D2D1_GAUSSIANBLUR_PROP_BORDER_MODE: + return (UInt32)D2D1_BORDER_MODE.D2D1_BORDER_MODE_HARD; + } + + return null; + } + + private IGraphicsEffectSource _source = new CompositionEffectSourceParameter("backdrop"); + + public IGraphicsEffectSource GetSource(uint index) + { + if (index == 0) + { + return _source; + } + else + { + return null; + } + } + } +} + diff --git a/src/Windows/Avalonia.Win32/Composition/ICompositorDesktopInterop.cs b/src/Windows/Avalonia.Win32/Composition/ICompositorDesktopInterop.cs new file mode 100644 index 0000000000..1d4cd3450f --- /dev/null +++ b/src/Windows/Avalonia.Win32/Composition/ICompositorDesktopInterop.cs @@ -0,0 +1,14 @@ +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); + } +} + diff --git a/src/Windows/Avalonia.Win32/Composition/ICompositorDesktopInterop1.cs b/src/Windows/Avalonia.Win32/Composition/ICompositorDesktopInterop1.cs new file mode 100644 index 0000000000..1c3f06d679 --- /dev/null +++ b/src/Windows/Avalonia.Win32/Composition/ICompositorDesktopInterop1.cs @@ -0,0 +1,69 @@ +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()); + 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(thisPtr).CreateDesktopWindowTarget(hwndTarget, isTopMost != 0, out desktopWindowTarget); + return 0; + } + catch (Exception ex) + { + desktopWindowTarget = IntPtr.Zero; + return Marshal.GetHRForException(ex); + } + } + } + internal static ObjectReference FromAbi(IntPtr thisPtr) => ObjectReference.FromAbi(thisPtr); + + public static implicit operator ICompositorDesktopInterop(IObjectReference obj) => (obj != null) ? new ICompositorDesktopInterop(obj) : null; + protected readonly ObjectReference _obj; + public IObjectReference ObjRef { get => _obj; } + public IntPtr ThisPtr => _obj.ThisPtr; + public ObjectReference AsInterface() => _obj.As(); + public A As() => _obj.AsType(); + public ICompositorDesktopInterop(IObjectReference obj) : this(obj.As()) { } + internal ICompositorDesktopInterop(ObjectReference 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)); + } + } +} + diff --git a/src/Windows/Avalonia.Win32/Composition/ICompositorInterop.cs b/src/Windows/Avalonia.Win32/Composition/ICompositorInterop.cs new file mode 100644 index 0000000000..d9b25e497e --- /dev/null +++ b/src/Windows/Avalonia.Win32/Composition/ICompositorInterop.cs @@ -0,0 +1,139 @@ +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()); + 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(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(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(thisPtr).CreateGraphicsDevice(renderingDevice).ThisPtr; + return 0; + } + catch (Exception ex) + { + graphicsDevice = IntPtr.Zero; + return Marshal.GetHRForException(ex); + } + } + } + internal static ObjectReference FromAbi(IntPtr thisPtr) => ObjectReference.FromAbi(thisPtr); + + public static implicit operator ICompositorInterop(IObjectReference obj) => (obj != null) ? new ICompositorInterop(obj) : null; + protected readonly ObjectReference _obj; + public IObjectReference ObjRef { get => _obj; } + public IntPtr ThisPtr => _obj.ThisPtr; + public ObjectReference AsInterface() => _obj.As(); + public A As() => _obj.AsType(); + public ICompositorInterop(IObjectReference obj) : this(obj.As()) { } + internal ICompositorInterop(ObjectReference 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); + } + } +} + diff --git a/src/Windows/Avalonia.Win32/Composition/IGraphicsEffectD2D1Interop.cs b/src/Windows/Avalonia.Win32/Composition/IGraphicsEffectD2D1Interop.cs new file mode 100644 index 0000000000..74d3939a98 --- /dev/null +++ b/src/Windows/Avalonia.Win32/Composition/IGraphicsEffectD2D1Interop.cs @@ -0,0 +1,24 @@ +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; } + } +} + diff --git a/src/Windows/Avalonia.Win32/Composition/IGraphicsEffectD2D1Interop1.cs b/src/Windows/Avalonia.Win32/Composition/IGraphicsEffectD2D1Interop1.cs new file mode 100644 index 0000000000..9d053c9e22 --- /dev/null +++ b/src/Windows/Avalonia.Win32/Composition/IGraphicsEffectD2D1Interop1.cs @@ -0,0 +1,217 @@ +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()); + Marshal.StructureToPtr(AbiToProjectionVftable, AbiToProjectionVftablePtr, false); + } + + private static int Do_Abi_Get_Effect_Id(IntPtr thisPtr, out Guid guid) + { + guid = default; + + try + { + guid = ComWrappersSupport.FindObject(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(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(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(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(thisPtr).GetSource(index); + + value = MarshalInterface.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(thisPtr).SourceCount; + } + catch (Exception ex) + { + return Marshal.GetHRForException(ex); + } + + return 0; + } + } + internal static ObjectReference FromAbi(IntPtr thisPtr) => ObjectReference.FromAbi(thisPtr); + + public static implicit operator IGraphicsEffectD2D1Interop(IObjectReference obj) => (obj != null) ? new IGraphicsEffectD2D1Interop(obj) : null; + protected readonly ObjectReference _obj; + public IObjectReference ObjRef { get => _obj; } + public IntPtr ThisPtr => _obj.ThisPtr; + + public ObjectReference AsInterface() => _obj.As(); + public A As() => _obj.AsType(); + public IGraphicsEffectD2D1Interop(IObjectReference obj) : this(obj.As()) { } + internal IGraphicsEffectD2D1Interop(ObjectReference 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(); + } + } +} + diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 36398eb810..ab07bdebb3 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -599,6 +599,8 @@ namespace Avalonia.Win32 _scaling = dpix / 96.0; } } + + CompositionHost.Instance.Initialize(_hwnd); } private void CreateDropTarget() From bd2b283ad7d4df2e2088916823b174e6d37d9d24 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 25 Jun 2020 18:30:43 -0300 Subject: [PATCH 03/75] add drawing surface interop.. --- .../Composition/CompositionHost.cs | 21 ++- .../ICompositionDrawingSurfaceInterop.cs | 135 ++++++++++++++++++ .../IGraphicsEffectD2D1Interop1.cs | 2 +- 3 files changed, 155 insertions(+), 3 deletions(-) create mode 100644 src/Windows/Avalonia.Win32/Composition/ICompositionDrawingSurfaceInterop.cs diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs index 223c208829..a94fd82e1a 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs @@ -2,6 +2,7 @@ using System.Runtime.InteropServices; using Avalonia.OpenGL.Angle; using Windows.UI.Composition; +using Windows.UI.Composition.Interop; using WinRT; namespace Avalonia.Win32 @@ -89,8 +90,24 @@ namespace Avalonia.Win32 var gDevice = interop.CreateGraphicsDevice(display.GetDirect3DDevice()); - gDevice.CreateDrawingSurface(new Windows.Foundation.Size(100,100), Windows.Graphics.DirectX.DirectXPixelFormat.B8G8R8A8UIntNormalized, Windows.Graphics.DirectX.DirectXAlphaMode.Premultiplied); - + var surface = gDevice.CreateDrawingSurface(new Windows.Foundation.Size(100,100), Windows.Graphics.DirectX.DirectXPixelFormat.B8G8R8A8UIntNormalized, Windows.Graphics.DirectX.DirectXAlphaMode.Premultiplied); + + var surfaceInterop = surface.As(); + + surfaceInterop.BeginDraw(new Windows.Foundation.Rect(0, 0, 100, 100), Guid.Parse("6f15aaf2-d208-4e89-9ab4-489535d34f9c"), out var texture, new Windows.Foundation.Point(0, 0)); + surfaceInterop.EndDraw(); + + var brush = _compositor.CreateSurfaceBrush(surface); + + var visual = _compositor.CreateSpriteVisual(); + + visual.RelativeSizeAdjustment = new System.Numerics.Vector2(1.0f, 1.0f); + visual.Brush = brush; + + _target.Root = visual; + + AddElement(100, 200, 200); + } public void CreateBlur() diff --git a/src/Windows/Avalonia.Win32/Composition/ICompositionDrawingSurfaceInterop.cs b/src/Windows/Avalonia.Win32/Composition/ICompositionDrawingSurfaceInterop.cs new file mode 100644 index 0000000000..fd9387b59e --- /dev/null +++ b/src/Windows/Avalonia.Win32/Composition/ICompositionDrawingSurfaceInterop.cs @@ -0,0 +1,135 @@ +using System; +using System.Runtime.InteropServices; +using Windows.Foundation; +using WinRT; + +namespace Windows.UI.Composition.Interop +{ + [WindowsRuntimeType] + [Guid("FD04E6E3-FE0C-4C3C-AB19-A07601A576EE")] + public interface ICompositionDrawingSurfaceInterop + { + void BeginDraw(Rect updateRect, Guid iid, out IntPtr updateObject, Point point); + + void EndDraw(); + + void Resize(Size 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; + + [Guid("FD04E6E3-FE0C-4C3C-AB19-A07601A576EE")] + internal class ICompositionDrawingSurfaceInterop : global::Windows.UI.Composition.Interop.ICompositionDrawingSurfaceInterop + + { + [Guid("FD04E6E3-FE0C-4C3C-AB19-A07601A576EE")] + public struct Vftbl + { + public delegate int _BeginDraw(IntPtr ThisPtr, Guid iid, out IntPtr updateObject, Point updateOffset); + public delegate int _EndDraw(IntPtr ThisPtr); + public delegate int _Resize(IntPtr ThisPtr, Size 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()); + Marshal.StructureToPtr(AbiToProjectionVftable, AbiToProjectionVftablePtr, false); + } + + private static int Do_Abi_BeginDraw(IntPtr ThisPtr, Guid iid, out IntPtr updateObject, 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, Size sizePixels) + { + return 0; + } + } + internal static ObjectReference FromAbi(IntPtr thisPtr) => ObjectReference.FromAbi(thisPtr); + + public static implicit operator ICompositionDrawingSurfaceInterop(IObjectReference obj) => (obj != null) ? new ICompositionDrawingSurfaceInterop(obj) : null; + protected readonly ObjectReference _obj; + public IObjectReference ObjRef { get => _obj; } + public IntPtr ThisPtr => _obj.ThisPtr; + public ObjectReference AsInterface() => _obj.As(); + public A As() => _obj.AsType(); + + public ICompositionDrawingSurfaceInterop(IObjectReference obj) : this(obj.As()) { } + internal ICompositionDrawingSurfaceInterop(ObjectReference obj) + { + _obj = obj; + } + + public void BeginDraw(Rect updateRect, Guid iid, out IntPtr updateObject, Point point) + { + Marshal.ThrowExceptionForHR(_obj.Vftbl.BeginDraw(ThisPtr, iid, out updateObject, point)); + } + + public void EndDraw() + { + Marshal.ThrowExceptionForHR(_obj.Vftbl.EndDraw(ThisPtr)); + } + + public void Resize(Size sizePixels) + { + throw new NotImplementedException(); + } + + 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(); + } + } +} + diff --git a/src/Windows/Avalonia.Win32/Composition/IGraphicsEffectD2D1Interop1.cs b/src/Windows/Avalonia.Win32/Composition/IGraphicsEffectD2D1Interop1.cs index 9d053c9e22..8466b05fb5 100644 --- a/src/Windows/Avalonia.Win32/Composition/IGraphicsEffectD2D1Interop1.cs +++ b/src/Windows/Avalonia.Win32/Composition/IGraphicsEffectD2D1Interop1.cs @@ -122,7 +122,7 @@ namespace ABI.Windows.Graphics.Effects.Interop value = default; try - { + { var source = ComWrappersSupport.FindObject(thisPtr).GetSource(index); value = MarshalInterface.FromManaged(source); From 016935a0235844b0d0b1fed42735c26f22060b72 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 26 Jun 2020 11:54:23 -0300 Subject: [PATCH 04/75] attached composition gl surface to composition tree. --- .../Composition/CompositionHost.cs | 67 +++++++++++++++++-- src/Windows/Avalonia.Win32/WindowImpl.cs | 11 +-- 2 files changed, 69 insertions(+), 9 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs index a94fd82e1a..961c3b0319 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs @@ -1,5 +1,6 @@ using System; using System.Runtime.InteropServices; +using Avalonia.OpenGL; using Avalonia.OpenGL.Angle; using Windows.UI.Composition; using Windows.UI.Composition.Interop; @@ -7,6 +8,61 @@ using WinRT; namespace Avalonia.Win32 { + public class CompositionEglGlPlatformSurface : EglGlPlatformSurfaceBase + { + private readonly EglDisplay _display; + private readonly EglContext _context; + private readonly IEglWindowGlPlatformSurfaceInfo _info; + private ICompositionDrawingSurfaceInterop _surfaceInterop; + + public CompositionEglGlPlatformSurface(EglContext context, IEglWindowGlPlatformSurfaceInfo info) : base() + { + _display = context.Display; + _context = context; + _info = info; + } + + public void AttachToCompositionTree(IntPtr hwnd) + { + _surfaceInterop = CompositionHost.Instance.Initialize(hwnd); + } + + public override IGlPlatformSurfaceRenderTarget CreateGlRenderTarget() + { + var glSurface = _display.CreateWindowSurface(_info.Handle); + return new CompositionRenderTarget(_display, _context, glSurface, _surfaceInterop, _info); + } + + class CompositionRenderTarget : EglPlatformSurfaceRenderTargetBase + { + private readonly EglDisplay _display; + private readonly EglContext _context; + private readonly EglSurface _glSurface; + private readonly IEglWindowGlPlatformSurfaceInfo _info; + private PixelSize _initialSize; + private readonly ICompositionDrawingSurfaceInterop _surfaceInterop; + + public CompositionRenderTarget(EglDisplay display, EglContext context, + EglSurface glSurface, ICompositionDrawingSurfaceInterop interopSurface, IEglWindowGlPlatformSurfaceInfo info) : base(display, context) + { + _display = display; + _context = context; + _glSurface = glSurface; + _surfaceInterop = interopSurface; + _info = info; + _initialSize = info.Size; + } + + public override void Dispose() => _glSurface.Dispose(); + + public override bool IsCorrupted => _initialSize != _info.Size; + + public override IGlPlatformSurfaceRenderingSession BeginDraw() => base.BeginDraw(_glSurface, _info); + } + } + + + class CompositionHost { internal enum DISPATCHERQUEUE_THREAD_APARTMENTTYPE @@ -75,7 +131,7 @@ namespace Avalonia.Win32 } } - public void Initialize(IntPtr hwnd) + public ICompositionDrawingSurfaceInterop Initialize(IntPtr hwnd) { EnsureDispatcherQueue(); if (_dispatcherQueueController != null) @@ -90,13 +146,13 @@ namespace Avalonia.Win32 var gDevice = interop.CreateGraphicsDevice(display.GetDirect3DDevice()); - var surface = gDevice.CreateDrawingSurface(new Windows.Foundation.Size(100,100), Windows.Graphics.DirectX.DirectXPixelFormat.B8G8R8A8UIntNormalized, Windows.Graphics.DirectX.DirectXAlphaMode.Premultiplied); + var surface = gDevice.CreateDrawingSurface(new Windows.Foundation.Size(100, 100), Windows.Graphics.DirectX.DirectXPixelFormat.B8G8R8A8UIntNormalized, Windows.Graphics.DirectX.DirectXAlphaMode.Premultiplied); var surfaceInterop = surface.As(); - surfaceInterop.BeginDraw(new Windows.Foundation.Rect(0, 0, 100, 100), Guid.Parse("6f15aaf2-d208-4e89-9ab4-489535d34f9c"), out var texture, new Windows.Foundation.Point(0, 0)); - surfaceInterop.EndDraw(); - + //surfaceInterop.BeginDraw(new Windows.Foundation.Rect(0, 0, 100, 100), Guid.Parse("6f15aaf2-d208-4e89-9ab4-489535d34f9c"), out var texture, new Windows.Foundation.Point(0, 0)); + //surfaceInterop.EndDraw(); + var brush = _compositor.CreateSurfaceBrush(surface); var visual = _compositor.CreateSpriteVisual(); @@ -108,6 +164,7 @@ namespace Avalonia.Win32 AddElement(100, 200, 200); + return surfaceInterop; } public void CreateBlur() diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index ab07bdebb3..03d2a328a6 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -100,7 +100,12 @@ namespace Avalonia.Win32 _framebuffer = new FramebufferManager(_hwnd); if (Win32GlManager.EglFeature != null) - _gl = new EglGlPlatformSurface(Win32GlManager.EglFeature.DeferredContext, this); + _gl = new CompositionEglGlPlatformSurface(Win32GlManager.EglFeature.DeferredContext, this); + + if (_gl is CompositionEglGlPlatformSurface cgl) + { + cgl.AttachToCompositionTree(_hwnd); + } Screen = new ScreenImpl(); @@ -598,9 +603,7 @@ namespace Avalonia.Win32 { _scaling = dpix / 96.0; } - } - - CompositionHost.Instance.Initialize(_hwnd); + } } private void CreateDropTarget() From 203e346a4d855dba07d64173844434fa31fdd1f1 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 26 Jun 2020 12:49:48 -0300 Subject: [PATCH 05/75] make begindraw work. --- .../Composition/CompositionHost.cs | 96 +++++++++++++++---- .../ICompositionDrawingSurfaceInterop.cs | 45 ++++++--- 2 files changed, 110 insertions(+), 31 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs index 961c3b0319..5f20d18faf 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs @@ -28,36 +28,99 @@ namespace Avalonia.Win32 } public override IGlPlatformSurfaceRenderTarget CreateGlRenderTarget() - { - var glSurface = _display.CreateWindowSurface(_info.Handle); - return new CompositionRenderTarget(_display, _context, glSurface, _surfaceInterop, _info); + { + return new CompositionRenderTarget(_display, _context, _surfaceInterop, _info); } class CompositionRenderTarget : EglPlatformSurfaceRenderTargetBase { private readonly EglDisplay _display; - private readonly EglContext _context; - private readonly EglSurface _glSurface; + private readonly EglContext _context; private readonly IEglWindowGlPlatformSurfaceInfo _info; private PixelSize _initialSize; private readonly ICompositionDrawingSurfaceInterop _surfaceInterop; - public CompositionRenderTarget(EglDisplay display, EglContext context, - EglSurface glSurface, ICompositionDrawingSurfaceInterop interopSurface, IEglWindowGlPlatformSurfaceInfo info) : base(display, context) + public CompositionRenderTarget(EglDisplay display, EglContext context, ICompositionDrawingSurfaceInterop interopSurface, IEglWindowGlPlatformSurfaceInfo info) : base(display, context) { _display = display; - _context = context; - _glSurface = glSurface; + _context = context; _surfaceInterop = interopSurface; _info = info; _initialSize = info.Size; } - public override void Dispose() => _glSurface.Dispose(); + public override bool IsCorrupted => _initialSize != _info.Size; + + public override IGlPlatformSurfaceRenderingSession BeginDraw() + { + var l = _context.Lock(); + + var iid = Guid.Parse("6f15aaf2-d208-4e89-9ab4-489535d34f9c"); + var updateRect = new RECT { right = _info.Size.Width, bottom = _info.Size.Height }; + var offset = new POINT(); + + _surfaceInterop.Resize(new POINT { X = _info.Size.Width, Y = _info.Size.Height }); + _surfaceInterop.BeginDraw( + ref updateRect, + ref iid, + out IntPtr texture, ref offset); - public override bool IsCorrupted => _initialSize != _info.Size; + var surface = (_display as AngleWin32EglDisplay).WrapDirect3D11Texture(texture); - public override IGlPlatformSurfaceRenderingSession BeginDraw() => base.BeginDraw(_glSurface, _info); + var restoreContext = _context.MakeCurrent(surface); + + return new Session(_display, _context, null, _info, l, restoreContext, () => { }, true); + } + + public override void Dispose() + { + _surfaceInterop.EndDraw(); + base.Dispose(); + } + } + + class Session : IGlPlatformSurfaceRenderingSession + { + private readonly EglContext _context; + private readonly EglSurface _glSurface; + private readonly EglGlPlatformSurfaceBase.IEglWindowGlPlatformSurfaceInfo _info; + private readonly EglDisplay _display; + private readonly IDisposable _lock; + private readonly IDisposable _restoreContext; + private readonly Action _onFinish; + + + public Session(EglDisplay display, EglContext context, + EglSurface glSurface, EglGlPlatformSurfaceBase.IEglWindowGlPlatformSurfaceInfo info, + IDisposable @lock, IDisposable restoreContext, Action onFinish, bool isYFlipped) + { + IsYFlipped = isYFlipped; + _context = context; + _display = display; + _glSurface = glSurface; + _info = info; + _lock = @lock; + _restoreContext = restoreContext; + _onFinish = onFinish; + } + + public void Dispose() + { + _context.GlInterface.Flush(); + _display.EglInterface.WaitGL(); + _glSurface?.SwapBuffers(); + _display.EglInterface.WaitClient(); + _display.EglInterface.WaitGL(); + _display.EglInterface.WaitNative(EglConsts.EGL_CORE_NATIVE_ENGINE); + _restoreContext.Dispose(); + _lock.Dispose(); + _onFinish?.Invoke(); + } + + public IGlContext Context => _context; + public PixelSize Size => _info.Size; + public double Scaling => _info.Scaling; + public bool IsYFlipped { get; } } } @@ -146,12 +209,11 @@ namespace Avalonia.Win32 var gDevice = interop.CreateGraphicsDevice(display.GetDirect3DDevice()); - var surface = gDevice.CreateDrawingSurface(new Windows.Foundation.Size(100, 100), Windows.Graphics.DirectX.DirectXPixelFormat.B8G8R8A8UIntNormalized, Windows.Graphics.DirectX.DirectXAlphaMode.Premultiplied); - - var surfaceInterop = surface.As(); + var surface = gDevice.CreateDrawingSurface(new Windows.Foundation.Size(100, 100), + Windows.Graphics.DirectX.DirectXPixelFormat.B8G8R8A8UIntNormalized, + Windows.Graphics.DirectX.DirectXAlphaMode.Premultiplied); - //surfaceInterop.BeginDraw(new Windows.Foundation.Rect(0, 0, 100, 100), Guid.Parse("6f15aaf2-d208-4e89-9ab4-489535d34f9c"), out var texture, new Windows.Foundation.Point(0, 0)); - //surfaceInterop.EndDraw(); + var surfaceInterop = surface.As(); var brush = _compositor.CreateSurfaceBrush(surface); diff --git a/src/Windows/Avalonia.Win32/Composition/ICompositionDrawingSurfaceInterop.cs b/src/Windows/Avalonia.Win32/Composition/ICompositionDrawingSurfaceInterop.cs index fd9387b59e..8fea5f293b 100644 --- a/src/Windows/Avalonia.Win32/Composition/ICompositionDrawingSurfaceInterop.cs +++ b/src/Windows/Avalonia.Win32/Composition/ICompositionDrawingSurfaceInterop.cs @@ -1,23 +1,39 @@ using System; using System.Runtime.InteropServices; -using Windows.Foundation; 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(Rect updateRect, Guid iid, out IntPtr updateObject, Point point); + void BeginDraw(ref RECT updateRect, ref Guid iid, out IntPtr updateObject, ref POINT point); void EndDraw(); - void Resize(Size sizePixels); + void Resize(POINT sizePixels); void ResumeDraw(); - void Scroll(Rect scrollRect, Rect clipRect, int offsetX, int offsetY); + void Scroll(RECT scrollRect, RECT clipRect, int offsetX, int offsetY); void SuspendDraw(); } @@ -28,6 +44,7 @@ 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 @@ -36,11 +53,11 @@ namespace ABI.Windows.UI.Composition.Interop [Guid("FD04E6E3-FE0C-4C3C-AB19-A07601A576EE")] public struct Vftbl { - public delegate int _BeginDraw(IntPtr ThisPtr, Guid iid, out IntPtr updateObject, Point updateOffset); + public delegate int _BeginDraw(IntPtr ThisPtr, ref RECT updateRect, ref Guid iid, out IntPtr updateObject, ref POINT updateOffset); public delegate int _EndDraw(IntPtr ThisPtr); - public delegate int _Resize(IntPtr ThisPtr, Size sizePixels); + 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 _Scroll(IntPtr ThisPtr, RECT scrollRect, RECT clipRect, int offsetX, int offsetY); public delegate int _SuspendDraw(IntPtr ThisPtr); internal global::WinRT.Interop.IUnknownVftbl IUnknownVftbl; @@ -70,7 +87,7 @@ namespace ABI.Windows.UI.Composition.Interop Marshal.StructureToPtr(AbiToProjectionVftable, AbiToProjectionVftablePtr, false); } - private static int Do_Abi_BeginDraw(IntPtr ThisPtr, Guid iid, out IntPtr updateObject, Point updateOffset) + private static int Do_Abi_BeginDraw(IntPtr ThisPtr, ref RECT updateRect, ref Guid iid, out IntPtr updateObject, ref POINT updateOffset) { updateObject = IntPtr.Zero; return 0; @@ -81,7 +98,7 @@ namespace ABI.Windows.UI.Composition.Interop return 0; } - private static int Do_Abi_Resize(IntPtr ThisPtr, Size sizePixels) + private static int Do_Abi_Resize(IntPtr ThisPtr, POINT sizePixels) { return 0; } @@ -101,9 +118,9 @@ namespace ABI.Windows.UI.Composition.Interop _obj = obj; } - public void BeginDraw(Rect updateRect, Guid iid, out IntPtr updateObject, Point point) + public void BeginDraw(ref RECT updateRect, ref Guid iid, out IntPtr updateObject, ref POINT point) { - Marshal.ThrowExceptionForHR(_obj.Vftbl.BeginDraw(ThisPtr, iid, out updateObject, point)); + Marshal.ThrowExceptionForHR(_obj.Vftbl.BeginDraw(ThisPtr, ref updateRect, ref iid, out updateObject, ref point)); } public void EndDraw() @@ -111,9 +128,9 @@ namespace ABI.Windows.UI.Composition.Interop Marshal.ThrowExceptionForHR(_obj.Vftbl.EndDraw(ThisPtr)); } - public void Resize(Size sizePixels) + public void Resize(POINT sizePixels) { - throw new NotImplementedException(); + Marshal.ThrowExceptionForHR(_obj.Vftbl.Resize(ThisPtr, sizePixels)); } public void ResumeDraw() @@ -121,7 +138,7 @@ namespace ABI.Windows.UI.Composition.Interop throw new NotImplementedException(); } - public void Scroll(Rect scrollRect, Rect clipRect, int offsetX, int offsetY) + public void Scroll(RECT scrollRect, RECT clipRect, int offsetX, int offsetY) { throw new NotImplementedException(); } From 6adb1d062475ec8679ef01048bba24902c2c95b8 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 26 Jun 2020 12:51:37 -0300 Subject: [PATCH 06/75] pass in wrapped surface to session. --- src/Windows/Avalonia.Win32/Composition/CompositionHost.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs index 5f20d18faf..02291d93ed 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs @@ -69,7 +69,7 @@ namespace Avalonia.Win32 var restoreContext = _context.MakeCurrent(surface); - return new Session(_display, _context, null, _info, l, restoreContext, () => { }, true); + return new Session(_display, _context, surface, _info, l, restoreContext, () => { }, true); } public override void Dispose() @@ -108,7 +108,7 @@ namespace Avalonia.Win32 { _context.GlInterface.Flush(); _display.EglInterface.WaitGL(); - _glSurface?.SwapBuffers(); + _glSurface.SwapBuffers(); _display.EglInterface.WaitClient(); _display.EglInterface.WaitGL(); _display.EglInterface.WaitNative(EglConsts.EGL_CORE_NATIVE_ENGINE); From f5dd50e8ea855a8e903af1e872648b60c5e7de52 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 26 Jun 2020 12:56:46 -0300 Subject: [PATCH 07/75] call enddraw. --- src/Windows/Avalonia.Win32/Composition/CompositionHost.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs index 02291d93ed..b82fbc7d1d 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs @@ -69,7 +69,7 @@ namespace Avalonia.Win32 var restoreContext = _context.MakeCurrent(surface); - return new Session(_display, _context, surface, _info, l, restoreContext, () => { }, true); + return new Session(_display, _context, surface, _info, l, restoreContext, () => { _surfaceInterop.EndDraw(); }, true); } public override void Dispose() From f0c2ff7394715407368979f5361f7746a032099e Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 26 Jun 2020 13:02:03 -0300 Subject: [PATCH 08/75] call base.BeginDraw we dont need our own session class. --- .../Composition/CompositionHost.cs | 52 +------------------ 1 file changed, 1 insertion(+), 51 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs index b82fbc7d1d..3837134643 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs @@ -69,58 +69,8 @@ namespace Avalonia.Win32 var restoreContext = _context.MakeCurrent(surface); - return new Session(_display, _context, surface, _info, l, restoreContext, () => { _surfaceInterop.EndDraw(); }, true); + return base.BeginDraw(surface, _info, () => { _surfaceInterop.EndDraw(); }, true); } - - public override void Dispose() - { - _surfaceInterop.EndDraw(); - base.Dispose(); - } - } - - class Session : IGlPlatformSurfaceRenderingSession - { - private readonly EglContext _context; - private readonly EglSurface _glSurface; - private readonly EglGlPlatformSurfaceBase.IEglWindowGlPlatformSurfaceInfo _info; - private readonly EglDisplay _display; - private readonly IDisposable _lock; - private readonly IDisposable _restoreContext; - private readonly Action _onFinish; - - - public Session(EglDisplay display, EglContext context, - EglSurface glSurface, EglGlPlatformSurfaceBase.IEglWindowGlPlatformSurfaceInfo info, - IDisposable @lock, IDisposable restoreContext, Action onFinish, bool isYFlipped) - { - IsYFlipped = isYFlipped; - _context = context; - _display = display; - _glSurface = glSurface; - _info = info; - _lock = @lock; - _restoreContext = restoreContext; - _onFinish = onFinish; - } - - public void Dispose() - { - _context.GlInterface.Flush(); - _display.EglInterface.WaitGL(); - _glSurface.SwapBuffers(); - _display.EglInterface.WaitClient(); - _display.EglInterface.WaitGL(); - _display.EglInterface.WaitNative(EglConsts.EGL_CORE_NATIVE_ENGINE); - _restoreContext.Dispose(); - _lock.Dispose(); - _onFinish?.Invoke(); - } - - public IGlContext Context => _context; - public PixelSize Size => _info.Size; - public double Scaling => _info.Scaling; - public bool IsYFlipped { get; } } } From 53f3bc6e7fe84fc0fb3bf9e5f11fd327664ff9ca Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 26 Jun 2020 13:25:24 -0300 Subject: [PATCH 09/75] working rendering. --- .../Composition/CompositionHost.cs | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs index 3837134643..d4bbb67a3b 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs @@ -28,14 +28,14 @@ namespace Avalonia.Win32 } public override IGlPlatformSurfaceRenderTarget CreateGlRenderTarget() - { + { return new CompositionRenderTarget(_display, _context, _surfaceInterop, _info); } class CompositionRenderTarget : EglPlatformSurfaceRenderTargetBase { private readonly EglDisplay _display; - private readonly EglContext _context; + private readonly EglContext _context; private readonly IEglWindowGlPlatformSurfaceInfo _info; private PixelSize _initialSize; private readonly ICompositionDrawingSurfaceInterop _surfaceInterop; @@ -43,7 +43,7 @@ namespace Avalonia.Win32 public CompositionRenderTarget(EglDisplay display, EglContext context, ICompositionDrawingSurfaceInterop interopSurface, IEglWindowGlPlatformSurfaceInfo info) : base(display, context) { _display = display; - _context = context; + _context = context; _surfaceInterop = interopSurface; _info = info; _initialSize = info.Size; @@ -53,8 +53,6 @@ namespace Avalonia.Win32 public override IGlPlatformSurfaceRenderingSession BeginDraw() { - var l = _context.Lock(); - var iid = Guid.Parse("6f15aaf2-d208-4e89-9ab4-489535d34f9c"); var updateRect = new RECT { right = _info.Size.Width, bottom = _info.Size.Height }; var offset = new POINT(); @@ -67,8 +65,6 @@ namespace Avalonia.Win32 var surface = (_display as AngleWin32EglDisplay).WrapDirect3D11Texture(texture); - var restoreContext = _context.MakeCurrent(surface); - return base.BeginDraw(surface, _info, () => { _surfaceInterop.EndDraw(); }, true); } } @@ -159,11 +155,11 @@ namespace Avalonia.Win32 var gDevice = interop.CreateGraphicsDevice(display.GetDirect3DDevice()); - var surface = gDevice.CreateDrawingSurface(new Windows.Foundation.Size(100, 100), - Windows.Graphics.DirectX.DirectXPixelFormat.B8G8R8A8UIntNormalized, + var surface = gDevice.CreateDrawingSurface(new Windows.Foundation.Size(100, 100), + Windows.Graphics.DirectX.DirectXPixelFormat.B8G8R8A8UIntNormalized, Windows.Graphics.DirectX.DirectXAlphaMode.Premultiplied); - var surfaceInterop = surface.As(); + var surfaceInterop = surface.As(); var brush = _compositor.CreateSurfaceBrush(surface); @@ -174,7 +170,7 @@ namespace Avalonia.Win32 _target.Root = visual; - AddElement(100, 200, 200); + //CreateBlur(); return surfaceInterop; } From e53dfc0d360cb1c34706ae81b54bda7aed65b4c2 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 26 Jun 2020 14:02:51 -0300 Subject: [PATCH 10/75] add blur and avalonia surface visual ontop of blur. --- samples/ControlCatalog/MainWindow.xaml | 3 ++- .../Avalonia.Win32/Composition/CompositionHost.cs | 11 +++++++---- .../Avalonia.Win32/Interop/UnmanagedMethods.cs | 1 + src/Windows/Avalonia.Win32/WindowImpl.cs | 4 ++++ 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/samples/ControlCatalog/MainWindow.xaml b/samples/ControlCatalog/MainWindow.xaml index 76422bc130..c34e392d40 100644 --- a/samples/ControlCatalog/MainWindow.xaml +++ b/samples/ControlCatalog/MainWindow.xaml @@ -7,7 +7,8 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:vm="clr-namespace:ControlCatalog.ViewModels" xmlns:v="clr-namespace:ControlCatalog.Views" - x:Class="ControlCatalog.MainWindow" WindowState="{Binding WindowState, Mode=TwoWay}" Background="{DynamicResource SystemControlPageBackgroundAltHighBrush}"> + TransparencyLevelHint="Transparent" + x:Class="ControlCatalog.MainWindow" WindowState="{Binding WindowState, Mode=TwoWay}" Background="{x:Null}"> diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs index d4bbb67a3b..874bdaaf69 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs @@ -155,7 +155,7 @@ namespace Avalonia.Win32 var gDevice = interop.CreateGraphicsDevice(display.GetDirect3DDevice()); - var surface = gDevice.CreateDrawingSurface(new Windows.Foundation.Size(100, 100), + var surface = gDevice.CreateDrawingSurface(new Windows.Foundation.Size(0, 0), Windows.Graphics.DirectX.DirectXPixelFormat.B8G8R8A8UIntNormalized, Windows.Graphics.DirectX.DirectXAlphaMode.Premultiplied); @@ -167,10 +167,13 @@ namespace Avalonia.Win32 visual.RelativeSizeAdjustment = new System.Numerics.Vector2(1.0f, 1.0f); visual.Brush = brush; + //_target.Root = visual; - _target.Root = visual; + CreateBlur(); + + var visuals = _target.Root.As().Children; - //CreateBlur(); + visuals.InsertAtTop(visual); return surfaceInterop; } @@ -196,7 +199,7 @@ namespace Avalonia.Win32 void CreateCompositionRoot() { var root = _compositor.CreateContainerVisual(); - root.RelativeSizeAdjustment = new System.Numerics.Vector2(1.0f, 1.0f); + root.RelativeSizeAdjustment = new System.Numerics.Vector2(1.0f, 1.0f); //root.Offset = new System.Numerics.Vector3(0, 0, 0); _target.Root = root; } diff --git a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs index b3b38db1ab..bef65a06d8 100644 --- a/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs +++ b/src/Windows/Avalonia.Win32/Interop/UnmanagedMethods.cs @@ -465,6 +465,7 @@ namespace Avalonia.Win32.Interop WS_VSCROLL = 0x200000, WS_EX_DLGMODALFRAME = 0x00000001, WS_EX_NOPARENTNOTIFY = 0x00000004, + WS_EX_NOREDIRECTIONBITMAP = 0x00200000, WS_EX_TOPMOST = 0x00000008, WS_EX_ACCEPTFILES = 0x00000010, WS_EX_TRANSPARENT = 0x00000020, diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 03d2a328a6..fdde128800 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -106,6 +106,10 @@ namespace Avalonia.Win32 { cgl.AttachToCompositionTree(_hwnd); } + else + { + CompositionHost.Instance.Initialize(_hwnd); + } Screen = new ScreenImpl(); From 1f9e395fabb55234e452cdfe94562774e950e61a Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 26 Jun 2020 14:53:05 -0300 Subject: [PATCH 11/75] hack to clear window context, and only call interopsurface.resize when size actually changes. --- .../Composition/CompositionHost.cs | 33 +++++++++++++++++-- .../Composition/GaussianBlurEffect.cs | 2 +- src/Windows/Avalonia.Win32/WindowImpl.cs | 2 ++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs index 874bdaaf69..fd76e4a523 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs @@ -51,13 +51,42 @@ namespace Avalonia.Win32 public override bool IsCorrupted => _initialSize != _info.Size; + bool _firstRun = true; + POINT lastSize; public override IGlPlatformSurfaceRenderingSession BeginDraw() { + if (_firstRun) + { + _firstRun = false; + var windowSurface = new EglGlPlatformSurface(Win32GlManager.EglFeature.DeferredContext, _info); + + using (var target = windowSurface.CreateGlRenderTarget()) + { + using (var session = target.BeginDraw()) + { + using (session.Context.MakeCurrent()) + { + var gl = _context.GlInterface; + gl.Viewport(0, 0, _info.Size.Width, _info.Size.Height); + gl.ClearStencil(0); + gl.ClearColor(0, 0, 0, 0); + gl.Clear(GlConsts.GL_COLOR_BUFFER_BIT | GlConsts.GL_DEPTH_BUFFER_BIT); + gl.Flush(); + } + } + } + } + + var iid = Guid.Parse("6f15aaf2-d208-4e89-9ab4-489535d34f9c"); var updateRect = new RECT { right = _info.Size.Width, bottom = _info.Size.Height }; var offset = new POINT(); - _surfaceInterop.Resize(new POINT { X = _info.Size.Width, Y = _info.Size.Height }); + if (lastSize.X != _info.Size.Width || lastSize.Y != _info.Size.Height) + { + lastSize = new POINT { X = _info.Size.Width, Y = _info.Size.Height }; + _surfaceInterop.Resize(lastSize); + } _surfaceInterop.BeginDraw( ref updateRect, ref iid, @@ -65,7 +94,7 @@ namespace Avalonia.Win32 var surface = (_display as AngleWin32EglDisplay).WrapDirect3D11Texture(texture); - return base.BeginDraw(surface, _info, () => { _surfaceInterop.EndDraw(); }, true); + return base.BeginDraw(surface, _info, () => { _surfaceInterop.EndDraw(); Marshal.Release(texture); surface.Dispose(); }, true); } } } diff --git a/src/Windows/Avalonia.Win32/Composition/GaussianBlurEffect.cs b/src/Windows/Avalonia.Win32/Composition/GaussianBlurEffect.cs index 19595e8977..4e1be3af1a 100644 --- a/src/Windows/Avalonia.Win32/Composition/GaussianBlurEffect.cs +++ b/src/Windows/Avalonia.Win32/Composition/GaussianBlurEffect.cs @@ -52,7 +52,7 @@ namespace Avalonia.Win32 return 30.0f; case D2D1GaussianBlurProp.D2D1_GAUSSIANBLUR_PROP_OPTIMIZATION: - return (UInt32)D2D1_GAUSSIANBLUR_OPTIMIZATION.D2D1_GAUSSIANBLUR_OPTIMIZATION_SPEED; + return (UInt32)D2D1_GAUSSIANBLUR_OPTIMIZATION.D2D1_GAUSSIANBLUR_OPTIMIZATION_BALANCED; case D2D1GaussianBlurProp.D2D1_GAUSSIANBLUR_PROP_BORDER_MODE: return (UInt32)D2D1_BORDER_MODE.D2D1_BORDER_MODE_HARD; diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index fdde128800..151a998673 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -100,7 +100,9 @@ namespace Avalonia.Win32 _framebuffer = new FramebufferManager(_hwnd); if (Win32GlManager.EglFeature != null) + { _gl = new CompositionEglGlPlatformSurface(Win32GlManager.EglFeature.DeferredContext, this); + } if (_gl is CompositionEglGlPlatformSurface cgl) { From 372f8e3938088ed882f006e32e1d7b083149a145 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 26 Jun 2020 15:29:35 -0300 Subject: [PATCH 12/75] 1 graphics device, 1 surface and visual tree per window. --- .../Composition/CompositionHost.cs | 49 +++++++++---------- src/Windows/Avalonia.Win32/WindowImpl.cs | 2 +- 2 files changed, 24 insertions(+), 27 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs index fd76e4a523..1735b22035 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs @@ -24,7 +24,7 @@ namespace Avalonia.Win32 public void AttachToCompositionTree(IntPtr hwnd) { - _surfaceInterop = CompositionHost.Instance.Initialize(hwnd); + _surfaceInterop = CompositionHost.Instance.InitialiseWindowCompositionTree(hwnd); } public override IGlPlatformSurfaceRenderTarget CreateGlRenderTarget() @@ -47,6 +47,8 @@ namespace Avalonia.Win32 _surfaceInterop = interopSurface; _info = info; _initialSize = info.Size; + lastSize = new POINT { X = _info.Size.Width, Y = _info.Size.Height }; + _surfaceInterop.Resize(lastSize); } public override bool IsCorrupted => _initialSize != _info.Size; @@ -85,7 +87,7 @@ namespace Avalonia.Win32 if (lastSize.X != _info.Size.Width || lastSize.Y != _info.Size.Height) { lastSize = new POINT { X = _info.Size.Width, Y = _info.Size.Height }; - _surfaceInterop.Resize(lastSize); + // _surfaceInterop.Resize(lastSize); } _surfaceInterop.BeginDraw( ref updateRect, @@ -135,17 +137,18 @@ namespace Avalonia.Win32 private Compositor _compositor; private Windows.System.DispatcherQueueController _dispatcherQueueController; - private Windows.UI.Composition.Desktop.DesktopWindowTarget _target; + private CompositionGraphicsDevice _graphicsDevice; private CompositionHost() { + Initialize(); } - public void AddElement(float size, float x, float y) + public void AddElement(CompositionTarget target, float size, float x, float y) { - if (_target.Root != null) + if (target.Root != null) { - var visuals = _target.Root.As().Children; + var visuals = target.Root.As().Children; var visual = _compositor.CreateSpriteVisual(); @@ -169,22 +172,24 @@ namespace Avalonia.Win32 } } - public ICompositionDrawingSurfaceInterop Initialize(IntPtr hwnd) + private void Initialize() { EnsureDispatcherQueue(); if (_dispatcherQueueController != null) _compositor = new Windows.UI.Composition.Compositor(); - CreateDesktopWindowTarget(hwnd); - CreateCompositionRoot(); - var interop = _compositor.As(); var display = Win32GlManager.EglFeature.Display as AngleWin32EglDisplay; - var gDevice = interop.CreateGraphicsDevice(display.GetDirect3DDevice()); + _graphicsDevice = interop.CreateGraphicsDevice(display.GetDirect3DDevice()); + } + + public ICompositionDrawingSurfaceInterop InitialiseWindowCompositionTree(IntPtr hwnd) + { + var target = CreateDesktopWindowTarget(hwnd); - var surface = gDevice.CreateDrawingSurface(new Windows.Foundation.Size(0, 0), + var surface = _graphicsDevice.CreateDrawingSurface(new Windows.Foundation.Size(0, 0), Windows.Graphics.DirectX.DirectXPixelFormat.B8G8R8A8UIntNormalized, Windows.Graphics.DirectX.DirectXAlphaMode.Premultiplied); @@ -198,16 +203,16 @@ namespace Avalonia.Win32 visual.Brush = brush; //_target.Root = visual; - CreateBlur(); + target.Root = CreateBlur(); - var visuals = _target.Root.As().Children; + var visuals = target.Root.As().Children; visuals.InsertAtTop(visual); return surfaceInterop; } - public void CreateBlur() + public SpriteVisual CreateBlur() { var effect = new GaussianBlurEffect(); var effectFactory = _compositor.CreateEffectFactory(effect); @@ -222,23 +227,15 @@ namespace Avalonia.Win32 visual.RelativeSizeAdjustment = new System.Numerics.Vector2(1.0f, 1.0f); visual.Brush = blurBrush; - _target.Root = visual; - } - - void CreateCompositionRoot() - { - var root = _compositor.CreateContainerVisual(); - root.RelativeSizeAdjustment = new System.Numerics.Vector2(1.0f, 1.0f); - //root.Offset = new System.Numerics.Vector3(0, 0, 0); - _target.Root = root; + return visual; } - void CreateDesktopWindowTarget(IntPtr window) + CompositionTarget CreateDesktopWindowTarget(IntPtr window) { var interop = _compositor.As(); interop.CreateDesktopWindowTarget(window, false, out var windowTarget); - _target = Windows.UI.Composition.Desktop.DesktopWindowTarget.FromAbi(windowTarget); + return Windows.UI.Composition.Desktop.DesktopWindowTarget.FromAbi(windowTarget); } void EnsureDispatcherQueue() diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 151a998673..bcccdf4810 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -110,7 +110,7 @@ namespace Avalonia.Win32 } else { - CompositionHost.Instance.Initialize(_hwnd); + CompositionHost.Instance.InitialiseWindowCompositionTree(_hwnd); } Screen = new ScreenImpl(); From bcf502e1ca158db751519a8c69819a8aa983030a Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 11 Sep 2020 03:41:52 -0700 Subject: [PATCH 13/75] texture offsets --- .../ControlCatalog.NetCore/Properties/launchSettings.json | 8 ++++++++ src/Avalonia.OpenGL/Angle/AngleEglInterface.cs | 8 ++++---- src/Avalonia.OpenGL/Angle/AngleWin32EglDisplay.cs | 4 ++-- src/Avalonia.OpenGL/EglConsts.cs | 4 ++++ src/Windows/Avalonia.Win32/Composition/CompositionHost.cs | 2 +- 5 files changed, 19 insertions(+), 7 deletions(-) create mode 100644 samples/ControlCatalog.NetCore/Properties/launchSettings.json diff --git a/samples/ControlCatalog.NetCore/Properties/launchSettings.json b/samples/ControlCatalog.NetCore/Properties/launchSettings.json new file mode 100644 index 0000000000..cd8a2c824b --- /dev/null +++ b/samples/ControlCatalog.NetCore/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "ControlCatalog.NetCore": { + "commandName": "Project", + "nativeDebugging": true + } + } +} \ No newline at end of file diff --git a/src/Avalonia.OpenGL/Angle/AngleEglInterface.cs b/src/Avalonia.OpenGL/Angle/AngleEglInterface.cs index 375b93c27c..ef0ddf65b6 100644 --- a/src/Avalonia.OpenGL/Angle/AngleEglInterface.cs +++ b/src/Avalonia.OpenGL/Angle/AngleEglInterface.cs @@ -7,8 +7,8 @@ namespace Avalonia.OpenGL.Angle { public class AngleEglInterface : EglInterface { - [DllImport("libegl.dll", CharSet = CharSet.Ansi)] - static extern IntPtr eglGetProcAddress(string proc); + [DllImport("libglesv2.dll", CharSet = CharSet.Ansi)] + static extern IntPtr EGL_GetProcAddress(string proc); public AngleEglInterface() : base(LoadAngle()) { @@ -20,10 +20,10 @@ namespace Avalonia.OpenGL.Angle if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) throw new PlatformNotSupportedException(); { - var disp = eglGetProcAddress("eglGetPlatformDisplayEXT"); + var disp = EGL_GetProcAddress("eglGetPlatformDisplayEXT"); if (disp == IntPtr.Zero) throw new OpenGlException("libegl.dll doesn't have eglGetPlatformDisplayEXT entry point"); - return eglGetProcAddress; + return EGL_GetProcAddress; } } diff --git a/src/Avalonia.OpenGL/Angle/AngleWin32EglDisplay.cs b/src/Avalonia.OpenGL/Angle/AngleWin32EglDisplay.cs index 1a42ed90c2..af10211f15 100644 --- a/src/Avalonia.OpenGL/Angle/AngleWin32EglDisplay.cs +++ b/src/Avalonia.OpenGL/Angle/AngleWin32EglDisplay.cs @@ -78,11 +78,11 @@ namespace Avalonia.OpenGL.Angle return d3dDeviceHandle; } - public EglSurface WrapDirect3D11Texture(IntPtr handle) + public EglSurface WrapDirect3D11Texture(IntPtr handle, int offsetX, int offsetY) { if (PlatformApi != AngleOptions.PlatformApi.DirectX11) throw new InvalidOperationException("Current platform API is " + PlatformApi); - return CreatePBufferFromClientBuffer(EGL_D3D_TEXTURE_ANGLE, handle, new[] { EGL_NONE, EGL_NONE }); + return CreatePBufferFromClientBuffer(EGL_D3D_TEXTURE_ANGLE, handle, new[] { EGL_TEXTURE_OFFSET_X_ANGLE, offsetX, EGL_TEXTURE_OFFSET_Y_ANGLE, offsetY, EGL_NONE, EGL_NONE }); } } } diff --git a/src/Avalonia.OpenGL/EglConsts.cs b/src/Avalonia.OpenGL/EglConsts.cs index 8e44004f2d..c644df97bf 100644 --- a/src/Avalonia.OpenGL/EglConsts.cs +++ b/src/Avalonia.OpenGL/EglConsts.cs @@ -205,5 +205,9 @@ namespace Avalonia.OpenGL public const int EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE = 0x3200; public const int EGL_D3D_TEXTURE_ANGLE = 0x33A3; + + + public const int EGL_TEXTURE_OFFSET_X_ANGLE = 0x3490; + public const int EGL_TEXTURE_OFFSET_Y_ANGLE = 0x3491; } } diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs index 1735b22035..afd5ff4e39 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs @@ -94,7 +94,7 @@ namespace Avalonia.Win32 ref iid, out IntPtr texture, ref offset); - var surface = (_display as AngleWin32EglDisplay).WrapDirect3D11Texture(texture); + var surface = (_display as AngleWin32EglDisplay).WrapDirect3D11Texture(texture, offset.X, offset.Y); return base.BeginDraw(surface, _info, () => { _surfaceInterop.EndDraw(); Marshal.Release(texture); surface.Dispose(); }, true); } From e6cf04d4e1eb6f2955cf495a65c125ceb391111d Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 11 Sep 2020 03:58:34 -0700 Subject: [PATCH 14/75] update egl properties for wrapped texture. --- src/Avalonia.OpenGL/Angle/AngleWin32EglDisplay.cs | 4 ++-- src/Avalonia.OpenGL/EglConsts.cs | 2 ++ src/Windows/Avalonia.Win32/Composition/CompositionHost.cs | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Avalonia.OpenGL/Angle/AngleWin32EglDisplay.cs b/src/Avalonia.OpenGL/Angle/AngleWin32EglDisplay.cs index af10211f15..3b254d401a 100644 --- a/src/Avalonia.OpenGL/Angle/AngleWin32EglDisplay.cs +++ b/src/Avalonia.OpenGL/Angle/AngleWin32EglDisplay.cs @@ -78,11 +78,11 @@ namespace Avalonia.OpenGL.Angle return d3dDeviceHandle; } - public EglSurface WrapDirect3D11Texture(IntPtr handle, int offsetX, int offsetY) + public EglSurface WrapDirect3D11Texture(IntPtr handle, int offsetX, int offsetY, int width, int height) { if (PlatformApi != AngleOptions.PlatformApi.DirectX11) throw new InvalidOperationException("Current platform API is " + PlatformApi); - return CreatePBufferFromClientBuffer(EGL_D3D_TEXTURE_ANGLE, handle, new[] { EGL_TEXTURE_OFFSET_X_ANGLE, offsetX, EGL_TEXTURE_OFFSET_Y_ANGLE, offsetY, EGL_NONE, EGL_NONE }); + return CreatePBufferFromClientBuffer(EGL_D3D_TEXTURE_ANGLE, handle, new[] { EGL_WIDTH, width, EGL_HEIGHT, height, EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE, EGL_TRUE, EGL_TEXTURE_OFFSET_X_ANGLE, offsetX, EGL_TEXTURE_OFFSET_Y_ANGLE, offsetY, EGL_NONE }); } } } diff --git a/src/Avalonia.OpenGL/EglConsts.cs b/src/Avalonia.OpenGL/EglConsts.cs index c644df97bf..5910e32ee1 100644 --- a/src/Avalonia.OpenGL/EglConsts.cs +++ b/src/Avalonia.OpenGL/EglConsts.cs @@ -209,5 +209,7 @@ namespace Avalonia.OpenGL public const int EGL_TEXTURE_OFFSET_X_ANGLE = 0x3490; public const int EGL_TEXTURE_OFFSET_Y_ANGLE = 0x3491; + + public const int EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE = 0x33A6; } } diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs index afd5ff4e39..427655adf1 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs @@ -87,14 +87,14 @@ namespace Avalonia.Win32 if (lastSize.X != _info.Size.Width || lastSize.Y != _info.Size.Height) { lastSize = new POINT { X = _info.Size.Width, Y = _info.Size.Height }; - // _surfaceInterop.Resize(lastSize); + _surfaceInterop.Resize(lastSize); } _surfaceInterop.BeginDraw( ref updateRect, ref iid, out IntPtr texture, ref offset); - var surface = (_display as AngleWin32EglDisplay).WrapDirect3D11Texture(texture, offset.X, offset.Y); + var surface = (_display as AngleWin32EglDisplay).WrapDirect3D11Texture(texture, offset.X, offset.Y, _info.Size.Width, _info.Size.Height); return base.BeginDraw(surface, _info, () => { _surfaceInterop.EndDraw(); Marshal.Release(texture); surface.Dispose(); }, true); } From b6667530a25ae46916d11c4f76df83a3b0b7ba04 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 11 Sep 2020 06:27:51 -0700 Subject: [PATCH 15/75] force ui thread rendering for now. --- src/Avalonia.OpenGL/Angle/AngleWin32EglDisplay.cs | 2 +- src/Windows/Avalonia.Win32/Win32Platform.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.OpenGL/Angle/AngleWin32EglDisplay.cs b/src/Avalonia.OpenGL/Angle/AngleWin32EglDisplay.cs index 3b254d401a..c1f0f376b1 100644 --- a/src/Avalonia.OpenGL/Angle/AngleWin32EglDisplay.cs +++ b/src/Avalonia.OpenGL/Angle/AngleWin32EglDisplay.cs @@ -82,7 +82,7 @@ namespace Avalonia.OpenGL.Angle { if (PlatformApi != AngleOptions.PlatformApi.DirectX11) throw new InvalidOperationException("Current platform API is " + PlatformApi); - return CreatePBufferFromClientBuffer(EGL_D3D_TEXTURE_ANGLE, handle, new[] { EGL_WIDTH, width, EGL_HEIGHT, height, EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE, EGL_TRUE, EGL_TEXTURE_OFFSET_X_ANGLE, offsetX, EGL_TEXTURE_OFFSET_Y_ANGLE, offsetY, EGL_NONE }); + return CreatePBufferFromClientBuffer(EGL_D3D_TEXTURE_ANGLE, handle, new[] { EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE, EGL_TRUE, EGL_TEXTURE_OFFSET_X_ANGLE, offsetX, EGL_TEXTURE_OFFSET_Y_ANGLE, offsetY, EGL_NONE }); } } } diff --git a/src/Windows/Avalonia.Win32/Win32Platform.cs b/src/Windows/Avalonia.Win32/Win32Platform.cs index af6058d197..8840dcacef 100644 --- a/src/Windows/Avalonia.Win32/Win32Platform.cs +++ b/src/Windows/Avalonia.Win32/Win32Platform.cs @@ -88,7 +88,7 @@ namespace Avalonia.Win32 .Bind().ToConstant(s_instance) .Bind().ToConstant(s_instance) .Bind().ToConstant(new RenderLoop()) - .Bind().ToConstant(new DefaultRenderTimer(60)) + .Bind().ToConstant(new UiThreadRenderTimer(60)) .Bind().ToSingleton() .Bind().ToConstant(s_instance) .Bind().ToSingleton() From 3e96718d90e2c8bad28ab4110a4464e4e418ada9 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 11 Sep 2020 07:13:55 -0700 Subject: [PATCH 16/75] simplify hack to clear window. --- .../Composition/CompositionHost.cs | 20 ++----------------- 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs index 427655adf1..b810ec45e0 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs @@ -64,18 +64,7 @@ namespace Avalonia.Win32 using (var target = windowSurface.CreateGlRenderTarget()) { - using (var session = target.BeginDraw()) - { - using (session.Context.MakeCurrent()) - { - var gl = _context.GlInterface; - gl.Viewport(0, 0, _info.Size.Width, _info.Size.Height); - gl.ClearStencil(0); - gl.ClearColor(0, 0, 0, 0); - gl.Clear(GlConsts.GL_COLOR_BUFFER_BIT | GlConsts.GL_DEPTH_BUFFER_BIT); - gl.Flush(); - } - } + target.BeginDraw().Dispose(); } } @@ -83,12 +72,7 @@ namespace Avalonia.Win32 var iid = Guid.Parse("6f15aaf2-d208-4e89-9ab4-489535d34f9c"); var updateRect = new RECT { right = _info.Size.Width, bottom = _info.Size.Height }; var offset = new POINT(); - - if (lastSize.X != _info.Size.Width || lastSize.Y != _info.Size.Height) - { - lastSize = new POINT { X = _info.Size.Width, Y = _info.Size.Height }; - _surfaceInterop.Resize(lastSize); - } + _surfaceInterop.BeginDraw( ref updateRect, ref iid, From 40f45115fbbe1e6a9dddc075ef5d926829e34768 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 11 Sep 2020 07:14:28 -0700 Subject: [PATCH 17/75] remove unnecessary calls. --- src/Skia/Avalonia.Skia/Gpu/OpenGl/GlRenderTarget.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Skia/Avalonia.Skia/Gpu/OpenGl/GlRenderTarget.cs b/src/Skia/Avalonia.Skia/Gpu/OpenGl/GlRenderTarget.cs index 081db5d26a..ce4c6ecb90 100644 --- a/src/Skia/Avalonia.Skia/Gpu/OpenGl/GlRenderTarget.cs +++ b/src/Skia/Avalonia.Skia/Gpu/OpenGl/GlRenderTarget.cs @@ -72,10 +72,6 @@ namespace Avalonia.Skia $"Can't create drawing context for surface with {size} size and {scaling} scaling"); } - gl.Viewport(0, 0, size.Width, size.Height); - gl.ClearStencil(0); - gl.ClearColor(0, 0, 0, 0); - gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); lock (_grContext) { _grContext.ResetContext(); @@ -88,6 +84,7 @@ namespace Avalonia.Skia SKColorType.Rgba8888); success = true; + return new GlGpuSession(_grContext, renderTarget, surface, glSession); } } From 3deae8dbff8e4734e96b1f6aed2791f0eb989ee1 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 11 Sep 2020 07:32:53 -0700 Subject: [PATCH 18/75] no redirection bitmap --- .../Avalonia.Win32/Composition/CompositionHost.cs | 13 ------------- src/Windows/Avalonia.Win32/WindowImpl.cs | 2 +- 2 files changed, 1 insertion(+), 14 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs index b810ec45e0..6d293a31eb 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs @@ -53,22 +53,9 @@ namespace Avalonia.Win32 public override bool IsCorrupted => _initialSize != _info.Size; - bool _firstRun = true; POINT lastSize; public override IGlPlatformSurfaceRenderingSession BeginDraw() { - if (_firstRun) - { - _firstRun = false; - var windowSurface = new EglGlPlatformSurface(Win32GlManager.EglFeature.DeferredContext, _info); - - using (var target = windowSurface.CreateGlRenderTarget()) - { - target.BeginDraw().Dispose(); - } - } - - var iid = Guid.Parse("6f15aaf2-d208-4e89-9ab4-489535d34f9c"); var updateRect = new RECT { right = _info.Size.Width, bottom = _info.Size.Height }; var offset = new POINT(); diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 25ae755990..3047f44a71 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -626,7 +626,7 @@ namespace Avalonia.Win32 protected virtual IntPtr CreateWindowOverride(ushort atom) { return CreateWindowEx( - 0, + (int)WindowStyles.WS_EX_NOREDIRECTIONBITMAP, // TODO this is only when using Win UI Comp. atom, null, (int)WindowStyles.WS_OVERLAPPEDWINDOW | (int) WindowStyles.WS_CLIPCHILDREN, From 2981cc470dc2258450c1b6dae80e405f1ab357a9 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 11 Sep 2020 08:46:12 -0700 Subject: [PATCH 19/75] use render thread. --- src/Windows/Avalonia.Win32/Win32Platform.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Windows/Avalonia.Win32/Win32Platform.cs b/src/Windows/Avalonia.Win32/Win32Platform.cs index 8840dcacef..af6058d197 100644 --- a/src/Windows/Avalonia.Win32/Win32Platform.cs +++ b/src/Windows/Avalonia.Win32/Win32Platform.cs @@ -88,7 +88,7 @@ namespace Avalonia.Win32 .Bind().ToConstant(s_instance) .Bind().ToConstant(s_instance) .Bind().ToConstant(new RenderLoop()) - .Bind().ToConstant(new UiThreadRenderTimer(60)) + .Bind().ToConstant(new DefaultRenderTimer(60)) .Bind().ToSingleton() .Bind().ToConstant(s_instance) .Bind().ToSingleton() From 62e2a2d2e64426ed69c0b97cf41ffbb6b386b7e6 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 11 Sep 2020 16:59:14 +0100 Subject: [PATCH 20/75] remove override directx api. --- samples/ControlCatalog.NetCore/Program.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/samples/ControlCatalog.NetCore/Program.cs b/samples/ControlCatalog.NetCore/Program.cs index 9fcf618614..142736a0bb 100644 --- a/samples/ControlCatalog.NetCore/Program.cs +++ b/samples/ControlCatalog.NetCore/Program.cs @@ -10,8 +10,6 @@ using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Headless; using Avalonia.LogicalTree; using Avalonia.Skia; -using Avalonia.Dialogs; -using Avalonia.OpenGL; using Avalonia.ReactiveUI; using Avalonia.Threading; using Avalonia.Dialogs; @@ -120,10 +118,6 @@ namespace ControlCatalog.NetCore EnableMultitouch = true, AllowEglInitialization = true }) - .With(new AngleOptions - { - AllowedPlatformApis = new System.Collections.Generic.List { AngleOptions.PlatformApi.DirectX11} - }) .UseSkia() .UseReactiveUI() .UseManagedSystemDialogs() From 758ddafad888f0791a6a0cd256b11ca97ac24971 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 11 Sep 2020 17:02:38 +0100 Subject: [PATCH 21/75] restore file. --- src/Avalonia.OpenGL/Angle/AngleEglInterface.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Avalonia.OpenGL/Angle/AngleEglInterface.cs b/src/Avalonia.OpenGL/Angle/AngleEglInterface.cs index ef0ddf65b6..375b93c27c 100644 --- a/src/Avalonia.OpenGL/Angle/AngleEglInterface.cs +++ b/src/Avalonia.OpenGL/Angle/AngleEglInterface.cs @@ -7,8 +7,8 @@ namespace Avalonia.OpenGL.Angle { public class AngleEglInterface : EglInterface { - [DllImport("libglesv2.dll", CharSet = CharSet.Ansi)] - static extern IntPtr EGL_GetProcAddress(string proc); + [DllImport("libegl.dll", CharSet = CharSet.Ansi)] + static extern IntPtr eglGetProcAddress(string proc); public AngleEglInterface() : base(LoadAngle()) { @@ -20,10 +20,10 @@ namespace Avalonia.OpenGL.Angle if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) throw new PlatformNotSupportedException(); { - var disp = EGL_GetProcAddress("eglGetPlatformDisplayEXT"); + var disp = eglGetProcAddress("eglGetPlatformDisplayEXT"); if (disp == IntPtr.Zero) throw new OpenGlException("libegl.dll doesn't have eglGetPlatformDisplayEXT entry point"); - return EGL_GetProcAddress; + return eglGetProcAddress; } } From e68ce5643e815210d0b8f8b622eed3aae30e74dd Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 11 Sep 2020 09:05:24 -0700 Subject: [PATCH 22/75] Revert "restore file." This reverts commit 758ddafad888f0791a6a0cd256b11ca97ac24971. --- src/Avalonia.OpenGL/Angle/AngleEglInterface.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Avalonia.OpenGL/Angle/AngleEglInterface.cs b/src/Avalonia.OpenGL/Angle/AngleEglInterface.cs index 375b93c27c..ef0ddf65b6 100644 --- a/src/Avalonia.OpenGL/Angle/AngleEglInterface.cs +++ b/src/Avalonia.OpenGL/Angle/AngleEglInterface.cs @@ -7,8 +7,8 @@ namespace Avalonia.OpenGL.Angle { public class AngleEglInterface : EglInterface { - [DllImport("libegl.dll", CharSet = CharSet.Ansi)] - static extern IntPtr eglGetProcAddress(string proc); + [DllImport("libglesv2.dll", CharSet = CharSet.Ansi)] + static extern IntPtr EGL_GetProcAddress(string proc); public AngleEglInterface() : base(LoadAngle()) { @@ -20,10 +20,10 @@ namespace Avalonia.OpenGL.Angle if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) throw new PlatformNotSupportedException(); { - var disp = eglGetProcAddress("eglGetPlatformDisplayEXT"); + var disp = EGL_GetProcAddress("eglGetPlatformDisplayEXT"); if (disp == IntPtr.Zero) throw new OpenGlException("libegl.dll doesn't have eglGetPlatformDisplayEXT entry point"); - return eglGetProcAddress; + return EGL_GetProcAddress; } } From f068fa02e989e55ac3d24c944a0aa66837480dad Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 11 Sep 2020 09:14:37 -0700 Subject: [PATCH 23/75] restore render timer. --- src/Windows/Avalonia.Win32/Win32Platform.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Windows/Avalonia.Win32/Win32Platform.cs b/src/Windows/Avalonia.Win32/Win32Platform.cs index af6058d197..8840dcacef 100644 --- a/src/Windows/Avalonia.Win32/Win32Platform.cs +++ b/src/Windows/Avalonia.Win32/Win32Platform.cs @@ -88,7 +88,7 @@ namespace Avalonia.Win32 .Bind().ToConstant(s_instance) .Bind().ToConstant(s_instance) .Bind().ToConstant(new RenderLoop()) - .Bind().ToConstant(new DefaultRenderTimer(60)) + .Bind().ToConstant(new UiThreadRenderTimer(60)) .Bind().ToSingleton() .Bind().ToConstant(s_instance) .Bind().ToSingleton() From 0de7f4d7e0c5141060038d4a7f1f55ab36c10e51 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Sat, 12 Sep 2020 11:24:21 -0700 Subject: [PATCH 24/75] pass egl_width / height. --- src/Avalonia.OpenGL/Angle/AngleWin32EglDisplay.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.OpenGL/Angle/AngleWin32EglDisplay.cs b/src/Avalonia.OpenGL/Angle/AngleWin32EglDisplay.cs index c1f0f376b1..3b254d401a 100644 --- a/src/Avalonia.OpenGL/Angle/AngleWin32EglDisplay.cs +++ b/src/Avalonia.OpenGL/Angle/AngleWin32EglDisplay.cs @@ -82,7 +82,7 @@ namespace Avalonia.OpenGL.Angle { if (PlatformApi != AngleOptions.PlatformApi.DirectX11) throw new InvalidOperationException("Current platform API is " + PlatformApi); - return CreatePBufferFromClientBuffer(EGL_D3D_TEXTURE_ANGLE, handle, new[] { EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE, EGL_TRUE, EGL_TEXTURE_OFFSET_X_ANGLE, offsetX, EGL_TEXTURE_OFFSET_Y_ANGLE, offsetY, EGL_NONE }); + return CreatePBufferFromClientBuffer(EGL_D3D_TEXTURE_ANGLE, handle, new[] { EGL_WIDTH, width, EGL_HEIGHT, height, EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE, EGL_TRUE, EGL_TEXTURE_OFFSET_X_ANGLE, offsetX, EGL_TEXTURE_OFFSET_Y_ANGLE, offsetY, EGL_NONE }); } } } From 75025a15c195cf91197674f78a368e9ee6ac3da0 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Sat, 12 Sep 2020 11:46:32 -0700 Subject: [PATCH 25/75] avalonia never resizes so use intptr for update rect. --- .../Avalonia.Win32/Composition/CompositionHost.cs | 7 +++---- .../Composition/ICompositionDrawingSurfaceInterop.cs | 12 ++++++------ 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs index 6d293a31eb..5d13109dda 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs @@ -39,6 +39,7 @@ namespace Avalonia.Win32 private readonly IEglWindowGlPlatformSurfaceInfo _info; private PixelSize _initialSize; private readonly ICompositionDrawingSurfaceInterop _surfaceInterop; + private static Guid s_Iid = Guid.Parse("6f15aaf2-d208-4e89-9ab4-489535d34f9c"); public CompositionRenderTarget(EglDisplay display, EglContext context, ICompositionDrawingSurfaceInterop interopSurface, IEglWindowGlPlatformSurfaceInfo info) : base(display, context) { @@ -56,13 +57,11 @@ namespace Avalonia.Win32 POINT lastSize; public override IGlPlatformSurfaceRenderingSession BeginDraw() { - var iid = Guid.Parse("6f15aaf2-d208-4e89-9ab4-489535d34f9c"); - var updateRect = new RECT { right = _info.Size.Width, bottom = _info.Size.Height }; var offset = new POINT(); _surfaceInterop.BeginDraw( - ref updateRect, - ref iid, + IntPtr.Zero, + ref s_Iid, out IntPtr texture, ref offset); var surface = (_display as AngleWin32EglDisplay).WrapDirect3D11Texture(texture, offset.X, offset.Y, _info.Size.Width, _info.Size.Height); diff --git a/src/Windows/Avalonia.Win32/Composition/ICompositionDrawingSurfaceInterop.cs b/src/Windows/Avalonia.Win32/Composition/ICompositionDrawingSurfaceInterop.cs index 8fea5f293b..2eac796376 100644 --- a/src/Windows/Avalonia.Win32/Composition/ICompositionDrawingSurfaceInterop.cs +++ b/src/Windows/Avalonia.Win32/Composition/ICompositionDrawingSurfaceInterop.cs @@ -25,7 +25,7 @@ namespace Windows.UI.Composition.Interop [Guid("FD04E6E3-FE0C-4C3C-AB19-A07601A576EE")] public interface ICompositionDrawingSurfaceInterop { - void BeginDraw(ref RECT updateRect, ref Guid iid, out IntPtr updateObject, ref POINT point); + void BeginDraw(IntPtr updateRect, ref Guid iid, out IntPtr updateObject, ref POINT point); void EndDraw(); @@ -51,9 +51,9 @@ namespace ABI.Windows.UI.Composition.Interop { [Guid("FD04E6E3-FE0C-4C3C-AB19-A07601A576EE")] - public struct Vftbl + public unsafe struct Vftbl { - public delegate int _BeginDraw(IntPtr ThisPtr, ref RECT updateRect, ref Guid iid, out IntPtr updateObject, ref POINT updateOffset); + 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); @@ -87,7 +87,7 @@ namespace ABI.Windows.UI.Composition.Interop Marshal.StructureToPtr(AbiToProjectionVftable, AbiToProjectionVftablePtr, false); } - private static int Do_Abi_BeginDraw(IntPtr ThisPtr, ref RECT updateRect, ref Guid iid, out IntPtr updateObject, ref POINT updateOffset) + private static int Do_Abi_BeginDraw(IntPtr ThisPtr, IntPtr updateRect, ref Guid iid, out IntPtr updateObject, ref POINT updateOffset) { updateObject = IntPtr.Zero; return 0; @@ -118,9 +118,9 @@ namespace ABI.Windows.UI.Composition.Interop _obj = obj; } - public void BeginDraw(ref RECT updateRect, ref Guid iid, out IntPtr updateObject, ref POINT point) + public void BeginDraw(IntPtr updateRect, ref Guid iid, out IntPtr updateObject, ref POINT point) { - Marshal.ThrowExceptionForHR(_obj.Vftbl.BeginDraw(ThisPtr, ref updateRect, ref iid, out updateObject, ref point)); + Marshal.ThrowExceptionForHR(_obj.Vftbl.BeginDraw(ThisPtr, updateRect, ref iid, out updateObject, ref point)); } public void EndDraw() From 688ba15b6a3c6b1010bb558cf8b224de589936b7 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 14 Sep 2020 01:53:54 -0700 Subject: [PATCH 26/75] seperate classes. --- .../CompositionEglGlPlatformSurface.cs | 75 +++++++++++++++++ .../Composition/CompositionHost.cs | 83 ++----------------- 2 files changed, 84 insertions(+), 74 deletions(-) create mode 100644 src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs b/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs new file mode 100644 index 0000000000..c5e99a4b5d --- /dev/null +++ b/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs @@ -0,0 +1,75 @@ +using System; +using System.Runtime.InteropServices; +using Avalonia.OpenGL; +using Avalonia.OpenGL.Angle; +using Windows.UI.Composition.Interop; + +namespace Avalonia.Win32 +{ + public class CompositionEglGlPlatformSurface : EglGlPlatformSurfaceBase + { + private readonly EglDisplay _display; + private readonly EglContext _context; + private readonly IEglWindowGlPlatformSurfaceInfo _info; + private ICompositionDrawingSurfaceInterop _surfaceInterop; + private Windows.UI.Composition.Visual _surface; + + public CompositionEglGlPlatformSurface(EglContext context, IEglWindowGlPlatformSurfaceInfo info) : base() + { + _display = context.Display; + _context = context; + _info = info; + } + + public void AttachToCompositionTree(IntPtr hwnd) + { + _surfaceInterop = CompositionHost.Instance.InitialiseWindowCompositionTree(hwnd, out _surface); + } + + public override IGlPlatformSurfaceRenderTarget CreateGlRenderTarget() + { + return new CompositionRenderTarget(_display, _context, _surface, _surfaceInterop, _info); + } + + class CompositionRenderTarget : EglPlatformSurfaceRenderTargetBase + { + private readonly EglDisplay _display; + private readonly IEglWindowGlPlatformSurfaceInfo _info; + private PixelSize _initialSize; + private readonly ICompositionDrawingSurfaceInterop _surfaceInterop; + private static Guid s_Iid = Guid.Parse("6f15aaf2-d208-4e89-9ab4-489535d34f9c"); + private Windows.UI.Composition.Visual _compositionVisual; + + public CompositionRenderTarget(EglDisplay display, + EglContext context, + Windows.UI.Composition.Visual compositionVisual, + ICompositionDrawingSurfaceInterop interopSurface, + IEglWindowGlPlatformSurfaceInfo info) + : base(display, context) + { + _display = display; + _surfaceInterop = interopSurface; + _info = info; + _initialSize = info.Size; + _compositionVisual = compositionVisual; + _surfaceInterop.Resize(new POINT { X = _info.Size.Width, Y = _info.Size.Height }); + } + + public override bool IsCorrupted => _initialSize != _info.Size; + public override IGlPlatformSurfaceRenderingSession BeginDraw() + { + var offset = new POINT(); + + _surfaceInterop.BeginDraw( + IntPtr.Zero, + ref s_Iid, + out IntPtr texture, ref offset); + + var surface = (_display as AngleWin32EglDisplay).WrapDirect3D11Texture(texture, offset.X, offset.Y, _info.Size.Width, _info.Size.Height); + + return base.BeginDraw(surface, _info, () => { _surfaceInterop.EndDraw(); Marshal.Release(texture); surface.Dispose(); _compositionVisual.Size = new System.Numerics.Vector2(_info.Size.Width, _info.Size.Height); }, true); + } + } + } +} + diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs index 5d13109dda..48656e1816 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs @@ -1,6 +1,5 @@ using System; using System.Runtime.InteropServices; -using Avalonia.OpenGL; using Avalonia.OpenGL.Angle; using Windows.UI.Composition; using Windows.UI.Composition.Interop; @@ -8,71 +7,6 @@ using WinRT; namespace Avalonia.Win32 { - public class CompositionEglGlPlatformSurface : EglGlPlatformSurfaceBase - { - private readonly EglDisplay _display; - private readonly EglContext _context; - private readonly IEglWindowGlPlatformSurfaceInfo _info; - private ICompositionDrawingSurfaceInterop _surfaceInterop; - - public CompositionEglGlPlatformSurface(EglContext context, IEglWindowGlPlatformSurfaceInfo info) : base() - { - _display = context.Display; - _context = context; - _info = info; - } - - public void AttachToCompositionTree(IntPtr hwnd) - { - _surfaceInterop = CompositionHost.Instance.InitialiseWindowCompositionTree(hwnd); - } - - public override IGlPlatformSurfaceRenderTarget CreateGlRenderTarget() - { - return new CompositionRenderTarget(_display, _context, _surfaceInterop, _info); - } - - class CompositionRenderTarget : EglPlatformSurfaceRenderTargetBase - { - private readonly EglDisplay _display; - private readonly EglContext _context; - private readonly IEglWindowGlPlatformSurfaceInfo _info; - private PixelSize _initialSize; - private readonly ICompositionDrawingSurfaceInterop _surfaceInterop; - private static Guid s_Iid = Guid.Parse("6f15aaf2-d208-4e89-9ab4-489535d34f9c"); - - public CompositionRenderTarget(EglDisplay display, EglContext context, ICompositionDrawingSurfaceInterop interopSurface, IEglWindowGlPlatformSurfaceInfo info) : base(display, context) - { - _display = display; - _context = context; - _surfaceInterop = interopSurface; - _info = info; - _initialSize = info.Size; - lastSize = new POINT { X = _info.Size.Width, Y = _info.Size.Height }; - _surfaceInterop.Resize(lastSize); - } - - public override bool IsCorrupted => _initialSize != _info.Size; - - POINT lastSize; - public override IGlPlatformSurfaceRenderingSession BeginDraw() - { - var offset = new POINT(); - - _surfaceInterop.BeginDraw( - IntPtr.Zero, - ref s_Iid, - out IntPtr texture, ref offset); - - var surface = (_display as AngleWin32EglDisplay).WrapDirect3D11Texture(texture, offset.X, offset.Y, _info.Size.Width, _info.Size.Height); - - return base.BeginDraw(surface, _info, () => { _surfaceInterop.EndDraw(); Marshal.Release(texture); surface.Dispose(); }, true); - } - } - } - - - class CompositionHost { internal enum DISPATCHERQUEUE_THREAD_APARTMENTTYPE @@ -155,7 +89,7 @@ namespace Avalonia.Win32 _graphicsDevice = interop.CreateGraphicsDevice(display.GetDirect3DDevice()); } - public ICompositionDrawingSurfaceInterop InitialiseWindowCompositionTree(IntPtr hwnd) + public ICompositionDrawingSurfaceInterop InitialiseWindowCompositionTree(IntPtr hwnd, out Windows.UI.Composition.Visual surfaceVisual) { var target = CreateDesktopWindowTarget(hwnd); @@ -163,22 +97,23 @@ namespace Avalonia.Win32 Windows.Graphics.DirectX.DirectXPixelFormat.B8G8R8A8UIntNormalized, Windows.Graphics.DirectX.DirectXAlphaMode.Premultiplied); - var surfaceInterop = surface.As(); + var surfaceInterop = surface.As(); var brush = _compositor.CreateSurfaceBrush(surface); - var visual = _compositor.CreateSpriteVisual(); - - visual.RelativeSizeAdjustment = new System.Numerics.Vector2(1.0f, 1.0f); + visual.Brush = brush; - //_target.Root = visual; - + visual.Offset = new System.Numerics.Vector3(0, 0, 0); target.Root = CreateBlur(); var visuals = target.Root.As().Children; visuals.InsertAtTop(visual); + visual.CompositeMode = CompositionCompositeMode.SourceOver; + + surfaceVisual = visual; + return surfaceInterop; } @@ -204,7 +139,7 @@ namespace Avalonia.Win32 { var interop = _compositor.As(); - interop.CreateDesktopWindowTarget(window, false, out var windowTarget); + interop.CreateDesktopWindowTarget(window, true, out var windowTarget); return Windows.UI.Composition.Desktop.DesktopWindowTarget.FromAbi(windowTarget); } From b0bc3f4ea8fd47237f946ad72e59da4d399a1568 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 14 Sep 2020 01:56:40 -0700 Subject: [PATCH 27/75] check for windows 10 to decide to use windows.ui.comp tree to render into. --- src/Windows/Avalonia.Win32/WindowImpl.cs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 3047f44a71..d964e490c0 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -104,17 +104,17 @@ namespace Avalonia.Win32 _framebuffer = new FramebufferManager(_hwnd); if (Win32GlManager.EglFeature != null) - { - _gl = new CompositionEglGlPlatformSurface(Win32GlManager.EglFeature.DeferredContext, this); - } - - if (_gl is CompositionEglGlPlatformSurface cgl) - { - cgl.AttachToCompositionTree(_hwnd); - } - else { - CompositionHost.Instance.InitialiseWindowCompositionTree(_hwnd); + if (Win32Platform.WindowsVersion.Major >= 10) + { + var cgl = new CompositionEglGlPlatformSurface(Win32GlManager.EglFeature.DeferredContext, this); + cgl.AttachToCompositionTree(_hwnd); + _gl = cgl; + } + else + { + _gl = new EglGlPlatformSurface(Win32GlManager.EglFeature.DeferredContext, this); + } } Screen = new ScreenImpl(); From 8913cea89ec85f4b4a24ea82c32ac70cbf603198 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 14 Sep 2020 01:57:00 -0700 Subject: [PATCH 28/75] code tidy. --- .../CompositionEglGlPlatformSurface.cs | 15 +++---- .../Composition/CompositionHost.cs | 42 ++++--------------- 2 files changed, 15 insertions(+), 42 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs b/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs index c5e99a4b5d..701070a6b5 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs @@ -27,7 +27,7 @@ namespace Avalonia.Win32 } public override IGlPlatformSurfaceRenderTarget CreateGlRenderTarget() - { + { return new CompositionRenderTarget(_display, _context, _surface, _surfaceInterop, _info); } @@ -40,11 +40,11 @@ namespace Avalonia.Win32 private static Guid s_Iid = Guid.Parse("6f15aaf2-d208-4e89-9ab4-489535d34f9c"); private Windows.UI.Composition.Visual _compositionVisual; - public CompositionRenderTarget(EglDisplay display, - EglContext context, - Windows.UI.Composition.Visual compositionVisual, - ICompositionDrawingSurfaceInterop interopSurface, - IEglWindowGlPlatformSurfaceInfo info) + public CompositionRenderTarget(EglDisplay display, + EglContext context, + Windows.UI.Composition.Visual compositionVisual, + ICompositionDrawingSurfaceInterop interopSurface, + IEglWindowGlPlatformSurfaceInfo info) : base(display, context) { _display = display; @@ -53,6 +53,7 @@ namespace Avalonia.Win32 _initialSize = info.Size; _compositionVisual = compositionVisual; _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 bool IsCorrupted => _initialSize != _info.Size; @@ -67,7 +68,7 @@ namespace Avalonia.Win32 var surface = (_display as AngleWin32EglDisplay).WrapDirect3D11Texture(texture, offset.X, offset.Y, _info.Size.Width, _info.Size.Height); - return base.BeginDraw(surface, _info, () => { _surfaceInterop.EndDraw(); Marshal.Release(texture); surface.Dispose(); _compositionVisual.Size = new System.Numerics.Vector2(_info.Size.Width, _info.Size.Height); }, true); + return base.BeginDraw(surface, _info, () => { _surfaceInterop.EndDraw(); Marshal.Release(texture); surface.Dispose(); }, true); } } } diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs index 48656e1816..8da205fdc6 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs @@ -48,41 +48,13 @@ namespace Avalonia.Win32 Initialize(); } - public void AddElement(CompositionTarget target, float size, float x, float y) - { - if (target.Root != null) - { - var visuals = target.Root.As().Children; - - var visual = _compositor.CreateSpriteVisual(); - - var element = _compositor.CreateSpriteVisual(); - var rand = new Random(); - - element.Brush = _compositor.CreateColorBrush(new Windows.UI.Color { A = 255, R = (byte)(rand.NextDouble() * 255), G = (byte)(rand.NextDouble() * 255), B = (byte)(rand.NextDouble() * 255) }); - element.Size = new System.Numerics.Vector2(size, size); - element.Offset = new System.Numerics.Vector3(x, y, 0.0f); - - var animation = _compositor.CreateVector3KeyFrameAnimation(); - var bottom = (float)600 - element.Size.Y; - animation.InsertKeyFrame(1, new System.Numerics.Vector3(element.Offset.X, bottom, 0)); - - animation.Duration = TimeSpan.FromSeconds(2); - animation.DelayTime = TimeSpan.FromSeconds(3); - element.StartAnimation("Offset", animation); - visuals.InsertAtTop(element); - - visuals.InsertAtTop(visual); - } - } - private void Initialize() { EnsureDispatcherQueue(); if (_dispatcherQueueController != null) - _compositor = new Windows.UI.Composition.Compositor(); + _compositor = new Compositor(); - var interop = _compositor.As(); + var interop = _compositor.As(); var display = Win32GlManager.EglFeature.Display as AngleWin32EglDisplay; @@ -91,19 +63,19 @@ namespace Avalonia.Win32 public ICompositionDrawingSurfaceInterop InitialiseWindowCompositionTree(IntPtr hwnd, out Windows.UI.Composition.Visual surfaceVisual) { - var target = CreateDesktopWindowTarget(hwnd); + 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(); + var surfaceInterop = surface.As(); var brush = _compositor.CreateSurfaceBrush(surface); var visual = _compositor.CreateSpriteVisual(); - + visual.Brush = brush; - visual.Offset = new System.Numerics.Vector3(0, 0, 0); + visual.Offset = new System.Numerics.Vector3(0, 0, 0); target.Root = CreateBlur(); var visuals = target.Root.As().Children; @@ -139,7 +111,7 @@ namespace Avalonia.Win32 { var interop = _compositor.As(); - interop.CreateDesktopWindowTarget(window, true, out var windowTarget); + interop.CreateDesktopWindowTarget(window, false, out var windowTarget); return Windows.UI.Composition.Desktop.DesktopWindowTarget.FromAbi(windowTarget); } From 0140d201a1d3ea1444f9397c35cba495e2a39283 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 14 Sep 2020 02:08:43 -0700 Subject: [PATCH 29/75] use render thread. --- src/Windows/Avalonia.Win32/Win32Platform.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Windows/Avalonia.Win32/Win32Platform.cs b/src/Windows/Avalonia.Win32/Win32Platform.cs index 8840dcacef..af6058d197 100644 --- a/src/Windows/Avalonia.Win32/Win32Platform.cs +++ b/src/Windows/Avalonia.Win32/Win32Platform.cs @@ -88,7 +88,7 @@ namespace Avalonia.Win32 .Bind().ToConstant(s_instance) .Bind().ToConstant(s_instance) .Bind().ToConstant(new RenderLoop()) - .Bind().ToConstant(new UiThreadRenderTimer(60)) + .Bind().ToConstant(new DefaultRenderTimer(60)) .Bind().ToSingleton() .Bind().ToConstant(s_instance) .Bind().ToSingleton() From 75bf2fcb67e7f63b53aec383c89ad5e18bb0c742 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 14 Sep 2020 02:19:29 -0700 Subject: [PATCH 30/75] remove usings. --- src/Avalonia.OpenGL/Angle/AngleEglInterface.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Avalonia.OpenGL/Angle/AngleEglInterface.cs b/src/Avalonia.OpenGL/Angle/AngleEglInterface.cs index b73053b52e..07890b260c 100644 --- a/src/Avalonia.OpenGL/Angle/AngleEglInterface.cs +++ b/src/Avalonia.OpenGL/Angle/AngleEglInterface.cs @@ -1,7 +1,5 @@ using System; using System.Runtime.InteropServices; -using Avalonia.Platform; -using Avalonia.Platform.Interop; namespace Avalonia.OpenGL.Angle { From 0b7f211b3a9a98449fc0e6a6c6efd4a911645739 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 14 Sep 2020 02:22:17 -0700 Subject: [PATCH 31/75] fix build error. --- src/Avalonia.OpenGL/Angle/AngleEglInterface.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.OpenGL/Angle/AngleEglInterface.cs b/src/Avalonia.OpenGL/Angle/AngleEglInterface.cs index 07890b260c..0067124c0b 100644 --- a/src/Avalonia.OpenGL/Angle/AngleEglInterface.cs +++ b/src/Avalonia.OpenGL/Angle/AngleEglInterface.cs @@ -24,7 +24,7 @@ namespace Avalonia.OpenGL.Angle throw new OpenGlException("libegl.dll doesn't have eglGetPlatformDisplayEXT entry point"); } - return eglGetProcAddress; + return EGL_GetProcAddress; } throw new PlatformNotSupportedException(); From 7dc21fa2164b376f064e12d8b00219c3f4c78791 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 14 Sep 2020 02:29:30 -0700 Subject: [PATCH 32/75] only apply no-redirection bitmap if we are on windows 10. --- src/Windows/Avalonia.Win32/WindowImpl.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index d964e490c0..a96a662a71 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -45,6 +45,7 @@ namespace Avalonia.Win32 private Thickness _extendedMargins; private Thickness _offScreenMargin; private double _extendTitleBarHint = -1; + private bool _isUsingComposition; #if USE_MANAGED_DRAG private readonly ManagedWindowResizeDragHelper _managedDrag; @@ -110,6 +111,7 @@ namespace Avalonia.Win32 var cgl = new CompositionEglGlPlatformSurface(Win32GlManager.EglFeature.DeferredContext, this); cgl.AttachToCompositionTree(_hwnd); _gl = cgl; + _isUsingComposition = true; } else { @@ -626,7 +628,7 @@ namespace Avalonia.Win32 protected virtual IntPtr CreateWindowOverride(ushort atom) { return CreateWindowEx( - (int)WindowStyles.WS_EX_NOREDIRECTIONBITMAP, // TODO this is only when using Win UI Comp. + _isUsingComposition ? (int)WindowStyles.WS_EX_NOREDIRECTIONBITMAP : 0, atom, null, (int)WindowStyles.WS_OVERLAPPEDWINDOW | (int) WindowStyles.WS_CLIPCHILDREN, From 094e605af9000e257eff19b0657b4db217527bf0 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 14 Sep 2020 02:36:46 -0700 Subject: [PATCH 33/75] ensure dx11 api for win.ui.comp. --- src/Windows/Avalonia.Win32/WindowImpl.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index a96a662a71..fb9f7783b1 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -7,6 +7,7 @@ using Avalonia.Controls.Platform; using Avalonia.Input; using Avalonia.Input.Raw; using Avalonia.OpenGL; +using Avalonia.OpenGL.Angle; using Avalonia.Platform; using Avalonia.Rendering; using Avalonia.Win32.Input; @@ -106,11 +107,15 @@ namespace Avalonia.Win32 if (Win32GlManager.EglFeature != null) { - if (Win32Platform.WindowsVersion.Major >= 10) + if (Win32Platform.WindowsVersion.Major >= 10 && + Win32GlManager.EglFeature.Display is AngleWin32EglDisplay angleDisplay && + angleDisplay.PlatformApi == AngleOptions.PlatformApi.DirectX11) { var cgl = new CompositionEglGlPlatformSurface(Win32GlManager.EglFeature.DeferredContext, this); cgl.AttachToCompositionTree(_hwnd); + _gl = cgl; + _isUsingComposition = true; } else From 874ac50de24753be252f42a237250137fff14447 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 14 Sep 2020 02:54:31 -0700 Subject: [PATCH 34/75] add a texture wrapping method without requiring offset, etc. --- src/Avalonia.OpenGL/Angle/AngleWin32EglDisplay.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Avalonia.OpenGL/Angle/AngleWin32EglDisplay.cs b/src/Avalonia.OpenGL/Angle/AngleWin32EglDisplay.cs index 3b254d401a..9bb0dd8351 100644 --- a/src/Avalonia.OpenGL/Angle/AngleWin32EglDisplay.cs +++ b/src/Avalonia.OpenGL/Angle/AngleWin32EglDisplay.cs @@ -78,6 +78,13 @@ namespace Avalonia.OpenGL.Angle return d3dDeviceHandle; } + public EglSurface WrapDirect3D11Texture(IntPtr handle) + { + if (PlatformApi != AngleOptions.PlatformApi.DirectX11) + throw new InvalidOperationException("Current platform API is " + PlatformApi); + return CreatePBufferFromClientBuffer(EGL_D3D_TEXTURE_ANGLE, handle, new[] { EGL_FLEXIBLE_SURFACE_COMPATIBILITY_SUPPORTED_ANGLE, EGL_TRUE, EGL_NONE }); + } + public EglSurface WrapDirect3D11Texture(IntPtr handle, int offsetX, int offsetY, int width, int height) { if (PlatformApi != AngleOptions.PlatformApi.DirectX11) From fdb68480463776f8d5cd125ce4eb867a5a9ebc75 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 14 Sep 2020 02:55:13 -0700 Subject: [PATCH 35/75] check windows 10 build number and set composition flag before create window is called. --- src/Windows/Avalonia.Win32/WindowImpl.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index fb9f7783b1..c100b3308d 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -101,15 +101,16 @@ namespace Avalonia.Win32 }; _rendererLock = new ManagedDeferredRendererLock(); + _isUsingComposition = Win32Platform.WindowsVersion.Major >= 10 && Win32Platform.WindowsVersion.Build >= 14393 && + Win32GlManager.EglFeature.Display is AngleWin32EglDisplay angleDisplay && + angleDisplay.PlatformApi == AngleOptions.PlatformApi.DirectX11; CreateWindow(); _framebuffer = new FramebufferManager(_hwnd); if (Win32GlManager.EglFeature != null) { - if (Win32Platform.WindowsVersion.Major >= 10 && - Win32GlManager.EglFeature.Display is AngleWin32EglDisplay angleDisplay && - angleDisplay.PlatformApi == AngleOptions.PlatformApi.DirectX11) + if (_isUsingComposition) { var cgl = new CompositionEglGlPlatformSurface(Win32GlManager.EglFeature.DeferredContext, this); cgl.AttachToCompositionTree(_hwnd); From d25d88cdfac7ab224b3fb6f5342699c262a5fabd Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 14 Sep 2020 04:20:17 -0700 Subject: [PATCH 36/75] increase min windows version. --- src/Windows/Avalonia.Win32/WindowImpl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index c100b3308d..7222b66beb 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -101,7 +101,7 @@ namespace Avalonia.Win32 }; _rendererLock = new ManagedDeferredRendererLock(); - _isUsingComposition = Win32Platform.WindowsVersion.Major >= 10 && Win32Platform.WindowsVersion.Build >= 14393 && + _isUsingComposition = Win32Platform.WindowsVersion.Major >= 10 && Win32Platform.WindowsVersion.Build >= 16299 && Win32GlManager.EglFeature.Display is AngleWin32EglDisplay angleDisplay && angleDisplay.PlatformApi == AngleOptions.PlatformApi.DirectX11; From 974c73ca46c414899535635ffab73930e53b5924 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 15 Sep 2020 02:36:27 -0700 Subject: [PATCH 37/75] opengl es 3 --- src/Avalonia.OpenGL/EglDisplay.cs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Avalonia.OpenGL/EglDisplay.cs b/src/Avalonia.OpenGL/EglDisplay.cs index 7b194e4346..a3d11f2311 100644 --- a/src/Avalonia.OpenGL/EglDisplay.cs +++ b/src/Avalonia.OpenGL/EglDisplay.cs @@ -67,12 +67,13 @@ namespace Avalonia.OpenGL { Attributes = new[] { - EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_CONTEXT_MAJOR_VERSION, 3, + EGL_CONTEXT_MINOR_VERSION, 0, EGL_NONE }, Api = EGL_OPENGL_ES_API, - RenderableTypeBit = EGL_OPENGL_ES2_BIT, - Version = new GlVersion(GlProfileType.OpenGLES, 2, 0) + RenderableTypeBit = EGL_OPENGL_ES3_BIT, + Version = new GlVersion(GlProfileType.OpenGLES, 3, 0) } }) { From 1d1275059883ba603db9727422b5c10471776d8b Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 16 Sep 2020 03:25:47 -0700 Subject: [PATCH 38/75] allow enabling of windows.ui.composition with win32 options. --- src/Windows/Avalonia.Win32/Win32Platform.cs | 9 +++++++++ src/Windows/Avalonia.Win32/WindowImpl.cs | 3 ++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/Windows/Avalonia.Win32/Win32Platform.cs b/src/Windows/Avalonia.Win32/Win32Platform.cs index af6058d197..7f1ac443ad 100644 --- a/src/Windows/Avalonia.Win32/Win32Platform.cs +++ b/src/Windows/Avalonia.Win32/Win32Platform.cs @@ -39,6 +39,15 @@ namespace Avalonia public bool AllowEglInitialization { get; set; } = true; public bool? EnableMultitouch { get; set; } public bool OverlayPopups { get; set; } + + /// + /// Render Avalonia to a Texture inside the Windows.UI.Composition tree. + /// + /// + /// Supported on Windows 10 build 16299 and above. Ignored on other versions. + /// This is recommended if you need to use AcrylicBlur or acrylic in your applications. + /// + public bool UseWindowsUIComposition { get; set; } } } diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 7222b66beb..a2bd7f57b9 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -101,7 +101,8 @@ namespace Avalonia.Win32 }; _rendererLock = new ManagedDeferredRendererLock(); - _isUsingComposition = Win32Platform.WindowsVersion.Major >= 10 && Win32Platform.WindowsVersion.Build >= 16299 && + _isUsingComposition = Win32Platform.Options.UseWindowsUIComposition && + Win32Platform.WindowsVersion.Major >= 10 && Win32Platform.WindowsVersion.Build >= 16299 && Win32GlManager.EglFeature.Display is AngleWin32EglDisplay angleDisplay && angleDisplay.PlatformApi == AngleOptions.PlatformApi.DirectX11; From 8470a399b6214ecdd82774cbbc7a1620751db787 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 17 Sep 2020 14:52:02 -0700 Subject: [PATCH 39/75] point angle interface to avalonias custom built optimised angle. --- samples/ControlCatalog.NetCore/Program.cs | 4 +++- src/Avalonia.OpenGL/Angle/AngleEglInterface.cs | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/samples/ControlCatalog.NetCore/Program.cs b/samples/ControlCatalog.NetCore/Program.cs index 142736a0bb..9b62c2c98e 100644 --- a/samples/ControlCatalog.NetCore/Program.cs +++ b/samples/ControlCatalog.NetCore/Program.cs @@ -13,6 +13,7 @@ using Avalonia.Skia; using Avalonia.ReactiveUI; using Avalonia.Threading; using Avalonia.Dialogs; +using Avalonia.OpenGL; namespace ControlCatalog.NetCore { @@ -116,7 +117,8 @@ namespace ControlCatalog.NetCore .With(new Win32PlatformOptions { EnableMultitouch = true, - AllowEglInitialization = true + AllowEglInitialization = true, + UseWindowsUIComposition = true }) .UseSkia() .UseReactiveUI() diff --git a/src/Avalonia.OpenGL/Angle/AngleEglInterface.cs b/src/Avalonia.OpenGL/Angle/AngleEglInterface.cs index 0067124c0b..a6f5f33968 100644 --- a/src/Avalonia.OpenGL/Angle/AngleEglInterface.cs +++ b/src/Avalonia.OpenGL/Angle/AngleEglInterface.cs @@ -5,7 +5,7 @@ namespace Avalonia.OpenGL.Angle { public class AngleEglInterface : EglInterface { - [DllImport("avangle.dll", CharSet = CharSet.Ansi)] + [DllImport("av_libGLESv2.dll", CharSet = CharSet.Ansi)] static extern IntPtr EGL_GetProcAddress(string proc); public AngleEglInterface() : base(LoadAngle()) From a114c59fe7930c523f4503c0bd401ee7e0f8bac6 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 17 Sep 2020 16:09:59 -0700 Subject: [PATCH 40/75] update angle binaries. --- samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj b/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj index 28b0257eda..6b3e3a5f61 100644 --- a/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj +++ b/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj @@ -13,7 +13,7 @@ - + From d3700adb560d295908c87231dc1b77ff973c4d7f Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 17 Sep 2020 16:23:40 -0700 Subject: [PATCH 41/75] setup the acrylic blur in a way it can be show or hidden. --- .../Avalonia.Win32/Composition/CompositionHost.cs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs index 8da205fdc6..958959bc93 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs @@ -76,7 +76,15 @@ namespace Avalonia.Win32 visual.Brush = brush; visual.Offset = new System.Numerics.Vector3(0, 0, 0); - target.Root = CreateBlur(); + + var container = _compositor.CreateContainerVisual(); + container.RelativeSizeAdjustment = new System.Numerics.Vector2(1, 1); + + target.Root = container; + + var blur = CreateBlur(); + + container.Children.InsertAtTop(blur); var visuals = target.Root.As().Children; From e00aa6e5ded72e32e356793c38bb68daeb2f127c Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 17 Sep 2020 17:30:13 -0700 Subject: [PATCH 42/75] iscorrupted no longer useful. --- .../Composition/CompositionEglGlPlatformSurface.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs b/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs index 701070a6b5..96646b9590 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs @@ -35,7 +35,7 @@ namespace Avalonia.Win32 { private readonly EglDisplay _display; private readonly IEglWindowGlPlatformSurfaceInfo _info; - private PixelSize _initialSize; + private readonly PixelSize _initialSize; private readonly ICompositionDrawingSurfaceInterop _surfaceInterop; private static Guid s_Iid = Guid.Parse("6f15aaf2-d208-4e89-9ab4-489535d34f9c"); private Windows.UI.Composition.Visual _compositionVisual; @@ -56,7 +56,7 @@ namespace Avalonia.Win32 _compositionVisual.Size = new System.Numerics.Vector2(_info.Size.Width, _info.Size.Height); } - public override bool IsCorrupted => _initialSize != _info.Size; + public override bool IsCorrupted => false; public override IGlPlatformSurfaceRenderingSession BeginDraw() { var offset = new POINT(); From 6bcf36e23fc61353406ee1dcb6009fe8cba6aa65 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 18 Sep 2020 01:36:17 -0700 Subject: [PATCH 43/75] windows.ui.composition compatible with acrylic blur setting. --- .../CompositionEglGlPlatformSurface.cs | 8 +- .../Composition/CompositionHost.cs | 24 +++++- src/Windows/Avalonia.Win32/WindowImpl.cs | 84 +++++++++++-------- 3 files changed, 75 insertions(+), 41 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs b/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs index 96646b9590..38ea545957 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs @@ -6,7 +6,7 @@ using Windows.UI.Composition.Interop; namespace Avalonia.Win32 { - public class CompositionEglGlPlatformSurface : EglGlPlatformSurfaceBase + internal class CompositionEglGlPlatformSurface : EglGlPlatformSurfaceBase { private readonly EglDisplay _display; private readonly EglContext _context; @@ -21,9 +21,11 @@ namespace Avalonia.Win32 _info = info; } - public void AttachToCompositionTree(IntPtr hwnd) + public IBlurHost AttachToCompositionTree(IntPtr hwnd) { - _surfaceInterop = CompositionHost.Instance.InitialiseWindowCompositionTree(hwnd, out _surface); + _surfaceInterop = CompositionHost.Instance.InitialiseWindowCompositionTree(hwnd, out _surface, out var blurHost); + + return blurHost; } public override IGlPlatformSurfaceRenderTarget CreateGlRenderTarget() diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs index 958959bc93..dfcf6e1d7f 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs @@ -7,6 +7,26 @@ using WinRT; namespace Avalonia.Win32 { + internal interface IBlurHost + { + void SetBlur(bool enabled); + } + + 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; + } + } + class CompositionHost { internal enum DISPATCHERQUEUE_THREAD_APARTMENTTYPE @@ -61,7 +81,7 @@ namespace Avalonia.Win32 _graphicsDevice = interop.CreateGraphicsDevice(display.GetDirect3DDevice()); } - public ICompositionDrawingSurfaceInterop InitialiseWindowCompositionTree(IntPtr hwnd, out Windows.UI.Composition.Visual surfaceVisual) + public ICompositionDrawingSurfaceInterop InitialiseWindowCompositionTree(IntPtr hwnd, out Windows.UI.Composition.Visual surfaceVisual, out IBlurHost blurHost) { var target = CreateDesktopWindowTarget(hwnd); @@ -84,6 +104,8 @@ namespace Avalonia.Win32 var blur = CreateBlur(); + blurHost = new CompositionBlurHost(blur); + container.Children.InsertAtTop(blur); var visuals = target.Root.As().Children; diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index a2bd7f57b9..46c18dea68 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -47,6 +47,7 @@ namespace Avalonia.Win32 private Thickness _offScreenMargin; private double _extendTitleBarHint = -1; private bool _isUsingComposition; + private IBlurHost _blurHost; #if USE_MANAGED_DRAG private readonly ManagedWindowResizeDragHelper _managedDrag; @@ -114,7 +115,7 @@ namespace Avalonia.Win32 if (_isUsingComposition) { var cgl = new CompositionEglGlPlatformSurface(Win32GlManager.EglFeature.DeferredContext, this); - cgl.AttachToCompositionTree(_hwnd); + _blurHost = cgl.AttachToCompositionTree(_hwnd); _gl = cgl; @@ -341,54 +342,63 @@ namespace Avalonia.Win32 private WindowTransparencyLevel Win10EnableBlur(WindowTransparencyLevel transparencyLevel) { - bool canUseAcrylic = Win32Platform.WindowsVersion.Major > 10 || Win32Platform.WindowsVersion.Build >= 19628; - - var accent = new AccentPolicy(); - var accentStructSize = Marshal.SizeOf(accent); - - if (transparencyLevel == WindowTransparencyLevel.AcrylicBlur && !canUseAcrylic) + if (_isUsingComposition) { - transparencyLevel = WindowTransparencyLevel.Blur; - } + _blurHost?.SetBlur(transparencyLevel >= WindowTransparencyLevel.Blur); - switch (transparencyLevel) + return transparencyLevel; + } + else { - default: - case WindowTransparencyLevel.None: - accent.AccentState = AccentState.ACCENT_DISABLED; - break; + bool canUseAcrylic = Win32Platform.WindowsVersion.Major > 10 || Win32Platform.WindowsVersion.Build >= 19628; - case WindowTransparencyLevel.Transparent: - accent.AccentState = AccentState.ACCENT_ENABLE_TRANSPARENTGRADIENT; - break; + var accent = new AccentPolicy(); + var accentStructSize = Marshal.SizeOf(accent); - case WindowTransparencyLevel.Blur: - accent.AccentState = AccentState.ACCENT_ENABLE_BLURBEHIND; - break; + if (transparencyLevel == WindowTransparencyLevel.AcrylicBlur && !canUseAcrylic) + { + transparencyLevel = WindowTransparencyLevel.Blur; + } - case WindowTransparencyLevel.AcrylicBlur: - case (WindowTransparencyLevel.AcrylicBlur + 1): // hack-force acrylic. - accent.AccentState = AccentState.ACCENT_ENABLE_ACRYLIC; - transparencyLevel = WindowTransparencyLevel.AcrylicBlur; - break; - } + switch (transparencyLevel) + { + default: + case WindowTransparencyLevel.None: + accent.AccentState = AccentState.ACCENT_DISABLED; + break; + + case WindowTransparencyLevel.Transparent: + accent.AccentState = AccentState.ACCENT_ENABLE_TRANSPARENTGRADIENT; + break; + + case WindowTransparencyLevel.Blur: + accent.AccentState = AccentState.ACCENT_ENABLE_BLURBEHIND; + break; + + case WindowTransparencyLevel.AcrylicBlur: + case (WindowTransparencyLevel.AcrylicBlur + 1): // hack-force acrylic. + accent.AccentState = AccentState.ACCENT_ENABLE_ACRYLIC; + transparencyLevel = WindowTransparencyLevel.AcrylicBlur; + break; + } - accent.AccentFlags = 2; - accent.GradientColor = 0x01000000; + accent.AccentFlags = 2; + accent.GradientColor = 0x01000000; - var accentPtr = Marshal.AllocHGlobal(accentStructSize); - Marshal.StructureToPtr(accent, accentPtr, false); + var accentPtr = Marshal.AllocHGlobal(accentStructSize); + Marshal.StructureToPtr(accent, accentPtr, false); - var data = new WindowCompositionAttributeData(); - data.Attribute = WindowCompositionAttribute.WCA_ACCENT_POLICY; - data.SizeOfData = accentStructSize; - data.Data = accentPtr; + var data = new WindowCompositionAttributeData(); + data.Attribute = WindowCompositionAttribute.WCA_ACCENT_POLICY; + data.SizeOfData = accentStructSize; + data.Data = accentPtr; - SetWindowCompositionAttribute(_hwnd, ref data); + SetWindowCompositionAttribute(_hwnd, ref data); - Marshal.FreeHGlobal(accentPtr); + Marshal.FreeHGlobal(accentPtr); - return transparencyLevel; + return transparencyLevel; + } } public IEnumerable Surfaces => new object[] { Handle, _gl, _framebuffer }; From 8fa906281fa2b175247bd39db8b8b33acab8ee1f Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 18 Sep 2020 01:39:49 -0700 Subject: [PATCH 44/75] zero bitmap memory, not transparent white. --- src/Avalonia.Visuals/Rendering/RenderLayer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Visuals/Rendering/RenderLayer.cs b/src/Avalonia.Visuals/Rendering/RenderLayer.cs index ddf5f4e5cf..668e9167dc 100644 --- a/src/Avalonia.Visuals/Rendering/RenderLayer.cs +++ b/src/Avalonia.Visuals/Rendering/RenderLayer.cs @@ -35,7 +35,7 @@ namespace Avalonia.Rendering using (var context = resized.Item.CreateDrawingContext(null)) { - context.Clear(Colors.Transparent); + context.Clear(default); Bitmap = resized; Scaling = scaling; From 274e76fec9211b016d53750cc202835549adbf1c Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 18 Sep 2020 01:49:48 -0700 Subject: [PATCH 45/75] dispose current bitmap whilst context is current. --- src/Avalonia.Visuals/Rendering/RenderLayer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Visuals/Rendering/RenderLayer.cs b/src/Avalonia.Visuals/Rendering/RenderLayer.cs index 668e9167dc..1fbd8c02c0 100644 --- a/src/Avalonia.Visuals/Rendering/RenderLayer.cs +++ b/src/Avalonia.Visuals/Rendering/RenderLayer.cs @@ -30,11 +30,11 @@ namespace Avalonia.Rendering { if (Size != size || Scaling != scaling) { - Bitmap.Dispose(); var resized = RefCountable.Create(drawingContext.CreateLayer(size)); using (var context = resized.Item.CreateDrawingContext(null)) { + Bitmap.Dispose(); context.Clear(default); Bitmap = resized; From 7f9b675efbe154439a956504464883fffae7bbd5 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 18 Sep 2020 03:11:42 -0700 Subject: [PATCH 46/75] refactor effects. --- .../Composition/CompositionHost.cs | 18 ++++++-- .../Avalonia.Win32/Composition/EffectBase.cs | 45 +++++++++++++++++++ .../Composition/GaussianBlurEffect.cs | 42 +++++------------ .../Composition/SaturationEffect.cs | 35 +++++++++++++++ 4 files changed, 104 insertions(+), 36 deletions(-) create mode 100644 src/Windows/Avalonia.Win32/Composition/EffectBase.cs create mode 100644 src/Windows/Avalonia.Win32/Composition/SaturationEffect.cs diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs index dfcf6e1d7f..f1cf5af0e8 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs @@ -121,18 +121,28 @@ namespace Avalonia.Win32 public SpriteVisual CreateBlur() { - var effect = new GaussianBlurEffect(); - var effectFactory = _compositor.CreateEffectFactory(effect); - var blurBrush = effectFactory.CreateBrush(); + var blurEffect = new GaussianBlurEffect(new CompositionEffectSourceParameter ("backdrop")); + var blurEffectFactory = _compositor.CreateEffectFactory(blurEffect); + var blurBrush = blurEffectFactory.CreateBrush(); var backDropBrush = _compositor.CreateBackdropBrush(); blurBrush.SetSourceParameter("backdrop", backDropBrush); + + var saturateEffect = new SaturationEffect(blurEffect); + var satEffectFactory = _compositor.CreateEffectFactory(saturateEffect); + + + var satBrush = satEffectFactory.CreateBrush(); + satBrush.SetSourceParameter("backdrop", backDropBrush); + + + var visual = _compositor.CreateSpriteVisual(); visual.RelativeSizeAdjustment = new System.Numerics.Vector2(1.0f, 1.0f); - visual.Brush = blurBrush; + visual.Brush = satBrush; return visual; } diff --git a/src/Windows/Avalonia.Win32/Composition/EffectBase.cs b/src/Windows/Avalonia.Win32/Composition/EffectBase.cs new file mode 100644 index 0000000000..ca5b15971e --- /dev/null +++ b/src/Windows/Avalonia.Win32/Composition/EffectBase.cs @@ -0,0 +1,45 @@ +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); + } +} + diff --git a/src/Windows/Avalonia.Win32/Composition/GaussianBlurEffect.cs b/src/Windows/Avalonia.Win32/Composition/GaussianBlurEffect.cs index 4e1be3af1a..342e68eeb4 100644 --- a/src/Windows/Avalonia.Win32/Composition/GaussianBlurEffect.cs +++ b/src/Windows/Avalonia.Win32/Composition/GaussianBlurEffect.cs @@ -1,13 +1,14 @@ using System; using Windows.Graphics.Effects; -using Windows.Graphics.Effects.Interop; -using Windows.UI.Composition; - namespace Avalonia.Win32 { - class GaussianBlurEffect : IGraphicsEffect, IGraphicsEffectSource, global::Windows.Graphics.Effects.Interop.IGraphicsEffectD2D1Interop + class GaussianBlurEffect : EffectBase { + public GaussianBlurEffect(IGraphicsEffectSource source) : base(source) + { + } + enum D2D1_GAUSSIANBLUR_OPTIMIZATION { D2D1_GAUSSIANBLUR_OPTIMIZATION_SPEED, @@ -31,20 +32,11 @@ namespace Avalonia.Win32 D2D1_GAUSSIANBLUR_PROP_FORCE_DWORD }; - public string Name { get; set; } - - public Guid EffectId => D2DEffects.CLSID_D2D1GaussianBlur; + public override Guid EffectId => D2DEffects.CLSID_D2D1GaussianBlur; - public uint PropertyCount => 3; - - public uint SourceCount => 1; - - public uint GetNamedPropertyMapping(string name, out GRAPHICS_EFFECT_PROPERTY_MAPPING mapping) - { - throw new NotImplementedException(); - } + public override uint PropertyCount => 3; - public object GetProperty(uint index) + public override object GetProperty(uint index) { switch ((D2D1GaussianBlurProp)index) { @@ -52,28 +44,14 @@ namespace Avalonia.Win32 return 30.0f; case D2D1GaussianBlurProp.D2D1_GAUSSIANBLUR_PROP_OPTIMIZATION: - return (UInt32)D2D1_GAUSSIANBLUR_OPTIMIZATION.D2D1_GAUSSIANBLUR_OPTIMIZATION_BALANCED; + return (uint)D2D1_GAUSSIANBLUR_OPTIMIZATION.D2D1_GAUSSIANBLUR_OPTIMIZATION_BALANCED; case D2D1GaussianBlurProp.D2D1_GAUSSIANBLUR_PROP_BORDER_MODE: - return (UInt32)D2D1_BORDER_MODE.D2D1_BORDER_MODE_HARD; + return (uint)D2D1_BORDER_MODE.D2D1_BORDER_MODE_HARD; } return null; } - - private IGraphicsEffectSource _source = new CompositionEffectSourceParameter("backdrop"); - - public IGraphicsEffectSource GetSource(uint index) - { - if (index == 0) - { - return _source; - } - else - { - return null; - } - } } } diff --git a/src/Windows/Avalonia.Win32/Composition/SaturationEffect.cs b/src/Windows/Avalonia.Win32/Composition/SaturationEffect.cs new file mode 100644 index 0000000000..90eca22d8e --- /dev/null +++ b/src/Windows/Avalonia.Win32/Composition/SaturationEffect.cs @@ -0,0 +1,35 @@ +using System; +using Windows.Graphics.Effects; + + +namespace Avalonia.Win32 +{ + class SaturationEffect : EffectBase + { + public SaturationEffect(IGraphicsEffect 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; + } + } +} + From 57b3f0b10574a167a448ad4401b6de88c1563354 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 18 Sep 2020 03:21:04 -0700 Subject: [PATCH 47/75] revert changed code. --- .../ControlCatalog.NetCore/Properties/launchSettings.json | 8 -------- samples/ControlCatalog/MainWindow.xaml | 8 ++++++-- 2 files changed, 6 insertions(+), 10 deletions(-) delete mode 100644 samples/ControlCatalog.NetCore/Properties/launchSettings.json diff --git a/samples/ControlCatalog.NetCore/Properties/launchSettings.json b/samples/ControlCatalog.NetCore/Properties/launchSettings.json deleted file mode 100644 index cd8a2c824b..0000000000 --- a/samples/ControlCatalog.NetCore/Properties/launchSettings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "profiles": { - "ControlCatalog.NetCore": { - "commandName": "Project", - "nativeDebugging": true - } - } -} \ No newline at end of file diff --git a/samples/ControlCatalog/MainWindow.xaml b/samples/ControlCatalog/MainWindow.xaml index eebc804a64..97bd88f5e4 100644 --- a/samples/ControlCatalog/MainWindow.xaml +++ b/samples/ControlCatalog/MainWindow.xaml @@ -7,8 +7,12 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:vm="clr-namespace:ControlCatalog.ViewModels" xmlns:v="clr-namespace:ControlCatalog.Views" - TransparencyLevelHint="Transparent" - x:Class="ControlCatalog.MainWindow" WindowState="{Binding WindowState, Mode=TwoWay}" Background="{x:Null}"> + ExtendClientAreaToDecorationsHint="{Binding ExtendClientAreaEnabled}" + ExtendClientAreaChromeHints="{Binding ChromeHints}" + ExtendClientAreaTitleBarHeightHint="{Binding TitleBarHeight}" + TransparencyLevelHint="{Binding TransparencyLevel}" + x:Name="MainWindow" + x:Class="ControlCatalog.MainWindow" WindowState="{Binding WindowState, Mode=TwoWay}"> From 4d0c27dc8f8da04be98b690a8406df2d86a9f49a Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 18 Sep 2020 03:32:43 -0700 Subject: [PATCH 48/75] whitespace. --- src/Windows/Avalonia.Win32/WindowImpl.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 46c18dea68..9c002038cb 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -717,7 +717,7 @@ namespace Avalonia.Win32 { _scaling = dpix / 96.0; } - } + } } private void CreateDropTarget() From 28168d571be4912cb85d87629fba798ae5fd3b09 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 18 Sep 2020 10:06:19 -0700 Subject: [PATCH 49/75] make managed deferredrenderer lock global. --- src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs | 6 +++--- src/Windows/Avalonia.Win32/WindowImpl.cs | 5 ++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs index 25a34561fc..0bab0d1657 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs @@ -339,7 +339,7 @@ namespace Avalonia.Win32 case WindowsMessage.WM_PAINT: { - using (_rendererLock.Lock()) + using (s_rendererLock.Lock()) { if (BeginPaint(_hwnd, out PAINTSTRUCT ps) != IntPtr.Zero) { @@ -356,7 +356,7 @@ namespace Avalonia.Win32 case WindowsMessage.WM_SIZE: { - using (_rendererLock.Lock()) + using (s_rendererLock.Lock()) { // Do nothing here, just block until the pending frame render is completed on the render thread } @@ -464,7 +464,7 @@ namespace Avalonia.Win32 } } - using (_rendererLock.Lock()) + using (s_rendererLock.Lock()) { return DefWindowProc(hWnd, msg, wParam, lParam); } diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 9c002038cb..7b8b6d3e83 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -56,7 +56,7 @@ namespace Avalonia.Win32 private const WindowStyles WindowStateMask = (WindowStyles.WS_MAXIMIZE | WindowStyles.WS_MINIMIZE); private readonly TouchDevice _touchDevice; private readonly MouseDevice _mouseDevice; - private readonly ManagedDeferredRendererLock _rendererLock; + private static readonly ManagedDeferredRendererLock s_rendererLock = new ManagedDeferredRendererLock(); private readonly FramebufferManager _framebuffer; private readonly IGlPlatformSurface _gl; @@ -100,7 +100,6 @@ namespace Avalonia.Win32 IsResizable = true, Decorations = SystemDecorations.Full }; - _rendererLock = new ManagedDeferredRendererLock(); _isUsingComposition = Win32Platform.Options.UseWindowsUIComposition && Win32Platform.WindowsVersion.Major >= 10 && Win32Platform.WindowsVersion.Build >= 16299 && @@ -443,7 +442,7 @@ namespace Avalonia.Win32 return customRendererFactory.Create(root, loop); return Win32Platform.UseDeferredRendering ? - (IRenderer)new DeferredRenderer(root, loop, rendererLock: _rendererLock) : + (IRenderer)new DeferredRenderer(root, loop, rendererLock: s_rendererLock) : new ImmediateRenderer(root); } From 7720d8f9062c220e05b2c40183694defccccb616 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 18 Sep 2020 10:42:39 -0700 Subject: [PATCH 50/75] fix visual tree so that content resizes with the window. --- .../Composition/CompositionEglGlPlatformSurface.cs | 3 ++- .../Avalonia.Win32/Composition/CompositionHost.cs | 11 ++++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs b/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs index 38ea545957..4e6dc79673 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs @@ -58,7 +58,8 @@ namespace Avalonia.Win32 _compositionVisual.Size = new System.Numerics.Vector2(_info.Size.Width, _info.Size.Height); } - public override bool IsCorrupted => false; + public override bool IsCorrupted => _info.Size != _initialSize; + public override IGlPlatformSurfaceRenderingSession BeginDraw() { var offset = new POINT(); diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs index f1cf5af0e8..615b5d303a 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs @@ -95,11 +95,10 @@ namespace Avalonia.Win32 var visual = _compositor.CreateSpriteVisual(); visual.Brush = brush; - visual.Offset = new System.Numerics.Vector3(0, 0, 0); + visual.RelativeSizeAdjustment = new System.Numerics.Vector2(1, 1); var container = _compositor.CreateContainerVisual(); - container.RelativeSizeAdjustment = new System.Numerics.Vector2(1, 1); - + target.Root = container; var blur = CreateBlur(); @@ -108,13 +107,11 @@ namespace Avalonia.Win32 container.Children.InsertAtTop(blur); - var visuals = target.Root.As().Children; - - visuals.InsertAtTop(visual); + container.Children.InsertAtTop(visual); visual.CompositeMode = CompositionCompositeMode.SourceOver; - surfaceVisual = visual; + surfaceVisual = container; return surfaceInterop; } From a004366e70c0e8b7dead53f092bc261246597a4d Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 18 Sep 2020 10:50:27 -0700 Subject: [PATCH 51/75] make blur not visible at startup. --- src/Windows/Avalonia.Win32/Composition/CompositionHost.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs index 615b5d303a..516ad44071 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs @@ -126,17 +126,14 @@ namespace Avalonia.Win32 blurBrush.SetSourceParameter("backdrop", backDropBrush); - 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; From 099909d4e286a9820e8a34b9b793979c4b827e77 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 18 Sep 2020 10:55:07 -0700 Subject: [PATCH 52/75] make win.ui.comp the default when running on win10 and compatible gpu is used. --- samples/ControlCatalog.NetCore/Program.cs | 3 +-- src/Windows/Avalonia.Win32/Win32Platform.cs | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/samples/ControlCatalog.NetCore/Program.cs b/samples/ControlCatalog.NetCore/Program.cs index 9b62c2c98e..d967fde34c 100644 --- a/samples/ControlCatalog.NetCore/Program.cs +++ b/samples/ControlCatalog.NetCore/Program.cs @@ -117,8 +117,7 @@ namespace ControlCatalog.NetCore .With(new Win32PlatformOptions { EnableMultitouch = true, - AllowEglInitialization = true, - UseWindowsUIComposition = true + AllowEglInitialization = true }) .UseSkia() .UseReactiveUI() diff --git a/src/Windows/Avalonia.Win32/Win32Platform.cs b/src/Windows/Avalonia.Win32/Win32Platform.cs index 7f1ac443ad..e9d34d7d56 100644 --- a/src/Windows/Avalonia.Win32/Win32Platform.cs +++ b/src/Windows/Avalonia.Win32/Win32Platform.cs @@ -47,7 +47,7 @@ namespace Avalonia /// Supported on Windows 10 build 16299 and above. Ignored on other versions. /// This is recommended if you need to use AcrylicBlur or acrylic in your applications. /// - public bool UseWindowsUIComposition { get; set; } + public bool UseWindowsUIComposition { get; set; } = true; } } From 59d68a30370694203a4647399cddc81542c09c92 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 18 Sep 2020 10:57:45 -0700 Subject: [PATCH 53/75] remove usings. --- samples/ControlCatalog.NetCore/Program.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/samples/ControlCatalog.NetCore/Program.cs b/samples/ControlCatalog.NetCore/Program.cs index d967fde34c..3851cbf9a6 100644 --- a/samples/ControlCatalog.NetCore/Program.cs +++ b/samples/ControlCatalog.NetCore/Program.cs @@ -7,13 +7,11 @@ using System.Threading.Tasks; using Avalonia; using Avalonia.Controls; using Avalonia.Controls.ApplicationLifetimes; +using Avalonia.Dialogs; using Avalonia.Headless; using Avalonia.LogicalTree; -using Avalonia.Skia; using Avalonia.ReactiveUI; using Avalonia.Threading; -using Avalonia.Dialogs; -using Avalonia.OpenGL; namespace ControlCatalog.NetCore { From 02f33d561c21439849838cce4587f27b5560122e Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 18 Sep 2020 10:59:16 -0700 Subject: [PATCH 54/75] 1 file per class. --- .../Composition/CompositionBlurHost.cs | 18 +++++++++++++++++ .../Composition/CompositionHost.cs | 20 ------------------- .../Avalonia.Win32/Composition/IBlurHost.cs | 8 ++++++++ 3 files changed, 26 insertions(+), 20 deletions(-) create mode 100644 src/Windows/Avalonia.Win32/Composition/CompositionBlurHost.cs create mode 100644 src/Windows/Avalonia.Win32/Composition/IBlurHost.cs diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionBlurHost.cs b/src/Windows/Avalonia.Win32/Composition/CompositionBlurHost.cs new file mode 100644 index 0000000000..4c090e797c --- /dev/null +++ b/src/Windows/Avalonia.Win32/Composition/CompositionBlurHost.cs @@ -0,0 +1,18 @@ +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; + } + } +} + diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs index 516ad44071..07a0170810 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs @@ -7,26 +7,6 @@ using WinRT; namespace Avalonia.Win32 { - internal interface IBlurHost - { - void SetBlur(bool enabled); - } - - 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; - } - } - class CompositionHost { internal enum DISPATCHERQUEUE_THREAD_APARTMENTTYPE diff --git a/src/Windows/Avalonia.Win32/Composition/IBlurHost.cs b/src/Windows/Avalonia.Win32/Composition/IBlurHost.cs new file mode 100644 index 0000000000..6ab470d81c --- /dev/null +++ b/src/Windows/Avalonia.Win32/Composition/IBlurHost.cs @@ -0,0 +1,8 @@ +namespace Avalonia.Win32 +{ + internal interface IBlurHost + { + void SetBlur(bool enabled); + } +} + From 3541e70c3b4c822ca8a082c76c45efaae752d37d Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 18 Sep 2020 11:50:45 -0700 Subject: [PATCH 55/75] fix hostapp for designer. --- .../Avalonia.Designer.HostApp/Avalonia.Designer.HostApp.csproj | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tools/Avalonia.Designer.HostApp/Avalonia.Designer.HostApp.csproj b/src/tools/Avalonia.Designer.HostApp/Avalonia.Designer.HostApp.csproj index 51d18e55d1..152581de27 100644 --- a/src/tools/Avalonia.Designer.HostApp/Avalonia.Designer.HostApp.csproj +++ b/src/tools/Avalonia.Designer.HostApp/Avalonia.Designer.HostApp.csproj @@ -23,5 +23,8 @@ + + + From 8c667faf64f9adf0829929a2a70a9e9247a3d931 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 18 Sep 2020 13:37:16 -0700 Subject: [PATCH 56/75] use stable Angle. --- samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj | 2 +- samples/interop/NativeEmbedSample/NativeEmbedSample.csproj | 2 +- src/Windows/Avalonia.Win32/Avalonia.Win32.csproj | 2 +- .../Avalonia.Designer.HostApp/Avalonia.Designer.HostApp.csproj | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj b/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj index 6b3e3a5f61..d4d50163d5 100644 --- a/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj +++ b/samples/ControlCatalog.NetCore/ControlCatalog.NetCore.csproj @@ -13,7 +13,7 @@ - + diff --git a/samples/interop/NativeEmbedSample/NativeEmbedSample.csproj b/samples/interop/NativeEmbedSample/NativeEmbedSample.csproj index cc831ef8ae..abdcac3b77 100644 --- a/samples/interop/NativeEmbedSample/NativeEmbedSample.csproj +++ b/samples/interop/NativeEmbedSample/NativeEmbedSample.csproj @@ -13,7 +13,7 @@ - + Designer diff --git a/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj b/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj index c6af049868..5889d919df 100644 --- a/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj +++ b/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj @@ -6,7 +6,7 @@ - + diff --git a/src/tools/Avalonia.Designer.HostApp/Avalonia.Designer.HostApp.csproj b/src/tools/Avalonia.Designer.HostApp/Avalonia.Designer.HostApp.csproj index 152581de27..a2d27fd579 100644 --- a/src/tools/Avalonia.Designer.HostApp/Avalonia.Designer.HostApp.csproj +++ b/src/tools/Avalonia.Designer.HostApp/Avalonia.Designer.HostApp.csproj @@ -24,7 +24,7 @@ - + From 10206e728dacd64f4b754965ad6555ee6ac6a6bc Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Sun, 27 Sep 2020 21:26:25 +0100 Subject: [PATCH 57/75] Revert "make managed deferredrenderer lock global." This reverts commit 28168d571be4912cb85d87629fba798ae5fd3b09. --- src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs | 6 +++--- src/Windows/Avalonia.Win32/WindowImpl.cs | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs index 0bab0d1657..25a34561fc 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.AppWndProc.cs @@ -339,7 +339,7 @@ namespace Avalonia.Win32 case WindowsMessage.WM_PAINT: { - using (s_rendererLock.Lock()) + using (_rendererLock.Lock()) { if (BeginPaint(_hwnd, out PAINTSTRUCT ps) != IntPtr.Zero) { @@ -356,7 +356,7 @@ namespace Avalonia.Win32 case WindowsMessage.WM_SIZE: { - using (s_rendererLock.Lock()) + using (_rendererLock.Lock()) { // Do nothing here, just block until the pending frame render is completed on the render thread } @@ -464,7 +464,7 @@ namespace Avalonia.Win32 } } - using (s_rendererLock.Lock()) + using (_rendererLock.Lock()) { return DefWindowProc(hWnd, msg, wParam, lParam); } diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 6ca12e571f..848635fe23 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -58,7 +58,7 @@ namespace Avalonia.Win32 private const WindowStyles WindowStateMask = (WindowStyles.WS_MAXIMIZE | WindowStyles.WS_MINIMIZE); private readonly TouchDevice _touchDevice; private readonly MouseDevice _mouseDevice; - private static readonly ManagedDeferredRendererLock s_rendererLock = new ManagedDeferredRendererLock(); + private readonly ManagedDeferredRendererLock _rendererLock; private readonly FramebufferManager _framebuffer; private readonly IGlPlatformSurface _gl; @@ -102,6 +102,7 @@ namespace Avalonia.Win32 IsResizable = true, Decorations = SystemDecorations.Full }; + _rendererLock = new ManagedDeferredRendererLock(); _isUsingComposition = Win32Platform.Options.UseWindowsUIComposition && Win32Platform.WindowsVersion.Major >= 10 && Win32Platform.WindowsVersion.Build >= 16299 && @@ -445,7 +446,7 @@ namespace Avalonia.Win32 return customRendererFactory.Create(root, loop); return Win32Platform.UseDeferredRendering ? - (IRenderer)new DeferredRenderer(root, loop, rendererLock: s_rendererLock) : + (IRenderer)new DeferredRenderer(root, loop, rendererLock: _rendererLock) : new ImmediateRenderer(root); } From 05f7ee83af016d4f6f10b9294e270299295596e9 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 29 Sep 2020 18:23:19 +0100 Subject: [PATCH 58/75] fix resizing of composition surface. --- .../Composition/CompositionEglGlPlatformSurface.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs b/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs index c034d8f7f7..2e4b69c0b5 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs @@ -39,7 +39,7 @@ namespace Avalonia.Win32 { private readonly EglPlatformOpenGlInterface _egl; private readonly IEglWindowGlPlatformSurfaceInfo _info; - private readonly PixelSize _initialSize; + 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; @@ -53,7 +53,7 @@ namespace Avalonia.Win32 _egl = egl; _surfaceInterop = interopSurface; _info = info; - _initialSize = info.Size; + _currentSize = info.Size; _compositionVisual = compositionVisual; _surfaceInterop.Resize(new POINT { X = _info.Size.Width, Y = _info.Size.Height }); _compositionVisual.Size = new System.Numerics.Vector2(_info.Size.Width, _info.Size.Height); @@ -61,6 +61,13 @@ namespace Avalonia.Win32 public override IGlPlatformSurfaceRenderingSession BeginDraw() { + 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( From b5c5cc7192b8298c6136f331e3256a58a778256b Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Fri, 2 Oct 2020 20:27:21 +0100 Subject: [PATCH 59/75] protect d3d calls. --- .../CompositionEglGlPlatformSurface.cs | 43 ++++++++++++------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs b/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs index 2e4b69c0b5..b30043fedd 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs @@ -25,9 +25,11 @@ namespace Avalonia.Win32 public IBlurHost AttachToCompositionTree(IntPtr hwnd) { - _surfaceInterop = CompositionHost.Instance.InitialiseWindowCompositionTree(hwnd, out _surface, out var blurHost); - - return blurHost; + using (_egl.PrimaryContext.MakeCurrent()) + { + _surfaceInterop = CompositionHost.Instance.InitialiseWindowCompositionTree(hwnd, out _surface, out var blurHost); + return blurHost; + } } public override IGlPlatformSurfaceRenderTarget CreateGlRenderTarget() @@ -55,27 +57,38 @@ namespace Avalonia.Win32 _info = info; _currentSize = info.Size; _compositionVisual = compositionVisual; - _surfaceInterop.Resize(new POINT { X = _info.Size.Width, Y = _info.Size.Height }); + + 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() { - if (_info.Size != _currentSize) + IntPtr texture; + EglSurface surface; + + using (_egl.PrimaryEglContext.EnsureCurrent()) { - _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; - } + 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(); + var offset = new POINT(); - _surfaceInterop.BeginDraw( - IntPtr.Zero, - ref s_Iid, - out IntPtr texture, ref offset); + _surfaceInterop.BeginDraw( + IntPtr.Zero, + ref s_Iid, + out texture, ref offset); - var surface = (_egl.Display as AngleWin32EglDisplay).WrapDirect3D11Texture(_egl, texture, offset.X, offset.Y, _info.Size.Width, _info.Size.Height); + 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); } From ddd3dfa0a70ef98b9797fae4d1d1d17e2aa1cf00 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 8 Oct 2020 22:18:41 +0100 Subject: [PATCH 60/75] change surface origin. --- src/Skia/Avalonia.Skia/Gpu/OpenGl/FboSkiaSurface.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Skia/Avalonia.Skia/Gpu/OpenGl/FboSkiaSurface.cs b/src/Skia/Avalonia.Skia/Gpu/OpenGl/FboSkiaSurface.cs index 9ee8d698ba..24464c39d9 100644 --- a/src/Skia/Avalonia.Skia/Gpu/OpenGl/FboSkiaSurface.cs +++ b/src/Skia/Avalonia.Skia/Gpu/OpenGl/FboSkiaSurface.cs @@ -93,7 +93,7 @@ namespace Avalonia.Skia var target = new GRBackendRenderTarget(pixelSize.Width, pixelSize.Height, 0, 8, new GRGlFramebufferInfo((uint)_fbo, SKColorType.Rgba8888.ToGlSizedFormat())); Surface = SKSurface.Create(_grContext, target, - GRSurfaceOrigin.BottomLeft, SKColorType.Rgba8888); + GRSurfaceOrigin.TopLeft, SKColorType.Rgba8888); CanBlit = gl.BlitFramebuffer != null; } From 8fddd4b94e19f3434868bd3367e83a6914a7b0cf Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 8 Oct 2020 22:51:48 +0100 Subject: [PATCH 61/75] remove unused var. --- .../Composition/CompositionEglGlPlatformSurface.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs b/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs index b30043fedd..547e2d3c0e 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs @@ -10,15 +10,13 @@ namespace Avalonia.Win32 { internal class CompositionEglGlPlatformSurface : EglGlPlatformSurfaceBase { - private readonly EglDisplay _display; private EglPlatformOpenGlInterface _egl; private readonly IEglWindowGlPlatformSurfaceInfo _info; private ICompositionDrawingSurfaceInterop _surfaceInterop; - private Windows.UI.Composition.Visual _surface; + private Windows.UI.Composition.Visual _surface; public CompositionEglGlPlatformSurface(EglPlatformOpenGlInterface egl, IEglWindowGlPlatformSurfaceInfo info) : base() - { - _display = egl.Display; + { _egl = egl; _info = info; } From 0e70ce4999b3a7c452026d7e095c9b62f5262766 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 12 Oct 2020 18:27:26 +0100 Subject: [PATCH 62/75] rename CompositionHost to CompositionConnector. --- .../{CompositionHost.cs => CompositionConnector.cs} | 6 +++--- .../Composition/CompositionEglGlPlatformSurface.cs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) rename src/Windows/Avalonia.Win32/Composition/{CompositionHost.cs => CompositionConnector.cs} (97%) diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs b/src/Windows/Avalonia.Win32/Composition/CompositionConnector.cs similarity index 97% rename from src/Windows/Avalonia.Win32/Composition/CompositionHost.cs rename to src/Windows/Avalonia.Win32/Composition/CompositionConnector.cs index c88d239670..1519520d89 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionHost.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionConnector.cs @@ -9,7 +9,7 @@ using WinRT; namespace Avalonia.Win32 { - class CompositionHost + class CompositionConnector { internal enum DISPATCHERQUEUE_THREAD_APARTMENTTYPE { @@ -39,13 +39,13 @@ namespace Avalonia.Win32 [DllImport("coremessaging.dll", EntryPoint = "CreateDispatcherQueueController", CharSet = CharSet.Unicode)] internal static extern IntPtr CreateDispatcherQueueController(DispatcherQueueOptions options, out IntPtr dispatcherQueueController); - public static CompositionHost Instance { get; } = new CompositionHost(); + public static CompositionConnector Instance { get; } = new CompositionConnector(); private Compositor _compositor; private Windows.System.DispatcherQueueController _dispatcherQueueController; private CompositionGraphicsDevice _graphicsDevice; - private CompositionHost() + private CompositionConnector() { var glPlatform = AvaloniaLocator.Current.GetService(); diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs b/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs index 547e2d3c0e..6b6e272580 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs @@ -25,7 +25,7 @@ namespace Avalonia.Win32 { using (_egl.PrimaryContext.MakeCurrent()) { - _surfaceInterop = CompositionHost.Instance.InitialiseWindowCompositionTree(hwnd, out _surface, out var blurHost); + _surfaceInterop = CompositionConnector.Instance.InitialiseWindowCompositionTree(hwnd, out _surface, out var blurHost); return blurHost; } } From ae876bd058675e644924eb24d20837f4191208ad Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 12 Oct 2020 18:48:12 +0100 Subject: [PATCH 63/75] simplify composition connection. --- .../Composition/CompositionConnector.cs | 15 ++------------- .../CompositionEglGlPlatformSurface.cs | 4 ++-- src/Windows/Avalonia.Win32/Win32GlManager.cs | 18 ++++++++++++++---- src/Windows/Avalonia.Win32/Win32Platform.cs | 3 ++- src/Windows/Avalonia.Win32/WindowImpl.cs | 9 +++++---- 5 files changed, 25 insertions(+), 24 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionConnector.cs b/src/Windows/Avalonia.Win32/Composition/CompositionConnector.cs index 1519520d89..447f8a8c90 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionConnector.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionConnector.cs @@ -39,24 +39,13 @@ namespace Avalonia.Win32 [DllImport("coremessaging.dll", EntryPoint = "CreateDispatcherQueueController", CharSet = CharSet.Unicode)] internal static extern IntPtr CreateDispatcherQueueController(DispatcherQueueOptions options, out IntPtr dispatcherQueueController); - public static CompositionConnector Instance { get; } = new CompositionConnector(); - private Compositor _compositor; private Windows.System.DispatcherQueueController _dispatcherQueueController; private CompositionGraphicsDevice _graphicsDevice; - private CompositionConnector() + internal CompositionConnector(EglPlatformOpenGlInterface egl) { - var glPlatform = AvaloniaLocator.Current.GetService(); - - if (glPlatform is EglPlatformOpenGlInterface egl) - { - Initialize(egl); - } - else - { - throw new PlatformNotSupportedException(); - } + Initialize(egl); } private void Initialize(EglPlatformOpenGlInterface egl) diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs b/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs index 6b6e272580..441da93787 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionEglGlPlatformSurface.cs @@ -21,11 +21,11 @@ namespace Avalonia.Win32 _info = info; } - public IBlurHost AttachToCompositionTree(IntPtr hwnd) + public IBlurHost AttachToCompositionTree(CompositionConnector connector, IntPtr hwnd) { using (_egl.PrimaryContext.MakeCurrent()) { - _surfaceInterop = CompositionConnector.Instance.InitialiseWindowCompositionTree(hwnd, out _surface, out var blurHost); + _surfaceInterop = connector.InitialiseWindowCompositionTree(hwnd, out _surface, out var blurHost); return blurHost; } } diff --git a/src/Windows/Avalonia.Win32/Win32GlManager.cs b/src/Windows/Avalonia.Win32/Win32GlManager.cs index 523a059e0e..6a6ce2ec3c 100644 --- a/src/Windows/Avalonia.Win32/Win32GlManager.cs +++ b/src/Windows/Avalonia.Win32/Win32GlManager.cs @@ -7,8 +7,6 @@ namespace Avalonia.Win32 { static class Win32GlManager { - private static bool s_attemptedToInitialize; - public static void Initialize() { AvaloniaLocator.CurrentMutable.Bind().ToLazy(() => @@ -19,9 +17,21 @@ namespace Avalonia.Win32 var wgl = WglPlatformOpenGlInterface.TryCreate(); return wgl; } - + if (opts?.AllowEglInitialization == true) - return EglPlatformOpenGlInterface.TryCreate(() => new AngleWin32EglDisplay()); + { + var egl = EglPlatformOpenGlInterface.TryCreate(() => new AngleWin32EglDisplay()); + + if (egl is { } && + opts?.UseWindowsUIComposition == true && + Win32Platform.WindowsVersion.Major >= 10 && + Win32Platform.WindowsVersion.Build >= 16299) + { + AvaloniaLocator.CurrentMutable.BindToSelf(new CompositionConnector(egl)); + } + + return egl; + } return null; }); diff --git a/src/Windows/Avalonia.Win32/Win32Platform.cs b/src/Windows/Avalonia.Win32/Win32Platform.cs index 493ae45656..5b16cae26e 100644 --- a/src/Windows/Avalonia.Win32/Win32Platform.cs +++ b/src/Windows/Avalonia.Win32/Win32Platform.cs @@ -12,6 +12,7 @@ using Avalonia.Controls.Platform; using Avalonia.Input; using Avalonia.Input.Platform; using Avalonia.OpenGL; +using Avalonia.OpenGL.Egl; using Avalonia.Platform; using Avalonia.Rendering; using Avalonia.Threading; @@ -113,7 +114,7 @@ namespace Avalonia.Win32 .Bind().ToConstant(new WindowsMountedVolumeInfoProvider()); Win32GlManager.Initialize(); - + _uiThread = Thread.CurrentThread; if (OleContext.Current != null) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 1fd8752a8f..715c8fc01d 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -107,9 +107,10 @@ namespace Avalonia.Win32 var glPlatform = AvaloniaLocator.Current.GetService(); - _isUsingComposition = Win32Platform.Options.UseWindowsUIComposition && - Win32Platform.WindowsVersion.Major >= 10 && Win32Platform.WindowsVersion.Build >= 16299 && - glPlatform != null && glPlatform is EglPlatformOpenGlInterface egl && + var compositionConnector = AvaloniaLocator.Current.GetService(); + + _isUsingComposition = compositionConnector is { } && + glPlatform is EglPlatformOpenGlInterface egl && egl.Display is AngleWin32EglDisplay angleDisplay && angleDisplay.PlatformApi == AngleOptions.PlatformApi.DirectX11; @@ -121,7 +122,7 @@ namespace Avalonia.Win32 if (_isUsingComposition) { var cgl = new CompositionEglGlPlatformSurface(glPlatform as EglPlatformOpenGlInterface, this); - _blurHost = cgl.AttachToCompositionTree(_hwnd); + _blurHost = cgl.AttachToCompositionTree(compositionConnector, _hwnd); _gl = cgl; From 614c0c6726eaaf7fbc0a825618cf518cd4320f3e Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Mon, 12 Oct 2020 18:51:00 +0100 Subject: [PATCH 64/75] tidy composition connector. --- .../Composition/CompositionConnector.cs | 30 ++++++++----------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionConnector.cs b/src/Windows/Avalonia.Win32/Composition/CompositionConnector.cs index 447f8a8c90..3929dc07bf 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionConnector.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionConnector.cs @@ -9,8 +9,12 @@ using WinRT; namespace Avalonia.Win32 { - class CompositionConnector + internal class CompositionConnector { + private Compositor _compositor; + private Windows.System.DispatcherQueueController _dispatcherQueueController; + private CompositionGraphicsDevice _graphicsDevice; + internal enum DISPATCHERQUEUE_THREAD_APARTMENTTYPE { DQTAT_COM_NONE = 0, @@ -39,23 +43,15 @@ namespace Avalonia.Win32 [DllImport("coremessaging.dll", EntryPoint = "CreateDispatcherQueueController", CharSet = CharSet.Unicode)] internal static extern IntPtr CreateDispatcherQueueController(DispatcherQueueOptions options, out IntPtr dispatcherQueueController); - private Compositor _compositor; - private Windows.System.DispatcherQueueController _dispatcherQueueController; - private CompositionGraphicsDevice _graphicsDevice; - - internal CompositionConnector(EglPlatformOpenGlInterface egl) - { - Initialize(egl); - } - - private void Initialize(EglPlatformOpenGlInterface egl) + public CompositionConnector(EglPlatformOpenGlInterface egl) { EnsureDispatcherQueue(); + if (_dispatcherQueueController != null) _compositor = new Compositor(); var interop = _compositor.As(); - + var display = egl.Display as AngleWin32EglDisplay; _graphicsDevice = interop.CreateGraphicsDevice(display.GetDirect3DDevice()); @@ -78,7 +74,7 @@ namespace Avalonia.Win32 visual.RelativeSizeAdjustment = new System.Numerics.Vector2(1, 1); var container = _compositor.CreateContainerVisual(); - + target.Root = container; var blur = CreateBlur(); @@ -96,9 +92,9 @@ namespace Avalonia.Win32 return surfaceInterop; } - public SpriteVisual CreateBlur() + private SpriteVisual CreateBlur() { - var blurEffect = new GaussianBlurEffect(new CompositionEffectSourceParameter ("backdrop")); + var blurEffect = new GaussianBlurEffect(new CompositionEffectSourceParameter("backdrop")); var blurEffectFactory = _compositor.CreateEffectFactory(blurEffect); var blurBrush = blurEffectFactory.CreateBrush(); @@ -121,7 +117,7 @@ namespace Avalonia.Win32 return visual; } - CompositionTarget CreateDesktopWindowTarget(IntPtr window) + private CompositionTarget CreateDesktopWindowTarget(IntPtr window) { var interop = _compositor.As(); @@ -129,7 +125,7 @@ namespace Avalonia.Win32 return Windows.UI.Composition.Desktop.DesktopWindowTarget.FromAbi(windowTarget); } - void EnsureDispatcherQueue() + private void EnsureDispatcherQueue() { if (_dispatcherQueueController == null) { From 21fadbedd6734fd74e07fdeb7c2383b546ce6b38 Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Fri, 16 Oct 2020 12:43:17 +0300 Subject: [PATCH 65/75] add tests for text issue:4866 --- .../Controls/TextBlockTests.cs | 54 ++++++++++++++++++ ...estrictedHeight_VerticalAlign.expected.png | Bin 0 -> 527 bytes ...estrictedHeight_VerticalAlign.expected.png | Bin 0 -> 527 bytes 3 files changed, 54 insertions(+) create mode 100644 tests/TestFiles/Direct2D1/Controls/TextBlock/RestrictedHeight_VerticalAlign.expected.png create mode 100644 tests/TestFiles/Skia/Controls/TextBlock/RestrictedHeight_VerticalAlign.expected.png diff --git a/tests/Avalonia.RenderTests/Controls/TextBlockTests.cs b/tests/Avalonia.RenderTests/Controls/TextBlockTests.cs index ab769e4ff0..53a2959848 100644 --- a/tests/Avalonia.RenderTests/Controls/TextBlockTests.cs +++ b/tests/Avalonia.RenderTests/Controls/TextBlockTests.cs @@ -40,5 +40,59 @@ namespace Avalonia.Direct2D1.RenderTests.Controls await RenderToFile(target); CompareImages(); } + + + [Win32Fact("Has text")] + public async Task RestrictedHeight_VerticalAlign() + { + IControl text(VerticalAlignment verticalAlingnment, bool clip = true, bool restrictHeight = true) + { + return new Border() + { + BorderBrush = Brushes.Blue, + BorderThickness = new Thickness(1), + VerticalAlignment = VerticalAlignment.Center, + HorizontalAlignment = HorizontalAlignment.Center, + Height = restrictHeight ? 20 : double.NaN, + Margin = new Thickness(1), + Child = new TextBlock + { + FontFamily = new FontFamily("Courier New"), + Background = Brushes.Red, + FontSize = 24, + Foreground = Brushes.Black, + Text = "L", + VerticalAlignment = verticalAlingnment, + ClipToBounds = clip + } + }; + } + Decorator target = new Decorator + { + Padding = new Thickness(8), + Width = 180, + Height = 80, + + Child = new StackPanel() + { + Orientation = Orientation.Horizontal, + Children = + { + text(VerticalAlignment.Stretch, restrictHeight: false), + text(VerticalAlignment.Center), + text(VerticalAlignment.Stretch), + text(VerticalAlignment.Top), + text(VerticalAlignment.Bottom), + text(VerticalAlignment.Center, clip:false), + text(VerticalAlignment.Stretch, clip:false), + text(VerticalAlignment.Top, clip:false), + text(VerticalAlignment.Bottom, clip:false), + } + } + }; + + await RenderToFile(target); + CompareImages(); + } } } diff --git a/tests/TestFiles/Direct2D1/Controls/TextBlock/RestrictedHeight_VerticalAlign.expected.png b/tests/TestFiles/Direct2D1/Controls/TextBlock/RestrictedHeight_VerticalAlign.expected.png new file mode 100644 index 0000000000000000000000000000000000000000..c5a0a14e52616d76ebd7926248e785e0c6b42296 GIT binary patch literal 527 zcmeAS@N?(olHy`uVBq!ia0vp^TYxx#gAGV-kceLfq*#ibJVQ8upoSx*gMoqZn5T}U;+IFz$-)-2Qso+}Sug{{q>EZbaGG{*& z^BrhqNHVFa5_;F;p$aq=4P+N;Sm#Ql+4(;Fe8A?um%ofx_5WVyv^uebmhOAP3E}(H zCG9Noq|YTwv?afjs6ErKopYshQv6nS-E$W{D;@W4TQ~J+@8*An?jwXI=Mg#)U&G&X+8f+7-6YKb)<8(jSY;J4LA* zLS7lie%u!OY5#?jJ6KrO-q@BLY*L~g?)mTQydzD%YtOHe-W9g&{YH-6{+~*gZH#}j z(QdKPmrGYpeTj~h269&aYirvscK^brXV0%Z-@4hfWUbTo6SKC?Njp1RW&h{GZ);p@ z!i5)L7|fua=M~7lo_83w~vya^yjSMfh`j0J+JDUAFAD)x=QqT z_~xVcen?B5^9CAdVlq2uPwsR5y=Y<0z|in+9^)@(Q)>rl$*mwsPgg&ebxsLQ0Q>~$ ATmS$7 literal 0 HcmV?d00001 diff --git a/tests/TestFiles/Skia/Controls/TextBlock/RestrictedHeight_VerticalAlign.expected.png b/tests/TestFiles/Skia/Controls/TextBlock/RestrictedHeight_VerticalAlign.expected.png new file mode 100644 index 0000000000000000000000000000000000000000..c5a0a14e52616d76ebd7926248e785e0c6b42296 GIT binary patch literal 527 zcmeAS@N?(olHy`uVBq!ia0vp^TYxx#gAGV-kceLfq*#ibJVQ8upoSx*gMoqZn5T}U;+IFz$-)-2Qso+}Sug{{q>EZbaGG{*& z^BrhqNHVFa5_;F;p$aq=4P+N;Sm#Ql+4(;Fe8A?um%ofx_5WVyv^uebmhOAP3E}(H zCG9Noq|YTwv?afjs6ErKopYshQv6nS-E$W{D;@W4TQ~J+@8*An?jwXI=Mg#)U&G&X+8f+7-6YKb)<8(jSY;J4LA* zLS7lie%u!OY5#?jJ6KrO-q@BLY*L~g?)mTQydzD%YtOHe-W9g&{YH-6{+~*gZH#}j z(QdKPmrGYpeTj~h269&aYirvscK^brXV0%Z-@4hfWUbTo6SKC?Njp1RW&h{GZ);p@ z!i5)L7|fua=M~7lo_83w~vya^yjSMfh`j0J+JDUAFAD)x=QqT z_~xVcen?B5^9CAdVlq2uPwsR5y=Y<0z|in+9^)@(Q)>rl$*mwsPgg&ebxsLQ0Q>~$ ATmS$7 literal 0 HcmV?d00001 From dda966676c62932cc3d92a53a0430d03cb3296eb Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Fri, 16 Oct 2020 15:38:43 +0300 Subject: [PATCH 66/75] fix Textblock text alignment with restricted height #4866 --- src/Avalonia.Controls/TextBlock.cs | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/TextBlock.cs b/src/Avalonia.Controls/TextBlock.cs index d61519e697..31517ba59d 100644 --- a/src/Avalonia.Controls/TextBlock.cs +++ b/src/Avalonia.Controls/TextBlock.cs @@ -3,6 +3,7 @@ using Avalonia.LogicalTree; using Avalonia.Media; using Avalonia.Media.TextFormatting; using Avalonia.Metadata; +using Avalonia.Layout; namespace Avalonia.Controls { @@ -427,14 +428,32 @@ namespace Avalonia.Controls case TextAlignment.Center: offsetX = (width - TextLayout.Size.Width) / 2; break; + case TextAlignment.Right: - offsetX = width - TextLayout.Size.Width; + offsetX = width - TextLayout.Size.Width; break; } var padding = Padding; - using (context.PushPostTransform(Matrix.CreateTranslation(padding.Left + offsetX, padding.Top))) + var top = padding.Top; + var textSize = TextLayout.Size; + + if (Bounds.Height < textSize.Height) + { + switch (VerticalAlignment) + { + case VerticalAlignment.Center: + top += (Bounds.Height - textSize.Height) / 2; + break; + + case VerticalAlignment.Bottom: + top += (Bounds.Height - textSize.Height); + break; + } + } + + using (context.PushPostTransform(Matrix.CreateTranslation(padding.Left + offsetX, top))) { TextLayout.Draw(context); } From 1dc2b0b12a12542a95bfc40373cf28d44e8fc688 Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Fri, 16 Oct 2020 15:39:06 +0300 Subject: [PATCH 67/75] fix TextPresenter text alignment with restricted height #4866 --- .../Presenters/TextPresenter.cs | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Controls/Presenters/TextPresenter.cs b/src/Avalonia.Controls/Presenters/TextPresenter.cs index 6a6d37605d..078d8050bf 100644 --- a/src/Avalonia.Controls/Presenters/TextPresenter.cs +++ b/src/Avalonia.Controls/Presenters/TextPresenter.cs @@ -4,6 +4,7 @@ using Avalonia.Media; using Avalonia.Metadata; using Avalonia.Threading; using Avalonia.VisualTree; +using Avalonia.Layout; namespace Avalonia.Controls.Presenters { @@ -312,7 +313,24 @@ namespace Avalonia.Controls.Presenters context.FillRectangle(background, new Rect(Bounds.Size)); } - context.DrawText(Foreground, new Point(), FormattedText); + double top = 0; + var textSize = FormattedText.Bounds.Size; + + if (Bounds.Height < textSize.Height) + { + switch (VerticalAlignment) + { + case VerticalAlignment.Center: + top += (Bounds.Height - textSize.Height) / 2; + break; + + case VerticalAlignment.Bottom: + top += (Bounds.Height - textSize.Height); + break; + } + } + + context.DrawText(Foreground, new Point(0, top), FormattedText); } public override void Render(DrawingContext context) From 32b8cc811c087ddd8cda77668a7babed025b5093 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 20 Oct 2020 15:46:06 +0100 Subject: [PATCH 68/75] pass surfaceorigin to FboSkiaSurface. --- src/Skia/Avalonia.Skia/DrawingContextImpl.cs | 7 ++++++- src/Skia/Avalonia.Skia/Gpu/ISkiaGpu.cs | 2 +- src/Skia/Avalonia.Skia/Gpu/ISkiaGpuRenderSession.cs | 2 ++ src/Skia/Avalonia.Skia/Gpu/OpenGl/FboSkiaSurface.cs | 4 ++-- src/Skia/Avalonia.Skia/Gpu/OpenGl/GlRenderTarget.cs | 4 ++++ src/Skia/Avalonia.Skia/Gpu/OpenGl/GlSkiaGpu.cs | 4 ++-- src/Skia/Avalonia.Skia/Gpu/SkiaGpuRenderTarget.cs | 3 ++- src/Skia/Avalonia.Skia/PlatformRenderInterface.cs | 2 +- src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs | 6 +++--- 9 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs index cbc896813f..dac284ce1a 100644 --- a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs +++ b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs @@ -36,6 +36,7 @@ namespace Avalonia.Skia private readonly SKPaint _fillPaint = new SKPaint(); private readonly SKPaint _boxShadowPaint = new SKPaint(); private static SKShader s_acrylicNoiseShader; + private readonly GRSurfaceOrigin _surfaceOrigin; /// /// Context create info. @@ -76,6 +77,8 @@ namespace Avalonia.Skia /// Skia GPU provider context (optional) /// public ISkiaGpu Gpu; + + public ISkiaGpuRenderSession CurrentSession; } /// @@ -96,6 +99,8 @@ namespace Avalonia.Skia Surface = createInfo.Surface; Canvas = createInfo.Canvas ?? createInfo.Surface?.Canvas; + _surfaceOrigin = createInfo.CurrentSession?.SurfaceOrigin ?? GRSurfaceOrigin.TopLeft; + if (Canvas == null) { throw new ArgumentException("Invalid create info - no Canvas provided", nameof(createInfo)); @@ -972,7 +977,7 @@ namespace Avalonia.Skia Gpu = _gpu }; - return new SurfaceRenderTarget(createInfo); + return new SurfaceRenderTarget(createInfo, _surfaceOrigin); } /// diff --git a/src/Skia/Avalonia.Skia/Gpu/ISkiaGpu.cs b/src/Skia/Avalonia.Skia/Gpu/ISkiaGpu.cs index 869c261f1b..7442f90ecf 100644 --- a/src/Skia/Avalonia.Skia/Gpu/ISkiaGpu.cs +++ b/src/Skia/Avalonia.Skia/Gpu/ISkiaGpu.cs @@ -21,7 +21,7 @@ namespace Avalonia.Skia /// Creates an offscreen render target surface /// /// size in pixels - ISkiaSurface TryCreateSurface(PixelSize size); + ISkiaSurface TryCreateSurface(PixelSize size, GRSurfaceOrigin surfaceOrigin); } public interface ISkiaSurface : IDisposable diff --git a/src/Skia/Avalonia.Skia/Gpu/ISkiaGpuRenderSession.cs b/src/Skia/Avalonia.Skia/Gpu/ISkiaGpuRenderSession.cs index a4e2bfed52..5faa6a41ec 100644 --- a/src/Skia/Avalonia.Skia/Gpu/ISkiaGpuRenderSession.cs +++ b/src/Skia/Avalonia.Skia/Gpu/ISkiaGpuRenderSession.cs @@ -22,5 +22,7 @@ namespace Avalonia.Skia /// Scaling factor. /// double ScaleFactor { get; } + + GRSurfaceOrigin SurfaceOrigin { get; } } } diff --git a/src/Skia/Avalonia.Skia/Gpu/OpenGl/FboSkiaSurface.cs b/src/Skia/Avalonia.Skia/Gpu/OpenGl/FboSkiaSurface.cs index 24464c39d9..8ab275df63 100644 --- a/src/Skia/Avalonia.Skia/Gpu/OpenGl/FboSkiaSurface.cs +++ b/src/Skia/Avalonia.Skia/Gpu/OpenGl/FboSkiaSurface.cs @@ -14,7 +14,7 @@ namespace Avalonia.Skia private int _texture; private static readonly bool[] TrueFalse = new[] { true, false }; - public FboSkiaSurface(GRContext grContext, IGlContext glContext, PixelSize pixelSize) + public FboSkiaSurface(GRContext grContext, IGlContext glContext, PixelSize pixelSize, GRSurfaceOrigin surfaceOrigin) { _grContext = grContext; _glContext = glContext; @@ -93,7 +93,7 @@ namespace Avalonia.Skia var target = new GRBackendRenderTarget(pixelSize.Width, pixelSize.Height, 0, 8, new GRGlFramebufferInfo((uint)_fbo, SKColorType.Rgba8888.ToGlSizedFormat())); Surface = SKSurface.Create(_grContext, target, - GRSurfaceOrigin.TopLeft, SKColorType.Rgba8888); + surfaceOrigin, SKColorType.Rgba8888); CanBlit = gl.BlitFramebuffer != null; } diff --git a/src/Skia/Avalonia.Skia/Gpu/OpenGl/GlRenderTarget.cs b/src/Skia/Avalonia.Skia/Gpu/OpenGl/GlRenderTarget.cs index e109922a3f..b4c5619c85 100644 --- a/src/Skia/Avalonia.Skia/Gpu/OpenGl/GlRenderTarget.cs +++ b/src/Skia/Avalonia.Skia/Gpu/OpenGl/GlRenderTarget.cs @@ -39,6 +39,8 @@ namespace Avalonia.Skia _backendRenderTarget = backendRenderTarget; _surface = surface; _glSession = glSession; + + SurfaceOrigin = glSession.IsYFlipped ? GRSurfaceOrigin.TopLeft : GRSurfaceOrigin.BottomLeft; } public void Dispose() { @@ -48,6 +50,8 @@ namespace Avalonia.Skia GrContext.Flush(); _glSession.Dispose(); } + + public GRSurfaceOrigin SurfaceOrigin { get; } public GRContext GrContext { get; } public SKSurface SkSurface => _surface; diff --git a/src/Skia/Avalonia.Skia/Gpu/OpenGl/GlSkiaGpu.cs b/src/Skia/Avalonia.Skia/Gpu/OpenGl/GlSkiaGpu.cs index c02d813e24..02e3766d40 100644 --- a/src/Skia/Avalonia.Skia/Gpu/OpenGl/GlSkiaGpu.cs +++ b/src/Skia/Avalonia.Skia/Gpu/OpenGl/GlSkiaGpu.cs @@ -47,7 +47,7 @@ namespace Avalonia.Skia return null; } - public ISkiaSurface TryCreateSurface(PixelSize size) + public ISkiaSurface TryCreateSurface(PixelSize size, GRSurfaceOrigin surfaceOrigin) { // Only windows platform needs our FBO trickery if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) @@ -62,7 +62,7 @@ namespace Avalonia.Skia return null; try { - var surface = new FboSkiaSurface(_grContext, _glContext, size); + var surface = new FboSkiaSurface(_grContext, _glContext, size, surfaceOrigin); _canCreateSurfaces = true; return surface; } diff --git a/src/Skia/Avalonia.Skia/Gpu/SkiaGpuRenderTarget.cs b/src/Skia/Avalonia.Skia/Gpu/SkiaGpuRenderTarget.cs index 9992c9ba8c..6626546c0c 100644 --- a/src/Skia/Avalonia.Skia/Gpu/SkiaGpuRenderTarget.cs +++ b/src/Skia/Avalonia.Skia/Gpu/SkiaGpuRenderTarget.cs @@ -33,7 +33,8 @@ namespace Avalonia.Skia Dpi = SkiaPlatform.DefaultDpi * session.ScaleFactor, VisualBrushRenderer = visualBrushRenderer, DisableTextLcdRendering = true, - Gpu = _skiaGpu + Gpu = _skiaGpu, + CurrentSession = session }; return new DrawingContextImpl(nfo, session); diff --git a/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs b/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs index d6f76a2c20..6048482110 100644 --- a/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs +++ b/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs @@ -127,7 +127,7 @@ namespace Avalonia.Skia DisableTextLcdRendering = false }; - return new SurfaceRenderTarget(createInfo); + return new SurfaceRenderTarget(createInfo, GRSurfaceOrigin.TopLeft); } /// diff --git a/src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs b/src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs index 61b599a731..905c9160a7 100644 --- a/src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs +++ b/src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs @@ -42,7 +42,7 @@ namespace Avalonia.Skia /// Create new surface render target. /// /// Create info. - public SurfaceRenderTarget(CreateInfo createInfo) + public SurfaceRenderTarget(CreateInfo createInfo, GRSurfaceOrigin surfaceOrigin) { PixelSize = new PixelSize(createInfo.Width, createInfo.Height); Dpi = createInfo.Dpi; @@ -51,7 +51,7 @@ namespace Avalonia.Skia _grContext = createInfo.GrContext; _gpu = createInfo.Gpu; - _surface = _gpu?.TryCreateSurface(PixelSize); + _surface = _gpu?.TryCreateSurface(PixelSize, surfaceOrigin); if (_surface == null) _surface = new SkiaSurfaceWrapper(CreateSurface(createInfo.GrContext, PixelSize.Width, PixelSize.Height, createInfo.Format)); @@ -100,7 +100,7 @@ namespace Avalonia.Skia VisualBrushRenderer = visualBrushRenderer, DisableTextLcdRendering = _disableLcdRendering, GrContext = _grContext, - Gpu = _gpu + Gpu = _gpu, }; return new DrawingContextImpl(createInfo, Disposable.Create(() => Version++)); From d218e2be2074a39cc0348c90c2cfe7334fdab73b Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 20 Oct 2020 20:32:32 +0100 Subject: [PATCH 69/75] dont save surfaceorigin as a field of drawing context. --- src/Skia/Avalonia.Skia/DrawingContextImpl.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs index dac284ce1a..136b14140e 100644 --- a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs +++ b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs @@ -36,7 +36,7 @@ namespace Avalonia.Skia private readonly SKPaint _fillPaint = new SKPaint(); private readonly SKPaint _boxShadowPaint = new SKPaint(); private static SKShader s_acrylicNoiseShader; - private readonly GRSurfaceOrigin _surfaceOrigin; + private readonly ISkiaGpuRenderSession _session; /// /// Context create info. @@ -99,7 +99,7 @@ namespace Avalonia.Skia Surface = createInfo.Surface; Canvas = createInfo.Canvas ?? createInfo.Surface?.Canvas; - _surfaceOrigin = createInfo.CurrentSession?.SurfaceOrigin ?? GRSurfaceOrigin.TopLeft; + _session = createInfo.CurrentSession; if (Canvas == null) { @@ -977,7 +977,7 @@ namespace Avalonia.Skia Gpu = _gpu }; - return new SurfaceRenderTarget(createInfo, _surfaceOrigin); + return new SurfaceRenderTarget(createInfo, _session?.SurfaceOrigin ?? GRSurfaceOrigin.TopLeft); } /// From ce08964f0371452ce8301cd2206d6e32f295982f Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Tue, 20 Oct 2020 20:34:51 +0100 Subject: [PATCH 70/75] refactor how surface origin is passed. --- src/Skia/Avalonia.Skia/DrawingContextImpl.cs | 5 +++-- src/Skia/Avalonia.Skia/PlatformRenderInterface.cs | 2 +- src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs | 6 ++++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs index 136b14140e..98692b7483 100644 --- a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs +++ b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs @@ -974,10 +974,11 @@ namespace Avalonia.Skia Format = format, DisableTextLcdRendering = !_canTextUseLcdRendering, GrContext = _grContext, - Gpu = _gpu + Gpu = _gpu, + SurfaceOrigin = _session?.SurfaceOrigin ?? GRSurfaceOrigin.TopLeft }; - return new SurfaceRenderTarget(createInfo, _session?.SurfaceOrigin ?? GRSurfaceOrigin.TopLeft); + return new SurfaceRenderTarget(createInfo); } /// diff --git a/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs b/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs index 6048482110..d6f76a2c20 100644 --- a/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs +++ b/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs @@ -127,7 +127,7 @@ namespace Avalonia.Skia DisableTextLcdRendering = false }; - return new SurfaceRenderTarget(createInfo, GRSurfaceOrigin.TopLeft); + return new SurfaceRenderTarget(createInfo); } /// diff --git a/src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs b/src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs index 905c9160a7..d3d4515689 100644 --- a/src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs +++ b/src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs @@ -42,7 +42,7 @@ namespace Avalonia.Skia /// Create new surface render target. /// /// Create info. - public SurfaceRenderTarget(CreateInfo createInfo, GRSurfaceOrigin surfaceOrigin) + public SurfaceRenderTarget(CreateInfo createInfo) { PixelSize = new PixelSize(createInfo.Width, createInfo.Height); Dpi = createInfo.Dpi; @@ -51,7 +51,7 @@ namespace Avalonia.Skia _grContext = createInfo.GrContext; _gpu = createInfo.Gpu; - _surface = _gpu?.TryCreateSurface(PixelSize, surfaceOrigin); + _surface = _gpu?.TryCreateSurface(PixelSize, createInfo.SurfaceOrigin); if (_surface == null) _surface = new SkiaSurfaceWrapper(CreateSurface(createInfo.GrContext, PixelSize.Width, PixelSize.Height, createInfo.Format)); @@ -218,6 +218,8 @@ namespace Avalonia.Skia public GRContext GrContext; public ISkiaGpu Gpu; + + public GRSurfaceOrigin SurfaceOrigin; } } } From c7908d98c275e61ae34f2e59d28d1505d661e10d Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Wed, 21 Oct 2020 15:30:52 +0100 Subject: [PATCH 71/75] pass session down TryCreateSurface. --- src/Skia/Avalonia.Skia/DrawingContextImpl.cs | 2 +- src/Skia/Avalonia.Skia/Gpu/ISkiaGpu.cs | 2 +- src/Skia/Avalonia.Skia/Gpu/OpenGl/GlSkiaGpu.cs | 4 ++-- src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs index 98692b7483..a32b3327c2 100644 --- a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs +++ b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs @@ -975,7 +975,7 @@ namespace Avalonia.Skia DisableTextLcdRendering = !_canTextUseLcdRendering, GrContext = _grContext, Gpu = _gpu, - SurfaceOrigin = _session?.SurfaceOrigin ?? GRSurfaceOrigin.TopLeft + Session = _session }; return new SurfaceRenderTarget(createInfo); diff --git a/src/Skia/Avalonia.Skia/Gpu/ISkiaGpu.cs b/src/Skia/Avalonia.Skia/Gpu/ISkiaGpu.cs index 7442f90ecf..aa86df7c23 100644 --- a/src/Skia/Avalonia.Skia/Gpu/ISkiaGpu.cs +++ b/src/Skia/Avalonia.Skia/Gpu/ISkiaGpu.cs @@ -21,7 +21,7 @@ namespace Avalonia.Skia /// Creates an offscreen render target surface /// /// size in pixels - ISkiaSurface TryCreateSurface(PixelSize size, GRSurfaceOrigin surfaceOrigin); + ISkiaSurface TryCreateSurface(PixelSize size, ISkiaGpuRenderSession session); } public interface ISkiaSurface : IDisposable diff --git a/src/Skia/Avalonia.Skia/Gpu/OpenGl/GlSkiaGpu.cs b/src/Skia/Avalonia.Skia/Gpu/OpenGl/GlSkiaGpu.cs index 02e3766d40..a393f0b64d 100644 --- a/src/Skia/Avalonia.Skia/Gpu/OpenGl/GlSkiaGpu.cs +++ b/src/Skia/Avalonia.Skia/Gpu/OpenGl/GlSkiaGpu.cs @@ -47,7 +47,7 @@ namespace Avalonia.Skia return null; } - public ISkiaSurface TryCreateSurface(PixelSize size, GRSurfaceOrigin surfaceOrigin) + public ISkiaSurface TryCreateSurface(PixelSize size, ISkiaGpuRenderSession session) { // Only windows platform needs our FBO trickery if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) @@ -62,7 +62,7 @@ namespace Avalonia.Skia return null; try { - var surface = new FboSkiaSurface(_grContext, _glContext, size, surfaceOrigin); + var surface = new FboSkiaSurface(_grContext, _glContext, size, session?.SurfaceOrigin ?? GRSurfaceOrigin.TopLeft); _canCreateSurfaces = true; return surface; } diff --git a/src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs b/src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs index d3d4515689..6347c64aed 100644 --- a/src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs +++ b/src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs @@ -51,7 +51,7 @@ namespace Avalonia.Skia _grContext = createInfo.GrContext; _gpu = createInfo.Gpu; - _surface = _gpu?.TryCreateSurface(PixelSize, createInfo.SurfaceOrigin); + _surface = _gpu?.TryCreateSurface(PixelSize, createInfo.Session); if (_surface == null) _surface = new SkiaSurfaceWrapper(CreateSurface(createInfo.GrContext, PixelSize.Width, PixelSize.Height, createInfo.Format)); @@ -219,7 +219,7 @@ namespace Avalonia.Skia public ISkiaGpu Gpu; - public GRSurfaceOrigin SurfaceOrigin; + public ISkiaGpuRenderSession Session; } } } From 5f3ba2008f35cf0150e03a5089230e5192ceb790 Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 22 Oct 2020 17:26:41 +0100 Subject: [PATCH 72/75] fix splitview by making it use contentpresenter, templates and hve its children be logical children. --- src/Avalonia.Controls/ApiCompatBaseline.txt | 8 ++- src/Avalonia.Controls/SplitView.cs | 54 +++++++++++++-------- src/Avalonia.Dialogs/ApiCompatBaseline.txt | 1 + src/Avalonia.Themes.Default/SplitView.xaml | 8 +-- src/Avalonia.Themes.Fluent/SplitView.xaml | 8 +-- 5 files changed, 50 insertions(+), 29 deletions(-) create mode 100644 src/Avalonia.Dialogs/ApiCompatBaseline.txt diff --git a/src/Avalonia.Controls/ApiCompatBaseline.txt b/src/Avalonia.Controls/ApiCompatBaseline.txt index af88c569a6..16c801201c 100644 --- a/src/Avalonia.Controls/ApiCompatBaseline.txt +++ b/src/Avalonia.Controls/ApiCompatBaseline.txt @@ -8,6 +8,12 @@ MembersMustExist : Member 'public void Avalonia.Controls.ListBox.Selection.set(A TypesMustExist : Type 'Avalonia.Controls.SelectionModel' does not exist in the implementation but it does exist in the contract. TypesMustExist : Type 'Avalonia.Controls.SelectionModelChildrenRequestedEventArgs' does not exist in the implementation but it does exist in the contract. TypesMustExist : Type 'Avalonia.Controls.SelectionModelSelectionChangedEventArgs' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'public Avalonia.StyledProperty Avalonia.StyledProperty Avalonia.Controls.SplitView.ContentProperty' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'public Avalonia.StyledProperty Avalonia.StyledProperty Avalonia.Controls.SplitView.PaneProperty' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'public Avalonia.Controls.IControl Avalonia.Controls.SplitView.Content.get()' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'public void Avalonia.Controls.SplitView.Content.set(Avalonia.Controls.IControl)' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'public Avalonia.Controls.IControl Avalonia.Controls.SplitView.Pane.get()' does not exist in the implementation but it does exist in the contract. +MembersMustExist : Member 'public void Avalonia.Controls.SplitView.Pane.set(Avalonia.Controls.IControl)' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'public Avalonia.DirectProperty Avalonia.DirectProperty Avalonia.Controls.TreeView.SelectionProperty' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'public Avalonia.Interactivity.RoutedEvent Avalonia.Interactivity.RoutedEvent Avalonia.Controls.TreeView.SelectionChangedEvent' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'public Avalonia.Controls.ISelectionModel Avalonia.Controls.TreeView.Selection.get()' does not exist in the implementation but it does exist in the contract. @@ -17,4 +23,4 @@ InterfacesShouldHaveSameMembers : Interface member 'public System.String[] Avalo MembersMustExist : Member 'public Avalonia.DirectProperty Avalonia.DirectProperty Avalonia.Controls.Primitives.SelectingItemsControl.SelectionProperty' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'protected Avalonia.Controls.ISelectionModel Avalonia.Controls.Primitives.SelectingItemsControl.Selection.get()' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'protected void Avalonia.Controls.Primitives.SelectingItemsControl.Selection.set(Avalonia.Controls.ISelectionModel)' does not exist in the implementation but it does exist in the contract. -Total Issues: 18 +Total Issues: 24 diff --git a/src/Avalonia.Controls/SplitView.cs b/src/Avalonia.Controls/SplitView.cs index 8267efc466..4500d52484 100644 --- a/src/Avalonia.Controls/SplitView.cs +++ b/src/Avalonia.Controls/SplitView.cs @@ -9,6 +9,8 @@ using Avalonia.Platform; using Avalonia.VisualTree; using System; using System.Reactive.Disposables; +using Avalonia.Controls.Presenters; +using Avalonia.Controls.Templates; namespace Avalonia.Controls { @@ -78,7 +80,7 @@ namespace Avalonia.Controls [PseudoClasses(":compactoverlay", ":compactinline", ":overlay", ":inline")] [PseudoClasses(":left", ":right")] [PseudoClasses(":lightdismiss")] - public class SplitView : TemplatedControl + public class SplitView : ContentControl { /* Pseudo classes & combos @@ -87,12 +89,6 @@ namespace Avalonia.Controls :left :right */ - /// - /// Defines the property - /// - public static readonly StyledProperty ContentProperty = - AvaloniaProperty.Register(nameof(Content)); - /// /// Defines the property /// @@ -133,8 +129,14 @@ namespace Avalonia.Controls /// /// Defines the property /// - public static readonly StyledProperty PaneProperty = - AvaloniaProperty.Register(nameof(Pane)); + public static readonly StyledProperty PaneProperty = + AvaloniaProperty.Register(nameof(Pane)); + + /// + /// Defines the property. + /// + public static readonly StyledProperty PaneTemplateProperty = + AvaloniaProperty.Register(nameof(PaneTemplate)); /// /// Defines the property @@ -166,16 +168,7 @@ namespace Avalonia.Controls CompactPaneLengthProperty.Changed.AddClassHandler((x, v) => x.OnCompactPaneLengthChanged(v)); PanePlacementProperty.Changed.AddClassHandler((x, v) => x.OnPanePlacementChanged(v)); DisplayModeProperty.Changed.AddClassHandler((x, v) => x.OnDisplayModeChanged(v)); - } - - /// - /// Gets or sets the content of the SplitView - /// - [Content] - public IControl Content - { - get => GetValue(ContentProperty); - set => SetValue(ContentProperty, value); + } /// @@ -265,11 +258,20 @@ namespace Avalonia.Controls /// /// Gets or sets the Pane for the SplitView /// - public IControl Pane + public object Pane { get => GetValue(PaneProperty); set => SetValue(PaneProperty, value); } + + /// + /// Gets or sets the data template used to display the header content of the control. + /// + public IDataTemplate? PaneTemplate + { + get => GetValue(PaneTemplateProperty); + set => SetValue(PaneTemplateProperty, value); + } /// /// Gets or sets whether WinUI equivalent LightDismissOverlayMode is enabled @@ -312,6 +314,18 @@ namespace Avalonia.Controls /// public event EventHandler PaneOpening; + protected override bool RegisterContentPresenter(IContentPresenter presenter) + { + var result = base.RegisterContentPresenter(presenter); + + if (presenter.Name == "PART_PanePresenter") + { + return true; + } + + return result; + } + protected override void OnApplyTemplate(TemplateAppliedEventArgs e) { base.OnApplyTemplate(e); diff --git a/src/Avalonia.Dialogs/ApiCompatBaseline.txt b/src/Avalonia.Dialogs/ApiCompatBaseline.txt new file mode 100644 index 0000000000..fcc74cf864 --- /dev/null +++ b/src/Avalonia.Dialogs/ApiCompatBaseline.txt @@ -0,0 +1 @@ +Total Issues: 0 diff --git a/src/Avalonia.Themes.Default/SplitView.xaml b/src/Avalonia.Themes.Default/SplitView.xaml index 2fb59cdbc4..18da3edb46 100644 --- a/src/Avalonia.Themes.Default/SplitView.xaml +++ b/src/Avalonia.Themes.Default/SplitView.xaml @@ -32,12 +32,12 @@ ClipToBounds="True" HorizontalAlignment="Left" ZIndex="100"> - + - + @@ -106,14 +106,14 @@ ClipToBounds="True" HorizontalAlignment="Right" ZIndex="100"> - + - + diff --git a/src/Avalonia.Themes.Fluent/SplitView.xaml b/src/Avalonia.Themes.Fluent/SplitView.xaml index 71e92459f1..7d6f7a9b9a 100644 --- a/src/Avalonia.Themes.Fluent/SplitView.xaml +++ b/src/Avalonia.Themes.Fluent/SplitView.xaml @@ -32,12 +32,12 @@ ClipToBounds="True" HorizontalAlignment="Left" ZIndex="100"> - + - + @@ -106,14 +106,14 @@ ClipToBounds="True" HorizontalAlignment="Right" ZIndex="100"> - + - + From ba6bf035623ae99e7e2b5a9ddef625e3b4a0a05a Mon Sep 17 00:00:00 2001 From: Dan Walmsley Date: Thu, 22 Oct 2020 17:46:33 +0100 Subject: [PATCH 73/75] dont use apartments. --- src/Windows/Avalonia.Win32/Composition/CompositionConnector.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Windows/Avalonia.Win32/Composition/CompositionConnector.cs b/src/Windows/Avalonia.Win32/Composition/CompositionConnector.cs index 3929dc07bf..fc18b623bf 100644 --- a/src/Windows/Avalonia.Win32/Composition/CompositionConnector.cs +++ b/src/Windows/Avalonia.Win32/Composition/CompositionConnector.cs @@ -130,7 +130,7 @@ namespace Avalonia.Win32 if (_dispatcherQueueController == null) { DispatcherQueueOptions options = new DispatcherQueueOptions(); - options.apartmentType = DISPATCHERQUEUE_THREAD_APARTMENTTYPE.DQTAT_COM_STA; + options.apartmentType = DISPATCHERQUEUE_THREAD_APARTMENTTYPE.DQTAT_COM_NONE; options.threadType = DISPATCHERQUEUE_THREAD_TYPE.DQTYPE_THREAD_CURRENT; options.dwSize = Marshal.SizeOf(typeof(DispatcherQueueOptions)); From 0cdb2202bfcb402dd831c86f6324712539c19d18 Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Fri, 23 Oct 2020 10:31:12 +0300 Subject: [PATCH 74/75] macos fix crash on popup close #4293 --- native/Avalonia.Native/src/OSX/window.mm | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/native/Avalonia.Native/src/OSX/window.mm b/native/Avalonia.Native/src/OSX/window.mm index fb945a105e..67b1ea50a6 100644 --- a/native/Avalonia.Native/src/OSX/window.mm +++ b/native/Avalonia.Native/src/OSX/window.mm @@ -1338,6 +1338,12 @@ NSArray* AllLoopModes = [NSArray arrayWithObjects: NSDefaultRunLoopMode, NSEvent } _parent->BaseEvents->RunRenderPriorityJobs(); + + if (_parent == nullptr) + { + return; + } + _parent->BaseEvents->Paint(); } From 6b0ff56202f85e747b0de85de4394f8577230a42 Mon Sep 17 00:00:00 2001 From: Andrey Kunchev Date: Fri, 23 Oct 2020 13:18:02 +0300 Subject: [PATCH 75/75] fix dragging in datagrid --- src/Avalonia.Controls.DataGrid/DataGridColumnHeader.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Avalonia.Controls.DataGrid/DataGridColumnHeader.cs b/src/Avalonia.Controls.DataGrid/DataGridColumnHeader.cs index 77f23392e9..7f8d205949 100644 --- a/src/Avalonia.Controls.DataGrid/DataGridColumnHeader.cs +++ b/src/Avalonia.Controls.DataGrid/DataGridColumnHeader.cs @@ -438,7 +438,7 @@ namespace Avalonia.Controls _lastMousePositionHeaders = mousePositionHeaders; - if (args.Pointer.Captured != this) + if (args.Pointer.Captured != this && _dragMode == DragMode.Drag) args.Pointer.Capture(this); SetDragCursor(mousePosition);