summaryrefslogtreecommitdiffstats
path: root/dom/canvas/test
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:13:27 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:13:27 +0000
commit40a355a42d4a9444dc753c04c6608dade2f06a23 (patch)
tree871fc667d2de662f171103ce5ec067014ef85e61 /dom/canvas/test
parentAdding upstream version 124.0.1. (diff)
downloadfirefox-40a355a42d4a9444dc753c04c6608dade2f06a23.tar.xz
firefox-40a355a42d4a9444dc753c04c6608dade2f06a23.zip
Adding upstream version 125.0.1.upstream/125.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/canvas/test')
-rw-r--r--dom/canvas/test/mochitest.toml4
-rw-r--r--dom/canvas/test/reftest/colors/_generated_reftest.list176
-rw-r--r--dom/canvas/test/reftest/colors/color_canvas.html461
-rw-r--r--dom/canvas/test/reftest/colors/generate_color_canvas_reftests.py427
-rw-r--r--dom/canvas/test/reftest/filters/reftest.list4
-rw-r--r--dom/canvas/test/reftest/reftest.list12
-rw-r--r--dom/canvas/test/test_accelerated_canvas_context_loss.html121
-rw-r--r--dom/canvas/test/webgl-conf/generated-mochitest.toml9
-rw-r--r--dom/canvas/test/webgl-conf/mochitest-errata.toml10
-rw-r--r--dom/canvas/test/webgl-mochitest/mochitest.toml53
10 files changed, 1234 insertions, 43 deletions
diff --git a/dom/canvas/test/mochitest.toml b/dom/canvas/test/mochitest.toml
index 86cf26b632..3e96fff26b 100644
--- a/dom/canvas/test/mochitest.toml
+++ b/dom/canvas/test/mochitest.toml
@@ -185,6 +185,10 @@ support-files = [
["test_ImageData_ctor.html"]
+["test_accelerated_canvas_context_loss.html"]
+subsuite = "gpu"
+skip-if = ["verify || (os == 'win' && debug)"]
+
["test_bitmaprenderer.html"]
["test_bug232227.html"]
diff --git a/dom/canvas/test/reftest/colors/_generated_reftest.list b/dom/canvas/test/reftest/colors/_generated_reftest.list
new file mode 100644
index 0000000000..29761e3df8
--- /dev/null
+++ b/dom/canvas/test/reftest/colors/_generated_reftest.list
@@ -0,0 +1,176 @@
+### Generated, do not edit. ###
+ ### Generated, do not edit. ###
+ ### Generated, do not edit. ###
+
+# Generated by `./generate_color_canvas_reftests.py --write`.
+# -
+
+defaults pref(webgl.colorspaces.prototype,true)
+
+### Generated, do not edit. ###
+# -
+
+# Ensure not white-screening:
+!= color_canvas.html?= about:blank
+# Ensure differing results with different args:
+!= color_canvas.html?e_color=color(srgb,1,0,0) color_canvas.html?e_color=color(srgb,0,1,0)
+
+### Generated, do not edit. ###
+# -
+skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.000)
+skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.000)
+skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.200,0.200)
+skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.200,0.200)
+ ### Generated, do not edit. ###
+skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.000,0.000)
+skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.000,0.000)
+skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.200,0.000)
+skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.200,0.000)
+ ### Generated, do not edit. ###
+skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.200)
+skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.200)
+skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.502,0.502)
+skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.502,0.502)
+ ### Generated, do not edit. ###
+skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.000,0.000)
+skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.000,0.000)
+skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.502,0.000)
+skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.502,0.000)
+ ### Generated, do not edit. ###
+skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.502)
+skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.502)
+skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(srgb,1.000,1.000,1.000)
+skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=srgb&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(srgb,1.000,1.000,1.000)
+ ### Generated, do not edit. ###
+skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.000)
+skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.000)
+skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.200,0.200)
+skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.200,0.200)
+ ### Generated, do not edit. ###
+skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.000,0.000)
+skip-if(cocoaWidget) fails == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.000,0.000)
+skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.000,0.000)
+skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.200,0.000)
+ ### Generated, do not edit. ###
+skip-if(cocoaWidget) fails-if(!Android) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.200,0.000)
+skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.200,0.000)
+skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.200)
+skip-if(cocoaWidget) fails == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.200)
+ ### Generated, do not edit. ###
+skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.200)
+skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.502,0.502)
+skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.502,0.502)
+skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.000,0.000)
+ ### Generated, do not edit. ###
+skip-if(cocoaWidget) fails == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.000,0.000)
+skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.000,0.000)
+skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.502,0.000)
+skip-if(cocoaWidget) fails-if(!Android) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.502,0.000)
+ ### Generated, do not edit. ###
+skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.502,0.000)
+skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.502)
+skip-if(cocoaWidget) fails == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.502)
+skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.502)
+ ### Generated, do not edit. ###
+skip-if(!cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(display-p3,1.000,1.000,1.000)
+skip-if(cocoaWidget) == color_canvas.html?e_context=webgl&e_webgl_format=RGBA8&e_cspace=display-p3&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(display-p3,1.000,1.000,1.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.200,0.200)
+ ### Generated, do not edit. ###
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.000,0.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.200,0.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.200)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.502,0.502)
+ ### Generated, do not edit. ###
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.000,0.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.502,0.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.502)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(srgb,1.000,1.000,1.000)
+ ### Generated, do not edit. ###
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.200,0.200)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.000,0.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.200,0.000)
+ ### Generated, do not edit. ###
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.200)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.502,0.502)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.000,0.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.502,0.000)
+ ### Generated, do not edit. ###
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.502)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=srgb&e_color=color(display-p3,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(display-p3,1.000,1.000,1.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.200,0.200)
+ ### Generated, do not edit. ###
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.000,0.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.200,0.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.200)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.502,0.502)
+ ### Generated, do not edit. ###
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.000,0.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.502,0.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.502)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(srgb,1.000,1.000,1.000)
+ ### Generated, do not edit. ###
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.200,0.200)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.000,0.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.200,0.000)
+ ### Generated, do not edit. ###
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.200)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.502,0.502)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.000,0.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.502,0.000)
+ ### Generated, do not edit. ###
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.502)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"true"}&e_cspace=display-p3&e_color=color(display-p3,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(display-p3,1.000,1.000,1.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.200,0.200)
+ ### Generated, do not edit. ###
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.000,0.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.200,0.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.200)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.502,0.502)
+ ### Generated, do not edit. ###
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.000,0.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.502,0.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.502)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(srgb,1.000,1.000,1.000)
+ ### Generated, do not edit. ###
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.200,0.200)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.000,0.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.200,0.000)
+ ### Generated, do not edit. ###
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.200)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.502,0.502)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.000,0.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.502,0.000)
+ ### Generated, do not edit. ###
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.502)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=srgb&e_color=color(display-p3,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(display-p3,1.000,1.000,1.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.200,0.200)
+ ### Generated, do not edit. ###
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.200,0.000,0.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.200,0.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.200)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.502,0.502)
+ ### Generated, do not edit. ###
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.502,0.000,0.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.502,0.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(srgb,0.000,0.000,0.502)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(srgb,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(srgb,1.000,1.000,1.000)
+ ### Generated, do not edit. ###
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.200,0.200,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.200,0.200)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.200,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.200,0.000,0.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.200,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.200,0.000)
+ ### Generated, do not edit. ###
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.000,0.200) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.200)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.502,0.502,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.502,0.502)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.502,0.000,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.502,0.000,0.000)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.502,0.000) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.502,0.000)
+ ### Generated, do not edit. ###
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,0.000,0.000,0.502) color_canvas.html?e_context=css&e_color=color(display-p3,0.000,0.000,0.502)
+ == color_canvas.html?e_context=2d&e_options={"willReadFrequently":"false"}&e_cspace=display-p3&e_color=color(display-p3,1.000,1.000,1.000) color_canvas.html?e_context=css&e_color=color(display-p3,1.000,1.000,1.000)
diff --git a/dom/canvas/test/reftest/colors/color_canvas.html b/dom/canvas/test/reftest/colors/color_canvas.html
new file mode 100644
index 0000000000..7abbc86255
--- /dev/null
+++ b/dom/canvas/test/reftest/colors/color_canvas.html
@@ -0,0 +1,461 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset=utf-8>
+ <title>color_canvas.html</title>
+ </head>
+ <!--
+# color_canvas.html
+
+* Default is a 100x100 'css' canvas-equivalent div, filled with 50% srgb red.
+
+* We default to showing the settings pane when loaded without a query string.
+ This way, someone naively opens this in a browser, they can immediately see
+ all available options.
+
+* The 'Publish' button updates the url, and so causes the settings pane to
+ hide.
+
+* Clicking on the canvas toggles the settings pane for further editing.
+ -->
+ <body>
+ <form id=e_settings><fieldset><legend>Settings</legend>
+ Width: <input id=e_width type=text value=100>
+ <br>
+ Height: <input id=e_height type=text value=100>
+ <br>
+ <fieldset><legend>Canvas Context</legend>
+ Type: <select id=e_context>
+ <option value=css selected>css</option>
+ <option value=2d>2d</option>
+ <option value=webgl>webgl</option>
+ </select>
+ <br>
+ Options: <input id=e_options type=text value={}>
+ <br>
+ Colorspace: <input id=e_cspace type=text placeholder=srgb>
+ <br>
+ WebGL Format: <input id=e_webgl_format type=text placeholder=RGBA8>
+ </fieldset>
+ <br>
+ Color: <input id=e_color type=text value='color(srgb 0 0.5 0)'>
+ <br>
+ <input id=e_publish type=button value=Publish>
+ <input type=checkbox id=e_publish_omit_defaults checked><label for=e_publish_omit_defaults>Omit defaults</label>
+ <hr>
+ </fieldset></form>
+ <div id=e_canvas_list><canvas></canvas></div>
+ <script>
+'use strict';
+
+// -
+
+function walk_nodes_depth_first(e, fn) {
+ if (fn(e) === false) return; // Don't stop on `true`, or `undefined`!
+ for (const c of e.childNodes) {
+ walk_nodes_depth_first(c, fn);
+ }
+}
+
+// -
+
+// Click the canvas to toggle the settings pane.
+e_canvas_list.addEventListener('click', () => {
+ // Toggle display:none to hide/unhide.
+ e_settings.hidden = !e_settings.hidden;
+});
+
+// Hide settings initially if there's a query string in the url.
+if (window.location.search.startsWith('?')) {
+ e_settings.hidden = true;
+}
+
+// -
+
+// Imply .name from .id, because `new FormData` collects based on names.
+walk_nodes_depth_first(e_settings, e => {
+ if (e.id) {
+ e.name = e.id;
+ e._default_value = e.value;
+ }
+});
+
+// -
+
+const URL_PARAMS = new URLSearchParams(window.location.search);
+URL_PARAMS.forEach((v,k) => {
+ const e = window[k];
+ if (!e) {
+ if (k) {
+ console.warn(`Unrecognized setting: ${k} = ${v}`);
+ }
+ return;
+ }
+ v = decode_url_v(k,v);
+ e.value = v;
+});
+
+// -
+
+globalThis.ASSERT = (() => {
+ function toPrettyString(arg) {
+ if (!arg) return ''+arg;
+
+ if (arg.call) {
+ let s = arg.toString();
+ const RE_TRIVIAL_LAMBDA = /\( *\) *=> *(.*)/;
+ const m = RE_TRIVIAL_LAMBDA.exec(s);
+ if (m) {
+ s = '`' + m[1] + '`';
+ }
+ return s;
+ }
+ if (arg.constructor == Array) {
+ return `[${[].join.call(arg, ', ')}]`;
+ }
+ return JSON.stringify(arg);
+ }
+
+ /// new AssertArg(): Construct a wrapper for args to assert functions.
+ function AssertArg(dict) {
+ this.label = Object.keys(dict)[0];
+
+ this.set = function(arg) {
+ this.arg = arg;
+ this.value = (arg && arg.call) ? arg.call() : arg;
+ this.value = toPrettyString(this.value);
+ };
+ this.set(dict[this.label]);
+
+ this.toString = function() {
+ let ret = `${this.label} ${toPrettyString(this.arg)}`;
+ if (this.arg.call) {
+ ret += ` (${this.value})`;
+ }
+ return ret;
+ }
+ }
+
+ const eq = (a,b) => a == b;
+ const neq = (a,b) => a != b;
+
+ const CMP_BY_NAME = {
+ '==': eq,
+ '!=': neq,
+ };
+
+ function IS(cmp, was, expected, _console) {
+ _console = _console || console;
+
+ _console.assert(was.call, '`was.call` not defined.');
+ was = new AssertArg({was});
+ expected = new AssertArg({expected});
+
+ const fn_cmp = CMP_BY_NAME[cmp] || cmp;
+
+ _console.assert(fn_cmp(was.value, expected.value), `${toPrettyString(was.arg)} => ${was.value} not ${cmp} ${expected}`);
+ if (was.value != expected.value) {
+ } else if (globalThis.ASSERT && globalThis.ASSERT.verbose) {
+ const maybe_cmp_str = (cmp == '==') ? '' : ` ${was.value} ${cmp}`;
+ _console.log(`${toPrettyString(was.arg)} => ${maybe_cmp_str}${expected}`);
+ }
+ }
+
+ // -
+
+ const MOCK_CONSOLE = {
+ _asserts: [],
+ assert: function(expr, ...args) {
+ if (!expr) {
+ this._asserts.push(args);
+ }
+ },
+ log: function(...args) {
+ // Don't record.
+ },
+ };
+
+ // -
+ // Test `==`
+
+ IS('==', () => 1, 1, MOCK_CONSOLE);
+ console.assert(MOCK_CONSOLE._asserts.length == 0, MOCK_CONSOLE._asserts);
+ MOCK_CONSOLE._asserts = [];
+
+ IS('==', () => 2, 2, MOCK_CONSOLE);
+ console.assert(MOCK_CONSOLE._asserts.length == 0, MOCK_CONSOLE._asserts);
+ MOCK_CONSOLE._asserts = [];
+
+ IS('==', () => 5, () => 3, MOCK_CONSOLE);
+ console.assert(MOCK_CONSOLE._asserts.length == 1, MOCK_CONSOLE._asserts);
+ MOCK_CONSOLE._asserts = [];
+
+ IS('==', () => [1,2], () => [1,2], MOCK_CONSOLE);
+ console.assert(MOCK_CONSOLE._asserts.length == 0, MOCK_CONSOLE._asserts);
+ MOCK_CONSOLE._asserts = [];
+
+ // -
+ // Test `!=`
+
+ IS('!=', () => [1,2,5], () => [1,2,3], MOCK_CONSOLE);
+ console.assert(MOCK_CONSOLE._asserts.length == 0, MOCK_CONSOLE._asserts);
+ MOCK_CONSOLE._asserts = [];
+
+ // -
+
+ const ret = {
+ verbose: false,
+ IS,
+ };
+ ret.EQ = (was,expected) => ret.IS('==', was, expected);
+ ret.NEQ = (was,expected) => ret.IS('!=', was, expected);
+ ret.EEQ = (was,expected) => ret.IS('===', was, expected);
+ ret.NEEQ = (was,expected) => ret.IS('!==', was, expected);
+ ret.TRUE = was => ret.EQ(was, true);
+ ret.FALSE = was => ret.EQ(was, false);
+ ret.NULL = was => ret.EEQ(was, null);
+ return ret;
+})();
+
+// -
+
+function parse_css_rgb(str) {
+ // rgb (R ,G ,B /A )
+ const m = /rgba?\(([^,]+),([^,]+),([^/)]+)(?: *\/([^)]+))?\)/.exec(str);
+ if (!m) throw str;
+ const rgba = m.slice(1,1+4).map((s,i) => {
+ if (s === undefined && i == 3) {
+ s = '1'; // Alpha defaults to 1.
+ }
+ s = s.trim();
+ let v = parseFloat(s);
+ if (s.endsWith('%')) {
+ v /= 100;
+ } else {
+ if (i < 3) { // r,g,b but not a!
+ v /= 255;
+ }
+ }
+ return v;
+ });
+ return rgba;
+}
+ASSERT.EQ(() => parse_css_rgb('rgb(255,255,255)'), [1,1,1,1]);
+ASSERT.EQ(() => parse_css_rgb('rgba(255,255,255)'), [1,1,1,1]);
+ASSERT.EQ(() => parse_css_rgb('rgb(255,255,255)'), [1,1,1,1]);
+ASSERT.EQ(() => parse_css_rgb('rgba(255,255,255)'), [1,1,1,1]);
+ASSERT.EQ(() => parse_css_rgb('rgb(20,40,60)'), () => [20/255, 40/255, 60/255, 1]);
+ASSERT.EQ(() => parse_css_rgb('rgb(20,40,60 / 0.5)'), () => [20/255, 40/255, 60/255, 0.5]);
+ASSERT.EQ(() => parse_css_rgb('rgb(20,40,60 / 0)'), () => [20/255, 40/255, 60/255, 0]);
+
+// -
+
+function parse_css_color(str) {
+ // color ( srgb R G B /A )
+ const m = /color\( *([^ ]+) +([^ ]+) +([^ ]+) +([^/)]+)(?:\/([^)]+))?\)/.exec(str);
+ if (!m) {
+ return ['srgb', ...parse_css_rgb(str)];
+ }
+
+ const cspace = m[1].trim();
+ let has_extreme_colors = false;
+ const rgba = m.slice(2, 2+4).map((s,i) => {
+ if (s === undefined && i == 3) {
+ s = '1'; // Alpha defaults to 1.
+ }
+ s = s.trim();
+ let v = parseFloat(s);
+ if (s.endsWith('%')) {
+ v /= 100;
+ }
+ if (v < 0 || v > 1) {
+ has_extreme_colors = true;
+ }
+ return v;
+ });
+ if (has_extreme_colors) {
+ console.warn(`parse_css_color('${str}') has colors outside [0.0,1.0]: ${JSON.stringify(rgba)}`);
+ }
+ return [cspace, ...rgba];
+}
+ASSERT.EQ(() => parse_css_color('rgb(255,255,255)'), ['srgb',1,1,1,1]);
+ASSERT.EQ(() => parse_css_color('rgb(20,40,60 / 0.5)'), () => ['srgb', 20/255, 40/255, 60/255, 0.5]);
+ASSERT.EQ(() => parse_css_color('color(srgb 1 0 1 /0.3)'), ['srgb',1,0,1,0.3]);
+ASSERT.EQ(() => parse_css_color('color(display-p3 1 0% 100%/ 30%)'), ['display-p3',1,0,1,0.3]);
+
+// -
+
+class CssColor {
+ constructor(cspace, r,g,b,a=1) {
+ this.cspace = cspace;
+ this.rgba = [this.r, this.g, this.b, this.a] = [r,g,b,a];
+ this.rgb = this.rgba.slice(0,3);
+ this.tuple = [this.cspace, ...this.rgba];
+ }
+
+ toString() {
+ return `color(${this.cspace} ${this.rgb.join(' ')} / ${this.a})`;
+ }
+};
+CssColor.parse = function(str) {
+ return new CssColor(...parse_css_color(str));
+}
+
+{
+ let STR;
+ // Test round-trip.
+ STR = 'color(display-p3 1 0 1 / 0.3)';
+ ASSERT.EQ(() => CssColor.parse(STR).toString(), STR);
+
+ // Test round-trip normalization
+ ASSERT.EQ(() => CssColor.parse('color( display-p3 1 0 1/30% )').toString(), 'color(display-p3 1 0 1 / 0.3)');
+}
+
+// -
+
+function redraw() {
+ while (e_canvas_list.firstChild) {
+ e_canvas_list.removeChild(e_canvas_list.firstChild);
+ }
+
+ const c = make_canvas(e_color.value.trim());
+ c.style.border = '4px solid black';
+ e_canvas_list.appendChild(c);
+}
+
+function fill_canvas_rect(context /*: CanvasRenderingContext | WebGLRenderingContext*/, css_color, rect=null) {
+ rect = rect || {left: 0, top: 0, w: context.canvas.width, h: context.canvas.height};
+
+ const is_c2d = ('fillRect' in context);
+ if (is_c2d) {
+ const c2d = context;
+ c2d.fillStyle = css_color;
+ c2d.fillRect(rect.left, rect.top, rect.w, rect.h);
+ return;
+ }
+
+ const is_webgl = ('drawArrays' in context);
+ if (is_webgl) {
+ const gl = context;
+ console.assert(context.canvas.width == gl.drawingBufferWidth, context.canvas.width, '!=', gl.drawingBufferWidth);
+ console.assert(context.canvas.height == gl.drawingBufferHeight, context.canvas.height, '!=', gl.drawingBufferHeight);
+
+ gl.enable(gl.SCISSOR_TEST);
+ gl.disable(gl.DEPTH_TEST);
+ const bottom = rect.top + rect.h; // in y-down c2d coords
+ gl.scissor(rect.left, context.canvas.height - bottom, rect.w, rect.h);
+
+ const canvas_cspace = context.drawingBufferColorSpace || 'srgb';
+ if (css_color.cspace != canvas_cspace) {
+ console.warn(`Ignoring mismatched color vs webgl canvas cspace: ${css_color.cspace} vs ${canvas_cspace}`);
+ }
+ gl.clearColor(...css_color.rgba);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ return;
+ }
+
+ console.error('Unhandled context kind:', context);
+}
+
+window.e_canvas = null;
+
+function make_canvas(css_color) {
+ css_color = CssColor.parse(css_color);
+
+ // `e_width` and e_friends are elements (by id) that we added to the raw HTML above.
+ // `e_width` is an old shorthand for `window.e_width || document.getElementById('e_width')`.
+ const W = parseInt(e_width.value);
+ const H = parseInt(e_height.value);
+ if (e_context.value == 'css') {
+ e_canvas = document.createElement('div');
+ e_canvas.style.width = `${W}px`;
+ e_canvas.style.height = `${H}px`;
+ e_canvas.style.backgroundColor = css_color;
+ return e_canvas;
+ }
+ e_canvas = document.createElement('canvas');
+ e_canvas.width = W;
+ e_canvas.height = H;
+
+ let requested_options = JSON.parse(e_options.value);
+ requested_options.colorSpace = e_cspace.value || undefined;
+
+ const context = e_canvas.getContext(e_context.value, requested_options);
+ if (requested_options.colorSpace) {
+ if (!context.drawingBufferColorSpace) {
+ console.warn(`${context.constructor.name}.drawingBufferColorSpace not supported by browser.`);
+ } else {
+ context.drawingBufferColorSpace = requested_options.colorSpace;
+ }
+ }
+
+ if (e_webgl_format.value) {
+ if (!context.drawingBufferStorage) {
+ console.warn(`${context.constructor.name}.drawingBufferStorage not supported by browser.`);
+ } else {
+ context.drawingBufferStorage(W, H, context[e_webgl_format.value]);
+ }
+ }
+
+ let actual_options;
+ if (!context.getContextAttributes) {
+ console.warn(`${canvas.constructor.name}.getContextAttributes not supported by browser.`);
+ actual_options = requested_options;
+ } else {
+ actual_options = context.getContextAttributes();
+ }
+
+ // -
+
+ fill_canvas_rect(context, css_color);
+
+ return e_canvas;
+}
+
+e_settings.addEventListener('change', async () => {
+ redraw();
+ const e_updated = document.createElement('i');
+ e_updated.textContent = '(Updated!)';
+ document.body.appendChild(e_updated);
+ await new Promise(go => setTimeout(go, 1000));
+ document.body.removeChild(e_updated);
+});
+redraw();
+
+// -
+
+function encode_url_v(k,v) {
+ if (k == 'e_color') {
+ v = v.replaceAll(' ', ',');
+ }
+ console.assert(!v.includes(' '), v);
+ return v
+}
+function decode_url_v(k,v) {
+ console.assert(!v.includes(' '), v);
+ if (k == 'e_color') {
+ v = v.replaceAll(',', ' ');
+ }
+ return v
+}
+ASSERT.EQ(() => decode_url_v('e_color', encode_url_v('e_color', 'color(srgb 1 0 0)')), 'color(srgb 1 0 0)')
+
+e_publish.addEventListener('click', () => {
+ const fd = new FormData(e_settings);
+ let settings = [];
+ for (let [k,v] of fd) {
+ const e = window[k];
+ if (e_publish_omit_defaults.checked && v == e._default_value) continue;
+
+ v = encode_url_v(k,v);
+ settings.push(`${k}=${v}`);
+ }
+ settings = settings.join('&');
+ if (!settings) {
+ settings = '='; // Empty key-value pair is 'publish with default settings'
+ }
+ window.location.search = '?' + settings;
+});
+ </script>
+ </body>
+</html>
diff --git a/dom/canvas/test/reftest/colors/generate_color_canvas_reftests.py b/dom/canvas/test/reftest/colors/generate_color_canvas_reftests.py
new file mode 100644
index 0000000000..8c1e5f3788
--- /dev/null
+++ b/dom/canvas/test/reftest/colors/generate_color_canvas_reftests.py
@@ -0,0 +1,427 @@
+#! python3
+
+# Typecheck:
+# `pip -m mypy generate_color_canvas_reftests.py`
+#
+# Run:
+# `./generate_color_canvas_reftests.py [--write]`
+
+import functools
+import json
+import math
+import pathlib
+import re
+import sys
+from typing import Iterable, NamedTuple, TypeVar
+
+ARGS = sys.argv[1:]
+DEST = pathlib.Path(__file__).parent / "_generated_reftest.list"
+
+COL_DELIM = " "
+COL_ALIGNMENT = 4
+
+# -
+
+T = TypeVar("T")
+U = TypeVar("U")
+
+# -
+
+
+# crossCombine([{a:false},{a:5}], [{},{b:5}])
+# [{a:false}, {a:true}, {a:false,b:5}, {a:true,b:5}]
+def cross_combine(*args_tup: list[dict]) -> list[dict]:
+ args = list(args_tup)
+ for i, a in enumerate(args):
+ assert type(a) == list, f"Arg{i} is {type(a)}, expected {list}."
+
+ def cross_combine2(listA, listB):
+ listC = []
+ for a in listA:
+ for b in listB:
+ c = dict()
+ c.update(a)
+ c.update(b)
+ listC.append(c)
+ return listC
+
+ res: list[dict] = [dict()]
+ while True:
+ try:
+ next = args.pop(0)
+ except IndexError:
+ break
+ res = cross_combine2(res, next)
+ return res
+
+
+# keyed_alternatives('count', [1,2,3]) -> [{count: 1}, {count: 2}, {count: 3}]
+def keyed_alternatives(key: T, vals: Iterable[U]) -> list[dict[T, U]]:
+ """
+ res = []
+ for v in vals:
+ d = dict()
+ d[key] = v
+ res.append(d)
+ return res
+ """
+ # return [dict([[key,v]]) for v in vals]
+ return [{key: v} for v in vals]
+
+
+# -
+
+
+def eprint(*args, **kwargs):
+ sys.stdout.flush()
+ print(*args, file=sys.stderr, **kwargs)
+ sys.stderr.flush()
+
+
+# -
+
+# color_canvas.html?e_width=100&e_height=100&e_context=css&e_options={}&e_cspace=&e_webgl_format=&e_color=rgb(127,0,0)
+
+CSPACE_LIST = ["srgb", "display-p3"]
+CANVAS_CSPACES = keyed_alternatives("e_cspace", CSPACE_LIST)
+
+RGB_LIST = [
+ "0.000 0.000 0.000",
+ "0.200 0.200 0.200", # 0.2*255 = 51
+ "0.200 0.000 0.000",
+ "0.000 0.200 0.000",
+ "0.000 0.000 0.200",
+ "0.502 0.502 0.502", # 0.502*255 = 128.01
+ "0.502 0.000 0.000",
+ "0.000 0.502 0.000",
+ "0.000 0.000 0.502",
+ "1.000 1.000 1.000",
+ #'1.000 0.000 0.000', # These will hit gamut clipping on most displays.
+ #'0.000 1.000 0.000',
+ #'0.000 0.000 1.000',
+]
+
+WEBGL_COLORS = keyed_alternatives("e_color", [f"color(srgb {rgb})" for rgb in RGB_LIST])
+
+C2D_COLORS = []
+for cspace in CSPACE_LIST:
+ C2D_COLORS += keyed_alternatives(
+ "e_color", [f"color({cspace} {rgb})" for rgb in RGB_LIST]
+ )
+
+# -
+
+WEBGL_FORMATS = keyed_alternatives(
+ "e_webgl_format",
+ [
+ "RGBA8",
+ # Bug 1883748: (webgl.drawingbufferStorage)
+ #'SRGB8_ALPHA8',
+ #'RGBA16F',
+ ],
+)
+WEBGL = cross_combine(
+ [{"e_context": "webgl"}], WEBGL_FORMATS, CANVAS_CSPACES, WEBGL_COLORS
+)
+
+# -
+
+C2D_OPTIONS_COMBOS = cross_combine(
+ keyed_alternatives("willReadFrequently", ["true", "false"]), # E.g. D2D vs Skia
+ # keyed_alternatives('alpha', ['true','false'])
+)
+C2D_OPTIONS = [
+ json.dumps(config, separators=(",", ":")) for config in C2D_OPTIONS_COMBOS
+]
+
+C2D = cross_combine(
+ [{"e_context": "2d"}],
+ keyed_alternatives("e_options", C2D_OPTIONS),
+ CANVAS_CSPACES,
+ C2D_COLORS,
+)
+
+# -
+
+COMBOS: list[dict[str, str]] = cross_combine(WEBGL + C2D)
+
+eprint(f"{len(COMBOS)} combinations...")
+
+# -
+
+Config = dict[str, str]
+
+
+class CssColor(NamedTuple):
+ cspace: str
+ rgb: str
+
+ def rgb_vals(self) -> tuple[float, float, float]:
+ (r, g, b) = [float(z) for z in self.rgb.split(" ")]
+ return (r, g, b)
+
+ def is_same_color(x, y) -> bool:
+ if x == y:
+ return True
+ (r, g, b) = x.rgb_vals()
+ if x.rgb == y.rgb and r == g and g == b:
+ return True
+ return False
+
+
+class Reftest(NamedTuple):
+ notes: list[str]
+ op: str
+ test_config: Config
+ ref_config: Config
+
+
+def make_ref_config(color: CssColor) -> Config:
+ return {
+ "e_context": "css",
+ "e_color": f"color({color.cspace} {color.rgb})",
+ }
+
+
+class ColorReftest(NamedTuple):
+ notes: list[str]
+ test_config: Config
+ ref_color: CssColor
+
+ def to_reftest(self):
+ ref_config = make_ref_config(self.ref_color)
+ return Reftest(self.notes.copy(), "==", self.test_config.copy(), ref_config)
+
+
+class Expectation(NamedTuple):
+ notes: list[str]
+ test_config: Config
+ color: CssColor
+
+
+def parse_css_color(s: str) -> CssColor:
+ m = re.match("color[(]([^)]+)[)]", s)
+ assert m, s
+ (cspace, rgb) = m.group(1).split(" ", 1)
+ return CssColor(cspace, rgb)
+
+
+def correct_color_from_test_config(test_config: Config) -> CssColor:
+ canvas_cspace = test_config["e_cspace"]
+ if not canvas_cspace:
+ canvas_cspace = "srgb"
+
+ correct_color = parse_css_color(test_config["e_color"])
+ if test_config["e_context"] == "webgl":
+ # Webgl ignores the color's cspace, because webgl has no concept of
+ # source colorspace for clears/draws to the backbuffer.
+ # This (correct) behavior is as if the color's cspace were overwritten by the
+ # cspace of the canvas. (so expect that)
+ correct_color = CssColor(canvas_cspace, correct_color.rgb)
+
+ return correct_color
+
+
+# -------------------------------------
+# -------------------------------------
+# -------------------------------------
+# Choose (multiple?) reference configs given a test config.
+
+
+def reftests_from_config(test_config: Config) -> Iterable[ColorReftest]:
+ correct_color = correct_color_from_test_config(test_config)
+
+ if test_config["e_context"] == "2d":
+ # Canvas2d generally has the same behavior as css, so expect all passing.
+ yield ColorReftest([], test_config, correct_color)
+ return
+
+ assert test_config["e_context"] == "webgl", test_config["e_context"]
+
+ # -
+
+ def reftests_from_expected_color(
+ notes: list[str], expected_color: CssColor
+ ) -> Iterable[ColorReftest]:
+ # If expecting failure, generate two tests, both expecting failure:
+ # 1. expected-fail test == correct_color
+ # 2. expected-pass test == (incorrect) expected_color
+ # If we fix an error, we'll see one unexpected-pass and one unexpected-fail.
+ # If we get a new wrong answer, we'll see one unexpected-fail.
+
+ if not expected_color.is_same_color(correct_color):
+ yield ColorReftest(notes + ["fails"], test_config, correct_color)
+ yield ColorReftest(notes, test_config, expected_color)
+ else:
+ yield ColorReftest(notes, test_config, correct_color)
+
+ # -
+ # On Mac, (with the pref) we do tag the IOSurface with the right cspace.
+ # On other platforms, Webgl always outputs in the display color profile
+ # right now. This is the same as "srgb".
+
+ expected_color_srgb = CssColor("srgb", correct_color.rgb)
+ # Mac
+ yield from reftests_from_expected_color(["skip-if(!cocoaWidget)"], correct_color)
+ # Win, Lin, Android
+ yield from reftests_from_expected_color(
+ ["skip-if(cocoaWidget) "], expected_color_srgb
+ )
+
+
+# -
+
+
+def amended_notes_from_reftest(reftest: ColorReftest) -> list[str]:
+ notes = reftest.notes[:]
+
+ ref_rgb_vals = reftest.ref_color.rgb_vals()
+ is_green_only = ref_rgb_vals == (0, ref_rgb_vals[1], 0)
+ if (
+ "fails" in reftest.notes
+ and reftest.test_config["e_context"] == "webgl"
+ and reftest.test_config["e_cspace"] == "display-p3"
+ and is_green_only
+ ):
+ # Android's display bitdepth rounds srgb green and p3 green to the same thing.
+ notes[notes.index("fails")] = "fails-if(!Android)"
+
+ return notes
+
+
+# -------------------------------------
+# -------------------------------------
+# -------------------------------------
+# Ok, back to implementation.
+
+
+def encode_url_v(k, v):
+ if k == "e_color":
+ # reftest harness can't deal with spaces in urls, and 'color(srgb%201%200%200)' is hard to read.
+ v = v.replace(" ", ",")
+
+ assert " " not in v, (k, v)
+ return v
+
+
+# Cool:
+assert encode_url_v("e_color", "color(srgb 0 0 0)") == "color(srgb,0,0,0)"
+# Unfortunate, but tolerable:
+assert encode_url_v("e_color", "color(srgb 0 0 0)") == "color(srgb,,,0,,,0,,,0)"
+
+# -
+
+
+def url_from_config(kvs: Config) -> str:
+ parts = [f"{k}={encode_url_v(k,v)}" for k, v in kvs.items()]
+ url = "color_canvas.html?" + "&".join(parts)
+ return url
+
+
+# -
+
+color_reftests: list[ColorReftest] = []
+for c in COMBOS:
+ color_reftests += reftests_from_config(c)
+color_reftests = [
+ ColorReftest(amended_notes_from_reftest(r), r.test_config, r.ref_color)
+ for r in color_reftests
+]
+reftests = [r.to_reftest() for r in color_reftests]
+
+# -
+
+HEADINGS = ["# annotations", "op", "test", "reference"]
+table: list[list[str]] = [HEADINGS]
+table = [
+ [
+ " ".join(r.notes),
+ r.op,
+ url_from_config(r.test_config),
+ url_from_config(r.ref_config),
+ ]
+ for r in reftests
+]
+
+# -
+
+
+def round_to(a, b: int) -> int:
+ return int(math.ceil(a / b) * b)
+
+
+def aligned_lines_from_table(
+ rows: list[list[str]], col_delim=" ", col_alignment=4
+) -> Iterable[str]:
+ max_col_len = functools.reduce(
+ lambda accum, input: [max(r, len(c)) for r, c in zip(accum, input)],
+ rows,
+ [0 for _ in rows[0]],
+ )
+ max_col_len = [round_to(x, col_alignment) for x in max_col_len]
+
+ for i, row in enumerate(rows):
+ parts = [s + (" " * (col_len - len(s))) for s, col_len in zip(row, max_col_len)]
+ line = col_delim.join(parts)
+ yield line
+
+
+# -
+
+GENERATED_FILE_LINE = "### Generated, do not edit. ###"
+
+lines = list(aligned_lines_from_table(table, COL_DELIM, COL_ALIGNMENT))
+WARN_EVERY_N_LINES = 5
+i = WARN_EVERY_N_LINES - 1
+while i < len(lines):
+ lines.insert(i, " " + GENERATED_FILE_LINE)
+ i += WARN_EVERY_N_LINES
+
+# -
+
+GENERATED_BY_ARGS = [f"./{pathlib.Path(__file__).name}"] + ARGS
+
+REFTEST_LIST_PREAMBLE = f"""\
+{GENERATED_FILE_LINE}
+ {GENERATED_FILE_LINE}
+ {GENERATED_FILE_LINE}
+
+# Generated by `{' '.join(GENERATED_BY_ARGS)}`.
+# -
+
+defaults pref(webgl.colorspaces.prototype,true)
+
+{GENERATED_FILE_LINE}
+# -
+
+# Ensure not white-screening:
+!= {url_from_config({})+'='} about:blank
+# Ensure differing results with different args:
+!= {url_from_config({'e_color':'color(srgb 1 0 0)'})} {url_from_config({'e_color':'color(srgb 0 1 0)'})}
+
+{GENERATED_FILE_LINE}
+# -
+"""
+
+lines.insert(0, REFTEST_LIST_PREAMBLE)
+lines.append("")
+
+# -
+
+for line in lines:
+ print(line)
+
+if "--write" not in ARGS:
+ eprint("Use --write to write. Exiting...")
+ sys.exit(0)
+
+# -
+
+eprint("Concatenating...")
+file_str = "\n".join([line.rstrip() for line in lines])
+
+eprint(f"Writing to {DEST}...")
+DEST.write_bytes(file_str.encode())
+eprint("Done!")
+
+sys.exit(0)
diff --git a/dom/canvas/test/reftest/filters/reftest.list b/dom/canvas/test/reftest/filters/reftest.list
index cf851e2a3b..e4f21db6ce 100644
--- a/dom/canvas/test/reftest/filters/reftest.list
+++ b/dom/canvas/test/reftest/filters/reftest.list
@@ -1,7 +1,7 @@
== default-color.html ref.html
== drop-shadow.html ref.html
== drop-shadow-transformed.html ref.html
-fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)||azureSkia,0-1,0-1500) == global-alpha.html global-alpha-ref.html
+fuzzy(0-1,0-1500) == global-alpha.html global-alpha-ref.html
== global-composite-operation.html global-composite-operation-ref.html
== liveness.html ref.html
== liveness-document-open.html data:text/html,PASS
@@ -20,7 +20,7 @@ fuzzy-if(/^Windows\x20NT\x2010\.0/.test(http.oscpu)||azureSkia,0-1,0-1500) == gl
== units-off-screen.html ref.html
fuzzy(0-2,0-700) == fillText-with-filter-opacity-1.html fillText-with-filter-opacity-1-ref.html
fuzzy(0-1,0-302) == fillText-with-filter-opacity-2.html fillText-with-filter-opacity-2-ref.html
-fuzzy(0-1,0-600) fuzzy-if(d2d&&!swgl,0-36,0-15) == strokeText-with-filter-grayscale-1.html strokeText-with-filter-grayscale-1-ref.html
+fuzzy(0-1,0-600) fuzzy-if(winWidget&&!swgl,0-36,0-15) == strokeText-with-filter-grayscale-1.html strokeText-with-filter-grayscale-1-ref.html
fuzzy(0-1,0-600) == strokeText-with-filter-grayscale-2.html strokeText-with-filter-grayscale-2-ref.html
!= fillText-with-shadow-1.html fillText-without-shadow-1-ref.html
!= fillText-with-shadow-2.html fillText-without-shadow-2-ref.html
diff --git a/dom/canvas/test/reftest/reftest.list b/dom/canvas/test/reftest/reftest.list
index 0eef0b3daf..26f373b32c 100644
--- a/dom/canvas/test/reftest/reftest.list
+++ b/dom/canvas/test/reftest/reftest.list
@@ -1,4 +1,5 @@
# Canvas Filter Reftests
+include colors/_generated_reftest.list
include filters/reftest.list
include color_quads.list
@@ -26,15 +27,6 @@ skip-if(Android) == webgl-resize-test.html wrapper.html?green.png
# Check that captureStream() displays in a local video element
skip-if(Android) == webgl-capturestream-test.html?preserve wrapper.html?green.png
-# Some of the failure conditions are a little weird. I'm (jgilbert) setting these based on
-# failures encountered when running on Try, and then targetting the Try config by
-# differences in the `sandbox` contents. That is, I'm labeling based on symptoms rather
-# than cause.
-# WinXP R: winWidget && layersGPUAccelerated && !d3d11
-# Win7+ R: winWidget && layersGPUAccelerated && d3d11
-# Win7+ Ru: winWidget && !layersGPUAccelerated && d3d11
-# (Note that we have to remove spaces when used below)
-
# IMPORTANT: Expected outcomes are evaluated left-to-right, and they replace eachother.
# That means that if an unconditional status (`fuzzy()`) is to the right of another status
# (such as fails-if), it will overwrite the old status.
@@ -233,7 +225,7 @@ fuzzy(0-1,0-150) == clip-multiple-move-2.html clip-multiple-move-2-ref.html
== stroketext-shadow.html stroketext-shadow-ref.html
# focus rings
-fuzzy(0-1,0-2) skip-if(cocoaWidget||winWidget||gtkWidget) needs-focus == drawFocusIfNeeded.html drawFocusIfNeeded-ref.html
+fuzzy(0-1,0-2) skip-if(cocoaWidget||gtkWidget||winWidget) needs-focus == drawFocusIfNeeded.html drawFocusIfNeeded-ref.html
# Check that captureStream() displays in a local video element
== capturestream.html wrapper.html?green.png
diff --git a/dom/canvas/test/test_accelerated_canvas_context_loss.html b/dom/canvas/test/test_accelerated_canvas_context_loss.html
new file mode 100644
index 0000000000..6172420bcb
--- /dev/null
+++ b/dom/canvas/test/test_accelerated_canvas_context_loss.html
@@ -0,0 +1,121 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Check for contextlost/restored events after GPU process restart</title>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" href="/tests/SimpleTest/test.css">
+</head>
+<body>
+<canvas id="c" width="512" height="512"></canvas>
+
+<script type="application/javascript">
+
+function waitRAF() {
+ return new Promise((resolve, reject) => {
+ window.requestAnimationFrame(resolve);
+ });
+}
+
+async function restartGPUProcess() {
+ return await SpecialPowers.spawnChrome([], async () => {
+ const gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo);
+
+ if (gfxInfo.usingGPUProcess) {
+ const { TestUtils } = ChromeUtils.importESModule(
+ "resource://testing-common/TestUtils.sys.mjs"
+ );
+ let promise = TestUtils.topicObserved("compositor-reinitialized");
+
+ const remoteCanvas = gfxInfo.usingRemoteCanvas;
+ const acceleratedCanvas = gfxInfo.usingAcceleratedCanvas;
+ ok(true, "Restarting GPU process, remote canvas " + remoteCanvas + ", accelerated canvas " + acceleratedCanvas);
+
+ gfxInfo.killGPUProcessForTests();
+ await promise;
+
+ return remoteCanvas || acceleratedCanvas;
+ }
+
+ ok(true, "Not using GPU process");
+ return false;
+ });
+}
+
+const canvas = document.getElementById("c");
+const context = canvas.getContext("2d");
+
+let restoredPromiseResolve;
+let restoredPromiseReject;
+
+const restoredPromise = new Promise((resolve, reject) => {
+ restoredPromiseResolve = resolve;
+ restoredPromiseReject = reject;
+});
+
+let countLostEvents = 0;
+let countRestoredEvents = 0;
+
+function onContextLost() {
+ ok(context.isContextLost(), "Canvas context should be lost during contextlost event");
+ countLostEvents += 1;
+}
+
+function onContextRestored() {
+ ok(!context.isContextLost(), "Canvas context should not be lost during contextrestored event");
+ countRestoredEvents += 1;
+
+ restoredPromiseResolve(true);
+}
+
+function waitContextRestored() {
+ let timeoutId = window.setTimeout(restoredPromiseReject, 5000);
+ return restoredPromise.then(() => {
+ window.clearTimeout(timeoutId);
+ });
+}
+
+async function start() {
+ try {
+ canvas.addEventListener("contextlost", onContextLost);
+ canvas.addEventListener("contextrestored", onContextRestored);
+
+ ok(!context.isContextLost(), "Canvas context should not be lost before initial fill");
+
+ context.fillStyle = 'red';
+ context.fill();
+ await waitRAF();
+
+ ok(!context.isContextLost(), "Canvas context should not be lost after initial fill");
+
+ const restarted = await restartGPUProcess();
+ const expectedEvents = restarted ? 1 : 0;
+
+ if (expectedEvents) {
+ await waitContextRestored();
+ }
+ await waitRAF();
+
+ is(countLostEvents, expectedEvents, "Should have fired " + expectedEvents + " contextlost events");
+ is(countRestoredEvents, expectedEvents, "Should have fired " + expectedEvents + " contextrestored events");
+ ok(!context.isContextLost(), "Canvas context should not be lost after restoration");
+
+ context.fillStyle = 'green';
+ context.fill();
+ await waitRAF();
+
+ ok(!context.isContextLost(), "Canvas context should not be lost at completion");
+ } catch (err) {
+ ok(false, "Caught exception " + err);
+ } finally {
+ SimpleTest.finish();
+ }
+}
+
+SimpleTest.waitForExplicitFinish();
+SimpleTest.requestFlakyTimeout("Wait for failure condition");
+start();
+
+</script>
+</body>
+</html>
diff --git a/dom/canvas/test/webgl-conf/generated-mochitest.toml b/dom/canvas/test/webgl-conf/generated-mochitest.toml
index 8a4694100d..0cee17acf4 100644
--- a/dom/canvas/test/webgl-conf/generated-mochitest.toml
+++ b/dom/canvas/test/webgl-conf/generated-mochitest.toml
@@ -3,7 +3,6 @@
# Mark failing (fail-if) and crashing (skip-if) tests in mochitest-errata.ini.
[DEFAULT]
-skip-if = ["os == 'android' && isEmulator"]
prefs = "media.seamless-looping-video=false"
support-files = [
@@ -5669,7 +5668,6 @@ subsuite = "webgl2-core"
["generated/test_2_conformance2__renderbuffers__multisampled-renderbuffer-initialization.html"]
subsuite = "webgl2-core"
-fail-if = ["os == 'android' && android_version == '26'"]
["generated/test_2_conformance2__renderbuffers__multisampled-stencil-renderbuffer-initialization.html"]
subsuite = "webgl2-core"
@@ -9275,7 +9273,6 @@ subsuite = "webgl2-ext"
["generated/test_2_conformance__glsl__bugs__vector-matrix-constructor-scalarization.html"]
subsuite = "webgl2-ext"
fail-if = [
- "os == 'android' && android_version == '26'",
"os == 'android' && !debug",
"os == 'mac' && !apple_silicon",
]
@@ -14501,7 +14498,6 @@ subsuite = "webgl1-ext"
["generated/test_conformance__glsl__bugs__vector-matrix-constructor-scalarization.html"]
subsuite = "webgl1-ext"
fail-if = [
- "os == 'android' && android_version == '26'",
"os == 'mac' && !apple_silicon",
]
@@ -16706,7 +16702,10 @@ skip-if = ["os == 'android'"]
["generated/test_conformance__textures__misc__texture-npot-video.html"]
subsuite = "webgl1-core"
-skip-if = ["win11_2009"] # win11 - 50/50 intermittent
+skip-if = [
+ "win11_2009", # win11 - 50/50 intermittent
+ "os == 'android' && android_version == '33'", #Bug 1873144
+ ]
["generated/test_conformance__textures__misc__texture-npot.html"]
subsuite = "webgl1-core"
diff --git a/dom/canvas/test/webgl-conf/mochitest-errata.toml b/dom/canvas/test/webgl-conf/mochitest-errata.toml
index 05bcf2c6ac..5bf2b3f89b 100644
--- a/dom/canvas/test/webgl-conf/mochitest-errata.toml
+++ b/dom/canvas/test/webgl-conf/mochitest-errata.toml
@@ -23,8 +23,6 @@
# * Windows 10: 10.0
[DEFAULT]
-# Cross-process WebGL doesn't seem to work under an emulator
-skip-if = ["os == 'android' && isEmulator"]
# Bug 1799213
prefs = "media.seamless-looping-video=false"
@@ -87,7 +85,10 @@ fail-if = ["os == 'mac' && !apple_silicon"]
fail-if = ["os == 'android'"]
["generated/test_conformance__textures__misc__texture-npot-video.html"]
-skip-if = ["win11_2009"] # win11 - 50/50 intermittent
+skip-if = [
+ "win11_2009", # win11 - 50/50 intermittent
+ "os == 'android' && android_version == '33'", #Bug 1873144
+ ]
####################
# Bugs surfaced during fx93 CTS update
@@ -141,14 +142,12 @@ skip-if = ["os == 'linux' && debug"]
["generated/test_conformance__glsl__bugs__vector-matrix-constructor-scalarization.html"]
# https://bugzilla.mozilla.org/show_bug.cgi?id=1725075
fail-if = [
- "os == 'android' && android_version == '26'",
"os == 'mac' && !apple_silicon",
]
["generated/test_2_conformance__glsl__bugs__vector-matrix-constructor-scalarization.html"]
# Ditto
fail-if = [
- "os == 'android' && android_version == '26'",
"os == 'android' && !debug",
"os == 'mac' && !apple_silicon",
]
@@ -1102,7 +1101,6 @@ fail-if = ["os == 'win' && debug"]
skip-if = ["os == 'android'"]
["generated/test_2_conformance2__renderbuffers__multisampled-renderbuffer-initialization.html"]
-fail-if = ["os == 'android' && android_version == '26'"]
["generated/test_conformance__extensions__ext-sRGB.html"]
fail-if = ["os == 'android'"]
diff --git a/dom/canvas/test/webgl-mochitest/mochitest.toml b/dom/canvas/test/webgl-mochitest/mochitest.toml
index c76e2773e0..88e2fab88b 100644
--- a/dom/canvas/test/webgl-mochitest/mochitest.toml
+++ b/dom/canvas/test/webgl-mochitest/mochitest.toml
@@ -35,7 +35,8 @@ fail-if = ["os == 'android'"]
["ensure-exts/test_EXT_texture_compression_bptc.html"]
fail-if = [
"os == 'android'",
- "os == 'mac'",
+ "apple_catalina",
+ "apple_silicon",
]
["ensure-exts/test_EXT_texture_compression_rgtc.html"]
@@ -53,36 +54,45 @@ fail-if = ["os == 'linux' && display != 'wayland'"]
["ensure-exts/test_OVR_multiview2.html"]
fail-if = [
"os == 'linux'",
- "os == 'mac'",
+ "apple_catalina",
+ "apple_silicon",
]
["ensure-exts/test_WEBGL_color_buffer_float.html"]
["ensure-exts/test_WEBGL_compressed_texture_astc.html"]
fail-if = [
- "os == 'mac'",
- "os == 'win'",
+ "apple_catalina",
+ "apple_silicon",
+ "win10_2009",
+ "win11_2009",
]
["ensure-exts/test_WEBGL_compressed_texture_etc.html"]
fail-if = [
- "os == 'mac'",
- "os == 'win'",
+ "apple_catalina",
+ "apple_silicon",
+ "win10_2009",
+ "win11_2009",
]
["ensure-exts/test_WEBGL_compressed_texture_etc1.html"]
fail-if = [
"os == 'linux'",
- "os == 'mac'",
- "os == 'win'",
+ "apple_catalina",
+ "apple_silicon",
+ "win10_2009",
+ "win11_2009",
]
["ensure-exts/test_WEBGL_compressed_texture_pvrtc.html"]
fail-if = [
"os == 'android'",
"os == 'linux'",
- "os == 'mac'",
- "os == 'win'",
+ "apple_catalina",
+ "apple_silicon",
+ "win10_2009",
+ "win11_2009",
]
["ensure-exts/test_WEBGL_compressed_texture_s3tc.html"]
@@ -137,9 +147,9 @@ support-files = ["../captureStream_common.js"]
["test_has_rbab.html"]
fail-if = [
- "os == 'android' && android_version == '26'",
"os == 'linux'",
- "os == 'mac'",
+ "apple_catalina",
+ "apple_silicon",
]
["test_hidden_alpha.html"]
@@ -157,9 +167,9 @@ fail-if = [
["test_noprog_draw.html"]
["test_pixel_pack_buffer.html"]
-# skip-if = os == "win" && os_version == "10.0" # Bug 1302199
skip-if = [
- "os == 'win'", # Unofficial DXGL support regressed by bug 1632249
+ "win10_2009", # Unofficial DXGL support regressed by bug 1632249
+ "win11_2009", # Unofficial DXGL support regressed by bug 1632249
"apple_silicon",
]
@@ -191,22 +201,25 @@ skip-if = ["win11_2009 && bits == 32"] # No fast video path for h264 decoder (do
["test_video_fastpath_theora.html"]
skip-if = [
- "os == 'linux'",
- "os == 'mac'",
+ "os == 'linux' && os_version == '18.04'",
+ "apple_catalina",
+ "apple_silicon",
"win11_2009 && bits == 32", # No fast video path for theora decoder (done in RDD, can't be read in content)
]
["test_video_fastpath_vp8.html"]
skip-if = [
- "os == 'linux'",
- "os == 'mac'",
+ "os == 'linux' && os_version == '18.04'",
+ "apple_catalina",
+ "apple_silicon",
"win11_2009 && bits == 32", # No fast video path for theora decoder (done in RDD, can't be read in content)
]
["test_video_fastpath_vp9.html"]
skip-if = [
- "os == 'linux'",
- "os == 'mac'",
+ "os == 'linux' && os_version == '18.04'",
+ "apple_catalina",
+ "apple_silicon",
"win11_2009 && bits == 32", # No fast video path for theora decoder (done in RDD, can't be read in content)
]