Bug 1517975 - Update webrender to commit 1b226534099a24c741e9827c4612eee1ec12d4ee (WR PR #3478). r=kats
authorWR Updater Bot <graphics-team@mozilla.staktrace.com>
Mon, 07 Jan 2019 12:47:12 +0000
changeset 452719 8828a5a7028605c49e4276fb3cab5c6465ffa033
parent 452718 06c59ba512bafc9e6b4830496026793998151c54
child 452720 17ae2e56509f21aadf30d839235ecac424108871
push id75549
push userkgupta@mozilla.com
push dateMon, 07 Jan 2019 12:48:31 +0000
treeherderautoland@8828a5a70286 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs1517975
milestone66.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 1517975 - Update webrender to commit 1b226534099a24c741e9827c4612eee1ec12d4ee (WR PR #3478). r=kats https://github.com/servo/webrender/pull/3478 Differential Revision: https://phabricator.services.mozilla.com/D15822
gfx/webrender_bindings/revision.txt
gfx/wr/webrender/src/picture.rs
--- a/gfx/webrender_bindings/revision.txt
+++ b/gfx/webrender_bindings/revision.txt
@@ -1,1 +1,1 @@
-b298150b65db9e80ec15aff6877ca3277cb79f92
+1b226534099a24c741e9827c4612eee1ec12d4ee
--- a/gfx/wr/webrender/src/picture.rs
+++ b/gfx/wr/webrender/src/picture.rs
@@ -1,30 +1,30 @@
 /* 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::{DevicePixelScale, RasterRect, RasterSpace, ColorF, ImageKey, DirtyRect, WorldSize, LayoutSize, ClipMode};
-use api::{PicturePixel, RasterPixel, WorldPixel, WorldRect, ImageFormat, ImageDescriptor, WorldVector2D};
+use api::{DevicePixelScale, RasterRect, RasterSpace, ColorF, ImageKey, DirtyRect, WorldSize, ClipMode};
+use api::{PicturePixel, RasterPixel, WorldPixel, WorldRect, ImageFormat, ImageDescriptor, WorldVector2D, LayoutPoint};
 use box_shadow::{BLUR_SAMPLE_SCALE};
 use clip::{ClipNodeCollector, ClipStore, ClipChainId, ClipChainNode, ClipItem};
 use clip_scroll_tree::{ROOT_SPATIAL_NODE_INDEX, ClipScrollTree, SpatialNodeIndex, CoordinateSystemId};
 use device::TextureFilter;
 use euclid::{TypedScale, vec3, TypedRect, TypedPoint2D, TypedSize2D};
 use euclid::approxeq::ApproxEq;
 use intern::ItemUid;
-use internal_types::{FastHashMap, PlaneSplitter};
+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};
 use prim_store::{PictureIndex, PrimitiveInstance, SpaceMapper, VisibleFace, PrimitiveInstanceKind};
-use prim_store::{get_raster_rects, CoordinateSpaceMapping, VectorKey};
+use prim_store::{get_raster_rects, CoordinateSpaceMapping};
 use prim_store::{OpacityBindingStorage, ImageInstanceStorage, OpacityBindingIndex};
 use print_tree::PrintTreePrinter;
 use render_backend::FrameResources;
 use render_task::{ClearMode, RenderTask, RenderTaskCacheEntryHandle, TileBlit};
 use render_task::{RenderTaskCacheKey, RenderTaskCacheKeyKind, RenderTaskId, RenderTaskLocation};
 use resource_cache::ResourceCache;
 use scene::{FilterOpHelpers, SceneProperties};
 use scene_builder::DocumentResources;
@@ -123,48 +123,54 @@ pub struct Tile {
     pub handle: TextureCacheHandle,
     /// If true, this tile is marked valid, and the existing texture
     /// cache handle can be used. Tiles are invalidated during the
     /// build_dirty_regions method.
     is_valid: bool,
     /// The tile id is stable between display lists and / or frames,
     /// if the tile is retained. Useful for debugging tile evictions.
     id: TileId,
+    /// The set of transforms that affect primitives on this tile we
+    /// care about. Stored as a set here, and then collected, sorted
+    /// and converted to transform key values during post_update.
+    transforms: FastHashSet<SpatialNodeIndex>,
 }
 
 impl Tile {
     /// Construct a new, invalid tile.
     fn new(
         id: TileId,
     ) -> Self {
         Tile {
             local_rect: LayoutRect::zero(),
             world_rect: WorldRect::zero(),
             valid_rect: WorldRect::zero(),
             visible_rect: None,
             handle: TextureCacheHandle::invalid(),
             descriptor: TileDescriptor::new(),
             is_valid: false,
+            transforms: FastHashSet::default(),
             id,
         }
     }
 
     /// Clear the dependencies for a tile.
     fn clear(&mut self) {
+        self.transforms.clear();
         self.descriptor.clear();
     }
 }
 
 /// Defines a key that uniquely identifies a primitive instance.
 #[derive(Debug, Clone, PartialEq)]
 pub struct PrimitiveDescriptor {
     /// Uniquely identifies the content of the primitive template.
     prim_uid: ItemUid,
-    /// The origin in world space of this primitive.
-    origin: WorldPoint,
+    /// The origin in local space of this primitive.
+    origin: LayoutPoint,
     /// The first clip in the clip_uids array of clips that affect this tile.
     first_clip: u16,
     /// The number of clips that affect this primitive instance.
     clip_count: u16,
 }
 
 /// Uniquely describes the content of this tile, in a way that can be
 /// (reasonably) efficiently hashed and compared.
@@ -174,57 +180,63 @@ pub struct TileDescriptor {
     /// to uniquely describe the content of the primitive template, while
     /// the other parameters describe the clip chain and instance params.
     prims: ComparableVec<PrimitiveDescriptor>,
 
     /// List of clip node unique identifiers. The uid is guaranteed
     /// to uniquely describe the content of the clip node.
     clip_uids: ComparableVec<ItemUid>,
 
-    /// List of tile relative offsets of the clip node origins. This
+    /// List of local offsets of the clip node origins. This
     /// ensures that if a clip node is supplied but has a different
     /// transform between frames that the tile is invalidated.
-    clip_vertices: ComparableVec<VectorKey>,
+    clip_vertices: ComparableVec<LayoutPoint>,
 
     /// List of image keys that this tile depends on.
     image_keys: ComparableVec<ImageKey>,
 
     /// The set of opacity bindings that this tile depends on.
     // TODO(gw): Ugh, get rid of all opacity binding support!
     opacity_bindings: ComparableVec<PropertyBindingId>,
 
     /// List of the required valid rectangles for each primitive.
     needed_rects: Vec<WorldRect>,
 
     /// List of the currently valid rectangles for each primitive.
     current_rects: Vec<WorldRect>,
+
+    /// List of the (quantized) transforms that we care about
+    /// tracking for this tile.
+    transforms: ComparableVec<TransformKey>,
 }
 
 impl TileDescriptor {
     fn new() -> Self {
         TileDescriptor {
             prims: ComparableVec::new(),
             clip_uids: ComparableVec::new(),
             clip_vertices: ComparableVec::new(),
             opacity_bindings: ComparableVec::new(),
             image_keys: ComparableVec::new(),
             needed_rects: Vec::new(),
             current_rects: Vec::new(),
+            transforms: ComparableVec::new(),
         }
     }
 
     /// Clear the dependency information for a tile, when the dependencies
     /// are being rebuilt.
     fn clear(&mut self) {
         self.prims.reset();
         self.clip_uids.reset();
         self.clip_vertices.reset();
         self.opacity_bindings.reset();
         self.image_keys.reset();
         self.needed_rects.clear();
+        self.transforms.reset();
     }
 
     /// Check if the dependencies of this tile are valid.
     fn is_valid(&self) -> bool {
         // For a tile to be valid, it needs to ensure that the currently valid
         // rect of each primitive encloses the required valid rect.
         // TODO(gw): This is only needed for tiles that are partially rendered
         //           (i.e. those clipped to edge of screen). We can make this much
@@ -244,16 +256,17 @@ impl TileDescriptor {
             false
         };
 
         self.image_keys.is_valid() &&
         self.opacity_bindings.is_valid() &&
         self.clip_uids.is_valid() &&
         self.clip_vertices.is_valid() &&
         self.prims.is_valid() &&
+        self.transforms.is_valid() &&
         rects_valid
     }
 }
 
 /// Represents the dirty region of a tile cache picture.
 /// In future, we will want to support multiple dirty
 /// regions.
 #[derive(Debug)]
@@ -684,19 +697,20 @@ impl TileCache {
         }
 
         // Get the tile coordinates in the picture space.
         let (p0, p1) = self.get_tile_coords_for_rect(&world_rect);
 
         // Build the list of resources that this primitive has dependencies on.
         let mut opacity_bindings: SmallVec<[PropertyBindingId; 4]> = SmallVec::new();
         let mut clip_chain_uids: SmallVec<[ItemUid; 8]> = SmallVec::new();
-        let mut clip_vertices: SmallVec<[WorldPoint; 8]> = SmallVec::new();
+        let mut clip_vertices: SmallVec<[LayoutPoint; 8]> = SmallVec::new();
         let mut image_keys: SmallVec<[ImageKey; 8]> = SmallVec::new();
         let mut current_clip_chain_id = prim_instance.clip_chain_id;
+        let mut clip_spatial_nodes = FastHashSet::default();
 
         // Some primitives can not be cached (e.g. external video images)
         let is_cacheable = prim_instance.is_cacheable(
             &resources,
             resource_cache,
         );
 
         // For pictures, we don't (yet) know the valid clip rect, so we can't correctly
@@ -814,29 +828,19 @@ impl TileCache {
                 ClipItem::RoundedRectangle(..) |
                 ClipItem::Image { .. } |
                 ClipItem::BoxShadow(..) => {
                     true
                 }
             };
 
             if add_to_clip_deps {
-                // TODO(gw): Constructing a rect here rather than mapping a point
-                //           is wasteful. We can optimize this by extending the
-                //           SpaceMapper struct to support mapping a point.
-                let local_rect = LayoutRect::new(
-                    clip_chain_node.local_pos,
-                    LayoutSize::zero(),
-                );
-
-                if let Some(clip_world_rect) = self.map_local_to_world.map(&local_rect) {
-                    clip_vertices.push(clip_world_rect.origin);
-                }
-
+                clip_vertices.push(clip_chain_node.local_pos);
                 clip_chain_uids.push(clip_chain_node.handle.uid());
+                clip_spatial_nodes.insert(clip_chain_node.spatial_node_index);
             }
 
             current_clip_chain_id = clip_chain_node.parent_clip_chain_id;
         }
 
         if include_clip_rect {
             self.world_bounding_rect = self.world_bounding_rect.union(&world_clip_rect);
         }
@@ -886,47 +890,29 @@ impl TileCache {
                 tile.is_valid &= is_cacheable;
 
                 // Include any image keys this tile depends on.
                 tile.descriptor.image_keys.extend_from_slice(&image_keys);
 
                 // // Include any opacity bindings this primitive depends on.
                 tile.descriptor.opacity_bindings.extend_from_slice(&opacity_bindings);
 
-                // For the primitive origin, store the world origin relative to
-                // the world origin of the containing picture. This ensures that
-                // a tile with primitives in the same coordinate system as the
-                // container picture itself, but different offsets relative to
-                // the containing picture are correctly invalidated. It does this
-                // while still maintaining the property of keeping the same hash
-                // for different display lists where the local origin is different
-                // but the primitives themselves are at the same relative position.
-                let origin = WorldPoint::new(
-                    world_rect.origin.x - tile.world_rect.origin.x,
-                    world_rect.origin.y - tile.world_rect.origin.y
-                );
-
                 // Update the tile descriptor, used for tile comparison during scene swaps.
                 tile.descriptor.prims.push(PrimitiveDescriptor {
                     prim_uid: prim_instance.uid(),
-                    origin,
+                    origin: prim_instance.prim_origin,
                     first_clip: tile.descriptor.clip_uids.len() as u16,
                     clip_count: clip_chain_uids.len() as u16,
                 });
                 tile.descriptor.clip_uids.extend_from_slice(&clip_chain_uids);
+                tile.descriptor.clip_vertices.extend_from_slice(&clip_vertices);
 
-                // Store tile relative clip vertices.
-                // TODO(gw): We might need to quantize these to avoid
-                //           invalidations due to FP accuracy.
-                for clip_vertex in &clip_vertices {
-                    let clip_vertex = VectorKey {
-                        x: clip_vertex.x - tile.world_rect.origin.x,
-                        y: clip_vertex.y - tile.world_rect.origin.y,
-                    };
-                    tile.descriptor.clip_vertices.push(clip_vertex);
+                tile.transforms.insert(prim_instance.spatial_node_index);
+                for spatial_node_index in &clip_spatial_nodes {
+                    tile.transforms.insert(*spatial_node_index);
                 }
             }
         }
     }
 
     /// Apply any updates after prim dependency updates. This applies
     /// any late tile invalidations, and sets up the dirty rect and
     /// set of tile blits.
@@ -962,16 +948,28 @@ impl TileCache {
         );
 
         let local_clip_rect = map_surface_to_world
             .unmap(&self.world_bounding_rect)
             .expect("bug: unable to map local clip rect");
 
         // Step through each tile and invalidate if the dependencies have changed.
         for (i, tile) in self.tiles.iter_mut().enumerate() {
+            // Update tile transforms
+            let mut transform_spatial_nodes: Vec<SpatialNodeIndex> = tile.transforms.drain().collect();
+            transform_spatial_nodes.sort();
+            for spatial_node_index in transform_spatial_nodes {
+                let mapping: CoordinateSpaceMapping<LayoutPixel, PicturePixel> = CoordinateSpaceMapping::new(
+                    self.spatial_node_index,
+                    spatial_node_index,
+                    frame_context.clip_scroll_tree,
+                ).expect("todo: handle invalid mappings");
+                tile.descriptor.transforms.push(mapping.into());
+            }
+
             // Invalidate if the backing texture was evicted.
             if resource_cache.texture_cache.is_allocated(&tile.handle) {
                 // Request the backing texture so it won't get evicted this frame.
                 // We specifically want to mark the tile texture as used, even
                 // if it's detected not visible below and skipped. This is because
                 // we maintain the set of tiles we care about based on visibility
                 // during pre_update. If a tile still exists after that, we are
                 // assuming that it's either visible or we want to retain it for
@@ -995,17 +993,17 @@ impl TileCache {
                 // If the tile is valid, we will generally want to draw it
                 // on screen. However, if there are no primitives there is
                 // no need to draw it.
                 if !tile.descriptor.prims.is_empty() {
                     self.tiles_to_draw.push(TileIndex(i));
                 }
             } else {
                 // Add the tile rect to the dirty rect.
-                dirty_world_rect = dirty_world_rect.union(&tile.world_rect);
+                dirty_world_rect = dirty_world_rect.union(&visible_rect);
 
                 // Ensure that this texture is allocated.
                 resource_cache.texture_cache.update(
                     &mut tile.handle,
                     descriptor,
                     TextureFilter::Linear,
                     None,
                     [0.0; 3],