diff options
Diffstat (limited to 'dom/canvas/test/webgl-conf/checkout/conformance2/extensions/webgl-stencil-texturing.html')
-rw-r--r-- | dom/canvas/test/webgl-conf/checkout/conformance2/extensions/webgl-stencil-texturing.html | 279 |
1 files changed, 279 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/webgl-stencil-texturing.html b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/webgl-stencil-texturing.html new file mode 100644 index 0000000000..729a5bcf8a --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/extensions/webgl-stencil-texturing.html @@ -0,0 +1,279 @@ +<!-- +Copyright (c) 2023 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>WebGL WEBGL_stencil_texturing Conformance Tests</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"; +description("This test verifies the functionality of the WEBGL_stencil_texturing extension, if it is available."); + +debug(""); + +var wtu = WebGLTestUtils; +var gl = wtu.create3DContext(null, null, 2); +var ext; + +function runTestNoExtension() { + debug(""); + debug("Check the texture parameter without the extension"); + + const tex = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, tex); + + shouldBeNull("gl.getTexParameter(gl.TEXTURE_2D, 0x90EA /* DEPTH_STENCIL_TEXTURE_MODE_WEBGL */)"); + wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "parameter unknown without enabling the extension"); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no more errors"); + + gl.texParameteri(gl.TEXTURE_2D, 0x90EA /* DEPTH_STENCIL_TEXTURE_MODE_WEBGL */, gl.DEPTH_COMPONENT); + wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "parameter unknown for texParameteri without enabling the extension"); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no more errors"); + + gl.texParameterf(gl.TEXTURE_2D, 0x90EA /* DEPTH_STENCIL_TEXTURE_MODE_WEBGL */, gl.DEPTH_COMPONENT); + wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "parameter unknown for texParameterf without enabling the extension"); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no more errors"); + + const sampler = gl.createSampler(); + gl.samplerParameteri(sampler, 0x90EA /* DEPTH_STENCIL_TEXTURE_MODE_WEBGL */, gl.DEPTH_COMPONENT); + wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "parameter unknown for samplerParameteri"); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no more errors"); + gl.samplerParameterf(sampler, 0x90EA /* DEPTH_STENCIL_TEXTURE_MODE_WEBGL */, gl.DEPTH_COMPONENT); + wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "parameter unknown for samplerParameterf"); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no more errors"); +} + +function checkEnums() { + debug(""); + debug("Check enums"); + shouldBe("ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL", "0x90EA"); + shouldBe("ext.STENCIL_INDEX_WEBGL", "0x1901"); +} + +function checkQueries() { + const tex = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, tex); + + debug(""); + debug("Check default texture state"); + shouldBe('gl.getTexParameter(gl.TEXTURE_2D, ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL)', 'gl.DEPTH_COMPONENT'); + debug(""); + debug("Check texture state updates using texParameteri"); + gl.texParameteri(gl.TEXTURE_2D, ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL, ext.STENCIL_INDEX_WEBGL); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors"); + shouldBe('gl.getTexParameter(gl.TEXTURE_2D, ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL)', 'ext.STENCIL_INDEX_WEBGL'); + gl.texParameteri(gl.TEXTURE_2D, ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL, gl.DEPTH_COMPONENT); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors"); + shouldBe('gl.getTexParameter(gl.TEXTURE_2D, ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL)', 'gl.DEPTH_COMPONENT'); + gl.texParameteri(gl.TEXTURE_2D, ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL, 0); + wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "invalid depth stencil mode value rejected by texParameteri"); + shouldBe('gl.getTexParameter(gl.TEXTURE_2D, ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL)', 'gl.DEPTH_COMPONENT'); + debug(""); + debug("Check texture state updates using texParameterf"); + gl.texParameterf(gl.TEXTURE_2D, ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL, ext.STENCIL_INDEX_WEBGL); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors"); + shouldBe('gl.getTexParameter(gl.TEXTURE_2D, ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL)', 'ext.STENCIL_INDEX_WEBGL'); + gl.texParameterf(gl.TEXTURE_2D, ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL, gl.DEPTH_COMPONENT); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors"); + shouldBe('gl.getTexParameter(gl.TEXTURE_2D, ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL)', 'gl.DEPTH_COMPONENT'); + gl.texParameterf(gl.TEXTURE_2D, ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL, 0); + wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "invalid depth stencil mode value rejected by texParameterf"); + shouldBe('gl.getTexParameter(gl.TEXTURE_2D, ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL)', 'gl.DEPTH_COMPONENT'); + + debug(""); + debug("Check that depth stencil texture mode is not accepted as a sampler state"); + const sampler = gl.createSampler(); + gl.samplerParameteri(sampler, ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL, gl.DEPTH_COMPONENT); + wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "parameter unknown for samplerParameteri"); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no more errors"); + gl.samplerParameterf(sampler, ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL, gl.DEPTH_COMPONENT); + wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "parameter unknown for samplerParameterf"); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no more errors"); +} + +function checkSampling() { + const formats = [ + {name: "DEPTH_COMPONENT16", internalFormat: gl.DEPTH_COMPONENT16, + format: gl.DEPTH_COMPONENT, type: gl.UNSIGNED_SHORT}, + {name: "DEPTH_COMPONENT24", internalFormat: gl.DEPTH_COMPONENT24, + format: gl.DEPTH_COMPONENT, type: gl.UNSIGNED_INT}, + {name: "DEPTH_COMPONENT32F", internalFormat: gl.DEPTH_COMPONENT32F, + format: gl.DEPTH_COMPONENT, type: gl.FLOAT}, + {name: "DEPTH24_STENCIL8", internalFormat: gl.DEPTH24_STENCIL8, + format: gl.DEPTH_STENCIL, type: gl.UNSIGNED_INT_24_8}, + {name: "DEPTH32F_STENCIL8", internalFormat: gl.DEPTH32F_STENCIL8, + format: gl.DEPTH_STENCIL, type: gl.FLOAT_32_UNSIGNED_INT_24_8_REV} + ]; + + gl.enable(gl.DEPTH_TEST); + gl.enable(gl.STENCIL_TEST); + gl.stencilFunc(gl.ALWAYS, 170, 0xFF); + gl.stencilOp(gl.REPLACE, gl.REPLACE, gl.REPLACE); + + wtu.setupUnitQuad(gl); + + const drawProgram = wtu.setupProgram(gl, [wtu.simpleVertexShader, + wtu.simpleColorFragmentShader]); + + const readDepthProgram = wtu.setupProgram(gl, [wtu.simpleTextureVertexShaderESSL300, + wtu.simpleTextureFragmentShaderESSL300]); + + const readStencilShader = `#version 300 es + precision highp float; + uniform highp usampler2D tex; + in vec2 texCoord; + out vec4 out_color; + void main() { + out_color = vec4(texture(tex, texCoord)) / 255.0; + }`; + const readStencilProgram = wtu.setupProgram(gl, [wtu.simpleTextureVertexShaderESSL300, + readStencilShader]); + + for (const format of formats) { + debug(""); + debug(`Testing depth stencil texture modes with ${format.name}`); + const fbo = gl.createFramebuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); + + const rbo = gl.createRenderbuffer(); + gl.bindRenderbuffer(gl.RENDERBUFFER, rbo); + gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA8, 1, 1); + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rbo); + + const tex = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, tex); + gl.texImage2D(gl.TEXTURE_2D, 0, format.internalFormat, 1, 1, 0, format.format, format.type, null); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texture created"); + + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, tex, 0); + if (format.format == gl.DEPTH_STENCIL) { + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.TEXTURE_2D, tex, 0); + } + wtu.framebufferStatusShouldBe(gl, gl.FRAMEBUFFER, gl.FRAMEBUFFER_COMPLETE); + + gl.clear(gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT); + gl.useProgram(drawProgram); + wtu.drawUnitQuad(gl); + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no errors after drawing to the depth or depth stencil texture"); + + // Detach the depth or depth stencil texture to avoid feedback loop + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, null); + wtu.framebufferStatusShouldBe(gl, gl.FRAMEBUFFER, gl.FRAMEBUFFER_COMPLETE); + + const magFilters = ['NEAREST', 'LINEAR']; + + const minFilters = [ + 'NEAREST', + 'LINEAR', + 'NEAREST_MIPMAP_NEAREST', + 'LINEAR_MIPMAP_NEAREST', + 'NEAREST_MIPMAP_LINEAR', + 'LINEAR_MIPMAP_LINEAR' + ]; + + const modes = [ + [gl.DEPTH_COMPONENT, 'DEPTH_COMPONENT'], + [ext.STENCIL_INDEX_WEBGL, 'STENCIL_INDEX_WEBGL'] + ]; + + const programs = [ + [readDepthProgram, 'depth'], + [readStencilProgram, 'stencil'] + ]; + + function validFilters(magFilter, minFilter) { + return magFilter == gl.NEAREST && + (minFilter == gl.NEAREST || minFilter == gl.NEAREST_MIPMAP_NEAREST); + } + + for (const program of programs) { + gl.useProgram(program[0]); + for (const mode of modes) { + gl.texParameteri(gl.TEXTURE_2D, ext.DEPTH_STENCIL_TEXTURE_MODE_WEBGL, mode[0]); + for (const magFilter of magFilters) { + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl[magFilter]); + for (const minFilter of minFilters) { + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl[minFilter]); + debug(`Program: ${program[1]}, mode: ${mode[1]}, mag: ${magFilter}, min: ${minFilter}`); + + gl.clear(gl.COLOR_BUFFER_BIT); + wtu.drawUnitQuad(gl); + + if (format.format == gl.DEPTH_COMPONENT || mode[0] == gl.DEPTH_COMPONENT) { + if (program[1] == 'depth') { + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors"); + if (validFilters(gl[magFilter], gl[minFilter])) { + wtu.checkCanvasRect(gl, 0, 0, 1, 1, [128, 0, 0, 255], "sampling depth from complete texture", 1); + } else { + wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 0, 0, 255], "sampling depth from incomplete texture", 1); + } + } else { + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "sampling depth using incompatible program"); + } + } else { + if (program[1] == 'stencil') { + wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors"); + if (validFilters(gl[magFilter], gl[minFilter])) { + wtu.checkCanvasRect(gl, 0, 0, 1, 1, [170, 0, 0, 1], "sampling stencil from complete texture", 1); + } else { + // Incomplete textures may produce [0, 0, 0, 1] or [0, 0, 0, 255]. + const value = new Uint8Array(4); + gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, value); + wtu.glErrorShouldBe(gl, gl.NO_ERROR); + const msg = "sampling stencil from incomplete texture"; + if (value[0] == 0 && value[1] == 0 && value[2] == 0 && (value[3] == 1 || value[3] == 255)) { + testPassed(msg); + } else { + testFailed(`${msg}: ${value}`); + } + } + } else { + wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "sampling stencil using incompatible program"); + } + } + } + } + } + } + } +} + +function runTest() { + if (!gl) { + testFailed("context does not exist"); + return; + } + testPassed("context exists"); + + runTestNoExtension(); + + ext = gl.getExtension("WEBGL_stencil_texturing"); + wtu.runExtensionSupportedTest(gl, "WEBGL_stencil_texturing", ext !== null); + + if (ext !== null) { + checkEnums(); + checkQueries(); + checkSampling(); + } else { + testPassed("No WEBGL_stencil_texturing support -- this is legal"); + } +} + +runTest(); + +var successfullyParsed = true; +</script> +<script src="../../js/js-test-post.js"></script> +</body> +</html> |