Bug 1518769 - Update webrender to commit 32e2f83a809e91f699847cbde209d4f24fca0141 (WR PR #3492). r=kats
authorWR Updater Bot <graphics-team@mozilla.staktrace.com>
Wed, 09 Jan 2019 20:25:47 +0000
changeset 510247 be1da0e72bafec7982d6c04e07bd6e9f7cd9cf21
parent 510246 741ded5432288db8ea024097cd3e597ddde895fa
child 510248 ce7f9998683947e56d308894aa8e17ee7ce57674
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats
bugs1518769
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 1518769 - Update webrender to commit 32e2f83a809e91f699847cbde209d4f24fca0141 (WR PR #3492). r=kats https://github.com/servo/webrender/pull/3492 Differential Revision: https://phabricator.services.mozilla.com/D16081
gfx/webrender_bindings/revision.txt
gfx/wr/webrender/src/render_backend.rs
gfx/wr/webrender/src/resource_cache.rs
gfx/wr/webrender/src/scene_builder.rs
--- a/gfx/webrender_bindings/revision.txt
+++ b/gfx/webrender_bindings/revision.txt
@@ -1,1 +1,1 @@
-f24d6fbc8598dbaffee70b745e043dd390664f72
+32e2f83a809e91f699847cbde209d4f24fca0141
--- a/gfx/wr/webrender/src/render_backend.rs
+++ b/gfx/wr/webrender/src/render_backend.rs
@@ -854,18 +854,18 @@ impl RenderBackend {
                                 tx.send(SceneSwapResult::Aborted).unwrap();
                             }
                             continue;
                         }
 
                         self.resource_cache.add_rasterized_blob_images(
                             replace(&mut txn.rasterized_blobs, Vec::new())
                         );
-                        if let Some((rasterizer, epoch)) = txn.blob_rasterizer.take() {
-                            self.resource_cache.set_blob_rasterizer(rasterizer, epoch);
+                        if let Some((rasterizer, info)) = txn.blob_rasterizer.take() {
+                            self.resource_cache.set_blob_rasterizer(rasterizer, info);
                         }
 
                         self.update_document(
                             txn.document_id,
                             replace(&mut txn.resource_updates, Vec::new()),
                             txn.doc_resource_updates.take(),
                             replace(&mut txn.frame_ops, Vec::new()),
                             replace(&mut txn.notifications, Vec::new()),
--- a/gfx/wr/webrender/src/resource_cache.rs
+++ b/gfx/wr/webrender/src/resource_cache.rs
@@ -405,16 +405,38 @@ impl BlobImageResources for Resources {
     }
 }
 
 pub type GlyphDimensionsCache = FastHashMap<(FontInstance, GlyphIndex), Option<GlyphDimensions>>;
 
 #[derive(Clone, Copy, Debug, PartialEq)]
 pub struct BlobImageRasterizerEpoch(usize);
 
+/// Stores parameters for clearing blob image tiles.
+///
+/// The clearing is necessary when originally requested tile range exceeds
+/// MAX_TILES_PER_REQUEST. In this case, some tiles are not rasterized by
+/// AsyncBlobImageRasterizer. They need to be cleared.
+#[derive(Clone, Copy, Debug)]
+pub struct BlobImageClearParams {
+    pub key: BlobImageKey,
+    /// Originally requested tile range to rasterize.
+    pub original_tile_range: TileRange,
+    /// Actual tile range that is requested to rasterize by
+    /// AsyncBlobImageRasterizer.
+    pub actual_tile_range: TileRange,
+}
+
+/// Information attached to AsyncBlobImageRasterizer.
+#[derive(Clone, Debug)]
+pub struct AsyncBlobImageInfo {
+    pub epoch: BlobImageRasterizerEpoch,
+    pub clear_requests: Vec<BlobImageClearParams>,
+}
+
 /// 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,
@@ -653,20 +675,52 @@ impl ResourceCache {
                         instance.variations,
                     );
                 }
                 _ => { unreachable!(); }
             }
         );
     }
 
-    pub fn set_blob_rasterizer(&mut self, rasterizer: Box<AsyncBlobImageRasterizer>, epoch: BlobImageRasterizerEpoch) {
-        if self.blob_image_rasterizer_consumed_epoch.0 < epoch.0 {
+    pub fn set_blob_rasterizer(
+        &mut self, rasterizer: Box<AsyncBlobImageRasterizer>,
+        supp: AsyncBlobImageInfo,
+    ) {
+        if self.blob_image_rasterizer_consumed_epoch.0 < supp.epoch.0 {
             self.blob_image_rasterizer = Some(rasterizer);
-            self.blob_image_rasterizer_consumed_epoch = epoch;
+            self.blob_image_rasterizer_consumed_epoch = supp.epoch;
+        }
+
+        // Discard blob image tiles that are not rendered by AsyncBlobImageRasterizer.
+        // It happens when originally requested tile range exceeds MAX_TILES_PER_REQUEST.
+        for req in supp.clear_requests {
+            let tiles = match self.rasterized_blob_images.get_mut(&req.key) {
+                Some(RasterizedBlob::Tiled(tiles)) => tiles,
+                _ => { continue; }
+            };
+
+            tiles.retain(|tile, _| {
+                !req.original_tile_range.contains(tile) ||
+                req.actual_tile_range.contains(tile)
+            });
+
+            let texture_cache = &mut self.texture_cache;
+            match self.cached_images.try_get_mut(&req.key.as_image()) {
+                Some(&mut ImageResult::Multi(ref mut entries)) => {
+                    entries.retain(|key, entry| {
+                        if !req.original_tile_range.contains(&key.tile.unwrap()) ||
+                           req.actual_tile_range.contains(&key.tile.unwrap()) {
+                            return true;
+                        }
+                        entry.mark_unused(texture_cache);
+                        return false;
+                    });
+                }
+                _ => {}
+            }
         }
     }
 
     pub fn add_rasterized_blob_images(&mut self, images: Vec<(BlobImageRequest, BlobImageResult)>) {
         for (request, result) in images {
             let data = match result {
                 Ok(data) => data,
                 Err(..) => {
@@ -1097,21 +1151,22 @@ impl ResourceCache {
                 );
             }
         }
     }
 
     pub fn create_blob_scene_builder_requests(
         &mut self,
         keys: &[BlobImageKey]
-    ) -> (Option<(Box<AsyncBlobImageRasterizer>, BlobImageRasterizerEpoch)>, Vec<BlobImageParams>) {
+    ) -> (Option<(Box<AsyncBlobImageRasterizer>, AsyncBlobImageInfo)>, Vec<BlobImageParams>) {
         if self.blob_image_handler.is_none() || keys.is_empty() {
             return (None, Vec::new());
         }
 
+        let mut blob_tiles_clear_requests = Vec::new();
         let mut blob_request_params = Vec::new();
         for key in keys {
             let template = self.blob_image_templates.get_mut(key).unwrap();
 
             if let Some(tile_size) = template.tiling {
                 // If we know that only a portion of the blob image is in the viewport,
                 // only request these visible tiles since blob images can be huge.
                 let mut tiles = template.viewport_tiles.unwrap_or_else(|| {
@@ -1141,16 +1196,18 @@ impl ResourceCache {
                     let dirty_tiles = compute_tile_range(
                         &dirty_rect,
                         tile_size,
                     );
 
                     tiles = tiles.intersection(&dirty_tiles).unwrap_or(TileRange::zero());
                 }
 
+                let original_tile_range = tiles;
+
                 // This code tries to keep things sane if Gecko sends
                 // nonsensical blob image requests.
                 // Constant here definitely needs to be tweaked.
                 const MAX_TILES_PER_REQUEST: i32 = 64;
                 // For truly nonsensical requests, we might run into overflow
                 // when computing width * height. Even if we don't, the loop
                 // below to reduce the number of tiles is linear and can take
                 // a long time to complete. These preliminary conditions help
@@ -1169,16 +1226,28 @@ impl ResourceCache {
                         tiles.size.width -= 2;
                         tiles.origin.x += 1;
                     } else {
                         tiles.size.height -= 2;
                         tiles.origin.y += 1;
                     }
                 }
 
+                // When originally requested tile range exceeds MAX_TILES_PER_REQUEST,
+                // some tiles are not rasterized by AsyncBlobImageRasterizer.
+                // They need to be cleared.
+                if original_tile_range != tiles {
+                    let clear_params = BlobImageClearParams {
+                        key: *key,
+                        original_tile_range,
+                        actual_tile_range: tiles,
+                    };
+                    blob_tiles_clear_requests.push(clear_params);
+                }
+
                 for_each_tile_in_range(&tiles, |tile| {
                     let descriptor = BlobImageDescriptor {
                         rect: LayoutIntRect {
                             origin: point2(tile.x, tile.y) * tile_size as i32,
                             size: blob_size(compute_tile_size(
                                 &template.descriptor,
                                 tile_size,
                                 tile,
@@ -1247,20 +1316,23 @@ impl ResourceCache {
                         },
                         dirty_rect,
                     }
                 );
             }
             template.dirty_rect = DirtyRect::empty();
         }
         self.blob_image_rasterizer_produced_epoch.0 += 1;
-        let epoch = self.blob_image_rasterizer_produced_epoch;
+        let info = AsyncBlobImageInfo {
+            epoch: self.blob_image_rasterizer_produced_epoch,
+            clear_requests: blob_tiles_clear_requests,
+        };
         let handler = self.blob_image_handler.as_mut().unwrap();
         handler.prepare_resources(&self.resources, &blob_request_params);
-        (Some((handler.create_blob_rasterizer(), epoch)), blob_request_params)
+        (Some((handler.create_blob_rasterizer(), info)), blob_request_params)
     }
 
     fn discard_tiles_outside_visible_area(
         &mut self,
         key: BlobImageKey,
         area: &DeviceIntRect
     ) {
         let template = match self.blob_image_templates.get(&key) {
--- a/gfx/wr/webrender/src/scene_builder.rs
+++ b/gfx/wr/webrender/src/scene_builder.rs
@@ -29,17 +29,17 @@ use prim_store::image::{
     Image, ImageDataInterner, ImageDataUpdateList,
     YuvImage, YuvImageDataInterner, YuvImageDataUpdateList,
 };
 use prim_store::line_dec::{
     LineDecoration, LineDecorationDataInterner, LineDecorationDataUpdateList
 };
 use prim_store::picture::{PictureDataInterner, Picture, PictureDataUpdateList};
 use prim_store::text_run::{TextRunDataInterner, TextRun, TextRunDataUpdateList};
-use resource_cache::{BlobImageRasterizerEpoch, FontInstanceMap};
+use resource_cache::{AsyncBlobImageInfo, FontInstanceMap};
 use render_backend::DocumentView;
 use renderer::{PipelineInfo, SceneBuilderHooks};
 use scene::Scene;
 use std::sync::mpsc::{channel, Receiver, Sender};
 use std::mem::replace;
 use time::precise_time_ns;
 use util::drain_filter;
 use std::thread;
@@ -62,17 +62,17 @@ pub struct DocumentResourceUpdates {
 /// Represents the work associated to a transaction before scene building.
 pub struct Transaction {
     pub document_id: DocumentId,
     pub display_list_updates: Vec<DisplayListUpdate>,
     pub removed_pipelines: Vec<PipelineId>,
     pub epoch_updates: Vec<(PipelineId, Epoch)>,
     pub request_scene_build: Option<SceneRequest>,
     pub blob_requests: Vec<BlobImageParams>,
-    pub blob_rasterizer: Option<(Box<AsyncBlobImageRasterizer>, BlobImageRasterizerEpoch)>,
+    pub blob_rasterizer: Option<(Box<AsyncBlobImageRasterizer>, AsyncBlobImageInfo)>,
     pub rasterized_blobs: Vec<(BlobImageRequest, BlobImageResult)>,
     pub resource_updates: Vec<ResourceUpdate>,
     pub frame_ops: Vec<FrameMsg>,
     pub notifications: Vec<NotificationRequest>,
     pub set_root_pipeline: Option<PipelineId>,
     pub render_frame: bool,
     pub invalidate_rendered_frame: bool,
 }
@@ -107,17 +107,17 @@ impl Transaction {
 
 /// Represent the remaining work associated to a transaction after the scene building
 /// phase as well as the result of scene building itself if applicable.
 pub struct BuiltTransaction {
     pub document_id: DocumentId,
     pub built_scene: Option<BuiltScene>,
     pub resource_updates: Vec<ResourceUpdate>,
     pub rasterized_blobs: Vec<(BlobImageRequest, BlobImageResult)>,
-    pub blob_rasterizer: Option<(Box<AsyncBlobImageRasterizer>, BlobImageRasterizerEpoch)>,
+    pub blob_rasterizer: Option<(Box<AsyncBlobImageRasterizer>, AsyncBlobImageInfo)>,
     pub frame_ops: Vec<FrameMsg>,
     pub removed_pipelines: Vec<PipelineId>,
     pub notifications: Vec<NotificationRequest>,
     pub doc_resource_updates: Option<DocumentResourceUpdates>,
     pub scene_build_start_time: u64,
     pub scene_build_end_time: u64,
     pub render_frame: bool,
     pub invalidate_rendered_frame: bool,