Bug 1470901 - WR patch draft
authorKartikaya Gupta <kgupta@mozilla.com>
Tue, 26 Jun 2018 12:13:19 -0400
changeset 810846 db4efb0c23539686e072558c8159abcea1abc8db
parent 810783 01a842b98dd68665ceef674083745ec13980fb0f
child 810847 e393b5a770004043bb6b7775a7dac5c6f5d14f13
push id114133
push userkgupta@mozilla.com
push dateTue, 26 Jun 2018 16:13:47 +0000
bugs1470901
milestone62.0a1
Bug 1470901 - WR patch MozReview-Commit-ID: 2Gq0Z9YeOeY
gfx/webrender/src/render_backend.rs
gfx/webrender/src/renderer.rs
gfx/webrender/src/scene_builder.rs
gfx/webrender_api/src/api.rs
--- a/gfx/webrender/src/render_backend.rs
+++ b/gfx/webrender/src/render_backend.rs
@@ -1058,38 +1058,42 @@ impl RenderBackend {
             // scroll at the same time. we should keep track of the fact that we skipped
             // composition here and do it as soon as we receive the scene.
             op.render = false;
             op.composite = false;
         }
 
         debug_assert!(op.render || !op.composite);
 
+        let mut render_time = None;
         if op.render && doc.has_pixels() {
             profile_scope!("generate frame");
 
             *frame_counter += 1;
 
             // borrow ck hack for profile_counters
             let (pending_update, rendered_document) = {
                 let _timer = profile_counters.total_time.timer();
+                let render_start_time = precise_time_ns();
 
                 let rendered_document = doc.render(
                     &mut self.resource_cache,
                     &mut self.gpu_cache,
                     &mut profile_counters.resources,
                     op.build || has_built_scene,
                 );
 
                 debug!("generated frame for document {:?} with {} passes",
                     document_id, rendered_document.frame.passes.len());
 
                 let msg = ResultMsg::UpdateGpuCache(self.gpu_cache.extract_updates());
                 self.result_tx.send(msg).unwrap();
 
+                render_time = Some(precise_time_ns() - render_start_time);
+
                 let pending_update = self.resource_cache.pending_updates();
                 (pending_update, rendered_document)
             };
 
             let msg = ResultMsg::PublishPipelineInfo(doc.updated_pipeline_info());
             self.result_tx.send(msg).unwrap();
 
             // Publish the frame
@@ -1106,17 +1110,17 @@ impl RenderBackend {
             // there's no pixels. We still want to pretend to render and request
             // a composite to make sure that the callbacks (particularly the
             // new_frame_ready callback below) has the right flags.
             let msg = ResultMsg::PublishPipelineInfo(doc.updated_pipeline_info());
             self.result_tx.send(msg).unwrap();
         }
 
         if transaction_msg.generate_frame {
-            self.notifier.new_frame_ready(document_id, op.scroll, op.composite);
+            self.notifier.new_frame_ready(document_id, op.scroll, op.composite, render_time);
         }
     }
 
     #[cfg(not(feature = "debugger"))]
     fn get_docs_for_debugger(&self) -> String {
         String::new()
     }
 
@@ -1405,14 +1409,14 @@ impl RenderBackend {
                 id,
                 render_doc,
                 self.resource_cache.pending_updates(),
                 profile_counters.clone(),
             );
             self.result_tx.send(msg_publish).unwrap();
             profile_counters.reset();
 
-            self.notifier.new_frame_ready(id, false, true);
+            self.notifier.new_frame_ready(id, false, true, None);
             self.documents.insert(id, doc);
         }
     }
 }
 
--- a/gfx/webrender/src/renderer.rs
+++ b/gfx/webrender/src/renderer.rs
@@ -4012,21 +4012,21 @@ pub trait ThreadListener {
 
 /// Allows callers to hook in at certain points of the async scene build. These
 /// functions are all called from the scene builder thread.
 pub trait SceneBuilderHooks {
     /// This is called exactly once, when the scene builder thread is started
     /// and before it processes anything.
     fn register(&self);
     /// This is called before each scene swap occurs.
-    fn pre_scene_swap(&self);
+    fn pre_scene_swap(&self, scenebuild_time: u64);
     /// This is called after each scene swap occurs. The PipelineInfo contains
     /// the updated epochs and pipelines removed in the new scene compared to
     /// the old scene.
-    fn post_scene_swap(&self, info: PipelineInfo);
+    fn post_scene_swap(&self, info: PipelineInfo, sceneswap_time: u64);
     /// This is called after a resource update operation on the scene builder
     /// thread, in the case where resource updates were applied without a scene
     /// build.
     fn post_resource_update(&self);
     /// This is a generic callback which provides an opportunity to run code
     /// on the scene builder thread. This is called as part of the main message
     /// loop of the scene builder thread, but outside of any specific message
     /// handler.
--- a/gfx/webrender/src/scene_builder.rs
+++ b/gfx/webrender/src/scene_builder.rs
@@ -8,16 +8,17 @@ use display_list_flattener::build_scene;
 use frame_builder::{FrameBuilderConfig, FrameBuilder};
 use clip_scroll_tree::ClipScrollTree;
 use internal_types::FastHashSet;
 use resource_cache::FontInstanceMap;
 use render_backend::DocumentView;
 use renderer::{PipelineInfo, SceneBuilderHooks};
 use scene::Scene;
 use std::sync::mpsc::{channel, Receiver, Sender};
+use time::precise_time_ns;
 
 // Message from render backend to scene builder.
 pub enum SceneBuilderRequest {
     Transaction {
         document_id: DocumentId,
         scene: Option<SceneRequest>,
         resource_updates: Vec<ResourceUpdate>,
         frame_ops: Vec<FrameMsg>,
@@ -132,16 +133,17 @@ impl SceneBuilder {
             }
             SceneBuilderRequest::Transaction {
                 document_id,
                 scene,
                 resource_updates,
                 frame_ops,
                 render,
             } => {
+                let scenebuild_start_time = precise_time_ns();
                 let built_scene = scene.map(|request|{
                     build_scene(&self.config, request)
                 });
 
                 // TODO: pre-rasterization.
 
                 // We only need the pipeline info and the result channel if we
                 // have a hook callback *and* if this transaction actually built
@@ -151,39 +153,42 @@ impl SceneBuilder {
                 let (pipeline_info, result_tx, result_rx) = match (&self.hooks, &built_scene) {
                     (&Some(ref hooks), &Some(ref built)) => {
                         let info = PipelineInfo {
                             epochs: built.scene.pipeline_epochs.clone(),
                             removed_pipelines: built.removed_pipelines.clone(),
                         };
                         let (tx, rx) = channel();
 
-                        hooks.pre_scene_swap();
+                        let scenebuild_time = precise_time_ns() - scenebuild_start_time;
+                        hooks.pre_scene_swap(scenebuild_time);
 
                         (Some(info), Some(tx), Some(rx))
                     }
                     _ => (None, None, None),
                 };
 
+                let sceneswap_start_time = precise_time_ns();
                 let has_resources_updates = !resource_updates.is_empty();
                 self.tx.send(SceneBuilderResult::Transaction {
                     document_id,
                     built_scene,
                     resource_updates,
                     frame_ops,
                     render,
                     result_tx,
                 }).unwrap();
 
                 let _ = self.api_tx.send(ApiMsg::WakeUp);
 
                 if let Some(pipeline_info) = pipeline_info {
                     // Block until the swap is done, then invoke the hook.
                     let swap_result = result_rx.unwrap().recv();
-                    self.hooks.as_ref().unwrap().post_scene_swap(pipeline_info);
+                    let sceneswap_time = precise_time_ns() - sceneswap_start_time;
+                    self.hooks.as_ref().unwrap().post_scene_swap(pipeline_info, sceneswap_time);
                     // Once the hook is done, allow the RB thread to resume
                     match swap_result {
                         Ok(SceneSwapResult::Complete(resume_tx)) => {
                             resume_tx.send(()).ok();
                         },
                         _ => (),
                     };
                 } else if has_resources_updates {
--- a/gfx/webrender_api/src/api.rs
+++ b/gfx/webrender_api/src/api.rs
@@ -1098,14 +1098,14 @@ pub struct PropertyValue<T> {
 pub struct DynamicProperties {
     pub transforms: Vec<PropertyValue<LayoutTransform>>,
     pub floats: Vec<PropertyValue<f32>>,
 }
 
 pub trait RenderNotifier: Send {
     fn clone(&self) -> Box<RenderNotifier>;
     fn wake_up(&self);
-    fn new_frame_ready(&self, DocumentId, scrolled: bool, composite_needed: bool);
+    fn new_frame_ready(&self, DocumentId, scrolled: bool, composite_needed: bool, render_time_ns: Option<u64>);
     fn external_event(&self, _evt: ExternalEvent) {
         unimplemented!()
     }
     fn shut_down(&self) {}
 }