summaryrefslogtreecommitdiffstats
path: root/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/immutable-tex-render-feedback.html
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/immutable-tex-render-feedback.html221
1 files changed, 221 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/immutable-tex-render-feedback.html b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/immutable-tex-render-feedback.html
new file mode 100644
index 0000000000..c94e359d64
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/immutable-tex-render-feedback.html
@@ -0,0 +1,221 @@
+<!--
+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">
+<title>Ensure sampling-feedback detection can allow certain immutable texture uses</title>
+<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>
+</head>
+<body>
+<div id="description"></div>
+<div id="console"></div>
+<script>
+"use strict";
+
+const wtu = WebGLTestUtils;
+description();
+
+const gl = wtu.create3DContext(undefined, undefined, 2);
+
+function* range(a, b) {
+ a.required;
+ if (b === undefined) {
+ b = a;
+ a = 0;
+ }
+ for (let i = a; i < b; i += 1) {
+ yield i;
+ }
+}
+
+const VS = `\
+void main() {
+ gl_PointSize = 1.0;
+}
+`;
+
+const FS = `\
+uniform sampler2D u_tex0;
+void main() {
+ gl_FragColor = texture2D(u_tex0, vec2(0));
+}
+`;
+
+const prog = wtu.loadProgram(gl, VS, FS);
+gl.useProgram(prog);
+
+(() => {
+ const MIPS = 3;
+ const SIZE = 10;
+
+ const immutTex = gl.createTexture();
+ immutTex.name = "immutTex";
+ immutTex.immutable = true;
+ gl.bindTexture(gl.TEXTURE_2D, immutTex);
+ gl.texStorage2D(gl.TEXTURE_2D, MIPS, gl.RGBA8, SIZE, SIZE);
+
+ const mutTex = gl.createTexture();
+ mutTex.name = "mutTex";
+ mutTex.immutable = false;
+ gl.bindTexture(gl.TEXTURE_2D, mutTex);
+ for (const mip of range(MIPS)) {
+ const size = SIZE >> mip;
+ gl.texImage2D(gl.TEXTURE_2D, mip, gl.RGBA8, size, size, 0,
+ gl.RGBA, gl.UNSIGNED_BYTE, null);
+ }
+
+ const MAG_FILTERS = [
+ 'LINEAR',
+ 'NEAREST',
+ ];
+ const MIN_FILTERS = [
+ ['LINEAR',false],
+ ['LINEAR_MIPMAP_LINEAR',true],
+ ['LINEAR_MIPMAP_NEAREST',true],
+ ['NEAREST',false],
+ ['NEAREST_MIPMAP_LINEAR',true],
+ ['NEAREST_MIPMAP_NEAREST',true],
+ ];
+
+ const fb = gl.createFramebuffer();
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
+
+ debug(`
+ mips: ${MIPS}: [0,${MIPS-1}] (inclusive)
+ size: ${SIZE}`);
+ const texs = [
+ immutTex,
+ mutTex,
+ ];
+ for (const tex of texs) {
+ debug(`\
+
+ immutable: ${tex.immutable}`);
+ gl.bindTexture(gl.TEXTURE_2D, tex);
+
+ for (const level_prime_base of range(MIPS+1)) { // `level_base` in GLES
+ // ES 3.0.6 p150
+ let _level_base = level_prime_base;
+ if (tex.immutable) {
+ _level_base = Math.min(_level_base, MIPS-1);
+ }
+ const level_base = _level_base;
+
+ for (let _level_prime_max of range(level_prime_base-1, MIPS+2)) { // `q` in GLES
+ if (_level_prime_max < 0) continue;
+ if (_level_prime_max == MIPS+1) {
+ _level_prime_max = 10000; // This is the default, after all!
+ }
+ const level_prime_max = _level_prime_max;
+
+ // ES 3.0.6 p150
+ let _level_max = level_prime_max;
+ if (tex.immutable) {
+ _level_max = Math.min(Math.max(level_base, level_prime_max), MIPS-1);
+ }
+ const level_max = _level_max;
+
+ const p = Math.floor(Math.log2(SIZE)) + level_base;
+ const q = Math.min(p, level_max);
+
+ debug(`\
+
+ level_prime_base/max: [${level_prime_base}, ${level_prime_max}] (inclusive)
+ level_base/max: [${level_base}, ${level_max}] (inclusive)
+ q: ${q}`);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_BASE_LEVEL,
+ level_prime_base);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAX_LEVEL,
+ level_prime_max);
+
+ const mipComplete = (q <= MIPS-1);
+
+ for (const [minFilter,useMips] of MIN_FILTERS) {
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER,
+ gl[minFilter]);
+
+ // ES3.0 p211
+ const srcMaxSampledMip = (useMips ? q : level_base);
+
+ // ES3.0 p160-161
+ const textureComplete = (srcMaxSampledMip <= MIPS-1) &&
+ (level_base <= level_max);
+
+ for (const magFilter of MAG_FILTERS) {
+ debug(`\
+
+ min: ${minFilter}, mag: ${magFilter}`);
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER,
+ gl[magFilter]);
+
+ for (const dstMip of range(0,MIPS+1)) {
+ debug(`
+ mip: ${dstMip}`);
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
+ gl.TEXTURE_2D, tex, dstMip);
+
+ // -
+
+ // ES3.0 p213-214
+ let fbComplete = true;
+
+ // * "The width and height of `image` are non-zero"
+ fbComplete &= (0 <= dstMip && dstMip <= MIPS-1);
+
+ if (!tex.immutable) { // "...does not name an immutable-format texture..."
+ // * "...the value of [level] must be in the range `[level_base, q]`"
+ fbComplete &= (level_base <= dstMip && dstMip <= q);
+
+ // * "...the value of [level] is not `level_base`, then the texture must be mipmap complete"
+ if (dstMip != level_base) {
+ fbComplete &= mipComplete;
+ }
+ }
+
+ // -
+
+ let expectError = 0;
+ let expectStatus = gl.FRAMEBUFFER_COMPLETE;
+
+ // ES3.0 p211
+ let samplingFeedback = (level_base <= dstMip && dstMip <= srcMaxSampledMip);
+ if (!textureComplete) {
+ // Incomplete textures are safe
+ samplingFeedback = false;
+ }
+ if (samplingFeedback) {
+ expectError = gl.INVALID_OPERATION;
+ }
+ if (!fbComplete) {
+ expectStatus = gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ expectError = gl.INVALID_FRAMEBUFFER_OPERATION;
+ }
+
+ // -
+
+ wtu.framebufferStatusShouldBe(gl, gl.FRAMEBUFFER,
+ expectStatus, `{immutable: ${tex.immutable}, level_prime_base/max: [${level_prime_base}, ${level_prime_max}], minFilter: ${minFilter}, dest: ${dstMip}}`);
+
+ gl.drawArrays(gl.POINTS, 0, 1);
+ wtu.glErrorShouldBe(gl, expectError, "after draw with texture");
+ }
+ }
+ }
+ }
+ }
+ }
+})();
+
+var successfullyParsed = true;
+</script>
+<script src="../../../js/js-test-post.js"></script>
+
+</body>
+</html>