DirectFbCompositionTests.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. #if AVALONIA_SKIA
  2. using System;
  3. using System.IO;
  4. using System.Runtime.CompilerServices;
  5. using System.Threading.Tasks;
  6. using Avalonia.Controls;
  7. using Avalonia.Controls.Platform.Surfaces;
  8. using Avalonia.Controls.Primitives;
  9. using Avalonia.Controls.Shapes;
  10. using Avalonia.Layout;
  11. using Avalonia.Media;
  12. using Avalonia.Platform;
  13. using Avalonia.Rendering;
  14. using Avalonia.Rendering.Composition;
  15. using Avalonia.Threading;
  16. using Avalonia.UnitTests;
  17. using SkiaSharp;
  18. using Xunit;
  19. namespace Avalonia.Skia.RenderTests;
  20. public class DirectFbCompositionTests : TestBase
  21. {
  22. public DirectFbCompositionTests()
  23. : base(@"Composition\DirectFb")
  24. {
  25. }
  26. class FuncFramebufferSurface : IFramebufferPlatformSurface
  27. {
  28. private readonly Func<IFramebufferRenderTarget> _cb;
  29. public FuncFramebufferSurface(Func<IFramebufferRenderTarget> cb)
  30. {
  31. _cb = cb;
  32. }
  33. public IFramebufferRenderTarget CreateFramebufferRenderTarget()
  34. {
  35. return _cb();
  36. }
  37. }
  38. [Theory,
  39. InlineData(false),
  40. InlineData(true)]
  41. void Should_Only_Update_Clipped_Rects_When_Retained_Fb_Is_Advertised(bool advertised)
  42. {
  43. var timer = new ManualRenderTimer();
  44. var compositor = new Compositor(new RenderLoop(timer), null, true,
  45. new DispatcherCompositorScheduler(), true, Dispatcher.UIThread, new CompositionOptions
  46. {
  47. UseRegionDirtyRectClipping = true
  48. });
  49. Rectangle r1, r2;
  50. var control = new Canvas
  51. {
  52. Width = 200, Height = 200, Background = Brushes.Yellow,
  53. Children =
  54. {
  55. (r1 = new Rectangle
  56. {
  57. Fill = Brushes.Black,
  58. Width = 40,
  59. Height = 40,
  60. Opacity = 0.6,
  61. [Canvas.LeftProperty] = 40,
  62. [Canvas.TopProperty] = 40,
  63. }),
  64. (r2 = new Rectangle
  65. {
  66. Fill = Brushes.Black,
  67. Width = 40,
  68. Height = 40,
  69. Opacity = 0.6,
  70. [Canvas.LeftProperty] = 120,
  71. [Canvas.TopProperty] = 40,
  72. }),
  73. }
  74. };
  75. var root = new TestRenderRoot(1, null!);
  76. SKBitmap fb = new SKBitmap(200, 200, SKColorType.Rgba8888, SKAlphaType.Premul);
  77. ILockedFramebuffer LockFb() => new LockedFramebuffer(fb.GetAddress(0, 0), new(fb.Width, fb.Height),
  78. fb.RowBytes, new Vector(96, 96), PixelFormat.Rgba8888, null);
  79. bool previousFrameIsRetained = false;
  80. IFramebufferRenderTarget rt = advertised
  81. ? new FuncRetainedFramebufferRenderTarget((out FramebufferLockProperties props) =>
  82. {
  83. props = new() { PreviousFrameIsRetained = previousFrameIsRetained };
  84. return LockFb();
  85. })
  86. : new FuncFramebufferRenderTarget(LockFb);
  87. using var renderer =
  88. new CompositingRenderer(root, compositor, () => new[] { new FuncFramebufferSurface(() => rt) });
  89. root.Initialize(renderer, control);
  90. control.Measure(new Size(control.Width, control.Height));
  91. control.Arrange(new Rect(control.DesiredSize));
  92. renderer.Start();
  93. Dispatcher.UIThread.RunJobs();
  94. timer.TriggerTick();
  95. var image1 =
  96. $"{nameof(Should_Only_Update_Clipped_Rects_When_Retained_Fb_Is_Advertised)}_advertized-{advertised}_initial";
  97. SaveFile(fb, image1);
  98. fb.Erase(SKColor.Empty);
  99. previousFrameIsRetained = advertised;
  100. r1.Fill = Brushes.Red;
  101. r2.Fill = Brushes.Green;
  102. Dispatcher.UIThread.RunJobs();
  103. timer.TriggerTick();
  104. var image2 =
  105. $"{nameof(Should_Only_Update_Clipped_Rects_When_Retained_Fb_Is_Advertised)}_advertized-{advertised}_updated";
  106. SaveFile(fb, image2);
  107. CompareImages(image1, skipImmediate: true);
  108. CompareImages(image2, skipImmediate: true);
  109. }
  110. void SaveFile(SKBitmap bmp, string name)
  111. {
  112. Directory.CreateDirectory(OutputPath);
  113. var path = System.IO.Path.Combine(OutputPath, name + ".composited.out.png");
  114. using var d = bmp.Encode(SKEncodedImageFormat.Png, 100);
  115. using var f = File.Create(path);
  116. d.SaveTo(f);
  117. }
  118. }
  119. #endif