Bug 1344966 - Set has-animating-descendants bit to ancestors of element which has animations for eRestyle_CSSAnimations. r?heycam draft
authorHiroyuki Ikezoe <hikezoe@mozilla.com>
Sat, 25 Mar 2017 12:47:51 +0900
changeset 551273 cba84439b0abbe09655b59f8e4eaf0589e7712d1
parent 551272 c19d58c51ff1990a6381ae9f40c32e62ba0bda4a
child 551274 a416429a2908492eb51471273d0ed2e970b955fc
push id51006
push userhikezoe@mozilla.com
push dateSat, 25 Mar 2017 09:59:39 +0000
reviewersheycam
bugs1344966
milestone55.0a1
Bug 1344966 - Set has-animating-descendants bit to ancestors of element which has animations for eRestyle_CSSAnimations. r?heycam So we can traverse down dom tree to find element which needs animation-only restyle to track this bit. MozReview-Commit-ID: Iya2PqlUxeI
servo/ports/geckolib/glue.rs
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -1354,45 +1354,52 @@ pub extern "C" fn Servo_CSSSupports(cond
         cond.eval(&context)
     } else {
         false
     }
 }
 
 /// Only safe to call on the main thread, with exclusive access to the element and
 /// its ancestors.
-unsafe fn maybe_restyle<'a>(data: &'a mut AtomicRefMut<ElementData>, element: GeckoElement)
+unsafe fn maybe_restyle<'a>(data: &'a mut AtomicRefMut<ElementData>,
+                            element: GeckoElement,
+                            animation_only: bool)
     -> Option<&'a mut RestyleData>
 {
     // Don't generate a useless RestyleData if the element hasn't been styled.
     if !data.has_styles() {
         return None;
     }
 
     // Propagate the bit up the chain.
     let mut curr = element;
     while let Some(parent) = curr.parent_element() {
         curr = parent;
-        if curr.has_dirty_descendants() { break; }
-        curr.set_dirty_descendants();
+        if animation_only {
+            if curr.has_animation_only_dirty_descendants() { break; }
+            curr.set_animation_only_dirty_descendants();
+        } else {
+            if curr.has_dirty_descendants() { break; }
+            curr.set_dirty_descendants();
+        }
     }
     bindings::Gecko_SetOwnerDocumentNeedsStyleFlush(element.0);
 
     // Ensure and return the RestyleData.
     Some(data.ensure_restyle())
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_Element_GetSnapshot(element: RawGeckoElementBorrowed) -> *mut structs::ServoElementSnapshot
 {
     let element = GeckoElement(element);
     let snapshot = match element.mutate_data() {
         None => ptr::null_mut(),
         Some(mut data) => {
-            if let Some(restyle_data) = unsafe { maybe_restyle(&mut data, element) } {
+            if let Some(restyle_data) = unsafe { maybe_restyle(&mut data, element, false) } {
                 restyle_data.snapshot.ensure(|| element.create_snapshot()).borrow_mut_raw()
             } else {
                 ptr::null_mut()
             }
         },
     };
 
     debug!("Servo_Element_GetSnapshot: {:?}: {:?}", element, snapshot);
@@ -1402,20 +1409,24 @@ pub extern "C" fn Servo_Element_GetSnaps
 #[no_mangle]
 pub extern "C" fn Servo_NoteExplicitHints(element: RawGeckoElementBorrowed,
                                           restyle_hint: nsRestyleHint,
                                           change_hint: nsChangeHint) {
     let element = GeckoElement(element);
     let damage = GeckoRestyleDamage::new(change_hint);
     debug!("Servo_NoteExplicitHints: {:?}, restyle_hint={:?}, change_hint={:?}",
            element, restyle_hint, change_hint);
+    debug_assert!(restyle_hint == structs::nsRestyleHint_eRestyle_CSSAnimations ||
+                  (restyle_hint.0 & structs::nsRestyleHint_eRestyle_CSSAnimations.0) == 0,
+                  "eRestyle_CSSAnimations should only appear by itself");
 
     let mut maybe_data = element.mutate_data();
-    let maybe_restyle_data =
-        maybe_data.as_mut().and_then(|d| unsafe { maybe_restyle(d, element) });
+    let maybe_restyle_data = maybe_data.as_mut().and_then(|d| unsafe {
+        maybe_restyle(d, element, restyle_hint == structs::nsRestyleHint_eRestyle_CSSAnimations)
+    });
     if let Some(restyle_data) = maybe_restyle_data {
         let restyle_hint: RestyleHint = restyle_hint.into();
         restyle_data.hint.insert(&restyle_hint.into());
         restyle_data.damage |= damage;
     } else {
         debug!("(Element not styled, discarding hints)");
     }
 }