servo: Merge #17850 - Record viewport unit usage and generate proper restyle hint (from upsuper:bug1382077); r=heycam
authorXidorn Quan <me@upsuper.org>
Tue, 25 Jul 2017 02:09:45 -0700
changeset 419517 d7eb050d790601812c56f8b1dba8bd916cd9fce5
parent 419516 a34cb0f468bce65e7b8e7eae1c86bcbd4529fa10
child 419518 7c3ddf34fc42d5fb32a9cd2d98ba84f3c606dc7d
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersheycam
bugs1382077
milestone56.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
servo: Merge #17850 - Record viewport unit usage and generate proper restyle hint (from upsuper:bug1382077); r=heycam This is the Servo side change of [bug 1382077](https://bugzilla.mozilla.org/show_bug.cgi?id=1382077). Source-Repo: https://github.com/servo/servo Source-Revision: e825bf14427c6aab239a82e09d0915467f23aa60
servo/components/style/gecko/generated/bindings.rs
servo/components/style/gecko/media_queries.rs
servo/components/style/stylesheets/viewport_rule.rs
servo/ports/geckolib/glue.rs
--- a/servo/components/style/gecko/generated/bindings.rs
+++ b/servo/components/style/gecko/generated/bindings.rs
@@ -1916,18 +1916,19 @@ extern "C" {
 }
 extern "C" {
     pub fn Servo_StyleSet_Clear(set: RawServoStyleSetBorrowed);
 }
 extern "C" {
     pub fn Servo_StyleSet_RebuildData(set: RawServoStyleSetBorrowed);
 }
 extern "C" {
-    pub fn Servo_StyleSet_MediumFeaturesChanged(set: RawServoStyleSetBorrowed)
-     -> bool;
+    pub fn Servo_StyleSet_MediumFeaturesChanged(set: RawServoStyleSetBorrowed,
+                                                viewport_changed: bool)
+     -> nsRestyleHint;
 }
 extern "C" {
     pub fn Servo_StyleSet_CompatModeChanged(raw_data:
                                                 RawServoStyleSetBorrowed);
 }
 extern "C" {
     pub fn Servo_StyleSet_AppendStyleSheet(set: RawServoStyleSetBorrowed,
                                            gecko_sheet:
--- a/servo/components/style/gecko/media_queries.rs
+++ b/servo/components/style/gecko/media_queries.rs
@@ -49,31 +49,35 @@ pub struct Device {
     /// When computing the style of the root element, there can't be any
     /// other style being computed at the same time, given we need the style of
     /// the parent to compute everything else. So it is correct to just use
     /// a relaxed atomic here.
     root_font_size: AtomicIsize,
     /// Whether any styles computed in the document relied on the root font-size
     /// by using rem units.
     used_root_font_size: AtomicBool,
+    /// Whether any styles computed in the document relied on the viewport size
+    /// by using vw/vh/vmin/vmax units.
+    used_viewport_size: AtomicBool,
 }
 
 unsafe impl Sync for Device {}
 unsafe impl Send for Device {}
 
 impl Device {
     /// Trivially constructs a new `Device`.
     pub fn new(pres_context: RawGeckoPresContextOwned) -> Self {
         assert!(!pres_context.is_null());
         Device {
             pres_context: pres_context,
             default_values: ComputedValues::default_values(unsafe { &*pres_context }),
             viewport_override: None,
             root_font_size: AtomicIsize::new(font_size::get_initial_value().0 as isize), // FIXME(bz): Seems dubious?
             used_root_font_size: AtomicBool::new(false),
+            used_viewport_size: AtomicBool::new(false),
         }
     }
 
     /// Tells the device that a new viewport rule has been found, and stores the
     /// relevant viewport constraints.
     pub fn account_for_viewport_rule(&mut self,
                                      constraints: &ViewportConstraints) {
         self.viewport_override = Some(constraints.clone());
@@ -107,16 +111,17 @@ impl Device {
     }
 
     /// Recreates the default computed values.
     pub fn reset_computed_values(&mut self) {
         // NB: A following stylesheet flush will populate this if appropriate.
         self.viewport_override = None;
         self.default_values = ComputedValues::default_values(self.pres_context());
         self.used_root_font_size.store(false, Ordering::Relaxed);
+        self.used_viewport_size.store(false, Ordering::Relaxed);
     }
 
     /// Returns whether we ever looked up the root font size of the Device.
     pub fn used_root_font_size(&self) -> bool {
         self.used_root_font_size.load(Ordering::Relaxed)
     }
 
     /// Recreates all the temporary state that the `Device` stores.
@@ -141,26 +146,32 @@ impl Device {
                 debug_assert!(self.pres_context().mMedium == atom!("print").as_ptr());
                 MediaType::Print
             }
         }
     }
 
     /// Returns the current viewport size in app units.
     pub fn au_viewport_size(&self) -> Size2D<Au> {
+        self.used_viewport_size.store(true, Ordering::Relaxed);
         self.viewport_override.as_ref().map(|v| {
             Size2D::new(Au::from_f32_px(v.size.width),
                         Au::from_f32_px(v.size.height))
         }).unwrap_or_else(|| unsafe {
             // TODO(emilio): Need to take into account scrollbars.
             let area = &self.pres_context().mVisibleArea;
             Size2D::new(Au(area.width), Au(area.height))
         })
     }
 
+    /// Returns whether we ever looked up the viewport size of the Device.
+    pub fn used_viewport_size(&self) -> bool {
+        self.used_viewport_size.load(Ordering::Relaxed)
+    }
+
     /// Returns the device pixel ratio.
     pub fn device_pixel_ratio(&self) -> ScaleFactor<f32, CSSPixel, DevicePixel> {
         let override_dppx = self.pres_context().mOverrideDPPX;
         if override_dppx > 0.0 { return ScaleFactor::new(override_dppx); }
         let au_per_dpx = self.pres_context().mCurAppUnitsPerDevPixel as f32;
         let au_per_px = AU_PER_PX as f32;
         ScaleFactor::new(au_per_px / au_per_dpx)
     }
--- a/servo/components/style/stylesheets/viewport_rule.rs
+++ b/servo/components/style/stylesheets/viewport_rule.rs
@@ -691,16 +691,20 @@ impl MaybeNew for ViewportConstraints {
         if initial_zoom.is_some() {
             initial_zoom = max!(min_zoom, min!(max_zoom, initial_zoom));
         }
 
         // DEVICE-ADAPT § 6.2.3 Resolve non-auto lengths to pixel lengths
         //
         // Note: DEVICE-ADAPT § 5. states that relative length values are
         // resolved against initial values
+        //
+        // Note, we set used_viewport_size flag for Gecko in au_viewport_size.
+        // If we ever start supporting ViewportRule in Gecko, we probably want
+        // to avoid doing so at this place.
         let initial_viewport = device.au_viewport_size();
 
         let provider = get_metrics_provider_for_product();
 
         let default_values = device.default_computed_values();
 
         let context = Context {
             is_root_element: false,
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -860,37 +860,46 @@ pub extern "C" fn Servo_StyleSet_AppendS
         &guard
     );
     data.clear_stylist();
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_StyleSet_MediumFeaturesChanged(
     raw_data: RawServoStyleSetBorrowed,
-) -> bool {
+    viewport_changed: bool,
+) -> nsRestyleHint {
     let global_style_data = &*GLOBAL_STYLE_DATA;
     let guard = global_style_data.shared_lock.read();
 
     // NOTE(emilio): We don't actually need to flush the stylist here and ensure
     // it's up to date.
     //
     // In case it isn't we would trigger a rebuild + restyle as needed too.
     //
     // We need to ensure the default computed values are up to date though,
     // because those can influence the result of media query evaluation.
     //
     // FIXME(emilio, bug 1369984): do the computation conditionally, to do it
     // less often.
     let mut data = PerDocumentStyleData::from_ffi(raw_data).borrow_mut();
 
+    let viewport_units_used = data.stylist.device().used_viewport_size();
     data.stylist.device_mut().reset_computed_values();
-    data.stylist.media_features_change_changed_style(
+    let rules_changed = data.stylist.media_features_change_changed_style(
         data.stylesheets.iter(),
         &guard,
-    )
+    );
+    if rules_changed {
+        structs::nsRestyleHint_eRestyle_Subtree
+    } else if viewport_changed && viewport_units_used {
+        structs::nsRestyleHint_eRestyle_ForceDescendants
+    } else {
+        nsRestyleHint(0)
+    }
 }
 
 #[no_mangle]
 pub extern "C" fn Servo_StyleSet_PrependStyleSheet(
     raw_data: RawServoStyleSetBorrowed,
     sheet: *const ServoStyleSheet,
 ) {
     let global_style_data = &*GLOBAL_STYLE_DATA;