Bug 870192 - Prevent rounding issues in gfxMatrix::ScaleFactors from combinging with timing issues to cause sporadic invalidation of transforming elements. r=roc
authorJonathan Watt <jwatt@jwatt.org>
Mon, 13 May 2013 00:12:19 +0100
changeset 131685 b2f16d5e0ebde723a425c30d1576013c5cdd62ce
parent 131684 a51bca32e1dd25df11578fd8d8ad234e7b3f0e47
child 131686 89ae725c012559b4712d94a5e88fb8d44ee47f04
push id27933
push userjwatt@jwatt.org
push dateSun, 12 May 2013 23:13:11 +0000
treeherdermozilla-inbound@b2f16d5e0ebd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs870192
milestone23.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
Bug 870192 - Prevent rounding issues in gfxMatrix::ScaleFactors from combinging with timing issues to cause sporadic invalidation of transforming elements. r=roc
layout/base/FrameLayerBuilder.cpp
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -2621,16 +2621,21 @@ ContainerState::Finish(uint32_t* aTextCo
     Layer *layerToRemove = layer;
     layer = layer->GetNextSibling();
     mContainerLayer->RemoveChild(layerToRemove);
   }
 
   *aTextContentFlags = textContentFlags;
 }
 
+static inline gfxSize RoundToFloatPrecision(const gfxSize& aSize)
+{
+  return gfxSize(float(aSize.width), float(aSize.height));
+}
+
 static bool
 ChooseScaleAndSetTransform(FrameLayerBuilder* aLayerBuilder,
                            nsDisplayListBuilder* aDisplayListBuilder,
                            nsIFrame* aContainerFrame,
                            const gfx3DMatrix* aTransform,
                            const FrameLayerBuilder::ContainerParameters& aIncomingScale,
                            ContainerLayer* aLayer,
                            LayerState aState,
@@ -2682,33 +2687,33 @@ ChooseScaleAndSetTransform(FrameLayerBui
     // If the container's transform is animated off main thread, then use the
     // maximum scale.
     if (aContainerFrame->GetContent() &&
         nsLayoutUtils::HasAnimationsForCompositor(
           aContainerFrame->GetContent(), eCSSProperty_transform)) {
       scale = nsLayoutUtils::GetMaximumAnimatedScale(aContainerFrame->GetContent());
     } else {
       //Scale factors are normalized to a power of 2 to reduce the number of resolution changes
-      scale = transform2d.ScaleFactors(true);
+      scale = RoundToFloatPrecision(transform2d.ScaleFactors(true));
       // For frames with a changing transform that's not just a translation,
       // round scale factors up to nearest power-of-2 boundary so that we don't
       // keep having to redraw the content as it scales up and down. Rounding up to nearest
       // power-of-2 boundary ensures we never scale up, only down --- avoiding
       // jaggies. It also ensures we never scale down by more than a factor of 2,
       // avoiding bad downscaling quality.
       gfxMatrix frameTransform;
       if (aContainerFrame->AreLayersMarkedActive(nsChangeHint_UpdateTransformLayer) &&
           aTransform &&
           (!aTransform->Is2D(&frameTransform) || frameTransform.HasNonTranslationOrFlip())) {
         // Don't clamp the scale factor when the new desired scale factor matches the old one
         // or it was previously unscaled.
         bool clamp = true;
         gfxMatrix oldFrameTransform2d;
         if (aLayer->GetBaseTransform().Is2D(&oldFrameTransform2d)) {
-          gfxSize oldScale = oldFrameTransform2d.ScaleFactors(true);
+          gfxSize oldScale = RoundToFloatPrecision(oldFrameTransform2d.ScaleFactors(true));
           if (oldScale == scale || oldScale == gfxSize(1.0, 1.0)) {
             clamp = false;
           }
         }
         if (clamp) {
           scale.width = gfxUtils::ClampToScaleFactor(scale.width);
           scale.height = gfxUtils::ClampToScaleFactor(scale.height);
         }