summaryrefslogtreecommitdiffstats
path: root/testing/web-platform/tests/html/canvas/element/layers
diff options
context:
space:
mode:
Diffstat (limited to 'testing/web-platform/tests/html/canvas/element/layers')
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.endlayer.alone-expected.html21
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.endlayer.alone.html24
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.endlayer.unmatched-expected.html24
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.endlayer.unmatched.html28
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha-expected.html31
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending-expected.html32
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending.html35
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending.shadow-expected.html35
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending.shadow.html38
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite-expected.html32
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite.html35
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite.shadow-expected.html35
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite.shadow.html38
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.html34
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.shadow-expected.html34
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.shadow.html37
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending-expected.html31
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.html34
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.shadow-expected.html34
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.shadow.html37
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite-expected.html31
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.html34
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.shadow-expected.html34
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.shadow.html37
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha-expected.html50
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending-expected.html51
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending.html38
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending.shadow-expected.html54
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending.shadow.html41
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite-expected.html51
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite.html38
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite.shadow-expected.html54
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite.shadow.html41
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.html37
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.shadow-expected.html53
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.shadow.html40
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending-expected.html50
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.html37
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.shadow-expected.html53
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.shadow.html40
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite-expected.html50
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.html37
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.shadow-expected.html53
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.shadow.html40
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-global-states-expected.html50
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-global-states.html37
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.shadow-expected.html52
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.shadow.html39
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-global-states-expected.html31
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-global-states.html34
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.shadow-expected.html33
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.shadow.html36
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.nested-expected.html37
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.nested.html36
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.createImageBitmap-expected.html32
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.createImageBitmap.html32
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.drawImage-expected.html32
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.drawImage.html34
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.getImageData-expected.html32
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.getImageData.html32
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.putImageData-expected.html32
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.putImageData.html34
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.requestAnimationFrame-expected.html35
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.requestAnimationFrame.html35
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.toBlob-expected.html35
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.toBlob.html35
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.toDataURL-expected.html32
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.toDataURL.html32
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.restore-style-expected.html24
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.restore-style.html25
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.several-complex-expected.html34
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.several-complex.html34
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.unclosed-expected.html23
-rw-r--r--testing/web-platform/tests/html/canvas/element/layers/2d.layer.unclosed.html22
74 files changed, 2704 insertions, 0 deletions
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.endlayer.alone-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.endlayer.alone-expected.html
new file mode 100644
index 0000000000..607526e437
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.endlayer.alone-expected.html
@@ -0,0 +1,21 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.endlayer.alone</title>
+<h1>2d.layer.endlayer.alone</h1>
+<p class="desc">A test to make sure a single endLayer with no beginLayer is a no-op.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+ ctx.fillRect(60, 60, 75, 50);
+ ctx.globalAlpha = 0.5;
+
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.endlayer.alone.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.endlayer.alone.html
new file mode 100644
index 0000000000..a7a5933b33
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.endlayer.alone.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.endlayer.alone-expected.html">
+<title>Canvas test: 2d.layer.endlayer.alone</title>
+<h1>2d.layer.endlayer.alone</h1>
+<p class="desc">A test to make sure a single endLayer with no beginLayer is a no-op.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+ ctx.fillRect(60, 60, 75, 50);
+ ctx.globalAlpha = 0.5;
+
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.endlayer.unmatched-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.endlayer.unmatched-expected.html
new file mode 100644
index 0000000000..e6dd85b7e2
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.endlayer.unmatched-expected.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.endlayer.unmatched</title>
+<h1>2d.layer.endlayer.unmatched</h1>
+<p class="desc">A test to make sure an unmatched endLayer is a no-op and has no effect on the code following it.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+ ctx.fillRect(60, 60, 75, 50);
+
+ ctx.globalAlpha = 0.5;
+
+ ctx.beginLayer();
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.endlayer.unmatched.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.endlayer.unmatched.html
new file mode 100644
index 0000000000..5f53983232
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.endlayer.unmatched.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.endlayer.unmatched-expected.html">
+<title>Canvas test: 2d.layer.endlayer.unmatched</title>
+<h1>2d.layer.endlayer.unmatched</h1>
+<p class="desc">A test to make sure an unmatched endLayer is a no-op and has no effect on the code following it.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+ ctx.fillRect(60, 60, 75, 50);
+
+ ctx.globalAlpha = 0.5;
+
+ // This endlayer call should no-op.
+ ctx.endLayer();
+
+ ctx.beginLayer();
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha-expected.html
new file mode 100644
index 0000000000..0666e3098a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha-expected.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.alpha</title>
+<h1>2d.layer.global-states.alpha</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending-expected.html
new file mode 100644
index 0000000000..8a45027588
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending-expected.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.alpha.blending</title>
+<h1>2d.layer.global-states.alpha.blending</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'multiply';
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending.html
new file mode 100644
index 0000000000..8e15a2b936
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.alpha.blending-expected.html">
+<title>Canvas test: 2d.layer.global-states.alpha.blending</title>
+<h1>2d.layer.global-states.alpha.blending</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'multiply';
+
+ ctx.beginLayer();
+
+ // Enable compositing in the layer to validate that draw calls in the layer
+ // won't individually composite with the background.
+ ctx.globalCompositeOperation = 'screen';
+
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending.shadow-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending.shadow-expected.html
new file mode 100644
index 0000000000..d7ba158d16
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending.shadow-expected.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.alpha.blending.shadow</title>
+<h1>2d.layer.global-states.alpha.blending.shadow</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending.shadow.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending.shadow.html
new file mode 100644
index 0000000000..22946174cd
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.blending.shadow.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.alpha.blending.shadow-expected.html">
+<title>Canvas test: 2d.layer.global-states.alpha.blending.shadow</title>
+<h1>2d.layer.global-states.alpha.blending.shadow</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ // Enable compositing in the layer to validate that draw calls in the layer
+ // won't individually composite with the background.
+ ctx.globalCompositeOperation = 'screen';
+
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite-expected.html
new file mode 100644
index 0000000000..951049e638
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite-expected.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.alpha.composite</title>
+<h1>2d.layer.global-states.alpha.composite</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'source-in';
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite.html
new file mode 100644
index 0000000000..1ac6a2cbfe
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.alpha.composite-expected.html">
+<title>Canvas test: 2d.layer.global-states.alpha.composite</title>
+<h1>2d.layer.global-states.alpha.composite</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'source-in';
+
+ ctx.beginLayer();
+
+ // Enable compositing in the layer to validate that draw calls in the layer
+ // won't individually composite with the background.
+ ctx.globalCompositeOperation = 'screen';
+
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite.shadow-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite.shadow-expected.html
new file mode 100644
index 0000000000..a669a2271e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite.shadow-expected.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.alpha.composite.shadow</title>
+<h1>2d.layer.global-states.alpha.composite.shadow</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite.shadow.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite.shadow.html
new file mode 100644
index 0000000000..c07e717a66
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.composite.shadow.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.alpha.composite.shadow-expected.html">
+<title>Canvas test: 2d.layer.global-states.alpha.composite.shadow</title>
+<h1>2d.layer.global-states.alpha.composite.shadow</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ // Enable compositing in the layer to validate that draw calls in the layer
+ // won't individually composite with the background.
+ ctx.globalCompositeOperation = 'screen';
+
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.html
new file mode 100644
index 0000000000..829796acbf
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.alpha-expected.html">
+<title>Canvas test: 2d.layer.global-states.alpha</title>
+<h1>2d.layer.global-states.alpha</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+
+ ctx.beginLayer();
+
+ // Enable compositing in the layer to validate that draw calls in the layer
+ // won't individually composite with the background.
+ ctx.globalCompositeOperation = 'screen';
+
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.shadow-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.shadow-expected.html
new file mode 100644
index 0000000000..206eb75013
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.shadow-expected.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.alpha.shadow</title>
+<h1>2d.layer.global-states.alpha.shadow</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.5;
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.shadow.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.shadow.html
new file mode 100644
index 0000000000..bcb7fe5096
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.alpha.shadow.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.alpha.shadow-expected.html">
+<title>Canvas test: 2d.layer.global-states.alpha.shadow</title>
+<h1>2d.layer.global-states.alpha.shadow</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.5;
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ // Enable compositing in the layer to validate that draw calls in the layer
+ // won't individually composite with the background.
+ ctx.globalCompositeOperation = 'screen';
+
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending-expected.html
new file mode 100644
index 0000000000..33fdf46a28
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending-expected.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.blending</title>
+<h1>2d.layer.global-states.blending</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'multiply';
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.html
new file mode 100644
index 0000000000..7d4d9ae4b5
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.blending-expected.html">
+<title>Canvas test: 2d.layer.global-states.blending</title>
+<h1>2d.layer.global-states.blending</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'multiply';
+
+ ctx.beginLayer();
+
+ // Enable compositing in the layer to validate that draw calls in the layer
+ // won't individually composite with the background.
+ ctx.globalCompositeOperation = 'screen';
+
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.shadow-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.shadow-expected.html
new file mode 100644
index 0000000000..02275c8cc2
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.shadow-expected.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.blending.shadow</title>
+<h1>2d.layer.global-states.blending.shadow</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.shadow.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.shadow.html
new file mode 100644
index 0000000000..80f414d4ee
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.blending.shadow.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.blending.shadow-expected.html">
+<title>Canvas test: 2d.layer.global-states.blending.shadow</title>
+<h1>2d.layer.global-states.blending.shadow</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ // Enable compositing in the layer to validate that draw calls in the layer
+ // won't individually composite with the background.
+ ctx.globalCompositeOperation = 'screen';
+
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite-expected.html
new file mode 100644
index 0000000000..ed7669c4cf
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite-expected.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.composite</title>
+<h1>2d.layer.global-states.composite</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'source-in';
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.html
new file mode 100644
index 0000000000..898d149924
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.composite-expected.html">
+<title>Canvas test: 2d.layer.global-states.composite</title>
+<h1>2d.layer.global-states.composite</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'source-in';
+
+ ctx.beginLayer();
+
+ // Enable compositing in the layer to validate that draw calls in the layer
+ // won't individually composite with the background.
+ ctx.globalCompositeOperation = 'screen';
+
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.shadow-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.shadow-expected.html
new file mode 100644
index 0000000000..e380cccab8
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.shadow-expected.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.composite.shadow</title>
+<h1>2d.layer.global-states.composite.shadow</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.shadow.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.shadow.html
new file mode 100644
index 0000000000..9e32dddd40
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.composite.shadow.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.composite.shadow-expected.html">
+<title>Canvas test: 2d.layer.global-states.composite.shadow</title>
+<h1>2d.layer.global-states.composite.shadow</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ // Enable compositing in the layer to validate that draw calls in the layer
+ // won't individually composite with the background.
+ ctx.globalCompositeOperation = 'screen';
+
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha-expected.html
new file mode 100644
index 0000000000..f304700feb
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha-expected.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.alpha</title>
+<h1>2d.layer.global-states.filter.alpha</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending-expected.html
new file mode 100644
index 0000000000..7c91ce4229
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending-expected.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.alpha.blending</title>
+<h1>2d.layer.global-states.filter.alpha.blending</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'multiply';
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending.html
new file mode 100644
index 0000000000..6f92e6d33f
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.filter.alpha.blending-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.alpha.blending</title>
+<h1>2d.layer.global-states.filter.alpha.blending</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'multiply';
+
+ ctx.beginLayer([
+ {filter: 'colorMatrix', values: [0.393, 0.769, 0.189, 0, 0,
+ 0.349, 0.686, 0.168, 0, 0,
+ 0.272, 0.534, 0.131, 0, 0,
+ 0, 0, 0, 1, 0]},
+ {filter: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.7]}},
+ {filter: 'dropShadow', dx: 5, dy: 5, floodColor: '#81e'}]);
+
+ ctx.fillStyle = 'rgba(200, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 200, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending.shadow-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending.shadow-expected.html
new file mode 100644
index 0000000000..d9c93719b9
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending.shadow-expected.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.alpha.blending.shadow</title>
+<h1>2d.layer.global-states.filter.alpha.blending.shadow</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending.shadow.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending.shadow.html
new file mode 100644
index 0000000000..68bdee684d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.blending.shadow.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.filter.alpha.blending.shadow-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.alpha.blending.shadow</title>
+<h1>2d.layer.global-states.filter.alpha.blending.shadow</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer([
+ {filter: 'colorMatrix', values: [0.393, 0.769, 0.189, 0, 0,
+ 0.349, 0.686, 0.168, 0, 0,
+ 0.272, 0.534, 0.131, 0, 0,
+ 0, 0, 0, 1, 0]},
+ {filter: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.7]}},
+ {filter: 'dropShadow', dx: 5, dy: 5, floodColor: '#81e'}]);
+
+ ctx.fillStyle = 'rgba(200, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 200, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite-expected.html
new file mode 100644
index 0000000000..8e0d98648e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite-expected.html
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.alpha.composite</title>
+<h1>2d.layer.global-states.filter.alpha.composite</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'source-in';
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite.html
new file mode 100644
index 0000000000..72282d6559
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite.html
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.filter.alpha.composite-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.alpha.composite</title>
+<h1>2d.layer.global-states.filter.alpha.composite</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'source-in';
+
+ ctx.beginLayer([
+ {filter: 'colorMatrix', values: [0.393, 0.769, 0.189, 0, 0,
+ 0.349, 0.686, 0.168, 0, 0,
+ 0.272, 0.534, 0.131, 0, 0,
+ 0, 0, 0, 1, 0]},
+ {filter: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.7]}},
+ {filter: 'dropShadow', dx: 5, dy: 5, floodColor: '#81e'}]);
+
+ ctx.fillStyle = 'rgba(200, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 200, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite.shadow-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite.shadow-expected.html
new file mode 100644
index 0000000000..26d13a4cae
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite.shadow-expected.html
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.alpha.composite.shadow</title>
+<h1>2d.layer.global-states.filter.alpha.composite.shadow</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite.shadow.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite.shadow.html
new file mode 100644
index 0000000000..71c99dba35
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.composite.shadow.html
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.filter.alpha.composite.shadow-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.alpha.composite.shadow</title>
+<h1>2d.layer.global-states.filter.alpha.composite.shadow</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer([
+ {filter: 'colorMatrix', values: [0.393, 0.769, 0.189, 0, 0,
+ 0.349, 0.686, 0.168, 0, 0,
+ 0.272, 0.534, 0.131, 0, 0,
+ 0, 0, 0, 1, 0]},
+ {filter: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.7]}},
+ {filter: 'dropShadow', dx: 5, dy: 5, floodColor: '#81e'}]);
+
+ ctx.fillStyle = 'rgba(200, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 200, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.html
new file mode 100644
index 0000000000..9e687bcaf8
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.filter.alpha-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.alpha</title>
+<h1>2d.layer.global-states.filter.alpha</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.6;
+
+ ctx.beginLayer([
+ {filter: 'colorMatrix', values: [0.393, 0.769, 0.189, 0, 0,
+ 0.349, 0.686, 0.168, 0, 0,
+ 0.272, 0.534, 0.131, 0, 0,
+ 0, 0, 0, 1, 0]},
+ {filter: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.7]}},
+ {filter: 'dropShadow', dx: 5, dy: 5, floodColor: '#81e'}]);
+
+ ctx.fillStyle = 'rgba(200, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 200, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.shadow-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.shadow-expected.html
new file mode 100644
index 0000000000..9cc735fd42
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.shadow-expected.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.alpha.shadow</title>
+<h1>2d.layer.global-states.filter.alpha.shadow</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.5;
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.shadow.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.shadow.html
new file mode 100644
index 0000000000..a9564c44a7
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.alpha.shadow.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.filter.alpha.shadow-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.alpha.shadow</title>
+<h1>2d.layer.global-states.filter.alpha.shadow</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalAlpha = 0.5;
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer([
+ {filter: 'colorMatrix', values: [0.393, 0.769, 0.189, 0, 0,
+ 0.349, 0.686, 0.168, 0, 0,
+ 0.272, 0.534, 0.131, 0, 0,
+ 0, 0, 0, 1, 0]},
+ {filter: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.7]}},
+ {filter: 'dropShadow', dx: 5, dy: 5, floodColor: '#81e'}]);
+
+ ctx.fillStyle = 'rgba(200, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 200, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending-expected.html
new file mode 100644
index 0000000000..f81dcf72dc
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending-expected.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.blending</title>
+<h1>2d.layer.global-states.filter.blending</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'multiply';
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.html
new file mode 100644
index 0000000000..a812563398
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.filter.blending-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.blending</title>
+<h1>2d.layer.global-states.filter.blending</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'multiply';
+
+ ctx.beginLayer([
+ {filter: 'colorMatrix', values: [0.393, 0.769, 0.189, 0, 0,
+ 0.349, 0.686, 0.168, 0, 0,
+ 0.272, 0.534, 0.131, 0, 0,
+ 0, 0, 0, 1, 0]},
+ {filter: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.7]}},
+ {filter: 'dropShadow', dx: 5, dy: 5, floodColor: '#81e'}]);
+
+ ctx.fillStyle = 'rgba(200, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 200, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.shadow-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.shadow-expected.html
new file mode 100644
index 0000000000..a48485f7e8
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.shadow-expected.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.blending.shadow</title>
+<h1>2d.layer.global-states.filter.blending.shadow</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.shadow.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.shadow.html
new file mode 100644
index 0000000000..bf30126ff2
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.blending.shadow.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.filter.blending.shadow-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.blending.shadow</title>
+<h1>2d.layer.global-states.filter.blending.shadow</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'multiply';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer([
+ {filter: 'colorMatrix', values: [0.393, 0.769, 0.189, 0, 0,
+ 0.349, 0.686, 0.168, 0, 0,
+ 0.272, 0.534, 0.131, 0, 0,
+ 0, 0, 0, 1, 0]},
+ {filter: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.7]}},
+ {filter: 'dropShadow', dx: 5, dy: 5, floodColor: '#81e'}]);
+
+ ctx.fillStyle = 'rgba(200, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 200, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite-expected.html
new file mode 100644
index 0000000000..97e85a1593
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite-expected.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.composite</title>
+<h1>2d.layer.global-states.filter.composite</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'source-in';
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.html
new file mode 100644
index 0000000000..a2636d8525
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.filter.composite-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.composite</title>
+<h1>2d.layer.global-states.filter.composite</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'source-in';
+
+ ctx.beginLayer([
+ {filter: 'colorMatrix', values: [0.393, 0.769, 0.189, 0, 0,
+ 0.349, 0.686, 0.168, 0, 0,
+ 0.272, 0.534, 0.131, 0, 0,
+ 0, 0, 0, 1, 0]},
+ {filter: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.7]}},
+ {filter: 'dropShadow', dx: 5, dy: 5, floodColor: '#81e'}]);
+
+ ctx.fillStyle = 'rgba(200, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 200, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.shadow-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.shadow-expected.html
new file mode 100644
index 0000000000..79191ee391
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.shadow-expected.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.composite.shadow</title>
+<h1>2d.layer.global-states.filter.composite.shadow</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.shadow.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.shadow.html
new file mode 100644
index 0000000000..85b83b59b9
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.composite.shadow.html
@@ -0,0 +1,40 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.filter.composite.shadow-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.composite.shadow</title>
+<h1>2d.layer.global-states.filter.composite.shadow</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'source-in';
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer([
+ {filter: 'colorMatrix', values: [0.393, 0.769, 0.189, 0, 0,
+ 0.349, 0.686, 0.168, 0, 0,
+ 0.272, 0.534, 0.131, 0, 0,
+ 0, 0, 0, 1, 0]},
+ {filter: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.7]}},
+ {filter: 'dropShadow', dx: 5, dy: 5, floodColor: '#81e'}]);
+
+ ctx.fillStyle = 'rgba(200, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 200, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-global-states-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-global-states-expected.html
new file mode 100644
index 0000000000..e56fe0b360
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-global-states-expected.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.no-global-states</title>
+<h1>2d.layer.global-states.filter.no-global-states</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ // No global states.
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-global-states.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-global-states.html
new file mode 100644
index 0000000000..af495b21cd
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.no-global-states.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.filter.no-global-states-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.no-global-states</title>
+<h1>2d.layer.global-states.filter.no-global-states</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ // No global states.
+
+ ctx.beginLayer([
+ {filter: 'colorMatrix', values: [0.393, 0.769, 0.189, 0, 0,
+ 0.349, 0.686, 0.168, 0, 0,
+ 0.272, 0.534, 0.131, 0, 0,
+ 0, 0, 0, 1, 0]},
+ {filter: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.7]}},
+ {filter: 'dropShadow', dx: 5, dy: 5, floodColor: '#81e'}]);
+
+ ctx.fillStyle = 'rgba(200, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 200, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.shadow-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.shadow-expected.html
new file mode 100644
index 0000000000..59cf16fa87
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.shadow-expected.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.filter.shadow</title>
+<h1>2d.layer.global-states.filter.shadow</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ const svg = `
+ <svg xmlns="http://www.w3.org/2000/svg"
+ width="200" height="200"
+ color-interpolation-filters="sRGB">
+ <filter id="filter" x="-100%" y="-100%" width="300%" height="300%">
+ <feColorMatrix
+ type="matrix"
+ values="0.393 0.769 0.189 0 0
+ 0.349 0.686 0.168 0 0
+ 0.272 0.534 0.131 0 0
+ 0 0 0 1 0" />
+ <feComponentTransfer>
+ <feFuncA type="table" tableValues="0 0.7"></feFuncA>
+ </feComponentTransfer>
+ <feDropShadow dx="5" dy="5" flood-color="#81e" />
+ </filter>
+ <g filter="url(#filter)">
+ <rect x="50" y="50" width="75" height="50" fill="rgba(200, 0, 0, 1)"/>
+ <rect x="70" y="70" width="75" height="50" fill="rgba(0, 200, 0, 1)"/>
+ </g>
+ </svg>`;
+
+ const img = new Image();
+ img.width = 200;
+ img.height = 200;
+ img.onload = () => {
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.drawImage(img, 0, 0);
+ };
+ img.src = 'data:image/svg+xml;base64,' + btoa(svg);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.shadow.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.shadow.html
new file mode 100644
index 0000000000..2c692d6db7
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.filter.shadow.html
@@ -0,0 +1,39 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.filter.shadow-expected.html">
+<title>Canvas test: 2d.layer.global-states.filter.shadow</title>
+<h1>2d.layer.global-states.filter.shadow</h1>
+<p class="desc">Checks that layers with filters correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer([
+ {filter: 'colorMatrix', values: [0.393, 0.769, 0.189, 0, 0,
+ 0.349, 0.686, 0.168, 0, 0,
+ 0.272, 0.534, 0.131, 0, 0,
+ 0, 0, 0, 1, 0]},
+ {filter: 'componentTransfer',
+ funcA: {type: "table", tableValues: [0, 0.7]}},
+ {filter: 'dropShadow', dx: 5, dy: 5, floodColor: '#81e'}]);
+
+ ctx.fillStyle = 'rgba(200, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 200, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-global-states-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-global-states-expected.html
new file mode 100644
index 0000000000..b91a2ae8b5
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-global-states-expected.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.no-global-states</title>
+<h1>2d.layer.global-states.no-global-states</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ // No global states.
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-global-states.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-global-states.html
new file mode 100644
index 0000000000..d561be2341
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.no-global-states.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.no-global-states-expected.html">
+<title>Canvas test: 2d.layer.global-states.no-global-states</title>
+<h1>2d.layer.global-states.no-global-states</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ // No global states.
+
+ ctx.beginLayer();
+
+ // Enable compositing in the layer to validate that draw calls in the layer
+ // won't individually composite with the background.
+ ctx.globalCompositeOperation = 'screen';
+
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.shadow-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.shadow-expected.html
new file mode 100644
index 0000000000..ba56644d6c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.shadow-expected.html
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.global-states.shadow</title>
+<h1>2d.layer.global-states.shadow</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.globalCompositeOperation = 'screen';
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(50, 50, 75, 50);
+ ctx2.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2.fillRect(70, 70, 75, 50);
+
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.shadow.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.shadow.html
new file mode 100644
index 0000000000..bd9e868d1e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.global-states.shadow.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.global-states.shadow-expected.html">
+<title>Canvas test: 2d.layer.global-states.shadow</title>
+<h1>2d.layer.global-states.shadow</h1>
+<p class="desc">Checks that layers correctly use global render states.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 45, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'rgba(255, 165, 0, 0.5)';
+
+ ctx.beginLayer();
+
+ // Enable compositing in the layer to validate that draw calls in the layer
+ // won't individually composite with the background.
+ ctx.globalCompositeOperation = 'screen';
+
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.nested-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.nested-expected.html
new file mode 100644
index 0000000000..65525d4d6a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.nested-expected.html
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.nested</title>
+<h1>2d.layer.nested</h1>
+<p class="desc">Tests nested canvas layers.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 40, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'source-in';
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+
+ ctx2.fillStyle = 'rgba(0, 0, 255, 1)';
+ ctx2.fillRect(60, 60, 75, 50);
+
+ ctx2.globalAlpha = 0.5;
+
+ canvas3 = document.createElement("canvas");
+ ctx3 = canvas3.getContext("2d");
+
+ ctx3.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx3.fillRect(50, 50, 75, 50);
+ ctx3.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx3.fillRect(70, 70, 75, 50);
+
+ ctx2.drawImage(canvas3, 0, 0);
+ ctx.drawImage(canvas2, 0, 0);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.nested.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.nested.html
new file mode 100644
index 0000000000..a508d8e5c8
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.nested.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.nested-expected.html">
+<title>Canvas test: 2d.layer.nested</title>
+<h1>2d.layer.nested</h1>
+<p class="desc">Tests nested canvas layers.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ var circle = new Path2D();
+ circle.arc(90, 90, 40, 0, 2 * Math.PI);
+ ctx.fill(circle);
+
+ ctx.globalCompositeOperation = 'source-in';
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+ ctx.fillRect(60, 60, 75, 50);
+
+ ctx.globalAlpha = 0.5;
+
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(70, 70, 75, 50);
+
+ ctx.endLayer();
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.createImageBitmap-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.createImageBitmap-expected.html
new file mode 100644
index 0000000000..8ce0c51e8e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.createImageBitmap-expected.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.render-opportunities.createImageBitmap</title>
+<h1>2d.layer.render-opportunities.createImageBitmap</h1>
+<p class="desc">Check that layers state stack is flushed and rebuilt on frame renders.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'purple';
+ ctx.fillRect(60, 60, 75, 50);
+ ctx.globalAlpha = 0.5;
+
+ ctx.beginLayer({filter: 'dropShadow', dx: -2, dy: 2});
+ ctx.fillStyle = 'purple';
+ ctx.fillRect(40, 40, 75, 50);
+ ctx.fillStyle = 'grey';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.endLayer();
+
+ ctx.beginLayer({filter: 'dropShadow', dx: -2, dy: 2});
+ ctx.fillStyle = 'grey';
+ ctx.fillRect(70, 70, 75, 50);
+ ctx.fillStyle = 'orange';
+ ctx.fillRect(80, 80, 75, 50);
+ ctx.endLayer();
+
+ ctx.fillRect(80, 40, 75, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.createImageBitmap.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.createImageBitmap.html
new file mode 100644
index 0000000000..4ffcaa3e3c
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.createImageBitmap.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.render-opportunities.createImageBitmap-expected.html">
+<title>Canvas test: 2d.layer.render-opportunities.createImageBitmap</title>
+<h1>2d.layer.render-opportunities.createImageBitmap</h1>
+<p class="desc">Check that layers state stack is flushed and rebuilt on frame renders.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'purple';
+ ctx.fillRect(60, 60, 75, 50);
+ ctx.globalAlpha = 0.5;
+
+ ctx.beginLayer({filter: 'dropShadow', dx: -2, dy: 2});
+ ctx.fillRect(40, 40, 75, 50);
+ ctx.fillStyle = 'grey';
+ ctx.fillRect(50, 50, 75, 50);
+
+ // Force a flush and restoration of the state stack:
+ createImageBitmap(canvas);
+
+ ctx.fillRect(70, 70, 75, 50);
+ ctx.fillStyle = 'orange';
+ ctx.fillRect(80, 80, 75, 50);
+ ctx.endLayer();
+
+ ctx.fillRect(80, 40, 75, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.drawImage-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.drawImage-expected.html
new file mode 100644
index 0000000000..1ddc6d1b44
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.drawImage-expected.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.render-opportunities.drawImage</title>
+<h1>2d.layer.render-opportunities.drawImage</h1>
+<p class="desc">Check that layers state stack is flushed and rebuilt on frame renders.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'purple';
+ ctx.fillRect(60, 60, 75, 50);
+ ctx.globalAlpha = 0.5;
+
+ ctx.beginLayer({filter: 'dropShadow', dx: -2, dy: 2});
+ ctx.fillStyle = 'purple';
+ ctx.fillRect(40, 40, 75, 50);
+ ctx.fillStyle = 'grey';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.endLayer();
+
+ ctx.beginLayer({filter: 'dropShadow', dx: -2, dy: 2});
+ ctx.fillStyle = 'grey';
+ ctx.fillRect(70, 70, 75, 50);
+ ctx.fillStyle = 'orange';
+ ctx.fillRect(80, 80, 75, 50);
+ ctx.endLayer();
+
+ ctx.fillRect(80, 40, 75, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.drawImage.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.drawImage.html
new file mode 100644
index 0000000000..4eb0b6f721
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.drawImage.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.render-opportunities.drawImage-expected.html">
+<title>Canvas test: 2d.layer.render-opportunities.drawImage</title>
+<h1>2d.layer.render-opportunities.drawImage</h1>
+<p class="desc">Check that layers state stack is flushed and rebuilt on frame renders.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'purple';
+ ctx.fillRect(60, 60, 75, 50);
+ ctx.globalAlpha = 0.5;
+
+ ctx.beginLayer({filter: 'dropShadow', dx: -2, dy: 2});
+ ctx.fillRect(40, 40, 75, 50);
+ ctx.fillStyle = 'grey';
+ ctx.fillRect(50, 50, 75, 50);
+
+ // Force a flush and restoration of the state stack:
+ const canvas2 = new OffscreenCanvas(200, 200);
+ const ctx2 = canvas2.getContext('2d');
+ ctx2.drawImage(canvas, 0, 0);
+
+ ctx.fillRect(70, 70, 75, 50);
+ ctx.fillStyle = 'orange';
+ ctx.fillRect(80, 80, 75, 50);
+ ctx.endLayer();
+
+ ctx.fillRect(80, 40, 75, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.getImageData-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.getImageData-expected.html
new file mode 100644
index 0000000000..ea0e78e0f2
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.getImageData-expected.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.render-opportunities.getImageData</title>
+<h1>2d.layer.render-opportunities.getImageData</h1>
+<p class="desc">Check that layers state stack is flushed and rebuilt on frame renders.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'purple';
+ ctx.fillRect(60, 60, 75, 50);
+ ctx.globalAlpha = 0.5;
+
+ ctx.beginLayer({filter: 'dropShadow', dx: -2, dy: 2});
+ ctx.fillStyle = 'purple';
+ ctx.fillRect(40, 40, 75, 50);
+ ctx.fillStyle = 'grey';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.endLayer();
+
+ ctx.beginLayer({filter: 'dropShadow', dx: -2, dy: 2});
+ ctx.fillStyle = 'grey';
+ ctx.fillRect(70, 70, 75, 50);
+ ctx.fillStyle = 'orange';
+ ctx.fillRect(80, 80, 75, 50);
+ ctx.endLayer();
+
+ ctx.fillRect(80, 40, 75, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.getImageData.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.getImageData.html
new file mode 100644
index 0000000000..3cf514a03f
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.getImageData.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.render-opportunities.getImageData-expected.html">
+<title>Canvas test: 2d.layer.render-opportunities.getImageData</title>
+<h1>2d.layer.render-opportunities.getImageData</h1>
+<p class="desc">Check that layers state stack is flushed and rebuilt on frame renders.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'purple';
+ ctx.fillRect(60, 60, 75, 50);
+ ctx.globalAlpha = 0.5;
+
+ ctx.beginLayer({filter: 'dropShadow', dx: -2, dy: 2});
+ ctx.fillRect(40, 40, 75, 50);
+ ctx.fillStyle = 'grey';
+ ctx.fillRect(50, 50, 75, 50);
+
+ // Force a flush and restoration of the state stack:
+ ctx.getImageData(0, 0, 200, 200);
+
+ ctx.fillRect(70, 70, 75, 50);
+ ctx.fillStyle = 'orange';
+ ctx.fillRect(80, 80, 75, 50);
+ ctx.endLayer();
+
+ ctx.fillRect(80, 40, 75, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.putImageData-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.putImageData-expected.html
new file mode 100644
index 0000000000..3d63bbe776
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.putImageData-expected.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.render-opportunities.putImageData</title>
+<h1>2d.layer.render-opportunities.putImageData</h1>
+<p class="desc">Check that layers state stack is flushed and rebuilt on frame renders.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'purple';
+ ctx.fillRect(60, 60, 75, 50);
+ ctx.globalAlpha = 0.5;
+
+ ctx.beginLayer({filter: 'dropShadow', dx: -2, dy: 2});
+ ctx.fillStyle = 'purple';
+ ctx.fillRect(40, 40, 75, 50);
+ ctx.fillStyle = 'grey';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.endLayer();
+
+ ctx.beginLayer({filter: 'dropShadow', dx: -2, dy: 2});
+ ctx.fillStyle = 'grey';
+ ctx.fillRect(70, 70, 75, 50);
+ ctx.fillStyle = 'orange';
+ ctx.fillRect(80, 80, 75, 50);
+ ctx.endLayer();
+
+ ctx.fillRect(80, 40, 75, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.putImageData.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.putImageData.html
new file mode 100644
index 0000000000..8da3dafbb7
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.putImageData.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.render-opportunities.putImageData-expected.html">
+<title>Canvas test: 2d.layer.render-opportunities.putImageData</title>
+<h1>2d.layer.render-opportunities.putImageData</h1>
+<p class="desc">Check that layers state stack is flushed and rebuilt on frame renders.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'purple';
+ ctx.fillRect(60, 60, 75, 50);
+ ctx.globalAlpha = 0.5;
+
+ ctx.beginLayer({filter: 'dropShadow', dx: -2, dy: 2});
+ ctx.fillRect(40, 40, 75, 50);
+ ctx.fillStyle = 'grey';
+ ctx.fillRect(50, 50, 75, 50);
+
+ // Force a flush and restoration of the state stack:
+ const canvas2 = new OffscreenCanvas(200, 200);
+ const ctx2 = canvas2.getContext('2d');
+ ctx.putImageData(ctx2.getImageData(0, 0, 1, 1), 0, 0);
+
+ ctx.fillRect(70, 70, 75, 50);
+ ctx.fillStyle = 'orange';
+ ctx.fillRect(80, 80, 75, 50);
+ ctx.endLayer();
+
+ ctx.fillRect(80, 40, 75, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.requestAnimationFrame-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.requestAnimationFrame-expected.html
new file mode 100644
index 0000000000..138f3a7ccb
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.requestAnimationFrame-expected.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<html class="reftest-wait">
+<title>Canvas test: 2d.layer.render-opportunities.requestAnimationFrame</title>
+<h1>2d.layer.render-opportunities.requestAnimationFrame</h1>
+<p class="desc">Check that layers state stack is flushed and rebuilt on frame renders.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script type="module">
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'purple';
+ ctx.fillRect(60, 60, 75, 50);
+ ctx.globalAlpha = 0.5;
+
+ ctx.beginLayer({filter: 'dropShadow', dx: -2, dy: 2});
+ ctx.fillStyle = 'purple';
+ ctx.fillRect(40, 40, 75, 50);
+ ctx.fillStyle = 'grey';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.endLayer();
+
+ ctx.beginLayer({filter: 'dropShadow', dx: -2, dy: 2});
+ ctx.fillStyle = 'grey';
+ ctx.fillRect(70, 70, 75, 50);
+ ctx.fillStyle = 'orange';
+ ctx.fillRect(80, 80, 75, 50);
+ ctx.endLayer();
+
+ ctx.fillRect(80, 40, 75, 50);
+ document.documentElement.classList.remove("reftest-wait");
+</script>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.requestAnimationFrame.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.requestAnimationFrame.html
new file mode 100644
index 0000000000..889ff5ba09
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.requestAnimationFrame.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<html class="reftest-wait">
+<link rel="match" href="2d.layer.render-opportunities.requestAnimationFrame-expected.html">
+<title>Canvas test: 2d.layer.render-opportunities.requestAnimationFrame</title>
+<h1>2d.layer.render-opportunities.requestAnimationFrame</h1>
+<p class="desc">Check that layers state stack is flushed and rebuilt on frame renders.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script type="module">
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'purple';
+ ctx.fillRect(60, 60, 75, 50);
+ ctx.globalAlpha = 0.5;
+
+ ctx.beginLayer({filter: 'dropShadow', dx: -2, dy: 2});
+ ctx.fillRect(40, 40, 75, 50);
+ ctx.fillStyle = 'grey';
+ ctx.fillRect(50, 50, 75, 50);
+
+ // Force a flush and restoration of the state stack:
+ await new Promise(resolve => requestAnimationFrame(resolve));
+
+ ctx.fillRect(70, 70, 75, 50);
+ ctx.fillStyle = 'orange';
+ ctx.fillRect(80, 80, 75, 50);
+ ctx.endLayer();
+
+ ctx.fillRect(80, 40, 75, 50);
+ document.documentElement.classList.remove("reftest-wait");
+</script>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.toBlob-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.toBlob-expected.html
new file mode 100644
index 0000000000..fda8e8d7c6
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.toBlob-expected.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<html class="reftest-wait">
+<title>Canvas test: 2d.layer.render-opportunities.toBlob</title>
+<h1>2d.layer.render-opportunities.toBlob</h1>
+<p class="desc">Check that layers state stack is flushed and rebuilt on frame renders.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script type="module">
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'purple';
+ ctx.fillRect(60, 60, 75, 50);
+ ctx.globalAlpha = 0.5;
+
+ ctx.beginLayer({filter: 'dropShadow', dx: -2, dy: 2});
+ ctx.fillStyle = 'purple';
+ ctx.fillRect(40, 40, 75, 50);
+ ctx.fillStyle = 'grey';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.endLayer();
+
+ ctx.beginLayer({filter: 'dropShadow', dx: -2, dy: 2});
+ ctx.fillStyle = 'grey';
+ ctx.fillRect(70, 70, 75, 50);
+ ctx.fillStyle = 'orange';
+ ctx.fillRect(80, 80, 75, 50);
+ ctx.endLayer();
+
+ ctx.fillRect(80, 40, 75, 50);
+ document.documentElement.classList.remove("reftest-wait");
+</script>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.toBlob.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.toBlob.html
new file mode 100644
index 0000000000..908730424a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.toBlob.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<html class="reftest-wait">
+<link rel="match" href="2d.layer.render-opportunities.toBlob-expected.html">
+<title>Canvas test: 2d.layer.render-opportunities.toBlob</title>
+<h1>2d.layer.render-opportunities.toBlob</h1>
+<p class="desc">Check that layers state stack is flushed and rebuilt on frame renders.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script type="module">
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'purple';
+ ctx.fillRect(60, 60, 75, 50);
+ ctx.globalAlpha = 0.5;
+
+ ctx.beginLayer({filter: 'dropShadow', dx: -2, dy: 2});
+ ctx.fillRect(40, 40, 75, 50);
+ ctx.fillStyle = 'grey';
+ ctx.fillRect(50, 50, 75, 50);
+
+ // Force a flush and restoration of the state stack:
+ await new Promise(resolve => canvas.toBlob(resolve));
+
+ ctx.fillRect(70, 70, 75, 50);
+ ctx.fillStyle = 'orange';
+ ctx.fillRect(80, 80, 75, 50);
+ ctx.endLayer();
+
+ ctx.fillRect(80, 40, 75, 50);
+ document.documentElement.classList.remove("reftest-wait");
+</script>
+</html> \ No newline at end of file
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.toDataURL-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.toDataURL-expected.html
new file mode 100644
index 0000000000..22a9770331
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.toDataURL-expected.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.render-opportunities.toDataURL</title>
+<h1>2d.layer.render-opportunities.toDataURL</h1>
+<p class="desc">Check that layers state stack is flushed and rebuilt on frame renders.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'purple';
+ ctx.fillRect(60, 60, 75, 50);
+ ctx.globalAlpha = 0.5;
+
+ ctx.beginLayer({filter: 'dropShadow', dx: -2, dy: 2});
+ ctx.fillStyle = 'purple';
+ ctx.fillRect(40, 40, 75, 50);
+ ctx.fillStyle = 'grey';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.endLayer();
+
+ ctx.beginLayer({filter: 'dropShadow', dx: -2, dy: 2});
+ ctx.fillStyle = 'grey';
+ ctx.fillRect(70, 70, 75, 50);
+ ctx.fillStyle = 'orange';
+ ctx.fillRect(80, 80, 75, 50);
+ ctx.endLayer();
+
+ ctx.fillRect(80, 40, 75, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.toDataURL.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.toDataURL.html
new file mode 100644
index 0000000000..152f66a12b
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.render-opportunities.toDataURL.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.render-opportunities.toDataURL-expected.html">
+<title>Canvas test: 2d.layer.render-opportunities.toDataURL</title>
+<h1>2d.layer.render-opportunities.toDataURL</h1>
+<p class="desc">Check that layers state stack is flushed and rebuilt on frame renders.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'purple';
+ ctx.fillRect(60, 60, 75, 50);
+ ctx.globalAlpha = 0.5;
+
+ ctx.beginLayer({filter: 'dropShadow', dx: -2, dy: 2});
+ ctx.fillRect(40, 40, 75, 50);
+ ctx.fillStyle = 'grey';
+ ctx.fillRect(50, 50, 75, 50);
+
+ // Force a flush and restoration of the state stack:
+ canvas.toDataURL();
+
+ ctx.fillRect(70, 70, 75, 50);
+ ctx.fillStyle = 'orange';
+ ctx.fillRect(80, 80, 75, 50);
+ ctx.endLayer();
+
+ ctx.fillRect(80, 40, 75, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.restore-style-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.restore-style-expected.html
new file mode 100644
index 0000000000..1d0ac3558d
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.restore-style-expected.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.restore-style</title>
+<h1>2d.layer.restore-style</h1>
+<p class="desc">Test that ensure layers restores style values upon endLayer.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.globalAlpha = 0.5;
+
+ canvas2 = document.createElement("canvas");
+ ctx2 = canvas2.getContext("2d");
+ ctx2.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2.fillRect(60, 60, 75, 50);
+ ctx.drawImage(canvas2, 0, 0);
+
+ ctx.fillRect(70, 70, 75, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.restore-style.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.restore-style.html
new file mode 100644
index 0000000000..2537f409d6
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.restore-style.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.restore-style-expected.html">
+<meta name=fuzzy content="maxDifference=0-1; totalPixels=0-950">
+<title>Canvas test: 2d.layer.restore-style</title>
+<h1>2d.layer.restore-style</h1>
+<p class="desc">Test that ensure layers restores style values upon endLayer.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0,0,255,1)';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.globalAlpha = 0.5;
+
+ ctx.beginLayer();
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(60, 60, 75, 50);
+ ctx.endLayer();
+
+ ctx.fillRect(70, 70, 75, 50);
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.several-complex-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.several-complex-expected.html
new file mode 100644
index 0000000000..84ad624474
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.several-complex-expected.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.several-complex</title>
+<h1>2d.layer.several-complex</h1>
+<p class="desc">Test to ensure beginlayer works for filter, alpha and shadow, even with consecutive layers.</p>
+<canvas id="canvas" width="500" height="500">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+ ctx.fillRect(50, 50, 95, 70);
+
+ ctx.globalAlpha = 0.5;
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'orange';
+
+ var canvas2 = [5];
+ var ctx2 = [5];
+
+ for (let i = 0; i < 5; i++) {
+ canvas2[i] = document.createElement("canvas");
+ ctx2[i] = canvas2[i].getContext("2d");
+ ctx2[i].fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx2[i].fillRect(60, 40, 75, 50);
+ ctx2[i].fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx2[i].fillRect(80, 60, 75, 50);
+
+ ctx.drawImage(canvas2[i], i, i);
+ }
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.several-complex.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.several-complex.html
new file mode 100644
index 0000000000..6ae78f690a
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.several-complex.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.several-complex-expected.html">
+<meta name=fuzzy content="maxDifference=0-3; totalPixels=0-6318">
+<title>Canvas test: 2d.layer.several-complex</title>
+<h1>2d.layer.several-complex</h1>
+<p class="desc">Test to ensure beginlayer works for filter, alpha and shadow, even with consecutive layers.</p>
+<canvas id="canvas" width="500" height="500">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'rgba(0, 0, 255, 1)';
+ ctx.fillRect(50, 50, 95, 70);
+
+ ctx.globalAlpha = 0.5;
+ ctx.shadowOffsetX = -10;
+ ctx.shadowOffsetY = 10;
+ ctx.shadowColor = 'orange';
+
+
+ for (let i = 0; i < 5; i++) {
+ ctx.beginLayer();
+
+ ctx.fillStyle = 'rgba(225, 0, 0, 1)';
+ ctx.fillRect(60 + i, 40 + i, 75, 50);
+ ctx.fillStyle = 'rgba(0, 255, 0, 1)';
+ ctx.fillRect(80 + i, 60 + i, 75, 50);
+
+ ctx.endLayer();
+ }
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.unclosed-expected.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.unclosed-expected.html
new file mode 100644
index 0000000000..c41b253c95
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.unclosed-expected.html
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<title>Canvas test: 2d.layer.unclosed</title>
+<h1>2d.layer.unclosed</h1>
+<p class="desc">Check that layers are rendered even if not closed.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'purple';
+ ctx.fillRect(60, 60, 75, 50);
+ ctx.globalAlpha = 0.5;
+
+ ctx.beginLayer({filter: 'dropShadow', dx: -2, dy: 2});
+ ctx.fillStyle = 'purple';
+ ctx.fillRect(40, 40, 75, 50);
+ ctx.fillStyle = 'grey';
+ ctx.fillRect(50, 50, 75, 50);
+ ctx.endLayer();
+</script>
diff --git a/testing/web-platform/tests/html/canvas/element/layers/2d.layer.unclosed.html b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.unclosed.html
new file mode 100644
index 0000000000..788889ee7e
--- /dev/null
+++ b/testing/web-platform/tests/html/canvas/element/layers/2d.layer.unclosed.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<!-- DO NOT EDIT! This test has been generated by /html/canvas/tools/gentest.py. -->
+<link rel="match" href="2d.layer.unclosed-expected.html">
+<title>Canvas test: 2d.layer.unclosed</title>
+<h1>2d.layer.unclosed</h1>
+<p class="desc">Check that layers are rendered even if not closed.</p>
+<canvas id="canvas" width="200" height="200">
+ <p class="fallback">FAIL (fallback content)</p>
+</canvas>
+<script>
+ const canvas = document.getElementById("canvas");
+ const ctx = canvas.getContext('2d');
+
+ ctx.fillStyle = 'purple';
+ ctx.fillRect(60, 60, 75, 50);
+ ctx.globalAlpha = 0.5;
+
+ ctx.beginLayer({filter: 'dropShadow', dx: -2, dy: 2});
+ ctx.fillRect(40, 40, 75, 50);
+ ctx.fillStyle = 'grey';
+ ctx.fillRect(50, 50, 75, 50);
+</script>