read-draw-when-missing-image.html (13469B)
1 <!-- 2 Copyright (c) 2019 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 --> 6 7 <!DOCTYPE html> 8 <html> 9 <head> 10 <meta charset="utf-8"> 11 <title>Read or Draw when Attachment(s) Miss Image</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="example" width="8" height="8"></canvas> 18 <div id="description"></div> 19 <div id="console"></div> 20 21 <script> 22 "use strict"; 23 24 var wtu = WebGLTestUtils; 25 description("This test verifies the functionality of reading/drawing when color attachment(s) miss image."); 26 27 var gl = wtu.create3DContext("example", undefined, 2); 28 29 var tex_read = gl.createTexture(); 30 var tex_draw = gl.createTexture(); 31 var tex_depth = gl.createTexture(); 32 var tex_stencil = gl.createTexture(); 33 var fbo_read = gl.createFramebuffer(); 34 var fbo_draw = gl.createFramebuffer(); 35 var size = 8; 36 37 if (!gl) { 38 testFailed("WebGL context does not exist"); 39 } else { 40 testPassed("WebGL context exists"); 41 42 // READ_FRAMEBUFFER has image at COLOR_ATTACHMENT0. READ_FRAMEBUFFER is framebuffer complete. 43 // Read from COLOR_ATTACHMENT1, which has no image attached. 44 init_read_fbo(); 45 read(); 46 47 // DRAW_FRAMEBUFFER has image at COLOR_ATTACHMENT0. DRAW_FRAMEBUFFER is framebuffer complete. 48 // Clear and draw COLOR_ATTACHMENT1 or COLOR_ATTACHMENT0 + COLOR_ATTACHMENT1 attaching point(s). 49 init_draw_fbo(); 50 clear(); 51 draw(); 52 53 blit(); 54 } 55 56 function init_read_fbo() { 57 gl.bindTexture(gl.TEXTURE_2D, tex_read); 58 wtu.fillTexture(gl, tex_read, size, size, [0x0, 0xff, 0xff, 0xff], 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.RGBA8); 59 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_read); 60 gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex_read, 0); 61 if (gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) { 62 testFailed("Framebuffer incomplete."); 63 return; 64 } else { 65 testPassed("framebuffer complete!"); 66 } 67 } 68 69 function init_draw_fbo() { 70 gl.bindTexture(gl.TEXTURE_2D, tex_draw); 71 wtu.fillTexture(gl, tex_draw, size, size, [0x0, 0xff, 0xff, 0xff], 0, gl.RGBA, gl.UNSIGNED_BYTE, gl.RGBA8); 72 wtu.fillTexture(gl, tex_depth, size, size, [0x80], 0, gl.DEPTH_COMPONENT, gl.UNSIGNED_INT, gl.DEPTH_COMPONENT16); 73 wtu.fillTexture(gl, tex_stencil, size, size, [0x40], 0, gl.DEPTH_STENCIL, gl.UNSIGNED_INT_24_8, gl.DEPTH24_STENCIL8); 74 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw); 75 gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex_draw, 0); 76 if (gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) { 77 testFailed("Framebuffer incomplete."); 78 return; 79 } else { 80 testPassed("framebuffer complete!"); 81 } 82 } 83 84 function read() { 85 debug(""); 86 debug("read from a color buffer which has no image attached"); 87 88 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo_read); 89 gl.readBuffer(gl.COLOR_ATTACHMENT1); 90 91 var data = new Uint8Array(size * size * 4); 92 gl.readPixels(0, 0, size, size, gl.RGBA, gl.UNSIGNED_BYTE, data); 93 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Should generate INVALID_OPERATION when reading from a color buffer without image."); 94 95 var copy_2d = gl.createTexture(); 96 gl.bindTexture(gl.TEXTURE_2D, copy_2d); 97 gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, 0, 0, size, size, 0); 98 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Should generate INVALID_OPERATION when reading from a color buffer without image."); 99 100 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, size, size, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 101 gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, size / 2, size / 2, 0, 0, size / 2, size / 2); 102 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Should generate INVALID_OPERATION when reading from a color buffer without image."); 103 104 var copy_3d = gl.createTexture(); 105 gl.bindTexture(gl.TEXTURE_3D, copy_3d); 106 gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGBA8, size, size, 2, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 107 gl.copyTexSubImage3D(gl.TEXTURE_3D, 0, size / 2, size / 2, 0, 0, 0, size / 2, size / 2); 108 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Should generate INVALID_OPERATION when reading from a color buffer without image."); 109 110 gl.bindTexture(gl.TEXTURE_2D, null); 111 gl.deleteTexture(copy_2d); 112 gl.bindTexture(gl.TEXTURE_3D, null); 113 gl.deleteTexture(copy_3d); 114 } 115 116 function checkTextureValue(fbo, buffer, value) { 117 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo); 118 gl.readBuffer(buffer); 119 wtu.checkCanvas(gl, value); 120 gl.readBuffer(gl.COLOR_ATTACHMENT0); 121 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null); 122 } 123 124 function clear() { 125 debug(""); 126 debug("clear a color buffer which has no image attached"); 127 128 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw); 129 var color = [0.0, 1.0, 0.0, 1.0]; 130 gl.clearColor(color[0], color[1], color[2], color[3]); 131 gl.drawBuffers([gl.NONE, gl.COLOR_ATTACHMENT1]); 132 gl.clear(gl.COLOR_BUFFER_BIT); 133 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no error."); 134 // The image color at COLOR_ATTACHMENT0 should not be changed. 135 checkTextureValue(fbo_draw, gl.COLOR_ATTACHMENT0, [0, 255, 255, 255]); 136 137 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw); 138 gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1]); 139 gl.clear(gl.COLOR_BUFFER_BIT); 140 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no error."); 141 // The image color at COLOR_ATTACHMENT0 should be changed. 142 checkTextureValue(fbo_draw, gl.COLOR_ATTACHMENT0, [0, 255, 0, 255]); 143 144 var data = new Float32Array(color); 145 gl.clearBufferfv(gl.COLOR, 1, data); 146 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no error."); 147 } 148 149 function draw() { 150 debug(""); 151 debug("draw to a color buffer which has no image attached"); 152 153 var program = wtu.setupSimpleColorProgram(gl, 0); 154 gl.uniform4f(gl.getUniformLocation(program, "u_color"), 1, 0, 0, 1); 155 wtu.setupUnitQuad(gl, 0); 156 157 // Call to drawArrays 158 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw); 159 gl.drawBuffers([gl.NONE, gl.COLOR_ATTACHMENT1]); 160 wtu.drawUnitQuad(gl); 161 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no error."); 162 // The image color at COLOR_ATTACHMENT0 should not be changed. 163 checkTextureValue(fbo_draw, gl.COLOR_ATTACHMENT0, [0, 255, 0, 255]); 164 165 gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1]); 166 wtu.drawUnitQuad(gl); 167 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no error."); 168 // The image color at COLOR_ATTACHMENT0 should be changed. 169 checkTextureValue(fbo_draw, gl.COLOR_ATTACHMENT0, [255, 0, 0, 255]); 170 171 // Call to drawElements 172 gl.uniform4f(gl.getUniformLocation(program, "u_color"), 1, 1, 0, 1); 173 wtu.setupIndexedQuad(gl, 1); 174 gl.drawBuffers([gl.NONE, gl.COLOR_ATTACHMENT1]); 175 wtu.drawIndexedQuad(gl, 1); 176 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no error."); 177 // The image color at COLOR_ATTACHMENT0 should not be changed. 178 checkTextureValue(fbo_draw, gl.COLOR_ATTACHMENT0, [255, 0, 0, 255]); 179 180 gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1]); 181 wtu.drawIndexedQuad(gl, 1); 182 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no error."); 183 // The image color at COLOR_ATTACHMENT0 should be changed. 184 checkTextureValue(fbo_draw, gl.COLOR_ATTACHMENT0, [255, 255, 0, 255]); 185 } 186 187 function blit() { 188 debug(""); 189 debug("blit color buffer(s) which have no image attached"); 190 // Some or all draw buffers have no image. Read buffer have image. It should be OK. 191 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw); 192 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_read); 193 gl.readBuffer(gl.COLOR_ATTACHMENT0); 194 gl.drawBuffers([gl.NONE, gl.COLOR_ATTACHMENT1]); 195 gl.blitFramebuffer(0, 0, size, size, 0, 0, size, size, gl.COLOR_BUFFER_BIT, gl.NEAREST); 196 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no error."); 197 // The image color at COLOR_ATTACHMENT0 in draw fbo should not be changed. 198 checkTextureValue(fbo_draw, gl.COLOR_ATTACHMENT0, [255, 255, 0, 255]); 199 200 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw); 201 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_read); 202 gl.readBuffer(gl.COLOR_ATTACHMENT0); 203 gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1]); 204 gl.blitFramebuffer(0, 0, size, size, 0, 0, size, size, gl.COLOR_BUFFER_BIT, gl.NEAREST); 205 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no error."); 206 // The image color at COLOR_ATTACHMENT0 in draw fbo should be changed. 207 checkTextureValue(fbo_draw, gl.COLOR_ATTACHMENT0, [0, 255, 255, 255]); 208 209 // Draw buffer(s) have no image. Read buffer have no image. It should be OK. 210 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw); 211 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_read); 212 gl.readBuffer(gl.COLOR_ATTACHMENT1); 213 gl.drawBuffers([gl.NONE, gl.COLOR_ATTACHMENT1]); 214 gl.blitFramebuffer(0, 0, size, size, 0, 0, size, size, gl.COLOR_BUFFER_BIT, gl.NEAREST); 215 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no error."); 216 // The image color at COLOR_ATTACHMENT0 in draw fbo should not be changed. 217 checkTextureValue(fbo_draw, gl.COLOR_ATTACHMENT0, [0, 255, 255, 255]); 218 219 // Read buffer have no image. Some or all draw buffers have image. It should generate INVALID_OPERATION. 220 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw); 221 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_read); 222 gl.readBuffer(gl.COLOR_ATTACHMENT1); 223 gl.drawBuffers([gl.COLOR_ATTACHMENT0]); 224 gl.blitFramebuffer(0, 0, size, size, 0, 0, size, size, gl.COLOR_BUFFER_BIT, gl.NEAREST); 225 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Should generate INVALID_OPERATION when read buffer misses image."); 226 // The image color at COLOR_ATTACHMENT0 in draw fbo should not be changed. 227 checkTextureValue(fbo_draw, gl.COLOR_ATTACHMENT0, [0, 255, 255, 255]); 228 229 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw); 230 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_read); 231 gl.readBuffer(gl.COLOR_ATTACHMENT1); 232 gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1]); 233 gl.blitFramebuffer(0, 0, size, size, 0, 0, size, size, gl.COLOR_BUFFER_BIT, gl.NEAREST); 234 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Should generate INVALID_OPERATION when read buffer misses image."); 235 // The image color at COLOR_ATTACHMENT0 in draw fbo should not be changed. 236 checkTextureValue(fbo_draw, gl.COLOR_ATTACHMENT0, [0, 255, 255, 255]); 237 238 // Depth buffer in read fbo has no image. It should generate INVALID_OPERATION if depth buffer in draw fbo has image. 239 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw); 240 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_read); 241 gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, tex_depth, 0); 242 gl.blitFramebuffer(0, 0, size, size, 0, 0, size, size, gl.DEPTH_BUFFER_BIT, gl.NEAREST); 243 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Should generate INVALID_OPERATION when depth buffer misses image."); 244 245 // Depth buffer in read fbo has no image. It should be OK if depth buffer in draw fbo has no image too. 246 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw); 247 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_read); 248 gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.TEXTURE_2D, null, 0); 249 gl.blitFramebuffer(0, 0, size, size, 0, 0, size, size, gl.DEPTH_BUFFER_BIT, gl.NEAREST); 250 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no error."); 251 // Validate some other parameters as usual 252 gl.blitFramebuffer(0, 0, size, size, 0, 0, size, size, gl.DEPTH_BUFFER_BIT, gl.LINEAR); 253 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid filter"); 254 255 // Stencil buffer in read fbo has no image. It should generate INVALID_OPERATION if stencil buffer in draw fbo has image. 256 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw); 257 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_read); 258 gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.TEXTURE_2D, tex_stencil, 0); 259 gl.blitFramebuffer(0, 0, size, size, 0, 0, size, size, gl.STENCIL_BUFFER_BIT, gl.NEAREST); 260 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "Should generate INVALID_OPERATION when stencil buffer misses image."); 261 262 // Stencil buffer in read fbo has no image. It should be OK if stencil buffer in draw fbo has no image too. 263 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo_draw); 264 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo_read); 265 gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.TEXTURE_2D, null, 0); 266 gl.blitFramebuffer(0, 0, size, size, 0, 0, size, size, gl.STENCIL_BUFFER_BIT, gl.NEAREST); 267 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Should be no error."); 268 // Validate some other parameters as usual 269 gl.blitFramebuffer(0, 0, size, size, 0, 0, size, size, gl.STENCIL_BUFFER_BIT, gl.LINEAR); 270 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid filter"); 271 } 272 273 gl.bindTexture(gl.TEXTURE_2D, null); 274 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null); 275 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null); 276 gl.deleteTexture(tex_read); 277 gl.deleteTexture(tex_draw); 278 gl.deleteTexture(tex_depth); 279 gl.deleteTexture(tex_stencil); 280 gl.deleteFramebuffer(fbo_read); 281 gl.deleteFramebuffer(fbo_draw); 282 283 var successfullyParsed = true; 284 </script> 285 <script src="../../js/js-test-post.js"></script> 286 287 </body> 288 </html>