summaryrefslogtreecommitdiffstats
path: root/dom/canvas/test/webgl-conf/checkout/conformance/rendering/blending.html
diff options
context:
space:
mode:
Diffstat (limited to 'dom/canvas/test/webgl-conf/checkout/conformance/rendering/blending.html')
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance/rendering/blending.html266
1 files changed, 266 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance/rendering/blending.html b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/blending.html
new file mode 100644
index 0000000000..b14705cd50
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance/rendering/blending.html
@@ -0,0 +1,266 @@
+<!--
+Copyright (c) 2019 The Khronos Group Inc.
+Use of this source code is governed by an MIT-style license that can be
+found in the LICENSE.txt file.
+-->
+
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="utf-8">
+<link rel="stylesheet" href="../../resources/js-test-style.css"/>
+<script src="../../js/js-test-pre.js"></script>
+<script src="../../js/webgl-test-utils.js"></script>
+
+<script id="eVsSrc" type="text/plain">
+void main()
+{
+ gl_PointSize = 1.0;
+ gl_Position = vec4(0, 0, 0, 1);
+}
+</script>
+
+<script id="eFsSrc" type="text/plain">
+precision mediump float;
+uniform vec4 uColor;
+
+void main()
+{
+ gl_FragColor = uColor;
+}
+</script>
+
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+description('Blending tests');
+
+const wtu = WebGLTestUtils;
+
+function CreateContext() {
+ const gl = wtu.create3DContext();
+ gl.viewport(0, 0, 1, 1);
+
+ gl.prog = wtu.setupProgram(gl, [eVsSrc.innerHTML, eFsSrc.innerHTML]);
+ gl.prog.uColor = (() => {
+ const loc = gl.getUniformLocation(gl.prog, 'uColor');
+ return x => gl.uniform4fv(loc, x);
+ })();
+ gl.useProgram(gl.prog);
+ gl.prog.uColor([1 / 255, 2 / 255, 3 / 255, 4 / 255]);
+
+ gl.drawAndRead = type => {
+ gl.drawArrays(gl.POINTS, 0, 1);
+ let ret;
+ if (type == gl.UNSIGNED_BYTE) {
+ ret = new Uint8Array(4);
+ } else if (type == gl.FLOAT) {
+ ret = new Float32Array(4);
+ }
+ gl.readPixels(0, 0, 1, 1, gl.RGBA, type, ret);
+ return ret;
+ };
+
+ gl.enable(gl.BLEND);
+ gl.blendFunc(gl.CONSTANT_COLOR, gl.ZERO);
+
+ return gl;
+}
+
+function CreateValidFb(gl, formats) {
+ const fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+
+ for (let i in formats) {
+ i = i|0; // Otherwise i is a string. :(
+ const f = formats[i];
+ if (!f)
+ continue;
+ if (f.length == 1) {
+ const rb = gl.createRenderbuffer();
+ gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
+ gl.renderbufferStorage(gl.RENDERBUFFER, f[0], 1, 1);
+ gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0+i,
+ gl.RENDERBUFFER, rb);
+ continue;
+ }
+ if (f.length == 3) {
+ let internalFormat = f[0];
+ if (internalFormat === undefined) {
+ internalFormat = f[1];
+ }
+
+ const tex = gl.createTexture();
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+ gl.texImage2D(gl.TEXTURE_2D, 0, internalFormat, 1,1,0, f[1],f[2], null);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0+i,
+ gl.TEXTURE_2D, tex, 0);
+ continue;
+ }
+ throw new Error('Invalid format length: ' + f);
+ }
+
+ const status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+ if (status != gl.FRAMEBUFFER_COMPLETE) {
+ gl.deleteFramebuffer(fb);
+ return null;
+ }
+ return fb;
+}
+
+let was, fb;
+
+const TESTS = [
+ () => {
+ debug('');
+ debug('Clamping of blendColor args:');
+
+ const gl = wtu.create3DContext();
+ if (!gl.texImage3D) { // WebGL 1.0
+ // WebGL 1.0 clamps without EXT_color_buffer_half_float or WEBGL_color_buffer_float.
+ gl.blendColor(1000, 1, 1, 1);
+ const was = gl.getParameter(gl.BLEND_COLOR);
+ expectArray(was, [1, 1, 1, 1]);
+
+ const ext = gl.getExtension('EXT_color_buffer_half_float') ||
+ gl.getExtension('WEBGL_color_buffer_float');
+ if (!ext) return;
+ }
+
+ // WebGL 2.0 or extended WebGL 1.0 may still clamp the value on store
+ // when the underlying platform does the same.
+ gl.blendColor(1000, 1, 1, 1);
+ const was = gl.getParameter(gl.BLEND_COLOR);
+ if (was[0] == 1000) {
+ expectArray(was, [1000, 1, 1, 1]);
+ } else {
+ debug("Platform does not support unclamped blend color.")
+ expectArray(was, [1, 1, 1, 1]);
+ }
+ },
+ () => {
+ debug('');
+ debug('Blending for RGBA8:');
+
+ const gl = CreateContext();
+ fb = CreateValidFb(gl, [[gl.RGBA8, gl.RGBA, gl.UNSIGNED_BYTE]]);
+ shouldBeNonNull('fb');
+
+ // Regardless of the context version and enabled extensions,
+ // the value will be clamped at draw time,
+ gl.blendColor(10, 1, 1, 1);
+ const was = gl.drawAndRead(gl.UNSIGNED_BYTE);
+ expectArray(was, [1, 2, 3, 4]);
+
+ if (gl.getExtension('EXT_color_buffer_half_float') ||
+ gl.getExtension('WEBGL_color_buffer_float') ||
+ gl.getExtension('EXT_color_buffer_float'))
+ {
+ debug('Enable floating-point color buffers and retest');
+ gl.blendColor(1000, 1, 1, 1);
+ const was = gl.drawAndRead(gl.UNSIGNED_BYTE);
+ expectArray(was, [1, 2, 3, 4]);
+ }
+ },
+ () => {
+ debug('');
+ debug('Blending for RGBA16F:');
+
+ const gl = CreateContext();
+
+ // Set the value before enabling the extension.
+ // It must be clamped only on WebGL 1.0 contexts.
+ gl.blendColor(10, 1, 1, 1);
+ if (!gl.getExtension('EXT_color_buffer_half_float')) {
+ testPassed('Missing ext EXT_color_buffer_half_float is optional, skipping.');
+ return;
+ }
+ if (!gl.texImage3D) { // WebGL 1.0
+ const ext = gl.getExtension('OES_texture_half_float');
+ gl.HALF_FLOAT = ext.HALF_FLOAT_OES; // These aren't the same value, but this'll work.
+ }
+
+ fb = CreateValidFb(gl, [[gl.RGBA16F, gl.RGBA, gl.HALF_FLOAT]]);
+ shouldBeNonNull('fb');
+ gl.prog.uColor([1, 2, 3, 4]);
+
+ let was = gl.drawAndRead(gl.FLOAT);
+ if (!gl.texImage3D) { // WebGL 1.0
+ expectArray(was, [1, 2, 3, 4]);
+ } else {
+ // Some WebGL 2.0 implementations may clamp the blend color anyway.
+ const r = gl.getParameter(gl.BLEND_COLOR)[0];
+ expectArray(was, [r, 2, 3, 4]);
+ }
+
+ // Re-set the value after the extension was enabled.
+ gl.blendColor(100, 1, 1, 1);
+ const r = gl.getParameter(gl.BLEND_COLOR)[0];
+ was = gl.drawAndRead(gl.FLOAT);
+ expectArray(was, [r, 2, 3, 4]);
+ },
+ () => {
+ debug('');
+ debug('Blending for RGBA32F:');
+
+ const gl = CreateContext();
+
+ // Set the value before enabling the extension.
+ // It must be clamped only on WebGL 1.0 contexts.
+ gl.blendColor(10, 1, 1, 1);
+ if (gl.texImage3D) { // WebGL 2.0
+ if (!gl.getExtension('EXT_color_buffer_float')) {
+ testPassed('Missing ext EXT_color_buffer_float is optional, skipping.');
+ return;
+ }
+ } else {
+ if (!gl.getExtension('WEBGL_color_buffer_float')) {
+ testPassed('Missing ext WEBGL_color_buffer_float is optional, skipping.');
+ return;
+ }
+ gl.getExtension('OES_texture_float');
+ }
+ fb = CreateValidFb(gl, [[gl.RGBA32F, gl.RGBA, gl.FLOAT]]);
+ shouldBeNonNull('fb');
+ gl.prog.uColor([1, 2, 3, 4]);
+
+ let was = gl.drawAndRead(gl.FLOAT);
+ if (!gl.texImage3D) { // WebGL 1.0
+ expectArray(was, [1, 2, 3, 4]);
+ } else {
+ // Some WebGL 2.0 implementations may clamp the blend color anyway.
+ const r = gl.getParameter(gl.BLEND_COLOR)[0];
+ expectArray(was, [r, 2, 3, 4]);
+ }
+
+ // Re-set the value after the extension was enabled.
+ gl.blendColor(100, 1, 1, 1);
+ const r = gl.getParameter(gl.BLEND_COLOR)[0];
+ was = gl.drawAndRead(gl.FLOAT);
+
+ if (!gl.getExtension('EXT_float_blend')) {
+ wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, 'Should not be able to blend 32F formats.');
+ return;
+ }
+ wtu.glErrorShouldBe(gl, 0, 'Should be able to blend 32F formats.');
+ expectArray(was, [r, 2, 3, 4]);
+ },
+];
+
+async function Test() {
+ for (const fn of TESTS) {
+ await wtu.dispatchPromise(fn);
+ }
+ wtu.destroyAllContexts();
+ finishTest();
+}
+
+Test();
+
+var successfullyParsed = true;
+</script>
+</body>
+</html>