diff --git a/src/Avalonia.Base/Rendering/Composition/CompositingRenderer.cs b/src/Avalonia.Base/Rendering/Composition/CompositingRenderer.cs
index c67142648a..8cb7daca6b 100644
--- a/src/Avalonia.Base/Rendering/Composition/CompositingRenderer.cs
+++ b/src/Avalonia.Base/Rendering/Composition/CompositingRenderer.cs
@@ -189,6 +189,7 @@ public class CompositingRenderer : RendererBase, IRendererWithCompositor
comp.Opacity = (float)visual.Opacity;
comp.ClipToBounds = visual.ClipToBounds;
comp.Clip = visual.Clip?.PlatformImpl;
+ comp.OpacityMask = visual.OpacityMask;
var renderTransform = Matrix.Identity;
diff --git a/src/Avalonia.Base/Rendering/Composition/Server/ServerVisual.cs b/src/Avalonia.Base/Rendering/Composition/Server/ServerVisual.cs
index 0b2ba6922b..d42bcae7e7 100644
--- a/src/Avalonia.Base/Rendering/Composition/Server/ServerVisual.cs
+++ b/src/Avalonia.Base/Rendering/Composition/Server/ServerVisual.cs
@@ -24,10 +24,13 @@ namespace Avalonia.Rendering.Composition.Server
canvas.Transform = Matrix.Identity;
if (Opacity != 1)
canvas.PushOpacity(Opacity);
+ var boundsRect = new Rect(new Size(Size.X, Size.Y));
if(ClipToBounds)
- canvas.PushClip(new Rect(new Size(Size.X, Size.Y)));
+ canvas.PushClip(boundsRect);
if (Clip != null)
canvas.PushGeometryClip(Clip);
+ if(OpacityMaskBrush != null)
+ canvas.PushOpacityMask(OpacityMaskBrush, boundsRect);
//TODO: Check clip
RenderCore(canvas);
@@ -35,7 +38,9 @@ namespace Avalonia.Rendering.Composition.Server
// Hack to force invalidation of SKMatrix
canvas.PreTransform = MatrixUtils.ToMatrix(transform);
canvas.Transform = Matrix.Identity;
-
+
+ if (OpacityMaskBrush != null)
+ canvas.PopOpacityMask();
if (Clip != null)
canvas.PopGeometryClip();
if (ClipToBounds)
diff --git a/src/Avalonia.Base/Rendering/Composition/Visual.cs b/src/Avalonia.Base/Rendering/Composition/Visual.cs
index 3d6e3fdaeb..f092029457 100644
--- a/src/Avalonia.Base/Rendering/Composition/Visual.cs
+++ b/src/Avalonia.Base/Rendering/Composition/Visual.cs
@@ -1,11 +1,14 @@
using System;
using System.Numerics;
+using Avalonia.Media;
using Avalonia.VisualTree;
namespace Avalonia.Rendering.Composition
{
public abstract partial class CompositionVisual
{
+ private IBrush? _opacityMask;
+
private protected virtual void OnRootChangedCore()
{
}
@@ -14,6 +17,16 @@ namespace Avalonia.Rendering.Composition
partial void OnParentChanged() => Root = Parent?.Root;
+ public IBrush? OpacityMask
+ {
+ get => _opacityMask;
+ set
+ {
+ if (_opacityMask == value)
+ return;
+ OpacityMaskBrush = (_opacityMask = value)?.ToImmutable();
+ }
+ }
internal Matrix4x4? TryGetServerTransform()
{
diff --git a/src/Avalonia.Base/composition-schema.xml b/src/Avalonia.Base/composition-schema.xml
index b86ce35d5f..2b555359c6 100644
--- a/src/Avalonia.Base/composition-schema.xml
+++ b/src/Avalonia.Base/composition-schema.xml
@@ -6,13 +6,15 @@
Avalonia.Rendering.Composition.Animations
+