@ -1,4 +1,6 @@
using System ;
using System ;
using System.Diagnostics.CodeAnalysis ;
using Avalonia.Controls ;
using Avalonia.OpenGL.Egl ;
using Avalonia.OpenGL.Egl ;
using Avalonia.Platform ;
using Avalonia.Platform ;
using Avalonia.Win32.DirectX ;
using Avalonia.Win32.DirectX ;
@ -26,6 +28,7 @@ namespace Avalonia.Win32.WinRT.Composition
? . WinUICompositionBackdropCornerRadius ;
? . WinUICompositionBackdropCornerRadius ;
_ window ? ? = new WinUiCompositedWindow ( _ info , _ shared , cornerRadius ) ;
_ window ? ? = new WinUiCompositedWindow ( _ info , _ shared , cornerRadius ) ;
_ window . SetBlur ( _ blurEffect ) ;
_ window . SetBlur ( _ blurEffect ) ;
_ window . SetTransparencyLevel ( _ windowTransparencyLevel ) ;
return new WinUiCompositedWindowRenderTarget ( context , _ window , d3dDevice , _ shared . Compositor ) ;
return new WinUiCompositedWindowRenderTarget ( context , _ window , d3dDevice , _ shared . Compositor ) ;
}
}
@ -50,6 +53,14 @@ namespace Avalonia.Win32.WinRT.Composition
_ blurEffect = enable ;
_ blurEffect = enable ;
_ window ? . SetBlur ( enable ) ;
_ window ? . SetBlur ( enable ) ;
}
}
public void SetTransparencyLevel ( WindowTransparencyLevel transparencyLevel )
{
_ windowTransparencyLevel = transparencyLevel ;
_ window ? . SetTransparencyLevel ( transparencyLevel ) ;
}
private WindowTransparencyLevel _ windowTransparencyLevel ;
}
}
internal class WinUiCompositedWindowRenderTarget : IDirect3D11TextureRenderTarget
internal class WinUiCompositedWindowRenderTarget : IDirect3D11TextureRenderTarget
@ -63,11 +74,11 @@ namespace Avalonia.Win32.WinRT.Composition
private readonly ICompositorInterop _ interop ;
private readonly ICompositorInterop _ interop ;
private readonly ICompositionGraphicsDevice _ compositionDevice ;
private readonly ICompositionGraphicsDevice _ compositionDevice ;
private readonly ICompositionGraphicsDevice2 _ compositionDevice2 ;
private readonly ICompositionGraphicsDevice2 _ compositionDevice2 ;
private readonly ICompositionSurface _ surface ;
private ICompositionSurface _ surface ;
private PixelSize _ size ;
private PixelSize _ size ;
private bool _l ost ;
private bool _l ost ;
private readonly ICompositionDrawingSurfaceInterop _ surfaceInterop ;
private ICompositionDrawingSurfaceInterop _ surfaceInterop ;
private readonly ICompositionDrawingSurface _d rawingSurface ;
private ICompositionDrawingSurface _d rawingSurface ;
public WinUiCompositedWindowRenderTarget ( IPlatformGraphicsContext context ,
public WinUiCompositedWindowRenderTarget ( IPlatformGraphicsContext context ,
WinUiCompositedWindow window , IntPtr device ,
WinUiCompositedWindow window , IntPtr device ,
@ -83,10 +94,8 @@ namespace Avalonia.Win32.WinRT.Composition
_ interop = compositor . QueryInterface < ICompositorInterop > ( ) ;
_ interop = compositor . QueryInterface < ICompositorInterop > ( ) ;
_ compositionDevice = _ interop . CreateGraphicsDevice ( _d 3d Device ) ;
_ compositionDevice = _ interop . CreateGraphicsDevice ( _d 3d Device ) ;
_ compositionDevice2 = _ compositionDevice . QueryInterface < ICompositionGraphicsDevice2 > ( ) ;
_ compositionDevice2 = _ compositionDevice . QueryInterface < ICompositionGraphicsDevice2 > ( ) ;
_d rawingSurface = _ compositionDevice2 . CreateDrawingSurface2 ( new UnmanagedMethods . SIZE ( ) ,
DirectXPixelFormat . B8G8R8A8UIntNormalized , DirectXAlphaMode . Premultiplied ) ;
CreateSurface ( window ) ;
_ surface = _d rawingSurface . QueryInterface < ICompositionSurface > ( ) ;
_ surfaceInterop = _d rawingSurface . QueryInterface < ICompositionDrawingSurfaceInterop > ( ) ;
}
}
catch
catch
{
{
@ -102,6 +111,17 @@ 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
var alphaMode = window . IsTransparency ? DirectXAlphaMode . Premultiplied : DirectXAlphaMode . Ignore ;
_d rawingSurface = _ compositionDevice2 . CreateDrawingSurface2 ( new UnmanagedMethods . SIZE ( ) ,
DirectXPixelFormat . B8G8R8A8UIntNormalized , alphaMode ) ;
_ surface = _d rawingSurface . QueryInterface < ICompositionSurface > ( ) ;
_ surfaceInterop = _d rawingSurface . QueryInterface < ICompositionDrawingSurfaceInterop > ( ) ;
}
public void Dispose ( )
public void Dispose ( )
{
{
_ surface . Dispose ( ) ;
_ surface . Dispose ( ) ;
@ -121,9 +141,25 @@ namespace Avalonia.Win32.WinRT.Composition
if ( IsCorrupted )
if ( IsCorrupted )
throw new RenderTargetCorruptedException ( ) ;
throw new RenderTargetCorruptedException ( ) ;
var transaction = _ window . BeginTransaction ( ) ;
var transaction = _ window . BeginTransaction ( ) ;
bool needsEndDraw = false ;
bool needsEndDraw = false ;
try
try
{
{
bool forceResize = false ;
var supportTransparency = _d rawingSurface . 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 ( ) ;
_d rawingSurface . Dispose ( ) ;
CreateSurface ( _ window ) ;
// The _drawingSurface.Size != _size, so that require force resize to update the size of surface.
forceResize = true ;
}
var size = _ window . WindowInfo . Size ;
var size = _ window . WindowInfo . Size ;
var scale = _ window . WindowInfo . Scaling ;
var scale = _ window . WindowInfo . Scaling ;
_ window . ResizeIfNeeded ( size ) ;
_ window . ResizeIfNeeded ( size ) ;
@ -133,7 +169,7 @@ namespace Avalonia.Win32.WinRT.Composition
UnmanagedMethods . POINT off ;
UnmanagedMethods . POINT off ;
try
try
{
{
if ( _ size ! = size )
if ( forceResize | | _ size ! = size )
{
{
_ surfaceInterop . Resize ( new UnmanagedMethods . POINT
_ surfaceInterop . Resize ( new UnmanagedMethods . POINT
{
{