Bug 1512287 - Use smaller tiles during testing. r=gw
authorBobby Holley <bobbyholley@gmail.com>
Wed, 30 Jan 2019 08:57:52 +0000
changeset 456112 39090734374723e5041c8621f325b428b40bd9ec
parent 456111 892ec53492676aac4229cd2dd50016e446f26100
child 456113 fb6f1ac131309b8cda82ccd8d140f8d041330123
push id77122
push userbholley@mozilla.com
push dateWed, 30 Jan 2019 17:21:30 +0000
treeherderautoland@65a10a9e93f2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgw
bugs1512287
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1512287 - Use smaller tiles during testing. r=gw Depends on D17992 Differential Revision: https://phabricator.services.mozilla.com/D17993
gfx/wr/webrender/src/picture.rs
--- a/gfx/wr/webrender/src/picture.rs
+++ b/gfx/wr/webrender/src/picture.rs
@@ -1,23 +1,24 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-use api::{DeviceRect, FilterOp, MixBlendMode, PipelineId, PremultipliedColorF, PictureRect, PicturePoint, WorldPoint};
-use api::{DeviceIntRect, DevicePoint, LayoutRect, PictureToRasterTransform, LayoutPixel, PropertyBinding, PropertyBindingId};
+use api::{FilterOp, MixBlendMode, PipelineId, PremultipliedColorF, PictureRect, PicturePoint, WorldPoint};
+use api::{DeviceIntRect, DeviceIntSize, DevicePoint, DeviceRect};
+use api::{LayoutRect, PictureToRasterTransform, LayoutPixel, PropertyBinding, PropertyBindingId};
 use api::{DevicePixelScale, RasterRect, RasterSpace, ColorF, ImageKey, DirtyRect, WorldSize, ClipMode, LayoutSize};
 use api::{PicturePixel, RasterPixel, WorldPixel, WorldRect, ImageFormat, ImageDescriptor, WorldVector2D, LayoutPoint};
 use api::{DebugFlags, DeviceVector2D};
 use box_shadow::{BLUR_SAMPLE_SCALE};
 use clip::{ClipChainId, ClipChainNode, ClipItem};
 use clip_scroll_tree::{ROOT_SPATIAL_NODE_INDEX, ClipScrollTree, SpatialNodeIndex, CoordinateSystemId};
 use debug_colors;
 use device::TextureFilter;
-use euclid::{TypedScale, vec3, TypedRect, TypedPoint2D, TypedSize2D};
+use euclid::{size2, TypedScale, vec3, TypedRect, TypedPoint2D, TypedSize2D};
 use euclid::approxeq::ApproxEq;
 use frame_builder::{FrameVisibilityContext, FrameVisibilityState};
 use intern::ItemUid;
 use internal_types::{FastHashMap, FastHashSet, PlaneSplitter};
 use frame_builder::{FrameBuildingContext, FrameBuildingState, PictureState, PictureContext};
 use gpu_cache::{GpuCache, GpuCacheAddress, GpuCacheHandle};
 use gpu_types::{TransformPalette, TransformPaletteId, UvRectKind};
 use plane_split::{Clipper, Polygon, Splitter};
@@ -89,18 +90,23 @@ pub struct TileCoordinate;
 // Geometry types for tile coordinates.
 pub type TileOffset = TypedPoint2D<i32, TileCoordinate>;
 pub type TileSize = TypedSize2D<i32, TileCoordinate>;
 pub struct TileIndex(pub usize);
 
 /// The size in device pixels of a cached tile. The currently chosen
 /// size is arbitrary. We should do some profiling to find the best
 /// size for real world pages.
+///
+/// Note that we use a separate, smaller size during wrench testing, so that
+/// we get tighter dirty rects and can do more meaningful invalidation
+/// tests.
 pub const TILE_SIZE_WIDTH: i32 = 1024;
 pub const TILE_SIZE_HEIGHT: i32 = 256;
+pub const TILE_SIZE_TESTING: i32 = 64;
 const FRAMES_BEFORE_CACHING: usize = 2;
 const MAX_DIRTY_RECTS: usize = 3;
 
 /// The maximum size per axis of a surface,
 ///  in WorldPixel coordinates.
 const MAX_SURFACE_SIZE: f32 = 4096.0;
 
 
@@ -748,16 +754,19 @@ impl TileCache {
 
     /// Update transforms, opacity bindings and tile rects.
     pub fn pre_update(
         &mut self,
         pic_rect: LayoutRect,
         frame_context: &FrameVisibilityContext,
         frame_state: &mut FrameVisibilityState,
     ) {
+        let DeviceIntSize { width: tile_width, height: tile_height, _unit: _ } =
+            self.tile_dimensions(frame_context.config.testing);
+
         // Work out the scroll offset to apply to the world reference point.
         let scroll_transform = frame_context.clip_scroll_tree.get_relative_transform(
             ROOT_SPATIAL_NODE_INDEX,
             self.spatial_node_index,
         ).expect("bug: unable to get scroll transform");
         let scroll_offset = WorldVector2D::new(
             scroll_transform.m41,
             scroll_transform.m42,
@@ -864,35 +873,35 @@ impl TileCache {
         // Expand the needed device rect vertically by a small number of tiles. This
         // ensures that as tiles are scrolled in/out of view, they are retained for
         // a while before being discarded.
         // TODO(gw): On some pages it might be worth also inflating horizontally.
         //           (is this locale specific?). It might be possible to make a good
         //           guess based on the size of the picture rect for the tile cache.
         let needed_device_rect = needed_device_rect.inflate(
             0.0,
-            3.0 * TILE_SIZE_HEIGHT as f32,
+            3.0 * tile_height as f32,
         );
 
         let p0 = needed_device_rect.origin;
         let p1 = needed_device_rect.bottom_right();
 
         let p0 = DevicePoint::new(
-            device_ref_point.x + ((p0.x - device_ref_point.x) / TILE_SIZE_WIDTH as f32).floor() * TILE_SIZE_WIDTH as f32,
-            device_ref_point.y + ((p0.y - device_ref_point.y) / TILE_SIZE_HEIGHT as f32).floor() * TILE_SIZE_HEIGHT as f32,
+            device_ref_point.x + ((p0.x - device_ref_point.x) / tile_width as f32).floor() * tile_width as f32,
+            device_ref_point.y + ((p0.y - device_ref_point.y) / tile_height as f32).floor() * tile_height as f32,
         );
 
         let p1 = DevicePoint::new(
-            device_ref_point.x + ((p1.x - device_ref_point.x) / TILE_SIZE_WIDTH as f32).ceil() * TILE_SIZE_WIDTH as f32,
-            device_ref_point.y + ((p1.y - device_ref_point.y) / TILE_SIZE_HEIGHT as f32).ceil() * TILE_SIZE_HEIGHT as f32,
+            device_ref_point.x + ((p1.x - device_ref_point.x) / tile_width as f32).ceil() * tile_width as f32,
+            device_ref_point.y + ((p1.y - device_ref_point.y) / tile_height as f32).ceil() * tile_height as f32,
         );
 
         // And now the number of tiles from that device rect.
-        let x_tiles = ((p1.x - p0.x) / TILE_SIZE_WIDTH as f32).round() as i32;
-        let y_tiles = ((p1.y - p0.y) / TILE_SIZE_HEIGHT as f32).round() as i32;
+        let x_tiles = ((p1.x - p0.x) / tile_width as f32).round() as i32;
+        let y_tiles = ((p1.y - p0.y) / tile_height as f32).round() as i32;
 
         // Step through any old tiles, and retain them if we can. They are keyed only on
         // the (scroll adjusted) world position, relying on the descriptor content checks
         // later to invalidate them if the content has changed.
         let mut old_tiles = FastHashMap::default();
         for tile in self.tiles.drain(..) {
             let tile_device_pos = (tile.world_rect.origin + scroll_delta) * frame_context.device_pixel_scale;
             let key = (
@@ -903,27 +912,27 @@ impl TileCache {
         }
 
         // Store parameters about the current tiling rect for use during dependency updates.
         self.world_origin = WorldPoint::new(
             p0.x / frame_context.device_pixel_scale.0,
             p0.y / frame_context.device_pixel_scale.0,
         );
         self.world_tile_size = WorldSize::new(
-            TILE_SIZE_WIDTH as f32 / frame_context.device_pixel_scale.0,
-            TILE_SIZE_HEIGHT as f32 / frame_context.device_pixel_scale.0,
+            tile_width as f32 / frame_context.device_pixel_scale.0,
+            tile_height as f32 / frame_context.device_pixel_scale.0,
         );
         self.tile_count = TileSize::new(x_tiles, y_tiles);
 
         // Step through each tile and try to retain an old tile from the
         // previous frame, and update bounding rects.
         for y in 0 .. y_tiles {
             for x in 0 .. x_tiles {
-                let px = p0.x + x as f32 * TILE_SIZE_WIDTH as f32;
-                let py = p0.y + y as f32 * TILE_SIZE_HEIGHT as f32;
+                let px = p0.x + x as f32 * tile_width as f32;
+                let py = p0.y + y as f32 * tile_height as f32;
                 let key = (px.round() as i32, py.round() as i32);
 
                 let mut tile = match old_tiles.remove(&key) {
                     Some(tile) => tile,
                     None => {
                         let next_id = TileId(NEXT_TILE_ID.fetch_add(1, Ordering::Relaxed));
                         Tile::new(next_id)
                     }
@@ -1327,19 +1336,20 @@ impl TileCache {
         resource_cache: &mut ResourceCache,
         gpu_cache: &mut GpuCache,
         frame_context: &FrameVisibilityContext,
         scratch: &mut PrimitiveScratchBuffer,
     ) -> LayoutRect {
         self.dirty_region.clear();
         self.pending_blits.clear();
 
+        let dim = self.tile_dimensions(frame_context.config.testing);
         let descriptor = ImageDescriptor::new(
-            TILE_SIZE_WIDTH,
-            TILE_SIZE_HEIGHT,
+            dim.width,
+            dim.height,
             ImageFormat::BGRA8,
             true,
             false,
         );
 
         // Skip all tiles if completely off-screen.
         if !self.world_bounding_rect.intersects(&frame_context.screen_world_rect) {
             return LayoutRect::zero();
@@ -1531,16 +1541,24 @@ impl TileCache {
         // with a single, large dirty rect. In future we can consider improving
         // on this by supporting batching per dirty region.
         if self.dirty_region.dirty_rects.len() > MAX_DIRTY_RECTS {
             self.dirty_region.collapse();
         }
 
         local_clip_rect
     }
+
+    fn tile_dimensions(&self, testing: bool) -> DeviceIntSize {
+        if testing {
+            size2(TILE_SIZE_TESTING, TILE_SIZE_TESTING)
+        } else {
+            size2(TILE_SIZE_WIDTH, TILE_SIZE_HEIGHT)
+        }
+    }
 }
 
 /// Maintains a stack of picture and surface information, that
 /// is used during the initial picture traversal.
 pub struct PictureUpdateState<'a> {
     pub surfaces: &'a mut Vec<SurfaceInfo>,
     surface_stack: Vec<SurfaceIndex>,
     picture_stack: Vec<PictureInfo>,