Backed out changeset 7272b7396c78 (bug 1932758) for causing fenix debug failures...
[gecko.git] / dom / canvas / test / webgl-conf / checkout / conformance2 / textures / misc / immutable-tex-render-feedback.html
blobc94e359d644c831ede2073e08ecdc52544b34dc1
1 <!--
2 Copyright (c) 2019 The Khronos Group Inc.
3 Use of this source code is governed by an MIT-style license that can be
4 found in the LICENSE.txt file.
5 -->
7 <!DOCTYPE html>
8 <html>
9 <head>
10 <meta charset="utf-8">
11 <title>Ensure sampling-feedback detection can allow certain immutable texture uses</title>
12 <link rel="stylesheet" href="../../../resources/js-test-style.css"/>
13 <script src="../../../js/js-test-pre.js"></script>
14 <script src="../../../js/webgl-test-utils.js"></script>
15 </head>
16 <body>
17 <div id="description"></div>
18 <div id="console"></div>
19 <script>
20 "use strict";
22 const wtu = WebGLTestUtils;
23 description();
25 const gl = wtu.create3DContext(undefined, undefined, 2);
27 function* range(a, b) {
28 a.required;
29 if (b === undefined) {
30 b = a;
31 a = 0;
33 for (let i = a; i < b; i += 1) {
34 yield i;
38 const VS = `\
39 void main() {
40 gl_PointSize = 1.0;
44 const FS = `\
45 uniform sampler2D u_tex0;
46 void main() {
47 gl_FragColor = texture2D(u_tex0, vec2(0));
51 const prog = wtu.loadProgram(gl, VS, FS);
52 gl.useProgram(prog);
54 (() => {
55 const MIPS = 3;
56 const SIZE = 10;
58 const immutTex = gl.createTexture();
59 immutTex.name = "immutTex";
60 immutTex.immutable = true;
61 gl.bindTexture(gl.TEXTURE_2D, immutTex);
62 gl.texStorage2D(gl.TEXTURE_2D, MIPS, gl.RGBA8, SIZE, SIZE);
64 const mutTex = gl.createTexture();
65 mutTex.name = "mutTex";
66 mutTex.immutable = false;
67 gl.bindTexture(gl.TEXTURE_2D, mutTex);
68 for (const mip of range(MIPS)) {
69 const size = SIZE >> mip;
70 gl.texImage2D(gl.TEXTURE_2D, mip, gl.RGBA8, size, size, 0,
71 gl.RGBA, gl.UNSIGNED_BYTE, null);
74 const MAG_FILTERS = [
75 'LINEAR',
76 'NEAREST',
78 const MIN_FILTERS = [
79 ['LINEAR',false],
80 ['LINEAR_MIPMAP_LINEAR',true],
81 ['LINEAR_MIPMAP_NEAREST',true],
82 ['NEAREST',false],
83 ['NEAREST_MIPMAP_LINEAR',true],
84 ['NEAREST_MIPMAP_NEAREST',true],
87 const fb = gl.createFramebuffer();
88 gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
90 debug(`
91 mips: ${MIPS}: [0,${MIPS-1}] (inclusive)
92 size: ${SIZE}`);
93 const texs = [
94 immutTex,
95 mutTex,
97 for (const tex of texs) {
98 debug(`\
100 immutable: ${tex.immutable}`);
101 gl.bindTexture(gl.TEXTURE_2D, tex);
103 for (const level_prime_base of range(MIPS+1)) { // `level_base` in GLES
104 // ES 3.0.6 p150
105 let _level_base = level_prime_base;
106 if (tex.immutable) {
107 _level_base = Math.min(_level_base, MIPS-1);
109 const level_base = _level_base;
111 for (let _level_prime_max of range(level_prime_base-1, MIPS+2)) { // `q` in GLES
112 if (_level_prime_max < 0) continue;
113 if (_level_prime_max == MIPS+1) {
114 _level_prime_max = 10000; // This is the default, after all!
116 const level_prime_max = _level_prime_max;
118 // ES 3.0.6 p150
119 let _level_max = level_prime_max;
120 if (tex.immutable) {
121 _level_max = Math.min(Math.max(level_base, level_prime_max), MIPS-1);
123 const level_max = _level_max;
125 const p = Math.floor(Math.log2(SIZE)) + level_base;
126 const q = Math.min(p, level_max);
128 debug(`\
130 level_prime_base/max: [${level_prime_base}, ${level_prime_max}] (inclusive)
131 level_base/max: [${level_base}, ${level_max}] (inclusive)
132 q: ${q}`);
133 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_BASE_LEVEL,
134 level_prime_base);
135 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAX_LEVEL,
136 level_prime_max);
138 const mipComplete = (q <= MIPS-1);
140 for (const [minFilter,useMips] of MIN_FILTERS) {
141 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER,
142 gl[minFilter]);
144 // ES3.0 p211
145 const srcMaxSampledMip = (useMips ? q : level_base);
147 // ES3.0 p160-161
148 const textureComplete = (srcMaxSampledMip <= MIPS-1) &&
149 (level_base <= level_max);
151 for (const magFilter of MAG_FILTERS) {
152 debug(`\
154 min: ${minFilter}, mag: ${magFilter}`);
155 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER,
156 gl[magFilter]);
158 for (const dstMip of range(0,MIPS+1)) {
159 debug(`
160 mip: ${dstMip}`);
161 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
162 gl.TEXTURE_2D, tex, dstMip);
164 // -
166 // ES3.0 p213-214
167 let fbComplete = true;
169 // * "The width and height of `image` are non-zero"
170 fbComplete &= (0 <= dstMip && dstMip <= MIPS-1);
172 if (!tex.immutable) { // "...does not name an immutable-format texture..."
173 // * "...the value of [level] must be in the range `[level_base, q]`"
174 fbComplete &= (level_base <= dstMip && dstMip <= q);
176 // * "...the value of [level] is not `level_base`, then the texture must be mipmap complete"
177 if (dstMip != level_base) {
178 fbComplete &= mipComplete;
182 // -
184 let expectError = 0;
185 let expectStatus = gl.FRAMEBUFFER_COMPLETE;
187 // ES3.0 p211
188 let samplingFeedback = (level_base <= dstMip && dstMip <= srcMaxSampledMip);
189 if (!textureComplete) {
190 // Incomplete textures are safe
191 samplingFeedback = false;
193 if (samplingFeedback) {
194 expectError = gl.INVALID_OPERATION;
196 if (!fbComplete) {
197 expectStatus = gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
198 expectError = gl.INVALID_FRAMEBUFFER_OPERATION;
201 // -
203 wtu.framebufferStatusShouldBe(gl, gl.FRAMEBUFFER,
204 expectStatus, `{immutable: ${tex.immutable}, level_prime_base/max: [${level_prime_base}, ${level_prime_max}], minFilter: ${minFilter}, dest: ${dstMip}}`);
206 gl.drawArrays(gl.POINTS, 0, 1);
207 wtu.glErrorShouldBe(gl, expectError, "after draw with texture");
214 })();
216 var successfullyParsed = true;
217 </script>
218 <script src="../../../js/js-test-post.js"></script>
220 </body>
221 </html>