Skip to content

Commit

Permalink
Memory and performance improvements to the XAML acrylic brush
Browse files Browse the repository at this point in the history
  • Loading branch information
Sergio0694 committed Aug 10, 2017
1 parent c136e2d commit 9eb8b5c
Show file tree
Hide file tree
Showing 9 changed files with 138 additions and 30 deletions.
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
namespace UICompositionAnimations.Behaviours.Effects
using System;

namespace UICompositionAnimations.Behaviours.Effects
{
/// <summary>
/// Indicates the UI mode for an acrylic effect brush
/// </summary>
[Flags]
public enum AcrylicEffectMode
{
/// <summary>
/// The source content is the blurred UI of the application window
/// </summary>
InAppBlur,
InAppBlur = 1,

/// <summary>
/// The source content is the host screen
/// </summary>
HostBackdrop
HostBackdrop = 1 << 1
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using Windows.Graphics.Effects;
using Windows.UI.Composition;
using JetBrains.Annotations;

namespace UICompositionAnimations.Brushes.Cache
{
/// <summary>
/// A simple class that holds information on a <see cref="CompositionBackdropBrush"/> instance and its effects pipeline
/// </summary>
internal sealed class HostBackdropInstanceWrapper
{
/// <summary>
/// Gets the partial pipeline with the host backdrop effect
/// </summary>
[NotNull]
public IGraphicsEffectSource Pipeline { get; }

/// <summary>
/// Gets the host backdrop effect brush instance
/// </summary>
[NotNull]
public CompositionBackdropBrush Brush { get; }

/// <summary>
/// Creates a new wrapper instance with the given parameters
/// </summary>
/// <param name="pipeline">The current effects pipeline</param>
/// <param name="brush">The host backdrop brush instance</param>
public HostBackdropInstanceWrapper([NotNull] IGraphicsEffectSource pipeline, [NotNull] CompositionBackdropBrush brush)
{
Pipeline = pipeline;
Brush = brush;
}
}
}
107 changes: 88 additions & 19 deletions UICompositionAnimations/Brushes/CustomAcrylicBrush.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
using Windows.UI.Composition;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Media;
using JetBrains.Annotations;
using UICompositionAnimations.Behaviours;
using UICompositionAnimations.Behaviours.Effects;
using UICompositionAnimations.Brushes.Cache;
using UICompositionAnimations.Enums;
using UICompositionAnimations.Helpers;

Expand Down Expand Up @@ -254,6 +256,51 @@ protected override async void OnDisconnected()
base.OnDisconnected();
}

#region CompositionBackdropBrush cache

// The synchronization semaphore for the in-app backdrop brush
private static readonly SemaphoreSlim BackdropSemaphore = new SemaphoreSlim(1);

// The cached in-app backdrop brush
private static CompositionBackdropBrush _BackdropInstance;

// The name to use for the in-app backdrop reference parameter
private const String BackdropReferenceParameterName = "BackdropBrush";

// The synchronization semaphore for the host backdrop brush
private static readonly SemaphoreSlim HostBackdropSemaphore = new SemaphoreSlim(1);

// The cached host backdrop effect and partial pipeline to reuse
private static HostBackdropInstanceWrapper _HostBackdropCache;

// The name to use for the host backdrop reference parameter
private const String HostBackdropReferenceParameterName = "HostBackdropBrush";

/// <summary>
/// Clears the internal cache of <see cref="CompositionBackdropBrush"/> instances
/// </summary>
[PublicAPI]
public static async Task ClearCacheAsync(AcrylicEffectMode targets)
{
// In-app backdrop brush
if (targets.HasFlag(AcrylicEffectMode.InAppBlur))
{
await BackdropSemaphore.WaitAsync();
_BackdropInstance = null;
BackdropSemaphore.Release();
}

// Host backdrop brush
if (targets.HasFlag(AcrylicEffectMode.HostBackdrop))
{
await HostBackdropSemaphore.WaitAsync();
_HostBackdropCache = null;
HostBackdropSemaphore.Release();
}
}

#endregion

/// <summary>
/// Initializes the appropriate acrylic effect for the current instance
/// </summary>
Expand Down Expand Up @@ -291,39 +338,61 @@ private async Task SetupEffectAsync()
IGraphicsEffectSource baseEffect;
if (Mode == AcrylicEffectMode.InAppBlur)
{
// Prepare a luminosity to alpha effect to adjust the background contrast
CompositionBackdropBrush backdropBrush = Window.Current.Compositor.CreateBackdropBrush();
// Manage the cache
await BackdropSemaphore.WaitAsync();
if (_BackdropInstance == null)
{
_BackdropInstance = Window.Current.Compositor.CreateBackdropBrush();
}

// Prepare the blur effect for the backdrop brush
baseEffect = new GaussianBlurEffect
{
Name = "Blur",
BlurAmount = 0f, // The blur value is inserted later on as it isn't applied correctly when set from here
BorderMode = EffectBorderMode.Hard,
Optimization = EffectOptimization.Balanced,
Source = new CompositionEffectSourceParameter(nameof(backdropBrush))
Source = new CompositionEffectSourceParameter(nameof(BackdropReferenceParameterName))
};
animatableParameters.Add(BlurAmountParameterName);
sourceParameters.Add(nameof(backdropBrush), backdropBrush);
sourceParameters.Add(nameof(BackdropReferenceParameterName), _BackdropInstance);
BackdropSemaphore.Release();
}
else
{
// Prepare a luminosity to alpha effect to adjust the background contrast
CompositionBackdropBrush hostBackdropBrush = Window.Current.Compositor.CreateHostBackdropBrush();
CompositionEffectSourceParameter backgroundParameter = new CompositionEffectSourceParameter(nameof(hostBackdropBrush));
LuminanceToAlphaEffect alphaEffect = new LuminanceToAlphaEffect { Source = backgroundParameter };
OpacityEffect opacityEffect = new OpacityEffect
// Manage the cache
await HostBackdropSemaphore.WaitAsync();
if (_HostBackdropCache == null)
{
Source = alphaEffect,
Opacity = 0.4f // Reduce the amount of the effect to avoid making bright areas completely black
};
// Prepare a luminosity to alpha effect to adjust the background contrast
CompositionBackdropBrush hostBackdropBrush = Window.Current.Compositor.CreateHostBackdropBrush();
CompositionEffectSourceParameter backgroundParameter = new CompositionEffectSourceParameter(nameof(hostBackdropBrush));
LuminanceToAlphaEffect alphaEffect = new LuminanceToAlphaEffect { Source = backgroundParameter };
OpacityEffect opacityEffect = new OpacityEffect
{
Source = alphaEffect,
Opacity = 0.4f // Reduce the amount of the effect to avoid making bright areas completely black
};

// Layer [0,1,3] - Desktop background with blur and opacity mask
baseEffect = new BlendEffect
{
Background = backgroundParameter,
Foreground = opacityEffect,
Mode = BlendEffectMode.Multiply
};
sourceParameters.Add(HostBackdropReferenceParameterName, hostBackdropBrush);

// Layer [0,1,3] - Desktop background with blur and opacity mask
baseEffect = new BlendEffect
// Update the cache
_HostBackdropCache = new HostBackdropInstanceWrapper(baseEffect, hostBackdropBrush);
}
else
{
Background = backgroundParameter,
Foreground = opacityEffect,
Mode = BlendEffectMode.Multiply
};
sourceParameters.Add(nameof(hostBackdropBrush), hostBackdropBrush);
// Reuse the cached pipeline and effect
baseEffect = _HostBackdropCache.Pipeline;
sourceParameters.Add(HostBackdropReferenceParameterName, _HostBackdropCache.Brush);
}
HostBackdropSemaphore.Release();
}

// Get the noise brush using Win2D
Expand Down
2 changes: 1 addition & 1 deletion UICompositionAnimations/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.10.1.0")]
[assembly: AssemblyVersion("2.10.2.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: ComVisible(false)]
1 change: 1 addition & 0 deletions UICompositionAnimations/UICompositionAnimations.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@
<Compile Include="Behaviours\Effects\AttachedStaticCompositionEffect.cs" />
<Compile Include="Behaviours\Misc\CompositionAnimationParameters.cs" />
<Compile Include="Behaviours\Misc\FixedAnimationType.cs" />
<Compile Include="Brushes\Cache\HostBackdropInstanceWrapper.cs" />
<Compile Include="Brushes\CustomAcrylicBrush.cs" />
<Compile Include="Brushes\LightingBrush.cs" />
<Compile Include="CompositionExtensions.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@
<Import Project="$(NuGetPackageRoot)microsoft.net.native.sharedlibrary-x86\1.6.1\build\Microsoft.Net.Native.SharedLibrary-x86.props" Condition="Exists('$(NuGetPackageRoot)microsoft.net.native.sharedlibrary-x86\1.6.1\build\Microsoft.Net.Native.SharedLibrary-x86.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.net.native.sharedlibrary-x64\1.6.1\build\Microsoft.Net.Native.SharedLibrary-x64.props" Condition="Exists('$(NuGetPackageRoot)microsoft.net.native.sharedlibrary-x64\1.6.1\build\Microsoft.Net.Native.SharedLibrary-x64.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.net.native.sharedlibrary-arm\1.6.1\build\Microsoft.Net.Native.SharedLibrary-arm.props" Condition="Exists('$(NuGetPackageRoot)microsoft.net.native.sharedlibrary-arm\1.6.1\build\Microsoft.Net.Native.SharedLibrary-arm.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.net.native.compiler\1.6.2\build\Microsoft.Net.Native.Compiler.props" Condition="Exists('$(NuGetPackageRoot)microsoft.net.native.compiler\1.6.2\build\Microsoft.Net.Native.Compiler.props')" />
<Import Project="$(NuGetPackageRoot)microsoft.net.native.compiler\1.6.3\build\Microsoft.Net.Native.Compiler.props" Condition="Exists('$(NuGetPackageRoot)microsoft.net.native.compiler\1.6.3\build\Microsoft.Net.Native.Compiler.props')" />
</ImportGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
<Import Project="$(NuGetPackageRoot)microsoft.net.native.sharedlibrary-x86\1.6.1\build\Microsoft.Net.Native.SharedLibrary-x86.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.net.native.sharedlibrary-x86\1.6.1\build\Microsoft.Net.Native.SharedLibrary-x86.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.net.native.sharedlibrary-x64\1.6.1\build\Microsoft.Net.Native.SharedLibrary-x64.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.net.native.sharedlibrary-x64\1.6.1\build\Microsoft.Net.Native.SharedLibrary-x64.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.net.native.sharedlibrary-arm\1.6.1\build\Microsoft.Net.Native.SharedLibrary-arm.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.net.native.sharedlibrary-arm\1.6.1\build\Microsoft.Net.Native.SharedLibrary-arm.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.net.native.compiler\1.6.2\build\Microsoft.Net.Native.Compiler.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.net.native.compiler\1.6.2\build\Microsoft.Net.Native.Compiler.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.net.native.compiler\1.6.3\build\Microsoft.Net.Native.Compiler.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.net.native.compiler\1.6.3\build\Microsoft.Net.Native.Compiler.targets')" />
</ImportGroup>
</Project>
6 changes: 3 additions & 3 deletions UICompositionAnimations/UICompositionAnimations.nuspec
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
<?xml version="1.0"?>
<package >
<package>
<metadata>
<id>Sergio0694.UWP.UICompositionAnimations</id>
<version>2.10.1.0</version>
<version>2.10.2.0</version>
<title>UICompositionAnimations</title>
<description>A wrapper UWP PCL to work with Windows.UI.Composition and XAML animations, and Win2D effects</description>
<authors>Sergio Pedri</authors>
<owners>Sergio Pedri</owners>
<projectUrl>https://github.com/Sergio0694/UICompositionAnimations</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<releaseNotes>Minor XAML designer fixes in the LightsSourceHelper class</releaseNotes>
<releaseNotes>Minor memory and performance improvements in the custom acrylic brush</releaseNotes>
<copyright>Copyright 2017</copyright>
<tags>uwp composition animations xaml csharp windows winrt universal app ui win2d graphics</tags>
</metadata>
Expand Down
4 changes: 2 additions & 2 deletions UICompositionAnimations/project.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"dependencies": {
"JetBrains.Annotations": "10.4.0",
"Microsoft.NETCore.UniversalWindowsPlatform": "5.3.3",
"JetBrains.Annotations": "11.0.0",
"Microsoft.NETCore.UniversalWindowsPlatform": "5.3.4",
"System.Threading.Tasks.Extensions": "4.3.0",
"Win2D.uwp": "1.21.0"
},
Expand Down

0 comments on commit 9eb8b5c

Please sign in to comment.