author | Jerry Shih <hshih@mozilla.com> |
Tue, 18 Feb 2014 09:58:01 -0500 | |
changeset 169366 | 940b00462eb765491c176727f08c59b14f82a450 |
parent 169365 | b95d0fb140264ad21beb8bcf91f590ab1122bc02 |
child 169367 | 31806aaa5ab26bae48c167acb08ea314ac6d1a45 |
push id | 26245 |
push user | ryanvm@gmail.com |
push date | Tue, 18 Feb 2014 20:18:17 +0000 |
treeherder | mozilla-central@9019cc90719c [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | roc |
bugs | 972310 |
milestone | 30.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
|
--- a/layout/base/FrameLayerBuilder.cpp +++ b/layout/base/FrameLayerBuilder.cpp @@ -2989,22 +2989,22 @@ ChooseScaleAndSetTransform(FrameLayerBui if (transform.IsSingular()) { return false; } bool canDraw2D = transform.CanDraw2D(&transform2d); gfxSize scale; // XXX Should we do something for 3D transforms? if (canDraw2D) { -// // If the container's transform is animated off main thread, then use the - // maximum scale. + // If the container's transform is animated off main thread, fix a suitable scale size + // for animation if (aContainerFrame->GetContent() && nsLayoutUtils::HasAnimationsForCompositor( aContainerFrame->GetContent(), eCSSProperty_transform)) { - scale = nsLayoutUtils::GetMaximumAnimatedScale(aContainerFrame->GetContent()); + scale = nsLayoutUtils::ComputeSuitableScaleForAnimation(aContainerFrame->GetContent()); } else { // Scale factors are normalized to a power of 2 to reduce the number of resolution changes 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,
--- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -304,73 +304,93 @@ GetScaleForValue(const nsStyleAnimation: bool canDraw2D = transform.CanDraw2D(&transform2d); if (!canDraw2D) { return gfxSize(); } return transform2d.ScaleFactors(true); } +float +GetSuitableScale(float aMaxScale, float aMinScale) +{ + // If the minimum scale >= 1.0f, use it; if the maximum <= 1.0f, use it; + // otherwise use 1.0f. + if (aMinScale >= 1.0f) { + return aMinScale; + } + else if (aMaxScale <= 1.0f) { + return aMaxScale; + } + + return 1.0f; +} + gfxSize -nsLayoutUtils::GetMaximumAnimatedScale(nsIContent* aContent) -{ - gfxSize result; +nsLayoutUtils::ComputeSuitableScaleForAnimation(nsIContent* aContent) +{ + gfxSize maxScale(1.0f, 1.0f); + gfxSize minScale(1.0f, 1.0f); + ElementAnimations* animations = HasAnimationOrTransitionForCompositor<ElementAnimations> (aContent, nsGkAtoms::animationsProperty, eCSSProperty_transform); if (animations) { for (uint32_t animIdx = animations->mAnimations.Length(); animIdx-- != 0; ) { ElementAnimation& anim = animations->mAnimations[animIdx]; for (uint32_t propIdx = anim.mProperties.Length(); propIdx-- != 0; ) { AnimationProperty& prop = anim.mProperties[propIdx]; if (prop.mProperty == eCSSProperty_transform) { for (uint32_t segIdx = prop.mSegments.Length(); segIdx-- != 0; ) { AnimationPropertySegment& segment = prop.mSegments[segIdx]; gfxSize from = GetScaleForValue(segment.mFromValue, aContent->GetPrimaryFrame()); - result.width = std::max<float>(result.width, from.width); - result.height = std::max<float>(result.height, from.height); + maxScale.width = std::max<float>(maxScale.width, from.width); + maxScale.height = std::max<float>(maxScale.height, from.height); + minScale.width = std::min<float>(minScale.width, from.width); + minScale.height = std::min<float>(minScale.height, from.height); gfxSize to = GetScaleForValue(segment.mToValue, aContent->GetPrimaryFrame()); - result.width = std::max<float>(result.width, to.width); - result.height = std::max<float>(result.height, to.height); + maxScale.width = std::max<float>(maxScale.width, to.width); + maxScale.height = std::max<float>(maxScale.height, to.height); + minScale.width = std::min<float>(minScale.width, to.width); + minScale.height = std::min<float>(minScale.height, to.height); } } } } } + ElementTransitions* transitions = HasAnimationOrTransitionForCompositor<ElementTransitions> (aContent, nsGkAtoms::transitionsProperty, eCSSProperty_transform); if (transitions) { for (uint32_t i = 0, i_end = transitions->mPropertyTransitions.Length(); - i < i_end; ++i) - { + i < i_end; ++i){ ElementPropertyTransition &pt = transitions->mPropertyTransitions[i]; if (pt.IsRemovedSentinel()) { continue; } - if (pt.mProperty == eCSSProperty_transform) { gfxSize start = GetScaleForValue(pt.mStartValue, aContent->GetPrimaryFrame()); - result.width = std::max<float>(result.width, start.width); - result.height = std::max<float>(result.height, start.height); + maxScale.width = std::max<float>(maxScale.width, start.width); + maxScale.height = std::max<float>(maxScale.height, start.height); + minScale.width = std::min<float>(minScale.width, start.width); + minScale.height = std::min<float>(minScale.height, start.height); gfxSize end = GetScaleForValue(pt.mEndValue, aContent->GetPrimaryFrame()); - result.width = std::max<float>(result.width, end.width); - result.height = std::max<float>(result.height, end.height); + maxScale.width = std::max<float>(maxScale.width, end.width); + maxScale.height = std::max<float>(maxScale.height, end.height); + minScale.width = std::min<float>(minScale.width, end.width); + minScale.height = std::min<float>(minScale.height, end.height); } } } - // If we didn't manage to find a max scale, use no scale rather than 0,0 - if (result == gfxSize()) { - return gfxSize(1, 1); - } - - return result; + return gfxSize(GetSuitableScale(maxScale.width, minScale.width), + GetSuitableScale(maxScale.height, minScale.height)); } bool nsLayoutUtils::AreAsyncAnimationsEnabled() { static bool sAreAsyncAnimationsEnabled; static bool sAsyncPrefCached = false;
--- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -1723,21 +1723,24 @@ public: static bool AreAsyncAnimationsEnabled(); /** * Checks if we should warn about animations that can't be async */ static bool IsAnimationLoggingEnabled(); /** - * Find the maximum scale for an element (aContent) over the course of any - * animations and transitions on the element. Will return 1,1 if there is no - * animated scaling. + * Find a suitable scale for an element (aContent) over the course of any + * animations and transitions on the element. + * It will check the maximum and minimum scale during the animations and + * transitions and return a suitable value for performance and quality. + * Will return scale(1,1) if there is no animated scaling. + * Always return positive value. */ - static gfxSize GetMaximumAnimatedScale(nsIContent* aContent); + static gfxSize ComputeSuitableScaleForAnimation(nsIContent* aContent); /** * Checks if we should forcibly use nearest pixel filtering for the * background. */ static bool UseBackgroundNearestFiltering(); /**