Skip to content

Commit

Permalink
Merge pull request #7830 from workgroupengineering/features/Skia/Rend…
Browse files Browse the repository at this point in the history
…erTargetBitmap

feat: Support for RenderTargetBitmap, BitmapEncoder, SoftwareBitmap
  • Loading branch information
MartinZikmund authored Jul 13, 2022
2 parents b862a99 + 2736374 commit 674d344
Show file tree
Hide file tree
Showing 60 changed files with 2,239 additions and 543 deletions.
8 changes: 8 additions & 0 deletions build/PackageDiffIgnore.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8855,6 +8855,14 @@
<Member
fullName="System.Void Windows.UI.UIContext..ctor()"
reason="Not part of UWP API" />
<!-- BEGIN BitmapEncoder -->
<Member
fullName="System.Void Windows.Graphics.Imaging.BitmapEncoder..ctor()"
reason="Add private ctor for initialize BitmapEncoder" />
<Member
fullName="System.Void Windows.Graphics.Imaging.BitmapEncoder::.ctor()"
reason="Add private ctor for initialize BitmapEncoder" />
<!-- END BitmapEncoder API -->
</Methods>
<Properties>
<Member
Expand Down
114 changes: 114 additions & 0 deletions build/ci/.azure-devops-macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,117 @@ jobs:
PathtoPublish: $(build.artifactstagingdirectory)
ArtifactName: uno-macos-artifacts
ArtifactType: Container

- job: macOS_Runtime_Tests
timeoutInMinutes: 90
condition: eq(1,2)
displayName: macOS SamplesApp Runtime Tests

variables:
CI_Build: true
SourceLinkEnabled: false
NUGET_PACKAGES: $(build.sourcesdirectory)/.nuget

dependsOn: macOS

pool:
vmImage: ${{ parameters.vmImage }}

steps:
- checkout: none
clean: true

- template: templates/dotnet-install.yml
- template: templates/optimize-roslyn-mono.yml

- template: templates/nuget-cache.yml
parameters:
nugetPackages: $(NUGET_PACKAGES)

- task: DownloadBuildArtifacts@0
inputs:
artifactName: uno-macos-artifacts
downloadPath: '$(build.sourcesdirectory)/build'

- task: PowerShell@2
displayName: 'Install coreutils'
inputs:
targetType: inline
script: |
brew install coreutils
- script: |
cd $(build.sourcesdirectory)/build/uno-macos-artifacts
installer -pkg SamplesApp.macOS-1.0.pkg -target CurrentUserHomeDirectory
displayName: Install SamplesApp
- script: |
timeout 70m /Applications/SamplesApp.macOS.app/Contents/MacOS/SamplesApp.macOS --runtime-tests=$(build.sourcesdirectory)/build/macOS-runtime-tests-results.xml
displayName: Run macOS Runtime Tests
- task: PublishTestResults@2
displayName: Publish macOS Runtime Tests
condition: always()
inputs:
testRunTitle: 'macOS Runtime Tests'
testResultsFormat: 'NUnit'
testResultsFiles: '$(build.sourcesdirectory)/build/macOS-runtime-tests-results.xml'
failTaskOnFailedTests: true

- job: macOS_Screenshot_Tests
timeoutInMinutes: 100
displayName: macOS SamplesApp Screenshot Test

variables:
CI_Build: true
SourceLinkEnabled: false
NUGET_PACKAGES: $(build.sourcesdirectory)/.nuget

dependsOn: macOS

pool:
vmImage: ${{ parameters.vmImage }}

steps:
- checkout: none
clean: true

- template: templates/dotnet-install.yml
- template: templates/optimize-roslyn-mono.yml

- template: templates/nuget-cache.yml
parameters:
nugetPackages: $(NUGET_PACKAGES)

- task: DownloadBuildArtifacts@0
inputs:
artifactName: uno-macos-artifacts
downloadPath: '$(build.sourcesdirectory)/build'

- task: PowerShell@2
displayName: 'Install coreutils'
inputs:
targetType: inline
script: |
brew install coreutils
- script: |
cd $(build.sourcesdirectory)/build/uno-macos-artifacts
installer -pkg SamplesApp.macOS-1.0.pkg -target CurrentUserHomeDirectory
displayName: Install SamplesApp
- script: |
timeout 90m /Applications/SamplesApp.macOS.app/Contents/MacOS/SamplesApp.macOS --auto-screenshots=$(build.artifactstagingdirectory)/screenshots/macOS-screenshots
displayName: Run macOS UI Snapshot Tests
- task: PublishBuildArtifacts@1
displayName: Publish macOS Screenshots
condition: always()
inputs:
PathtoPublish: $(build.artifactstagingdirectory)
ArtifactName: uitests-results
ArtifactType: Container
1 change: 1 addition & 0 deletions build/ci/.azure-devops-screenshot-compare.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ jobs:
- iOS_Snapshot_Tests_Group_02
- iOS_Snapshot_Tests_Group_03
- iOS_Snapshot_Tests_Group_04
- macOS_Screenshot_Tests

condition: or(succeeded(), and(failed(), ge(variables['System.StageAttempt'], 5)))

Expand Down
10 changes: 7 additions & 3 deletions src/SamplesApp/SamplesApp.Droid/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using System.Runtime.InteropServices;
using Android.App;

// General Information about an assembly is controlled through the following
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("UnoQuickStart.Droid")]
Expand All @@ -19,11 +19,11 @@
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// 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("1.0.0.0")]
Expand All @@ -36,3 +36,7 @@
[assembly: UsesPermission("android.permission.ACCESS_NETWORK_STATE")]
[assembly: UsesPermission("android.permission.SET_WALLPAPER")]
[assembly: UsesPermission("android.permission.READ_CONTACTS")]
[assembly: UsesPermission("android.permission.MANAGE_DOCUMENTS")]
[assembly: UsesPermission("android.permission.MANAGE_EXTERNAL_STORAGE")]
[assembly: UsesPermission("android.permission.MANAGE_MEDIA")]
[assembly: UsesPermission("android.permission.USE_FULL_SCREEN_INTENT")]
9 changes: 5 additions & 4 deletions src/SamplesApp/SamplesApp.Shared/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -150,15 +150,14 @@ override void OnLaunched(LaunchActivatedEventArgs e)

private static async Task<bool> HandleSkiaAutoScreenshots(LaunchActivatedEventArgs e)
{
#if __SKIA__
#if __SKIA__ || __MACOS__
var runAutoScreenshotsParam =
e.Arguments.Split(';').FirstOrDefault(a => a.StartsWith("--auto-screenshots"));

var screenshotsPath = runAutoScreenshotsParam?.Split('=').LastOrDefault();

if (!string.IsNullOrEmpty(screenshotsPath))
{
var sw = Stopwatch.StartNew();
var n = Windows.UI.Xaml.Window.Current.Dispatcher.RunIdleAsync(
_ =>
{
Expand All @@ -181,7 +180,7 @@ private static async Task<bool> HandleSkiaAutoScreenshots(LaunchActivatedEventAr

private static async Task<bool> HandleSkiaRuntimeTests(LaunchActivatedEventArgs e)
{
#if __SKIA__
#if __SKIA__ || __MACOS__
var runRuntimeTestsResultsParam =
e.Arguments.Split(';').FirstOrDefault(a => a.StartsWith("--runtime-tests"));

Expand All @@ -191,7 +190,7 @@ private static async Task<bool> HandleSkiaRuntimeTests(LaunchActivatedEventArgs
{
Console.WriteLine($"HandleSkiaRuntimeTests: {runtimeTestResultFilePath}");

_ = Window.Current.Dispatcher.RunIdleAsync(async _ =>
var runner = new Action(async () =>
{
// let the app finish its startup
await Task.Delay(TimeSpan.FromSeconds(5));
Expand All @@ -207,6 +206,8 @@ await SampleControl.Presentation.SampleChooserViewModel.Instance.RunRuntimeTests
);
});

await Task.Run(runner);

return true;
}
#endif
Expand Down
2 changes: 0 additions & 2 deletions src/SamplesApp/SamplesApp.Skia.Gtk/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ public static void Main(string[] args)

var host = new GtkHost(() => new SamplesApp.App());

SampleControl.Presentation.SampleChooserViewModel.TakeScreenShot = filePath => host.TakeScreenshot(filePath);

host.Run();
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/SamplesApp/SamplesApp.UITests/SamplesApp.UITests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@

<ItemGroup>
<Folder Include="MessageDialogTests\" />
<Folder Include="Windows_UI_Xaml_Media_Imaging\RenderTargetBitmap_Tests_ExpectedResults\" />
<Folder Include="Windows_UI_Xaml_Shapes\Basics_Shapes_Tests_EpectedResults\" />
</ItemGroup>

Expand All @@ -49,6 +50,9 @@
<Compile Include="$(MSBuildThisFileDirectory)..\..\Uno.UWP\Devices\Input\PointerDeviceType.cs">
<Link>TestFramework\PointerDeviceType.cs</Link>
</Compile>
<None Update="Windows_UI_Xaml_Media_Imaging\RenderTargetBitmap_Tests_ExpectedResults\Border.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
using System;
using System.IO;
using NUnit.Framework;
using SamplesApp.UITests.Extensions;
using SamplesApp.UITests.TestFramework;
using Uno.UITest.Helpers.Queries;

namespace SamplesApp.UITests.Windows_UI_Xaml_Media_Imaging
{
[TestFixture]
[ActivePlatforms(Platform.iOS | Platform.Android)]
public partial class RenderTargetBitmap_Tests : SampleControlUITestBase
{
private const int TestTimeout = 7 * 60 * 1000;
[Test]
[AutoRetry]
[Timeout(TestTimeout)]
public void When_Render_Border()
=> Validate("Border");

public void Validate(string controlName, PixelTolerance? tolerance = null)
{
Run("UITests.Windows_UI_Xaml_Media_Imaging.RenderTargetBitmaps", skipInitialScreenshot: true);

var ctrl = new QueryEx(q => q.Marked("_renderTargetTestRoot"));

var expectedDirectory = Path.Combine(
TestContext.CurrentContext.TestDirectory,
nameof(Windows_UI_Xaml_Media_Imaging) + "/RenderTargetBitmap_Tests_ExpectedResults");
var actualDirectory = Path.Combine(
TestContext.CurrentContext.WorkDirectory,
nameof(Windows_UI_Xaml_Media_Imaging),
nameof(RenderTargetBitmap_Tests),
controlName);

tolerance = tolerance ?? (new PixelTolerance()
.WithColor(132) // We are almost only trying to detect edges
.WithOffset(3, 3, LocationToleranceKind.PerPixel)
.Discrete(2));

ctrl.SetDependencyPropertyValue("RunTest", controlName);
_app.WaitFor(() => !string.IsNullOrWhiteSpace(ctrl.GetDependencyPropertyValue<string>("TestResult"))
, timeout: TimeSpan.FromMinutes(1));

var testResultsRaw = ctrl.GetDependencyPropertyValue<string>("TestResult");

var testResults = testResultsRaw.Split(';');
Assert.That(testResults.Length, Is.EqualTo(2));

var isSuccess = testResults[0] == "SUCCESS";
var data = Convert.FromBase64String(testResults[1]);

Assert.IsNotEmpty(data, "Invalid data");

var target = Path
.Combine(actualDirectory, controlName + (isSuccess ? ".png" : ".txt"))
.GetNormalizedLongPath();
var targetFile = new FileInfo(target);

targetFile.Directory.Create();
File.WriteAllBytes(target, data);
SetOptions(targetFile, new ScreenshotOptions { IgnoreInSnapshotCompare = true });
TestContext.AddTestAttachment(target, controlName);

if (!isSuccess)
{
Assert.Fail($"No test result for {controlName}.");
}

var expected = new FileInfo(Path.Combine(expectedDirectory, $"{controlName}.png"));
if (!expected.Exists)
{
Assert.Fail($"Expected screenshot does not exists ({expected.FullName})");
}

var scale = _app.GetDisplayScreenScaling();
ImageAssert.AreEqual(expected, ImageAssert.FirstQuadrant,
targetFile, ImageAssert.FirstQuadrant,
scale, tolerance.Value);
}
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,8 @@ public void ValidateShape(string shapeName, PixelTolerance? tolerance = null)
}

using (var actual = (Bitmap)testResult)
{
var scale = _app.GetDisplayScreenScaling();
{
var scale = 1d;
ImageAssert.AreAlmostEqual(expected, ImageAssert.FirstQuadrant, actual, ImageAssert.FirstQuadrant, scale, tolerance.Value);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,12 @@
#pragma warning disable 105 // Disabled until the tree is migrate to WinUI

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Reflection;
using System.Linq;
using System.Collections.Generic;
using System.Diagnostics;
using SampleControl.Entities;
using Uno.UI.Samples.Controls;
using Uno.UI.Samples.Entities;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Globalization;
using Windows.UI.Xaml.Data;
using Windows.ApplicationModel.Core;
using Windows.UI.Core;
using Windows.Storage;
using Uno.Extensions;
using Microsoft.Extensions.Logging;
using Windows.UI.Xaml;
using System.IO;
using Uno.Disposables;
using System.ComponentModel;
using Uno.UI.Common;
using Microsoft.UI.Xaml.Controls;

Expand Down
Loading

0 comments on commit 674d344

Please sign in to comment.