1
0

DeferredRendererTests.cs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Reactive.Subjects;
  5. using Avalonia.Controls;
  6. using Avalonia.Data;
  7. using Avalonia.Media;
  8. using Avalonia.Platform;
  9. using Avalonia.Rendering;
  10. using Avalonia.Rendering.SceneGraph;
  11. using Avalonia.Threading;
  12. using Avalonia.UnitTests;
  13. using Avalonia.Media.Imaging;
  14. using Avalonia.VisualTree;
  15. using Moq;
  16. using Xunit;
  17. namespace Avalonia.Base.UnitTests.Rendering
  18. {
  19. public class DeferredRendererTests
  20. {
  21. [Fact]
  22. public void First_Frame_Calls_SceneBuilder_UpdateAll()
  23. {
  24. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  25. {
  26. var root = new TestRoot();
  27. var sceneBuilder = MockSceneBuilder(root);
  28. CreateTargetAndRunFrame(root, sceneBuilder: sceneBuilder.Object);
  29. sceneBuilder.Verify(x => x.UpdateAll(It.IsAny<Scene>()));
  30. }
  31. }
  32. [Fact]
  33. public void Frame_Does_Not_Call_SceneBuilder_If_No_Dirty_Controls()
  34. {
  35. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  36. {
  37. var dispatcher = new ImmediateDispatcher();
  38. var loop = new Mock<IRenderLoop>();
  39. var root = new TestRoot();
  40. var sceneBuilder = MockSceneBuilder(root);
  41. var target = new DeferredRenderer(
  42. root,
  43. loop.Object,
  44. sceneBuilder: sceneBuilder.Object);
  45. target.Start();
  46. IgnoreFirstFrame(target, sceneBuilder);
  47. RunFrame(target);
  48. sceneBuilder.Verify(x => x.UpdateAll(It.IsAny<Scene>()), Times.Never);
  49. sceneBuilder.Verify(x => x.Update(It.IsAny<Scene>(), It.IsAny<Visual>()), Times.Never);
  50. }
  51. }
  52. [Fact]
  53. public void Should_Update_Dirty_Controls_In_Order()
  54. {
  55. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  56. {
  57. var dispatcher = new ImmediateDispatcher();
  58. var loop = new Mock<IRenderLoop>();
  59. Border border;
  60. Decorator decorator;
  61. Canvas canvas;
  62. var root = new TestRoot
  63. {
  64. Child = decorator = new Decorator
  65. {
  66. Child = border = new Border { Child = canvas = new Canvas() }
  67. }
  68. };
  69. var sceneBuilder = MockSceneBuilder(root);
  70. var target = new DeferredRenderer(
  71. root,
  72. loop.Object,
  73. sceneBuilder: sceneBuilder.Object,
  74. dispatcher: dispatcher);
  75. target.Start();
  76. IgnoreFirstFrame(target, sceneBuilder);
  77. target.AddDirty(border);
  78. target.AddDirty(canvas);
  79. target.AddDirty(root);
  80. target.AddDirty(decorator);
  81. var result = new List<IVisual>();
  82. sceneBuilder.Setup(x => x.Update(It.IsAny<Scene>(), It.IsAny<IVisual>()))
  83. .Callback<Scene, IVisual>((_, v) => result.Add(v));
  84. RunFrame(target);
  85. Assert.Equal(new List<IVisual> { root, decorator, border, canvas }, result);
  86. }
  87. }
  88. [Fact]
  89. public void Should_Add_Dirty_Rect_On_Child_Remove()
  90. {
  91. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  92. {
  93. var dispatcher = new ImmediateDispatcher();
  94. var loop = new Mock<IRenderLoop>();
  95. Decorator decorator;
  96. Border border;
  97. var root = new TestRoot
  98. {
  99. Width = 100,
  100. Height = 100,
  101. Child = decorator = new Decorator
  102. {
  103. Child = border = new Border { Width = 50, Height = 50, Background = Brushes.Red, },
  104. }
  105. };
  106. root.Measure(Size.Infinity);
  107. root.Arrange(new Rect(root.DesiredSize));
  108. var sceneBuilder = new SceneBuilder();
  109. var target = new DeferredRenderer(
  110. root,
  111. loop.Object,
  112. sceneBuilder: sceneBuilder,
  113. dispatcher: dispatcher);
  114. root.Renderer = target;
  115. target.Start();
  116. RunFrame(target);
  117. decorator.Child = null;
  118. RunFrame(target);
  119. var scene = target.UnitTestScene();
  120. var stackNode = scene.FindNode(decorator);
  121. var dirty = scene.Layers[0].Dirty.ToList();
  122. Assert.Equal(1, dirty.Count);
  123. Assert.Equal(new Rect(25, 25, 50, 50), dirty[0]);
  124. }
  125. }
  126. [Fact]
  127. public void Should_Update_VisualNode_Order_On_Child_Remove_Insert()
  128. {
  129. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  130. {
  131. var dispatcher = new ImmediateDispatcher();
  132. var loop = new Mock<IRenderLoop>();
  133. StackPanel stack;
  134. Canvas canvas1;
  135. Canvas canvas2;
  136. var root = new TestRoot
  137. {
  138. Child = stack = new StackPanel
  139. {
  140. Children = { (canvas1 = new Canvas()), (canvas2 = new Canvas()), }
  141. }
  142. };
  143. var sceneBuilder = new SceneBuilder();
  144. var target = new DeferredRenderer(
  145. root,
  146. loop.Object,
  147. sceneBuilder: sceneBuilder,
  148. dispatcher: dispatcher);
  149. root.Renderer = target;
  150. target.Start();
  151. RunFrame(target);
  152. stack.Children.Remove(canvas2);
  153. stack.Children.Insert(0, canvas2);
  154. RunFrame(target);
  155. var scene = target.UnitTestScene();
  156. var stackNode = scene.FindNode(stack);
  157. Assert.Same(stackNode.Children[0].Visual, canvas2);
  158. Assert.Same(stackNode.Children[1].Visual, canvas1);
  159. }
  160. }
  161. [Fact]
  162. public void Should_Update_VisualNode_Order_On_Child_Move()
  163. {
  164. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  165. {
  166. var dispatcher = new ImmediateDispatcher();
  167. var loop = new Mock<IRenderLoop>();
  168. StackPanel stack;
  169. Canvas canvas1;
  170. Canvas canvas2;
  171. var root = new TestRoot
  172. {
  173. Child = stack = new StackPanel
  174. {
  175. Children = { (canvas1 = new Canvas()), (canvas2 = new Canvas()), }
  176. }
  177. };
  178. var sceneBuilder = new SceneBuilder();
  179. var target = new DeferredRenderer(
  180. root,
  181. loop.Object,
  182. sceneBuilder: sceneBuilder,
  183. dispatcher: dispatcher);
  184. root.Renderer = target;
  185. target.Start();
  186. RunFrame(target);
  187. stack.Children.Move(1, 0);
  188. RunFrame(target);
  189. var scene = target.UnitTestScene();
  190. var stackNode = scene.FindNode(stack);
  191. Assert.Same(stackNode.Children[0].Visual, canvas2);
  192. Assert.Same(stackNode.Children[1].Visual, canvas1);
  193. }
  194. }
  195. [Fact]
  196. public void Should_Update_VisualNode_Order_On_ZIndex_Change()
  197. {
  198. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  199. {
  200. var dispatcher = new ImmediateDispatcher();
  201. var loop = new Mock<IRenderLoop>();
  202. StackPanel stack;
  203. Canvas canvas1;
  204. Canvas canvas2;
  205. var root = new TestRoot
  206. {
  207. Child = stack = new StackPanel
  208. {
  209. Children =
  210. {
  211. (canvas1 = new Canvas { ZIndex = 1 }), (canvas2 = new Canvas { ZIndex = 2 }),
  212. }
  213. }
  214. };
  215. var sceneBuilder = new SceneBuilder();
  216. var target = new DeferredRenderer(
  217. root,
  218. loop.Object,
  219. sceneBuilder: sceneBuilder,
  220. dispatcher: dispatcher);
  221. root.Renderer = target;
  222. target.Start();
  223. RunFrame(target);
  224. canvas1.ZIndex = 3;
  225. RunFrame(target);
  226. var scene = target.UnitTestScene();
  227. var stackNode = scene.FindNode(stack);
  228. Assert.Same(stackNode.Children[0].Visual, canvas2);
  229. Assert.Same(stackNode.Children[1].Visual, canvas1);
  230. }
  231. }
  232. [Fact]
  233. public void Should_Update_VisualNode_Order_On_ZIndex_Change_With_Dirty_Ancestor()
  234. {
  235. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  236. {
  237. var dispatcher = new ImmediateDispatcher();
  238. var loop = new Mock<IRenderLoop>();
  239. StackPanel stack;
  240. Canvas canvas1;
  241. Canvas canvas2;
  242. var root = new TestRoot
  243. {
  244. Child = stack = new StackPanel
  245. {
  246. Children =
  247. {
  248. (canvas1 = new Canvas { ZIndex = 1 }), (canvas2 = new Canvas { ZIndex = 2 }),
  249. }
  250. }
  251. };
  252. var sceneBuilder = new SceneBuilder();
  253. var target = new DeferredRenderer(
  254. root,
  255. loop.Object,
  256. sceneBuilder: sceneBuilder,
  257. dispatcher: dispatcher);
  258. root.Renderer = target;
  259. target.Start();
  260. RunFrame(target);
  261. root.InvalidateVisual();
  262. canvas1.ZIndex = 3;
  263. RunFrame(target);
  264. var scene = target.UnitTestScene();
  265. var stackNode = scene.FindNode(stack);
  266. Assert.Same(stackNode.Children[0].Visual, canvas2);
  267. Assert.Same(stackNode.Children[1].Visual, canvas1);
  268. }
  269. }
  270. [Fact]
  271. public void Should_Update_VisualNodes_When_Child_Moved_To_New_Parent()
  272. {
  273. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  274. {
  275. var dispatcher = new ImmediateDispatcher();
  276. var loop = new Mock<IRenderLoop>();
  277. Decorator moveFrom;
  278. Decorator moveTo;
  279. Canvas moveMe;
  280. var root = new TestRoot
  281. {
  282. Child = new StackPanel
  283. {
  284. Children =
  285. {
  286. (moveFrom = new Decorator { Child = moveMe = new Canvas(), }),
  287. (moveTo = new Decorator()),
  288. }
  289. }
  290. };
  291. var sceneBuilder = new SceneBuilder();
  292. var target = new DeferredRenderer(
  293. root,
  294. loop.Object,
  295. sceneBuilder: sceneBuilder,
  296. dispatcher: dispatcher);
  297. root.Renderer = target;
  298. target.Start();
  299. RunFrame(target);
  300. moveFrom.Child = null;
  301. moveTo.Child = moveMe;
  302. RunFrame(target);
  303. var scene = target.UnitTestScene();
  304. var moveFromNode = (VisualNode)scene.FindNode(moveFrom);
  305. var moveToNode = (VisualNode)scene.FindNode(moveTo);
  306. Assert.Empty(moveFromNode.Children);
  307. Assert.Equal(1, moveToNode.Children.Count);
  308. Assert.Same(moveMe, moveToNode.Children[0].Visual);
  309. }
  310. }
  311. [Fact]
  312. public void Should_Update_VisualNodes_When_Child_Moved_To_New_Parent_And_New_Root()
  313. {
  314. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  315. {
  316. var dispatcher = new ImmediateDispatcher();
  317. var loop = new Mock<IRenderLoop>();
  318. Decorator moveFrom;
  319. Decorator moveTo;
  320. Canvas moveMe;
  321. var root = new TestRoot
  322. {
  323. Child = new StackPanel
  324. {
  325. Children = { (moveFrom = new Decorator { Child = moveMe = new Canvas(), }) }
  326. }
  327. };
  328. var otherRoot = new TestRoot { Child = new StackPanel { Children = { (moveTo = new Decorator()) } } };
  329. var sceneBuilder = new SceneBuilder();
  330. var target = new DeferredRenderer(
  331. root,
  332. loop.Object,
  333. sceneBuilder: sceneBuilder,
  334. dispatcher: dispatcher);
  335. var otherSceneBuilder = new SceneBuilder();
  336. var otherTarget = new DeferredRenderer(
  337. otherRoot,
  338. loop.Object,
  339. sceneBuilder: otherSceneBuilder,
  340. dispatcher: dispatcher);
  341. root.Renderer = target;
  342. otherRoot.Renderer = otherTarget;
  343. target.Start();
  344. otherTarget.Start();
  345. RunFrame(target);
  346. RunFrame(otherTarget);
  347. moveFrom.Child = null;
  348. moveTo.Child = moveMe;
  349. RunFrame(target);
  350. RunFrame(otherTarget);
  351. var scene = target.UnitTestScene();
  352. var otherScene = otherTarget.UnitTestScene();
  353. var moveFromNode = (VisualNode)scene.FindNode(moveFrom);
  354. var moveToNode = (VisualNode)otherScene.FindNode(moveTo);
  355. Assert.Empty(moveFromNode.Children);
  356. Assert.Equal(1, moveToNode.Children.Count);
  357. Assert.Same(moveMe, moveToNode.Children[0].Visual);
  358. }
  359. }
  360. [Fact]
  361. public void Should_Push_Opacity_For_Controls_With_Less_Than_1_Opacity()
  362. {
  363. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  364. {
  365. var root = new TestRoot
  366. {
  367. Width = 100, Height = 100, Child = new Border { Background = Brushes.Red, Opacity = 0.5, }
  368. };
  369. root.Measure(Size.Infinity);
  370. root.Arrange(new Rect(root.DesiredSize));
  371. var target = CreateTargetAndRunFrame(root);
  372. var context = GetLayerContext(target, root);
  373. var animation = new BehaviorSubject<double>(0.5);
  374. context.Verify(x => x.PushOpacity(0.5), Times.Once);
  375. context.Verify(x => x.DrawRectangle(Brushes.Red, null, new Rect(0, 0, 100, 100), default), Times.Once);
  376. context.Verify(x => x.PopOpacity(), Times.Once);
  377. }
  378. }
  379. [Fact]
  380. public void Should_Not_Draw_Controls_With_0_Opacity()
  381. {
  382. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  383. {
  384. var root = new TestRoot
  385. {
  386. Width = 100,
  387. Height = 100,
  388. Child = new Border
  389. {
  390. Background = Brushes.Red,
  391. Opacity = 0,
  392. Child = new Border { Background = Brushes.Green, }
  393. }
  394. };
  395. root.Measure(Size.Infinity);
  396. root.Arrange(new Rect(root.DesiredSize));
  397. var target = CreateTargetAndRunFrame(root);
  398. var context = GetLayerContext(target, root);
  399. var animation = new BehaviorSubject<double>(0.5);
  400. context.Verify(x => x.PushOpacity(0.5), Times.Never);
  401. context.Verify(x => x.DrawRectangle(Brushes.Red, null, new Rect(0, 0, 100, 100), default), Times.Never);
  402. context.Verify(x => x.PopOpacity(), Times.Never);
  403. }
  404. }
  405. [Fact]
  406. public void Should_Push_Opacity_Mask()
  407. {
  408. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  409. {
  410. var root = new TestRoot
  411. {
  412. Width = 100,
  413. Height = 100,
  414. Child = new Border { Background = Brushes.Red, OpacityMask = Brushes.Green, }
  415. };
  416. root.Measure(Size.Infinity);
  417. root.Arrange(new Rect(root.DesiredSize));
  418. var target = CreateTargetAndRunFrame(root);
  419. var context = GetLayerContext(target, root);
  420. var animation = new BehaviorSubject<double>(0.5);
  421. context.Verify(x => x.PushOpacityMask(Brushes.Green, new Rect(0, 0, 100, 100)), Times.Once);
  422. context.Verify(x => x.DrawRectangle(Brushes.Red, null, new Rect(0, 0, 100, 100), default), Times.Once);
  423. context.Verify(x => x.PopOpacityMask(), Times.Once);
  424. }
  425. }
  426. [Fact]
  427. public void Should_Create_Layer_For_Root()
  428. {
  429. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  430. {
  431. var root = new TestRoot();
  432. var rootLayer = new Mock<IRenderTargetBitmapImpl>();
  433. var sceneBuilder = new Mock<ISceneBuilder>();
  434. sceneBuilder.Setup(x => x.UpdateAll(It.IsAny<Scene>()))
  435. .Callback<Scene>(scene =>
  436. {
  437. scene.Size = root.ClientSize;
  438. scene.Layers.Add(root).Dirty.Add(new Rect(root.ClientSize));
  439. });
  440. var renderInterface = new Mock<IPlatformRenderInterface>();
  441. var target = CreateTargetAndRunFrame(root, sceneBuilder: sceneBuilder.Object);
  442. Assert.Single(target.Layers);
  443. }
  444. }
  445. [Fact(Skip = "Layers are disabled. See #2244")]
  446. public void Should_Create_And_Delete_Layers_For_Controls_With_Animated_Opacity()
  447. {
  448. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  449. {
  450. Border border;
  451. var root = new TestRoot
  452. {
  453. Width = 100,
  454. Height = 100,
  455. Child = new Border
  456. {
  457. Background = Brushes.Red,
  458. Child = border = new Border
  459. {
  460. Background = Brushes.Green, Child = new Canvas(), Opacity = 0.9,
  461. }
  462. }
  463. };
  464. root.Measure(Size.Infinity);
  465. root.Arrange(new Rect(root.DesiredSize));
  466. var timer = new Mock<IRenderTimer>();
  467. var target = CreateTargetAndRunFrame(root, timer);
  468. Assert.Equal(new[] { root }, target.Layers.Select(x => x.LayerRoot));
  469. var animation = new BehaviorSubject<double>(0.5);
  470. border.Bind(Border.OpacityProperty, animation, BindingPriority.Animation);
  471. RunFrame(target);
  472. Assert.Equal(new IVisual[] { root, border }, target.Layers.Select(x => x.LayerRoot));
  473. animation.OnCompleted();
  474. RunFrame(target);
  475. Assert.Equal(new[] { root }, target.Layers.Select(x => x.LayerRoot));
  476. }
  477. }
  478. [Fact(Skip = "Layers are disabled. See #2244")]
  479. public void Should_Not_Create_Layer_For_Childless_Control_With_Animated_Opacity()
  480. {
  481. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  482. {
  483. Border border;
  484. var root = new TestRoot
  485. {
  486. Width = 100,
  487. Height = 100,
  488. Child = new Border
  489. {
  490. Background = Brushes.Red, Child = border = new Border { Background = Brushes.Green, }
  491. }
  492. };
  493. var animation = new BehaviorSubject<double>(0.5);
  494. border.Bind(Border.OpacityProperty, animation, BindingPriority.Animation);
  495. root.Measure(Size.Infinity);
  496. root.Arrange(new Rect(root.DesiredSize));
  497. var timer = new Mock<IRenderTimer>();
  498. var target = CreateTargetAndRunFrame(root, timer);
  499. Assert.Single(target.Layers);
  500. }
  501. }
  502. [Fact(Skip = "Layers are disabled. See #2244")]
  503. public void Should_Not_Push_Opacity_For_Transparent_Layer_Root_Control()
  504. {
  505. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  506. {
  507. Border border;
  508. var root = new TestRoot
  509. {
  510. Width = 100,
  511. Height = 100,
  512. Child = border = new Border { Background = Brushes.Red, Child = new Canvas(), }
  513. };
  514. var animation = new BehaviorSubject<double>(0.5);
  515. border.Bind(Border.OpacityProperty, animation, BindingPriority.Animation);
  516. root.Measure(Size.Infinity);
  517. root.Arrange(new Rect(root.DesiredSize));
  518. var target = CreateTargetAndRunFrame(root);
  519. var context = GetLayerContext(target, border);
  520. context.Verify(x => x.PushOpacity(0.5), Times.Never);
  521. context.Verify(x => x.DrawRectangle(Brushes.Red, null, new Rect(0, 0, 100, 100), default), Times.Once);
  522. context.Verify(x => x.PopOpacity(), Times.Never);
  523. }
  524. }
  525. [Fact(Skip = "Layers are disabled. See #2244")]
  526. public void Should_Draw_Transparent_Layer_With_Correct_Opacity()
  527. {
  528. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  529. {
  530. Border border;
  531. var root = new TestRoot
  532. {
  533. Width = 100,
  534. Height = 100,
  535. Child = border = new Border { Background = Brushes.Red, Child = new Canvas(), }
  536. };
  537. var animation = new BehaviorSubject<double>(0.5);
  538. border.Bind(Border.OpacityProperty, animation, BindingPriority.Animation);
  539. root.Measure(Size.Infinity);
  540. root.Arrange(new Rect(root.DesiredSize));
  541. var target = CreateTargetAndRunFrame(root);
  542. var context = Mock.Get(target.RenderTarget.CreateDrawingContext(null));
  543. var borderLayer = target.Layers[border].Bitmap;
  544. context.Verify(x => x.DrawBitmap(borderLayer, 0.5, It.IsAny<Rect>(), It.IsAny<Rect>(),
  545. BitmapInterpolationMode.Default));
  546. }
  547. }
  548. [Fact]
  549. public void Can_Dirty_Control_In_SceneInvalidated()
  550. {
  551. using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
  552. {
  553. Border border1;
  554. Border border2;
  555. var root = new TestRoot
  556. {
  557. Width = 100,
  558. Height = 100,
  559. Child = new StackPanel
  560. {
  561. Children =
  562. {
  563. (border1 = new Border { Background = Brushes.Red, Child = new Canvas(), }),
  564. (border2 = new Border { Background = Brushes.Red, Child = new Canvas(), }),
  565. }
  566. }
  567. };
  568. root.Measure(Size.Infinity);
  569. root.Arrange(new Rect(root.DesiredSize));
  570. var target = CreateTargetAndRunFrame(root);
  571. var invalidated = false;
  572. target.SceneInvalidated += (s, e) =>
  573. {
  574. invalidated = true;
  575. target.AddDirty(border2);
  576. };
  577. target.AddDirty(border1);
  578. target.Paint(new Rect(root.DesiredSize));
  579. Assert.True(invalidated);
  580. Assert.True(((IRenderLoopTask)target).NeedsUpdate);
  581. }
  582. }
  583. private DeferredRenderer CreateTargetAndRunFrame(
  584. TestRoot root,
  585. Mock<IRenderTimer> timer = null,
  586. ISceneBuilder sceneBuilder = null,
  587. IDispatcher dispatcher = null)
  588. {
  589. timer = timer ?? new Mock<IRenderTimer>();
  590. dispatcher = dispatcher ?? new ImmediateDispatcher();
  591. var target = new DeferredRenderer(
  592. root,
  593. new RenderLoop(timer.Object, dispatcher),
  594. sceneBuilder: sceneBuilder,
  595. dispatcher: dispatcher);
  596. root.Renderer = target;
  597. target.Start();
  598. RunFrame(target);
  599. return target;
  600. }
  601. private static Mock<IDrawingContextImpl> GetLayerContext(DeferredRenderer renderer, IControl layerRoot)
  602. {
  603. return Mock.Get(renderer.Layers[layerRoot].Bitmap.Item.CreateDrawingContext(null));
  604. }
  605. private void IgnoreFirstFrame(IRenderLoopTask task, Mock<ISceneBuilder> sceneBuilder)
  606. {
  607. RunFrame(task);
  608. sceneBuilder.Invocations.Clear();
  609. }
  610. private void RunFrame(IRenderLoopTask task)
  611. {
  612. task.Update(TimeSpan.Zero);
  613. task.Render();
  614. }
  615. private IRenderTargetBitmapImpl CreateLayer()
  616. {
  617. return Mock.Of<IRenderTargetBitmapImpl>(x =>
  618. x.CreateDrawingContext(It.IsAny<IVisualBrushRenderer>()) == Mock.Of<IDrawingContextImpl>());
  619. }
  620. private Mock<ISceneBuilder> MockSceneBuilder(IRenderRoot root)
  621. {
  622. var result = new Mock<ISceneBuilder>();
  623. result.Setup(x => x.UpdateAll(It.IsAny<Scene>()))
  624. .Callback<Scene>(x => x.Layers.Add(root).Dirty.Add(new Rect(root.ClientSize)));
  625. return result;
  626. }
  627. }
  628. }