Backed out changeset 7272b7396c78 (bug 1932758) for causing fenix debug failures...
[gecko.git] / dom / canvas / test / webgl-conf / checkout / conformance2 / extensions / webgl-stencil-texturing.html
blob729a5bcf8a72586faa67c52481522803945dce1b
1 <!--
2 Copyright (c) 2023 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>WebGL WEBGL_stencil_texturing Conformance Tests</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";
21 description("This test verifies the functionality of the WEBGL_stencil_texturing extension, if it is available.");
23 debug("");
25 var wtu = WebGLTestUtils;
26 var gl = wtu.create3DContext(null, null, 2);
27 var ext;
29 function runTestNoExtension() {
30 debug("");
31 debug("Check the texture parameter without the extension");
33 const tex = gl.createTexture();
34 gl.bindTexture(gl.TEXTURE_2D, tex);
36 shouldBeNull("gl.getTexParameter(gl.TEXTURE_2D, 0x90EA /* DEPTH_STENCIL_TEXTURE_MODE_WEBGL */)");
37 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "parameter unknown without enabling the extension");
38 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no more errors");
40 gl.texParameteri(gl.TEXTURE_2D, 0x90EA /* DEPTH_STENCIL_TEXTURE_MODE_WEBGL */, gl.DEPTH_COMPONENT);
41 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "parameter unknown for texParameteri without enabling the extension");
42 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no more errors");
44 gl.texParameterf(gl.TEXTURE_2D, 0x90EA /* DEPTH_STENCIL_TEXTURE_MODE_WEBGL */, gl.DEPTH_COMPONENT);
45 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "parameter unknown for texParameterf without enabling the extension");
46 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no more errors");
48 const sampler = gl.createSampler();
49 gl.samplerParameteri(sampler, 0x90EA /* DEPTH_STENCIL_TEXTURE_MODE_WEBGL */, gl.DEPTH_COMPONENT);
50 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "parameter unknown for samplerParameteri");
51 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no more errors");
52 gl.samplerParameterf(sampler, 0x90EA /* DEPTH_STENCIL_TEXTURE_MODE_WEBGL */, gl.DEPTH_COMPONENT);
53 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "parameter unknown for samplerParameterf");
54 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no more errors");
57 function checkEnums() {
58 debug("");
59 debug("Check enums");
60 shouldBe("ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL", "0x90EA");
61 shouldBe("ext.STENCIL_INDEX_WEBGL", "0x1901");
64 function checkQueries() {
65 const tex = gl.createTexture();
66 gl.bindTexture(gl.TEXTURE_2D, tex);
68 debug("");
69 debug("Check default texture state");
70 shouldBe('gl.getTexParameter(gl.TEXTURE_2D, ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL)', 'gl.DEPTH_COMPONENT');
71 debug("");
72 debug("Check texture state updates using texParameteri");
73 gl.texParameteri(gl.TEXTURE_2D, ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL, ext.STENCIL_INDEX_WEBGL);
74 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
75 shouldBe('gl.getTexParameter(gl.TEXTURE_2D, ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL)', 'ext.STENCIL_INDEX_WEBGL');
76 gl.texParameteri(gl.TEXTURE_2D, ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL, gl.DEPTH_COMPONENT);
77 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
78 shouldBe('gl.getTexParameter(gl.TEXTURE_2D, ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL)', 'gl.DEPTH_COMPONENT');
79 gl.texParameteri(gl.TEXTURE_2D, ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL, 0);
80 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "invalid depth stencil mode value rejected by texParameteri");
81 shouldBe('gl.getTexParameter(gl.TEXTURE_2D, ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL)', 'gl.DEPTH_COMPONENT');
82 debug("");
83 debug("Check texture state updates using texParameterf");
84 gl.texParameterf(gl.TEXTURE_2D, ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL, ext.STENCIL_INDEX_WEBGL);
85 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
86 shouldBe('gl.getTexParameter(gl.TEXTURE_2D, ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL)', 'ext.STENCIL_INDEX_WEBGL');
87 gl.texParameterf(gl.TEXTURE_2D, ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL, gl.DEPTH_COMPONENT);
88 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
89 shouldBe('gl.getTexParameter(gl.TEXTURE_2D, ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL)', 'gl.DEPTH_COMPONENT');
90 gl.texParameterf(gl.TEXTURE_2D, ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL, 0);
91 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "invalid depth stencil mode value rejected by texParameterf");
92 shouldBe('gl.getTexParameter(gl.TEXTURE_2D, ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL)', 'gl.DEPTH_COMPONENT');
94 debug("");
95 debug("Check that depth stencil texture mode is not accepted as a sampler state");
96 const sampler = gl.createSampler();
97 gl.samplerParameteri(sampler, ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL, gl.DEPTH_COMPONENT);
98 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "parameter unknown for samplerParameteri");
99 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no more errors");
100 gl.samplerParameterf(sampler, ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL, gl.DEPTH_COMPONENT);
101 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "parameter unknown for samplerParameterf");
102 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no more errors");
105 function checkSampling() {
106 const formats = [
107 {name: "DEPTH_COMPONENT16", internalFormat: gl.DEPTH_COMPONENT16,
108 format: gl.DEPTH_COMPONENT, type: gl.UNSIGNED_SHORT},
109 {name: "DEPTH_COMPONENT24", internalFormat: gl.DEPTH_COMPONENT24,
110 format: gl.DEPTH_COMPONENT, type: gl.UNSIGNED_INT},
111 {name: "DEPTH_COMPONENT32F", internalFormat: gl.DEPTH_COMPONENT32F,
112 format: gl.DEPTH_COMPONENT, type: gl.FLOAT},
113 {name: "DEPTH24_STENCIL8", internalFormat: gl.DEPTH24_STENCIL8,
114 format: gl.DEPTH_STENCIL, type: gl.UNSIGNED_INT_24_8},
115 {name: "DEPTH32F_STENCIL8", internalFormat: gl.DEPTH32F_STENCIL8,
116 format: gl.DEPTH_STENCIL, type: gl.FLOAT_32_UNSIGNED_INT_24_8_REV}
119 gl.enable(gl.DEPTH_TEST);
120 gl.enable(gl.STENCIL_TEST);
121 gl.stencilFunc(gl.ALWAYS, 170, 0xFF);
122 gl.stencilOp(gl.REPLACE, gl.REPLACE, gl.REPLACE);
124 wtu.setupUnitQuad(gl);
126 const drawProgram = wtu.setupProgram(gl, [wtu.simpleVertexShader,
127 wtu.simpleColorFragmentShader]);
129 const readDepthProgram = wtu.setupProgram(gl, [wtu.simpleTextureVertexShaderESSL300,
130 wtu.simpleTextureFragmentShaderESSL300]);
132 const readStencilShader = `#version 300 es
133 precision highp float;
134 uniform highp usampler2D tex;
135 in vec2 texCoord;
136 out vec4 out_color;
137 void main() {
138 out_color = vec4(texture(tex, texCoord)) / 255.0;
140 const readStencilProgram = wtu.setupProgram(gl, [wtu.simpleTextureVertexShaderESSL300,
141 readStencilShader]);
143 for (const format of formats) {
144 debug("");
145 debug(`Testing depth stencil texture modes with ${format.name}`);
146 const fbo = gl.createFramebuffer();
147 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
149 const rbo = gl.createRenderbuffer();
150 gl.bindRenderbuffer(gl.RENDERBUFFER, rbo);
151 gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA8, 1, 1);
152 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo);
154 const tex = gl.createTexture();
155 gl.bindTexture(gl.TEXTURE_2D, tex);
156 gl.texImage2D(gl.TEXTURE_2D, 0, format.internalFormat, 1, 1, 0, format.format, format.type, null);
157 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texture created");
159 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, tex, 0);
160 if (format.format == gl.DEPTH_STENCIL) {
161 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.TEXTURE_2D, tex, 0);
163 wtu.framebufferStatusShouldBe(gl, gl.FRAMEBUFFER, gl.FRAMEBUFFER_COMPLETE);
165 gl.clear(gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
166 gl.useProgram(drawProgram);
167 wtu.drawUnitQuad(gl);
168 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no errors after drawing to the depth or depth stencil texture");
170 // Detach the depth or depth stencil texture to avoid feedback loop
171 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, null);
172 wtu.framebufferStatusShouldBe(gl, gl.FRAMEBUFFER, gl.FRAMEBUFFER_COMPLETE);
174 const magFilters = ['NEAREST', 'LINEAR'];
176 const minFilters = [
177 'NEAREST',
178 'LINEAR',
179 'NEAREST_MIPMAP_NEAREST',
180 'LINEAR_MIPMAP_NEAREST',
181 'NEAREST_MIPMAP_LINEAR',
182 'LINEAR_MIPMAP_LINEAR'
185 const modes = [
186 [gl.DEPTH_COMPONENT, 'DEPTH_COMPONENT'],
187 [ext.STENCIL_INDEX_WEBGL, 'STENCIL_INDEX_WEBGL']
190 const programs = [
191 [readDepthProgram, 'depth'],
192 [readStencilProgram, 'stencil']
195 function validFilters(magFilter, minFilter) {
196 return magFilter == gl.NEAREST &&
197 (minFilter == gl.NEAREST || minFilter == gl.NEAREST_MIPMAP_NEAREST);
200 for (const program of programs) {
201 gl.useProgram(program[0]);
202 for (const mode of modes) {
203 gl.texParameteri(gl.TEXTURE_2D, ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL, mode[0]);
204 for (const magFilter of magFilters) {
205 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl[magFilter]);
206 for (const minFilter of minFilters) {
207 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl[minFilter]);
208 debug(`Program: ${program[1]}, mode: ${mode[1]}, mag: ${magFilter}, min: ${minFilter}`);
210 gl.clear(gl.COLOR_BUFFER_BIT);
211 wtu.drawUnitQuad(gl);
213 if (format.format == gl.DEPTH_COMPONENT || mode[0] == gl.DEPTH_COMPONENT) {
214 if (program[1] == 'depth') {
215 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
216 if (validFilters(gl[magFilter], gl[minFilter])) {
217 wtu.checkCanvasRect(gl, 0, 0, 1, 1, [128, 0, 0, 255], "sampling depth from complete texture", 1);
218 } else {
219 wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 0, 0, 255], "sampling depth from incomplete texture", 1);
221 } else {
222 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "sampling depth using incompatible program");
224 } else {
225 if (program[1] == 'stencil') {
226 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors");
227 if (validFilters(gl[magFilter], gl[minFilter])) {
228 wtu.checkCanvasRect(gl, 0, 0, 1, 1, [170, 0, 0, 1], "sampling stencil from complete texture", 1);
229 } else {
230 // Incomplete textures may produce [0, 0, 0, 1] or [0, 0, 0, 255].
231 const value = new Uint8Array(4);
232 gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, value);
233 wtu.glErrorShouldBe(gl, gl.NO_ERROR);
234 const msg = "sampling stencil from incomplete texture";
235 if (value[0] == 0 && value[1] == 0 && value[2] == 0 && (value[3] == 1 || value[3] == 255)) {
236 testPassed(msg);
237 } else {
238 testFailed(`${msg}: ${value}`);
241 } else {
242 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "sampling stencil using incompatible program");
252 function runTest() {
253 if (!gl) {
254 testFailed("context does not exist");
255 return;
257 testPassed("context exists");
259 runTestNoExtension();
261 ext = gl.getExtension("WEBGL_stencil_texturing");
262 wtu.runExtensionSupportedTest(gl, "WEBGL_stencil_texturing", ext !== null);
264 if (ext !== null) {
265 checkEnums();
266 checkQueries();
267 checkSampling();
268 } else {
269 testPassed("No WEBGL_stencil_texturing support -- this is legal");
273 runTest();
275 var successfullyParsed = true;
276 </script>
277 <script src="../../js/js-test-post.js"></script>
278 </body>
279 </html>