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.
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>
17 <div id=
"description"></div>
18 <div id=
"console"></div>
21 description("This test verifies the functionality of the WEBGL_stencil_texturing extension, if it is available.");
25 var wtu
= WebGLTestUtils
;
26 var gl
= wtu
.create3DContext(null, null, 2);
29 function runTestNoExtension() {
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() {
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
);
69 debug("Check default texture state");
70 shouldBe('gl.getTexParameter(gl.TEXTURE_2D, ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL)', 'gl.DEPTH_COMPONENT');
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');
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');
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() {
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;
138 out_color = vec4(texture(tex, texCoord)) / 255.0;
140 const readStencilProgram
= wtu
.setupProgram(gl
, [wtu
.simpleTextureVertexShaderESSL300
,
143 for (const format
of formats
) {
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'];
179 'NEAREST_MIPMAP_NEAREST',
180 'LINEAR_MIPMAP_NEAREST',
181 'NEAREST_MIPMAP_LINEAR',
182 'LINEAR_MIPMAP_LINEAR'
186 [gl
.DEPTH_COMPONENT
, 'DEPTH_COMPONENT'],
187 [ext
.STENCIL_INDEX_WEBGL
, 'STENCIL_INDEX_WEBGL']
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);
219 wtu
.checkCanvasRect(gl
, 0, 0, 1, 1, [0, 0, 0, 255], "sampling depth from incomplete texture", 1);
222 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "sampling depth using incompatible program");
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);
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)) {
238 testFailed(`${msg}: ${value}`);
242 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "sampling stencil using incompatible program");
254 testFailed("context does not exist");
257 testPassed("context exists");
259 runTestNoExtension();
261 ext
= gl
.getExtension("WEBGL_stencil_texturing");
262 wtu
.runExtensionSupportedTest(gl
, "WEBGL_stencil_texturing", ext
!== null);
269 testPassed("No WEBGL_stencil_texturing support -- this is legal");
275 var successfullyParsed
= true;
277 <script src=
"../../js/js-test-post.js"></script>