Browse Source
Improve effect render performance by providing Skia with information about subscene bounds (#20191 )
* Improve effect render performance by providing Skia with information about subscene bounds
* Fixed test
* apidiff
* Update API diff
---------
Co-authored-by: Julien Lebosquain <julien@lebosquain.net>
release/11.3.10
Nikita Tsukanov
2 months ago
committed by
Julien Lebosquain
No known key found for this signature in database
GPG Key ID: 1833CAD10ACC46FD
7 changed files with
41 additions and
12 deletions
api/Avalonia.nupkg.xml
src/Avalonia.Base/Platform/IDrawingContextImpl.cs
src/Avalonia.Base/Rendering/Composition/Server/DrawingContextProxy.PendingCommands.cs
src/Avalonia.Base/Rendering/Composition/Server/DrawingContextProxy.cs
src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionContainerVisual.cs
src/Avalonia.Base/Rendering/Composition/Server/ServerCompositionVisual.cs
src/Skia/Avalonia.Skia/DrawingContextImpl.Effects.cs
@ -187,4 +187,4 @@
<Left > baseline/netstandard2.0/Avalonia.Controls.dll</Left>
<Right > target/netstandard2.0/Avalonia.Controls.dll</Right>
</Suppression>
</Suppressions>
</Suppressions>
@ -201,9 +201,10 @@ namespace Avalonia.Platform
object? GetFeature ( Type t ) ;
}
public interface IDrawingContextImplWithEffects
[PrivateApi]
public interface IDrawingContextImplWithEffects : IDrawingContextImpl
{
void PushEffect ( IEffect effect ) ;
void PushEffect ( Rect ? clipRect , IEffect effect ) ;
void PopEffect ( ) ;
}
@ -48,6 +48,10 @@ internal partial class CompositorDrawingContextProxy
[FieldOffset(0)] public bool IsRoundRect ;
[FieldOffset(4)] public RoundedRect RoundRect ;
[FieldOffset(4)] public Rect NormalRect ;
// PushEffect
[FieldOffset(0)]
public Rect ? EffectClipRect ;
}
struct PendingCommand
@ -140,7 +144,7 @@ internal partial class CompositorDrawingContextProxy
else if ( cmd . Type = = PendingCommandType . PushEffect )
{
if ( _ impl is IDrawingContextImplWithEffects effects )
effects . PushEffect ( cmd . ObjectUnion . Effect ! ) ;
effects . PushEffect ( cmd . DataUnion . EffectClipRect , cmd . ObjectUnion . Effect ! ) ;
}
else if ( cmd . Type = = PendingCommandType . PushRenderOptions )
_ impl . PushRenderOptions ( cmd . DataUnion . RenderOptions ) ;
@ -285,14 +285,18 @@ internal partial class CompositorDrawingContextProxy : IDrawingContextImpl,
_ impl . DrawRectangle ( new ImmutableSolidColorBrush ( material . FallbackColor ) , null , rect ) ;
}
public void PushEffect ( IEffect effect )
public void PushEffect ( Rect ? clipRect , IEffect effect )
{
AddCommand ( new ( )
{
Type = PendingCommandType . PushEffect ,
ObjectUnion =
{
Effect = effect
Effect = effect ,
} ,
DataUnion =
{
EffectClipRect = clipRect
}
} ) ;
}
@ -65,6 +65,8 @@ namespace Avalonia.Rendering.Composition.Server
return new ( _ transformedContentBounds , oldInvalidated , newInvalidated ) ;
}
protected override LtrbRect GetEffectBounds ( ) = > _ transformedContentBounds ? ? default ;
void AddEffectPaddedDirtyRect ( IImmutableEffect effect , LtrbRect transformedBounds )
{
var padding = effect . GetEffectOutputPadding ( ) ;
@ -62,9 +62,8 @@ namespace Avalonia.Rendering.Composition.Server
if ( applyRenderOptions )
canvas . PushRenderOptions ( RenderOptions ) ;
if ( Effect ! = null )
canvas . PushEffect ( Effect ) ;
var needPopEffect = PushEffect ( canvas ) ;
if ( Opacity ! = 1 )
canvas . PushOpacity ( Opacity , ClipToBounds ? boundsRect : null ) ;
if ( ClipToBounds & & ! HandlesClipToBounds )
@ -87,12 +86,28 @@ namespace Avalonia.Rendering.Composition.Server
if ( Opacity ! = 1 )
canvas . PopOpacity ( ) ;
if ( Effect ! = null )
if ( needPop Effect)
canvas . PopEffect ( ) ;
if ( applyRenderOptions )
canvas . PopRenderOptions ( ) ;
}
protected virtual LtrbRect GetEffectBounds ( ) = > TransformedOwnContentBounds ;
private bool PushEffect ( CompositorDrawingContextProxy canvas )
{
if ( Effect = = null )
return false ;
var clip = GetEffectBounds ( ) ;
if ( clip . IsZeroSize )
return false ;
var oldMatrix = canvas . Transform ;
canvas . Transform = Matrix . Identity ;
canvas . PushEffect ( GetEffectBounds ( ) . ToRect ( ) , Effect ! ) ;
canvas . Transform = oldMatrix ;
return true ;
}
protected virtual bool HandlesClipToBounds = > false ;
private ReadbackData _ readback0 , _ readback1 , _ readback2 ;
@ -7,13 +7,16 @@ namespace Avalonia.Skia;
partial class DrawingContextImpl
{
public void PushEffect ( IEffect effect )
public void PushEffect ( Rect ? effectClipRect , IEffect effect )
{
CheckLease ( ) ;
using var filter = CreateEffect ( effect ) ;
var paint = SKPaintCache . Shared . Get ( ) ;
paint . ImageFilter = filter ;
Canvas . SaveLayer ( paint ) ;
if ( effectClipRect . HasValue )
Canvas . SaveLayer ( effectClipRect . Value . ToSKRect ( ) , paint ) ;
else
Canvas . SaveLayer ( paint ) ;
SKPaintCache . Shared . ReturnReset ( paint ) ;
}