DeferredRendererTests.cs 26 KB

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