From 2e0f2286ad71605b3b959f0cc175e4bc5357c299 Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Mon, 15 Jun 2015 19:20:59 -0400 Subject: [PATCH] Bug 1165185 - Try to avoid invalidations when scrolling transformed elements. r=roc --- gfx/2d/Matrix.h | 39 +++++++++++++++++++ gfx/layers/LayerTreeInvalidation.cpp | 2 +- layout/base/FrameLayerBuilder.cpp | 13 ++++--- .../backgrounds/vector/empty/reftest.list | 9 ++--- .../invalidation/fractional-transform-1.html | 36 +++++++++++++++++ .../invalidation/fractional-transform-2.html | 32 +++++++++++++++ .../invalidation/fractional-transform-3.html | 32 +++++++++++++++ layout/reftests/invalidation/reftest.list | 3 ++ mfbt/FloatingPoint.h | 7 ++++ 9 files changed, 161 insertions(+), 12 deletions(-) create mode 100644 layout/reftests/invalidation/fractional-transform-1.html create mode 100644 layout/reftests/invalidation/fractional-transform-2.html create mode 100644 layout/reftests/invalidation/fractional-transform-3.html diff --git a/gfx/2d/Matrix.h b/gfx/2d/Matrix.h index d865993fe2a..dec7c9ff98f 100644 --- a/gfx/2d/Matrix.h +++ b/gfx/2d/Matrix.h @@ -13,6 +13,7 @@ #include #include "mozilla/Attributes.h" #include "mozilla/DebugOnly.h" +#include "mozilla/FloatingPoint.h" namespace mozilla { namespace gfx { @@ -857,6 +858,26 @@ public: gfx::FuzzyEqual(_43, o._43) && gfx::FuzzyEqual(_44, o._44); } + bool FuzzyEqualsMultiplicative(const Matrix4x4& o) const + { + return ::mozilla::FuzzyEqualsMultiplicative(_11, o._11) && + ::mozilla::FuzzyEqualsMultiplicative(_12, o._12) && + ::mozilla::FuzzyEqualsMultiplicative(_13, o._13) && + ::mozilla::FuzzyEqualsMultiplicative(_14, o._14) && + ::mozilla::FuzzyEqualsMultiplicative(_21, o._21) && + ::mozilla::FuzzyEqualsMultiplicative(_22, o._22) && + ::mozilla::FuzzyEqualsMultiplicative(_23, o._23) && + ::mozilla::FuzzyEqualsMultiplicative(_24, o._24) && + ::mozilla::FuzzyEqualsMultiplicative(_31, o._31) && + ::mozilla::FuzzyEqualsMultiplicative(_32, o._32) && + ::mozilla::FuzzyEqualsMultiplicative(_33, o._33) && + ::mozilla::FuzzyEqualsMultiplicative(_34, o._34) && + ::mozilla::FuzzyEqualsMultiplicative(_41, o._41) && + ::mozilla::FuzzyEqualsMultiplicative(_42, o._42) && + ::mozilla::FuzzyEqualsMultiplicative(_43, o._43) && + ::mozilla::FuzzyEqualsMultiplicative(_44, o._44); + } + bool IsBackfaceVisible() const { // Inverse()._33 < 0; @@ -889,6 +910,24 @@ public: return *this; } + // Nudge the 3D components to integer so that this matrix will become 2D if + // it's very close to already being 2D. + // This doesn't change the _41 and _42 components. + Matrix4x4 &NudgeTo2D() + { + NudgeToInteger(&_13); + NudgeToInteger(&_14); + NudgeToInteger(&_23); + NudgeToInteger(&_24); + NudgeToInteger(&_31); + NudgeToInteger(&_32); + NudgeToInteger(&_33); + NudgeToInteger(&_34); + NudgeToInteger(&_43); + NudgeToInteger(&_44); + return *this; + } + Point4D TransposedVector(int aIndex) const { MOZ_ASSERT(aIndex >= 0 && aIndex <= 3, "Invalid matrix array index"); diff --git a/gfx/layers/LayerTreeInvalidation.cpp b/gfx/layers/LayerTreeInvalidation.cpp index c0f47684667..7154639943b 100644 --- a/gfx/layers/LayerTreeInvalidation.cpp +++ b/gfx/layers/LayerTreeInvalidation.cpp @@ -136,7 +136,7 @@ struct LayerPropertiesBase : public LayerProperties nsIntRegion ComputeChange(NotifySubDocInvalidationFunc aCallback, bool& aGeometryChanged) { - bool transformChanged = !mTransform.FuzzyEqual(mLayer->GetLocalTransform()) || + bool transformChanged = !mTransform.FuzzyEqualsMultiplicative(mLayer->GetLocalTransform()) || mLayer->GetPostXScale() != mPostXScale || mLayer->GetPostYScale() != mPostYScale; Layer* otherMask = mLayer->GetMaskLayer(); diff --git a/layout/base/FrameLayerBuilder.cpp b/layout/base/FrameLayerBuilder.cpp index 120fc3b7ab3..d876c347c31 100644 --- a/layout/base/FrameLayerBuilder.cpp +++ b/layout/base/FrameLayerBuilder.cpp @@ -4630,12 +4630,13 @@ ChooseScaleAndSetTransform(FrameLayerBuilder* aLayerBuilder, if (aTransform) { // aTransform is applied first, then the scale is applied to the result transform = (*aTransform)*transform; - // Set any matrix entries close to integers to be those exact integers. - // This protects against floating-point inaccuracies causing problems - // in the checks below. - // We use the fixed epsilon version here because we don't want the nudging - // to depend on the scroll position. - transform.NudgeToIntegersFixedEpsilon(); + // Set relevant 3d matrix entries that are close to integers to be those + // exact integers. This protects against floating-point inaccuracies + // causing problems in the CanDraw2D / Is2D checks below. + // We don't nudge all matrix components here. In particular, we don't want to + // nudge the X/Y translation components, because those include the scroll + // offset, and we don't want scrolling to affect whether we nudge or not. + transform.NudgeTo2D(); } Matrix transform2d; if (aContainerFrame && diff --git a/layout/reftests/backgrounds/vector/empty/reftest.list b/layout/reftests/backgrounds/vector/empty/reftest.list index d83e5c1da69..e65c8340564 100644 --- a/layout/reftests/backgrounds/vector/empty/reftest.list +++ b/layout/reftests/backgrounds/vector/empty/reftest.list @@ -3,11 +3,10 @@ == wide--contain--height.html ref-wide-empty.html == wide--contain--width.html ref-wide-empty.html -# These tests fail because of integer overflow; see bug 894555. -fails == tall--cover--height.html ref-tall-lime.html -fails == tall--cover--width.html ref-tall-lime.html -fails == wide--cover--height.html ref-wide-lime.html -fails == wide--cover--width.html ref-wide-lime.html +== tall--cover--height.html ref-tall-lime.html +== tall--cover--width.html ref-tall-lime.html +== wide--cover--height.html ref-wide-lime.html +== wide--cover--width.html ref-wide-lime.html == zero-height-ratio-contain.html ref-tall-empty.html == zero-height-ratio-cover.html ref-tall-empty.html diff --git a/layout/reftests/invalidation/fractional-transform-1.html b/layout/reftests/invalidation/fractional-transform-1.html new file mode 100644 index 00000000000..778621bcbce --- /dev/null +++ b/layout/reftests/invalidation/fractional-transform-1.html @@ -0,0 +1,36 @@ + + + +Scrolling shouldn't invalidate either rect. + + + + + + + + + + + + + + + + + + diff --git a/layout/reftests/invalidation/fractional-transform-2.html b/layout/reftests/invalidation/fractional-transform-2.html new file mode 100644 index 00000000000..9e47164ae32 --- /dev/null +++ b/layout/reftests/invalidation/fractional-transform-2.html @@ -0,0 +1,32 @@ + + + +Scrolling shouldn't invalidate the square. + + + + + + + + + + + + + + diff --git a/layout/reftests/invalidation/fractional-transform-3.html b/layout/reftests/invalidation/fractional-transform-3.html new file mode 100644 index 00000000000..ebd89a66d69 --- /dev/null +++ b/layout/reftests/invalidation/fractional-transform-3.html @@ -0,0 +1,32 @@ + + + +Scrolling shouldn't invalidate the square. + + + + + + + + + + + + + + diff --git a/layout/reftests/invalidation/reftest.list b/layout/reftests/invalidation/reftest.list index 6acb8da1c26..6c726cd8eaf 100644 --- a/layout/reftests/invalidation/reftest.list +++ b/layout/reftests/invalidation/reftest.list @@ -67,3 +67,6 @@ pref(layout.animated-image-layers.enabled,true) skip-if(Android||gtkWidget) == t fuzzy-if(gtkWidget,2,4) == image-scrolling-zoom-1.html image-scrolling-zoom-1-ref.html != image-scrolling-zoom-1-ref.html image-scrolling-zoom-1-notref.html != fast-scrolling.html about:blank +!= fractional-transform-1.html about:blank +!= fractional-transform-2.html about:blank +!= fractional-transform-3.html about:blank diff --git a/mfbt/FloatingPoint.h b/mfbt/FloatingPoint.h index abe261d5ca8..279363842cf 100644 --- a/mfbt/FloatingPoint.h +++ b/mfbt/FloatingPoint.h @@ -401,6 +401,13 @@ FuzzyEqualsMultiplicative(T aValue1, T aValue2, T aEpsilon = detail::FuzzyEqualsEpsilon::value()) { static_assert(IsFloatingPoint::value, "floating point type required"); + + // Short-circuit the common case in order to avoid the expensive operations + // below. + if (aValue1 == aValue2) { + return true; + } + // can't use std::min because of bug 965340 T smaller = Abs(aValue1) < Abs(aValue2) ? Abs(aValue1) : Abs(aValue2); return Abs(aValue1 - aValue2) <= aEpsilon * smaller;