Backed out changeset 7272b7396c78 (bug 1932758) for causing fenix debug failures...
[gecko.git] / dom / canvas / test / webgl-conf / checkout / conformance2 / rendering / framebuffer-to-texture.html
blob926e14beab7727567f42a01eb6a7966aa69c85a8
1 <!--
2 Copyright (c) 2022 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 framebuffer to texture conformance test.</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 <canvas id="canvas"></canvas>
18 <div id="description"></div>
19 <div id="console"></div>
20 <script>
21 "use strict";
22 description("Test resolving and copying the framebuffer to a texture, and drawing the result.");
23 debug('Reduced test case for <a href="http://anglebug.com/6972">http://anglebug.com/6972</a>');
25 // Reproduces two behaviors:
27 // 1) The initial draw disappearing entirely from the default back
28 // buffer. The current test case does not show this behavior
29 // independently from the other, but a previous iteration, with the
30 // textured quad scaled to half size and translated (-0.5, -0.5), did.
32 // 2) With Metal debug layers and load/store validation turned on on
33 // Intel Macs, the transparent area of the texture prior to the bug
34 // fix was magenta = undefined. Similar behavior would presumably
35 // reproduce on M1 hardware without debug layers or validation.
37 const size = 64;
38 const halfSize = size / 2;
39 const green = [ 0, 255, 0, 255 ];
40 const transparent = [ 0, 0, 0, 0 ];
42 let wtu = WebGLTestUtils;
43 let canvas = document.getElementById("canvas");
44 canvas.width = size;
45 canvas.height = size;
47 let gl = wtu.create3DContext("canvas", {
48 // Antialiasing is crucial for reproducing the bug.
49 antialias: true,
50 // Depth testing is not.
51 depth: false,
52 }, 2);
54 function allocateTexture(sz) {
55 let texture = gl.createTexture();
56 gl.bindTexture(gl.TEXTURE_2D, texture);
57 gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, sz, sz);
58 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
59 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
60 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
61 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
62 gl.bindTexture(gl.TEXTURE_2D, null);
63 return texture;
66 // Allocate destination texture
67 let destTexture = allocateTexture(halfSize);
69 // Set up half-size solid color quad in center
70 let colorQuadVAO = gl.createVertexArray();
71 gl.bindVertexArray(colorQuadVAO);
72 let colorQuadProgram = wtu.setupColorQuad(gl, 0, { scale: 0.5 });
74 // Setup textured quad covering the entire renderable area
75 let quadVAO = gl.createVertexArray();
76 gl.bindVertexArray(quadVAO);
77 let quadProgram = wtu.setupTexturedQuad(gl, 0, 1);
78 gl.useProgram(quadProgram);
79 let quadTexLoc = gl.getUniformLocation(quadProgram, "tex");
80 gl.uniform1i(quadTexLoc, 0);
82 gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
83 gl.activeTexture(gl.TEXTURE0); // To match quadTexLoc=0
85 function runTest() {
86 gl.clearColor(0, 0, 0, 0);
87 gl.clear(gl.COLOR_BUFFER_BIT);
88 gl.disable(gl.BLEND);
89 gl.bindVertexArray(colorQuadVAO);
90 gl.useProgram(colorQuadProgram);
91 wtu.drawUByteColorQuad(gl, [ 0, 255, 0, 255 ]);
93 gl.bindTexture(gl.TEXTURE_2D, destTexture);
94 // Copy the upper right corner of the framebuffer to the texture.
95 gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, halfSize, halfSize, halfSize, halfSize);
96 gl.bindTexture(gl.TEXTURE_2D, null);
97 gl.useProgram(quadProgram);
98 gl.enable(gl.BLEND);
99 gl.bindVertexArray(quadVAO);
100 gl.bindTexture(gl.TEXTURE_2D, destTexture);
101 // Magnify and blend this texture over the current framebuffer.
102 wtu.drawUnitQuad(gl);
105 function runUserDefinedFBOTest() {
106 let fbo1 = gl.createFramebuffer();
107 let fbo2 = gl.createFramebuffer();
108 let rb = gl.createRenderbuffer();
109 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo1);
110 gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
111 gl.renderbufferStorageMultisample(gl.RENDERBUFFER, 4, gl.RGBA8, size, size);
112 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb);
113 wtu.framebufferStatusShouldBe(gl, gl.FRAMEBUFFER, [ gl.FRAMEBUFFER_COMPLETE ]);
115 let tex = allocateTexture(size, size);
116 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2);
117 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
118 wtu.framebufferStatusShouldBe(gl, gl.FRAMEBUFFER, [ gl.FRAMEBUFFER_COMPLETE ]);
120 // Same rendering steps as in the default-framebuffer test, with appropriate framebuffer blits interspersed.
121 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo1);
122 gl.clearColor(0, 0, 0, 0);
123 gl.clear(gl.COLOR_BUFFER_BIT);
124 gl.disable(gl.BLEND);
125 gl.bindVertexArray(colorQuadVAO);
126 gl.useProgram(colorQuadProgram);
127 wtu.drawUByteColorQuad(gl, [ 0, 255, 0, 255 ]);
129 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo1);
130 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo2);
131 gl.blitFramebuffer(0, 0, size, size, 0, 0, size, size, gl.COLOR_BUFFER_BIT, gl.NEAREST);
132 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2);
134 gl.bindTexture(gl.TEXTURE_2D, destTexture);
135 // Copy the upper right corner of the framebuffer to the texture.
136 gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, halfSize, halfSize, halfSize, halfSize);
137 gl.bindTexture(gl.TEXTURE_2D, null);
139 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo1);
141 gl.useProgram(quadProgram);
142 gl.enable(gl.BLEND);
143 gl.bindVertexArray(quadVAO);
144 gl.bindTexture(gl.TEXTURE_2D, destTexture);
145 // Magnify and blend this texture over the current framebuffer.
146 wtu.drawUnitQuad(gl);
148 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo1);
149 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo2);
150 gl.blitFramebuffer(0, 0, size, size, 0, 0, size, size, gl.COLOR_BUFFER_BIT, gl.NEAREST);
151 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2);
153 // No longer easy to put these results on the canvas, because it's
154 // antialiased and we can't blitFramebuffer to it. Let's assume
155 // that if failures occur, they'll be straightforward to debug.
158 function checkRenderingResults(prefix) {
159 // Center quad should be rendered correctly.
160 wtu.checkCanvasRect(gl,
161 halfSize / 2 + 1, halfSize / 2 + 1,
162 halfSize - 2, halfSize - 2,
163 green,
164 prefix + ": center quad should be green");
166 // Overlapping lower-left quad should be green as well.
167 wtu.checkCanvasRect(gl,
168 1, 1,
169 halfSize - 2, halfSize - 2,
170 green,
171 prefix + ": lower left quad should be green");
173 // Leftmost area above the lower-left quad should be transparent.
174 wtu.checkCanvasRect(gl,
175 1, halfSize + 1,
176 halfSize / 2 - 2, halfSize / 2 - 2,
177 transparent,
178 prefix + ": leftmost area above lower left quad should be transparent");
180 // Bottommost area to the right of the lower-left quad should be transparent.
181 wtu.checkCanvasRect(gl,
182 halfSize + 1, 1,
183 halfSize / 2 - 2, halfSize / 2 - 2,
184 transparent,
185 prefix + ": bottommost area to the right of lower left quad should be transparent");
188 runTest();
189 checkRenderingResults("default back buffer");
191 runUserDefinedFBOTest();
192 checkRenderingResults("user-defined framebuffer");
194 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no errors at the end of the test.");
196 finishTest();
198 var successfullyParsed = true;
199 </script>
200 </body>
201 </html>