diff options
Diffstat (limited to '')
-rw-r--r-- | dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-to-texture.html | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-to-texture.html b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-to-texture.html new file mode 100644 index 0000000000..926e14beab --- /dev/null +++ b/dom/canvas/test/webgl-conf/checkout/conformance2/rendering/framebuffer-to-texture.html @@ -0,0 +1,201 @@ +<!-- +Copyright (c) 2022 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 framebuffer to texture conformance test.</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> +<canvas id="canvas"></canvas> +<div id="description"></div> +<div id="console"></div> +<script> +"use strict"; +description("Test resolving and copying the framebuffer to a texture, and drawing the result."); +debug('Reduced test case for <a href="http://anglebug.com/6972">http://anglebug.com/6972</a>'); + +// Reproduces two behaviors: +// +// 1) The initial draw disappearing entirely from the default back +// buffer. The current test case does not show this behavior +// independently from the other, but a previous iteration, with the +// textured quad scaled to half size and translated (-0.5, -0.5), did. +// +// 2) With Metal debug layers and load/store validation turned on on +// Intel Macs, the transparent area of the texture prior to the bug +// fix was magenta = undefined. Similar behavior would presumably +// reproduce on M1 hardware without debug layers or validation. + +const size = 64; +const halfSize = size / 2; +const green = [ 0, 255, 0, 255 ]; +const transparent = [ 0, 0, 0, 0 ]; + +let wtu = WebGLTestUtils; +let canvas = document.getElementById("canvas"); +canvas.width = size; +canvas.height = size; + +let gl = wtu.create3DContext("canvas", { + // Antialiasing is crucial for reproducing the bug. + antialias: true, + // Depth testing is not. + depth: false, +}, 2); + +function allocateTexture(sz) { + let texture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, sz, sz); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); + gl.bindTexture(gl.TEXTURE_2D, null); + return texture; +} + +// Allocate destination texture +let destTexture = allocateTexture(halfSize); + +// Set up half-size solid color quad in center +let colorQuadVAO = gl.createVertexArray(); +gl.bindVertexArray(colorQuadVAO); +let colorQuadProgram = wtu.setupColorQuad(gl, 0, { scale: 0.5 }); + +// Setup textured quad covering the entire renderable area +let quadVAO = gl.createVertexArray(); +gl.bindVertexArray(quadVAO); +let quadProgram = wtu.setupTexturedQuad(gl, 0, 1); +gl.useProgram(quadProgram); +let quadTexLoc = gl.getUniformLocation(quadProgram, "tex"); +gl.uniform1i(quadTexLoc, 0); + +gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); +gl.activeTexture(gl.TEXTURE0); // To match quadTexLoc=0 + +function runTest() { + gl.clearColor(0, 0, 0, 0); + gl.clear(gl.COLOR_BUFFER_BIT); + gl.disable(gl.BLEND); + gl.bindVertexArray(colorQuadVAO); + gl.useProgram(colorQuadProgram); + wtu.drawUByteColorQuad(gl, [ 0, 255, 0, 255 ]); + + gl.bindTexture(gl.TEXTURE_2D, destTexture); + // Copy the upper right corner of the framebuffer to the texture. + gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, halfSize, halfSize, halfSize, halfSize); + gl.bindTexture(gl.TEXTURE_2D, null); + gl.useProgram(quadProgram); + gl.enable(gl.BLEND); + gl.bindVertexArray(quadVAO); + gl.bindTexture(gl.TEXTURE_2D, destTexture); + // Magnify and blend this texture over the current framebuffer. + wtu.drawUnitQuad(gl); +} + +function runUserDefinedFBOTest() { + let fbo1 = gl.createFramebuffer(); + let fbo2 = gl.createFramebuffer(); + let rb = gl.createRenderbuffer(); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo1); + gl.bindRenderbuffer(gl.RENDERBUFFER, rb); + gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 4, gl.RGBA8, size, size); + gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb); + wtu.framebufferStatusShouldBe(gl, gl.FRAMEBUFFER, [ gl.FRAMEBUFFER_COMPLETE ]); + + let tex = allocateTexture(size, size); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2); + gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0); + wtu.framebufferStatusShouldBe(gl, gl.FRAMEBUFFER, [ gl.FRAMEBUFFER_COMPLETE ]); + + // Same rendering steps as in the default-framebuffer test, with appropriate framebuffer blits interspersed. + gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo1); + gl.clearColor(0, 0, 0, 0); + gl.clear(gl.COLOR_BUFFER_BIT); + gl.disable(gl.BLEND); + gl.bindVertexArray(colorQuadVAO); + gl.useProgram(colorQuadProgram); + wtu.drawUByteColorQuad(gl, [ 0, 255, 0, 255 ]); + + gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo1); + gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo2); + gl.blitFramebuffer(0, 0, size, size, 0, 0, size, size, gl.COLOR_BUFFER_BIT, gl.NEAREST); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2); + + gl.bindTexture(gl.TEXTURE_2D, destTexture); + // Copy the upper right corner of the framebuffer to the texture. + gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, halfSize, halfSize, halfSize, halfSize); + gl.bindTexture(gl.TEXTURE_2D, null); + + gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo1); + + gl.useProgram(quadProgram); + gl.enable(gl.BLEND); + gl.bindVertexArray(quadVAO); + gl.bindTexture(gl.TEXTURE_2D, destTexture); + // Magnify and blend this texture over the current framebuffer. + wtu.drawUnitQuad(gl); + + gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo1); + gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo2); + gl.blitFramebuffer(0, 0, size, size, 0, 0, size, size, gl.COLOR_BUFFER_BIT, gl.NEAREST); + gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2); + + // No longer easy to put these results on the canvas, because it's + // antialiased and we can't blitFramebuffer to it. Let's assume + // that if failures occur, they'll be straightforward to debug. +} + +function checkRenderingResults(prefix) { + // Center quad should be rendered correctly. + wtu.checkCanvasRect(gl, + halfSize / 2 + 1, halfSize / 2 + 1, + halfSize - 2, halfSize - 2, + green, + prefix + ": center quad should be green"); + + // Overlapping lower-left quad should be green as well. + wtu.checkCanvasRect(gl, + 1, 1, + halfSize - 2, halfSize - 2, + green, + prefix + ": lower left quad should be green"); + + // Leftmost area above the lower-left quad should be transparent. + wtu.checkCanvasRect(gl, + 1, halfSize + 1, + halfSize / 2 - 2, halfSize / 2 - 2, + transparent, + prefix + ": leftmost area above lower left quad should be transparent"); + + // Bottommost area to the right of the lower-left quad should be transparent. + wtu.checkCanvasRect(gl, + halfSize + 1, 1, + halfSize / 2 - 2, halfSize / 2 - 2, + transparent, + prefix + ": bottommost area to the right of lower left quad should be transparent"); +} + +runTest(); +checkRenderingResults("default back buffer"); + +runUserDefinedFBOTest(); +checkRenderingResults("user-defined framebuffer"); + +wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors at the end of the test."); + +finishTest(); + +var successfullyParsed = true; +</script> +</body> +</html> |