test_invalidation.rs (4930B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 use crate::NotifierEvent; 6 use crate::WindowWrapper; 7 use std::path::PathBuf; 8 use std::sync::mpsc::Receiver; 9 use crate::wrench::{Wrench, WrenchThing}; 10 use crate::yaml_frame_reader::YamlFrameReader; 11 use webrender::{PictureCacheDebugInfo, TileDebugInfo}; 12 use webrender::api::units::*; 13 14 pub struct TestHarness<'a> { 15 wrench: &'a mut Wrench, 16 window: &'a mut WindowWrapper, 17 rx: Receiver<NotifierEvent>, 18 } 19 20 struct RenderResult { 21 pc_debug: PictureCacheDebugInfo, 22 composite_needed: bool, 23 } 24 25 // Convenience method to build a picture rect 26 fn pr(x: f32, y: f32, w: f32, h: f32) -> PictureRect { 27 PictureRect::from_origin_and_size( 28 PicturePoint::new(x, y), 29 PictureSize::new(w, h), 30 ) 31 } 32 33 impl<'a> TestHarness<'a> { 34 pub fn new( 35 wrench: &'a mut Wrench, 36 window: &'a mut WindowWrapper, 37 rx: Receiver<NotifierEvent> 38 ) -> Self { 39 TestHarness { 40 wrench, 41 window, 42 rx, 43 } 44 } 45 46 /// Main entry point for invalidation tests 47 pub fn run( 48 mut self, 49 ) { 50 // List all invalidation tests here 51 self.test_basic(); 52 self.test_composite_nop(); 53 self.test_scroll_subpic(); 54 } 55 56 /// Simple validation / proof of concept of invalidation testing 57 fn test_basic( 58 &mut self, 59 ) { 60 // Render basic.yaml, ensure that the valid/dirty rects are as expected 61 let results = self.render_yaml("basic"); 62 let tile_info = results.pc_debug.slice(0).tile(0, 0).as_dirty(); 63 assert_eq!( 64 tile_info.local_valid_rect, 65 pr(100.0, 100.0, 500.0, 100.0), 66 ); 67 assert_eq!( 68 tile_info.local_dirty_rect, 69 pr(100.0, 100.0, 500.0, 100.0), 70 ); 71 72 // Render it again and ensure the tile was considered valid (no rasterization was done) 73 let results = self.render_yaml("basic"); 74 assert_eq!(*results.pc_debug.slice(0).tile(0, 0), TileDebugInfo::Valid); 75 } 76 77 /// Ensure WR detects composites are needed for position changes within a single tile. 78 fn test_composite_nop( 79 &mut self, 80 ) { 81 // Render composite_nop_1.yaml, ensure that the valid/dirty rects are as expected 82 let results = self.render_yaml("composite_nop_1"); 83 let tile_info = results.pc_debug.slice(0).tile(0, 0).as_dirty(); 84 assert_eq!( 85 tile_info.local_valid_rect, 86 pr(100.0, 100.0, 100.0, 100.0), 87 ); 88 assert_eq!( 89 tile_info.local_dirty_rect, 90 pr(100.0, 100.0, 100.0, 100.0), 91 ); 92 93 // Render composite_nop_2.yaml, ensure that the valid/dirty rects are as expected 94 let results = self.render_yaml("composite_nop_2"); 95 let tile_info = results.pc_debug.slice(0).tile(0, 0).as_dirty(); 96 assert_eq!( 97 tile_info.local_valid_rect, 98 pr(100.0, 120.0, 100.0, 100.0), 99 ); 100 assert_eq!( 101 tile_info.local_dirty_rect, 102 pr(100.0, 120.0, 100.0, 100.0), 103 ); 104 105 // Main part of this test - ensure WR detects a composite is required in this case 106 assert!(results.composite_needed); 107 } 108 109 /// Ensure that tile cache pictures are not invalidated upon scrolling 110 fn test_scroll_subpic( 111 &mut self, 112 ) { 113 // First frame at scroll-offset 0 114 let results = self.render_yaml("scroll_subpic_1"); 115 116 // Ensure we actually rendered something 117 assert!( 118 matches!(results.pc_debug.slice(0).tile(0, 0), TileDebugInfo::Dirty(..)), 119 "Ensure the first test frame actually rendered something", 120 ); 121 122 // Second frame just scrolls to scroll-offset 50 123 let results = self.render_yaml("scroll_subpic_2"); 124 125 // Ensure the cache tile was not invalidated 126 assert!( 127 results.pc_debug.slice(0).tile(0, 0).is_valid(), 128 "Ensure the cache tile was not invalidated after scrolling", 129 ); 130 } 131 132 /// Render a YAML file, and return the picture cache debug info 133 fn render_yaml( 134 &mut self, 135 filename: &str, 136 ) -> RenderResult { 137 let path = format!("invalidation/{}.yaml", filename); 138 let mut reader = YamlFrameReader::new(&PathBuf::from(path)); 139 140 reader.do_frame(self.wrench); 141 let composite_needed = match self.rx.recv().unwrap() { 142 NotifierEvent::WakeUp { composite_needed } => composite_needed, 143 NotifierEvent::ShutDown => unreachable!(), 144 }; 145 let results = self.wrench.render(); 146 self.window.swap_buffers(); 147 148 RenderResult { 149 pc_debug: results.picture_cache_debug, 150 composite_needed, 151 } 152 } 153 }