Bug 972310 - Set a suitable layer size for css scale animation/transition. r=roc

This commit is contained in:
Jerry Shih 2014-02-18 09:58:01 -05:00
parent 56f7c1ed2b
commit cbf26b902d
3 changed files with 50 additions and 27 deletions

View File

@ -2994,12 +2994,12 @@ ChooseScaleAndSetTransform(FrameLayerBuilder* aLayerBuilder,
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));

View File

@ -309,10 +309,27 @@ GetScaleForValue(const nsStyleAnimation::Value& aValue,
return transform2d.ScaleFactors(true);
}
gfxSize
nsLayoutUtils::GetMaximumAnimatedScale(nsIContent* aContent)
float
GetSuitableScale(float aMaxScale, float aMinScale)
{
gfxSize result;
// 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::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) {
@ -325,47 +342,50 @@ nsLayoutUtils::GetMaximumAnimatedScale(nsIContent* aContent)
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

View File

@ -1728,11 +1728,14 @@ public:
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