Skip to content

Commit

Permalink
Added ability to use the shared CanvasDevice instance
Browse files Browse the repository at this point in the history
  • Loading branch information
Sergio0694 committed Jul 1, 2017
1 parent 03c7ba0 commit 16acca8
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 14 deletions.
63 changes: 60 additions & 3 deletions UICompositionAnimations/Behaviours/AcrylicEffectHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,61 @@ async void Canvas_CreateResources(CanvasControl sender, CanvasCreateResourcesEve
return instance;
}

/// <summary>
/// Loads a <see cref="CompositionSurfaceBrush"/> instance with the target image from the shared <see cref="CanvasDevice"/> instance
/// </summary>
/// <param name="compositor">The compositor to use to render the Win2D image</param>
/// <param name="uri">The path to the image to load</param>
/// <param name="reload">Indicates whether or not to force the reload of the Win2D image</param>
[ItemCanBeNull]
private static async Task<CompositionSurfaceBrush> LoadWin2DSurfaceBrushFromImageAsync(
[NotNull] Compositor compositor, [NotNull] Uri uri, bool reload = false)
{
// Lock the semaphore and check the cache first
await Win2DSemaphore.WaitAsync();
if (!reload && SurfacesCache.TryGetValue(uri.ToString(), out CompositionSurfaceBrush cached))
{
Win2DSemaphore.Release();
return cached;
}

// Load the image
CompositionSurfaceBrush brush;
try
{
// This will throw and the canvas will re-initialize the Win2D device if needed
CanvasDevice sharedDevice = CanvasDevice.GetSharedDevice();
using (CanvasBitmap bitmap = await CanvasBitmap.LoadAsync(sharedDevice, uri))
{
// Get the device and the target surface
CompositionGraphicsDevice device = CanvasComposition.CreateCompositionGraphicsDevice(compositor, sharedDevice);
CompositionDrawingSurface surface = device.CreateDrawingSurface(default(Size),
DirectXPixelFormat.B8G8R8A8UIntNormalized, DirectXAlphaMode.Premultiplied);

// Calculate the surface size
Size size = bitmap.Size;
CanvasComposition.Resize(surface, size);

// Draw the image on the surface and get the resulting brush
using (CanvasDrawingSession session = CanvasComposition.CreateDrawingSession(surface))
{
session.Clear(Color.FromArgb(0, 0, 0, 0));
session.DrawImage(bitmap, new Rect(0, 0, size.Width, size.Height), new Rect(0, 0, size.Width, size.Height));
brush = surface.Compositor.CreateSurfaceBrush(surface);
}
}
}
catch
{
// Device error
brush = null;
}
String key = uri.ToString();
if (brush != null && !SurfacesCache.ContainsKey(key)) SurfacesCache.Add(key, brush);
Win2DSemaphore.Release();
return brush;
}

/// <summary>
/// Concatenates the source effect with a tint overlay and a border effect
/// </summary>
Expand All @@ -140,7 +195,7 @@ async void Canvas_CreateResources(CanvasControl sender, CanvasCreateResourcesEve
/// <param name="parameters">A dictionary to use to keep track of reference parameters to add when creating a <see cref="CompositionEffectFactory"/></param>
/// <param name="color">The tint color</param>
/// <param name="colorMix">The amount of tint color to apply</param>
/// <param name="canvas">The <see cref="CanvasControl"/> to use to generate the image for the <see cref="BorderEffect"/></param>
/// <param name="canvas">The optional <see cref="CanvasControl"/> to use to generate the image for the <see cref="BorderEffect"/></param>
/// <param name="uri">The path to the source image to use for the <see cref="BorderEffect"/></param>
/// <param name="timeThreshold">The maximum time to wait for the Win2D device to be restored in case of initial failure/></param>
/// <param name="reload">Indicates whether or not to force the reload of the Win2D image</param>
Expand All @@ -151,7 +206,7 @@ public static async Task<IGraphicsEffect> ConcatenateEffectWithTintAndBorderAsyn
[NotNull] Compositor compositor,
[NotNull] IGraphicsEffectSource source, [NotNull] IDictionary<String, CompositionBrush> parameters,
Color color, float colorMix,
[NotNull] CanvasControl canvas, [NotNull] Uri uri, int timeThreshold = 1000, bool reload = false)
[CanBeNull] CanvasControl canvas, [NotNull] Uri uri, int timeThreshold = 1000, bool reload = false)
{
// Setup the tint effect
ArithmeticCompositeEffect tint = new ArithmeticCompositeEffect
Expand All @@ -164,7 +219,9 @@ public static async Task<IGraphicsEffect> ConcatenateEffectWithTintAndBorderAsyn
};

// Get the noise brush using Win2D
CompositionSurfaceBrush noiseBitmap = await LoadWin2DSurfaceBrushFromImageAsync(compositor, canvas, uri, timeThreshold, reload);
CompositionSurfaceBrush noiseBitmap = canvas == null
? await LoadWin2DSurfaceBrushFromImageAsync(compositor, uri, reload)
: await LoadWin2DSurfaceBrushFromImageAsync(compositor, canvas, uri, timeThreshold, reload);

// Make sure the Win2D brush was loaded correctly
if (noiseBitmap != null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ public static async ValueTask<AttachedStaticCompositionEffect<T>> AttachComposit
/// <param name="color">The tint color for the effect</param>
/// <param name="colorMix">The opacity of the color over the blurred background</param>
/// <param name="saturation">An optional parameter to set the overall saturation of the effect (if null, it will default to 1)</param>
/// <param name="canvas">The source <see cref="CanvasControl"/> to generate the noise image using Win2D</param>
/// <param name="canvas">The optional source <see cref="CanvasControl"/> to generate the noise image using Win2D</param>
/// <param name="uri">The path of the noise image to use</param>
/// <param name="timeThreshold">The maximum time to wait for the Win2D device to be restored in case of initial failure</param>
/// <param name="reload">Indicates whether or not to force the reload of the Win2D image</param>
Expand All @@ -94,7 +94,7 @@ public static async ValueTask<AttachedStaticCompositionEffect<T>> AttachComposit
[ItemNotNull]
public static async Task<AttachedStaticCompositionEffect<T>> AttachCompositionInAppCustomAcrylicEffectAsync<TSource, T>(
[NotNull] this TSource element, [NotNull] T target, float blur, int ms, Color color, float colorMix, float? saturation,
[NotNull] CanvasControl canvas, [NotNull] Uri uri, int timeThreshold = 1000, bool reload = false, bool fadeIn = false, bool disposeOnUnload = false)
[CanBeNull] CanvasControl canvas, [NotNull] Uri uri, int timeThreshold = 1000, bool reload = false, bool fadeIn = false, bool disposeOnUnload = false)
where TSource : FrameworkElement
where T : FrameworkElement
{
Expand Down Expand Up @@ -207,15 +207,15 @@ public static async ValueTask<AttachedStaticCompositionEffect<T>> AttachComposit
/// <param name="element">The target element that will host the effect</param>
/// <param name="color">The tint color for the effect</param>
/// <param name="colorMix">The opacity of the color over the blurred background</param>
/// <param name="canvas">The source <see cref="CanvasControl"/> to generate the noise image using Win2D</param>
/// <param name="canvas">The optional source <see cref="CanvasControl"/> to generate the noise image using Win2D</param>
/// <param name="uri">The path of the noise image to use</param>
/// <param name="timeThreshold">The maximum time to wait for the Win2D device to be restored in case of initial failure/></param>
/// <param name="reload">Indicates whether or not to force the reload of the Win2D image</param>
/// <param name="disposeOnUnload">Indicates whether or not to automatically dispose and remove the effect when the target element is unloaded</param>
[ItemNotNull]
public static async Task<AttachedStaticCompositionEffect<T>> AttachCompositionCustomAcrylicEffectAsync<T>(
[NotNull] this T element, Color color, float colorMix,
[NotNull] CanvasControl canvas, [NotNull] Uri uri, int timeThreshold = 1000, bool reload = false, bool disposeOnUnload = false)
[CanBeNull] CanvasControl canvas, [NotNull] Uri uri, int timeThreshold = 1000, bool reload = false, bool disposeOnUnload = false)
where T : FrameworkElement
{
// Percentage check
Expand Down Expand Up @@ -366,7 +366,7 @@ public static async Task<AttachedAnimatableCompositionEffect<T>> AttachCompositi
/// <param name="initiallyVisible">Indicates whether or not to apply the effect right away</param>
/// <param name="color">The tint color for the effect</param>
/// <param name="colorMix">The opacity of the color over the blurred background</param>
/// <param name="canvas">The source <see cref="CanvasControl"/> to generate the noise image using Win2D</param>
/// <param name="canvas">The optional source <see cref="CanvasControl"/> to generate the noise image using Win2D</param>
/// <param name="uri">The path of the noise image to use</param>
/// <param name="timeThreshold">The maximum time to wait for the Win2D device to be restored in case of initial failure</param>
/// <param name="reload">Indicates whether or not to force the reload of the Win2D image</param>
Expand All @@ -375,7 +375,7 @@ public static async Task<AttachedAnimatableCompositionEffect<T>> AttachCompositi
public static async Task<AttachedAnimatableCompositionEffect<T>> AttachCompositionAnimatableInAppCustomAcrylicEffectAsync<TSource, T>(
[NotNull] this TSource element, [NotNull] T target,
float on, float off, bool initiallyVisible,
Color color, float colorMix, [NotNull] CanvasControl canvas, [NotNull] Uri uri,
Color color, float colorMix, [CanBeNull] CanvasControl canvas, [NotNull] Uri uri,
int timeThreshold = 1000, bool reload = false, bool disposeOnUnload = false)
where TSource : FrameworkElement
where T : FrameworkElement
Expand Down Expand Up @@ -438,7 +438,7 @@ public static async Task<AttachedAnimatableCompositionEffect<T>> AttachCompositi
/// <param name="initiallyVisible">Indicates whether or not to apply the effect right away</param>
/// <param name="color">The tint color for the effect</param>
/// <param name="colorMix">The opacity of the color over the blurred background</param>
/// <param name="canvas">The source <see cref="CanvasControl"/> to generate the noise image using Win2D</param>
/// <param name="canvas">The optional source <see cref="CanvasControl"/> to generate the noise image using Win2D</param>
/// <param name="uri">The path of the noise image to use</param>
/// <param name="timeThreshold">The maximum time to wait for the Win2D device to be restored in case of initial failure</param>
/// <param name="reload">Indicates whether or not to force the reload of the Win2D image</param>
Expand All @@ -449,7 +449,7 @@ public static async Task<AttachedCompositeAnimatableCompositionEffect<T>> Attach
float onBlur, float offBlur,
float onSaturation, float offSaturation,
bool initiallyVisible,
Color color, float colorMix, [NotNull] CanvasControl canvas, [NotNull] Uri uri,
Color color, float colorMix, [CanBeNull] CanvasControl canvas, [NotNull] Uri uri,
int timeThreshold = 1000, bool reload = false, bool disposeOnUnload = false)
where TSource : FrameworkElement
where T : FrameworkElement
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.5.4.0")]
[assembly: AssemblyVersion("2.5.5.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: ComVisible(false)]
4 changes: 2 additions & 2 deletions UICompositionAnimations/UICompositionAnimations.nuspec
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
<package >
<metadata>
<id>Sergio0694.UWP.UICompositionAnimations</id>
<version>2.5.4.0</version>
<version>2.5.5.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>The attached effects are now working properly even when created on a background thread</releaseNotes>
<releaseNotes>The custom acrylic effects can now be created without using an external CanvasDevice control</releaseNotes>
<copyright>Copyright 2017</copyright>
<tags>uwp composition animations xaml csharp windows winrt universal app ui win2d graphics</tags>
</metadata>
Expand Down

0 comments on commit 16acca8

Please sign in to comment.