Bug 1493097. Update webrender to commit 97a3807ea8266c324feb3ecada2ac5fd78c80e9b
authorJeff Muizelaar <jmuizelaar@mozilla.com>
Fri, 21 Sep 2018 15:36:53 -0400
changeset 493505 4e06207dc9fee5c03e7fcb7fbc3e3f549e20c382
parent 493504 bdb144bdca1649682b0a34712eb9aad3c4c799da
child 493506 d0f96a364b8fe8a2eaa516571c420b853a2021b2
push id9984
push userffxbld-merge
push dateMon, 15 Oct 2018 21:07:35 +0000
treeherdermozilla-beta@183d27ea8570 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1493097
milestone64.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 1493097. Update webrender to commit 97a3807ea8266c324feb3ecada2ac5fd78c80e9b
gfx/webrender/Cargo.toml
gfx/webrender/src/batch.rs
gfx/webrender/src/border.rs
gfx/webrender/src/gpu_types.rs
gfx/webrender/src/render_backend.rs
gfx/webrender/src/resource_cache.rs
gfx/webrender_api/src/api.rs
gfx/webrender_api/src/font.rs
gfx/webrender_bindings/revision.txt
--- a/gfx/webrender/Cargo.toml
+++ b/gfx/webrender/Cargo.toml
@@ -27,17 +27,17 @@ byteorder = "1.0"
 cfg-if = "0.1.2"
 euclid = "0.19"
 fxhash = "0.2.1"
 gleam = "0.6"
 image = { optional = true, version = "0.19" }
 lazy_static = "1"
 log = "0.4"
 num-traits = "0.2"
-plane-split = "0.13"
+plane-split = "0.13.1"
 png = { optional = true, version = "0.12" }
 rayon = "1"
 ron = { optional = true, version = "0.1.7" }
 serde = { optional = true, version = "1.0", features = ["serde_derive"] }
 serde_json = { optional = true, version = "1.0" }
 smallvec = "0.6"
 thread_profiler = "0.1.1"
 time = "0.1"
--- a/gfx/webrender/src/batch.rs
+++ b/gfx/webrender/src/batch.rs
@@ -698,19 +698,21 @@ impl AlphaBatchBuilder {
                             // since we determine the UVs by doing a bilerp with a factor
                             // from the original local rect.
                             let local_rect = prim_metadata.local_rect
                                                           .intersection(&prim_metadata.combined_local_clip_rect);
 
                             if let Some(local_rect) = local_rect {
                                 match transform.transform_kind() {
                                     TransformedRectKind::AxisAligned => {
-                                        let polygon = Polygon::from_transformed_rect(
+                                        let inv_transform = transforms.get_world_inv_transform(prim_metadata.spatial_node_index);
+                                        let polygon = Polygon::from_transformed_rect_with_inverse(
                                             local_rect.cast(),
-                                            transform.cast(),
+                                            &transform.cast(),
+                                            &inv_transform.cast(),
                                             prim_index.0,
                                         ).unwrap();
                                         splitter.add(polygon);
                                     }
                                     TransformedRectKind::Complex => {
                                         let mut clipper = Clipper::new();
                                         let matrix = transform.cast();
                                         let results = clipper.clip_transformed(
--- a/gfx/webrender/src/border.rs
+++ b/gfx/webrender/src/border.rs
@@ -3,16 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 use api::{BorderRadius, BorderSide, BorderStyle, ColorF, ColorU, DeviceRect, DeviceSize};
 use api::{LayoutSideOffsets, LayoutSizeAu, LayoutPrimitiveInfo, LayoutToDeviceScale};
 use api::{DeviceVector2D, DevicePoint, DeviceIntSize, LayoutRect, LayoutSize, NormalBorder};
 use api::{AuHelpers};
 use app_units::Au;
 use ellipse::Ellipse;
+use euclid::SideOffsets2D;
 use display_list_flattener::DisplayListFlattener;
 use gpu_types::{BorderInstance, BorderSegment, BrushFlags};
 use prim_store::{BrushKind, BrushPrimitive, BrushSegment};
 use prim_store::{EdgeAaSegmentMask, PrimitiveContainer, ScrollNodeAndClipChain};
 use util::{lerp, RectHelpers};
 
 // Using 2048 as the maximum radius in device space before which we
 // start stretching is up for debate.
@@ -73,37 +74,16 @@ impl From<BorderRadiusAu> for BorderRadi
             bottom_left: LayoutSize::from_au(radius.bottom_left),
         }
     }
 }
 
 #[derive(Clone, Debug, Hash, PartialEq, Eq)]
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
-pub struct BorderWidthsAu {
-    pub left: Au,
-    pub top: Au,
-    pub right: Au,
-    pub bottom: Au,
-}
-
-impl From<LayoutSideOffsets> for BorderWidthsAu {
-    fn from(widths: LayoutSideOffsets) -> Self {
-        BorderWidthsAu {
-            left: Au::from_f32_px(widths.left),
-            top: Au::from_f32_px(widths.top),
-            right: Au::from_f32_px(widths.right),
-            bottom: Au::from_f32_px(widths.bottom),
-        }
-    }
-}
-
-#[derive(Clone, Debug, Hash, PartialEq, Eq)]
-#[cfg_attr(feature = "capture", derive(Serialize))]
-#[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct BorderSideAu {
     pub color: ColorU,
     pub style: BorderStyle,
 }
 
 impl From<BorderSide> for BorderSideAu {
     fn from(side: BorderSide) -> Self {
         BorderSideAu {
@@ -117,28 +97,33 @@ impl From<BorderSide> for BorderSideAu {
 #[cfg_attr(feature = "capture", derive(Serialize))]
 #[cfg_attr(feature = "replay", derive(Deserialize))]
 pub struct BorderCacheKey {
     pub left: BorderSideAu,
     pub right: BorderSideAu,
     pub top: BorderSideAu,
     pub bottom: BorderSideAu,
     pub radius: BorderRadiusAu,
-    pub widths: BorderWidthsAu,
+    pub widths: SideOffsets2D<Au>,
     pub scale: Au,
 }
 
 impl BorderCacheKey {
     pub fn new(border: &NormalBorder, widths: &LayoutSideOffsets) -> Self {
         BorderCacheKey {
             left: border.left.into(),
             top: border.top.into(),
             right: border.right.into(),
             bottom: border.bottom.into(),
-            widths: (*widths).into(),
+            widths: SideOffsets2D::new(
+                Au::from_f32_px(widths.top),
+                Au::from_f32_px(widths.right),
+                Au::from_f32_px(widths.bottom),
+                Au::from_f32_px(widths.left),
+            ),
             radius: border.radius.into(),
             scale: Au(0),
         }
     }
 }
 
 pub fn ensure_no_corner_overlap(
     radius: &mut BorderRadius,
--- a/gfx/webrender/src/gpu_types.rs
+++ b/gfx/webrender/src/gpu_types.rs
@@ -1,14 +1,17 @@
 /* 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::{DevicePoint, DeviceSize, DeviceRect, LayoutRect, LayoutToWorldTransform, LayoutTransform};
-use api::{PremultipliedColorF, LayoutToPictureTransform, PictureToLayoutTransform, PicturePixel, WorldPixel};
+use api::{
+    DevicePoint, DeviceSize, DeviceRect, LayoutRect, LayoutToWorldTransform, LayoutTransform,
+    PremultipliedColorF, LayoutToPictureTransform, PictureToLayoutTransform, PicturePixel,
+    WorldPixel, WorldToLayoutTransform,
+};
 use clip_scroll_tree::{ClipScrollTree, ROOT_SPATIAL_NODE_INDEX, SpatialNodeIndex};
 use gpu_cache::{GpuCacheAddress, GpuDataRequest};
 use internal_types::FastHashMap;
 use prim_store::EdgeAaSegmentMask;
 use render_task::RenderTaskAddress;
 use util::{TransformedRectKind, MatrixHelpers};
 
 // Contains type that must exactly match the same structures declared in GLSL.
@@ -482,16 +485,25 @@ impl TransformPalette {
         &self,
         index: SpatialNodeIndex,
     ) -> LayoutToWorldTransform {
         self.transforms[index.0]
             .transform
             .with_destination::<WorldPixel>()
     }
 
+    pub fn get_world_inv_transform(
+        &self,
+        index: SpatialNodeIndex,
+    ) -> WorldToLayoutTransform {
+        self.transforms[index.0]
+            .inv_transform
+            .with_source::<WorldPixel>()
+    }
+
     // Get a transform palette id for the given spatial node.
     // TODO(gw): In the future, it will be possible to specify
     //           a coordinate system id here, to allow retrieving
     //           transforms in the local space of a given spatial node.
     pub fn get_id(
         &mut self,
         from_index: SpatialNodeIndex,
         to_index: SpatialNodeIndex,
--- a/gfx/webrender/src/render_backend.rs
+++ b/gfx/webrender/src/render_backend.rs
@@ -1185,27 +1185,29 @@ impl RenderBackend {
 
     fn size_of<T>(&self, ptr: *const T) -> usize {
         let op = self.size_of_op.as_ref().unwrap();
         unsafe { op(ptr as *const c_void) }
     }
 
     fn report_memory(&self) -> MemoryReport {
         let mut report = MemoryReport::default();
-        let op = self.size_of_op.as_ref().unwrap();
-        report.gpu_cache_metadata = self.gpu_cache.malloc_size_of(*op);
+        let op = self.size_of_op.unwrap();
+        report.gpu_cache_metadata = self.gpu_cache.malloc_size_of(op);
         for (_id, doc) in &self.documents {
             if let Some(ref fb) = doc.frame_builder {
                 report.primitive_stores += self.size_of(fb.prim_store.primitives.as_ptr());
-                report.clip_stores += fb.clip_store.malloc_size_of(*op);
+                report.clip_stores += fb.clip_store.malloc_size_of(op);
             }
             report.hit_testers +=
-                doc.hit_tester.as_ref().map_or(0, |ht| ht.malloc_size_of(*op));
+                doc.hit_tester.as_ref().map_or(0, |ht| ht.malloc_size_of(op));
         }
 
+        report += self.resource_cache.report_memory(op);
+
         report
     }
 }
 
 fn get_blob_image_updates(updates: &[ResourceUpdate]) -> Vec<ImageKey> {
     let mut requests = Vec::new();
     for update in updates {
         match *update {
--- a/gfx/webrender/src/resource_cache.rs
+++ b/gfx/webrender/src/resource_cache.rs
@@ -5,16 +5,17 @@
 use api::{AddFont, BlobImageResources, AsyncBlobImageRasterizer, ResourceUpdate};
 use api::{BlobImageDescriptor, BlobImageHandler, BlobImageRequest, RasterizedBlobImage};
 use api::{ClearCache, ColorF, DevicePoint, DeviceUintPoint, DeviceUintRect, DeviceUintSize};
 use api::{FontInstanceKey, FontKey, FontTemplate, GlyphIndex};
 use api::{ExternalImageData, ExternalImageType, BlobImageResult, BlobImageParams};
 use api::{FontInstanceData, FontInstanceOptions, FontInstancePlatformOptions, FontVariation};
 use api::{GlyphDimensions, IdNamespace};
 use api::{ImageData, ImageDescriptor, ImageKey, ImageRendering};
+use api::{MemoryReport, VoidPtrToSizeFn};
 use api::{TileOffset, TileSize, TileRange, NormalizedRect, BlobImageData};
 use app_units::Au;
 #[cfg(feature = "capture")]
 use capture::ExternalCaptureImage;
 #[cfg(feature = "replay")]
 use capture::PlainExternalImage;
 #[cfg(any(feature = "replay", feature = "png"))]
 use capture::CaptureConfig;
@@ -29,20 +30,21 @@ use gpu_types::UvRectKind;
 use image::{compute_tile_range, for_each_tile_in_range};
 use internal_types::{FastHashMap, FastHashSet, SourceTexture, TextureUpdateList};
 use profiler::{ResourceProfileCounters, TextureCacheProfileCounters};
 use render_backend::FrameId;
 use render_task::{RenderTaskCache, RenderTaskCacheKey, RenderTaskId};
 use render_task::{RenderTaskCacheEntry, RenderTaskCacheEntryHandle, RenderTaskTree};
 use smallvec::SmallVec;
 use std::collections::hash_map::Entry::{self, Occupied, Vacant};
-use std::collections::hash_map::ValuesMut;
+use std::collections::hash_map::IterMut;
 use std::{cmp, mem};
 use std::fmt::Debug;
 use std::hash::Hash;
+use std::os::raw::c_void;
 #[cfg(any(feature = "capture", feature = "replay"))]
 use std::path::PathBuf;
 use std::sync::{Arc, RwLock};
 use texture_cache::{TextureCache, TextureCacheHandle, Eviction};
 use tiling::SpecialRenderPasses;
 use util::drain_filter;
 
 const DEFAULT_TILE_SIZE: TileSize = 512;
@@ -240,18 +242,18 @@ where
     pub fn try_get_mut(&mut self, key: &K) -> Option<&mut V> {
         self.resources.get_mut(key)
     }
 
     pub fn entry(&mut self, key: K) -> Entry<K, V> {
         self.resources.entry(key)
     }
 
-    pub fn values_mut(&mut self) -> ValuesMut<K, V> {
-        self.resources.values_mut()
+    pub fn iter_mut(&mut self) -> IterMut<K, V> {
+        self.resources.iter_mut()
     }
 
     pub fn clear(&mut self) {
         self.resources.clear();
     }
 
     fn clear_keys<F>(&mut self, key_fun: F)
     where
@@ -374,16 +376,21 @@ impl BlobImageResources for Resources {
         self.image_templates
             .get(key)
             .map(|resource| (&resource.data, &resource.descriptor))
     }
 }
 
 pub type GlyphDimensionsCache = FastHashMap<(FontInstance, GlyphIndex), Option<GlyphDimensions>>;
 
+/// High-level container for resources managed by the `RenderBackend`.
+///
+/// This includes a variety of things, including images, fonts, and glyphs,
+/// which may be stored as memory buffers, GPU textures, or handles to resources
+/// managed by the OS or other parts of WebRender.
 pub struct ResourceCache {
     cached_glyphs: GlyphCache,
     cached_images: ImageCache,
     cached_render_tasks: RenderTaskCache,
 
     resources: Resources,
     state: State,
     current_frame_id: FrameId,
@@ -748,18 +755,31 @@ impl ResourceCache {
 
         // Each cache entry stores its own copy of the image's dirty rect. This allows them to be
         // updated independently.
         match self.cached_images.try_get_mut(&image_key) {
             Some(&mut ImageResult::UntiledAuto(ref mut entry)) => {
                 entry.dirty_rect = merge_dirty_rect(&entry.dirty_rect, &dirty_rect, &descriptor);
             }
             Some(&mut ImageResult::Multi(ref mut entries)) => {
-                for entry in entries.values_mut() {
-                    entry.dirty_rect = merge_dirty_rect(&entry.dirty_rect, &dirty_rect, &descriptor);
+                for (key, entry) in entries.iter_mut() {
+                    let merged_rect = merge_dirty_rect(&entry.dirty_rect, &dirty_rect, &descriptor);
+
+                    entry.dirty_rect = match (key.tile, merged_rect) {
+                        (Some(tile), Some(rect)) => {
+                            let tile_size = image.tiling.unwrap();
+                            let clipped_tile_size = compute_tile_size(&descriptor, tile_size, tile);
+
+                            rect.intersection(&DeviceUintRect::new(
+                                DeviceUintPoint::new(tile.x as u32, tile.y as u32) * tile_size as u32,
+                                clipped_tile_size,
+                            ))
+                        }
+                        _ => merged_rect,
+                    };
                 }
             }
             _ => {}
         }
 
         *image = ImageResource {
             descriptor,
             data,
@@ -1623,16 +1643,51 @@ impl ResourceCache {
             .retain(|key, _| key.0 != namespace);
         self.cached_glyphs
             .clear_fonts(|font| font.font_key.0 == namespace);
 
         if let Some(ref mut r) = self.blob_image_handler {
             r.clear_namespace(namespace);
         }
     }
+
+    /// Reports the CPU heap usage of this ResourceCache.
+    pub fn report_memory(&self, op: VoidPtrToSizeFn) -> MemoryReport {
+        let mut report = MemoryReport::default();
+
+        // Measure fonts. We only need the templates here, because the instances
+        // don't have big buffers.
+        for (_, font) in self.resources.font_templates.iter() {
+            if let FontTemplate::Raw(ref raw, _) = font {
+                report.fonts += unsafe { op(raw.as_ptr() as *const c_void) };
+            }
+        }
+
+        // Measure images.
+        for (_, image) in self.resources.image_templates.images.iter() {
+            report.images += match image.data {
+                ImageData::Raw(ref v) => unsafe { op(v.as_ptr() as *const c_void) },
+                ImageData::Blob(ref v) => unsafe { op(v.as_ptr() as *const c_void) },
+                ImageData::External(..) => 0,
+            }
+        }
+
+        // Mesure rasterized blobs.
+        for (_, image) in self.rasterized_blob_images.iter() {
+            let mut accumulate = |b: &RasterizedBlobImage| {
+                report.rasterized_blobs += unsafe { op(b.data.as_ptr() as *const c_void) };
+            };
+            match image {
+                RasterizedBlob::Tiled(map) => map.values().for_each(&mut accumulate),
+                RasterizedBlob::NonTiled(vec) => vec.iter().for_each(&mut accumulate),
+            };
+        }
+
+        report
+    }
 }
 
 pub fn get_blob_tiling(
     tiling: Option<TileSize>,
     descriptor: &ImageDescriptor,
     max_texture_size: u32,
 ) -> Option<TileSize> {
     if tiling.is_none() &&
--- a/gfx/webrender_api/src/api.rs
+++ b/gfx/webrender_api/src/api.rs
@@ -752,26 +752,32 @@ impl PipelineId {
 #[derive(Clone, Debug, Default, Deserialize, Serialize)]
 pub struct MemoryReport {
     pub primitive_stores: usize,
     pub clip_stores: usize,
     pub gpu_cache_metadata: usize,
     pub gpu_cache_cpu_mirror: usize,
     pub render_tasks: usize,
     pub hit_testers: usize,
+    pub fonts: usize,
+    pub images: usize,
+    pub rasterized_blobs: usize,
 }
 
 impl ::std::ops::AddAssign for MemoryReport {
     fn add_assign(&mut self, other: MemoryReport) {
         self.primitive_stores += other.primitive_stores;
         self.clip_stores += other.clip_stores;
         self.gpu_cache_metadata += other.gpu_cache_metadata;
         self.gpu_cache_cpu_mirror += other.gpu_cache_cpu_mirror;
         self.render_tasks += other.render_tasks;
         self.hit_testers += other.hit_testers;
+        self.fonts += other.fonts;
+        self.images += other.images;
+        self.rasterized_blobs += other.rasterized_blobs;
     }
 }
 
 /// A C function that takes a pointer to a heap allocation and returns its size.
 ///
 /// This is borrowed from the malloc_size_of crate, upon which we want to avoid
 /// a dependency from WebRender.
 pub type VoidPtrToSizeFn = unsafe extern "C" fn(ptr: *const c_void) -> usize;
--- a/gfx/webrender_api/src/font.rs
+++ b/gfx/webrender_api/src/font.rs
@@ -75,17 +75,23 @@ pub struct GlyphDimensions {
 pub struct FontKey(pub IdNamespace, pub u32);
 
 impl FontKey {
     pub fn new(namespace: IdNamespace, key: u32) -> FontKey {
         FontKey(namespace, key)
     }
 }
 
-
+/// Container for the raw data describing a font. This might be a stream of
+/// bytes corresponding to a downloaded font, or a handle to a native font from
+/// the operating system.
+///
+/// Note that fonts need to be instantiated before being used, which involves
+/// assigning size and various other options. The word 'template' here is
+/// intended to distinguish this data from instance-specific data.
 #[derive(Clone)]
 pub enum FontTemplate {
     Raw(Arc<Vec<u8>>, u32),
     Native(NativeFontHandle),
 }
 
 #[repr(u32)]
 #[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Ord, PartialOrd)]
@@ -343,16 +349,20 @@ impl Default for FontInstancePlatformOpt
 pub struct FontInstanceKey(pub IdNamespace, pub u32);
 
 impl FontInstanceKey {
     pub fn new(namespace: IdNamespace, key: u32) -> FontInstanceKey {
         FontInstanceKey(namespace, key)
     }
 }
 
+/// Data corresponding to an instantiation of a font, with size and
+/// other options specified.
+///
+/// Note that the actual font is stored out-of-band in `FontTemplate`.
 #[derive(Clone)]
 pub struct FontInstanceData {
     pub font_key: FontKey,
     pub size: Au,
     pub options: Option<FontInstanceOptions>,
     pub platform_options: Option<FontInstancePlatformOptions>,
     pub variations: Vec<FontVariation>,
 }
--- a/gfx/webrender_bindings/revision.txt
+++ b/gfx/webrender_bindings/revision.txt
@@ -1,1 +1,1 @@
-a601f9c291cee83257241ef61aaf62353c613438
+97a3807ea8266c324feb3ecada2ac5fd78c80e9b