@ -1,13 +1,15 @@
using System ;
using System ;
using System.Diagnostics.CodeAnalysis ;
using Avalonia.OpenGL.Egl ;
using Avalonia.OpenGL.Egl ;
using Avalonia.Platform ;
using Avalonia.Platform ;
using Avalonia.Rendering.Composition ;
using Avalonia.Win32.DirectX ;
using Avalonia.Win32.DirectX ;
using Avalonia.Win32.Interop ;
using Avalonia.Win32.Interop ;
using MicroCom.Runtime ;
using MicroCom.Runtime ;
namespace Avalonia.Win32.WinRT.Composition
namespace Avalonia.Win32.WinRT.Composition
{
{
internal class WinUiCompositedWindowSurface : IDirect3D11TexturePlatformSurface , IDisposable , ICompositionEffectsSurface
internal class WinUiCompositedWindowSurface : IDirect3D11TexturePlatformSurface , IDirect3D11TexturePlatformSurface2 , IDi sposable , ICompositionEffectsSurface
{
{
private readonly WinUiCompositionShared _ shared ;
private readonly WinUiCompositionShared _ shared ;
private readonly EglGlPlatformSurface . IEglWindowGlPlatformSurfaceInfo _ info ;
private readonly EglGlPlatformSurface . IEglWindowGlPlatformSurfaceInfo _ info ;
@ -20,7 +22,12 @@ namespace Avalonia.Win32.WinRT.Composition
_ info = info ;
_ 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 < Win32PlatformOptions > ( )
var cornerRadius = AvaloniaLocator . Current . GetService < Win32PlatformOptions > ( )
? . WinUICompositionBackdropCornerRadius ;
? . 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" ) ;
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 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 bool _ isSurfaceSupportTransparency ;
private readonly ICompositionDrawingSurface _d rawingSurface ;
private ICompositionDrawingSurfaceInterop ? _ surfaceInterop ;
private ICompositionDrawingSurface ? _d rawingSurface ;
public WinUiCompositedWindowRenderTarget ( IPlatformGraphicsContext context ,
public WinUiCompositedWindowRenderTarget ( IPlatformGraphicsContext context ,
WinUiCompositedWindow window , IntPtr device ,
WinUiCompositedWindow window , IntPtr device ,
@ -83,16 +91,9 @@ 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 ) ;
_ surface = _d rawingSurface . QueryInterface < ICompositionSurface > ( ) ;
_ surfaceInterop = _d rawingSurface . QueryInterface < ICompositionDrawingSurfaceInterop > ( ) ;
}
}
catch
catch
{
{
_ surface ? . Dispose ( ) ;
_ surfaceInterop ? . Dispose ( ) ;
_d rawingSurface ? . Dispose ( ) ;
_ compositionDevice2 ? . Dispose ( ) ;
_ compositionDevice2 ? . Dispose ( ) ;
_ compositionDevice ? . Dispose ( ) ;
_ compositionDevice ? . Dispose ( ) ;
_ interop ? . Dispose ( ) ;
_ interop ? . Dispose ( ) ;
@ -104,9 +105,9 @@ namespace Avalonia.Win32.WinRT.Composition
public void Dispose ( )
public void Dispose ( )
{
{
_ surface . Dispose ( ) ;
_ surface ? . Dispose ( ) ;
_ surfaceInterop . Dispose ( ) ;
_ surfaceInterop ? . Dispose ( ) ;
_d rawingSurface . Dispose ( ) ;
_d rawingSurface ? . Dispose ( ) ;
_ compositionDevice2 . Dispose ( ) ;
_ compositionDevice2 . Dispose ( ) ;
_ compositionDevice . Dispose ( ) ;
_ compositionDevice . Dispose ( ) ;
_ interop . Dispose ( ) ;
_ interop . Dispose ( ) ;
@ -114,19 +115,61 @@ namespace Avalonia.Win32.WinRT.Composition
_d 3d Device . Dispose ( ) ;
_d 3d Device . 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 ;
_d rawingSurface = _ compositionDevice2 . CreateDrawingSurface2 ( new UnmanagedMethods . SIZE ( )
{
X = surfaceSize . Width ,
Y = surfaceSize . Height ,
} ,
DirectXPixelFormat . B8G8R8A8UIntNormalized , alphaMode ) ;
_ surface = _d rawingSurface . QueryInterface < ICompositionSurface > ( ) ;
_ surfaceInterop = _d rawingSurface . QueryInterface < ICompositionDrawingSurfaceInterop > ( ) ;
_ isSurfaceSupportTransparency = isTransparency ;
_ size = surfaceSize ;
}
public PlatformRenderTargetState State = >
public PlatformRenderTargetState State = >
_ context . IsLost | | _l ost ? PlatformRenderTargetState . Corrupted : PlatformRenderTargetState . Ready ;
_ context . IsLost | | _l ost ? 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 )
if ( State . IsCorrupted )
throw new RenderTargetCorruptedException ( ) ;
throw new RenderTargetCorruptedException ( ) ;
var transaction = _ window . BeginTransaction ( ) ;
var transaction = _ window . BeginTransaction ( ) ;
bool needsEndDraw = false ;
bool needsEndDraw = false ;
try
try
{
{
var size = _ window . WindowInfo . Size ;
bool isTransparency = sceneInfo . TransparencyLevel ! = CompositionTransparencyLevel . None ;
var scale = _ window . WindowInfo . Scaling ;
if ( _ surface is null | | _ surfaceInterop is null | | _d rawingSurface 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 ( ) ;
_d rawingSurface ? . Dispose ( ) ;
CreateSurface ( in sceneInfo ) ;
}
var size = sceneInfo . Size ;
var scale = sceneInfo . Scaling ;
_ window . ResizeIfNeeded ( size ) ;
_ window . ResizeIfNeeded ( size ) ;
_ window . SetSurface ( _ surface ) ;
_ window . SetSurface ( _ surface ) ;
@ -165,7 +208,7 @@ namespace Avalonia.Win32.WinRT.Composition
if ( transaction ! = null )
if ( transaction ! = null )
{
{
if ( needsEndDraw )
if ( needsEndDraw )
_ surfaceInterop . EndDraw ( ) ;
_ surfaceInterop ? . EndDraw ( ) ;
transaction . Dispose ( ) ;
transaction . Dispose ( ) ;
}
}
}
}