Bug 1510883 - Update webrender to commit be659494b4f8d80081ea282c4b9b4c9170a70ef7 (WR PR #3362). r=kats
authorWR Updater Bot <graphics-team@mozilla.staktrace.com>
Thu, 29 Nov 2018 03:31:22 +0000
changeset 505093 54d56b9a77fb9d41eff3ce1662ba5fff538365d2
parent 505092 b6628da730a9dd6c5d88fd75e4b1b6878d357e4e
child 505094 4afa2578087306e0861987f20ee1a3de607b840d
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs1510883
milestone65.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 1510883 - Update webrender to commit be659494b4f8d80081ea282c4b9b4c9170a70ef7 (WR PR #3362). r=kats https://github.com/servo/webrender/pull/3362 Differential Revision: https://phabricator.services.mozilla.com/D13355
gfx/webrender_bindings/revision.txt
gfx/wr/webrender/src/display_list_flattener.rs
gfx/wr/webrender/src/frame_builder.rs
gfx/wr/webrender/src/prim_store.rs
gfx/wr/webrender/src/util.rs
gfx/wr/webrender_api/src/display_list.rs
--- a/gfx/webrender_bindings/revision.txt
+++ b/gfx/webrender_bindings/revision.txt
@@ -1,1 +1,1 @@
-0c6b52ec22023fae247baaa98f6ca1615ef523c8
+be659494b4f8d80081ea282c4b9b4c9170a70ef7
--- a/gfx/wr/webrender/src/display_list_flattener.rs
+++ b/gfx/wr/webrender/src/display_list_flattener.rs
@@ -29,17 +29,17 @@ use prim_store::{ScrollNodeAndClipChain,
 use render_backend::{DocumentView};
 use resource_cache::{FontInstanceMap, ImageRequest};
 use scene::{Scene, ScenePipeline, StackingContextHelpers};
 use scene_builder::DocumentResources;
 use spatial_node::{StickyFrameInfo};
 use std::{f32, mem};
 use std::collections::vec_deque::VecDeque;
 use tiling::{CompositeOps};
-use util::{MaxRect};
+use util::{MaxRect, VecHelper};
 
 #[derive(Debug, Copy, Clone)]
 struct ClipNode {
     id: ClipChainId,
     count: usize,
 }
 
 impl ClipNode {
@@ -1109,33 +1109,34 @@ impl<'a> DisplayListFlattener<'a> {
                     // the owning target.
                     None
                 },
                 stacking_context.frame_output_pipeline_id
             ),
         };
 
         // Add picture for this actual stacking context contents to render into.
-        let prim_list = PrimitiveList::new(
-            stacking_context.primitives,
-            &self.resources.prim_interner,
+        let leaf_pic_index = PictureIndex(self.prim_store.pictures
+            .alloc()
+            .init(PicturePrimitive::new_image(
+                leaf_composite_mode,
+                leaf_context_3d,
+                stacking_context.pipeline_id,
+                leaf_output_pipeline_id,
+                true,
+                stacking_context.requested_raster_space,
+                PrimitiveList::new(
+                    stacking_context.primitives,
+                    &self.resources.prim_interner,
+                ),
+                stacking_context.spatial_node_index,
+                max_clip,
+                &self.clip_store,
+            ))
         );
-        let leaf_picture = PicturePrimitive::new_image(
-            leaf_composite_mode,
-            leaf_context_3d,
-            stacking_context.pipeline_id,
-            leaf_output_pipeline_id,
-            true,
-            stacking_context.requested_raster_space,
-            prim_list,
-            stacking_context.spatial_node_index,
-            max_clip,
-            &self.clip_store,
-        );
-        let leaf_pic_index = self.prim_store.create_picture(leaf_picture);
 
         // Create a chain of pictures based on presence of filters,
         // mix-blend-mode and/or 3d rendering context containers.
 
         let mut current_pic_index = leaf_pic_index;
         let mut cur_instance = PrimitiveInstance::new(
             PrimitiveInstanceKind::Picture { pic_index: leaf_pic_index },
             stacking_context.primitive_data_handle,
@@ -1148,99 +1149,99 @@ impl<'a> DisplayListFlattener<'a> {
         }
 
         // If establishing a 3d context, the `cur_instance` represents
         // a picture with all the *trailing* immediate children elements.
         // We append this to the preserve-3D picture set and make a container picture of them.
         if let Picture3DContext::In { root_data: Some(mut prims), ancestor_index } = stacking_context.context_3d {
             prims.push(cur_instance.clone());
 
-            let prim_list = PrimitiveList::new(
-                prims,
-                &self.resources.prim_interner,
+            // This is the acttual picture representing our 3D hierarchy root.
+            current_pic_index = PictureIndex(self.prim_store.pictures
+                .alloc()
+                .init(PicturePrimitive::new_image(
+                    None,
+                    Picture3DContext::In {
+                        root_data: Some(Vec::new()),
+                        ancestor_index,
+                    },
+                    stacking_context.pipeline_id,
+                    stacking_context.frame_output_pipeline_id,
+                    true,
+                    stacking_context.requested_raster_space,
+                    PrimitiveList::new(
+                        prims,
+                        &self.resources.prim_interner,
+                    ),
+                    stacking_context.spatial_node_index,
+                    max_clip,
+                    &self.clip_store,
+                ))
             );
 
-            // This is the acttual picture representing our 3D hierarchy root.
-            let container_picture = PicturePrimitive::new_image(
-                None,
-                Picture3DContext::In {
-                    root_data: Some(Vec::new()),
-                    ancestor_index,
-                },
-                stacking_context.pipeline_id,
-                stacking_context.frame_output_pipeline_id,
-                true,
-                stacking_context.requested_raster_space,
-                prim_list,
-                stacking_context.spatial_node_index,
-                max_clip,
-                &self.clip_store,
-            );
-
-            current_pic_index = self.prim_store.create_picture(container_picture);
-
             cur_instance.kind = PrimitiveInstanceKind::Picture { pic_index: current_pic_index };
         }
 
         // For each filter, create a new image with that composite mode.
         for filter in &stacking_context.composite_ops.filters {
             let filter = filter.sanitize();
-            let prim_list = PrimitiveList::new(
-                vec![cur_instance.clone()],
-                &self.resources.prim_interner,
+
+            let filter_pic_index = PictureIndex(self.prim_store.pictures
+                .alloc()
+                .init(PicturePrimitive::new_image(
+                    Some(PictureCompositeMode::Filter(filter)),
+                    Picture3DContext::Out,
+                    stacking_context.pipeline_id,
+                    None,
+                    true,
+                    stacking_context.requested_raster_space,
+                    PrimitiveList::new(
+                        vec![cur_instance.clone()],
+                        &self.resources.prim_interner,
+                    ),
+                    stacking_context.spatial_node_index,
+                    max_clip,
+                    &self.clip_store,
+                ))
             );
 
-            let filter_picture = PicturePrimitive::new_image(
-                Some(PictureCompositeMode::Filter(filter)),
-                Picture3DContext::Out,
-                stacking_context.pipeline_id,
-                None,
-                true,
-                stacking_context.requested_raster_space,
-                prim_list,
-                stacking_context.spatial_node_index,
-                max_clip,
-                &self.clip_store,
-            );
-            let filter_pic_index = self.prim_store.create_picture(filter_picture);
             current_pic_index = filter_pic_index;
-
             cur_instance.kind = PrimitiveInstanceKind::Picture { pic_index: current_pic_index };
 
             if cur_instance.is_chased() {
                 println!("\tis a composite picture for a stacking context with {:?}", filter);
             }
 
             // Run the optimize pass on this picture, to see if we can
             // collapse opacity and avoid drawing to an off-screen surface.
             self.prim_store.optimize_picture_if_possible(current_pic_index);
         }
 
         // Same for mix-blend-mode.
         if let Some(mix_blend_mode) = stacking_context.composite_ops.mix_blend_mode {
-            let prim_list = PrimitiveList::new(
-                vec![cur_instance.clone()],
-                &self.resources.prim_interner,
+            let blend_pic_index = PictureIndex(self.prim_store.pictures
+                .alloc()
+                .init(PicturePrimitive::new_image(
+                    Some(PictureCompositeMode::MixBlend(mix_blend_mode)),
+                    Picture3DContext::Out,
+                    stacking_context.pipeline_id,
+                    None,
+                    true,
+                    stacking_context.requested_raster_space,
+                    PrimitiveList::new(
+                        vec![cur_instance.clone()],
+                        &self.resources.prim_interner,
+                    ),
+                    stacking_context.spatial_node_index,
+                    max_clip,
+                    &self.clip_store,
+                ))
             );
 
-            let blend_picture = PicturePrimitive::new_image(
-                Some(PictureCompositeMode::MixBlend(mix_blend_mode)),
-                Picture3DContext::Out,
-                stacking_context.pipeline_id,
-                None,
-                true,
-                stacking_context.requested_raster_space,
-                prim_list,
-                stacking_context.spatial_node_index,
-                max_clip,
-                &self.clip_store,
-            );
-            let blend_pic_index = self.prim_store.create_picture(blend_picture);
             current_pic_index = blend_pic_index;
-
             cur_instance.kind = PrimitiveInstanceKind::Picture { pic_index: blend_pic_index };
 
             if cur_instance.is_chased() {
                 println!("\tis a mix-blend picture for a stacking context with {:?}", mix_blend_mode);
             }
         }
 
         let has_mix_blend_on_secondary_framebuffer =
@@ -1548,41 +1549,41 @@ impl<'a> DisplayListFlattener<'a> {
                             // Add the new primitive to the shadow picture.
                             prims.push(shadow_prim_instance);
                         }
                     }
 
                     // No point in adding a shadow here if there were no primitives
                     // added to the shadow.
                     if !prims.is_empty() {
-                        let prim_list = PrimitiveList::new(
-                            prims,
-                            &self.resources.prim_interner,
-                        );
-
                         // Create a picture that the shadow primitives will be added to. If the
                         // blur radius is 0, the code in Picture::prepare_for_render will
                         // detect this and mark the picture to be drawn directly into the
                         // parent picture, which avoids an intermediate surface and blur.
                         let blur_filter = FilterOp::Blur(std_deviation).sanitize();
-                        let mut shadow_pic = PicturePrimitive::new_image(
-                            Some(PictureCompositeMode::Filter(blur_filter)),
-                            Picture3DContext::Out,
-                            pipeline_id,
-                            None,
-                            is_passthrough,
-                            raster_space,
-                            prim_list,
-                            pending_shadow.clip_and_scroll.spatial_node_index,
-                            max_clip,
-                            &self.clip_store,
-                        );
 
                         // Create the primitive to draw the shadow picture into the scene.
-                        let shadow_pic_index = self.prim_store.create_picture(shadow_pic);
+                        let shadow_pic_index = PictureIndex(self.prim_store.pictures
+                            .alloc()
+                            .init(PicturePrimitive::new_image(
+                                Some(PictureCompositeMode::Filter(blur_filter)),
+                                Picture3DContext::Out,
+                                pipeline_id,
+                                None,
+                                is_passthrough,
+                                raster_space,
+                                PrimitiveList::new(
+                                    prims,
+                                    &self.resources.prim_interner,
+                                ),
+                                pending_shadow.clip_and_scroll.spatial_node_index,
+                                max_clip,
+                                &self.clip_store,
+                            ))
+                        );
 
                         let shadow_prim_key = PrimitiveKey::new(
                             true,
                             LayoutRect::zero(),
                             LayoutRect::max_rect(),
                             PrimitiveKeyKind::Unused,
                         );
 
@@ -2198,36 +2199,35 @@ impl FlattenedStackingContext {
         let flat_items_context_3d = match self.context_3d {
             Picture3DContext::In { ancestor_index, .. } => Picture3DContext::In {
                 root_data: None,
                 ancestor_index,
             },
             Picture3DContext::Out => panic!("Unexpected out of 3D context"),
         };
 
-        let prim_list = PrimitiveList::new(
-            mem::replace(&mut self.primitives, Vec::new()),
-            prim_interner,
+        let pic_index = PictureIndex(prim_store.pictures
+            .alloc()
+            .init(PicturePrimitive::new_image(
+                Some(PictureCompositeMode::Blit),
+                flat_items_context_3d,
+                self.pipeline_id,
+                None,
+                true,
+                self.requested_raster_space,
+                PrimitiveList::new(
+                    mem::replace(&mut self.primitives, Vec::new()),
+                    prim_interner,
+                ),
+                self.spatial_node_index,
+                LayoutRect::max_rect(),
+                clip_store,
+            ))
         );
 
-        let container_picture = PicturePrimitive::new_image(
-            Some(PictureCompositeMode::Blit),
-            flat_items_context_3d,
-            self.pipeline_id,
-            None,
-            true,
-            self.requested_raster_space,
-            prim_list,
-            self.spatial_node_index,
-            LayoutRect::max_rect(),
-            clip_store,
-        );
-
-        let pic_index = prim_store.create_picture(container_picture);
-
         Some(PrimitiveInstance::new(
             PrimitiveInstanceKind::Picture { pic_index },
             self.primitive_data_handle,
             self.clip_chain_id,
             self.spatial_node_index,
         ))
     }
 }
--- a/gfx/wr/webrender/src/frame_builder.rs
+++ b/gfx/wr/webrender/src/frame_builder.rs
@@ -375,17 +375,17 @@ impl FrameBuilder {
         debug_assert!(
             DeviceIntRect::new(DeviceIntPoint::zero(), self.window_size)
                 .contains_rect(&self.screen_rect)
         );
 
         let mut profile_counters = FrameProfileCounters::new();
         profile_counters
             .total_primitives
-            .set(self.prim_store.prim_count);
+            .set(self.prim_store.prim_count());
 
         resource_cache.begin_frame(stamp);
         gpu_cache.begin_frame(stamp.frame_id());
 
         let mut transform_palette = TransformPalette::new();
         clip_scroll_tree.update_tree(
             pan,
             scene_properties,
--- a/gfx/wr/webrender/src/prim_store.rs
+++ b/gfx/wr/webrender/src/prim_store.rs
@@ -2582,30 +2582,25 @@ pub struct PrimitiveStore {
 
     /// A list of image instances. These are stored separately as
     /// storing them inline in the instance makes the structure bigger
     /// for other types.
     pub images: ImageInstanceStorage,
 
     /// List of animated opacity bindings for a primitive.
     pub opacity_bindings: OpacityBindingStorage,
-
-    /// Total count of primitive instances contained in pictures.
-    /// This is used for profile counters only.
-    pub prim_count: usize,
 }
 
 impl PrimitiveStore {
     pub fn new(stats: &PrimitiveStoreStats) -> PrimitiveStore {
         PrimitiveStore {
             pictures: Vec::with_capacity(stats.picture_count),
             text_runs: TextRunStorage::new(stats.text_run_count),
             images: ImageInstanceStorage::new(stats.image_count),
             opacity_bindings: OpacityBindingStorage::new(stats.opacity_binding_count),
-            prim_count: 0,
         }
     }
 
     pub fn get_stats(&self) -> PrimitiveStoreStats {
         PrimitiveStoreStats {
             picture_count: self.pictures.len(),
             text_run_count: self.text_runs.len(),
             image_count: self.images.len(),
@@ -2621,24 +2616,22 @@ impl PrimitiveStore {
     ) {
         for pic in self.pictures {
             pic.destroy(
                 retained_tiles,
             );
         }
     }
 
-    pub fn create_picture(
-        &mut self,
-        prim: PicturePrimitive,
-    ) -> PictureIndex {
-        let index = PictureIndex(self.pictures.len());
-        self.prim_count += prim.prim_list.prim_instances.len();
-        self.pictures.push(prim);
-        index
+    /// Returns the total count of primitive instances contained in pictures.
+    pub fn prim_count(&self) -> usize {
+        self.pictures
+            .iter()
+            .map(|p| p.prim_list.prim_instances.len())
+            .sum()
     }
 
     /// Update a picture, determining surface configuration,
     /// rasterization roots, and (in future) whether there
     /// are cached surfaces that can be used by this picture.
     pub fn update_picture(
         &mut self,
         pic_index: PictureIndex,
--- a/gfx/wr/webrender/src/util.rs
+++ b/gfx/wr/webrender/src/util.rs
@@ -3,22 +3,63 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use api::{BorderRadius, DeviceIntPoint, DeviceIntRect, DeviceIntSize, DevicePixelScale};
 use api::{LayoutPixel, DeviceRect, WorldPixel, RasterRect};
 use euclid::{Point2D, Rect, Size2D, TypedPoint2D, TypedRect, TypedSize2D, Vector2D};
 use euclid::{TypedTransform2D, TypedTransform3D, TypedVector2D, TypedScale};
 use num_traits::Zero;
 use plane_split::{Clipper, Polygon};
-use std::{i32, f32, fmt};
+use std::{i32, f32, fmt, ptr};
 use std::borrow::Cow;
 
+
 // Matches the definition of SK_ScalarNearlyZero in Skia.
 const NEARLY_ZERO: f32 = 1.0 / 4096.0;
 
+/// A typesafe helper that separates new value construction from
+/// vector growing, allowing LLVM to ideally construct the element in place.
+#[must_use]
+pub struct Allocation<'a, T: 'a> {
+    vec: &'a mut Vec<T>,
+    index: usize,
+}
+
+impl<'a, T> Allocation<'a, T> {
+    // writing is safe because alloc() ensured enough capacity
+    // and `Allocation` holds a mutable borrow to prevent anyone else
+    // from breaking this invariant.
+    #[inline(always)]
+    pub fn init(self, value: T) -> usize {
+        unsafe {
+            ptr::write(self.vec.as_mut_ptr().add(self.index), value);
+            self.vec.set_len(self.index + 1);
+        }
+        self.index
+    }
+}
+
+pub trait VecHelper<T> {
+    fn alloc(&mut self) -> Allocation<T>;
+}
+
+impl<T> VecHelper<T> for Vec<T> {
+    fn alloc(&mut self) -> Allocation<T> {
+        let index = self.len();
+        if self.capacity() == index {
+            self.reserve(1);
+        }
+        Allocation {
+            vec: self,
+            index,
+        }
+    }
+}
+
+
 // Represents an optimized transform where there is only
 // a scale and translation (which are guaranteed to maintain
 // an axis align rectangle under transformation). The
 // scaling is applied first, followed by the translation.
 // TODO(gw): We should try and incorporate F <-> T units here,
 //           but it's a bit tricky to do that now with the
 //           way the current clip-scroll tree works.
 #[derive(Debug, Clone, Copy)]
--- a/gfx/wr/webrender_api/src/display_list.rs
+++ b/gfx/wr/webrender_api/src/display_list.rs
@@ -945,17 +945,17 @@ impl DisplayListBuilder {
         let mut temp = BuiltDisplayList::default();
         mem::swap(&mut temp.data, &mut self.data);
 
         let mut index: usize = 0;
         {
             let mut iter = BuiltDisplayListIter::new(&temp);
             while let Some(item) = iter.next_raw() {
                 if index >= range.start.unwrap_or(0) && range.end.map_or(true, |e| index < e) {
-                    writeln!(sink, "{}{:?}", "  ".repeat(indent), item.display_item());
+                    writeln!(sink, "{}{:?}", "  ".repeat(indent), item.display_item()).unwrap();
                 }
                 index += 1;
             }
         }
 
         self.data = temp.data;
         index
     }