diff --git a/api/Avalonia.nupkg.xml b/api/Avalonia.nupkg.xml
index aaf84068f5..590fbdc538 100644
--- a/api/Avalonia.nupkg.xml
+++ b/api/Avalonia.nupkg.xml
@@ -1,4 +1,4 @@
-
+
@@ -19,6 +19,24 @@
baseline/Avalonia/lib/net10.0/Avalonia.Base.dll
current/Avalonia/lib/net10.0/Avalonia.Base.dll
+
+ CP0002
+ M:Avalonia.Platform.IRenderTarget.RenderTargetSceneInfo.#ctor(Avalonia.PixelSize,System.Double,Avalonia.Size)
+ baseline/Avalonia/lib/net10.0/Avalonia.Base.dll
+ current/Avalonia/lib/net10.0/Avalonia.Base.dll
+
+
+ CP0002
+ M:Avalonia.Platform.IRenderTarget.RenderTargetSceneInfo.#ctor(Avalonia.PixelSize,System.Double)
+ baseline/Avalonia/lib/net10.0/Avalonia.Base.dll
+ current/Avalonia/lib/net10.0/Avalonia.Base.dll
+
+
+ CP0002
+ M:Avalonia.Platform.IRenderTarget.RenderTargetSceneInfo.Deconstruct(Avalonia.PixelSize@,System.Double@,Avalonia.Size@)
+ baseline/Avalonia/lib/net10.0/Avalonia.Base.dll
+ current/Avalonia/lib/net10.0/Avalonia.Base.dll
+
CP0002
M:Avalonia.Platform.IRenderTarget.RenderTargetSceneInfo.Deconstruct(Avalonia.PixelSize@,System.Double@)
@@ -49,6 +67,24 @@
baseline/Avalonia/lib/net8.0/Avalonia.Base.dll
current/Avalonia/lib/net8.0/Avalonia.Base.dll
+
+ CP0002
+ M:Avalonia.Platform.IRenderTarget.RenderTargetSceneInfo.#ctor(Avalonia.PixelSize,System.Double,Avalonia.Size)
+ baseline/Avalonia/lib/net8.0/Avalonia.Base.dll
+ current/Avalonia/lib/net8.0/Avalonia.Base.dll
+
+
+ CP0002
+ M:Avalonia.Platform.IRenderTarget.RenderTargetSceneInfo.#ctor(Avalonia.PixelSize,System.Double)
+ baseline/Avalonia/lib/net8.0/Avalonia.Base.dll
+ current/Avalonia/lib/net8.0/Avalonia.Base.dll
+
+
+ CP0002
+ M:Avalonia.Platform.IRenderTarget.RenderTargetSceneInfo.Deconstruct(Avalonia.PixelSize@,System.Double@,Avalonia.Size@)
+ baseline/Avalonia/lib/net8.0/Avalonia.Base.dll
+ current/Avalonia/lib/net8.0/Avalonia.Base.dll
+
CP0002
M:Avalonia.Platform.IRenderTarget.RenderTargetSceneInfo.Deconstruct(Avalonia.PixelSize@,System.Double@)
@@ -61,4 +97,4 @@
baseline/Avalonia/lib/net8.0/Avalonia.OpenGL.dll
current/Avalonia/lib/net8.0/Avalonia.OpenGL.dll
-
\ No newline at end of file
+
diff --git a/samples/RenderDemo/MainWindow.xaml b/samples/RenderDemo/MainWindow.xaml
index c3e68ab735..058cc14278 100644
--- a/samples/RenderDemo/MainWindow.xaml
+++ b/samples/RenderDemo/MainWindow.xaml
@@ -43,6 +43,8 @@
diff --git a/samples/RenderDemo/MainWindow.xaml.cs b/samples/RenderDemo/MainWindow.xaml.cs
index a2f3f0eac8..96e21f0d2f 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,15 @@ namespace RenderDemo
{
AvaloniaXamlLoader.Load(this);
}
+
+ private void SetNotTransparencyMenuItem_OnClick(object? sender, RoutedEventArgs e)
+ {
+ TransparencyLevelHint = [WindowTransparencyLevel.None];
+ }
+
+ private void SetTransparencyMenuItem_OnClick(object? sender, RoutedEventArgs e)
+ {
+ TransparencyLevelHint = [WindowTransparencyLevel.Transparent];
+ }
}
}
diff --git a/src/Avalonia.Base/Platform/IRenderTarget.cs b/src/Avalonia.Base/Platform/IRenderTarget.cs
index b9da6a35b6..0bc84c7a14 100644
--- a/src/Avalonia.Base/Platform/IRenderTarget.cs
+++ b/src/Avalonia.Base/Platform/IRenderTarget.cs
@@ -1,5 +1,6 @@
using System;
using Avalonia.Metadata;
+using Avalonia.Rendering.Composition;
namespace Avalonia.Platform
{
@@ -32,9 +33,9 @@ namespace Avalonia.Platform
///
PlatformRenderTargetState PlatformRenderTargetState => PlatformRenderTargetState.Ready;
- public record struct RenderTargetSceneInfo(PixelSize Size, double Scaling, Size LogicalSize)
+ public record struct RenderTargetSceneInfo(PixelSize Size, double Scaling, Size LogicalSize, CompositionTransparencyLevel TransparencyLevel)
{
- public RenderTargetSceneInfo(PixelSize size, double scaling) : this(size, scaling, size.ToSize(scaling))
+ public RenderTargetSceneInfo(PixelSize size, double scaling, CompositionTransparencyLevel transparencyLevel) : this(size, scaling, size.ToSize(scaling), transparencyLevel)
{
}
}
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/Rendering/Composition/Server/ServerCompositionTarget.cs b/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.cs
index 3ce37aec28..72d1eac278 100644
--- a/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.cs
+++ b/src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionTarget.cs
@@ -205,7 +205,7 @@ namespace Avalonia.Rendering.Composition.Server
try
{
renderTargetContext =
- _renderTarget.CreateDrawingContext(new(PixelSize, Scaling, Size), out properties);
+ _renderTarget.CreateDrawingContext(new(PixelSize, Scaling, Size, TransparencyLevel), out properties);
}
catch (RenderTargetNotReadyException)
{
diff --git a/src/Avalonia.Base/composition-schema.xml b/src/Avalonia.Base/composition-schema.xml
index 207f80647b..442d0c9197 100644
--- a/src/Avalonia.Base/composition-schema.xml
+++ b/src/Avalonia.Base/composition-schema.xml
@@ -59,6 +59,7 @@
+
diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs
index 7a9cfa4abb..c30047fe7a 100644
--- a/src/Avalonia.Controls/TopLevel.cs
+++ b/src/Avalonia.Controls/TopLevel.cs
@@ -218,7 +218,8 @@ namespace Avalonia.Controls
_scaling = LayoutHelper.ValidateScaling(impl.RenderScaling);
_actualTransparencyLevel = PlatformImpl.TransparencyLevel;
-
+ _source.Renderer.CompositionTarget.TransparencyLevel =
+ ToCompositionTransparencyLevel(_actualTransparencyLevel);
_accessKeyHandler = TryGetService(dependencyResolver);
@@ -731,6 +732,8 @@ namespace Avalonia.Controls
}
ActualTransparencyLevel = transparencyLevel;
+ Renderer.CompositionTarget.TransparencyLevel =
+ ToCompositionTransparencyLevel(transparencyLevel);
}
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
@@ -833,5 +836,18 @@ namespace Avalonia.Controls
{
// Do nothing becuase TopLevel should't apply MirrorTransform on himself.
}
+
+ 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;
+ }
}
}
diff --git a/src/Avalonia.Wayland/Server/Persistent/WaylandBitmapCursor.cs b/src/Avalonia.Wayland/Server/Persistent/WaylandBitmapCursor.cs
index 716dd6ae99..e46d9d0d15 100644
--- a/src/Avalonia.Wayland/Server/Persistent/WaylandBitmapCursor.cs
+++ b/src/Avalonia.Wayland/Server/Persistent/WaylandBitmapCursor.cs
@@ -4,6 +4,7 @@ using System.Linq;
using System.Runtime.InteropServices;
using Avalonia;
using Avalonia.Platform;
+using Avalonia.Rendering.Composition;
using Avalonia.Wayland.Server.Interop;
using Avalonia.Wayland.Server.Transient;
using Avalonia.Wayland.Server.Transient.Rendering;
@@ -75,7 +76,7 @@ sealed class WaylandBitmapCursor : WaylandCursor, IPersistentWaylandObject, IWay
var framebuffer = new WaylandFramebuffer(this);
using var renderTarget = framebuffer.CreateFramebufferRenderTarget();
- using var locked = renderTarget.Lock(new IRenderTarget.RenderTargetSceneInfo(_size, 1), out _);
+ using var locked = renderTarget.Lock(new IRenderTarget.RenderTargetSceneInfo(_size, 1, CompositionTransparencyLevel.None), out _);
// The locked framebuffer is Bgra8888 premultiplied with stride == Width * 4, matching the
// packed pixel data we captured on the UI thread. Disposing the lock attaches + commits.
Marshal.Copy(_pixels, 0, locked.Address, _pixels.Length);
diff --git a/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs b/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs
index dabf1b6bfd..e0292c44e6 100644
--- a/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs
+++ b/src/Linux/Avalonia.LinuxFramebuffer/Output/DrmOutput.cs
@@ -8,6 +8,7 @@ using Avalonia.OpenGL;
using Avalonia.OpenGL.Egl;
using Avalonia.OpenGL.Surfaces;
using Avalonia.Platform;
+using Avalonia.Rendering.Composition;
using static Avalonia.LinuxFramebuffer.NativeUnsafeMethods;
using static Avalonia.LinuxFramebuffer.Output.LibDrm;
@@ -377,7 +378,7 @@ namespace Avalonia.LinuxFramebuffer.Output
{
//Go through two cycles of buffer swapping (there are render artifacts otherwise)
for (var c = 0; c < 2; c++)
- using (CreateGlRenderTarget().BeginDraw(new IRenderTarget.RenderTargetSceneInfo(PixelSize, 1)))
+ using (CreateGlRenderTarget().BeginDraw(new IRenderTarget.RenderTargetSceneInfo(PixelSize, 1, CompositionTransparencyLevel.None)))
{
_deferredContext.GlInterface.ClearColor(initialBufferSwappingColorR, initialBufferSwappingColorG,
initialBufferSwappingColorB, initialBufferSwappingColorA);
diff --git a/src/Skia/Avalonia.Skia/RenderTargetBitmapImpl.cs b/src/Skia/Avalonia.Skia/RenderTargetBitmapImpl.cs
index c5002510f9..8712cfc2b5 100644
--- a/src/Skia/Avalonia.Skia/RenderTargetBitmapImpl.cs
+++ b/src/Skia/Avalonia.Skia/RenderTargetBitmapImpl.cs
@@ -1,5 +1,6 @@
using Avalonia.Platform.Surfaces;
using Avalonia.Platform;
+using Avalonia.Rendering.Composition;
using SkiaSharp;
namespace Avalonia.Skia;
@@ -20,7 +21,7 @@ internal class RenderTargetBitmapImpl : WriteableBitmapImpl,
public IDrawingContextImpl CreateDrawingContext()
{
return _renderTarget.CreateDrawingContext(new IRenderTarget.RenderTargetSceneInfo(
- PixelSize, Dpi.X / 96.0), out _);
+ PixelSize, Dpi.X / 96.0, CompositionTransparencyLevel.None), out _);
}
diff --git a/src/Windows/Avalonia.Win32/DComposition/DirectCompositedWindow.cs b/src/Windows/Avalonia.Win32/DComposition/DirectCompositedWindow.cs
index 8935e8bcbf..4689ad9bc4 100644
--- a/src/Windows/Avalonia.Win32/DComposition/DirectCompositedWindow.cs
+++ b/src/Windows/Avalonia.Win32/DComposition/DirectCompositedWindow.cs
@@ -1,5 +1,4 @@
using System;
-using System.Numerics;
using System.Threading;
using Avalonia.OpenGL.Egl;
using Avalonia.Reactive;
diff --git a/src/Windows/Avalonia.Win32/DComposition/DirectCompositedWindowSurface.cs b/src/Windows/Avalonia.Win32/DComposition/DirectCompositedWindowSurface.cs
index 9c6f5707bf..e91ca786f7 100644
--- a/src/Windows/Avalonia.Win32/DComposition/DirectCompositedWindowSurface.cs
+++ b/src/Windows/Avalonia.Win32/DComposition/DirectCompositedWindowSurface.cs
@@ -1,14 +1,17 @@
using System;
-using System.ComponentModel;
+using System.Diagnostics.CodeAnalysis;
+
using Avalonia.OpenGL.Egl;
using Avalonia.Platform;
+using Avalonia.Rendering.Composition;
using Avalonia.Win32.DirectX;
using Avalonia.Win32.Interop;
+
using MicroCom.Runtime;
namespace Avalonia.Win32.DComposition;
-internal class DirectCompositedWindowSurface : IDirect3D11TexturePlatformSurface, IDisposable, ICompositionEffectsSurface
+internal class DirectCompositedWindowSurface : IDirect3D11TexturePlatformSurface, IDirect3D11TexturePlatformSurface2, IDisposable, ICompositionEffectsSurface
{
private readonly EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo _info;
private readonly DirectCompositionShared _shared;
@@ -21,7 +24,12 @@ internal class DirectCompositedWindowSurface : IDirect3D11TexturePlatformSurface
_info = info;
}
- public IDirect3D11TextureRenderTarget CreateRenderTarget(IPlatformGraphicsContext context, IntPtr d3dDevice)
+ IDirect3D11TextureRenderTarget IDirect3D11TexturePlatformSurface.CreateRenderTarget(IPlatformGraphicsContext context, IntPtr d3dDevice)
+ {
+ return (IDirect3D11TextureRenderTarget) CreateRenderTarget(context, d3dDevice);
+ }
+
+ public IDirect3D11TextureRenderTarget2 CreateRenderTarget(IPlatformGraphicsContext context, IntPtr d3dDevice)
{
_window ??= new DirectCompositedWindow(_info, _shared);
SetBlur(_blurEffect);
@@ -45,16 +53,18 @@ internal class DirectCompositedWindowSurface : IDirect3D11TexturePlatformSurface
}
}
-internal class DirectCompositedWindowRenderTarget : IDirect3D11TextureRenderTarget
+internal class DirectCompositedWindowRenderTarget : IDirect3D11TextureRenderTarget, IDirect3D11TextureRenderTarget2
{
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,
@@ -63,24 +73,44 @@ 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);
- }
+ [MemberNotNull(nameof(_surface))]
+ private void CreateSurface(in IRenderTarget.RenderTargetSceneInfo sceneInfo)
+ {
+ using var surfaceFactory = _shared.Device.CreateSurfaceFactory(_d3dDevice);
+
+ bool isTransparency = sceneInfo.TransparencyLevel != CompositionTransparencyLevel.None;
+ var surfaceSize = sceneInfo.Size;
+
+ var alphaMode = isTransparency ?
+ DXGI_ALPHA_MODE.DXGI_ALPHA_MODE_PREMULTIPLIED :
+ DXGI_ALPHA_MODE.DXGI_ALPHA_MODE_IGNORE;
+
+ _surface = surfaceFactory.CreateVirtualSurface((uint)surfaceSize.Width, (uint)surfaceSize.Height, DXGI_FORMAT.DXGI_FORMAT_B8G8R8A8_UNORM, alphaMode);
+
+ _isSurfaceSupportTransparency = isTransparency;
+ _size = surfaceSize;
}
public void Dispose()
{
- _surface.Dispose();
+ _surface?.Dispose();
_d3dDevice.Dispose();
}
public PlatformRenderTargetState State => _context.IsLost || _lost ? PlatformRenderTargetState.Corrupted : PlatformRenderTargetState.Ready;
-
- public unsafe IDirect3D11TextureRenderTargetRenderSession BeginDraw()
+
+ IDirect3D11TextureRenderTargetRenderSession IDirect3D11TextureRenderTarget.BeginDraw()
+ {
+ var fallbackSceneInfo = new IRenderTarget.RenderTargetSceneInfo(_window.WindowInfo.Size,
+ _window.WindowInfo.Scaling, CompositionTransparencyLevel.None);
+ return BeginDraw(fallbackSceneInfo);
+ }
+
+ public unsafe IDirect3D11TextureRenderTargetRenderSession BeginDraw(IRenderTarget.RenderTargetSceneInfo sceneInfo)
{
if (State.IsCorrupted)
throw new RenderTargetCorruptedException();
@@ -88,11 +118,19 @@ internal class DirectCompositedWindowRenderTarget : IDirect3D11TextureRenderTarg
bool needsEndDraw = false;
try
{
- var size = _window.WindowInfo.Size;
- var scale = _window.WindowInfo.Scaling;
+ bool isTransparency = sceneInfo.TransparencyLevel != CompositionTransparencyLevel.None;
+ if (_surface is null || isTransparency != _isSurfaceSupportTransparency)
+ {
+ _surface?.Dispose();
+
+ CreateSurface(in sceneInfo);
+ }
+
+ var size = sceneInfo.Size;
+ var scale = sceneInfo.Scaling;
if (_size != size)
{
- _surface.Resize((ushort)size.Width, (ushort)size.Height);
+ _surface.Resize((uint)size.Width, (uint)size.Height);
_size = size;
}
@@ -125,7 +163,7 @@ internal class DirectCompositedWindowRenderTarget : IDirect3D11TextureRenderTarg
if (transaction != null)
{
if (needsEndDraw)
- _surface.EndDraw();
+ _surface?.EndDraw();
transaction.Dispose();
}
}
diff --git a/src/Windows/Avalonia.Win32/DirectX/IDirect3D11TexturePlatformSurface.cs b/src/Windows/Avalonia.Win32/DirectX/IDirect3D11TexturePlatformSurface.cs
index ce077d6ce0..c0dda8592b 100644
--- a/src/Windows/Avalonia.Win32/DirectX/IDirect3D11TexturePlatformSurface.cs
+++ b/src/Windows/Avalonia.Win32/DirectX/IDirect3D11TexturePlatformSurface.cs
@@ -1,4 +1,6 @@
using System;
+
+using Avalonia.Metadata;
using Avalonia.OpenGL;
using Avalonia.OpenGL.Surfaces;
using Avalonia.Platform;
@@ -11,6 +13,11 @@ public interface IDirect3D11TexturePlatformSurface : IPlatformRenderSurface
public IDirect3D11TextureRenderTarget CreateRenderTarget(IPlatformGraphicsContext graphicsContext, IntPtr d3dDevice);
}
+[PrivateApi]
+public interface IDirect3D11TexturePlatformSurface2 : IPlatformRenderSurface
+{
+ IDirect3D11TextureRenderTarget2 CreateRenderTarget(IPlatformGraphicsContext graphicsContext, IntPtr d3dDevice);
+}
public interface IDirect3D11TextureRenderTarget : IPlatformRenderSurfaceRenderTarget, IDisposable
@@ -18,6 +25,12 @@ public interface IDirect3D11TextureRenderTarget : IPlatformRenderSurfaceRenderTa
IDirect3D11TextureRenderTargetRenderSession BeginDraw();
}
+[PrivateApi]
+public interface IDirect3D11TextureRenderTarget2 : IPlatformRenderSurfaceRenderTarget, IDisposable
+{
+ IDirect3D11TextureRenderTargetRenderSession BeginDraw(IRenderTarget.RenderTargetSceneInfo sceneInfo);
+}
+
public interface IDirect3D11TextureRenderTargetRenderSession : IDisposable
{
public IntPtr D3D11Texture2D { get; }
diff --git a/src/Windows/Avalonia.Win32/OpenGl/Angle/AngleD3DTextureFeature.cs b/src/Windows/Avalonia.Win32/OpenGl/Angle/AngleD3DTextureFeature.cs
index 60882fb62e..f2e2f270a4 100644
--- a/src/Windows/Avalonia.Win32/OpenGl/Angle/AngleD3DTextureFeature.cs
+++ b/src/Windows/Avalonia.Win32/OpenGl/Angle/AngleD3DTextureFeature.cs
@@ -14,16 +14,16 @@ internal class AngleD3DTextureFeature : IGlPlatformSurfaceRenderTargetFactory
context is EglContext
{
Display: AngleWin32EglDisplay { PlatformApi: AngleOptions.PlatformApi.DirectX11 }
- } && surface is IDirect3D11TexturePlatformSurface;
+ } && surface is IDirect3D11TexturePlatformSurface2;
private class RenderTargetWrapper : EglPlatformSurfaceRenderTargetBase
{
private readonly AngleWin32EglDisplay _angle;
- private readonly IDirect3D11TextureRenderTarget _target;
+ private readonly IDirect3D11TextureRenderTarget2 _target;
public RenderTargetWrapper(EglContext context,
AngleWin32EglDisplay angle,
- IDirect3D11TextureRenderTarget target) : base(context)
+ IDirect3D11TextureRenderTarget2 target) : base(context)
{
_angle = angle;
_target = target;
@@ -40,7 +40,7 @@ internal class AngleD3DTextureFeature : IGlPlatformSurfaceRenderTargetFactory
{
try
{
- session = _target.BeginDraw();
+ session = _target.BeginDraw(sceneInfo);
}
catch (RenderTargetCorruptedException e)
{
@@ -91,7 +91,7 @@ internal class AngleD3DTextureFeature : IGlPlatformSurfaceRenderTargetFactory
{
var ctx = (EglContext)context;
var angle = (AngleWin32EglDisplay)ctx.Display;
- var textureSurface = (IDirect3D11TexturePlatformSurface)surface;
+ var textureSurface = (IDirect3D11TexturePlatformSurface2)surface;
try
{
var target = textureSurface.CreateRenderTarget(context, angle.GetDirect3DDevice());
diff --git a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs
index 96e5fae00b..179d0c2060 100644
--- a/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs
+++ b/src/Windows/Avalonia.Win32/WinRT/Composition/WinUiCompositedWindowSurface.cs
@@ -1,13 +1,15 @@
using System;
+using System.Diagnostics.CodeAnalysis;
using Avalonia.OpenGL.Egl;
using Avalonia.Platform;
+using Avalonia.Rendering.Composition;
using Avalonia.Win32.DirectX;
using Avalonia.Win32.Interop;
using MicroCom.Runtime;
namespace Avalonia.Win32.WinRT.Composition
{
- internal class WinUiCompositedWindowSurface : IDirect3D11TexturePlatformSurface, IDisposable, ICompositionEffectsSurface
+ internal class WinUiCompositedWindowSurface : IDirect3D11TexturePlatformSurface, IDirect3D11TexturePlatformSurface2, IDisposable, ICompositionEffectsSurface
{
private readonly WinUiCompositionShared _shared;
private readonly EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo _info;
@@ -20,7 +22,12 @@ namespace Avalonia.Win32.WinRT.Composition
_info = info;
}
- public IDirect3D11TextureRenderTarget CreateRenderTarget(IPlatformGraphicsContext context, IntPtr d3dDevice)
+ IDirect3D11TextureRenderTarget IDirect3D11TexturePlatformSurface.CreateRenderTarget(IPlatformGraphicsContext context, IntPtr d3dDevice)
+ {
+ return (IDirect3D11TextureRenderTarget) CreateRenderTarget(context, d3dDevice);
+ }
+
+ public IDirect3D11TextureRenderTarget2 CreateRenderTarget(IPlatformGraphicsContext context, IntPtr d3dDevice)
{
var cornerRadius = AvaloniaLocator.Current.GetService()
?.WinUICompositionBackdropCornerRadius;
@@ -52,7 +59,7 @@ namespace Avalonia.Win32.WinRT.Composition
}
}
- internal class WinUiCompositedWindowRenderTarget : IDirect3D11TextureRenderTarget
+ internal class WinUiCompositedWindowRenderTarget : IDirect3D11TextureRenderTarget, IDirect3D11TextureRenderTarget2
{
private static readonly Guid IID_ID3D11Texture2D = Guid.Parse("6f15aaf2-d208-4e89-9ab4-489535d34f9c");
@@ -63,11 +70,12 @@ 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 bool _isSurfaceSupportTransparency;
+ private ICompositionDrawingSurfaceInterop? _surfaceInterop;
+ private ICompositionDrawingSurface? _drawingSurface;
public WinUiCompositedWindowRenderTarget(IPlatformGraphicsContext context,
WinUiCompositedWindow window, IntPtr device,
@@ -83,16 +91,9 @@ 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();
}
catch
{
- _surface?.Dispose();
- _surfaceInterop?.Dispose();
- _drawingSurface?.Dispose();
_compositionDevice2?.Dispose();
_compositionDevice?.Dispose();
_interop?.Dispose();
@@ -104,9 +105,9 @@ namespace Avalonia.Win32.WinRT.Composition
public void Dispose()
{
- _surface.Dispose();
- _surfaceInterop.Dispose();
- _drawingSurface.Dispose();
+ _surface?.Dispose();
+ _surfaceInterop?.Dispose();
+ _drawingSurface?.Dispose();
_compositionDevice2.Dispose();
_compositionDevice.Dispose();
_interop.Dispose();
@@ -114,19 +115,61 @@ namespace Avalonia.Win32.WinRT.Composition
_d3dDevice.Dispose();
}
+ [MemberNotNull(nameof(_drawingSurface), nameof(_surface), nameof(_surfaceInterop))]
+ private void CreateSurface(in IRenderTarget.RenderTargetSceneInfo sceneInfo)
+ {
+ bool isTransparency = sceneInfo.TransparencyLevel != CompositionTransparencyLevel.None;
+ var surfaceSize = sceneInfo.Size;
+
+ // 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 = isTransparency ? DirectXAlphaMode.Premultiplied : DirectXAlphaMode.Ignore;
+ _drawingSurface = _compositionDevice2.CreateDrawingSurface2(new UnmanagedMethods.SIZE()
+ {
+ X = surfaceSize.Width,
+ Y = surfaceSize.Height,
+ },
+ DirectXPixelFormat.B8G8R8A8UIntNormalized, alphaMode);
+ _surface = _drawingSurface.QueryInterface();
+ _surfaceInterop = _drawingSurface.QueryInterface();
+
+ _isSurfaceSupportTransparency = isTransparency;
+ _size = surfaceSize;
+ }
+
public PlatformRenderTargetState State =>
_context.IsLost || _lost ? PlatformRenderTargetState.Corrupted : PlatformRenderTargetState.Ready;
- public unsafe IDirect3D11TextureRenderTargetRenderSession BeginDraw()
+ IDirect3D11TextureRenderTargetRenderSession IDirect3D11TextureRenderTarget.BeginDraw()
+ {
+ var fallbackSceneInfo = new IRenderTarget.RenderTargetSceneInfo(_window.WindowInfo.Size,
+ _window.WindowInfo.Scaling, CompositionTransparencyLevel.None);
+ return BeginDraw(fallbackSceneInfo);
+ }
+
+ public unsafe IDirect3D11TextureRenderTargetRenderSession BeginDraw(
+ IRenderTarget.RenderTargetSceneInfo sceneInfo)
{
if (State.IsCorrupted)
throw new RenderTargetCorruptedException();
var transaction = _window.BeginTransaction();
+
bool needsEndDraw = false;
try
{
- var size = _window.WindowInfo.Size;
- var scale = _window.WindowInfo.Scaling;
+ bool isTransparency = sceneInfo.TransparencyLevel != CompositionTransparencyLevel.None;
+
+ if (_surface is null || _surfaceInterop is null || _drawingSurface is null || _isSurfaceSupportTransparency != isTransparency)
+ {
+ // 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(in sceneInfo);
+ }
+
+ var size = sceneInfo.Size;
+ var scale = sceneInfo.Scaling;
_window.ResizeIfNeeded(size);
_window.SetSurface(_surface);
@@ -165,7 +208,7 @@ namespace Avalonia.Win32.WinRT.Composition
if (transaction != null)
{
if (needsEndDraw)
- _surfaceInterop.EndDraw();
+ _surfaceInterop?.EndDraw();
transaction.Dispose();
}
}
diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs
index 2c778c86c8..a858761a64 100644
--- a/src/Windows/Avalonia.Win32/WindowImpl.cs
+++ b/src/Windows/Avalonia.Win32/WindowImpl.cs
@@ -373,6 +373,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))
diff --git a/tests/Avalonia.RenderTests/Media/BitmapTests.cs b/tests/Avalonia.RenderTests/Media/BitmapTests.cs
index cd5713b9a2..1db7556b46 100644
--- a/tests/Avalonia.RenderTests/Media/BitmapTests.cs
+++ b/tests/Avalonia.RenderTests/Media/BitmapTests.cs
@@ -8,6 +8,7 @@ using Avalonia.Media;
using Avalonia.Media.Imaging;
using Avalonia.Platform;
using Avalonia.Platform.Surfaces;
+using Avalonia.Rendering.Composition;
using Xunit;
using Path = System.IO.Path;
@@ -71,7 +72,7 @@ namespace Avalonia.Skia.RenderTests
var r = AvaloniaLocator.Current.GetRequiredService();
using(var cpuContext = r.CreateBackendContext(null))
using (var target = cpuContext.CreateRenderTarget(new IPlatformRenderSurface[] { fb }))
- using (var ctx = target.CreateDrawingContext(new IRenderTarget.RenderTargetSceneInfo(fb.Size, 1), out _))
+ using (var ctx = target.CreateDrawingContext(new IRenderTarget.RenderTargetSceneInfo(fb.Size, 1, CompositionTransparencyLevel.None), out _))
{
ctx.Clear(Colors.Transparent);
ctx.PushOpacity(0.8, new Rect(0, 0, 80, 80));