Bug 1344966 - Add flag that represents the traversal is only for animation-only restyle. r?heycam draft
authorHiroyuki Ikezoe <hikezoe@mozilla.com>
Sat, 25 Mar 2017 19:25:35 +0900
changeset 551281 49cc48fe9978bc4759742ef68784cb7e107cb47c
parent 551280 abf0fd2b7c85d6e31a0ad8fcafc83ceb842974ff
child 551282 5a292b6b4acb447a1f31e4c975286eaced98b17a
child 551381 565d39059401a9435e3049e3d96f0319496c841e
push id51007
push userhikezoe@mozilla.com
push dateSat, 25 Mar 2017 10:33:03 +0000
reviewersheycam
bugs1344966
milestone55.0a1
Bug 1344966 - Add flag that represents the traversal is only for animation-only restyle. r?heycam We will set the flag when the root node of the traversal has has-animation-only-dirty-descendants flag or has animation restyle hints. Also we will use this flag to detect whether we need to trigger CSS transitions or not. MozReview-Commit-ID: 1EMQ77e24ab
servo/components/style/context.rs
servo/components/style/dom.rs
servo/ports/geckolib/glue.rs
--- a/servo/components/style/context.rs
+++ b/servo/components/style/context.rs
@@ -82,16 +82,19 @@ pub struct SharedStyleContext<'a> {
     pub local_context_creation_data: Mutex<ThreadLocalStyleContextCreationInfo>,
 
     /// The current timer for transitions and animations. This is needed to test
     /// them.
     pub timer: Timer,
 
     /// The QuirksMode state which the document needs to be rendered with
     pub quirks_mode: QuirksMode,
+
+    /// True if the traversal is processing only animation restyles.
+    pub animation_only_restyle: bool,
 }
 
 impl<'a> SharedStyleContext<'a> {
     /// Return a suitable viewport size in order to be used for viewport units.
     pub fn viewport_size(&self) -> Size2D<Au> {
         self.stylist.device.au_viewport_size()
     }
 }
--- a/servo/components/style/dom.rs
+++ b/servo/components/style/dom.rs
@@ -367,16 +367,26 @@ pub trait TElement : PartialEq + Debug +
     fn has_selector_flags(&self, flags: ElementSelectorFlags) -> bool;
 
     /// Creates a task to update CSS Animations on a given (pseudo-)element.
     /// Note: Gecko only.
     fn update_animations(&self, _pseudo: Option<&PseudoElement>);
 
     /// Returns true if the element has a CSS animation.
     fn has_css_animations(&self, _pseudo: Option<&PseudoElement>) -> bool;
+
+    /// Returns true if the element has animation restyle hints.
+    fn has_animation_restyle_hints(&self) -> bool {
+        let data = match self.borrow_data() {
+            Some(d) => d,
+            None => return false,
+        };
+        return data.get_restyle()
+                   .map_or(false, |r| r.hint.has_animation_hint());
+    }
 }
 
 /// TNode and TElement aren't Send because we want to be careful and explicit
 /// about our parallel traversal. However, there are certain situations
 /// (including but not limited to the traversal) where we need to send DOM
 /// objects to other threads.
 ///
 /// That's the reason why `SendNode` exists.
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -120,31 +120,33 @@ pub extern "C" fn Servo_Initialize() {
 
 #[no_mangle]
 pub extern "C" fn Servo_Shutdown() {
     // Clear some static data to avoid shutdown leaks.
     gecko_properties::shutdown();
 }
 
 fn create_shared_context<'a>(guard: &'a SharedRwLockReadGuard,
-                             per_doc_data: &PerDocumentStyleDataImpl) -> SharedStyleContext<'a> {
+                             per_doc_data: &PerDocumentStyleDataImpl,
+                             animation_only: bool) -> SharedStyleContext<'a> {
     let local_context_data =
         ThreadLocalStyleContextCreationInfo::new(per_doc_data.new_animations_sender.clone());
 
     SharedStyleContext {
         stylist: per_doc_data.stylist.clone(),
         guards: StylesheetGuards::same(guard),
         running_animations: per_doc_data.running_animations.clone(),
         expired_animations: per_doc_data.expired_animations.clone(),
         // FIXME(emilio): Stop boxing here.
         error_reporter: Box::new(StdoutErrorReporter),
         local_context_creation_data: Mutex::new(local_context_data),
         timer: Timer::new(),
         // FIXME Find the real QuirksMode information for this document
         quirks_mode: QuirksMode::NoQuirks,
+        animation_only_restyle: animation_only,
     }
 }
 
 fn traverse_subtree(element: GeckoElement, raw_data: RawServoStyleSetBorrowed,
                     traversal_flags: &TraversalFlags) {
     // When new content is inserted in a display:none subtree, we will call into
     // servo to try to style it. Detect that here and bail out.
     if let Some(parent) = element.parent_element() {
@@ -161,17 +163,18 @@ fn traverse_subtree(element: GeckoElemen
         return;
     }
 
     debug!("Traversing subtree:");
     debug!("{:?}", ShowSubtreeData(element.as_node()));
 
     let global_style_data = &*GLOBAL_STYLE_DATA;
     let guard = global_style_data.shared_lock.read();
-    let shared_style_context = create_shared_context(&guard, &per_doc_data);
+    let shared_style_context = create_shared_context(&guard, &per_doc_data,
+                                                     traversal_flags.for_animation_only());
 
     let traversal_driver = if global_style_data.style_thread_pool.is_none() {
         TraversalDriver::Sequential
     } else {
         TraversalDriver::Parallel
     };
 
     let traversal = RecalcStyleOnly::new(shared_style_context, traversal_driver);
@@ -1499,17 +1502,17 @@ pub extern "C" fn Servo_ResolveStyleLazi
     // up all the computation machinery.
     let mut result = element.mutate_data()
                             .and_then(|d| d.get_styles().map(&finish));
     if result.is_some() {
         return result.unwrap().into_strong();
     }
 
     // We don't have the style ready. Go ahead and compute it as necessary.
-    let shared = create_shared_context(&guard, &mut doc_data.borrow_mut());
+    let shared = create_shared_context(&guard, &mut doc_data.borrow_mut(), false);
     let mut tlc = ThreadLocalStyleContext::new(&shared);
     let mut context = StyleContext {
         shared: &shared,
         thread_local: &mut tlc,
     };
     let ensure = |el: GeckoElement| { unsafe { el.ensure_data(); } };
     let clear = |el: GeckoElement| el.clear_data();
     resolve_style(&mut context, element, &ensure, &clear,