blob: da68b36c246ffe8674da6c2f6fc0226d34d9cf83 [file] [edit]
<!doctype html>
<meta charset="utf-8">
<title>WebGL state reaches a framebuffer created by the page</title>
<link rel="author" title="mxmgorin" href="mailto:102797145+mxmgorin@users.noreply.github.com">
<link rel="help" href="https://registry.khronos.org/webgl/specs/latest/1.0/#5.14.3">
<link rel="help" href="https://registry.khronos.org/OpenGL-Refpages/es2.0/xhtml/glStencilMask.xml">
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script>
function createContext() {
// No stencil on the default framebuffer, so the only stencil is the FBO's.
var gl = document.createElement("canvas").getContext("webgl", { stencil: false });
var framebuffer = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
var texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 4, 4, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
var renderbuffer = gl.createRenderbuffer();
gl.bindRenderbuffer(gl.RENDERBUFFER, renderbuffer);
gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, 4, 4);
gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT,
gl.RENDERBUFFER, renderbuffer);
assert_equals(gl.checkFramebufferStatus(gl.FRAMEBUFFER), gl.FRAMEBUFFER_COMPLETE);
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, "attribute vec2 p; void main() { gl_Position = vec4(p, 0, 1); }");
gl.compileShader(vertexShader);
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, "void main() { gl_FragColor = vec4(1, 0, 0, 1); }");
gl.compileShader(fragmentShader);
var program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
// One triangle covering the whole viewport.
var buffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 3, -1, -1, 3]), gl.STATIC_DRAW);
gl.enableVertexAttribArray(0);
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);
return gl;
}
function readPixel(gl) {
var pixel = new Uint8Array(4);
gl.readPixels(1, 1, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixel);
return Array.from(pixel);
}
test(function() {
var gl = document.createElement("canvas").getContext("webgl");
// Masked to the low byte: the stencil buffers WebGL gets are 8 bits deep.
assert_equals(gl.getParameter(gl.STENCIL_WRITEMASK) & 0xff, 0xff);
assert_equals(gl.getParameter(gl.STENCIL_BACK_WRITEMASK) & 0xff, 0xff);
}, "the initial stencil writemask is all ones");
test(function() {
var gl = createContext();
gl.enable(gl.STENCIL_TEST);
// Write 5 into the stencil buffer without ever calling stencilMask.
gl.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);
gl.stencilFunc(gl.ALWAYS, 5, 0xff);
gl.drawArrays(gl.TRIANGLES, 0, 3);
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
gl.stencilFunc(gl.EQUAL, 5, 0xff);
gl.drawArrays(gl.TRIANGLES, 0, 3);
assert_array_equals(readPixel(gl), [255, 0, 0, 255]);
assert_equals(gl.getError(), gl.NO_ERROR);
}, "stencil writes reach a framebuffer's stencil attachment by default");
test(function() {
var gl = createContext();
// Set before the framebuffer's first clear, which lazily initializes it.
gl.clearStencil(1);
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
gl.enable(gl.STENCIL_TEST);
gl.stencilFunc(gl.EQUAL, 1, 0xff);
gl.drawArrays(gl.TRIANGLES, 0, 3);
assert_array_equals(readPixel(gl), [255, 0, 0, 255]);
assert_equals(gl.getError(), gl.NO_ERROR);
}, "the stencil clear value survives a framebuffer's first clear");
test(function() {
var gl = createContext();
gl.clearDepth(0);
gl.clearColor(0, 0, 0, 1);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
// The triangle sits at depth 0.5: GREATER passes against 0, not against 1.
gl.enable(gl.DEPTH_TEST);
gl.depthFunc(gl.GREATER);
gl.drawArrays(gl.TRIANGLES, 0, 3);
assert_array_equals(readPixel(gl), [255, 0, 0, 255]);
assert_equals(gl.getError(), gl.NO_ERROR);
}, "the depth clear value survives a framebuffer's first clear");
</script>