webgl-shader-pixel-local-storage.html (19986B)
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>WebGL WEBGL_shader_pixel_local_storage Conformance Tests</title> 6 <link rel="stylesheet" href="../../resources/js-test-style.css"/> 7 <script src="../../js/desktop-gl-constants.js"></script> 8 <script src="../../js/js-test-pre.js"></script> 9 <script src="../../js/webgl-test-utils.js"></script> 10 <script src="../../js/tests/compositing-test.js"></script> 11 <script src="../../js/tests/invalid-vertex-attrib-test.js"></script> 12 </head> 13 <body> 14 <div id="description"></div> 15 <canvas id="canvas" width="128" height="128" style="background-color:#080"> </canvas> 16 <canvas id="canvas_no_alpha" width="128" height="128"> </canvas> 17 <div id="console"></div> 18 <script> 19 "use strict"; 20 description("This test verifies the functionality of the WEBGL_shader_pixel_local_storage " + 21 "extension, if it is available."); 22 23 const wtu = WebGLTestUtils; 24 const canvas = document.getElementById("canvas"); 25 const gl = wtu.create3DContext(canvas, {alpha: true}, 2); 26 const gl_no_alpha = wtu.create3DContext("canvas_no_alpha", {alpha: false}, 2); 27 let pls = null; 28 29 // Outputs a fullscreen quad from a 4-vertex triangle strip. 30 const fullscreenQuadVertexShader = `#version 300 es 31 void main() { 32 gl_Position.x = (gl_VertexID & 1) == 0 ? -1. : 1.; 33 gl_Position.y = (gl_VertexID & 2) == 0 ? -1. : 1.; 34 gl_Position.zw = vec2(0, 1); 35 }`; 36 37 function arraysEqual(a, b) { 38 if (typeof a !== typeof b) 39 return false; 40 if (a.length != b.length) 41 return false; 42 for (let i = 0; i < a.length; ++i) { 43 if (a[i] !== b[i]) 44 return false; 45 } 46 return true; 47 } 48 49 async function runTest() { 50 if (!gl) { 51 testFailed("WebGL2 context does not exist"); 52 finishTest(); 53 return; 54 } 55 56 debug("\nCheck the behavior surrounding WEBGL_shader_pixel_local_storage being enabled."); 57 checkExtensionNotSupportedWhenDisabled(); 58 checkDependencyExtensionsEnabled(false); 59 debug("Enable WEBGL_shader_pixel_local_storage."); 60 pls = gl.getExtension("WEBGL_shader_pixel_local_storage"); 61 wtu.runExtensionSupportedTest(gl, "WEBGL_shader_pixel_local_storage", pls != null); 62 if (!pls) { 63 finishTest(); 64 return; 65 } 66 checkDependencyExtensionsEnabled(true); 67 68 checkImplementationDependentLimits(); 69 checkInitialValues(); 70 checkWebGLNonNormativeBehavior(); 71 72 await checkRendering(gl); 73 await checkRendering(gl_no_alpha); 74 75 finishTest(); 76 } 77 78 function checkExtensionNotSupportedWhenDisabled() { 79 debug("\nCheck that a context does not support WEBGL_shader_pixel_local_storage before it is " + 80 "enabled"); 81 shouldBeNull("gl.getParameter(0x96E0 /*MAX_PIXEL_LOCAL_STORAGE_PLANES_WEBGL*/)"); 82 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "parameter unknown without enabling the extension"); 83 shouldBeNull( 84 "gl.getParameter(0x96E1 /*MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_WEBGL*/)"); 85 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "parameter unknown without enabling the extension"); 86 shouldBeNull( 87 "gl.getParameter(0x96E2 /*MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_WEBGL*/)"); 88 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "parameter unknown without enabling the extension"); 89 shouldBeNull( 90 "gl.getParameter(0x96E3 /*PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_WEBGL*/)"); 91 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, "parameter unknown without enabling the extension"); 92 wtu.glErrorShouldBe(gl, gl.NONE); 93 } 94 95 function checkDependencyExtensionsEnabled(enabled) { 96 debug("\nCheck that dependency extensions of WEBGL_shader_pixel_local_storage are " + 97 (enabled ? "enabled" : "disabled")); 98 if (wtu.getSupportedExtensionWithKnownPrefixes(gl, "OES_draw_buffers_indexed") !== undefined) { 99 gl.getIndexedParameter(gl.BLEND_EQUATION_RGB, 1); 100 wtu.glErrorShouldBe(gl, enabled ? gl.NONE : gl.INVALID_ENUM, 101 "OES_draw_buffers_indexed not enabled or disabled as expected"); 102 } 103 if (wtu.getSupportedExtensionWithKnownPrefixes(gl, "EXT_color_buffer_float") !== undefined) { 104 gl.bindRenderbuffer(gl.RENDERBUFFER, gl.createRenderbuffer()); 105 gl.renderbufferStorage(gl.RENDERBUFFER, gl.R32F, 1, 1); 106 wtu.glErrorShouldBe(gl, enabled ? gl.NONE : gl.INVALID_ENUM, 107 "EXT_color_buffer_float not enabled or disabled as expected"); 108 gl.bindRenderbuffer(gl.RENDERBUFFER, null); 109 } 110 if (wtu.getSupportedExtensionWithKnownPrefixes(gl, "EXT_color_buffer_half_float") !== undefined) { 111 gl.bindRenderbuffer(gl.RENDERBUFFER, gl.createRenderbuffer()); 112 gl.renderbufferStorage(gl.RENDERBUFFER, gl.RG16F, 1, 1); 113 wtu.glErrorShouldBe(gl, enabled ? gl.NONE : gl.INVALID_ENUM, 114 "EXT_color_buffer_half_float not enabled or disabled as expected"); 115 gl.bindRenderbuffer(gl.RENDERBUFFER, null); 116 } 117 } 118 119 function checkImplementationDependentLimits() { 120 debug("\nVerify conformant implementation-dependent PLS limits."); 121 window.MAX_PIXEL_LOCAL_STORAGE_PLANES = 122 gl.getParameter(pls.MAX_PIXEL_LOCAL_STORAGE_PLANES_WEBGL); 123 window.MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE = 124 gl.getParameter(pls.MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_WEBGL); 125 window.MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES = 126 gl.getParameter(pls.MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_WEBGL); 127 wtu.glErrorShouldBe(gl, gl.NONE, "Pixel local storage queries should be supported."); 128 129 window.MAX_COLOR_ATTACHMENTS = gl.getParameter(gl.MAX_COLOR_ATTACHMENTS); 130 window.MAX_DRAW_BUFFERS = gl.getParameter(gl.MAX_DRAW_BUFFERS); 131 132 // Table 6.X: Impementation Dependent Pixel Local Storage Limits. 133 shouldBeTrue("MAX_PIXEL_LOCAL_STORAGE_PLANES >= 4"); 134 shouldBeTrue("MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE >= 0"); 135 shouldBeTrue("MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES >= 4"); 136 137 // Logical deductions based on 6.X. 138 shouldBeTrue(`MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES >= 139 MAX_PIXEL_LOCAL_STORAGE_PLANES`); 140 shouldBeTrue(`MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES >= 141 MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE`); 142 shouldBeTrue(`MAX_COLOR_ATTACHMENTS + MAX_PIXEL_LOCAL_STORAGE_PLANES >= 143 MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES`); 144 shouldBeTrue(`MAX_DRAW_BUFFERS + MAX_PIXEL_LOCAL_STORAGE_PLANES >= 145 MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES`); 146 } 147 148 function checkInitialValues() { 149 debug("\nCheck that PLS state has the correct initial values."); 150 shouldBeTrue("gl.getParameter(pls.PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_WEBGL) == 0"); 151 wtu.glErrorShouldBe( 152 gl, gl.NONE, 153 "It's valid to query GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_WEBGL even when fbo 0 is bound."); 154 155 // Table 6.Y: Pixel Local Storage State 156 gl.bindFramebuffer(gl.FRAMEBUFFER, gl.createFramebuffer()); 157 shouldBeTrue("gl.getParameter(pls.PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_WEBGL) == 0"); 158 debug("Check the initial clear values for each plane."); 159 const MAX_PIXEL_LOCAL_STORAGE_PLANES = 160 gl.getParameter(pls.MAX_PIXEL_LOCAL_STORAGE_PLANES_WEBGL); 161 for (let i = 0; i < MAX_PIXEL_LOCAL_STORAGE_PLANES; ++i) 162 { 163 expectTrue(pls.getFramebufferPixelLocalStorageParameterWEBGL( 164 i, pls.PIXEL_LOCAL_FORMAT_WEBGL) == gl.NONE); 165 expectTrue(pls.getFramebufferPixelLocalStorageParameterWEBGL( 166 i, pls.PIXEL_LOCAL_TEXTURE_NAME_WEBGL) == null); 167 expectTrue(pls.getFramebufferPixelLocalStorageParameterWEBGL( 168 i, pls.PIXEL_LOCAL_TEXTURE_LEVEL_WEBGL) == 0); 169 expectTrue(pls.getFramebufferPixelLocalStorageParameterWEBGL( 170 i, pls.PIXEL_LOCAL_TEXTURE_LAYER_WEBGL) == 0); 171 expectTrue(arraysEqual( 172 pls.getFramebufferPixelLocalStorageParameterWEBGL( 173 i, pls.PIXEL_LOCAL_CLEAR_VALUE_FLOAT_WEBGL), 174 new Float32Array([0, 0, 0, 0]))); 175 expectTrue(arraysEqual( 176 pls.getFramebufferPixelLocalStorageParameterWEBGL( 177 i, pls.PIXEL_LOCAL_CLEAR_VALUE_INT_WEBGL), 178 new Int32Array([0, 0, 0, 0]))); 179 expectTrue(arraysEqual( 180 pls.getFramebufferPixelLocalStorageParameterWEBGL( 181 i, pls.PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT_WEBGL), 182 new Uint32Array([0, 0, 0, 0]))); 183 } 184 wtu.glErrorShouldBe(gl, gl.NONE); 185 gl.bindFramebuffer(gl.FRAMEBUFFER, null); 186 } 187 188 function checkWebGLNonNormativeBehavior() { 189 debug("\nCheck the WebGL-specific behavior not found in the " + 190 "ANGLE_shader_pixel_local_storage specification."); 191 gl.bindFramebuffer(gl.FRAMEBUFFER, gl.createFramebuffer()); 192 193 debug("If 'texture' has been deleted, generates an INVALID_OPERATION error."); 194 wtu.glErrorShouldBe(gl, gl.NONE); 195 const tex = gl.createTexture(); 196 gl.bindTexture(gl.TEXTURE_2D, tex); 197 gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, 1, 1); 198 wtu.glErrorShouldBe(gl, gl.NONE); 199 gl.deleteTexture(tex); 200 pls.framebufferTexturePixelLocalStorageWEBGL(0, tex, 0, 0); 201 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION); 202 203 debug("\nIf 'texture' was generated by a different WebGL2RenderingContext than this one, " + 204 "generates an INVALID_OPERATION error."); 205 const gl2 = wtu.create3DContext(null, null, 2); 206 const tex2 = gl2.createTexture(); 207 gl2.bindTexture(gl2.TEXTURE_2D, tex2); 208 gl2.texStorage2D(gl2.TEXTURE_2D, 1, gl2.RGBA8, 1, 1); 209 pls.framebufferTexturePixelLocalStorageWEBGL(0, tex2, 0, 0); 210 wtu.glErrorShouldBe(gl2, gl2.NONE); 211 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION); 212 213 debug("\nIf value has less than srcOffset + 4 elements, generates an INVALID_VALUE error."); 214 wtu.glErrorShouldBe(gl, gl.NONE); 215 pls.framebufferPixelLocalClearValuefvWEBGL(0, new Float32Array(3)); 216 wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); 217 pls.framebufferPixelLocalClearValuefvWEBGL(1, [0, 0, 0]); 218 wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); 219 pls.framebufferPixelLocalClearValueivWEBGL(2, new Int32Array(3)); 220 wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); 221 pls.framebufferPixelLocalClearValueivWEBGL(3, [0, 0, 0]); 222 wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); 223 pls.framebufferPixelLocalClearValueuivWEBGL(4, new Uint32Array(3)); 224 wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); 225 pls.framebufferPixelLocalClearValueuivWEBGL(3, [0, 0, 0]); 226 wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); 227 pls.framebufferPixelLocalClearValuefvWEBGL(2, new Float32Array(5), 2); 228 wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); 229 pls.framebufferPixelLocalClearValuefvWEBGL(1, [0, 0, 0, 0, 0], 2); 230 wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); 231 pls.framebufferPixelLocalClearValueivWEBGL(0, new Int32Array(5), 2); 232 wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); 233 pls.framebufferPixelLocalClearValueivWEBGL(1, [0, 0, 0, 0, 0], 2); 234 wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); 235 pls.framebufferPixelLocalClearValueuivWEBGL(2, new Uint32Array(5), 2); 236 wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); 237 pls.framebufferPixelLocalClearValueuivWEBGL(3, [0, 0, 0, 0, 0], 2); 238 wtu.glErrorShouldBe(gl, gl.INVALID_VALUE); 239 240 debug("\nCheck that srcOffset works properly."); 241 const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; 242 pls.framebufferPixelLocalClearValuefvWEBGL(0, new Float32Array(arr), 1); 243 wtu.glErrorShouldBe(gl, gl.NONE); 244 shouldBeTrue(`arraysEqual(pls.getFramebufferPixelLocalStorageParameterWEBGL( 245 0, pls.PIXEL_LOCAL_CLEAR_VALUE_FLOAT_WEBGL), 246 new Float32Array([1, 2, 3, 4]))`); 247 pls.framebufferPixelLocalClearValuefvWEBGL(1, arr, 2); 248 wtu.glErrorShouldBe(gl, gl.NONE); 249 shouldBeTrue(`arraysEqual(pls.getFramebufferPixelLocalStorageParameterWEBGL( 250 1, pls.PIXEL_LOCAL_CLEAR_VALUE_FLOAT_WEBGL), 251 [2, 3, 4, 5])`); 252 pls.framebufferPixelLocalClearValueivWEBGL(2, new Int32Array(arr), 3); 253 wtu.glErrorShouldBe(gl, gl.NONE); 254 shouldBeTrue(`arraysEqual(pls.getFramebufferPixelLocalStorageParameterWEBGL( 255 2, pls.PIXEL_LOCAL_CLEAR_VALUE_INT_WEBGL), 256 new Float32Array([3, 4, 5, 6]))`); 257 pls.framebufferPixelLocalClearValueivWEBGL(3, arr, 4); 258 wtu.glErrorShouldBe(gl, gl.NONE); 259 shouldBeTrue(`arraysEqual(pls.getFramebufferPixelLocalStorageParameterWEBGL( 260 3, pls.PIXEL_LOCAL_CLEAR_VALUE_INT_WEBGL), 261 [4, 5, 6, 7])`); 262 pls.framebufferPixelLocalClearValueuivWEBGL(2, new Uint32Array(arr), 5); 263 wtu.glErrorShouldBe(gl, gl.NONE); 264 shouldBeTrue(`arraysEqual(pls.getFramebufferPixelLocalStorageParameterWEBGL( 265 2, pls.PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT_WEBGL), 266 new Uint32Array([5, 6, 7, 8]))`); 267 pls.framebufferPixelLocalClearValueuivWEBGL(1, arr, 6); 268 wtu.glErrorShouldBe(gl, gl.NONE); 269 shouldBeTrue(`arraysEqual(pls.getFramebufferPixelLocalStorageParameterWEBGL( 270 1, pls.PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT_WEBGL), 271 [6, 7, 8, 9])`); 272 wtu.glErrorShouldBe(gl, gl.NONE); 273 274 debug("\nCheck that PIXEL_LOCAL_TEXTURE_NAME_WEBGL returns a WebGLTexture."); 275 shouldBeTrue(`pls.getFramebufferPixelLocalStorageParameterWEBGL( 276 0, pls.PIXEL_LOCAL_TEXTURE_NAME_WEBGL) === null`); 277 window.validTex = gl.createTexture(); 278 gl.bindTexture(gl.TEXTURE_2D, validTex); 279 gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, 1, 1); 280 wtu.glErrorShouldBe(gl, gl.NONE); 281 pls.framebufferTexturePixelLocalStorageWEBGL(0, validTex, 0, 0); 282 shouldBeTrue(`pls.getFramebufferPixelLocalStorageParameterWEBGL( 283 0, pls.PIXEL_LOCAL_TEXTURE_NAME_WEBGL) === validTex`); 284 pls.framebufferTexturePixelLocalStorageWEBGL(0, null, 0, 0); 285 shouldBeTrue(`pls.getFramebufferPixelLocalStorageParameterWEBGL( 286 0, pls.PIXEL_LOCAL_TEXTURE_NAME_WEBGL) === null`); 287 288 wtu.glErrorShouldBe(gl, gl.NONE); 289 gl.bindFramebuffer(gl.FRAMEBUFFER, null); 290 } 291 292 async function checkRendering(localGL) { 293 const localCanvas = localGL.canvas; 294 const alpha = localGL.getContextAttributes().alpha; 295 debug("\nCheck very simple rendering with {alpha: " + alpha + "}"); 296 297 const localPLS = localGL.getExtension("WEBGL_shader_pixel_local_storage"); 298 if (!localPLS) { 299 testFailed("localGL doesn't support pixel local storage."); 300 return; 301 } 302 303 const tex = localGL.createTexture(); 304 localGL.bindTexture(localGL.TEXTURE_2D, tex); 305 localGL.texStorage2D(localGL.TEXTURE_2D, 1, localGL.RGBA8, localCanvas.width, localCanvas.height); 306 wtu.glErrorShouldBe(localGL, localGL.NONE); 307 308 const plsFBO = localGL.createFramebuffer(); 309 localGL.bindFramebuffer(localGL.FRAMEBUFFER, plsFBO); 310 localPLS.framebufferTexturePixelLocalStorageWEBGL(0, tex, 0, 0); 311 wtu.glErrorShouldBe(localGL, localGL.NONE); 312 313 localGL.viewport(0, 0, localCanvas.width, localCanvas.height); 314 315 // Adds a uniform color into the existing color in pixel local storage. 316 const fs = `#version 300 es 317 #extension GL_ANGLE_shader_pixel_local_storage : require 318 precision lowp float; 319 uniform vec4 color; 320 layout(binding=0, rgba8) uniform lowp pixelLocalANGLE pls; 321 void main() { 322 vec4 newColor = color + pixelLocalLoadANGLE(pls); 323 pixelLocalStoreANGLE(pls, newColor); 324 }`; 325 326 const program = wtu.setupProgram(localGL, [fullscreenQuadVertexShader, fs]); 327 if (!program) { 328 testFailed("Failed to compile program."); 329 return; 330 } 331 332 localGL.useProgram(program); 333 const colorUniLocation = localGL.getUniformLocation(program, "color"); 334 wtu.glErrorShouldBe(localGL, localGL.NONE); 335 336 // Disable color mask to ensure PLS and canvas manage their own color masks properly. 337 localGL.colorMask(false, true, false, true); 338 339 // Set global variables for shouldBeTrue(). 340 window.localGL = localGL; 341 window.localPLS = localPLS; 342 343 debug("\nCheck that pixel local storage works properly"); 344 localGL.disable(localGL.DITHER); 345 localPLS.beginPixelLocalStorageWEBGL([localPLS.LOAD_OP_ZERO_WEBGL]); 346 wtu.glErrorShouldBe(localGL, localGL.NONE); 347 shouldBeTrue("localGL.getParameter(localPLS.PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_WEBGL) == 1"); 348 349 localGL.uniform4f(colorUniLocation, 0, 1, 0, 0); 350 localGL.drawArrays(localGL.TRIANGLE_STRIP, 0, 4); 351 352 localPLS.pixelLocalStorageBarrierWEBGL(); 353 354 localGL.uniform4f(colorUniLocation, 1, 0, 0, 0); 355 localGL.drawArrays(localGL.TRIANGLE_STRIP, 0, 4); 356 357 localPLS.endPixelLocalStorageWEBGL([localPLS.STORE_OP_STORE_WEBGL]); 358 wtu.glErrorShouldBe(localGL, localGL.NONE); 359 shouldBeTrue("localGL.getParameter(localPLS.PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_WEBGL) == 0"); 360 361 const readFBO = localGL.createFramebuffer(); 362 localGL.bindFramebuffer(localGL.READ_FRAMEBUFFER, readFBO); 363 localGL.framebufferTexture2D(localGL.READ_FRAMEBUFFER, localGL.COLOR_ATTACHMENT0, 364 localGL.TEXTURE_2D, tex, 0); 365 wtu.glErrorShouldBe(localGL, localGL.NONE); 366 wtu.checkCanvas(localGL, [255, 255, 0, 0]); 367 368 debug("\nCheck that alpha is properly handled in the main canvas."); 369 localGL.bindFramebuffer(localGL.DRAW_FRAMEBUFFER, null); 370 localGL.blitFramebuffer(0, 0, localCanvas.width, localCanvas.height, 0, 0, localCanvas.width, 371 localCanvas.height, localGL.COLOR_BUFFER_BIT, localGL.NEAREST); 372 localGL.bindFramebuffer(localGL.FRAMEBUFFER, null); 373 wtu.glErrorShouldBe(localGL, localGL.NONE); 374 wtu.checkCanvas(localGL, [255, 255, 0, alpha ? 0 : 255]); 375 376 localGL.bindFramebuffer(localGL.FRAMEBUFFER, plsFBO); 377 localPLS.beginPixelLocalStorageWEBGL([localPLS.LOAD_OP_LOAD_WEBGL]); 378 wtu.glErrorShouldBe(localGL, localGL.NONE); 379 shouldBeTrue("localGL.getParameter(localPLS.PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_WEBGL) == 1"); 380 381 debug("\nGoing down from composite."); 382 383 // The canvas should get cleared after compositing, even if PLS is active and color mask is 384 // disabled. 385 await new Promise(resolve => wtu.waitForComposite(resolve)); 386 387 // Reset global variables for shouldBeTrue() after await. 388 window.localGL = localGL; 389 window.localPLS = localPLS; 390 391 debug("\nBack from composite!"); 392 debug("\nPLS should still be active on plsFBO even after being interrupted for compositing."); 393 wtu.glErrorShouldBe(localGL, localGL.NONE); 394 shouldBeTrue("localGL.getParameter(localPLS.PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_WEBGL) == 1"); 395 396 localGL.uniform4f(colorUniLocation, 0, 0, 1, 0); 397 localGL.drawArrays(localGL.TRIANGLE_STRIP, 0, 4); 398 399 localPLS.endPixelLocalStorageWEBGL([localPLS.STORE_OP_STORE_WEBGL]); 400 wtu.glErrorShouldBe(localGL, localGL.NONE); 401 shouldBeTrue("localGL.getParameter(localPLS.PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_WEBGL) == 0"); 402 403 debug("\nThe canvas should have gotten cleared while PLS was active."); 404 localGL.bindFramebuffer(localGL.FRAMEBUFFER, null); 405 wtu.checkCanvas(localGL, [0, 0, 0, alpha ? 0 : 255]); 406 407 debug("\nThe additional PLS draw to plsFBO should have still worked after being interrupted " + 408 "for compositing."); 409 localGL.bindFramebuffer(localGL.READ_FRAMEBUFFER, readFBO); 410 wtu.checkCanvas(localGL, [255, 255, 255, 0]); 411 wtu.glErrorShouldBe(localGL, localGL.NONE); 412 413 // Draws 'tex' to the canvas. 414 const fs2 = `#version 300 es 415 uniform lowp sampler2D tex; 416 out lowp vec4 fragColor; 417 void main() { 418 ivec2 pixelCoord = ivec2(floor(gl_FragCoord.xy)); 419 fragColor = texelFetch(tex, pixelCoord, 0); 420 }`; 421 422 const program2 = wtu.setupProgram(localGL, [fullscreenQuadVertexShader, fs2]); 423 if (!program2) { 424 testFailed("Failed to compile program2."); 425 return; 426 } 427 428 debug("\nBlue should still be disabled in the color mask. Alpha is not disabled but should be " + 429 "implicitly disabled since the canvas doesn't have alpha."); 430 localGL.useProgram(program2); 431 localGL.uniform1i(localGL.getUniformLocation(program2, "tex"), 0); 432 localGL.bindFramebuffer(localGL.FRAMEBUFFER, null); 433 localGL.drawArrays(localGL.TRIANGLE_STRIP, 0, 4); 434 wtu.checkCanvas(localGL, [0, 255, 0, alpha ? 0 : 255]); 435 436 debug("\nThe client's color mask should have been preserved."); 437 shouldBeTrue(`arraysEqual(localGL.getParameter(localGL.COLOR_WRITEMASK), 438 [false, true, false, true])`); 439 } 440 441 runTest(); 442 var successfullyParsed = true; 443 </script> 444 </body> 445 </html>