diff options
Diffstat (limited to 'dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/immutable-tex-render-feedback.html')
-rw-r--r-- | dom/canvas/test/webgl-conf/checkout/conformance2/textures/misc/immutable-tex-render-feedback.html | 221 |
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> |