Bug 1512730 - Update webrender to commit 41c12cabc42228dda6a2d2628c9b24df9aca66b4 (WR PR #3398). r=kats, a=RyanVM
authorWR Updater Bot <graphics-team@mozilla.staktrace.com>
Tue, 11 Dec 2018 01:57:22 +0000
changeset 508974 86e560ca1e292800a65bf10ad8ec446277c2b2ef
parent 508973 60444ade289159d488b7ab144e28e7091946a43c
child 508975 ca8fd2a3447af7049cd4666d8a533ffeb64e365a
push id1905
push userffxbld-merge
push dateMon, 21 Jan 2019 12:33:13 +0000
treeherdermozilla-release@c2fca1944d8c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats, RyanVM
bugs1512730
milestone65.0
Bug 1512730 - Update webrender to commit 41c12cabc42228dda6a2d2628c9b24df9aca66b4 (WR PR #3398). r=kats, a=RyanVM https://github.com/servo/webrender/pull/3398 Differential Revision: https://phabricator.services.mozilla.com/D14121
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 @@
-34d58890821d2e606285f21cd6f4befd46c83d47
+41c12cabc42228dda6a2d2628c9b24df9aca66b4
--- a/gfx/wr/webrender/src/render_backend.rs
+++ b/gfx/wr/webrender/src/render_backend.rs
@@ -812,18 +812,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) = txn.blob_rasterizer.take() {
-                            self.resource_cache.set_blob_rasterizer(rasterizer);
+                        if let Some((rasterizer, epoch)) = txn.blob_rasterizer.take() {
+                            self.resource_cache.set_blob_rasterizer(rasterizer, epoch);
                         }
 
                         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
@@ -398,52 +398,64 @@ impl BlobImageResources for Resources {
             }),
             None => None,
         }
     }
 }
 
 pub type GlyphDimensionsCache = FastHashMap<(FontInstance, GlyphIndex), Option<GlyphDimensions>>;
 
+#[derive(Clone, Copy, Debug, PartialEq)]
+pub struct BlobImageRasterizerEpoch(usize);
+
 /// 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,
 
     pub texture_cache: TextureCache,
 
-    // TODO(gw): We should expire (parts of) this cache semi-regularly!
+    /// TODO(gw): We should expire (parts of) this cache semi-regularly!
     cached_glyph_dimensions: GlyphDimensionsCache,
     glyph_rasterizer: GlyphRasterizer,
 
-    // The set of images that aren't present or valid in the texture cache,
-    // and need to be rasterized and/or uploaded this frame. This includes
-    // both blobs and regular images.
+    /// The set of images that aren't present or valid in the texture cache,
+    /// and need to be rasterized and/or uploaded this frame. This includes
+    /// both blobs and regular images.
     pending_image_requests: FastHashSet<ImageRequest>,
 
     blob_image_handler: Option<Box<BlobImageHandler>>,
     rasterized_blob_images: FastHashMap<BlobImageKey, RasterizedBlob>,
     blob_image_templates: FastHashMap<BlobImageKey, BlobImageTemplate>,
 
-    // If while building a frame we encounter blobs that we didn't already
-    // rasterize, add them to this list and rasterize them synchronously.
+    /// If while building a frame we encounter blobs that we didn't already
+    /// rasterize, add them to this list and rasterize them synchronously.
     missing_blob_images: Vec<BlobImageParams>,
-    // The rasterizer associated with the current scene.
+    /// The rasterizer associated with the current scene.
     blob_image_rasterizer: Option<Box<AsyncBlobImageRasterizer>>,
-    // A log of the last three frames worth of deleted image keys kept
-    // for debugging purposes.
+    /// An epoch of the stored blob image rasterizer, used to skip the ones
+    /// coming from low-priority scene builds if the current one is newer.
+    /// This is to be removed when we get rid of the whole "missed" blob
+    /// images concept.
+    /// The produced one gets bumped whenever we produce a rasteriezer,
+    /// which then travels through the scene building and eventually gets
+    /// consumed back by us, bumping the consumed epoch.
+    blob_image_rasterizer_produced_epoch: BlobImageRasterizerEpoch,
+    blob_image_rasterizer_consumed_epoch: BlobImageRasterizerEpoch,
+    /// A log of the last three frames worth of deleted image keys kept
+    /// for debugging purposes.
     deleted_blob_keys: VecDeque<Vec<BlobImageKey>>
 }
 
 impl ResourceCache {
     pub fn new(
         texture_cache: TextureCache,
         glyph_rasterizer: GlyphRasterizer,
         blob_image_handler: Option<Box<BlobImageHandler>>,
@@ -459,16 +471,18 @@ impl ResourceCache {
             current_frame_id: FrameId::INVALID,
             pending_image_requests: FastHashSet::default(),
             glyph_rasterizer,
             blob_image_handler,
             rasterized_blob_images: FastHashMap::default(),
             blob_image_templates: FastHashMap::default(),
             missing_blob_images: Vec::new(),
             blob_image_rasterizer: None,
+            blob_image_rasterizer_produced_epoch: BlobImageRasterizerEpoch(0),
+            blob_image_rasterizer_consumed_epoch: BlobImageRasterizerEpoch(0),
             // We want to keep three frames worth of delete blob keys
             deleted_blob_keys: vec![Vec::new(), Vec::new(), Vec::new()].into(),
         }
     }
 
     pub fn max_texture_size(&self) -> i32 {
         self.texture_cache.max_texture_size()
     }
@@ -635,18 +649,21 @@ impl ResourceCache {
                         instance.variations,
                     );
                 }
                 _ => { unreachable!(); }
             }
         );
     }
 
-    pub fn set_blob_rasterizer(&mut self, rasterizer: Box<AsyncBlobImageRasterizer>) {
-        self.blob_image_rasterizer = Some(rasterizer);
+    pub fn set_blob_rasterizer(&mut self, rasterizer: Box<AsyncBlobImageRasterizer>, epoch: BlobImageRasterizerEpoch) {
+        if self.blob_image_rasterizer_consumed_epoch.0 < epoch.0 {
+            self.blob_image_rasterizer = Some(rasterizer);
+            self.blob_image_rasterizer_consumed_epoch = epoch;
+        }
     }
 
     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(..) => {
                     warn!("Failed to rasterize a blob image");
@@ -1076,17 +1093,17 @@ impl ResourceCache {
                 );
             }
         }
     }
 
     pub fn create_blob_scene_builder_requests(
         &mut self,
         keys: &[BlobImageKey]
-    ) -> (Option<Box<AsyncBlobImageRasterizer>>, Vec<BlobImageParams>) {
+    ) -> (Option<(Box<AsyncBlobImageRasterizer>, BlobImageRasterizerEpoch)>, Vec<BlobImageParams>) {
         if self.blob_image_handler.is_none() || keys.is_empty() {
             return (None, Vec::new());
         }
 
         let mut blob_request_params = Vec::new();
         for key in keys {
             let template = self.blob_image_templates.get_mut(key).unwrap();
 
@@ -1212,19 +1229,21 @@ impl ResourceCache {
                             format: template.descriptor.format,
                         },
                         dirty_rect,
                     }
                 );
             }
             template.dirty_rect = DirtyRect::empty();
         }
+        self.blob_image_rasterizer_produced_epoch.0 += 1;
+        let epoch = self.blob_image_rasterizer_produced_epoch;
         let handler = self.blob_image_handler.as_mut().unwrap();
         handler.prepare_resources(&self.resources, &blob_request_params);
-        (Some(handler.create_blob_rasterizer()), blob_request_params)
+        (Some((handler.create_blob_rasterizer(), epoch)), 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
@@ -16,17 +16,17 @@ use intern::{Internable, Interner};
 use internal_types::{FastHashMap, FastHashSet};
 use prim_store::{PrimitiveDataInterner, PrimitiveDataUpdateList, PrimitiveKeyKind};
 use prim_store::PrimitiveStoreStats;
 use prim_store::gradient::{
     LinearGradient, LinearGradientDataInterner, LinearGradientDataUpdateList,
     RadialGradient, RadialGradientDataInterner, RadialGradientDataUpdateList
 };
 use prim_store::text_run::{TextRunDataInterner, TextRun, TextRunDataUpdateList};
-use resource_cache::FontInstanceMap;
+use resource_cache::{BlobImageRasterizerEpoch, 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;
@@ -43,17 +43,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>>,
+    pub blob_rasterizer: Option<(Box<AsyncBlobImageRasterizer>, BlobImageRasterizerEpoch)>,
     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,
 }
@@ -67,26 +67,33 @@ impl Transaction {
             self.blob_requests.is_empty() &&
             self.set_root_pipeline.is_none()
     }
 
     pub fn should_build_scene(&self) -> bool {
         !self.display_list_updates.is_empty() ||
             self.set_root_pipeline.is_some()
     }
+
+    fn rasterize_blobs(&mut self, is_low_priority: bool) {
+        if let Some((ref mut rasterizer, _)) = self.blob_rasterizer {
+            let rasterized_blobs = rasterizer.rasterize(&self.blob_requests, is_low_priority);
+            self.rasterized_blobs.extend(rasterized_blobs);
+        }
+    }
 }
 
 /// 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>>,
+    pub blob_rasterizer: Option<(Box<AsyncBlobImageRasterizer>, BlobImageRasterizerEpoch)>,
     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,
@@ -538,39 +545,34 @@ impl SceneBuilder {
                     scene: new_scene,
                     frame_builder,
                     clip_scroll_tree,
                 });
             }
         }
 
         let is_low_priority = false;
-        let blob_requests = replace(&mut txn.blob_requests, Vec::new());
-        let mut rasterized_blobs = txn.blob_rasterizer.as_mut().map_or(
-            Vec::new(),
-            |rasterizer| rasterizer.rasterize(&blob_requests, is_low_priority),
-        );
-        rasterized_blobs.append(&mut txn.rasterized_blobs);
+        txn.rasterize_blobs(is_low_priority);
 
         drain_filter(
             &mut txn.notifications,
             |n| { n.when() == Checkpoint::SceneBuilt },
             |n| { n.notify(); },
         );
 
         if self.simulate_slow_ms > 0 {
             thread::sleep(Duration::from_millis(self.simulate_slow_ms as u64));
         }
 
         Box::new(BuiltTransaction {
             document_id: txn.document_id,
             render_frame: txn.render_frame,
             invalidate_rendered_frame: txn.invalidate_rendered_frame,
             built_scene,
-            rasterized_blobs,
+            rasterized_blobs: replace(&mut txn.rasterized_blobs, Vec::new()),
             resource_updates: replace(&mut txn.resource_updates, Vec::new()),
             blob_rasterizer: replace(&mut txn.blob_rasterizer, None),
             frame_ops: replace(&mut txn.frame_ops, Vec::new()),
             removed_pipelines: replace(&mut txn.removed_pipelines, Vec::new()),
             notifications: replace(&mut txn.notifications, Vec::new()),
             doc_resource_updates,
             scene_build_start_time,
             scene_build_end_time: precise_time_ns(),
@@ -665,23 +667,18 @@ impl LowPrioritySceneBuilder {
                 Err(_) => {
                     break;
                 }
             }
         }
     }
 
     fn process_transaction(&mut self, mut txn: Box<Transaction>) -> Box<Transaction> {
-        let blob_requests = replace(&mut txn.blob_requests, Vec::new());
         let is_low_priority = true;
-        let mut more_rasterized_blobs = txn.blob_rasterizer.as_mut().map_or(
-            Vec::new(),
-            |rasterizer| rasterizer.rasterize(&blob_requests, is_low_priority),
-        );
-        txn.rasterized_blobs.append(&mut more_rasterized_blobs);
+        txn.rasterize_blobs(is_low_priority);
 
         if self.simulate_slow_ms > 0 {
             thread::sleep(Duration::from_millis(self.simulate_slow_ms as u64));
         }
 
         txn
     }
 }