Bug 1714763. When computing the local scale use the local transform and the parent scale rather than the local transform and parent transform. r=jrmuizel

When the scale of the parent transform is increasing the parent scale will be much larger than the scale of the parent transform.

The bug in the testcase happens because there are two nested transforms. The outer is animating in scale between 0 and 1. So the choosen mScale for the parent is 1 and the scale of the transform at any instantaneous point is usually smaller, say 0.2. The inner transform is just a flip and is not animated. We combine that parent transform with our local flip transform and get a transform with a scale of 0.2 and use that as our mScale. However this ignores the animating aspect of the parent transform and the fact we choose an mScale of 1 for the parent.

To fix this we bring how we use ChooseScale with webrender more into alignment with how we used ChooseScale with non-wr/FrameLayerBuilder.

https://searchfox.org/mozilla-esr91/rev/f3f439e007bdd4b5b1c2ba05ca706b68563413b2/layout/painting/FrameLayerBuilder.cpp#6047

The old code was structured a little differently which obscured this difference. The old code had ChooseScale (the code shared by webrender and FrameLayerBuilder) and a wrapper function ChooseScaleAndSetTransform which only FrameLayerBuilder used. The old code passed the local transform to ChooseScaleAndSetTransform, and then ChooseScaleAndSetTransform combined it with the parent scale and then passed that transform to ChooseScale. Whereas webrender passed the combined transform to ChooseScale. This would produce the same results except if the scale was animating.

This mimics how we compute the scale in HasAnimationsForCompositor branch above, where we compute a scale for the local transform and then combine that with the parent scale.

See also bug 1569215 where we first started passing the parent scale into ChooseScale so that the HasAnimationsForCompositor would choose the correct scale.

Differential Revision: https://phabricator.services.mozilla.com/D178996
This commit is contained in:
Timothy Nikkel 2023-06-08 10:20:07 +00:00
parent 4f43391056
commit a57976fc90
8 changed files with 287 additions and 2 deletions

View File

@ -76,7 +76,8 @@ MatrixScales ChooseScale(nsIFrame* aContainerFrame,
} else {
// Scale factors are normalized to a power of 2 to reduce the number of
// resolution changes
scale = aTransform2d.ScaleFactors();
scale = (aTransform2d * gfx::Matrix::Scaling(aXScale, aYScale))
.ScaleFactors();
// For frames with a changing scale transform 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
@ -152,7 +153,7 @@ StackingContextHelper::StackingContextHelper(
nsRect r = LayoutDevicePixel::ToAppUnits(aBounds, apd);
mScale = ChooseScale(aContainerFrame, aContainerItem, r,
aParentSC.mScale.xScale, aParentSC.mScale.yScale,
mInheritedTransform,
transform2d,
/* aCanDraw2D = */ true);
} else {
mScale = gfx::MatrixScales(1.0f, 1.0f);

View File

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html>
<style>
html {
/* Suppress scrollbars to avoid periodical unthrottling for transform */
/* animations on the compositor. */
overflow: hidden;
}
body {
margin: 0px;
padding: 0px;
}
#target {
position: absolute;
left:100px;
top:100px;
scale:2.1;
}
#rotate {
transform: rotate(180deg);
transform-origin: 50% 50%;
}
#theimg {
width: 100px;
height: 100px;
}
</style>
<body>
<div id="target">
<div id="rotate">
<img id="theimg" src="repeatable-diagonal-gradient.png">
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,56 @@
<!DOCTYPE html>
<html class="reftest-wait reftest-no-flush">
<style>
html {
/* Suppress scrollbars to avoid periodical unthrottling for transform */
/* animations on the compositor. */
overflow: hidden;
}
body {
margin: 0px;
padding: 0px;
}
@keyframes anim {
0% { scale: 2.1; }
100% { scale: 2.1; }
}
#target {
position: absolute;
left:100px;
top:100px;
scale:0.05;
}
#rotate {
transform: rotate(180deg);
transform-origin: 50% 50%;
}
#theimg {
width: 100px;
height: 100px;
}
</style>
<body>
<div id="target">
<div id="rotate">
<img id="theimg" src="repeatable-diagonal-gradient.png">
</div>
</div>
<script>
document.addEventListener('MozReftestInvalidate', () => {
// Set a bit longer animation delay to avoid painting the initial animation
// style on the main thread.
target.style.animation = "anim 100s 1s";
target.addEventListener("animationstart", () => {
requestAnimationFrame(() => {
requestAnimationFrame(() => {
document.documentElement.classList.remove("reftest-wait");
});
});
});
}, { once: true });
</script>
</body>
</html>

View File

@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<style>
html {
/* Suppress scrollbars to avoid periodical unthrottling for transform */
/* animations on the compositor. */
overflow: hidden;
}
body {
margin: 0px;
padding: 0px;
}
#target {
position: absolute;
left:100px;
top:100px;
scale:2.1;
}
#rotate {
transform: rotate(180deg);
transform-origin: 50% 50%;
}
#theimg {
width: 100px;
height: 100px;
clip-path: polygon(0 0,100% 0,50% 100%);
}
</style>
<body>
<div id="target">
<div id="rotate">
<img id="theimg" src="repeatable-diagonal-gradient.png">
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,57 @@
<!DOCTYPE html>
<html class="reftest-wait reftest-no-flush">
<style>
html {
/* Suppress scrollbars to avoid periodical unthrottling for transform */
/* animations on the compositor. */
overflow: hidden;
}
body {
margin: 0px;
padding: 0px;
}
@keyframes anim {
0% { scale: 2.1; }
100% { scale: 2.1; }
}
#target {
position: absolute;
left:100px;
top:100px;
scale:0.05;
}
#rotate {
transform: rotate(180deg);
transform-origin: 50% 50%;
}
#theimg {
width: 100px;
height: 100px;
clip-path: polygon(0 0,100% 0,50% 100%);
}
</style>
<body>
<div id="target">
<div id="rotate">
<img id="theimg" src="repeatable-diagonal-gradient.png">
</div>
</div>
<script>
document.addEventListener('MozReftestInvalidate', () => {
// Set a bit longer animation delay to avoid painting the initial animation
// style on the main thread.
target.style.animation = "anim 100s 1s";
target.addEventListener("animationstart", () => {
requestAnimationFrame(() => {
requestAnimationFrame(() => {
document.documentElement.classList.remove("reftest-wait");
});
});
});
}, { once: true });
</script>
</body>
</html>

View File

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html>
<style>
html {
/* Suppress scrollbars to avoid periodical unthrottling for transform */
/* animations on the compositor. */
overflow: hidden;
}
body {
margin: 0px;
padding: 0px;
}
#target {
position: absolute;
left:100px;
top:100px;
scale:1.9;
}
#rotate {
transform: rotate(180deg);
transform-origin: 50% 50%;
}
</style>
<body>
<div id="target">
<div id="rotate">
<svg width="100" height="100">
<g id="g">
<circle cx="100" cy="100" r="40" style="fill: rgb(200, 20, 20);"></circle>
</g>
</svg>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,56 @@
<!DOCTYPE html>
<html class="reftest-wait reftest-no-flush">
<style>
html {
/* Suppress scrollbars to avoid periodical unthrottling for transform */
/* animations on the compositor. */
overflow: hidden;
}
body {
margin: 0px;
padding: 0px;
}
@keyframes anim {
0% { scale: 1.9; }
100% { scale: 1.9; }
}
#target {
position: absolute;
left:100px;
top:100px;
scale:0.05;
}
#rotate {
transform: rotate(180deg);
transform-origin: 50% 50%;
}
</style>
<body>
<div id="target">
<div id="rotate">
<svg width="100" height="100">
<g id="g">
<circle cx="100" cy="100" r="40" style="fill: rgb(200, 20, 20);"></circle>
</g>
</svg>
</div>
</div>
<script>
document.addEventListener('MozReftestInvalidate', () => {
// Set a bit longer animation delay to avoid painting the initial animation
// style on the main thread.
target.style.animation = "anim 100s 1s";
target.addEventListener("animationstart", () => {
requestAnimationFrame(() => {
requestAnimationFrame(() => {
document.documentElement.classList.remove("reftest-wait");
});
});
});
}, { once: true });
</script>
</body>
</html>

View File

@ -2091,6 +2091,9 @@ fuzzy(0-2,0-96600) == 1648282-1b.html 1648282-1-ref.html
== 1673677-3.html 1673677-3-ref.html
== 1686729-1.html 1686729-1-ref.html
!= chrome://reftest/content/bugs/1688004.xhtml about:blank
pref(image.downscale-during-decode.enabled,true) fuzzy-if(OSX||winWidget,0-167,0-44310) fuzzy-if(gtkWidget,0-2,0-37220) == 1714763-1.html 1714763-1-ref.html
pref(image.downscale-during-decode.enabled,true) fuzzy-if(OSX||winWidget,0-166,0-22530) fuzzy-if(gtkWidget,0-18,0-19006) fuzzy-if(Android,0-21,0-22254) == 1714763-2.html 1714763-2-ref.html
pref(image.downscale-during-decode.enabled,true) fuzzy-if(OSX||winWidget,0-235,0-289) fuzzy-if(gtkWidget,0-186,0-240) fuzzy-if(Android,0-185,0-232) == 1714763-3.html 1714763-3-ref.html
skip-if(!appleSilicon) != 1721223-1.html 1721223-1-notref.html # Big Sur required for updated system font; OSX value is clamped to 10.15
skip-if(Android) == 1727172-1.xhtml 1727172-1-ref.html
== 1726663-1.html 1726663-1-ref.html