summaryrefslogtreecommitdiffstats
path: root/layout/reftests/invalidation
diff options
context:
space:
mode:
Diffstat (limited to 'layout/reftests/invalidation')
-rw-r--r--layout/reftests/invalidation/1243409-1-ref.html11
-rw-r--r--layout/reftests/invalidation/1243409-1.html28
-rw-r--r--layout/reftests/invalidation/540247-1-ref.xul29
-rw-r--r--layout/reftests/invalidation/540247-1.xul33
-rw-r--r--layout/reftests/invalidation/543681-1-ref.html18
-rw-r--r--layout/reftests/invalidation/543681-1.html22
-rw-r--r--layout/reftests/invalidation/background-position-1-ref.html31
-rw-r--r--layout/reftests/invalidation/background-position-1.html41
-rw-r--r--layout/reftests/invalidation/background-position-2-ref.html20
-rw-r--r--layout/reftests/invalidation/background-position-2a.html32
-rw-r--r--layout/reftests/invalidation/background-position-2b.html36
-rw-r--r--layout/reftests/invalidation/background-position-2c.html36
-rw-r--r--layout/reftests/invalidation/background-position-2d.html43
-rw-r--r--layout/reftests/invalidation/background-position-2e.html43
-rw-r--r--layout/reftests/invalidation/background-position-2f.html36
-rw-r--r--layout/reftests/invalidation/box-shadow-border-radius-ref.html19
-rw-r--r--layout/reftests/invalidation/box-shadow-border-radius.html27
-rw-r--r--layout/reftests/invalidation/clipped-animated-transform-1.html62
-rw-r--r--layout/reftests/invalidation/fast-scrolling.html113
-rw-r--r--layout/reftests/invalidation/filter-userspace-offset.svg156
-rw-r--r--layout/reftests/invalidation/image-scrolling-zoom-1-notref.html36
-rw-r--r--layout/reftests/invalidation/image-scrolling-zoom-1-ref.html36
-rw-r--r--layout/reftests/invalidation/image-scrolling-zoom-1.html51
-rw-r--r--layout/reftests/invalidation/image_rgrg-256x256-animated.gifbin0 -> 1748 bytes
-rw-r--r--layout/reftests/invalidation/image_rgrg-256x256.pngbin0 -> 131 bytes
-rw-r--r--layout/reftests/invalidation/inactive-layertree-visible-region-1.html60
-rw-r--r--layout/reftests/invalidation/inactive-layertree-visible-region-2.html62
-rw-r--r--layout/reftests/invalidation/layer-splitting-1.html63
-rw-r--r--layout/reftests/invalidation/layer-splitting-2.html67
-rw-r--r--layout/reftests/invalidation/layer-splitting-3.html95
-rw-r--r--layout/reftests/invalidation/layer-splitting-4.html82
-rw-r--r--layout/reftests/invalidation/layer-splitting-5.html109
-rw-r--r--layout/reftests/invalidation/layer-splitting-6.html117
-rw-r--r--layout/reftests/invalidation/layer-splitting-7.html72
-rw-r--r--layout/reftests/invalidation/masklayer-1.html55
-rw-r--r--layout/reftests/invalidation/masklayer-2.html62
-rw-r--r--layout/reftests/invalidation/negative-w-component-ref.html73
-rw-r--r--layout/reftests/invalidation/negative-w-component.html86
-rw-r--r--layout/reftests/invalidation/nudge-to-integer-invalidation.html32
-rw-r--r--layout/reftests/invalidation/one-pixel-wide-background.pngbin0 -> 1059 bytes
-rw-r--r--layout/reftests/invalidation/paintedlayer-recycling-1.html75
-rw-r--r--layout/reftests/invalidation/paintedlayer-recycling-2.html67
-rw-r--r--layout/reftests/invalidation/paintedlayer-recycling-3.html71
-rw-r--r--layout/reftests/invalidation/paintedlayer-recycling-4.html70
-rw-r--r--layout/reftests/invalidation/paintedlayer-recycling-5.html77
-rw-r--r--layout/reftests/invalidation/paintedlayer-recycling-6.html78
-rw-r--r--layout/reftests/invalidation/paintedlayer-recycling-7.html82
-rw-r--r--layout/reftests/invalidation/reftest-stylo.list85
-rw-r--r--layout/reftests/invalidation/reftest.list80
-rw-r--r--layout/reftests/invalidation/scroll-inactive-layers-2.html86
-rw-r--r--layout/reftests/invalidation/scroll-inactive-layers.html81
-rw-r--r--layout/reftests/invalidation/table-repaint-a-ref.html13
-rw-r--r--layout/reftests/invalidation/table-repaint-a.html22
-rw-r--r--layout/reftests/invalidation/table-repaint-b-ref.html17
-rw-r--r--layout/reftests/invalidation/table-repaint-b.html29
-rw-r--r--layout/reftests/invalidation/table-repaint-c-ref.html19
-rw-r--r--layout/reftests/invalidation/table-repaint-c.html30
-rw-r--r--layout/reftests/invalidation/table-repaint-d-ref.html14
-rw-r--r--layout/reftests/invalidation/table-repaint-d.html23
-rw-r--r--layout/reftests/invalidation/test-animated-image-layers-background.html16
-rw-r--r--layout/reftests/invalidation/test-animated-image-layers-ref.html8
-rw-r--r--layout/reftests/invalidation/test-animated-image-layers.html16
-rw-r--r--layout/reftests/invalidation/test-image-layers-multiple-displayitem.html21
-rw-r--r--layout/reftests/invalidation/test-image-layers-ref.html8
-rw-r--r--layout/reftests/invalidation/test-image-layers.html16
-rw-r--r--layout/reftests/invalidation/transform-floating-point-invalidation.html32
-rw-r--r--layout/reftests/invalidation/zero-opacity-animation.html15
-rw-r--r--layout/reftests/invalidation/zero-opacity-text.html15
68 files changed, 3160 insertions, 0 deletions
diff --git a/layout/reftests/invalidation/1243409-1-ref.html b/layout/reftests/invalidation/1243409-1-ref.html
new file mode 100644
index 000000000..63b9c5b21
--- /dev/null
+++ b/layout/reftests/invalidation/1243409-1-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<title>Testcase for bug 1243409</title>
+<html>
+<body>
+<svg>
+ <g transform="matrix(1, 0, 0, 1, 20, 10)">
+ <rect fill-opacity="1" height="10" width="20" fill="#000"></rect>
+ </g>
+</svg>
+</body>
+</html>
diff --git a/layout/reftests/invalidation/1243409-1.html b/layout/reftests/invalidation/1243409-1.html
new file mode 100644
index 000000000..cef841f50
--- /dev/null
+++ b/layout/reftests/invalidation/1243409-1.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<title>Testcase for bug 1243409</title>
+<html class="reftest-wait">
+<body>
+<svg>
+ <g transform="matrix(1, 0, 0, 1, 0, 30)">
+ <rect fill-opacity="1" height="10" width="20" fill="#000"></rect>
+ </g>
+</svg>
+<script>
+var m = document.querySelector('svg > g').transform.baseVal[0].matrix;
+var times = 2;
+
+function doTest() {
+ if(!times--) {
+ document.documentElement.removeAttribute("class");
+ return;
+ }
+
+ m.e += 10;
+ m.f -= 10;
+ window.requestAnimationFrame(doTest);
+}
+
+document.addEventListener("MozReftestInvalidate", doTest);
+</script>
+</body>
+</html>
diff --git a/layout/reftests/invalidation/540247-1-ref.xul b/layout/reftests/invalidation/540247-1-ref.xul
new file mode 100644
index 000000000..4c4e18a7f
--- /dev/null
+++ b/layout/reftests/invalidation/540247-1-ref.xul
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+
+<window id="Test for bug 540247" title="Testcase" class="reftest-wait"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+<script><![CDATA[
+document.addEventListener("MozReftestInvalidate", runtest, false);
+
+function runtest() {
+ document.getElementById('b').height = '100';
+
+ var sbo = document.getElementById('s').boxObject;
+ sbo.scrollTo(0, 1000);
+
+ document.documentElement.className = "";
+}
+]]>
+</script>
+
+ <scrollbox id="s" height="200" style="overflow: scroll;">
+ <vbox>
+ <vbox height="150" width="200" style="background: red;" id="b"/>
+ <vbox height="150" width="200" style="background: green;"/>
+ <vbox height="150" width="200" style="background: blue;"/>
+ <label value="a"/>
+ </vbox>
+ </scrollbox>
+
+</window>
diff --git a/layout/reftests/invalidation/540247-1.xul b/layout/reftests/invalidation/540247-1.xul
new file mode 100644
index 000000000..8e2fe5d25
--- /dev/null
+++ b/layout/reftests/invalidation/540247-1.xul
@@ -0,0 +1,33 @@
+<?xml version="1.0"?>
+
+<window id="Test for bug 540247" title="Testcase" class="reftest-wait"
+ xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
+
+<script><![CDATA[
+document.addEventListener("MozReftestInvalidate", runtest, false);
+
+function runtest() {
+ // Make sure that the effects of the scroll are painted to the screen before
+ // shrinking the size of the scrolled frame.
+ window.addEventListener("MozAfterPaint", finish, false);
+ var sbo = document.getElementById('s').boxObject;
+ sbo.scrollTo(0, 1000);
+}
+
+function finish() {
+ document.getElementById('b').height = '100';
+ document.documentElement.className = "";
+}
+]]>
+</script>
+
+ <scrollbox id="s" height="200" style="overflow: scroll;">
+ <vbox>
+ <vbox height="150" width="200" style="background: red;" id="b"/>
+ <vbox height="150" width="200" style="background: green;"/>
+ <vbox height="150" width="200" style="background: blue;"/>
+ <label value="a"/>
+ </vbox>
+ </scrollbox>
+
+</window>
diff --git a/layout/reftests/invalidation/543681-1-ref.html b/layout/reftests/invalidation/543681-1-ref.html
new file mode 100644
index 000000000..8dd47d17a
--- /dev/null
+++ b/layout/reftests/invalidation/543681-1-ref.html
@@ -0,0 +1,18 @@
+<html class="reftest-wait">
+<head>
+<script>
+document.addEventListener("MozReftestInvalidate", doTest, false);
+
+function doTest() {
+ window.location.href = "#two";
+ document.documentElement.className = "";
+}
+</script>
+</head>
+<body>
+<div style="height: 200px;">spacer</div>
+<div id="one" style="background: blue; width: 200px; height: 200px; display: none;">div one</div>
+<div id="two" style="background: red; width: 200px; height: 200px;">div two</div>
+<div style="height: 10000px;">spacer</div>
+</body>
+</html>
diff --git a/layout/reftests/invalidation/543681-1.html b/layout/reftests/invalidation/543681-1.html
new file mode 100644
index 000000000..1ba94b1cc
--- /dev/null
+++ b/layout/reftests/invalidation/543681-1.html
@@ -0,0 +1,22 @@
+<html class="reftest-wait">
+<head>
+<script>
+document.addEventListener("MozReftestInvalidate", doTest, false);
+
+function doTest() {
+ var one = document.getElementById("one");
+ var two = document.getElementById("two");
+ one.style.display = "none";
+ two.style.display = "";
+ window.location.href = "#two";
+ document.documentElement.className = "";
+}
+</script>
+</head>
+<body>
+<div style="height: 200px;">spacer</div>
+<div id="one" style="background: blue; width: 200px; height: 200px;">div one</div>
+<div id="two" style="background: red; width: 200px; height: 200px; display: none;">div two</div>
+<div style="height: 10000px;">spacer</div>
+</body>
+</html>
diff --git a/layout/reftests/invalidation/background-position-1-ref.html b/layout/reftests/invalidation/background-position-1-ref.html
new file mode 100644
index 000000000..a5862f039
--- /dev/null
+++ b/layout/reftests/invalidation/background-position-1-ref.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta charset="utf-8">
+<title>Changes to background-position should not cause things to repaint that don't intersect the background image.</title>
+
+<style>
+
+body {
+ margin: 0;
+}
+
+#background {
+ height: 512px;
+ background-image: url(image_rgrg-256x256.png);
+ background-repeat: no-repeat;
+ background-position: 300px 100px;
+}
+
+#not-intersecting-background {
+ box-sizing: border-box;
+ width: 200px;
+ height: 200px;
+ margin: 50px;
+ border: 1px solid lime;
+}
+
+</style>
+
+<div id="background">
+ <div id="not-intersecting-background"></div>
+</div>
diff --git a/layout/reftests/invalidation/background-position-1.html b/layout/reftests/invalidation/background-position-1.html
new file mode 100644
index 000000000..c5d296b00
--- /dev/null
+++ b/layout/reftests/invalidation/background-position-1.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<html lang="en" class="reftest-wait">
+<meta charset="utf-8">
+<title>Changes to background-position should not cause things to repaint that don't intersect the background image.</title>
+
+<style>
+
+body {
+ margin: 0;
+}
+
+#background {
+ height: 512px;
+ background-image: url(image_rgrg-256x256.png);
+ background-repeat: no-repeat;
+ background-position: 300px 50px;
+}
+
+#not-intersecting-background {
+ box-sizing: border-box;
+ width: 200px;
+ height: 200px;
+ margin: 50px;
+ border: 1px solid lime;
+}
+
+</style>
+
+<div id="background">
+ <div id="not-intersecting-background" class="reftest-no-paint"></div>
+</div>
+
+<script>
+
+function doTest() {
+ document.querySelector("#background").style.backgroundPosition = "300px 100px";
+ document.documentElement.removeAttribute("class");
+}
+document.addEventListener("MozReftestInvalidate", doTest);
+
+</script>
diff --git a/layout/reftests/invalidation/background-position-2-ref.html b/layout/reftests/invalidation/background-position-2-ref.html
new file mode 100644
index 000000000..f5b790a92
--- /dev/null
+++ b/layout/reftests/invalidation/background-position-2-ref.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta charset="utf-8">
+<title>Reference for properly handled background-position changes.</title>
+
+<style>
+
+body {
+ margin: 0;
+}
+
+#background {
+ width: 100px;
+ height: 100px;
+ background-color: lime;
+}
+
+</style>
+
+<div id="background"></div>
diff --git a/layout/reftests/invalidation/background-position-2a.html b/layout/reftests/invalidation/background-position-2a.html
new file mode 100644
index 000000000..ddf798f5f
--- /dev/null
+++ b/layout/reftests/invalidation/background-position-2a.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en" class="reftest-wait">
+<meta charset="utf-8">
+<title>Changes to background-position should invalidate properly.</title>
+
+<style>
+
+body {
+ margin: 0;
+}
+
+#background {
+ width: 100px;
+ height: 100px;
+ background-image: url(image_rgrg-256x256.png);
+ background-repeat: no-repeat;
+ background-position: 0 0;
+}
+
+</style>
+
+<div id="background"></div>
+
+<script>
+
+function doTest() {
+ document.querySelector("#background").style.backgroundPosition = "-140px 0";
+ document.documentElement.removeAttribute("class");
+}
+document.addEventListener("MozReftestInvalidate", doTest);
+
+</script>
diff --git a/layout/reftests/invalidation/background-position-2b.html b/layout/reftests/invalidation/background-position-2b.html
new file mode 100644
index 000000000..332595055
--- /dev/null
+++ b/layout/reftests/invalidation/background-position-2b.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html lang="en" class="reftest-wait">
+<meta charset="utf-8">
+<title>Changes to background-position should invalidate properly for input type=text.</title>
+
+<style>
+
+body {
+ margin: 0;
+}
+
+#background {
+ width: 100px;
+ height: 100px;
+ background-image: url(image_rgrg-256x256.png);
+ background-repeat: no-repeat;
+ background-position: 0 0;
+
+ border: 0;
+ border-radius: 0;
+ padding: 0;
+}
+
+</style>
+
+<input type="text" id="background">
+
+<script>
+
+function doTest() {
+ document.querySelector("#background").style.backgroundPosition = "-140px 0";
+ document.documentElement.removeAttribute("class");
+}
+document.addEventListener("MozReftestInvalidate", doTest);
+
+</script>
diff --git a/layout/reftests/invalidation/background-position-2c.html b/layout/reftests/invalidation/background-position-2c.html
new file mode 100644
index 000000000..69e6ac588
--- /dev/null
+++ b/layout/reftests/invalidation/background-position-2c.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html lang="en" class="reftest-wait">
+<meta charset="utf-8">
+<title>Changes to background-position should invalidate properly for input type=button.</title>
+
+<style>
+
+body {
+ margin: 0;
+}
+
+#background {
+ width: 100px;
+ height: 100px;
+ background-image: url(image_rgrg-256x256.png);
+ background-repeat: no-repeat;
+ background-position: 0 0;
+
+ border: 0;
+ border-radius: 0;
+ padding: 0;
+}
+
+</style>
+
+<input type="button" id="background">
+
+<script>
+
+function doTest() {
+ document.querySelector("#background").style.backgroundPosition = "-140px 0";
+ document.documentElement.removeAttribute("class");
+}
+document.addEventListener("MozReftestInvalidate", doTest);
+
+</script>
diff --git a/layout/reftests/invalidation/background-position-2d.html b/layout/reftests/invalidation/background-position-2d.html
new file mode 100644
index 000000000..52d27c0f0
--- /dev/null
+++ b/layout/reftests/invalidation/background-position-2d.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html lang="en" class="reftest-wait">
+<meta charset="utf-8">
+<title>Changes to background-position should invalidate properly for table rows.</title>
+
+<style>
+
+body {
+ margin: 0;
+}
+
+#background {
+ width: 100px;
+ height: 100px;
+ background-image: url(image_rgrg-256x256.png);
+ background-repeat: no-repeat;
+ background-position: 0 0;
+
+ border: 0;
+ padding: 0;
+}
+
+table, tr, td {
+ width: 100px;
+ height: 100px;
+ border: 0;
+ padding: 0;
+ border-spacing: 0;
+}
+
+</style>
+
+<table><tr id="background"><td></td></table>
+
+<script>
+
+function doTest() {
+ document.querySelector("#background").style.backgroundPosition = "-140px 0";
+ document.documentElement.removeAttribute("class");
+}
+document.addEventListener("MozReftestInvalidate", doTest);
+
+</script>
diff --git a/layout/reftests/invalidation/background-position-2e.html b/layout/reftests/invalidation/background-position-2e.html
new file mode 100644
index 000000000..c9150da7a
--- /dev/null
+++ b/layout/reftests/invalidation/background-position-2e.html
@@ -0,0 +1,43 @@
+<!DOCTYPE html>
+<html lang="en" class="reftest-wait">
+<meta charset="utf-8">
+<title>Changes to background-position should invalidate properly for table cells.</title>
+
+<style>
+
+body {
+ margin: 0;
+}
+
+#background {
+ width: 100px;
+ height: 100px;
+ background-image: url(image_rgrg-256x256.png);
+ background-repeat: no-repeat;
+ background-position: 0 0;
+
+ border: 0;
+ padding: 0;
+}
+
+table, tr, td {
+ width: 100px;
+ height: 100px;
+ border: 0;
+ padding: 0;
+ border-spacing: 0;
+}
+
+</style>
+
+<table><tr><td id="background"></td></table>
+
+<script>
+
+function doTest() {
+ document.querySelector("#background").style.backgroundPosition = "-140px 0";
+ document.documentElement.removeAttribute("class");
+}
+document.addEventListener("MozReftestInvalidate", doTest);
+
+</script>
diff --git a/layout/reftests/invalidation/background-position-2f.html b/layout/reftests/invalidation/background-position-2f.html
new file mode 100644
index 000000000..eb3797038
--- /dev/null
+++ b/layout/reftests/invalidation/background-position-2f.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html lang="en" class="reftest-wait">
+<meta charset="utf-8">
+<title>Changes to background-position should invalidate properly for fieldsets.</title>
+
+<style>
+
+body {
+ margin: 0;
+}
+
+#background {
+ width: 100px;
+ height: 100px;
+ background-image: url(image_rgrg-256x256.png);
+ background-repeat: no-repeat;
+ background-position: 0 0;
+
+ border: 0;
+ padding: 0;
+ margin: 0;
+}
+
+</style>
+
+<fieldset id="background"><legend></legend></fieldset>
+
+<script>
+
+function doTest() {
+ document.querySelector("#background").style.backgroundPosition = "-140px 0";
+ document.documentElement.removeAttribute("class");
+}
+document.addEventListener("MozReftestInvalidate", doTest);
+
+</script>
diff --git a/layout/reftests/invalidation/box-shadow-border-radius-ref.html b/layout/reftests/invalidation/box-shadow-border-radius-ref.html
new file mode 100644
index 000000000..fe4516d7c
--- /dev/null
+++ b/layout/reftests/invalidation/box-shadow-border-radius-ref.html
@@ -0,0 +1,19 @@
+<html>
+<head>
+<style>
+div#blurred {
+ box-shadow: 0 0 50px 0 #000;
+ position: absolute;
+ width: 100px;
+ height: 100px;
+ top: 30px;
+ left: 60px;
+
+ border-radius: 40px;
+}
+</style>
+</head>
+<body>
+<div id="blurred"></div>
+</body>
+</html>
diff --git a/layout/reftests/invalidation/box-shadow-border-radius.html b/layout/reftests/invalidation/box-shadow-border-radius.html
new file mode 100644
index 000000000..1a89991ac
--- /dev/null
+++ b/layout/reftests/invalidation/box-shadow-border-radius.html
@@ -0,0 +1,27 @@
+<html class="reftest-wait">
+<head>
+<style>
+div#blurred {
+ box-shadow: 0 0 50px 0 #000;
+ position: absolute;
+ width: 100px;
+ height: 100px;
+ top: 30px;
+ left: 30px;
+
+ border-radius: 40px;
+}
+</style>
+</head>
+<body>
+<div id="blurred"></div>
+<script>
+function doTest() {
+ var div = document.getElementById("blurred");
+ div.style.left = '60px';
+ document.documentElement.removeAttribute("class");
+}
+document.addEventListener("MozReftestInvalidate", doTest, false);
+</script>
+</body>
+</html>
diff --git a/layout/reftests/invalidation/clipped-animated-transform-1.html b/layout/reftests/invalidation/clipped-animated-transform-1.html
new file mode 100644
index 000000000..a2faea289
--- /dev/null
+++ b/layout/reftests/invalidation/clipped-animated-transform-1.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html lang="en" class="reftest-wait">
+<meta charset="utf-8">
+<title>The green box shouldn't be invalidated when the blue box starts to move.</title>
+
+<style>
+
+body {
+ margin: 0;
+}
+
+#clip {
+ border: 1px solid black;
+ margin: 50px;
+ overflow: hidden;
+ height: 200px;
+ width: 400px;
+ position: relative;
+}
+
+#animatedTransform {
+ border: 1px solid blue;
+ width: 100px;
+ height: 100px;
+ position: absolute;
+ z-index: 1;
+ top: 50px;
+ left: 50px;
+ transition: transform ease-in-out .4s;
+}
+
+#clip:hover > #animatedTransform,
+#animatedTransform.animate {
+ transform: translateX(200px);
+}
+
+#aboveTransform {
+ position: relative;
+ margin: 50px 100px;
+ border: 1px solid lime;
+ width: 80px;
+ height: 80px;
+ z-index: 2;
+}
+
+</style>
+
+<div id="clip">
+ <div id="animatedTransform"></div>
+</div>
+
+<div id="aboveTransform" class="reftest-no-paint"></div>
+
+<script>
+
+function doTest() {
+ document.getElementById("animatedTransform").className = "animate";
+ document.documentElement.removeAttribute("class");
+}
+document.addEventListener("MozReftestInvalidate", doTest, false);
+
+</script>
diff --git a/layout/reftests/invalidation/fast-scrolling.html b/layout/reftests/invalidation/fast-scrolling.html
new file mode 100644
index 000000000..c78456fad
--- /dev/null
+++ b/layout/reftests/invalidation/fast-scrolling.html
@@ -0,0 +1,113 @@
+<!DOCTYPE html>
+<html lang="en" class="reftest-wait" reftest-async-scroll>
+<meta charset="utf-8">
+<title>Bug 1164227 - Testcase for the invalid region simplification bug</title>
+
+<style>
+
+#scrollbox {
+ width: 400px;
+ height: 500px;
+ overflow: auto;
+ margin: 80px;
+ border: 1px solid black;
+}
+
+.contents {
+ height: 600px;
+ background: white;
+ padding: 20px;
+ position: relative;
+}
+
+.boxes > div {
+ box-sizing: border-box;
+ width: 10px;
+ height: 10px;
+ border: 1px solid black;
+ float: left;
+ margin-left: -2px;
+}
+
+.boxes > div:nth-child(odd) {
+ transform: translateY(500px);
+}
+
+.reftest-no-paint {
+ position: absolute;
+ top: 250px;
+ left: 30px;
+ width: 200px;
+ height: 50px;
+ border: 1px solid red;
+}
+</style>
+
+<div id="scrollbox"
+ reftest-displayport-x="0"
+ reftest-displayport-y="0"
+ reftest-displayport-w="400"
+ reftest-displayport-h="500">
+
+ <div class="contents">
+
+ <div class="boxes">
+ <div style="margin-top: 0px"></div>
+ <div style="margin-top: 1px"></div>
+ <div style="margin-top: 2px"></div>
+ <div style="margin-top: 3px"></div>
+ <div style="margin-top: 4px"></div>
+ <div style="margin-top: 5px"></div>
+ <div style="margin-top: 6px"></div>
+ <div style="margin-top: 7px"></div>
+ <div style="margin-top: 8px"></div>
+ <div style="margin-top: 9px"></div>
+ <div style="margin-top: 10px"></div>
+ <div style="margin-top: 11px"></div>
+ <div style="margin-top: 12px"></div>
+ <div style="margin-top: 13px"></div>
+ <div style="margin-top: 14px"></div>
+ <div style="margin-top: 15px"></div>
+ <div style="margin-top: 16px"></div>
+ <div style="margin-top: 17px"></div>
+ <div style="margin-top: 18px"></div>
+ <div style="margin-top: 19px"></div>
+ <div style="margin-top: 20px"></div>
+ <div style="margin-top: 21px"></div>
+ <div style="margin-top: 22px"></div>
+ <div style="margin-top: 23px"></div>
+ <div style="margin-top: 24px"></div>
+ <div style="margin-top: 25px"></div>
+ <div style="margin-top: 26px"></div>
+ <div style="margin-top: 27px"></div>
+ <div style="margin-top: 28px"></div>
+ <div style="margin-top: 29px"></div>
+ <div style="margin-top: 30px"></div>
+ <div style="margin-top: 31px"></div>
+ <div style="margin-top: 32px"></div>
+ <div style="margin-top: 33px"></div>
+ <div style="margin-top: 34px"></div>
+ <div style="margin-top: 35px"></div>
+ <div style="margin-top: 36px"></div>
+ <div style="margin-top: 37px"></div>
+ <div style="margin-top: 38px"></div>
+ <div style="margin-top: 39px"></div>
+ </div>
+
+ <div class="reftest-no-paint"></div>
+
+ </div>
+
+</div>
+
+<script>
+
+var scrollbox = document.querySelector("#scrollbox");
+scrollbox.scrollTop = 100;
+
+window.addEventListener("MozReftestInvalidate", function (e) {
+ scrollbox.scrollTop = 0;
+ document.documentElement.removeAttribute("class");
+});
+
+</script>
diff --git a/layout/reftests/invalidation/filter-userspace-offset.svg b/layout/reftests/invalidation/filter-userspace-offset.svg
new file mode 100644
index 000000000..2f0581b4d
--- /dev/null
+++ b/layout/reftests/invalidation/filter-userspace-offset.svg
@@ -0,0 +1,156 @@
+<svg
+ width="500px" height="500px" viewBox="0 0 500 500"
+ xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+ >
+ <title>Filters and offsets, user space origins, invalidation</title>
+ <defs>
+ <filter id="flood-boundingBox"
+ filterUnits="objectBoundingBox"
+ x="0%" y="0%" width="100%" height="100%"
+ color-interpolation-filters="sRGB">
+ <feFlood flood-color="lime"/>
+ </filter>
+ <filter id="matrix-boundingBox"
+ filterUnits="objectBoundingBox"
+ x="0%" y="0%" width="100%" height="100%"
+ color-interpolation-filters="sRGB">
+ <feColorMatrix type="matrix" values="0 1 0 0 0
+ 1 0 0 0 0
+ 0 0 1 0 0
+ 0 0 0 1 0"/>
+ </filter>
+ <filter id="matrix-fillPaint-boundingBox"
+ filterUnits="objectBoundingBox"
+ x="0%" y="0%" width="100%" height="100%"
+ color-interpolation-filters="sRGB">
+ <feColorMatrix type="matrix" values="0 1 0 0 0
+ 1 0 0 0 0
+ 0 0 1 0 0
+ 0 0 0 1 0" in="FillPaint"/>
+ </filter>
+ <filter id="flood-userSpace-atZero"
+ filterUnits="userSpaceOnUse"
+ x="0" y="0" width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <feFlood flood-color="lime"/>
+ </filter>
+ <filter id="matrix-userSpace-atZero"
+ filterUnits="userSpaceOnUse"
+ x="0" y="0" width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <feColorMatrix type="matrix" values="0 1 0 0 0
+ 1 0 0 0 0
+ 0 0 1 0 0
+ 0 0 0 1 0"/>
+ </filter>
+ <filter id="flood-userSpace-at100"
+ filterUnits="userSpaceOnUse"
+ x="100" y="100" width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <feFlood flood-color="lime"/>
+ </filter>
+ <filter id="matrix-userSpace-at100"
+ filterUnits="userSpaceOnUse"
+ x="100" y="100" width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <feColorMatrix type="matrix" values="0 1 0 0 0
+ 1 0 0 0 0
+ 0 0 1 0 0
+ 0 0 0 1 0"/>
+ </filter>
+ <filter id="matrix-fillPaint-userSpace-at100"
+ filterUnits="userSpaceOnUse"
+ x="100" y="100" width="100" height="100"
+ color-interpolation-filters="sRGB">
+ <feColorMatrix type="matrix" values="0 1 0 0 0
+ 1 0 0 0 0
+ 0 0 1 0 0
+ 0 0 0 1 0" in="FillPaint"/>
+ </filter>
+ <mask id="boundingBox" maskContentUnits="objectBoundingBox">
+ <rect x="0" y="0" width="1" height="1" fill="white"/>
+ </mask>
+ <mask id="userSpace-atZero" maskContentUnits="userSpaceOnUse">
+ <rect x="0" y="0" width="100" height="100" fill="white"/>
+ </mask>
+ <mask id="userSpace-at100" maskContentUnits="userSpaceOnUse">
+ <rect x="100" y="100" width="100" height="100" fill="white"/>
+ </mask>
+ <g id="usedRect">
+ <rect class="fillColor" width="100" height="100"/>
+ </g>
+ </defs>
+ <g transform="translate(40,40)">
+ <rect stroke-width="1" stroke="black" fill="none" x="99.5" y="99.5" width="101" height="101"/>
+
+ <rect x="0" y="100" width="100" height="100" class="fillColor offsetContainer" id="rect"/>
+ <use xlink:href="#usedRect" x="0" y="100" class="offsetContainer" id="use"/>
+ <svg x="0" y="100" width="100" height="100" class="offsetContainer" id="innerSVG">
+ <rect class="fillColor" width="100" height="100"/>
+ </svg>
+ <foreignObject x="0" y="100" width="100" height="100" class="offsetContainer" id="foreignObject">
+ <svg width="100" height="100">
+ <rect class="fillColor" width="100" height="100"/>
+ </svg>
+ </foreignObject>
+ </g>
+ <script><![CDATA[
+
+var options = {
+ offsetContainer: "rect",
+ filter: null,
+ mask: null,
+ updateOffsetOn: "reftestInvalidate" // | "initial" | "timeout"
+};
+
+location.search.substr(1).split("&").forEach(function (s) {
+ var pv = s.split("=");
+ options[pv[0]] = pv[1] || true;
+});
+
+var offsetContainer = document.getElementById(options.offsetContainer);
+
+function updateOffsetNow() {
+ offsetContainer.setAttribute("x", "100");
+}
+
+function updateOffsetOnReftestInvalidate() {
+ document.documentElement.setAttribute("class", "reftest-wait");
+ document.addEventListener("MozReftestInvalidate", function () {
+ updateOffsetNow();
+ document.documentElement.removeAttribute("class");
+ }, false);
+}
+
+function updateOffsetOnTimeout() {
+ setTimeout(updateOffsetNow, 500);
+}
+
+options.updateOffset = options.updateOffsetOn == "initial" ? updateOffsetNow :
+ (options.updateOffsetOn == "timeout" ? updateOffsetOnTimeout :
+ updateOffsetOnReftestInvalidate);
+
+var offsetContainers = Array.prototype.slice.call(document.getElementsByClassName("offsetContainer"), 0);
+for (var i = 0; i < offsetContainers.length; i++) {
+ if (offsetContainers[i] != offsetContainer) {
+ offsetContainers[i].parentNode.removeChild(offsetContainers[i]);
+ }
+}
+
+var fillColor = options.filter ? "red" : "lime";
+if (options.filter) {
+ offsetContainer.setAttribute("filter", "url(#" + options.filter + ")");
+}
+if (options.mask) {
+ offsetContainer.setAttribute("mask", "url(#" + options.mask + ")");
+}
+
+var fillColors = document.getElementsByClassName("fillColor");
+for (var j = 0; j < fillColors.length; j++) {
+ fillColors[j].setAttribute("fill", fillColor);
+}
+
+options.updateOffset();
+
+]]></script>
+</svg>
diff --git a/layout/reftests/invalidation/image-scrolling-zoom-1-notref.html b/layout/reftests/invalidation/image-scrolling-zoom-1-notref.html
new file mode 100644
index 000000000..524109ff9
--- /dev/null
+++ b/layout/reftests/invalidation/image-scrolling-zoom-1-notref.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<!-- Any copyright is dedicated to the Public Domain.
+ - http://creativecommons.org/publicdomain/zero/1.0/ -->
+<html reftest-zoom="0.3">
+<head>
+ <style type="text/css">
+ #container {
+ height: 100px;
+ overflow: auto;
+ }
+ #container-background {
+ background-color: white;
+ }
+ #container-background > div {
+ line-height: 20px;
+ }
+ </style>
+</head>
+<body>
+ <div id="container">
+ <div id="container-background">
+ <div>Item</div>
+ <div>Item</div>
+ <div>Item</div>
+ <div>Item</div>
+ <div>Item</div>
+ <div>Item</div>
+ <div>Item</div>
+ <div>Item</div>
+ <div>Item</div>
+ <div>Item</div>
+ <div>Item</div>
+ </div>
+ </div>
+</body>
+</html>
diff --git a/layout/reftests/invalidation/image-scrolling-zoom-1-ref.html b/layout/reftests/invalidation/image-scrolling-zoom-1-ref.html
new file mode 100644
index 000000000..e989d0e86
--- /dev/null
+++ b/layout/reftests/invalidation/image-scrolling-zoom-1-ref.html
@@ -0,0 +1,36 @@
+<!DOCTYPE HTML>
+<!-- Any copyright is dedicated to the Public Domain.
+ - http://creativecommons.org/publicdomain/zero/1.0/ -->
+<html reftest-zoom="0.3">
+<head>
+ <style type="text/css">
+ #container {
+ height: 100px;
+ overflow: auto;
+ }
+ #container-background {
+ background: url(one-pixel-wide-background.png);
+ }
+ #container-background > div {
+ line-height: 20px;
+ }
+ </style>
+</head>
+<body>
+ <div id="container">
+ <div id="container-background">
+ <div>Item</div>
+ <div>Item</div>
+ <div>Item</div>
+ <div>Item</div>
+ <div>Item</div>
+ <div>Item</div>
+ <div>Item</div>
+ <div>Item</div>
+ <div>Item</div>
+ <div>Item</div>
+ <div>Item</div>
+ </div>
+ </div>
+</body>
+</html>
diff --git a/layout/reftests/invalidation/image-scrolling-zoom-1.html b/layout/reftests/invalidation/image-scrolling-zoom-1.html
new file mode 100644
index 000000000..85a2753b0
--- /dev/null
+++ b/layout/reftests/invalidation/image-scrolling-zoom-1.html
@@ -0,0 +1,51 @@
+<!DOCTYPE HTML>
+<!-- Any copyright is dedicated to the Public Domain.
+ - http://creativecommons.org/publicdomain/zero/1.0/ -->
+<html class="reftest-wait" reftest-zoom="0.3">
+<head>
+ <style type="text/css">
+ #container {
+ height: 100px;
+ overflow: auto;
+ }
+ #container-background {
+ background: url(one-pixel-wide-background.png);
+ }
+ #container-background > div {
+ line-height: 20px;
+ }
+ </style>
+</head>
+<body>
+ <div id="container">
+ <div id="container-background">
+ <div>Item</div>
+ <div>Item</div>
+ <div>Item</div>
+ <div>Item</div>
+ <div>Item</div>
+ <div>Item</div>
+ <div>Item</div>
+ <div>Item</div>
+ <div>Item</div>
+ <div>Item</div>
+ <div>Item</div>
+ </div>
+ </div>
+</body>
+<script>
+ var container = document.getElementById('container');
+
+ // Start scrolled all the way to the bottom.
+ container.scrollTop = container.scrollHeight;
+
+ // When we get MozReftestInvalidate, scroll to the top. This puts us at the
+ // same scroll position as the reference.
+ function doTest() {
+ container.scrollTop = 0;
+ document.documentElement.removeAttribute('class');
+ }
+
+ document.addEventListener("MozReftestInvalidate", doTest, false);
+</script>
+</html>
diff --git a/layout/reftests/invalidation/image_rgrg-256x256-animated.gif b/layout/reftests/invalidation/image_rgrg-256x256-animated.gif
new file mode 100644
index 000000000..c03fad8bb
--- /dev/null
+++ b/layout/reftests/invalidation/image_rgrg-256x256-animated.gif
Binary files differ
diff --git a/layout/reftests/invalidation/image_rgrg-256x256.png b/layout/reftests/invalidation/image_rgrg-256x256.png
new file mode 100644
index 000000000..e6fba3daa
--- /dev/null
+++ b/layout/reftests/invalidation/image_rgrg-256x256.png
Binary files differ
diff --git a/layout/reftests/invalidation/inactive-layertree-visible-region-1.html b/layout/reftests/invalidation/inactive-layertree-visible-region-1.html
new file mode 100644
index 000000000..6146187cf
--- /dev/null
+++ b/layout/reftests/invalidation/inactive-layertree-visible-region-1.html
@@ -0,0 +1,60 @@
+<!DOCTYPE html>
+<html lang="en" class="reftest-wait"
+ reftest-displayport-x="0"
+ reftest-displayport-y="0"
+ reftest-displayport-w="800"
+ reftest-displayport-h="1000">
+<meta charset="utf-8">
+<title>Scrolling the horizontal bar away shouldn't invalidate the green rectangle</title>
+
+<style>
+
+.wrapper {
+ transform: translateY(1px);
+}
+
+.content {
+ box-sizing: border-box;
+ border: 1px solid rgba(0, 0, 0, 0.2);
+}
+
+.first {
+ height: 20px;
+}
+
+.second {
+ margin-left: auto;
+ width: 20px;
+ height: 200px;
+}
+
+.reftest-no-paint {
+ margin: -150px 100px 0;
+ height: 100px;
+ border-color: lime;
+}
+
+body {
+ margin: 0;
+ padding: 50px;
+ height: 3000px;
+}
+
+</style>
+
+<div class="wrapper">
+ <div class="first content"></div>
+ <div class="second content"></div>
+</div>
+
+<div class="reftest-no-paint content"></div>
+
+<script>
+
+function doTest() {
+ document.documentElement.scrollTop = 100;
+ document.documentElement.removeAttribute("class");
+}
+document.addEventListener("MozReftestInvalidate", doTest, false);
+
+</script>
diff --git a/layout/reftests/invalidation/inactive-layertree-visible-region-2.html b/layout/reftests/invalidation/inactive-layertree-visible-region-2.html
new file mode 100644
index 000000000..8d8f4a7c1
--- /dev/null
+++ b/layout/reftests/invalidation/inactive-layertree-visible-region-2.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html lang="en" class="reftest-wait"
+ reftest-displayport-x="0"
+ reftest-displayport-y="0"
+ reftest-displayport-w="800"
+ reftest-displayport-h="1000">
+<meta charset="utf-8">
+<title>Scrolling the horizontal bar away shouldn't invalidate the green rectangle</title>
+
+<style>
+
+.wrapper {
+ transform: translateY(1px);
+}
+
+.content {
+ box-sizing: border-box;
+ border: 1px solid rgba(0, 0, 0, 0.2);
+}
+
+.first {
+ height: 20px;
+}
+
+.second {
+ margin-left: auto;
+ width: 20px;
+ height: 200px;
+}
+
+.reftest-no-paint {
+ margin: -150px 100px 0;
+ height: 100px;
+ border-color: lime;
+}
+
+body {
+ margin: 0;
+ padding: 50px;
+ height: 3000px;
+}
+
+</style>
+
+<div class="wrapper">
+ <div class="wrapper">
+ <div class="first content"></div>
+ <div class="second content"></div>
+ </div>
+</div>
+
+<div class="reftest-no-paint content"></div>
+
+<script>
+
+function doTest() {
+ document.documentElement.scrollTop = 100;
+ document.documentElement.removeAttribute("class");
+}
+document.addEventListener("MozReftestInvalidate", doTest, false);
+
+</script>
diff --git a/layout/reftests/invalidation/layer-splitting-1.html b/layout/reftests/invalidation/layer-splitting-1.html
new file mode 100644
index 000000000..a2b0c5e16
--- /dev/null
+++ b/layout/reftests/invalidation/layer-splitting-1.html
@@ -0,0 +1,63 @@
+<!DOCTYPE html>
+<html lang="en" class="reftest-wait">
+<meta charset="utf-8">
+<title>Moving the transform under the absolutely-positioned layer should cause that to invalidate</title>
+
+<style>
+
+.content {
+ box-sizing: border-box;
+ width: 200px;
+ height: 200px;
+ border: 1px solid black;
+}
+
+.absolute {
+ position: absolute;
+ z-index: 2;
+ top: 20px;
+ left: 240px;
+}
+
+.reftest-no-paint {
+ border-color: lime;
+}
+
+.transform {
+ will-change: transform;
+}
+
+body {
+ margin: 0;
+ padding: 20px;
+ height: 3000px;
+}
+
+</style>
+
+<div class="transform content" id="aboutToMoveUnderAbsolute">
+ <!--
+ This transform is active + prerendered, and will move under the
+ absolutely-positioned item.
+ -->
+</div>
+
+<div class="absolute reftest-no-paint content">
+ <!--
+ This absolutely-positioned element should get its own PaintedLayer above the
+ transform.
+
+ It shouldn't attempt to pull up an opaque background color from the page,
+ because the transform can move under it.
+ -->
+</div>
+
+<script>
+
+function doTest() {
+ document.querySelector("#aboutToMoveUnderAbsolute").style.transform = "translateX(100px)";
+ document.documentElement.removeAttribute("class");
+}
+document.addEventListener("MozReftestInvalidate", doTest, false);
+
+</script>
diff --git a/layout/reftests/invalidation/layer-splitting-2.html b/layout/reftests/invalidation/layer-splitting-2.html
new file mode 100644
index 000000000..d0b92bdac
--- /dev/null
+++ b/layout/reftests/invalidation/layer-splitting-2.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html lang="en" class="reftest-wait"
+ reftest-displayport-x="0"
+ reftest-displayport-y="0"
+ reftest-displayport-w="800"
+ reftest-displayport-h="1000">
+<meta charset="utf-8">
+<title>Scrolling shouldn't invalidate the fixed layer</title>
+
+<style>
+
+.content {
+ box-sizing: border-box;
+ width: 200px;
+ height: 200px;
+ border: 1px solid black;
+}
+
+.fixed {
+ position: fixed;
+ top: 20px;
+ left: 20px;
+}
+
+.reftest-no-paint {
+ border-color: lime;
+}
+
+.distanceFromTop {
+ margin-top: 240px;
+}
+
+body {
+ margin: 0;
+ padding: 20px;
+ height: 3000px;
+}
+
+
+</style>
+
+<div class="distanceFromTop content">
+ <!--
+ This is just a non-uniform item that will be scrolled so that it's between
+ the page background and the fixed layer.
+ -->
+</div>
+
+<div class="fixed reftest-no-paint content">
+ <!--
+ This fixed layer gets its own PaintedLayer above the page.
+
+ It shouldn't attempt to pull up an opaque background color from the page,
+ because the page can move under it.
+ -->
+</div>
+
+<script>
+
+function doTest() {
+ document.documentElement.scrollTop = 100;
+ document.documentElement.removeAttribute("class");
+}
+document.documentElement.scrollTop = 0;
+document.addEventListener("MozReftestInvalidate", doTest, false);
+
+</script>
diff --git a/layout/reftests/invalidation/layer-splitting-3.html b/layout/reftests/invalidation/layer-splitting-3.html
new file mode 100644
index 000000000..9fe47a9c0
--- /dev/null
+++ b/layout/reftests/invalidation/layer-splitting-3.html
@@ -0,0 +1,95 @@
+<!DOCTYPE html>
+<html lang="en" class="reftest-wait"
+ reftest-displayport-x="0"
+ reftest-displayport-y="0"
+ reftest-displayport-w="800"
+ reftest-displayport-h="1000">
+<meta charset="utf-8">
+<title>Scrolling shouldn't invalidate the fixed items</title>
+
+<style>
+
+.content {
+ box-sizing: border-box;
+ width: 200px;
+ height: 200px;
+ border: 1px solid black;
+}
+
+.fixed {
+ position: fixed;
+ top: 20px;
+ left: 20px;
+}
+
+.reftest-no-paint {
+ border-color: lime;
+}
+
+.distanceFromTop {
+ margin-top: 240px;
+}
+
+.clip {
+ width: 200px;
+ height: 200px;
+ overflow: hidden;
+}
+
+.transform {
+ position: relative;
+ will-change: transform;
+}
+
+body {
+ margin: 0;
+ padding: 20px;
+ height: 3000px;
+}
+
+
+</style>
+
+<div class="fixed reftest-no-paint content">
+ <!--
+ This fixed layer gets its own PaintedLayer above the page.
+ -->
+</div>
+
+<div class="distanceFromTop clip">
+ <!--
+ This clip determines the potential pixels that can be affected by the
+ animated transform, *in relation to the scrolled page*. If the page
+ is scrolled, the clip moves relative to the fixed items, so the fixed
+ items need to anticipate the transform getting between them.
+ -->
+
+ <div class="transform content">
+ <!--
+ This is an animated transform item. It can move freely but will be
+ clipped by the .clip element.
+ -->
+ </div>
+
+</div>
+
+<div class="fixed reftest-no-paint content">
+ <!--
+ This fixed layer is above the animated transform, in z-order. The
+ transform is clipped in such a way that initially, the clip doesn't
+ intersect the fixed items, but once the page is scrolled, it does.
+ So this fixed item must not share a layer with the lower fixed item.
+ -->
+</div>
+
+<script>
+
+function doTest() {
+ document.documentElement.scrollTop = 100;
+ document.documentElement.removeAttribute("class");
+}
+document.documentElement.scrollTop = 0;
+document.addEventListener("MozReftestInvalidate", doTest, false);
+// setTimeout(doTest, 500);
+
+</script>
diff --git a/layout/reftests/invalidation/layer-splitting-4.html b/layout/reftests/invalidation/layer-splitting-4.html
new file mode 100644
index 000000000..53af2eb90
--- /dev/null
+++ b/layout/reftests/invalidation/layer-splitting-4.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta charset="utf-8">
+<title>The two items in the scroll box should share a layer, despite all the other stuff that's going on around them</title>
+
+<style>
+
+.content {
+ box-sizing: border-box;
+ width: 200px;
+ height: 200px;
+ border: 1px solid blue;
+ background: white;
+}
+
+body {
+ margin: 0;
+ padding: 20px;
+ height: 3000px;
+}
+
+.opacity {
+ opacity: 0.9;
+ width: 200px;
+ height: 200px;
+ background-color: yellow;
+ will-change: opacity;
+}
+
+.overlap {
+ margin-top: -100px;
+}
+
+.scrollable {
+ position: absolute;
+ top: 20px;
+ left: 240px;
+ width: 400px;
+ height: 400px;
+ border: 1px solid black;
+ overflow: auto;
+}
+
+.scrollarea {
+ height: 800px;
+ padding: 40px;
+}
+
+.low-z, .mid-z, .high-z {
+ position: relative;
+}
+
+.low-z { z-index: 1; }
+.mid-z { z-index: 2; }
+.high-z { z-index: 3; }
+
+</style>
+
+<div class="content" reftest-assigned-layer="page-background"></div>
+<div class="overlap opacity"></div>
+<div class="overlap mid-z content" reftest-assigned-layer="on-top-of-opacity">
+ <!--
+ This item cannot merge into the page background layer because there's an
+ active container layer for the opacity in between.
+ -->
+</div>
+
+<div class="scrollable">
+ <div class="scrollarea">
+ <div class="low-z content" reftest-assigned-layer="scrolled-content"></div>
+ <div class="high-z overlap content" reftest-assigned-layer="scrolled-content"></div>
+ </div>
+</div>
+<script>
+
+var scrollable = document.querySelector(".scrollable");
+
+// Make .scrollable start out with active scrolling.
+scrollable.scrollTop = 0;
+scrollable.scrollTop = 20;
+
+</script>
diff --git a/layout/reftests/invalidation/layer-splitting-5.html b/layout/reftests/invalidation/layer-splitting-5.html
new file mode 100644
index 000000000..125648fa2
--- /dev/null
+++ b/layout/reftests/invalidation/layer-splitting-5.html
@@ -0,0 +1,109 @@
+<!DOCTYPE html>
+<html lang="en" class="reftest-wait"
+ reftest-displayport-x="0"
+ reftest-displayport-y="0"
+ reftest-displayport-w="800"
+ reftest-displayport-h="1000">
+<meta charset="utf-8">
+<title>Things overlapping active scrollboxes should be in a layer on top of the scrolled contents.</title>
+
+<style>
+
+div {
+ height: 50px;
+ border: 1px solid;
+ box-model: border-box;
+}
+
+.first, .second {
+ border-color: blue;
+ margin: 50px 0;
+}
+
+.overlap {
+ border-color: #088;
+ margin-left: 100px;
+ width: 80px;
+ margin-bottom: -30px;
+ position: relative;
+}
+
+.scrollable {
+ height: auto;
+ overflow: auto;
+}
+
+.scrollarea {
+ width: 5000px;
+ border: none;
+ padding: 10px 0 20px;
+ height: auto;
+}
+
+.scrolled {
+ margin-left: 220px;
+ width: 100px;
+ height: 100px;
+ border-color: red;
+}
+
+body {
+ margin: 0;
+ padding: 0 100px;
+ height: 3000px;
+}
+
+</style>
+
+<div class="first" reftest-assigned-layer="page-background">
+ <!--
+ This is just a regular box, it should end up in the page background layer.
+ -->
+</div>
+
+<div class="overlap reftest-no-paint">
+ <!--
+ This item intersects with the scrollable box and is positioned above
+ .scrolled, in z-order, so it should be split into its own layer as soon
+ as the scrollbox gets active scrolling. The splitting should not wait for
+ .scrolled to move under .overlap.
+ -->
+</div>
+
+<div class="scrollable">
+ <div class="scrollarea">
+ <div class="scrolled reftest-opaque-layer">
+ <!--
+ This will move under .overlap by .scrollable being scrolled. This
+ action should not invalidate .overlap.
+
+ Furthermore, since the background of .scrollable is uniform and opaque,
+ .scrolled should be able to pull up that background color and become
+ opaque itself.
+ -->
+ </div>
+ </div>
+</div>
+
+<div class="second" reftest-assigned-layer="page-background">
+ <!--
+ This should share a layer with .first and the page background.
+ -->
+</div>
+
+<script>
+
+var scrollable = document.querySelector(".scrollable");
+
+function doTest() {
+ scrollable.scrollLeft = 100;
+ document.documentElement.removeAttribute("class");
+}
+
+// Make .scrollable start out with active scrolling.
+scrollable.scrollLeft = 0;
+scrollable.scrollLeft = 20;
+document.addEventListener("MozReftestInvalidate", doTest, false);
+
+</script>
+
diff --git a/layout/reftests/invalidation/layer-splitting-6.html b/layout/reftests/invalidation/layer-splitting-6.html
new file mode 100644
index 000000000..42c235f37
--- /dev/null
+++ b/layout/reftests/invalidation/layer-splitting-6.html
@@ -0,0 +1,117 @@
+<!DOCTYPE html>
+<html lang="en" class="reftest-wait"
+ reftest-displayport-x="0"
+ reftest-displayport-y="0"
+ reftest-displayport-w="800"
+ reftest-displayport-h="1000">
+<meta charset="utf-8">
+<title>Things overlapping active scrollboxes should be in a layer on top of the scrolled contents, and that layer shouldn't pull up a background color through the scrollbox.</title>
+<!--
+ This test is the same as layer-splitting-5.html, but without the scrollbox
+ border. The lack of a border here makes it attractive for .overlap to pull
+ a background color from the page background (because there's no scrollbox
+ border in the way), but it shouldn't do that because .scrolled can move
+ under it.
+-->
+
+<style>
+
+div {
+ height: 50px;
+ border: 1px solid;
+ box-model: border-box;
+}
+
+.first, .second {
+ border-color: blue;
+ margin: 50px 0;
+}
+
+.overlap {
+ border-color: #088;
+ margin-left: 100px;
+ width: 80px;
+ margin-bottom: -30px;
+ position: relative;
+}
+
+.scrollable {
+ height: auto;
+ overflow: auto;
+ border: none;
+}
+
+.scrollarea {
+ width: 5000px;
+ border: none;
+ padding: 10px 0 20px;
+ height: auto;
+}
+
+.scrolled {
+ margin-left: 220px;
+ width: 100px;
+ height: 100px;
+ border-color: red;
+}
+
+body {
+ margin: 0;
+ padding: 0 100px;
+ height: 3000px;
+}
+
+</style>
+
+<div class="first" reftest-assigned-layer="page-background">
+ <!--
+ This is just a regular box, it should end up in the page background layer.
+ -->
+</div>
+
+<div class="overlap reftest-no-paint">
+ <!--
+ This item intersects with the scrollable box and is positioned above
+ .scrolled, in z-order, so it should be split into its own layer as soon
+ as the scrollbox gets active scrolling. The splitting should not wait for
+ .scrolled to move under .overlap.
+ -->
+</div>
+
+<div class="scrollable">
+ <div class="scrollarea">
+ <div class="scrolled reftest-opaque-layer">
+ <!--
+ This will move under .overlap by .scrollable being scrolled. This
+ action should not invalidate .overlap.
+
+ Furthermore, since the background of .scrollable is uniform and opaque,
+ .scrolled should be able to pull up that background color and become
+ opaque itself.
+ -->
+ </div>
+ </div>
+</div>
+
+<div class="second" reftest-assigned-layer="page-background">
+ <!--
+ This should share a layer with .first and the page background.
+ -->
+</div>
+
+<script>
+
+var scrollable = document.querySelector(".scrollable");
+
+function doTest() {
+ scrollable.scrollLeft = 100;
+ document.documentElement.removeAttribute("class");
+}
+
+// Make .scrollable start out with active scrolling.
+scrollable.scrollLeft = 0;
+scrollable.scrollLeft = 20;
+document.addEventListener("MozReftestInvalidate", doTest, false);
+
+</script>
+
diff --git a/layout/reftests/invalidation/layer-splitting-7.html b/layout/reftests/invalidation/layer-splitting-7.html
new file mode 100644
index 000000000..942c76c16
--- /dev/null
+++ b/layout/reftests/invalidation/layer-splitting-7.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<html lang="en" class="reftest-wait"
+ reftest-displayport-x="0"
+ reftest-displayport-y="0"
+ reftest-displayport-w="800"
+ reftest-displayport-h="1000">
+<meta charset="utf-8">
+<title>Scrolling shouldn't invalidate the relatively-positioned layer</title>
+
+<style>
+
+.content {
+ box-sizing: border-box;
+ width: 200px;
+ height: 200px;
+ border: 1px solid black;
+}
+
+.fixed {
+ position: fixed;
+ top: 20px;
+ left: 20px;
+}
+
+.reftest-no-paint {
+ border-color: lime;
+}
+
+.distanceFromTop {
+ margin-top: 240px;
+}
+
+.relative {
+ position: relative;
+}
+
+body {
+ margin: 0;
+ padding: 20px;
+ height: 3000px;
+}
+
+
+</style>
+
+<div class="fixed reftest-no-paint content">
+ <!--
+ This fixed layer gets its own PaintedLayer above the page.
+
+ It shouldn't attempt to pull up an opaque background color from the page,
+ because the page can move under it.
+ -->
+</div>
+
+<div class="distanceFromTop relative reftest-no-paint content">
+ <!--
+ This item is above .fixed in z-order, but it starts out not intersecting
+ .fixed. It should still get its own layer from the start, because it can
+ get scrolled on top of .fixed.
+ -->
+</div>
+
+<script>
+
+function doTest() {
+ document.documentElement.scrollTop = 100;
+ document.documentElement.removeAttribute("class");
+}
+document.documentElement.scrollTop = 0;
+document.addEventListener("MozReftestInvalidate", doTest, false);
+
+</script>
diff --git a/layout/reftests/invalidation/masklayer-1.html b/layout/reftests/invalidation/masklayer-1.html
new file mode 100644
index 000000000..fd8d9cb43
--- /dev/null
+++ b/layout/reftests/invalidation/masklayer-1.html
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta charset="utf-8">
+<title>Moving a layer in a box with a rounded clip shouldn't invalidate.</title>
+
+<style>
+
+#outer {
+ position: absolute;
+ top: 50px;
+ left: 50px;
+ width: 300px;
+ height: 200px;
+ background-color: #DDD;
+ overflow: hidden;
+ border-radius: 10px;
+}
+
+#animatedLeft {
+ position: absolute;
+ top: 50px;
+ left: 40px;
+ box-model: border-box;
+ border: 1px solid lime;
+ width: 100px;
+ height: 100px;
+}
+
+</style>
+
+<body>
+
+<div id="outer">
+ <div id="animatedLeft" class="reftest-no-paint"></div>
+</div>
+
+<script>
+
+var animatedLeft = document.getElementById("animatedLeft");
+
+function doTest() {
+ animatedLeft.style.left = "100px";
+ document.documentElement.removeAttribute("class");
+}
+
+// Layerize #animatedLeft
+animatedLeft.offsetLeft;
+animatedLeft.style.left = "60px";
+animatedLeft.offsetLeft;
+animatedLeft.style.left = "40px";
+animatedLeft.offsetLeft;
+
+document.addEventListener("MozReftestInvalidate", doTest, false);
+
+</script>
diff --git a/layout/reftests/invalidation/masklayer-2.html b/layout/reftests/invalidation/masklayer-2.html
new file mode 100644
index 000000000..46ce1d95e
--- /dev/null
+++ b/layout/reftests/invalidation/masklayer-2.html
@@ -0,0 +1,62 @@
+<!DOCTYPE html>
+<html lang="en" reftest-async-scroll>
+<meta charset="utf-8">
+<title>Moving a layer in a box with a rounded clip shouldn't invalidate.</title>
+
+<style>
+
+#scrollbox {
+ position: absolute;
+ top: 50px;
+ left: 50px;
+ width: 300px;
+ height: 200px;
+ background-color: #DDD;
+ overflow: auto;
+ border-radius: 10px;
+}
+
+#scrollable {
+ width: 600px;
+}
+
+#scrolledLayer {
+ margin-top: 50px;
+ margin-left: 100px;
+ box-model: border-box;
+ border: 1px solid lime;
+ width: 100px;
+ height: 100px;
+}
+
+</style>
+
+<body>
+
+<div id="scrollbox" reftest-displayport-x="0"
+ reftest-displayport-y="0"
+ reftest-displayport-w="300"
+ reftest-displayport-h="200">
+ <div id="scrollable">
+ <div id="scrolledLayer" class="reftest-no-paint"></div>
+ </div>
+</div>
+
+<script>
+
+var scrollbox = document.getElementById("scrollbox");
+
+function doTest() {
+ scrollbox.scrollLeft = 0;
+ document.documentElement.removeAttribute("class");
+}
+
+// Make #scrollbox have active scrolling
+scrollbox.scrollLeft = 60;
+scrollbox.offsetLeft;
+scrollbox.scrollLeft = 40;
+scrollbox.offsetLeft;
+
+document.addEventListener("MozReftestInvalidate", doTest, false);
+
+</script>
diff --git a/layout/reftests/invalidation/negative-w-component-ref.html b/layout/reftests/invalidation/negative-w-component-ref.html
new file mode 100644
index 000000000..f8d845d17
--- /dev/null
+++ b/layout/reftests/invalidation/negative-w-component-ref.html
@@ -0,0 +1,73 @@
+<!DOCTYPE html>
+<html lang="en">
+<meta charset="utf-8">
+<title>Change a layer's transform making negative w component.</title>
+
+<style>
+
+body {
+ background-color: white;
+ overflow: hidden;
+}
+
+#outer {
+ perspective: 500px;
+ perspective-origin: 350px 250px;
+ width: 700px;
+ height: 500px;
+ display: block;
+ top: 10px;
+ left: 10px;
+ position: absolute;
+ overflow: visible;
+}
+
+#container1 {
+ transform-style: preserve-3d;
+ transform: translateX(-50px) translateZ(350px) rotateY(-90deg);
+}
+
+#container2 {
+ transform-style: preserve-3d;
+ transform: translateY(-200px) translateX(50px) translateZ(350px) rotateY(90deg);
+}
+
+#scale {
+ transform-style: preserve-3d;
+}
+
+.negw {
+ transform: translateZ(1px);
+}
+
+.posw {
+ transform: translateZ(-500px);;
+}
+
+#dummy {
+ transform-style: preserve-3d;
+ transform: translateY(150px);
+}
+
+#square1, #square2 {
+ background-color: red;
+ width: 700px;
+ height: 200px;
+}
+
+</style>
+
+<body>
+
+<div id="outer">
+ <div id="scale" class="posw">
+ <div id="dummy">
+ <div id="container1">
+ <div id="square1"></div>
+ </div>
+ <div id="container2">
+ <div id="square2"></div>
+ </div>
+ </div>
+ </div>
+</div>
diff --git a/layout/reftests/invalidation/negative-w-component.html b/layout/reftests/invalidation/negative-w-component.html
new file mode 100644
index 000000000..b7cfcfb6c
--- /dev/null
+++ b/layout/reftests/invalidation/negative-w-component.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<html lang="en" class="reftest-wait">
+<meta charset="utf-8">
+<title>Change a layer's transform making negative w component.</title>
+
+<style>
+
+body {
+ background-color: white;
+ overflow: hidden;
+}
+
+#outer {
+ perspective: 500px;
+ perspective-origin: 350px 250px;
+ width: 700px;
+ height: 500px;
+ display: block;
+ top: 10px;
+ left: 10px;
+ position: absolute;
+ overflow: visible;
+}
+
+#container1 {
+ transform-style: preserve-3d;
+ transform: translateX(-50px) translateZ(350px) rotateY(-90deg);
+}
+
+#container2 {
+ transform-style: preserve-3d;
+ transform: translateY(-200px) translateX(50px) translateZ(350px) rotateY(90deg);
+}
+
+#scale {
+ transform-style: preserve-3d;
+}
+
+.negw {
+ transform: translateZ(1px);
+}
+
+.posw {
+ transform: translateZ(-500px);;
+}
+
+#dummy {
+ transform-style: preserve-3d;
+ transform: translateY(150px);
+}
+
+#square1, #square2 {
+ background-color: red;
+ width: 700px;
+ height: 200px;
+}
+
+</style>
+
+<body>
+
+<div id="outer">
+ <div id="scale" class="negw">
+ <div id="dummy">
+ <div id="container1">
+ <div id="square1"></div>
+ </div>
+ <div id="container2">
+ <div id="square2"></div>
+ </div>
+ </div>
+ </div>
+</div>
+
+<script>
+
+var scale = document.getElementById("scale");
+
+function doTest() {
+ scale.className = "posw";
+ document.documentElement.removeAttribute("class");
+}
+
+document.addEventListener("MozReftestInvalidate", doTest, false);
+
+</script>
diff --git a/layout/reftests/invalidation/nudge-to-integer-invalidation.html b/layout/reftests/invalidation/nudge-to-integer-invalidation.html
new file mode 100644
index 000000000..70de2605b
--- /dev/null
+++ b/layout/reftests/invalidation/nudge-to-integer-invalidation.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en" class="reftest-wait"
+ reftest-displayport-x="0"
+ reftest-displayport-y="0"
+ reftest-displayport-w="800"
+ reftest-displayport-h="1000">
+<meta charset="utf-8">
+<title>Different epsilons in NudeToInteger and FuzzyEqual cause invalidations</title>
+
+<body>
+
+<svg viewBox="0 0 700 3000" width="700px" height="3000px">
+ <g transform="translate(0, -220.999756)">
+ <rect x="100" y="400" height="50" width="50" fill="grey" class="reftest-no-paint"/>
+ </g>
+</svg>
+
+<script>
+
+var scrollPositions = [0, 50];
+if (location.search.includes("reverse")) {
+ scrollPositions.reverse();
+}
+document.documentElement.scrollTop = scrollPositions[0];
+
+function doTest() {
+ document.documentElement.scrollTop = scrollPositions[1];
+ document.documentElement.removeAttribute("class");
+}
+document.addEventListener("MozReftestInvalidate", doTest, false);
+
+</script>
diff --git a/layout/reftests/invalidation/one-pixel-wide-background.png b/layout/reftests/invalidation/one-pixel-wide-background.png
new file mode 100644
index 000000000..09f59e39a
--- /dev/null
+++ b/layout/reftests/invalidation/one-pixel-wide-background.png
Binary files differ
diff --git a/layout/reftests/invalidation/paintedlayer-recycling-1.html b/layout/reftests/invalidation/paintedlayer-recycling-1.html
new file mode 100644
index 000000000..a5f3b6880
--- /dev/null
+++ b/layout/reftests/invalidation/paintedlayer-recycling-1.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<html lang="en" class="reftest-wait">
+<meta charset="utf-8">
+<title>Switching the transform to animate shouldn't invalidate the fixed layer</title>
+
+<style>
+
+.content {
+ box-sizing: border-box;
+ width: 200px;
+ height: 200px;
+ border: 1px solid black;
+}
+
+.fixed {
+ position: fixed;
+ background-color: white;
+ top: 20px;
+ left: 240px;
+}
+
+.reftest-no-paint {
+ border-color: lime;
+}
+
+.transform {
+ transform: translateY(0.1px);
+}
+
+.aboveTransform {
+ margin-top: 20px;
+ border-color: blue;
+ position: relative;
+}
+
+body {
+ margin: 0;
+ padding: 20px;
+ height: 3000px;
+}
+
+</style>
+
+<div class="transform content" id="aboutToAnimate">
+ <!--
+ This transform starts out inactive and is going to turn active + prerendered.
+ -->
+</div>
+
+<div class="aboveTransform content">
+ <!--
+ This content is on top of .transform in z-order but starts out in the
+ same layer as .transform (and the canvas background). Once the transform
+ turns active, this needs its own PaintedLayer because the prerendered
+ transform might asynchronously move underneath it.
+ -->
+</div>
+
+<div class="fixed reftest-no-paint content">
+ <!--
+ This fixed layer gets its own PaintedLayer above the rest.
+ When .aboveTransform requires its own PaintedLayer, it should not cause
+ .fixed to change layers.
+ -->
+</div>
+
+<script>
+
+function doTest() {
+ document.querySelector("#aboutToAnimate").style.willChange = "transform";
+ document.documentElement.removeAttribute("class");
+}
+document.addEventListener("MozReftestInvalidate", doTest, false);
+
+</script>
diff --git a/layout/reftests/invalidation/paintedlayer-recycling-2.html b/layout/reftests/invalidation/paintedlayer-recycling-2.html
new file mode 100644
index 000000000..45d7cc982
--- /dev/null
+++ b/layout/reftests/invalidation/paintedlayer-recycling-2.html
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html lang="en" class="reftest-wait">
+<meta charset="utf-8">
+<title>Starting to scroll the nested scrollbox shouldn't invalidate the fixed layer</title>
+
+<style>
+
+.content {
+ box-sizing: border-box;
+ width: 200px;
+ height: 200px;
+ border: 1px solid black;
+}
+
+.fixed {
+ position: fixed;
+ top: 20px;
+ left: 240px;
+}
+
+.reftest-no-paint {
+ border-color: lime;
+}
+
+.scrollable {
+ overflow: auto;
+ padding: 10px;
+}
+
+.scrolled {
+ border: 1px solid gray;
+ height: 400px;
+}
+
+body {
+ margin: 0;
+ padding: 20px;
+ height: 3000px;
+}
+
+</style>
+
+<div class="scrollable content" id="aboutToScroll">
+ <!--
+ This scrollbox starts out without active scrolling and is going to become
+ actively scrolled.
+ -->
+ <div class="scrolled"></div>
+</div>
+
+<div class="fixed reftest-no-paint content">
+ <!--
+ This fixed layer gets its own PaintedLayer above the rest.
+ When the contents of .scrollable require their own PaintedLayer, that
+ should not cause .fixed to change layers.
+ -->
+</div>
+
+<script>
+
+function doTest() {
+ document.querySelector("#aboutToScroll").scrollTop = 50 - document.querySelector("#aboutToScroll").scrollTop;
+ document.documentElement.removeAttribute("class");
+}
+document.addEventListener("MozReftestInvalidate", doTest, false);
+
+</script>
diff --git a/layout/reftests/invalidation/paintedlayer-recycling-3.html b/layout/reftests/invalidation/paintedlayer-recycling-3.html
new file mode 100644
index 000000000..445e1241e
--- /dev/null
+++ b/layout/reftests/invalidation/paintedlayer-recycling-3.html
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html lang="en" class="reftest-wait">
+<meta charset="utf-8">
+<title>Adding a new display item to the bottom of an existing PaintedLayer shouldn't cause the other items in that layer to change layers</title>
+
+<style>
+
+.content {
+ box-sizing: border-box;
+ width: 200px;
+ height: 200px;
+ border: 1px solid black;
+}
+
+.fixed {
+ position: fixed;
+ top: 20px;
+ left: 140px;
+}
+
+.onTopOfFixed {
+ position: absolute;
+ top: 120px;
+ left: 260px;
+}
+
+.reftest-no-paint {
+ border-color: lime;
+}
+
+#aboutToBecomeVisible {
+ left: 20px;
+}
+
+body {
+ margin: 0;
+ padding: 20px;
+ height: 3000px;
+}
+
+</style>
+
+<div class="fixed content">
+ <!--
+ This layer is just there to force .onTopOfFixed into a PaintedLayer above
+ the page background.
+ -->
+</div>
+
+<div class="onTopOfFixed content" id="aboutToBecomeVisible" style="visibility: hidden">
+ <!--
+ This item starts out invisible but should end up in the same layer as the other
+ .onTopOfFixed item, once it's visible.
+ -->
+</div>
+
+<div class="onTopOfFixed reftest-no-paint content">
+ <!--
+ This item shouldn't repaint when the other .onTopOfFixed item becomes visible.
+ -->
+</div>
+
+<script>
+
+function doTest() {
+ document.querySelector("#aboutToBecomeVisible").style.visibility = "visible";
+ document.documentElement.removeAttribute("class");
+}
+document.addEventListener("MozReftestInvalidate", doTest, false);
+
+</script>
diff --git a/layout/reftests/invalidation/paintedlayer-recycling-4.html b/layout/reftests/invalidation/paintedlayer-recycling-4.html
new file mode 100644
index 000000000..17913a96a
--- /dev/null
+++ b/layout/reftests/invalidation/paintedlayer-recycling-4.html
@@ -0,0 +1,70 @@
+<!DOCTYPE html>
+<html lang="en" class="reftest-wait">
+<meta charset="utf-8">
+<title>Removing an existing display item from the bottom of an existing PaintedLayer shouldn't cause the other items in that layer to change layers</title>
+
+<style>
+
+.content {
+ box-sizing: border-box;
+ width: 200px;
+ height: 200px;
+ border: 1px solid black;
+}
+
+.fixed {
+ position: fixed;
+ top: 20px;
+ left: 140px;
+}
+
+.onTopOfFixed {
+ position: absolute;
+ top: 120px;
+ left: 260px;
+}
+
+.reftest-no-paint {
+ border-color: lime;
+}
+
+#aboutToBecomeHidden {
+ left: 20px;
+}
+
+body {
+ margin: 0;
+ padding: 20px;
+ height: 3000px;
+}
+
+</style>
+
+<div class="fixed content">
+ <!--
+ This layer is just there to force .onTopOfFixed into a PaintedLayer above
+ the page background.
+ -->
+</div>
+
+<div class="onTopOfFixed content" id="aboutToBecomeHidden" style="visibility: visible">
+ <!--
+ This item starts out visible, in the same layer as the other .onTopOfFixed item.
+ -->
+</div>
+
+<div class="onTopOfFixed reftest-no-paint content">
+ <!--
+ This item shouldn't repaint when the other .onTopOfFixed item becomes invisible.
+ -->
+</div>
+
+<script>
+
+function doTest() {
+ document.querySelector("#aboutToBecomeHidden").style.visibility = "hidden";
+ document.documentElement.removeAttribute("class");
+}
+document.addEventListener("MozReftestInvalidate", doTest, false);
+
+</script>
diff --git a/layout/reftests/invalidation/paintedlayer-recycling-5.html b/layout/reftests/invalidation/paintedlayer-recycling-5.html
new file mode 100644
index 000000000..c4d53915b
--- /dev/null
+++ b/layout/reftests/invalidation/paintedlayer-recycling-5.html
@@ -0,0 +1,77 @@
+<!DOCTYPE html>
+<html lang="en" class="reftest-wait">
+<meta charset="utf-8">
+<title>Removing an existing display item that has its own PaintedLayer shouldn't cause invalidations in other PaintedLayers on top of it</title>
+
+<style>
+
+.content {
+ box-sizing: border-box;
+ width: 200px;
+ height: 200px;
+ border: 1px solid black;
+}
+
+.fixed {
+ position: fixed;
+ top: 20px;
+ left: 140px;
+}
+
+.onTopOfFixed {
+ position: absolute;
+ top: 120px;
+ left: 260px;
+}
+
+.reftest-no-paint {
+ border-color: lime;
+}
+
+#aboutToBecomeHidden {
+ left: 20px;
+}
+
+body {
+ margin: 0;
+ padding: 20px;
+ height: 3000px;
+}
+
+</style>
+
+<div class="fixed content">
+ <!--
+ This layer is just there to force .onTopOfFixed into PaintedLayers above
+ the page background.
+ -->
+</div>
+
+<div class="onTopOfFixed content" id="aboutToBecomeHidden" style="visibility: visible">
+ <!--
+ This item starts out visible, and has its own PaintedLayer.
+ -->
+</div>
+
+<div class="fixed content">
+ <!--
+ This layer is just there to force the next .onTopOfFixed into its own
+ PaintedLayer.
+ -->
+</div>
+
+<div class="onTopOfFixed reftest-no-paint content">
+ <!--
+ This item shouldn't repaint when the other .onTopOfFixed item is hidden.
+ -->
+</div>
+
+<script>
+
+function doTest() {
+ document.querySelector("#aboutToBecomeHidden").style.visibility = "hidden";
+ document.documentElement.removeAttribute("class");
+}
+document.addEventListener("MozReftestInvalidate", doTest, false);
+
+</script>
diff --git a/layout/reftests/invalidation/paintedlayer-recycling-6.html b/layout/reftests/invalidation/paintedlayer-recycling-6.html
new file mode 100644
index 000000000..7af1984ae
--- /dev/null
+++ b/layout/reftests/invalidation/paintedlayer-recycling-6.html
@@ -0,0 +1,78 @@
+<!DOCTYPE html>
+<html lang="en" class="reftest-wait">
+<meta charset="utf-8">
+<title>Adding a new display item that has its own PaintedLayer shouldn't cause invalidations in other PaintedLayers on top of it</title>
+
+<style>
+
+.content {
+ box-sizing: border-box;
+ width: 200px;
+ height: 200px;
+ border: 1px solid black;
+}
+
+.fixed {
+ position: fixed;
+ top: 20px;
+ left: 140px;
+}
+
+.onTopOfFixed {
+ position: absolute;
+ top: 120px;
+ left: 260px;
+}
+
+.reftest-no-paint {
+ border-color: lime;
+}
+
+#aboutToBecomeVisible {
+ left: 20px;
+}
+
+body {
+ margin: 0;
+ padding: 20px;
+ height: 3000px;
+}
+
+</style>
+
+<div class="fixed content">
+ <!--
+ This layer is just there to force .onTopOfFixed into PaintedLayers above
+ the page background.
+ -->
+</div>
+
+<div class="onTopOfFixed content" id="aboutToBecomeVisible" style="visibility: hidden">
+ <!--
+ This item starts out hidden, and will get its own PaintedLayer when it
+ becomes visible.
+ -->
+</div>
+
+<div class="fixed content">
+ <!--
+ This layer is just there to force the next .onTopOfFixed into its own
+ PaintedLayer.
+ -->
+</div>
+
+<div class="onTopOfFixed reftest-no-paint content">
+ <!--
+ This item shouldn't repaint when the other .onTopOfFixed item becomes visible.
+ -->
+</div>
+
+<script>
+
+function doTest() {
+ document.querySelector("#aboutToBecomeVisible").style.visibility = "visible";
+ document.documentElement.removeAttribute("class");
+}
+document.addEventListener("MozReftestInvalidate", doTest, false);
+
+</script>
diff --git a/layout/reftests/invalidation/paintedlayer-recycling-7.html b/layout/reftests/invalidation/paintedlayer-recycling-7.html
new file mode 100644
index 000000000..fed64813c
--- /dev/null
+++ b/layout/reftests/invalidation/paintedlayer-recycling-7.html
@@ -0,0 +1,82 @@
+<!DOCTYPE html>
+<html lang="en" class="reftest-wait">
+<meta charset="utf-8">
+<title>When a PaintedLayer is split up into two, the lower items should stay in their layer and the higher items should get a new one.</title>
+<!-- The motivation for this is that we don't ever want to assign a new layer to the canvas background just because an item is split from it. -->
+
+
+<style>
+
+.content {
+ box-sizing: border-box;
+ width: 200px;
+ height: 200px;
+ border: 1px solid black;
+}
+
+.fixed {
+ position: fixed;
+ top: 20px;
+ left: 140px;
+}
+
+.onTopOfFixed {
+ position: absolute;
+ top: 120px;
+ left: 260px;
+}
+
+.reftest-no-paint {
+ border-color: lime;
+}
+
+.onTopOfFixed.reftest-no-paint {
+ left: 20px;
+}
+
+body {
+ margin: 0;
+ padding: 20px;
+ height: 3000px;
+}
+
+</style>
+
+<div class="fixed content">
+ <!--
+ This layer is just there to force .onTopOfFixed into PaintedLayers above
+ the page background.
+ -->
+</div>
+
+<div class="onTopOfFixed reftest-no-paint content">
+ <!--
+ This item should start out sharing a PaintedLayer with the other
+ .onTopOfFixed item.
+ -->
+</div>
+
+<div class="fixed content" id="aboutToBecomeVisible" style="visibility: hidden">
+ <!--
+ This layer starts out hidden. When it becomes visible, it forces the two
+ .onTopOfFixed items into separate layers.
+ -->
+</div>
+
+<div class="onTopOfFixed content">
+ <!--
+ This item should start out sharing a PaintedLayer with the other
+ .onTopOfFixed item, but when the two items get split up, it should be this
+ one that changes layers, not the other one.
+ -->
+</div>
+
+<script>
+
+function doTest() {
+ document.querySelector("#aboutToBecomeVisible").style.visibility = "visible";
+ document.documentElement.removeAttribute("class");
+}
+document.addEventListener("MozReftestInvalidate", doTest, false);
+
+</script>
diff --git a/layout/reftests/invalidation/reftest-stylo.list b/layout/reftests/invalidation/reftest-stylo.list
new file mode 100644
index 000000000..8ead7ca3d
--- /dev/null
+++ b/layout/reftests/invalidation/reftest-stylo.list
@@ -0,0 +1,85 @@
+# DO NOT EDIT! This is a auto-generated temporary list for Stylo testing
+== table-repaint-a.html table-repaint-a.html
+== table-repaint-b.html table-repaint-b.html
+== table-repaint-c.html table-repaint-c.html
+== table-repaint-d.html table-repaint-d.html
+skip-if((B2G&&browserIsRemote)||Mulet) == 540247-1.xul 540247-1.xul
+# bug 974780
+# Initial mulet triage: parity with B2G/B2G Desktop
+skip-if((B2G&&browserIsRemote)||Mulet) == 543681-1.html 543681-1.html
+# Initial mulet triage: parity with B2G/B2G Desktop
+== 1243409-1.html 1243409-1.html
+== test-image-layers.html test-image-layers.html
+random-if(B2G||Mulet) == test-image-layers-multiple-displayitem.html test-image-layers-multiple-displayitem.html
+# Initial mulet triage: parity with B2G/B2G Desktop
+pref(layout.animated-image-layers.enabled,true) skip-if(Android||gtkWidget) == test-animated-image-layers.html test-animated-image-layers.html
+fails pref(layout.animated-image-layers.enabled,true) skip-if(Android||gtkWidget) == test-animated-image-layers-background.html test-animated-image-layers-background.html
+== box-shadow-border-radius.html box-shadow-border-radius.html
+== filter-userspace-offset.svg?offsetContainer=rect filter-userspace-offset.svg?offsetContainer=rect
+== filter-userspace-offset.svg?offsetContainer=use filter-userspace-offset.svg?offsetContainer=use
+== filter-userspace-offset.svg?offsetContainer=innerSVG filter-userspace-offset.svg?offsetContainer=innerSVG
+== filter-userspace-offset.svg?offsetContainer=foreignObject filter-userspace-offset.svg?offsetContainer=foreignObject
+== filter-userspace-offset.svg?offsetContainer=rect&filter=flood-boundingBox filter-userspace-offset.svg?offsetContainer=rect&filter=flood-boundingBox
+== filter-userspace-offset.svg?offsetContainer=use&filter=flood-boundingBox filter-userspace-offset.svg?offsetContainer=use&filter=flood-boundingBox
+== filter-userspace-offset.svg?offsetContainer=innerSVG&filter=flood-boundingBox filter-userspace-offset.svg?offsetContainer=innerSVG&filter=flood-boundingBox
+== filter-userspace-offset.svg?offsetContainer=foreignObject&filter=flood-boundingBox filter-userspace-offset.svg?offsetContainer=foreignObject&filter=flood-boundingBox
+== filter-userspace-offset.svg?offsetContainer=rect&filter=matrix-boundingBox filter-userspace-offset.svg?offsetContainer=rect&filter=matrix-boundingBox
+== filter-userspace-offset.svg?offsetContainer=use&filter=matrix-boundingBox filter-userspace-offset.svg?offsetContainer=use&filter=matrix-boundingBox
+== filter-userspace-offset.svg?offsetContainer=innerSVG&filter=matrix-boundingBox filter-userspace-offset.svg?offsetContainer=innerSVG&filter=matrix-boundingBox
+== filter-userspace-offset.svg?offsetContainer=foreignObject&filter=matrix-boundingBox filter-userspace-offset.svg?offsetContainer=foreignObject&filter=matrix-boundingBox
+== filter-userspace-offset.svg?offsetContainer=rect&filter=flood-userSpace-at100 filter-userspace-offset.svg?offsetContainer=rect&filter=flood-userSpace-at100
+== filter-userspace-offset.svg?offsetContainer=use&filter=flood-userSpace-at100 filter-userspace-offset.svg?offsetContainer=use&filter=flood-userSpace-at100
+== filter-userspace-offset.svg?offsetContainer=innerSVG&filter=flood-userSpace-atZero filter-userspace-offset.svg?offsetContainer=innerSVG&filter=flood-userSpace-atZero
+== filter-userspace-offset.svg?offsetContainer=foreignObject&filter=flood-userSpace-at100 filter-userspace-offset.svg?offsetContainer=foreignObject&filter=flood-userSpace-at100
+== filter-userspace-offset.svg?offsetContainer=rect&filter=matrix-userSpace-at100 filter-userspace-offset.svg?offsetContainer=rect&filter=matrix-userSpace-at100
+== filter-userspace-offset.svg?offsetContainer=use&filter=matrix-userSpace-at100 filter-userspace-offset.svg?offsetContainer=use&filter=matrix-userSpace-at100
+== filter-userspace-offset.svg?offsetContainer=innerSVG&filter=matrix-userSpace-atZero filter-userspace-offset.svg?offsetContainer=innerSVG&filter=matrix-userSpace-atZero
+== filter-userspace-offset.svg?offsetContainer=foreignObject&filter=matrix-userSpace-at100 filter-userspace-offset.svg?offsetContainer=foreignObject&filter=matrix-userSpace-at100
+== filter-userspace-offset.svg?offsetContainer=rect&mask=boundingBox filter-userspace-offset.svg?offsetContainer=rect&mask=boundingBox
+== filter-userspace-offset.svg?offsetContainer=use&mask=boundingBox filter-userspace-offset.svg?offsetContainer=use&mask=boundingBox
+== filter-userspace-offset.svg?offsetContainer=innerSVG&mask=boundingBox filter-userspace-offset.svg?offsetContainer=innerSVG&mask=boundingBox
+== filter-userspace-offset.svg?offsetContainer=foreignObject&mask=boundingBox filter-userspace-offset.svg?offsetContainer=foreignObject&mask=boundingBox
+== filter-userspace-offset.svg?offsetContainer=rect&mask=userSpace-at100 filter-userspace-offset.svg?offsetContainer=rect&mask=userSpace-at100
+== filter-userspace-offset.svg?offsetContainer=use&mask=userSpace-at100 filter-userspace-offset.svg?offsetContainer=use&mask=userSpace-at100
+== filter-userspace-offset.svg?offsetContainer=innerSVG&mask=userSpace-atZero filter-userspace-offset.svg?offsetContainer=innerSVG&mask=userSpace-atZero
+== filter-userspace-offset.svg?offsetContainer=foreignObject&mask=userSpace-at100 filter-userspace-offset.svg?offsetContainer=foreignObject&mask=userSpace-at100
+== filter-userspace-offset.svg?offsetContainer=rect&filter=matrix-fillPaint-boundingBox filter-userspace-offset.svg?offsetContainer=rect&filter=matrix-fillPaint-boundingBox
+== filter-userspace-offset.svg?offsetContainer=rect&filter=matrix-fillPaint-userSpace-at100 filter-userspace-offset.svg?offsetContainer=rect&filter=matrix-fillPaint-userSpace-at100
+== scroll-inactive-layers.html scroll-inactive-layers.html
+== scroll-inactive-layers-2.html scroll-inactive-layers-2.html
+== inactive-layertree-visible-region-1.html inactive-layertree-visible-region-1.html
+== inactive-layertree-visible-region-2.html inactive-layertree-visible-region-2.html
+== transform-floating-point-invalidation.html transform-floating-point-invalidation.html
+== transform-floating-point-invalidation.html?reverse transform-floating-point-invalidation.html?reverse
+== nudge-to-integer-invalidation.html nudge-to-integer-invalidation.html
+== nudge-to-integer-invalidation.html?reverse nudge-to-integer-invalidation.html?reverse
+== clipped-animated-transform-1.html clipped-animated-transform-1.html
+== paintedlayer-recycling-1.html paintedlayer-recycling-1.html
+== paintedlayer-recycling-2.html paintedlayer-recycling-2.html
+pref(layers.single-tile.enabled,false) == paintedlayer-recycling-3.html paintedlayer-recycling-3.html
+== paintedlayer-recycling-4.html paintedlayer-recycling-4.html
+== paintedlayer-recycling-5.html paintedlayer-recycling-5.html
+== paintedlayer-recycling-6.html paintedlayer-recycling-6.html
+== paintedlayer-recycling-7.html paintedlayer-recycling-7.html
+== masklayer-1.html masklayer-1.html
+== masklayer-2.html masklayer-2.html
+random == layer-splitting-1.html layer-splitting-1.html
+random == layer-splitting-2.html layer-splitting-2.html
+random == layer-splitting-3.html layer-splitting-3.html
+fails == layer-splitting-4.html layer-splitting-4.html
+== layer-splitting-5.html layer-splitting-5.html
+== layer-splitting-6.html layer-splitting-6.html
+== layer-splitting-7.html layer-splitting-7.html
+fuzzy-if(gtkWidget,2,4) fuzzy-if(asyncPan,2,3955) fuzzy-if(OSX,179,30) fuzzy-if(skiaContent,16,3230) == image-scrolling-zoom-1.html image-scrolling-zoom-1.html
+== image-scrolling-zoom-1-ref.html image-scrolling-zoom-1-ref.html
+pref(layers.single-tile.enabled,false) == fast-scrolling.html fast-scrolling.html
+== background-position-1.html background-position-1.html
+== background-position-2a.html background-position-2a.html
+== background-position-2b.html background-position-2b.html
+== background-position-2c.html background-position-2c.html
+== background-position-2d.html background-position-2d.html
+== background-position-2e.html background-position-2e.html
+== background-position-2f.html background-position-2f.html
+== zero-opacity-animation.html zero-opacity-animation.html
+== zero-opacity-text.html zero-opacity-text.html
+== negative-w-component.html negative-w-component.html
diff --git a/layout/reftests/invalidation/reftest.list b/layout/reftests/invalidation/reftest.list
new file mode 100644
index 000000000..314693359
--- /dev/null
+++ b/layout/reftests/invalidation/reftest.list
@@ -0,0 +1,80 @@
+== table-repaint-a.html table-repaint-a-ref.html
+== table-repaint-b.html table-repaint-b-ref.html
+== table-repaint-c.html table-repaint-c-ref.html
+== table-repaint-d.html table-repaint-d-ref.html
+== 540247-1.xul 540247-1-ref.xul
+== 543681-1.html 543681-1-ref.html
+== 1243409-1.html 1243409-1-ref.html
+== test-image-layers.html test-image-layers-ref.html
+== test-image-layers-multiple-displayitem.html test-image-layers-ref.html
+pref(layout.animated-image-layers.enabled,true) skip-if(Android||gtkWidget) == test-animated-image-layers.html test-animated-image-layers-ref.html
+pref(layout.animated-image-layers.enabled,true) skip-if(Android||gtkWidget) == test-animated-image-layers-background.html test-animated-image-layers-ref.html
+== box-shadow-border-radius.html box-shadow-border-radius-ref.html
+== filter-userspace-offset.svg?offsetContainer=rect filter-userspace-offset.svg
+== filter-userspace-offset.svg?offsetContainer=use filter-userspace-offset.svg
+== filter-userspace-offset.svg?offsetContainer=innerSVG filter-userspace-offset.svg
+== filter-userspace-offset.svg?offsetContainer=foreignObject filter-userspace-offset.svg
+== filter-userspace-offset.svg?offsetContainer=rect&filter=flood-boundingBox filter-userspace-offset.svg
+== filter-userspace-offset.svg?offsetContainer=use&filter=flood-boundingBox filter-userspace-offset.svg
+== filter-userspace-offset.svg?offsetContainer=innerSVG&filter=flood-boundingBox filter-userspace-offset.svg
+== filter-userspace-offset.svg?offsetContainer=foreignObject&filter=flood-boundingBox filter-userspace-offset.svg
+== filter-userspace-offset.svg?offsetContainer=rect&filter=matrix-boundingBox filter-userspace-offset.svg
+== filter-userspace-offset.svg?offsetContainer=use&filter=matrix-boundingBox filter-userspace-offset.svg
+== filter-userspace-offset.svg?offsetContainer=innerSVG&filter=matrix-boundingBox filter-userspace-offset.svg
+== filter-userspace-offset.svg?offsetContainer=foreignObject&filter=matrix-boundingBox filter-userspace-offset.svg
+== filter-userspace-offset.svg?offsetContainer=rect&filter=flood-userSpace-at100 filter-userspace-offset.svg
+== filter-userspace-offset.svg?offsetContainer=use&filter=flood-userSpace-at100 filter-userspace-offset.svg
+== filter-userspace-offset.svg?offsetContainer=innerSVG&filter=flood-userSpace-atZero filter-userspace-offset.svg
+== filter-userspace-offset.svg?offsetContainer=foreignObject&filter=flood-userSpace-at100 filter-userspace-offset.svg
+== filter-userspace-offset.svg?offsetContainer=rect&filter=matrix-userSpace-at100 filter-userspace-offset.svg
+== filter-userspace-offset.svg?offsetContainer=use&filter=matrix-userSpace-at100 filter-userspace-offset.svg
+== filter-userspace-offset.svg?offsetContainer=innerSVG&filter=matrix-userSpace-atZero filter-userspace-offset.svg
+== filter-userspace-offset.svg?offsetContainer=foreignObject&filter=matrix-userSpace-at100 filter-userspace-offset.svg
+== filter-userspace-offset.svg?offsetContainer=rect&mask=boundingBox filter-userspace-offset.svg
+== filter-userspace-offset.svg?offsetContainer=use&mask=boundingBox filter-userspace-offset.svg
+== filter-userspace-offset.svg?offsetContainer=innerSVG&mask=boundingBox filter-userspace-offset.svg
+== filter-userspace-offset.svg?offsetContainer=foreignObject&mask=boundingBox filter-userspace-offset.svg
+== filter-userspace-offset.svg?offsetContainer=rect&mask=userSpace-at100 filter-userspace-offset.svg
+== filter-userspace-offset.svg?offsetContainer=use&mask=userSpace-at100 filter-userspace-offset.svg
+== filter-userspace-offset.svg?offsetContainer=innerSVG&mask=userSpace-atZero filter-userspace-offset.svg
+== filter-userspace-offset.svg?offsetContainer=foreignObject&mask=userSpace-at100 filter-userspace-offset.svg
+== filter-userspace-offset.svg?offsetContainer=rect&filter=matrix-fillPaint-boundingBox filter-userspace-offset.svg
+== filter-userspace-offset.svg?offsetContainer=rect&filter=matrix-fillPaint-userSpace-at100 filter-userspace-offset.svg
+!= scroll-inactive-layers.html about:blank
+!= scroll-inactive-layers-2.html about:blank
+!= inactive-layertree-visible-region-1.html about:blank
+!= inactive-layertree-visible-region-2.html about:blank
+!= transform-floating-point-invalidation.html about:blank
+!= transform-floating-point-invalidation.html?reverse about:blank
+!= nudge-to-integer-invalidation.html about:blank
+!= nudge-to-integer-invalidation.html?reverse about:blank
+!= clipped-animated-transform-1.html about:blank
+!= paintedlayer-recycling-1.html about:blank
+!= paintedlayer-recycling-2.html about:blank
+pref(layers.single-tile.enabled,false) != paintedlayer-recycling-3.html about:blank
+!= paintedlayer-recycling-4.html about:blank
+!= paintedlayer-recycling-5.html about:blank
+!= paintedlayer-recycling-6.html about:blank
+!= paintedlayer-recycling-7.html about:blank
+!= masklayer-1.html about:blank
+!= masklayer-2.html about:blank
+!= layer-splitting-1.html about:blank
+!= layer-splitting-2.html about:blank
+!= layer-splitting-3.html about:blank
+!= layer-splitting-4.html about:blank
+!= layer-splitting-5.html about:blank
+!= layer-splitting-6.html about:blank
+!= layer-splitting-7.html about:blank
+fuzzy-if(gtkWidget,2,4) fuzzy-if(asyncPan,2,3955) fuzzy-if(OSX,179,30) fuzzy-if(skiaContent,16,3230) == image-scrolling-zoom-1.html image-scrolling-zoom-1-ref.html
+!= image-scrolling-zoom-1-ref.html image-scrolling-zoom-1-notref.html
+pref(layers.single-tile.enabled,false) != fast-scrolling.html about:blank
+== background-position-1.html background-position-1-ref.html
+== background-position-2a.html background-position-2-ref.html
+== background-position-2b.html background-position-2-ref.html
+== background-position-2c.html background-position-2-ref.html
+== background-position-2d.html background-position-2-ref.html
+== background-position-2e.html background-position-2-ref.html
+== background-position-2f.html background-position-2-ref.html
+== zero-opacity-animation.html about:blank
+== zero-opacity-text.html about:blank
+== negative-w-component.html negative-w-component-ref.html
diff --git a/layout/reftests/invalidation/scroll-inactive-layers-2.html b/layout/reftests/invalidation/scroll-inactive-layers-2.html
new file mode 100644
index 000000000..11ccc75e5
--- /dev/null
+++ b/layout/reftests/invalidation/scroll-inactive-layers-2.html
@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<html class="reftest-wait"
+ reftest-displayport-x="0"
+ reftest-displayport-y="0"
+ reftest-displayport-w="800"
+ reftest-displayport-h="1000">
+<title>Scrolling over inactive layers shouldn't repaint their contents even if both the top and the bottom edge of the inactive layers are offscreen</title>
+
+<style>
+
+html, body {
+ margin: 0;
+ padding: 0;
+}
+
+.outer {
+ border: 1px solid black;
+ width: 100px;
+ height: 2000px;
+ margin-right: 20px;
+ padding-top: 200px;
+ float: left;
+}
+
+.opacity {
+ opacity: 0.5;
+}
+
+.transform {
+ transform: translateX(1px);
+}
+
+.filter {
+ filter: url(#filter);
+}
+
+.mask {
+ mask: url(#mask);
+}
+
+.reftest-no-paint {
+ height: 50px;
+ border: 1px solid lime;
+}
+
+</style>
+
+<svg height="0">
+ <defs>
+ <filter id="filter" filterUnits="objectBoundingBox"
+ x="0%" y="0%" width="100%" height="100%"
+ color-interpolation-filters="sRGB">
+ <feMerge><feMergeNode/><feMerge>
+ </filter>
+ <mask id="mask" maskContentUnits="objectBoundingBox">
+ <rect x="0" y="0" width="1" height="1" fill="white"/>
+ </mask>
+ </defs>
+</svg>
+
+<div class="outer opacity">
+ <div class="reftest-no-paint"></div>
+</div>
+
+<div class="outer transform">
+ <div class="reftest-no-paint"></div>
+</div>
+
+<div class="outer filter">
+ <div class="reftest-no-paint"></div>
+</div>
+
+<div class="outer mask">
+ <div class="reftest-no-paint"></div>
+</div>
+
+<script>
+
+function doTest() {
+ document.documentElement.scrollTop = 100;
+ document.documentElement.removeAttribute("class");
+}
+document.documentElement.scrollTop = 50;
+document.addEventListener("MozReftestInvalidate", doTest, false);
+
+</script>
diff --git a/layout/reftests/invalidation/scroll-inactive-layers.html b/layout/reftests/invalidation/scroll-inactive-layers.html
new file mode 100644
index 000000000..7b658b6fc
--- /dev/null
+++ b/layout/reftests/invalidation/scroll-inactive-layers.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<html class="reftest-wait"
+ reftest-displayport-x="0"
+ reftest-displayport-y="0"
+ reftest-displayport-w="800"
+ reftest-displayport-h="1000">
+<title>Scrolling over inactive layers shouldn't repaint their contents</title>
+
+<style>
+
+.outer {
+ border: 1px solid black;
+ width: 100px;
+ height: 2000px;
+ margin-top: 200px;
+ margin-right: 20px;
+ padding-top: 100px;
+ float: left;
+}
+
+.opacity {
+ opacity: 0.5;
+}
+
+.transform {
+ transform: translateX(1px);
+}
+
+.filter {
+ filter: url(#filter);
+}
+
+.mask {
+ mask: url(#mask);
+}
+
+.reftest-no-paint {
+ height: 50px;
+ border: 1px solid lime;
+}
+
+</style>
+
+<svg height="0">
+ <defs>
+ <filter id="filter" filterUnits="objectBoundingBox"
+ x="0%" y="0%" width="100%" height="100%"
+ color-interpolation-filters="sRGB">
+ <feMerge><feMergeNode/><feMerge>
+ </filter>
+ <mask id="mask" maskContentUnits="objectBoundingBox">
+ <rect x="0" y="0" width="1" height="1" fill="white"/>
+ </mask>
+ </defs>
+</svg>
+
+<div class="outer opacity">
+ <div class="reftest-no-paint"></div>
+</div>
+
+<div class="outer transform">
+ <div class="reftest-no-paint"></div>
+</div>
+
+<div class="outer filter">
+ <div class="reftest-no-paint"></div>
+</div>
+
+<div class="outer mask">
+ <div class="reftest-no-paint"></div>
+</div>
+
+<script>
+
+function doTest() {
+ document.documentElement.scrollTop = 100;
+ document.documentElement.removeAttribute("class");
+}
+document.addEventListener("MozReftestInvalidate", doTest, false);
+
+</script>
diff --git a/layout/reftests/invalidation/table-repaint-a-ref.html b/layout/reftests/invalidation/table-repaint-a-ref.html
new file mode 100644
index 000000000..a7957c34f
--- /dev/null
+++ b/layout/reftests/invalidation/table-repaint-a-ref.html
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>table-repaint-a-ref</title>
+</head>
+<body>
+<table>
+ <tr>
+ <td bgcolor="lime"></td>
+ </tr>
+</table>
+</body>
+</html>
diff --git a/layout/reftests/invalidation/table-repaint-a.html b/layout/reftests/invalidation/table-repaint-a.html
new file mode 100644
index 000000000..c1ec02620
--- /dev/null
+++ b/layout/reftests/invalidation/table-repaint-a.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<head>
+ <title>table-repaint-a</title>
+</head>
+<body>
+<table>
+ <tr>
+ <td bgcolor="black"></td>
+ <td bgcolor="lime"></td>
+ </tr>
+</table>
+<script>
+function foo() {
+ var x=document.getElementsByTagName('td')[0];
+ x.style.display = 'none';
+ document.documentElement.removeAttribute("class");
+}
+document.addEventListener("MozReftestInvalidate", foo, false);
+</script>
+</body>
+</html>
diff --git a/layout/reftests/invalidation/table-repaint-b-ref.html b/layout/reftests/invalidation/table-repaint-b-ref.html
new file mode 100644
index 000000000..1581e0458
--- /dev/null
+++ b/layout/reftests/invalidation/table-repaint-b-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<title>table-repaint-b-ref</title>
+<body>
+<table>
+<tr>
+ <td>aaa</td><td><span style="position: relative"><div style="height: 0px"><div style="height: 300px; width: 10px; background: green"></div></div>bbb</td>
+</tr>
+<tr>
+ <td>
+ longer text: above this, first cell should say 'aaa' while second says 'bbb'. There should be only one green rectangle.
+ </td>
+</tr>
+</table>
+</script>
+</body>
+</html>
diff --git a/layout/reftests/invalidation/table-repaint-b.html b/layout/reftests/invalidation/table-repaint-b.html
new file mode 100644
index 000000000..a3e9b4c65
--- /dev/null
+++ b/layout/reftests/invalidation/table-repaint-b.html
@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html class="reftest-wait"><head>
+<title>table-repaint-b-ref</title>
+<body>
+<table id="x">
+<tr>
+ <td>aaa</td>
+ <td>
+ <span style="position: relative">
+ <div style="height: 0px">
+ <div style="height: 300px; width: 10px; background: green"></div>
+ </div>bbb
+ </td>
+</tr>
+</table>
+<script>
+ function foo() {
+ var t = document.getElementById("x");
+ var r = document.createElement("tr");
+ var c = document.createElement("td");
+ c.appendChild(document.createTextNode("longer text: above this, first cell should say 'aaa' while second says 'bbb'. There should be only one green rectangle."));
+ r.appendChild(c);
+ t.tBodies[0].appendChild(r);
+ document.documentElement.removeAttribute("class");
+ }
+document.addEventListener("MozReftestInvalidate", foo, false);
+</script>
+</body>
+</html>
diff --git a/layout/reftests/invalidation/table-repaint-c-ref.html b/layout/reftests/invalidation/table-repaint-c-ref.html
new file mode 100644
index 000000000..1e9393b95
--- /dev/null
+++ b/layout/reftests/invalidation/table-repaint-c-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html>
+<title>table-repaint-c-ref</title>
+<style>
+td {
+width: 50px;
+height: 50px;
+}
+</style>
+</head>
+<body>
+<table >
+<tbody>
+<tr>
+<td bgcolor="lime"></td>
+</tr>
+</tbody></table>
+</body>
+</html>
diff --git a/layout/reftests/invalidation/table-repaint-c.html b/layout/reftests/invalidation/table-repaint-c.html
new file mode 100644
index 000000000..6a750f8a6
--- /dev/null
+++ b/layout/reftests/invalidation/table-repaint-c.html
@@ -0,0 +1,30 @@
+<!DOCTYPE html>
+<html class="reftest-wait"><head>
+<title>table-repaint-c</title>
+<style>
+td {
+width: 50px;
+height: 50px;
+}
+</style>
+</head>
+<body>
+<table>
+ <col id="foo">
+ <tbody>
+ <tr>
+ <td bgcolor="black"></td>
+ <td bgcolor="lime"></td>
+ </tr>
+ </tbody>
+</table>
+<script>
+function foo() {
+var x=document.getElementById("foo");
+x.style.visibility = 'collapse';
+document.documentElement.removeAttribute("class");
+}
+document.addEventListener("MozReftestInvalidate", foo, false);
+</script>
+</body>
+</html>
diff --git a/layout/reftests/invalidation/table-repaint-d-ref.html b/layout/reftests/invalidation/table-repaint-d-ref.html
new file mode 100644
index 000000000..917c73427
--- /dev/null
+++ b/layout/reftests/invalidation/table-repaint-d-ref.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+<title>table-repaint-d-ref</title>
+<body>
+<table>
+<tr>
+ <td>aaa</td><td>bbb</td>
+</tr>
+<tr>
+ <td>longer text: above this, first cell should say 'aaa' while second says 'bbb'.</td>
+</tr>
+</table>
+</body>
+</html>
diff --git a/layout/reftests/invalidation/table-repaint-d.html b/layout/reftests/invalidation/table-repaint-d.html
new file mode 100644
index 000000000..dad19dcb3
--- /dev/null
+++ b/layout/reftests/invalidation/table-repaint-d.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html class="reftest-wait"><head>
+<title>table-repaint-d</title>
+<body>
+<table id="x">
+<tr>
+ <td>aaa</td><td>bbb</td>
+</tr>
+</table>
+<script>
+ function foo() {
+ var t = document.getElementById("x");
+ var r = document.createElement("tr");
+ var c = document.createElement("td");
+ c.appendChild(document.createTextNode("longer text: above this, first cell should say 'aaa' while second says 'bbb'."));
+ r.appendChild(c);
+ t.tBodies[0].appendChild(r);
+ document.documentElement.removeAttribute("class");
+ }
+document.addEventListener("MozReftestInvalidate", foo, false);
+</script>
+</body>
+</html>
diff --git a/layout/reftests/invalidation/test-animated-image-layers-background.html b/layout/reftests/invalidation/test-animated-image-layers-background.html
new file mode 100644
index 000000000..06ebb2fbd
--- /dev/null
+++ b/layout/reftests/invalidation/test-animated-image-layers-background.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait">
+<body>
+<div>
+<div id="image" style="width: 256px; height: 256px; background-image: url('image_rgrg-256x256-animated.gif');" class="reftest-no-paint"></div>
+</div>
+<script type="application/javascript">
+
+function doTest() {
+ document.body.style.background = "black";
+ document.documentElement.removeAttribute("class");
+}
+document.addEventListener("MozReftestInvalidate", doTest, false);
+</script>
+</body>
+</html>
diff --git a/layout/reftests/invalidation/test-animated-image-layers-ref.html b/layout/reftests/invalidation/test-animated-image-layers-ref.html
new file mode 100644
index 000000000..d8bfb8655
--- /dev/null
+++ b/layout/reftests/invalidation/test-animated-image-layers-ref.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML>
+<html>
+<body style="background:black">
+<div>
+<img id="image" src="./image_rgrg-256x256.png"></img>
+</div>
+</body>
+</html>
diff --git a/layout/reftests/invalidation/test-animated-image-layers.html b/layout/reftests/invalidation/test-animated-image-layers.html
new file mode 100644
index 000000000..3eecf7f50
--- /dev/null
+++ b/layout/reftests/invalidation/test-animated-image-layers.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait">
+<body>
+<div>
+<img id="image" class="reftest-no-paint" src="./image_rgrg-256x256-animated.gif"></img>
+</div>
+<script type="application/javascript">
+
+function doTest() {
+ document.body.style.background = "black";
+ document.documentElement.removeAttribute("class");
+}
+document.addEventListener("MozReftestInvalidate", doTest, false);
+</script>
+</body>
+</html>
diff --git a/layout/reftests/invalidation/test-image-layers-multiple-displayitem.html b/layout/reftests/invalidation/test-image-layers-multiple-displayitem.html
new file mode 100644
index 000000000..c694e73b5
--- /dev/null
+++ b/layout/reftests/invalidation/test-image-layers-multiple-displayitem.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait">
+<body>
+<style>
+img {
+ background-color: green;
+}
+</style>
+<div>
+<img id="image" class="reftest-no-paint" src="./image_rgrg-256x256.png" style="-moz-transform: perspective(1px)"></img>
+</div>
+<script type="application/javascript">
+
+function doTest() {
+ document.body.style.background = "black";
+ document.documentElement.removeAttribute("class");
+}
+document.addEventListener("MozReftestInvalidate", doTest, false);
+</script>
+</body>
+</html>
diff --git a/layout/reftests/invalidation/test-image-layers-ref.html b/layout/reftests/invalidation/test-image-layers-ref.html
new file mode 100644
index 000000000..fce127b73
--- /dev/null
+++ b/layout/reftests/invalidation/test-image-layers-ref.html
@@ -0,0 +1,8 @@
+<!DOCTYPE HTML>
+<html>
+<body style="background:black">
+<div>
+<img id="image" src="./image_rgrg-256x256.png" style="-moz-transform: perspective(1px)"></img>
+</div>
+</body>
+</html>
diff --git a/layout/reftests/invalidation/test-image-layers.html b/layout/reftests/invalidation/test-image-layers.html
new file mode 100644
index 000000000..7c1ae7d8e
--- /dev/null
+++ b/layout/reftests/invalidation/test-image-layers.html
@@ -0,0 +1,16 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait">
+<body>
+<div>
+<img id="image" class="reftest-no-paint" src="./image_rgrg-256x256.png" style="-moz-transform: perspective(1px)"></img>
+</div>
+<script type="application/javascript">
+
+function doTest() {
+ document.body.style.background = "black";
+ document.documentElement.removeAttribute("class");
+}
+document.addEventListener("MozReftestInvalidate", doTest, false);
+</script>
+</body>
+</html>
diff --git a/layout/reftests/invalidation/transform-floating-point-invalidation.html b/layout/reftests/invalidation/transform-floating-point-invalidation.html
new file mode 100644
index 000000000..599d88078
--- /dev/null
+++ b/layout/reftests/invalidation/transform-floating-point-invalidation.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html lang="en" class="reftest-wait"
+ reftest-displayport-x="0"
+ reftest-displayport-y="0"
+ reftest-displayport-w="800"
+ reftest-displayport-h="1000">
+<meta charset="utf-8">
+<title>Scrolling shouldn't invalidate the rect</title>
+
+<body>
+
+<svg width="824" height="1375" viewBox="0 0 660 1100">
+ <rect x="100" y="600" width="120" height="120" fill="#EEE"
+ transform="matrix(0,0.969665,-2.0321494,0,1828.58132,65.718239)"
+ class="reftest-no-paint"/>
+</svg>
+
+<script>
+
+var scrollPositions = [81, 82];
+if (location.search.includes("reverse")) {
+ scrollPositions.reverse();
+}
+document.documentElement.scrollTop = scrollPositions[0];
+
+function doTest() {
+ document.documentElement.scrollTop = scrollPositions[1];
+ document.documentElement.removeAttribute("class");
+}
+document.addEventListener("MozReftestInvalidate", doTest, false);
+
+</script>
diff --git a/layout/reftests/invalidation/zero-opacity-animation.html b/layout/reftests/invalidation/zero-opacity-animation.html
new file mode 100644
index 000000000..0e4f4dd48
--- /dev/null
+++ b/layout/reftests/invalidation/zero-opacity-animation.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait">
+<body>
+<div style="opacity:0">
+ <div id="d" class="reftest-no-paint" style="height:50px; border:2px solid black"></div>
+</div>
+<script type="application/javascript">
+function doTest() {
+ d.style.border = "2px solid green";
+ document.documentElement.removeAttribute("class");
+}
+document.addEventListener("MozReftestInvalidate", doTest, false);
+</script>
+</body>
+</html>
diff --git a/layout/reftests/invalidation/zero-opacity-text.html b/layout/reftests/invalidation/zero-opacity-text.html
new file mode 100644
index 000000000..5524d29ef
--- /dev/null
+++ b/layout/reftests/invalidation/zero-opacity-text.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html class="reftest-wait">
+<body>
+<div style="opacity:0">
+ <div id="d" class="reftest-no-paint" style="height:50px;">abc</div>
+</div>
+<script type="application/javascript">
+function doTest() {
+ d.textContent = "def";
+ document.documentElement.removeAttribute("class");
+}
+document.addEventListener("MozReftestInvalidate", doTest, false);
+</script>
+</body>
+</html>