blitframebuffer-test.html (19542B)
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>WebGL BlitFramebuffer Tests</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 <script> 21 "use strict"; 22 23 var wtu = WebGLTestUtils; 24 description("This test verifies the functionality of blitFramebuffer for some corner cases."); 25 26 var width = 8; 27 var height = 8; 28 29 var gl = wtu.create3DContext("example", undefined, 2); 30 if (!gl) { 31 testFailed("WebGL context does not exist"); 32 } else { 33 testPassed("WebGL context exists"); 34 blit_framebuffer_repeated(); 35 blit_framebuffer_feedback_loop(); 36 blit_framebuffer_multisampling_srgb(); 37 } 38 39 function blit_framebuffer_repeated() { 40 debug(""); 41 debug("This test verifies repeated calls to blitFramebuffer."); 42 43 // Create offscreen fbo and its color attachment. 44 var tex_2d = gl.createTexture(); 45 gl.bindTexture(gl.TEXTURE_2D, tex_2d); 46 gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, width, height); 47 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 48 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 49 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); 50 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); 51 52 var fb = gl.createFramebuffer(); 53 gl.bindFramebuffer(gl.FRAMEBUFFER, fb); 54 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex_2d, 0); 55 if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) { 56 testFailed("Framebuffer incomplete."); 57 return; 58 } 59 60 var prog = wtu.setupColorQuad(gl, 0); 61 wtu.setFloatDrawColor(gl, [ 1.0, 0.0, 0.0, 1.0 ]); 62 wtu.drawUnitQuad(gl); 63 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fb); 64 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null); 65 gl.blitFramebuffer(0, 0, width, height, 0, 0, width, height, gl.COLOR_BUFFER_BIT, gl.NEAREST); 66 gl.bindFramebuffer(gl.FRAMEBUFFER, null); 67 wtu.checkCanvas(gl, [ 255, 0, 0, 255 ], "should be red at first"); 68 69 gl.bindFramebuffer(gl.FRAMEBUFFER, fb); 70 wtu.setFloatDrawColor(gl, [ 0.0, 1.0, 0.0, 1.0 ]); 71 wtu.drawUnitQuad(gl); 72 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fb); 73 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null); 74 gl.blitFramebuffer(0, 0, width, height, 0, 0, width, height, gl.COLOR_BUFFER_BIT, gl.NEAREST); 75 gl.bindFramebuffer(gl.FRAMEBUFFER, null); 76 wtu.checkCanvas(gl, [ 0, 255, 0, 255 ], "should be green"); 77 } 78 79 function blit_framebuffer_feedback_loop() { 80 81 debug(""); 82 debug("This test checks whether the src resource and dst resource have identical images."); 83 // Create read fbo and its color attachment. 84 var tex_2d = gl.createTexture(); 85 gl.bindTexture(gl.TEXTURE_2D, tex_2d); 86 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 87 gl.generateMipmap(gl.TEXTURE_2D); 88 89 var fb0 = gl.createFramebuffer(); 90 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fb0); 91 gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex_2d, 0); 92 if (gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) { 93 testFailed("Framebuffer incomplete."); 94 return; 95 } 96 97 // Create draw fbo and its color attachment. 98 var rb0 = gl.createRenderbuffer(); 99 gl.bindRenderbuffer(gl.RENDERBUFFER, rb0); 100 gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA8, width, height); 101 102 var fb1 = gl.createFramebuffer(); 103 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb1); 104 gl.framebufferRenderbuffer(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb0); 105 if (gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) { 106 testFailed("Framebuffer incomplete."); 107 return; 108 } 109 110 // Blit framebuffer, all conditions are OK. 111 gl.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl.COLOR_BUFFER_BIT, gl.NEAREST); 112 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "blitFramebuffer should succeed."); 113 114 // Blit framebuffer, the src buffer and the dst buffer should not be identical. 115 // Exactly the same read/draw fbo 116 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fb0); 117 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb0); 118 gl.blitFramebuffer(0, 0, 2, 2, 4, 4, 6, 6, gl.COLOR_BUFFER_BIT, gl.NEAREST); 119 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "blitFramebuffer should generate INVALID_OPERATION if read/draw buffer are identical."); 120 121 // Exactly the same read/draw framebuffer: default framebuffer 122 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null); 123 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null); 124 gl.blitFramebuffer(0, 0, 2, 2, 4, 4, 6, 6, gl.COLOR_BUFFER_BIT, gl.NEAREST); 125 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "blitFramebuffer should generate INVALID_OPERATION if read/draw buffer are identical."); 126 127 // The same image with the same level bound to read/draw buffer. 128 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fb0); 129 gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex_2d, 0); 130 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb1); 131 gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex_2d, 0); 132 if (gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE || 133 gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) { 134 testFailed("Framebuffer incomplete."); 135 return; 136 } 137 gl.blitFramebuffer(0, 0, 2, 2, 4, 4, 6, 6, gl.COLOR_BUFFER_BIT, gl.NEAREST); 138 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "blitFramebuffer should generate INVALID_OPERATION if read/draw color buffer are identical."); 139 140 // The same image in read/draw buffer, but different levels are bound to read/draw buffer respectively. 141 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb1); 142 gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex_2d, 1); 143 if (gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) { 144 testFailed("Framebuffer incomplete."); 145 return; 146 } 147 gl.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl.COLOR_BUFFER_BIT, gl.NEAREST); 148 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "blitFramebuffer should succeed if read/draw buffer has the same image with different levels."); 149 150 // The same cube_map image in read/draw buffer, but different faces are bound to read/draw buffer respectively. 151 var tex_cube_map = gl.createTexture(); 152 gl.bindTexture(gl.TEXTURE_CUBE_MAP, tex_cube_map); 153 gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_X, 0, gl.RGBA8, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 154 gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_X, 0, gl.RGBA8, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 155 gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Y, 0, gl.RGBA8, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 156 gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, gl.RGBA8, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 157 gl.texImage2D(gl.TEXTURE_CUBE_MAP_POSITIVE_Z, 0, gl.RGBA8, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 158 gl.texImage2D(gl.TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, gl.RGBA8, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 159 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fb0); 160 gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X, tex_cube_map, 0); 161 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb1); 162 gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_NEGATIVE_X, tex_cube_map, 0); 163 if ((gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) || 164 (gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE)) { 165 testFailed("Framebuffer incomplete."); 166 return; 167 } 168 gl.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl.COLOR_BUFFER_BIT, gl.NEAREST); 169 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "blitFramebuffer should succeed if read/draw buffer has the same CUBE_MAP image with different faces."); 170 171 // The same 3D/2D_ARRAY image in read/draw buffer, but different layers are bound to read/draw buffer respectively. 172 var tex_2d_array = gl.createTexture(); 173 gl.bindTexture(gl.TEXTURE_2D_ARRAY, tex_2d_array); 174 var depth = 2; 175 gl.texImage3D(gl.TEXTURE_2D_ARRAY, 0, gl.RGBA8, width, height, depth, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 176 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fb0); 177 var level = 0, layer = 0; 178 gl.framebufferTextureLayer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex_2d_array, level, layer); 179 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb1); 180 layer = 1; 181 gl.framebufferTextureLayer(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex_2d_array, level, layer); 182 if ((gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) || 183 (gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE)) { 184 testFailed("Framebuffer incomplete."); 185 return; 186 } 187 gl.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl.COLOR_BUFFER_BIT, gl.NEAREST); 188 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "blitFramebuffer should succeed if read/draw buffer has the same 3D/2D_ARRAY image with different layers."); 189 190 // The same image are bound as depth buffer in both read framebuffer and draw framebuffer 191 var rb1 = gl.createRenderbuffer(); 192 gl.bindRenderbuffer(gl.RENDERBUFFER, rb1); 193 gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH24_STENCIL8, width, height); 194 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fb0); 195 gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X, tex_cube_map, 0); 196 gl.framebufferRenderbuffer(gl.READ_FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, rb1); 197 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb1); 198 gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_NEGATIVE_X, tex_cube_map, 0); 199 gl.framebufferRenderbuffer(gl.DRAW_FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, rb1); 200 if (gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE || 201 gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) { 202 testFailed("Framebuffer incomplete."); 203 return; 204 } 205 // But the mask doesn't have depth buffer bit. 206 gl.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl.COLOR_BUFFER_BIT, gl.NEAREST); 207 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "blitFramebuffer should succeed."); 208 209 // The mask has depth buffer bit. 210 gl.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT, gl.NEAREST); 211 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "blitFramebuffer should generate INVALID_OPERATION if read/draw framebuffer have identical depth buffer attachment."); 212 213 // The same image are bound as stencil buffer in both read framebuffer and draw framebuffer 214 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fb0); 215 gl.framebufferRenderbuffer(gl.READ_FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, rb1); 216 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb1); 217 gl.framebufferRenderbuffer(gl.DRAW_FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, rb1); 218 if (gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE || 219 gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) { 220 testFailed("Framebuffer incomplete."); 221 return; 222 } 223 // But the mask doesn't have stencil buffer bit. 224 gl.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl.COLOR_BUFFER_BIT, gl.NEAREST); 225 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "blitFramebuffer should succeed."); 226 227 // The mask has stencil buffer bit. 228 gl.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT, gl.NEAREST); 229 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "blitFramebuffer should generate INVALID_OPERATION if read/draw framebuffer have identical stencil buffer attachment."); 230 231 // The same image are bound as color buffer in both read framebuffer and draw framebuffer 232 var rb2 = gl.createRenderbuffer(); 233 gl.bindRenderbuffer(gl.RENDERBUFFER, rb2); 234 gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH24_STENCIL8, width, height); 235 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fb0); 236 gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X, tex_cube_map, 0); 237 gl.framebufferRenderbuffer(gl.READ_FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, null); 238 gl.framebufferRenderbuffer(gl.DRAW_FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, null); 239 gl.framebufferRenderbuffer(gl.READ_FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, rb2); 240 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb1); 241 gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_NEGATIVE_X, tex_cube_map, 0); 242 gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT1, gl.TEXTURE_CUBE_MAP_POSITIVE_X, tex_cube_map, 0); 243 gl.framebufferRenderbuffer(gl.DRAW_FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, rb1); 244 if (gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE || 245 gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) { 246 testFailed("Framebuffer incomplete."); 247 return; 248 } 249 // But the mask doesn't have color buffer bit. 250 gl.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl.DEPTH_BUFFER_BIT, gl.NEAREST); 251 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "blitFramebuffer should succeed."); 252 253 // The mask has color buffer bit, but the same image is not specified as draw buffer. 254 gl.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT, gl.NEAREST); 255 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "blitFramebuffer should succeed."); 256 257 // The mask has color buffer bit, the same image is specified as both read buffer and draw buffer. 258 gl.drawBuffers([gl.COLOR_ATTACHENT0, gl.COLOR_ATTACHMENT1]); 259 gl.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT, gl.NEAREST); 260 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "blitFramebuffer should generate INVALID_OPERATION if read/draw buffers have identical color buffer attachment."); 261 262 gl.bindTexture(gl.TEXTURE_2D, null); 263 gl.bindTexture(gl.TEXTURE_CUBE_MAP, null); 264 gl.bindTexture(gl.TEXTURE_2D_ARRAY, null); 265 gl.bindRenderbuffer(gl.RENDERBUFFER, null); 266 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null); 267 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null); 268 gl.deleteTexture(tex_2d); 269 gl.deleteTexture(tex_cube_map); 270 gl.deleteTexture(tex_2d_array); 271 gl.deleteRenderbuffer(rb0); 272 gl.deleteRenderbuffer(rb1); 273 gl.deleteRenderbuffer(rb2); 274 gl.deleteFramebuffer(fb0); 275 gl.deleteFramebuffer(fb1); 276 }; 277 278 function blit_framebuffer_multisampling_srgb() { 279 280 debug(""); 281 debug("This test vefify the functionality of blitframebuffer from or to a multisampled srgb image."); 282 283 // Read buffer can have multisampled srgb image, but draw buffers can not. 284 var rb0 = gl.createRenderbuffer(); 285 var fb0 = gl.createFramebuffer(); 286 var rb1 = gl.createRenderbuffer(); 287 var fb1 = gl.createFramebuffer(); 288 var samples = gl.getInternalformatParameter(gl.RENDERBUFFER, gl.SRGB8_ALPHA8, gl.SAMPLES); 289 gl.bindRenderbuffer(gl.RENDERBUFFER, rb0); 290 gl.renderbufferStorageMultisample(gl.RENDERBUFFER, samples[0], gl.SRGB8_ALPHA8, width, height); 291 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fb0); 292 gl.framebufferRenderbuffer(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb0); 293 294 gl.bindRenderbuffer(gl.RENDERBUFFER, rb1); 295 gl.renderbufferStorage(gl.RENDERBUFFER, gl.SRGB8_ALPHA8, width, height); 296 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb1); 297 gl.framebufferRenderbuffer(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb1); 298 if (gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE || 299 gl.checkFramebufferStatus(gl.READ_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) { 300 testFailed("Framebuffer incomplete."); 301 return; 302 } 303 gl.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl.COLOR_BUFFER_BIT, gl.LINEAR); 304 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "blitFramebuffer from multisampled srgb image should succeed."); 305 306 gl.bindRenderbuffer(gl.RENDERBUFFER, rb1); 307 gl.renderbufferStorageMultisample(gl.RENDERBUFFER, samples[0], gl.SRGB8_ALPHA8, width, height); 308 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb1); 309 gl.framebufferRenderbuffer(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb1); 310 if (gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) { 311 testFailed("Framebuffer incomplete."); 312 return; 313 } 314 gl.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl.COLOR_BUFFER_BIT, gl.LINEAR); 315 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "blitFramebuffer to a multisampled srgb image should generate INVALID_OPERATION."); 316 317 // BlitFramebuffer from a multisampled srgb image, the src region and the dst region must be exactly the same. 318 gl.bindRenderbuffer(gl.RENDERBUFFER, rb1); 319 gl.renderbufferStorage(gl.RENDERBUFFER, gl.SRGB8_ALPHA8, width, height); 320 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb1); 321 gl.framebufferRenderbuffer(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, rb1); 322 if (gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) { 323 testFailed("Framebuffer incomplete."); 324 return; 325 } 326 gl.blitFramebuffer(0, 0, 2, 2, 2, 2, 4, 4, gl.COLOR_BUFFER_BIT, gl.LINEAR); 327 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "blitFramebuffer from a multisampled srgb image, the src region and the dst region must be exactly the same."); 328 329 gl.blitFramebuffer(0, 0, 2, 2, 0, 0, 4, 4, gl.COLOR_BUFFER_BIT, gl.LINEAR); 330 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "blitFramebuffer from a multisampled srgb image, the src region and the dst region must be exactly the same."); 331 332 // BlitFramebuffer from a multisampled srgb image, the format/type must be exactly the same. So blit from a multisampled srgb image to a linear image is invalid. 333 var tex = gl.createTexture(); 334 gl.bindTexture(gl.TEXTURE_2D, tex); 335 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 336 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb1); 337 gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0); 338 if (gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) { 339 testFailed("Framebuffer incomplete."); 340 return; 341 } 342 gl.blitFramebuffer(0, 0, 2, 2, 0, 0, 2, 2, gl.COLOR_BUFFER_BIT, gl.LINEAR); 343 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "blitFramebuffer from a multisampled srgb image, the format/type must be exactly the same."); 344 345 gl.bindRenderbuffer(gl.RENDERBUFFER, null); 346 gl.bindTexture(gl.TEXTURE_2D, null); 347 gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null); 348 gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null); 349 gl.deleteRenderbuffer(rb0); 350 gl.deleteRenderbuffer(rb1); 351 gl.deleteTexture(tex); 352 gl.deleteFramebuffer(fb0); 353 gl.deleteFramebuffer(fb1); 354 } 355 356 var successfullyParsed = true; 357 </script> 358 <script src="../../js/js-test-post.js"></script> 359 360 </body> 361 </html>