Bug 1646629 - Set updateCanvasPending explicitly when reftest-wait was removed and take a snapshot of the whole screen if reftest-no-flush is specified. r?mattwoodrow,tnikkel
That's because we no longer fire MozAfterPaint event for changes by
animations on the compositor.
Differential Revision:
https://phabricator.services.mozilla.com/D80157
new file mode 100644
--- /dev/null
+++ b/layout/reftests/reftest-sanity/reftest-no-flush-ref.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<style>
+html {
+ overflow: hidden;
+}
+body {
+ margin: 0px;
+ padding: 0px;
+}
+#target {
+ width: 100px;
+ height: 100px;
+ position: absolute;
+ transform: translateX(100px);
+ background-color: green;
+}
+</style>
+<div id="target"></div>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/reftest-sanity/reftest-no-flush.html
@@ -0,0 +1,35 @@
+<!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% { transform: translateX(100px); }
+ 100% { transform: translateX(100px); }
+}
+#target {
+ width: 100px;
+ height: 100px;
+ position: absolute;
+ background-color: green;
+}
+</style>
+<div id="target"></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", () => {
+ document.documentElement.classList.remove("reftest-wait");
+ });
+}, { once: true });
+</script>
+</html>
--- a/layout/reftests/reftest-sanity/reftest.list
+++ b/layout/reftests/reftest-sanity/reftest.list
@@ -206,8 +206,10 @@ fails-if(layerChecksEnabled) != reftest-
!= reftest-assigned-layer-pass.html about:blank
fails-if(layerChecksEnabled) != reftest-assigned-layer-fail-1.html about:blank
fails-if(layerChecksEnabled) != reftest-assigned-layer-fail-2.html about:blank
fails-if(layerChecksEnabled) != reftest-assigned-layer-fail-3.html about:blank
fails-if(layerChecksEnabled) != reftest-assigned-layer-fail-4.html about:blank
# reftest-resolution
pref(apz.allow_zooming,true) == reftest-resolution.html reftest-resolution-ref.html
+
+== reftest-no-flush.html reftest-no-flush-ref.html
--- a/layout/tools/reftest/reftest-content.js
+++ b/layout/tools/reftest/reftest-content.js
@@ -438,16 +438,24 @@ function shouldWaitForReftestWaitRemoval
function shouldSnapshotWholePage(contentRootElement) {
// use getAttribute because className works differently in HTML and SVG
return contentRootElement &&
contentRootElement.hasAttribute('class') &&
contentRootElement.getAttribute('class').split(/\s+/)
.includes("reftest-snapshot-all");
}
+function shouldNotFlush(contentRootElement) {
+ // use getAttribute because className works differently in HTML and SVG
+ return contentRootElement &&
+ contentRootElement.hasAttribute('class') &&
+ contentRootElement.getAttribute('class').split(/\s+/)
+ .includes("reftest-no-flush");
+}
+
function getNoPaintElements(contentRootElement) {
return contentRootElement.getElementsByClassName('reftest-no-paint');
}
function getNoDisplayListElements(contentRootElement) {
return contentRootElement.getElementsByClassName('reftest-no-display-list');
}
function getDisplayListElements(contentRootElement) {
return contentRootElement.getElementsByClassName('reftest-display-list');
@@ -849,16 +857,23 @@ function WaitForTestEnd(contentRootEleme
LogInfo("MakeProgress: STATE_WAITING_FOR_REFTEST_WAIT_REMOVAL");
CheckForLivenessOfContentRootElement();
if (shouldWaitForReftestWaitRemoval(contentRootElement)) {
gFailureReason = "timed out waiting for reftest-wait to be removed";
LogInfo("MakeProgress: waiting for reftest-wait to be removed");
return;
}
+ if (shouldNotFlush(contentRootElement)) {
+ // If reftest-no-flush is specified, we need to set
+ // updateCanvasPending explicitly to take the latest snapshot
+ // since animation changes on the compositor thread don't invoke
+ // any MozAfterPaint events at all.
+ updateCanvasPending = true;
+ }
// Try next state
state = STATE_WAITING_FOR_SPELL_CHECKS;
MakeProgress();
return;
case STATE_WAITING_FOR_SPELL_CHECKS:
LogInfo("MakeProgress: STATE_WAITING_FOR_SPELL_CHECKS");
if (numPendingSpellChecks) {
@@ -881,19 +896,17 @@ function WaitForTestEnd(contentRootEleme
} else {
MakeProgress();
}
};
os.addObserver(flushWaiter, "apz-repaints-flushed");
var willSnapshot = IsSnapshottableTestType();
CheckForLivenessOfContentRootElement();
- var noFlush =
- !(contentRootElement &&
- contentRootElement.classList.contains("reftest-no-flush"));
+ var noFlush = !shouldNotFlush(contentRootElement);
if (noFlush && willSnapshot && windowUtils().flushApzRepaints()) {
LogInfo("MakeProgress: done requesting APZ flush");
} else {
LogInfo("MakeProgress: APZ flush not required");
flushWaiter(null, null, null);
}
return;
@@ -1370,17 +1383,17 @@ function SynchronizeForSnapshot(flags)
if (!IsSnapshottableTestType()) {
return Promise.resolve(undefined);
}
if (flags & SYNC_ALLOW_DISABLE) {
var docElt = content.document.documentElement;
if (docElt &&
(docElt.hasAttribute("reftest-no-sync-layers") ||
- docElt.classList.contains("reftest-no-flush"))) {
+ shouldNotFlush(docElt))) {
LogInfo("Test file chose to skip SynchronizeForSnapshot");
return Promise.resolve(undefined);
}
}
let browsingContext = content.docShell.browsingContext;
let promise = content.windowGlobalChild.getActor("ReftestFission").sendQuery("UpdateLayerTree", {browsingContext});
return promise.then(function (result) {
@@ -1637,20 +1650,22 @@ function SendUpdateCanvasForEvent(forURL
return promise.then(function () {
sendAsyncMessage("reftest:UpdateWholeCanvasForInvalidation");
});
}
return Promise.resolve(undefined);
}
var message;
- if (gIsWebRenderEnabled && !windowUtils().isMozAfterPaintPending) {
- // Webrender doesn't have invalidation, so we just invalidate the whole
- // screen once we don't have anymore paints pending. This will force
- // the snapshot.
+ if ((gIsWebRenderEnabled || shouldNotFlush(contentRootElement)) &&
+ !windowUtils().isMozAfterPaintPending) {
+ // Webrender doesn't have invalidation, and animations on the compositor
+ // don't invoke any MozAfterEvent which means we have no invalidated
+ // rect so we just invalidate the whole screen once we don't have
+ // anymore paints pending. This will force the snapshot.
LogInfo("Webrender enabled, sending update whole canvas for invalidation");
message = "reftest:UpdateWholeCanvasForInvalidation";
} else {
LogInfo("SendUpdateCanvasForEvent with " + rectList.length + " rects");
for (var i = 0; i < rectList.length; ++i) {
var r = rectList[i];
// Set left/top/right/bottom to "device pixel" boundaries