From da0af790b15c62bb8d5f2e94ca6b3c904a79b4a2 Mon Sep 17 00:00:00 2001 From: lindexi Date: Thu, 26 Feb 2026 17:17:42 +0800 Subject: [PATCH 01/12] Adding TransparencyLevel property to CompositionTarget --- .../CompositionTransparencyLevel.cs | 10 +++++++++ src/Avalonia.Base/composition-schema.xml | 1 + src/Avalonia.Controls/TopLevel.cs | 21 +++++++++++++++++-- 3 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 src/Avalonia.Base/Rendering/Composition/CompositionTransparencyLevel.cs diff --git a/src/Avalonia.Base/Rendering/Composition/CompositionTransparencyLevel.cs b/src/Avalonia.Base/Rendering/Composition/CompositionTransparencyLevel.cs new file mode 100644 index 0000000000..fd2abd75ee --- /dev/null +++ b/src/Avalonia.Base/Rendering/Composition/CompositionTransparencyLevel.cs @@ -0,0 +1,10 @@ +namespace Avalonia.Rendering.Composition; + +public enum CompositionTransparencyLevel : byte +{ + None = 0, + Transparent = 1, + Blur = 2, + AcrylicBlur = 3, + Mica = 4 +} diff --git a/src/Avalonia.Base/composition-schema.xml b/src/Avalonia.Base/composition-schema.xml index febf465042..7435e43e44 100644 --- a/src/Avalonia.Base/composition-schema.xml +++ b/src/Avalonia.Base/composition-schema.xml @@ -58,6 +58,7 @@ + diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index 5cf1a5b71a..0f20b00ed2 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -199,9 +199,11 @@ namespace Avalonia.Controls _scaling = ValidateScaling(impl.RenderScaling); _actualTransparencyLevel = PlatformImpl.TransparencyLevel; - - + _source.Renderer.CompositionTarget.TransparencyLevel = + ToCompositionTransparencyLevel(_actualTransparencyLevel); + + _accessKeyHandler = TryGetService(dependencyResolver); _inputManager = TryGetService(dependencyResolver); @@ -715,6 +717,8 @@ namespace Avalonia.Controls } ActualTransparencyLevel = transparencyLevel; + Renderer.CompositionTarget.TransparencyLevel = + ToCompositionTransparencyLevel(transparencyLevel); } protected override void OnApplyTemplate(TemplateAppliedEventArgs e) @@ -837,5 +841,18 @@ namespace Avalonia.Controls return scaling; } + + private static CompositionTransparencyLevel ToCompositionTransparencyLevel(WindowTransparencyLevel level) + { + if (level == WindowTransparencyLevel.Transparent) + return CompositionTransparencyLevel.Transparent; + if (level == WindowTransparencyLevel.Blur) + return CompositionTransparencyLevel.Blur; + if (level == WindowTransparencyLevel.AcrylicBlur) + return CompositionTransparencyLevel.AcrylicBlur; + if (level == WindowTransparencyLevel.Mica) + return CompositionTransparencyLevel.Mica; + return CompositionTransparencyLevel.None; + } } } From bd1daa633dc063ad4c917cbb69ebe85b72f001b8 Mon Sep 17 00:00:00 2001 From: lindexi Date: Fri, 27 Feb 2026 10:34:35 +0800 Subject: [PATCH 02/12] Try to pass the WindowTransparencyLevel to surface --- .../DirectCompositedWindowSurface.cs | 6 ++++++ src/Windows/Avalonia.Win32/IBlurHost.cs | 5 ++++- .../WinRT/Composition/WinUiCompositedWindow.cs | 6 ++++++ .../WinUiCompositedWindowSurface.cs | 9 +++++++++ src/Windows/Avalonia.Win32/WindowImpl.cs | 18 ++++++++++++++---- 5 files changed, 39 insertions(+), 5 deletions(-) diff --git a/src/Windows/Avalonia.Win32/DComposition/DirectCompositedWindowSurface.cs b/src/Windows/Avalonia.Win32/DComposition/DirectCompositedWindowSurface.cs index d0651e08ee..e1b0a87aaa 100644 --- a/src/Windows/Avalonia.Win32/DComposition/DirectCompositedWindowSurface.cs +++ b/src/Windows/Avalonia.Win32/DComposition/DirectCompositedWindowSurface.cs @@ -1,5 +1,6 @@ using System; using System.ComponentModel; +using Avalonia.Controls; using Avalonia.OpenGL.Egl; using Avalonia.Platform; using Avalonia.Win32.DirectX; @@ -43,6 +44,11 @@ internal class DirectCompositedWindowSurface : IDirect3D11TexturePlatformSurface _blurEffect = enable; // _window?.SetBlur(enable); } + + public void SetTransparencyLevel(WindowTransparencyLevel transparencyLevel) + { + + } } internal class DirectCompositedWindowRenderTarget : IDirect3D11TextureRenderTarget diff --git a/src/Windows/Avalonia.Win32/IBlurHost.cs b/src/Windows/Avalonia.Win32/IBlurHost.cs index fcaf58eaac..1b5dd9c9b4 100644 --- a/src/Windows/Avalonia.Win32/IBlurHost.cs +++ b/src/Windows/Avalonia.Win32/IBlurHost.cs @@ -1,4 +1,6 @@ -namespace Avalonia.Win32; +using Avalonia.Controls; + +namespace Avalonia.Win32; internal enum BlurEffect { @@ -14,4 +16,5 @@ internal interface ICompositionEffectsSurface bool IsBlurSupported(BlurEffect effect); void SetBlur(BlurEffect enable); + void SetTransparencyLevel(WindowTransparencyLevel transparencyLevel); } diff --git a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindow.cs b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindow.cs index d720e525d3..cfc5435783 100644 --- a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindow.cs +++ b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindow.cs @@ -1,6 +1,7 @@ using System; using System.Numerics; using System.Threading; +using Avalonia.Controls; using Avalonia.OpenGL.Egl; using Avalonia.Reactive; using MicroCom.Runtime; @@ -112,4 +113,9 @@ internal class WinUiCompositedWindow : IDisposable } } } + + public void SetTransparencyLevel(WindowTransparencyLevel transparencyLevel) + { + + } } diff --git a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs index 2addbc6524..0191ce6255 100644 --- a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs +++ b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs @@ -1,4 +1,5 @@ using System; +using Avalonia.Controls; using Avalonia.OpenGL.Egl; using Avalonia.Platform; using Avalonia.Win32.DirectX; @@ -50,6 +51,14 @@ namespace Avalonia.Win32.WinRT.Composition _blurEffect = enable; _window?.SetBlur(enable); } + + public void SetTransparencyLevel(WindowTransparencyLevel transparencyLevel) + { + _windowTransparencyLevel = transparencyLevel; + _window?.SetTransparencyLevel(transparencyLevel); + } + + private WindowTransparencyLevel _windowTransparencyLevel; } internal class WinUiCompositedWindowRenderTarget : IDirect3D11TextureRenderTarget diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 081c488cd4..373d072019 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -5,6 +5,7 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; + using Avalonia.Collections.Pooled; using Avalonia.Controls; using Avalonia.Controls.Platform; @@ -12,21 +13,23 @@ using Avalonia.Input; using Avalonia.Input.Platform; using Avalonia.Input.Raw; using Avalonia.Input.TextInput; +using Avalonia.Logging; using Avalonia.OpenGL.Egl; using Avalonia.Platform; using Avalonia.Platform.Storage; +using Avalonia.Platform.Storage.FileIO; using Avalonia.Rendering.Composition; +using Avalonia.Threading; using Avalonia.Win32.DirectX; using Avalonia.Win32.Input; using Avalonia.Win32.Interop; using Avalonia.Win32.OpenGl; using Avalonia.Win32.OpenGl.Angle; using Avalonia.Win32.WinRT.Composition; -using static Avalonia.Win32.Interop.UnmanagedMethods; -using Avalonia.Platform.Storage.FileIO; -using Avalonia.Threading; + using static Avalonia.Controls.Win32Properties; -using Avalonia.Logging; +using static Avalonia.Rendering.Composition.Animations.PropertySetSnapshot; +using static Avalonia.Win32.Interop.UnmanagedMethods; namespace Avalonia.Win32 { @@ -180,6 +183,7 @@ namespace Avalonia.Win32 _nativeControlHost = new Win32NativeControlHost(this, !UseRedirectionBitmap); _defaultTransparencyLevel = UseRedirectionBitmap ? WindowTransparencyLevel.None : WindowTransparencyLevel.Transparent; _transparencyLevel = _defaultTransparencyLevel; + SetTransparencyLevel(_transparencyLevel); lock (s_instances) s_instances.Add(this); @@ -321,6 +325,7 @@ namespace Avalonia.Win32 if (_transparencyLevel != value) { _transparencyLevel = value; + SetTransparencyLevel(value); TransparencyLevelChanged?.Invoke(value); } } @@ -506,6 +511,11 @@ namespace Avalonia.Win32 return result == 0; } + private void SetTransparencyLevel(WindowTransparencyLevel transparencyLevel) + { + CompositionEffectsSurface?.SetTransparencyLevel(transparencyLevel); + } + public IEnumerable Surfaces => _glSurface is null ? new object[] { Handle, _framebuffer } : From fe555d86689dd902dd377290598f199a297c1403 Mon Sep 17 00:00:00 2001 From: lindexi Date: Fri, 27 Feb 2026 15:58:48 +0800 Subject: [PATCH 03/12] Enable change the AlphaMode in WinUI window. --- .../Composition/WinUiCompositedWindow.cs | 6 +++- .../WinUiCompositedWindowSurface.cs | 35 +++++++++++++++---- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindow.cs b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindow.cs index cfc5435783..4bade8530a 100644 --- a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindow.cs +++ b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindow.cs @@ -114,8 +114,12 @@ internal class WinUiCompositedWindow : IDisposable } } + public bool IsTransparency => _transparencyLevel != WindowTransparencyLevel.None; + public void SetTransparencyLevel(WindowTransparencyLevel transparencyLevel) { - + _transparencyLevel = transparencyLevel; } + + private WindowTransparencyLevel _transparencyLevel; } diff --git a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs index 0191ce6255..b814395599 100644 --- a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs +++ b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs @@ -27,6 +27,7 @@ namespace Avalonia.Win32.WinRT.Composition ?.WinUICompositionBackdropCornerRadius; _window ??= new WinUiCompositedWindow(_info, _shared, cornerRadius); _window.SetBlur(_blurEffect); + _window.SetTransparencyLevel(_windowTransparencyLevel); return new WinUiCompositedWindowRenderTarget(context, _window, d3dDevice, _shared.Compositor); } @@ -72,11 +73,11 @@ namespace Avalonia.Win32.WinRT.Composition private readonly ICompositorInterop _interop; private readonly ICompositionGraphicsDevice _compositionDevice; private readonly ICompositionGraphicsDevice2 _compositionDevice2; - private readonly ICompositionSurface _surface; + private ICompositionSurface _surface; private PixelSize _size; private bool _lost; - private readonly ICompositionDrawingSurfaceInterop _surfaceInterop; - private readonly ICompositionDrawingSurface _drawingSurface; + private ICompositionDrawingSurfaceInterop _surfaceInterop; + private ICompositionDrawingSurface _drawingSurface; public WinUiCompositedWindowRenderTarget(IPlatformGraphicsContext context, WinUiCompositedWindow window, IntPtr device, @@ -92,10 +93,8 @@ namespace Avalonia.Win32.WinRT.Composition _interop = compositor.QueryInterface(); _compositionDevice = _interop.CreateGraphicsDevice(_d3dDevice); _compositionDevice2 = _compositionDevice.QueryInterface(); - _drawingSurface = _compositionDevice2.CreateDrawingSurface2(new UnmanagedMethods.SIZE(), - DirectXPixelFormat.B8G8R8A8UIntNormalized, DirectXAlphaMode.Premultiplied); - _surface = _drawingSurface.QueryInterface(); - _surfaceInterop = _drawingSurface.QueryInterface(); + + CreateSurface(window); } catch { @@ -111,6 +110,16 @@ namespace Avalonia.Win32.WinRT.Composition } } + private void CreateSurface(WinUiCompositedWindow window) + { + // Do not use Premultiplied when the window is not Transparency. Because the Premultiplied AlphaMode will increase the performance loss of DWM. See https://github.com/AvaloniaUI/Avalonia/issues/20643 + var alphaMode = window.IsTransparency ? DirectXAlphaMode.Premultiplied : DirectXAlphaMode.Ignore; + _drawingSurface = _compositionDevice2.CreateDrawingSurface2(new UnmanagedMethods.SIZE(), + DirectXPixelFormat.B8G8R8A8UIntNormalized, alphaMode); + _surface = _drawingSurface.QueryInterface(); + _surfaceInterop = _drawingSurface.QueryInterface(); + } + public void Dispose() { _surface.Dispose(); @@ -130,6 +139,18 @@ namespace Avalonia.Win32.WinRT.Composition if (IsCorrupted) throw new RenderTargetCorruptedException(); var transaction = _window.BeginTransaction(); + + var supportTransparency = _drawingSurface.AlphaMode == DirectXAlphaMode.Premultiplied; + if (_window.IsTransparency != supportTransparency) + { + // Re-create the surface with correct alpha mode if the transparency support is not correct. This can happen when the transparency level is changed. + _surface.Dispose(); + _surfaceInterop.Dispose(); + _drawingSurface.Dispose(); + + CreateSurface(_window); + } + bool needsEndDraw = false; try { From 133a1847924b5287358cf6ad053dc031485f61f9 Mon Sep 17 00:00:00 2001 From: lindexi Date: Fri, 27 Feb 2026 16:29:42 +0800 Subject: [PATCH 04/12] Support disable transparency explicitly; --- src/Windows/Avalonia.Win32/WindowImpl.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 373d072019..b75d8f1bb2 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Linq; +using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; @@ -377,6 +378,13 @@ namespace Avalonia.Win32 public void SetTransparencyLevelHint(IReadOnlyList transparencyLevels) { + if (transparencyLevels.Count == 1 && transparencyLevels[0] == WindowTransparencyLevel.None) + { + // Explicitly disable transparency. Ignore the UseRedirectionBitmap property. + TransparencyLevel = WindowTransparencyLevel.None; + return; + } + foreach (var level in transparencyLevels) { if (!IsSupported(level)) From c04d9949c73c9e65408c5bbbc0d87dba29f571e9 Mon Sep 17 00:00:00 2001 From: lindexi Date: Fri, 27 Feb 2026 16:39:50 +0800 Subject: [PATCH 05/12] Adding the test demo code. --- samples/RenderDemo/MainWindow.xaml | 1 + samples/RenderDemo/MainWindow.xaml.cs | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/samples/RenderDemo/MainWindow.xaml b/samples/RenderDemo/MainWindow.xaml index e1dbd20b07..e67ec30639 100644 --- a/samples/RenderDemo/MainWindow.xaml +++ b/samples/RenderDemo/MainWindow.xaml @@ -43,6 +43,7 @@ + diff --git a/samples/RenderDemo/MainWindow.xaml.cs b/samples/RenderDemo/MainWindow.xaml.cs index a2f3f0eac8..bab9d27e6b 100644 --- a/samples/RenderDemo/MainWindow.xaml.cs +++ b/samples/RenderDemo/MainWindow.xaml.cs @@ -1,6 +1,7 @@ using System; using System.Linq.Expressions; using Avalonia.Controls; +using Avalonia.Interactivity; using Avalonia.Markup.Xaml; using Avalonia.Rendering; using RenderDemo.ViewModels; @@ -37,5 +38,10 @@ namespace RenderDemo { AvaloniaXamlLoader.Load(this); } + + private void SetNotTransparencyMenuItem_OnClick(object? sender, RoutedEventArgs e) + { + TransparencyLevelHint = [WindowTransparencyLevel.None]; + } } } From 39a6ec8f08d5aaa9f73759d98f7219cdb8985184 Mon Sep 17 00:00:00 2001 From: lindexi Date: Fri, 27 Feb 2026 16:47:10 +0800 Subject: [PATCH 06/12] Fix ICompositionDrawingSurfaceInterop.BeginDraw fail. Because the surface do not set size. --- .../WinRT/Composition/WinUiCompositedWindowSurface.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs index b814395599..8fa4f8307b 100644 --- a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs +++ b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs @@ -149,6 +149,13 @@ namespace Avalonia.Win32.WinRT.Composition _drawingSurface.Dispose(); CreateSurface(_window); + + var size = _window.WindowInfo.Size; + _surfaceInterop.Resize(new UnmanagedMethods.POINT + { + X = size.Width, + Y = size.Height + }); } bool needsEndDraw = false; From d9c9600019d3e15da9ae1ae8035a86cafda54144 Mon Sep 17 00:00:00 2001 From: lindexi Date: Fri, 27 Feb 2026 16:54:51 +0800 Subject: [PATCH 07/12] Merge the same code --- .../WinRT/Composition/WinUiCompositedWindowSurface.cs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs index 8fa4f8307b..5f2ff4e634 100644 --- a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs +++ b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs @@ -140,6 +140,7 @@ namespace Avalonia.Win32.WinRT.Composition throw new RenderTargetCorruptedException(); var transaction = _window.BeginTransaction(); + bool forceResize = false; var supportTransparency = _drawingSurface.AlphaMode == DirectXAlphaMode.Premultiplied; if (_window.IsTransparency != supportTransparency) { @@ -150,12 +151,8 @@ namespace Avalonia.Win32.WinRT.Composition CreateSurface(_window); - var size = _window.WindowInfo.Size; - _surfaceInterop.Resize(new UnmanagedMethods.POINT - { - X = size.Width, - Y = size.Height - }); + // The _drawingSurface.Size != _size, so that require force resize to update the size of surface. + forceResize = true; } bool needsEndDraw = false; @@ -170,7 +167,7 @@ namespace Avalonia.Win32.WinRT.Composition UnmanagedMethods.POINT off; try { - if (_size != size) + if (forceResize || _size != size) { _surfaceInterop.Resize(new UnmanagedMethods.POINT { From 0d11ff407fb38c387ebbd29c2d639c0fb7a3ac28 Mon Sep 17 00:00:00 2001 From: lindexi Date: Fri, 27 Feb 2026 16:57:34 +0800 Subject: [PATCH 08/12] Fix compile --- .../WinRT/Composition/WinUiCompositedWindowSurface.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs index 5f2ff4e634..798a580bd5 100644 --- a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs +++ b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs @@ -1,4 +1,5 @@ using System; +using System.Diagnostics.CodeAnalysis; using Avalonia.Controls; using Avalonia.OpenGL.Egl; using Avalonia.Platform; @@ -110,6 +111,7 @@ namespace Avalonia.Win32.WinRT.Composition } } + [MemberNotNull(nameof(_drawingSurface), nameof(_surface), nameof(_surfaceInterop))] private void CreateSurface(WinUiCompositedWindow window) { // Do not use Premultiplied when the window is not Transparency. Because the Premultiplied AlphaMode will increase the performance loss of DWM. See https://github.com/AvaloniaUI/Avalonia/issues/20643 From 4059deeb9c60e60885951527de083744ce8b813e Mon Sep 17 00:00:00 2001 From: lindexi Date: Fri, 27 Feb 2026 17:02:09 +0800 Subject: [PATCH 09/12] Add test demo code --- samples/RenderDemo/MainWindow.xaml | 1 + samples/RenderDemo/MainWindow.xaml.cs | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/samples/RenderDemo/MainWindow.xaml b/samples/RenderDemo/MainWindow.xaml index e67ec30639..e16791b894 100644 --- a/samples/RenderDemo/MainWindow.xaml +++ b/samples/RenderDemo/MainWindow.xaml @@ -44,6 +44,7 @@ + diff --git a/samples/RenderDemo/MainWindow.xaml.cs b/samples/RenderDemo/MainWindow.xaml.cs index bab9d27e6b..96e21f0d2f 100644 --- a/samples/RenderDemo/MainWindow.xaml.cs +++ b/samples/RenderDemo/MainWindow.xaml.cs @@ -43,5 +43,10 @@ namespace RenderDemo { TransparencyLevelHint = [WindowTransparencyLevel.None]; } + + private void SetTransparencyMenuItem_OnClick(object? sender, RoutedEventArgs e) + { + TransparencyLevelHint = [WindowTransparencyLevel.Transparent]; + } } } From 7bafdc87b7a8aac2e1b8a794bacb02d3555b775d Mon Sep 17 00:00:00 2001 From: lindexi Date: Thu, 5 Mar 2026 10:03:35 +0800 Subject: [PATCH 10/12] Put the re create surface to trycatch block. Solve the `transaction` do not be disposed when CreateSurface exception. --- .../WinUiCompositedWindowSurface.cs | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs index 798a580bd5..ee4c326fd6 100644 --- a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs +++ b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs @@ -142,24 +142,24 @@ namespace Avalonia.Win32.WinRT.Composition throw new RenderTargetCorruptedException(); var transaction = _window.BeginTransaction(); - bool forceResize = false; - var supportTransparency = _drawingSurface.AlphaMode == DirectXAlphaMode.Premultiplied; - if (_window.IsTransparency != supportTransparency) + bool needsEndDraw = false; + try { - // Re-create the surface with correct alpha mode if the transparency support is not correct. This can happen when the transparency level is changed. - _surface.Dispose(); - _surfaceInterop.Dispose(); - _drawingSurface.Dispose(); + bool forceResize = false; + var supportTransparency = _drawingSurface.AlphaMode == DirectXAlphaMode.Premultiplied; + if (_window.IsTransparency != supportTransparency) + { + // Re-create the surface with correct alpha mode if the transparency support is not correct. This can happen when the transparency level is changed. + _surface.Dispose(); + _surfaceInterop.Dispose(); + _drawingSurface.Dispose(); - CreateSurface(_window); + CreateSurface(_window); - // The _drawingSurface.Size != _size, so that require force resize to update the size of surface. - forceResize = true; - } + // The _drawingSurface.Size != _size, so that require force resize to update the size of surface. + forceResize = true; + } - bool needsEndDraw = false; - try - { var size = _window.WindowInfo.Size; var scale = _window.WindowInfo.Scaling; _window.ResizeIfNeeded(size); From 8572ee247aee319774fec198538cf361b67f0325 Mon Sep 17 00:00:00 2001 From: lindexi Date: Thu, 5 Mar 2026 10:15:29 +0800 Subject: [PATCH 11/12] Add the dynamic Transparency alpha mode support to DirectComposited --- .../DComposition/DirectCompositedWindow.cs | 11 ++++- .../DirectCompositedWindowSurface.cs | 49 ++++++++++++++++--- 2 files changed, 51 insertions(+), 9 deletions(-) diff --git a/src/Windows/Avalonia.Win32/DComposition/DirectCompositedWindow.cs b/src/Windows/Avalonia.Win32/DComposition/DirectCompositedWindow.cs index 8935e8bcbf..de8caa85cc 100644 --- a/src/Windows/Avalonia.Win32/DComposition/DirectCompositedWindow.cs +++ b/src/Windows/Avalonia.Win32/DComposition/DirectCompositedWindow.cs @@ -1,6 +1,6 @@ using System; -using System.Numerics; using System.Threading; +using Avalonia.Controls; using Avalonia.OpenGL.Egl; using Avalonia.Reactive; using MicroCom.Runtime; @@ -51,4 +51,13 @@ internal class DirectCompositedWindow : IDisposable Monitor.Exit(_shared.SyncRoot); }); } + + public bool IsTransparency => _transparencyLevel != WindowTransparencyLevel.None; + + public void SetTransparencyLevel(WindowTransparencyLevel transparencyLevel) + { + _transparencyLevel = transparencyLevel; + } + + private WindowTransparencyLevel _transparencyLevel; } diff --git a/src/Windows/Avalonia.Win32/DComposition/DirectCompositedWindowSurface.cs b/src/Windows/Avalonia.Win32/DComposition/DirectCompositedWindowSurface.cs index e1b0a87aaa..15e0f60c3c 100644 --- a/src/Windows/Avalonia.Win32/DComposition/DirectCompositedWindowSurface.cs +++ b/src/Windows/Avalonia.Win32/DComposition/DirectCompositedWindowSurface.cs @@ -1,10 +1,15 @@ using System; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; + using Avalonia.Controls; +using Avalonia.Controls.Shapes; using Avalonia.OpenGL.Egl; using Avalonia.Platform; using Avalonia.Win32.DirectX; using Avalonia.Win32.Interop; +using Avalonia.Win32.WinRT; + using MicroCom.Runtime; namespace Avalonia.Win32.DComposition; @@ -26,6 +31,7 @@ internal class DirectCompositedWindowSurface : IDirect3D11TexturePlatformSurface { _window ??= new DirectCompositedWindow(_info, _shared); SetBlur(_blurEffect); + _window.SetTransparencyLevel(_windowTransparencyLevel); return new DirectCompositedWindowRenderTarget(context, d3dDevice, _shared, _window); } @@ -47,8 +53,11 @@ internal class DirectCompositedWindowSurface : IDirect3D11TexturePlatformSurface public void SetTransparencyLevel(WindowTransparencyLevel transparencyLevel) { - + _windowTransparencyLevel = transparencyLevel; + _window?.SetTransparencyLevel(transparencyLevel); } + + private WindowTransparencyLevel _windowTransparencyLevel; } internal class DirectCompositedWindowRenderTarget : IDirect3D11TextureRenderTarget @@ -56,11 +65,13 @@ internal class DirectCompositedWindowRenderTarget : IDirect3D11TextureRenderTarg private static readonly Guid IID_ID3D11Texture2D = Guid.Parse("6f15aaf2-d208-4e89-9ab4-489535d34f9c"); private readonly IPlatformGraphicsContext _context; + private readonly DirectCompositionShared _shared; private readonly DirectCompositedWindow _window; - private readonly IDCompositionVirtualSurface _surface; + private IDCompositionVirtualSurface _surface; private bool _lost; private PixelSize _size; private readonly IUnknown _d3dDevice; + private bool _isSurfaceSupportTransparency; public DirectCompositedWindowRenderTarget( IPlatformGraphicsContext context, IntPtr d3dDevice, @@ -69,13 +80,25 @@ internal class DirectCompositedWindowRenderTarget : IDirect3D11TextureRenderTarg _d3dDevice = MicroComRuntime.CreateProxyFor(d3dDevice, false).CloneReference(); _context = context; + _shared = shared; _window = window; - using (var surfaceFactory = shared.Device.CreateSurfaceFactory(_d3dDevice)) - { - _surface = surfaceFactory.CreateVirtualSurface(1, 1, DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM, - DXGI_ALPHA_MODE.DXGI_ALPHA_MODE_PREMULTIPLIED); - } + CreateSurface(window); + } + + [MemberNotNull(nameof(_surface))] + private void CreateSurface(DirectCompositedWindow window) + { + using var surfaceFactory = _shared.Device.CreateSurfaceFactory(_d3dDevice); + + const uint initialSize = 1; + var alphaMode = window.IsTransparency ? + DXGI_ALPHA_MODE.DXGI_ALPHA_MODE_PREMULTIPLIED : + DXGI_ALPHA_MODE.DXGI_ALPHA_MODE_IGNORE; + _isSurfaceSupportTransparency = window.IsTransparency; + + _surface = surfaceFactory.CreateVirtualSurface(initialSize, initialSize, DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM, + alphaMode); } public void Dispose() @@ -94,9 +117,19 @@ internal class DirectCompositedWindowRenderTarget : IDirect3D11TextureRenderTarg bool needsEndDraw = false; try { + bool forceResize = false; + if (_window.IsTransparency != _isSurfaceSupportTransparency) + { + _surface.Dispose(); + + CreateSurface(_window); + + forceResize = true; + } + var size = _window.WindowInfo.Size; var scale = _window.WindowInfo.Scaling; - if (_size != size) + if (forceResize || _size != size) { _surface.Resize((ushort)size.Width, (ushort)size.Height); _size = size; From 7aeea4d32d3a46a06ed3255784dcf0b3a1765471 Mon Sep 17 00:00:00 2001 From: lindexi Date: Thu, 5 Mar 2026 11:16:47 +0800 Subject: [PATCH 12/12] Revert "Adding TransparencyLevel property to CompositionTarget" This reverts commit da0af790b15c62bb8d5f2e94ca6b3c904a79b4a2. --- .../CompositionTransparencyLevel.cs | 10 ---------- src/Avalonia.Base/composition-schema.xml | 1 - src/Avalonia.Controls/TopLevel.cs | 19 +------------------ 3 files changed, 1 insertion(+), 29 deletions(-) delete mode 100644 src/Avalonia.Base/Rendering/Composition/CompositionTransparencyLevel.cs diff --git a/src/Avalonia.Base/Rendering/Composition/CompositionTransparencyLevel.cs b/src/Avalonia.Base/Rendering/Composition/CompositionTransparencyLevel.cs deleted file mode 100644 index fd2abd75ee..0000000000 --- a/src/Avalonia.Base/Rendering/Composition/CompositionTransparencyLevel.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Avalonia.Rendering.Composition; - -public enum CompositionTransparencyLevel : byte -{ - None = 0, - Transparent = 1, - Blur = 2, - AcrylicBlur = 3, - Mica = 4 -} diff --git a/src/Avalonia.Base/composition-schema.xml b/src/Avalonia.Base/composition-schema.xml index 7435e43e44..febf465042 100644 --- a/src/Avalonia.Base/composition-schema.xml +++ b/src/Avalonia.Base/composition-schema.xml @@ -58,7 +58,6 @@ - diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index 0bf3a5730f..a555b88b41 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -199,9 +199,7 @@ namespace Avalonia.Controls _scaling = ValidateScaling(impl.RenderScaling); _actualTransparencyLevel = PlatformImpl.TransparencyLevel; - - _source.Renderer.CompositionTarget.TransparencyLevel = - ToCompositionTransparencyLevel(_actualTransparencyLevel); + @@ -715,8 +713,6 @@ namespace Avalonia.Controls } ActualTransparencyLevel = transparencyLevel; - Renderer.CompositionTarget.TransparencyLevel = - ToCompositionTransparencyLevel(transparencyLevel); } protected override void OnApplyTemplate(TemplateAppliedEventArgs e) @@ -835,18 +831,5 @@ namespace Avalonia.Controls return scaling; } - - private static CompositionTransparencyLevel ToCompositionTransparencyLevel(WindowTransparencyLevel level) - { - if (level == WindowTransparencyLevel.Transparent) - return CompositionTransparencyLevel.Transparent; - if (level == WindowTransparencyLevel.Blur) - return CompositionTransparencyLevel.Blur; - if (level == WindowTransparencyLevel.AcrylicBlur) - return CompositionTransparencyLevel.AcrylicBlur; - if (level == WindowTransparencyLevel.Mica) - return CompositionTransparencyLevel.Mica; - return CompositionTransparencyLevel.None; - } } }