oes-draw-buffers-indexed.html (22467B)
1 <!-- 2 Copyright (c) 2020 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 OES_draw_buffers_indexed Conformance 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 width="20" height="20" style="border: 1px solid blue;" id="c"></canvas> 18 <div id="description"></div> 19 <div id="console"></div> 20 <script> 21 "use strict"; 22 description("This test verifies the functionality of the OES_draw_buffers_indexed extension, if it is available."); 23 24 debug(""); 25 26 var wtu = WebGLTestUtils; 27 var gl = wtu.create3DContext("c", null, 2); 28 var ext; 29 30 const vs = `#version 300 es 31 layout(location=0) in vec4 vPosition; 32 void main() 33 { 34 gl_Position = vPosition; 35 } 36 `; 37 38 const fs = `#version 300 es 39 precision lowp float; 40 layout(location = 0) out vec4 o_color0; 41 layout(location = 1) out vec4 o_color1; 42 void main() 43 { 44 o_color0 = vec4(1, 0, 0, 0); 45 o_color1 = vec4(1, 0, 0, 0); 46 } 47 `; 48 49 function setup() { 50 const program = wtu.setupProgram(gl, [vs, fs]); 51 gl.useProgram(program); 52 wtu.setupUnitQuad(gl, 0); 53 wtu.glErrorShouldBe(gl, 0, 'No errors from program'); 54 55 const tex1 = gl.createTexture(); 56 gl.bindTexture(gl.TEXTURE_2D, tex1); 57 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 58 wtu.glErrorShouldBe(gl, 0, 'Create texture 1 successfully'); 59 60 const tex2 = gl.createTexture(); 61 gl.bindTexture(gl.TEXTURE_2D, tex2); 62 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 63 wtu.glErrorShouldBe(gl, 0, 'Create texture 2 successfully'); 64 65 const attachments = [gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1]; 66 67 const fb = gl.createFramebuffer(); 68 gl.bindFramebuffer(gl.FRAMEBUFFER, fb); 69 gl.framebufferTexture2D(gl.FRAMEBUFFER, attachments[0], gl.TEXTURE_2D, tex1, 0); 70 gl.framebufferTexture2D(gl.FRAMEBUFFER, attachments[1], gl.TEXTURE_2D, tex2, 0); 71 shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE'); 72 73 gl.drawBuffers(attachments); 74 wtu.glErrorShouldBe(gl, 0, 'Set draw buffers without errors'); 75 } 76 77 function enableDisableTest() { 78 debug("Testing enableiOES/disableiOES"); 79 80 // Invalid input 81 ext.enableiOES(gl.DEPTH_TEST, 0); 82 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, 'target could only be gl.BLEND'); 83 84 ext.disableiOES(gl.DEPTH_TEST, 0); 85 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, 'target could only be gl.BLEND'); 86 87 gl.disable(gl.BLEND); 88 89 // Valid input 90 ext.enableiOES(gl.BLEND, 0); 91 shouldBe('gl.isEnabled(gl.BLEND)', 'true'); 92 ext.disableiOES(gl.BLEND, 0); 93 ext.enableiOES(gl.BLEND, 1); 94 shouldBe('gl.isEnabled(gl.BLEND)', 'false'); 95 gl.enable(gl.BLEND); 96 shouldBe('gl.isEnabled(gl.BLEND)', 'true'); 97 wtu.glErrorShouldBe(gl, 0, 'No errors from enable and disable draw buffers blend state'); 98 } 99 100 function constantAlphaBlendColorValidationTest() { 101 debug("Testing CONSTANT_COLOR/ALPHA blend functions limit validation"); 102 function isConstantColorAndAlphaBlendFunctions(first, second) 103 { 104 return (first == gl.CONSTANT_COLOR || first == gl.ONE_MINUS_CONSTANT_COLOR) && 105 (second == gl.CONSTANT_ALPHA || second == gl.ONE_MINUS_CONSTANT_ALPHA); 106 } 107 108 function checkBlendFunctions(src, dst) 109 { 110 if (isConstantColorAndAlphaBlendFunctions(src, dst) || 111 isConstantColorAndAlphaBlendFunctions(dst, src)) 112 { 113 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, 'invalid combinations'); 114 return false; 115 } 116 else 117 { 118 wtu.glErrorShouldBe(gl, 0, 'No error'); 119 return true; 120 } 121 } 122 123 const srcFunc = [ 124 gl.ZERO, 125 gl.ONE, 126 gl.SRC_COLOR, 127 gl.ONE_MINUS_SRC_COLOR, 128 gl.DST_COLOR, 129 gl.ONE_MINUS_DST_COLOR, 130 gl.SRC_ALPHA, 131 gl.ONE_MINUS_SRC_ALPHA, 132 gl.DST_ALPHA, 133 gl.ONE_MINUS_DST_ALPHA, 134 gl.CONSTANT_COLOR, 135 gl.ONE_MINUS_CONSTANT_COLOR, 136 gl.CONSTANT_ALPHA, 137 gl.ONE_MINUS_CONSTANT_ALPHA, 138 gl.SRC_ALPHA_SATURATE, 139 ]; 140 141 const dstFunc = [ 142 gl.ZERO, gl.ONE, 143 gl.SRC_COLOR, gl.ONE_MINUS_SRC_COLOR, 144 gl.DST_COLOR, gl.ONE_MINUS_DST_COLOR, 145 gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, 146 gl.DST_ALPHA, gl.ONE_MINUS_DST_ALPHA, 147 gl.CONSTANT_COLOR, gl.ONE_MINUS_CONSTANT_COLOR, 148 gl.CONSTANT_ALPHA, gl.ONE_MINUS_CONSTANT_ALPHA, 149 ]; 150 151 let src, dst; 152 153 // CONSTANT_COLOR/ALPHA invalid combination check 154 for (let i = 0, leni = srcFunc.length; i < leni; i++) 155 { 156 src = srcFunc[i]; 157 for (let j = 0, lenj = dstFunc.length; j < lenj; j++) 158 { 159 dst = dstFunc[j]; 160 ext.blendFunciOES(0, src, dst); 161 checkBlendFunctions(src, dst); 162 ext.blendFuncSeparateiOES(0, src, dst, gl.ONE, gl.ONE); 163 checkBlendFunctions(src, dst); 164 } 165 } 166 } 167 168 function indexedBlendColorTest() { 169 debug(''); 170 debug("Testing blendEquationiOES and blendFunciOES"); 171 wtu.glErrorShouldBe(gl, 0, 'top of indexedBlendColorTest'); 172 173 gl.clearColor(0, 0, 1, 1); 174 gl.clear(gl.COLOR_BUFFER_BIT); 175 176 ext.blendEquationiOES(0, gl.FUNC_ADD); 177 ext.blendFunciOES(0, gl.ONE, gl.ONE); 178 ext.blendEquationiOES(1, gl.FUNC_ADD); 179 ext.blendFunciOES(1, gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); 180 gl.drawArrays(gl.TRIANGLES, 0, 6); 181 wtu.glErrorShouldBe(gl, 0, 'Draw quad without errors'); 182 183 gl.readBuffer(gl.COLOR_ATTACHMENT0); 184 wtu.checkCanvasRect(gl, 0, 0, 1, 1, [255, 0, 255, 255]); 185 186 gl.readBuffer(gl.COLOR_ATTACHMENT1); 187 wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 0, 255, 255]); 188 189 debug("Testing blendEquationSeparateiOES and blendFuncSeparateiOES"); 190 gl.clear(gl.COLOR_BUFFER_BIT); 191 192 ext.blendEquationSeparateiOES(0, gl.FUNC_ADD, gl.FUNC_SUBTRACT); 193 ext.blendFuncSeparateiOES(0, gl.ONE, gl.ONE, gl.ZERO, gl.ZERO); 194 ext.blendEquationSeparateiOES(1, gl.FUNC_ADD, gl.FUNC_SUBTRACT); 195 ext.blendFuncSeparateiOES(1, gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ZERO, gl.ZERO); 196 gl.drawArrays(gl.TRIANGLES, 0, 6); 197 wtu.glErrorShouldBe(gl, 0, 'Draw quad without errors'); 198 199 gl.readBuffer(gl.COLOR_ATTACHMENT0); 200 wtu.checkCanvasRect(gl, 0, 0, 1, 1, [255, 0, 255, 0]); 201 202 gl.readBuffer(gl.COLOR_ATTACHMENT1); 203 wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 0, 255, 0]); 204 205 debug("Testing colorMaskiOES"); 206 gl.clear(gl.COLOR_BUFFER_BIT); 207 ext.colorMaskiOES(0, false, false, false, false); 208 ext.colorMaskiOES(1, true, true, true, true); 209 210 gl.drawArrays(gl.TRIANGLES, 0, 6); 211 wtu.glErrorShouldBe(gl, 0, 'Draw quad without errors'); 212 213 gl.readBuffer(gl.COLOR_ATTACHMENT0); 214 wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 0, 255, 255]); 215 216 gl.readBuffer(gl.COLOR_ATTACHMENT1); 217 wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 0, 255, 0]); 218 219 debug(''); 220 debug(`Testing that new tokens aren't on the extension.`); 221 shouldBe('ext.BLEND_EQUATION_RGB', 'undefined'); 222 shouldBe('ext.BLEND_EQUATION_ALPHA', 'undefined'); 223 shouldBe('ext.BLEND_SRC_RGB', 'undefined'); 224 shouldBe('ext.BLEND_SRC_ALPHA', 'undefined'); 225 shouldBe('ext.BLEND_DST_RGB', 'undefined'); 226 shouldBe('ext.BLEND_DST_ALPHA', 'undefined'); 227 shouldBe('ext.COLOR_WRITEMASK', 'undefined'); 228 229 debug("Testing new tokens for getIndexedParameterTest"); 230 shouldBe('gl.getIndexedParameter(gl.BLEND_EQUATION_RGB, 0)', 'gl.FUNC_ADD'); 231 shouldBe('gl.getIndexedParameter(gl.BLEND_EQUATION_ALPHA, 0)', 'gl.FUNC_SUBTRACT'); 232 shouldBe('gl.getIndexedParameter(gl.BLEND_SRC_RGB, 0)', 'gl.ONE'); 233 shouldBe('gl.getIndexedParameter(gl.BLEND_DST_RGB, 0)', 'gl.ONE'); 234 shouldBe('gl.getIndexedParameter(gl.BLEND_SRC_ALPHA, 0)', 'gl.ZERO'); 235 shouldBe('gl.getIndexedParameter(gl.BLEND_DST_ALPHA, 0)', 'gl.ZERO'); 236 shouldBe('gl.getIndexedParameter(gl.BLEND_EQUATION_RGB, 1)', 'gl.FUNC_ADD'); 237 shouldBe('gl.getIndexedParameter(gl.BLEND_EQUATION_ALPHA, 1)', 'gl.FUNC_SUBTRACT'); 238 shouldBe('gl.getIndexedParameter(gl.BLEND_SRC_RGB, 1)', 'gl.SRC_ALPHA'); 239 shouldBe('gl.getIndexedParameter(gl.BLEND_DST_RGB, 1)', 'gl.ONE_MINUS_SRC_ALPHA'); 240 shouldBe('gl.getIndexedParameter(gl.BLEND_SRC_ALPHA, 1)', 'gl.ZERO'); 241 shouldBe('gl.getIndexedParameter(gl.BLEND_DST_ALPHA, 1)', 'gl.ZERO'); 242 243 shouldBe('gl.getIndexedParameter(gl.COLOR_WRITEMASK, 0)', '[false, false, false, false]'); 244 shouldBe('gl.getIndexedParameter(gl.COLOR_WRITEMASK, 1)', '[true, true, true, true]'); 245 246 debug("Testing non-indexed getParamter get state from draw buffer 0"); 247 shouldBe('gl.getParameter(gl.BLEND_SRC_RGB)', 'gl.ONE'); 248 shouldBe('gl.getParameter(gl.BLEND_DST_RGB)', 'gl.ONE'); 249 shouldBe('gl.getParameter(gl.BLEND_SRC_ALPHA)', 'gl.ZERO'); 250 shouldBe('gl.getParameter(gl.BLEND_DST_ALPHA)', 'gl.ZERO'); 251 shouldBe('gl.getParameter(gl.BLEND_EQUATION_RGB)', 'gl.FUNC_ADD'); 252 shouldBe('gl.getParameter(gl.BLEND_EQUATION_ALPHA)', 'gl.FUNC_SUBTRACT'); 253 shouldBe('gl.getParameter(gl.COLOR_WRITEMASK)', '[false, false, false, false]'); 254 255 debug("Testing non-indexed calls modify all draw buffers state"); 256 gl.blendEquationSeparate(gl.FUNC_SUBTRACT, gl.FUNC_ADD); 257 gl.blendFuncSeparate(gl.ONE_MINUS_DST_ALPHA, gl.DST_ALPHA, gl.ONE, gl.ONE); 258 gl.colorMask(true, false, true, false); 259 wtu.glErrorShouldBe(gl, 0, 'Non-indexed state set without errors'); 260 261 shouldBe('gl.getParameter(gl.BLEND_EQUATION_RGB)', 'gl.FUNC_SUBTRACT'); 262 shouldBe('gl.getParameter(gl.BLEND_EQUATION_ALPHA)', 'gl.FUNC_ADD'); 263 shouldBe('gl.getParameter(gl.BLEND_SRC_RGB)', 'gl.ONE_MINUS_DST_ALPHA'); 264 shouldBe('gl.getParameter(gl.BLEND_DST_RGB)', 'gl.DST_ALPHA'); 265 shouldBe('gl.getParameter(gl.BLEND_SRC_ALPHA)', 'gl.ONE'); 266 shouldBe('gl.getParameter(gl.BLEND_DST_ALPHA)', 'gl.ONE'); 267 shouldBe('gl.getParameter(gl.COLOR_WRITEMASK)', '[true, false, true, false]'); 268 269 shouldBe('gl.getIndexedParameter(gl.BLEND_EQUATION_RGB, 0)', 'gl.FUNC_SUBTRACT'); 270 shouldBe('gl.getIndexedParameter(gl.BLEND_EQUATION_ALPHA, 0)', 'gl.FUNC_ADD'); 271 shouldBe('gl.getIndexedParameter(gl.BLEND_SRC_RGB, 0)', 'gl.ONE_MINUS_DST_ALPHA'); 272 shouldBe('gl.getIndexedParameter(gl.BLEND_DST_RGB, 0)', 'gl.DST_ALPHA'); 273 shouldBe('gl.getIndexedParameter(gl.BLEND_SRC_ALPHA, 0)', 'gl.ONE'); 274 shouldBe('gl.getIndexedParameter(gl.BLEND_DST_ALPHA, 0)', 'gl.ONE'); 275 shouldBe('gl.getIndexedParameter(gl.BLEND_EQUATION_RGB, 1)', 'gl.FUNC_SUBTRACT'); 276 shouldBe('gl.getIndexedParameter(gl.BLEND_EQUATION_ALPHA, 1)', 'gl.FUNC_ADD'); 277 shouldBe('gl.getIndexedParameter(gl.BLEND_SRC_RGB, 1)', 'gl.ONE_MINUS_DST_ALPHA'); 278 shouldBe('gl.getIndexedParameter(gl.BLEND_DST_RGB, 1)', 'gl.DST_ALPHA'); 279 shouldBe('gl.getIndexedParameter(gl.BLEND_SRC_ALPHA, 1)', 'gl.ONE'); 280 shouldBe('gl.getIndexedParameter(gl.BLEND_DST_ALPHA, 1)', 'gl.ONE'); 281 282 shouldBe('gl.getIndexedParameter(gl.COLOR_WRITEMASK, 0)', '[true, false, true, false]'); 283 shouldBe('gl.getIndexedParameter(gl.COLOR_WRITEMASK, 1)', '[true, false, true, false]'); 284 } 285 286 function runTestExtension() { 287 setup(); 288 289 testInvalidValues(); 290 291 enableDisableTest(); 292 293 // blending should be enabled for drawBuffers 0 and 1 at this point 294 295 constantAlphaBlendColorValidationTest(); 296 297 indexedBlendColorTest(); 298 299 testColorMaskDrawNoOp(); 300 301 testColorMaskAfterComposite(); 302 } 303 304 function runInvalidEnumsTest() { 305 debug("Testing new enums for getIndexedParameterTest being invalid before requesting the extension"); 306 shouldBeNull("gl.getIndexedParameter(0x8009, 0)"); // BLEND_EQUATION_RGB 307 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, 'BLEND_EQUATION_RGB'); 308 shouldBeNull("gl.getIndexedParameter(0x883D, 0)"); // BLEND_EQUATION_ALPHA 309 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, 'BLEND_EQUATION_ALPHA'); 310 shouldBeNull("gl.getIndexedParameter(0x80C9, 0)"); // BLEND_SRC_RGB 311 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, 'BLEND_SRC_RGB'); 312 shouldBeNull("gl.getIndexedParameter(0x80CB, 0)"); // BLEND_SRC_ALPHA 313 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, 'BLEND_SRC_ALPHA'); 314 shouldBeNull("gl.getIndexedParameter(0x80C8, 0)"); // BLEND_DST_RGB 315 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, 'BLEND_DST_RGB'); 316 shouldBeNull("gl.getIndexedParameter(0x80CA, 0)"); // BLEND_DST_ALPHA 317 wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, 'BLEND_DST_ALPHA'); 318 shouldBeNull("gl.getIndexedParameter(0x0C23, 0)"); // COLOR_WRITEMASK 319 wtu.glErrorShouldBe(gl, [gl.INVALID_OPERATION, gl.INVALID_ENUM], 'invalid operations or invalid enums for COLOR_WRITEMASK'); 320 } 321 322 function testInvalidValues() { 323 const numDrawBuffers = gl.getParameter(gl.MAX_DRAW_BUFFERS); 324 if (!numDrawBuffers) throw new Error('!numDrawBuffers'); 325 wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.enableiOES(gl.BLEND, -1)`); 326 wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.enableiOES(gl.BLEND, ${numDrawBuffers})`); 327 wtu.shouldGenerateGLError(gl, 0, `ext.enableiOES(gl.BLEND, ${numDrawBuffers-1})`); 328 329 wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.disableiOES(gl.BLEND, -1)`); 330 wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.disableiOES(gl.BLEND, ${numDrawBuffers})`); 331 wtu.shouldGenerateGLError(gl, 0, `ext.disableiOES(gl.BLEND, ${numDrawBuffers-1})`); 332 333 wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.blendEquationiOES(-1, gl.FUNC_ADD)`); 334 wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.blendEquationiOES(${numDrawBuffers}, gl.FUNC_ADD)`); 335 wtu.shouldGenerateGLError(gl, 0, `ext.blendEquationiOES(${numDrawBuffers-1}, gl.FUNC_ADD)`); 336 337 wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.blendEquationSeparateiOES(-1, gl.FUNC_ADD, gl.FUNC_ADD)`); 338 wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.blendEquationSeparateiOES(${numDrawBuffers}, gl.FUNC_ADD, gl.FUNC_ADD)`); 339 wtu.shouldGenerateGLError(gl, 0, `ext.blendEquationSeparateiOES(${numDrawBuffers-1}, gl.FUNC_ADD, gl.FUNC_ADD)`); 340 341 wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.blendFunciOES(-1, gl.ONE, gl.ONE)`); 342 wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.blendFunciOES(${numDrawBuffers}, gl.ONE, gl.ONE)`); 343 wtu.shouldGenerateGLError(gl, 0, `ext.blendFunciOES(${numDrawBuffers-1}, gl.ONE, gl.ONE)`); 344 345 wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.blendFuncSeparateiOES(-1, gl.ONE, gl.ZERO, gl.ONE, gl.ZERO)`); 346 wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.blendFuncSeparateiOES(${numDrawBuffers}, gl.ONE, gl.ZERO, gl.ONE, gl.ZERO)`); 347 wtu.shouldGenerateGLError(gl, 0, `ext.blendFuncSeparateiOES(${numDrawBuffers-1}, gl.ONE, gl.ZERO, gl.ONE, gl.ZERO)`); 348 349 wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.colorMaskiOES(-1, 1,1,1,1)`); 350 wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.colorMaskiOES(${numDrawBuffers}, 1,1,1,1)`); 351 wtu.shouldGenerateGLError(gl, 0, `ext.colorMaskiOES(${numDrawBuffers-1}, 1,1,1,1)`); 352 } 353 354 function* range(n) { 355 for (let i = 0; i < n; i++) { 356 yield i; 357 } 358 } 359 360 function testColorMaskDrawNoOp() { 361 debug(''); 362 debug('testColorMaskDrawNoOp') 363 // > If any draw buffer with an attachment does not have a defined 364 // fragment shader output, draws generate INVALID_OPERATION, 365 // unless all 4 channels of colorMask are set to false. 366 const NUM_OUTPUTS = gl.getParameter(gl.MAX_COLOR_ATTACHMENTS); 367 shouldBeTrue(`${NUM_OUTPUTS} > 1`); 368 369 const fb = gl.createFramebuffer(); 370 gl.bindFramebuffer(gl.FRAMEBUFFER, fb); 371 gl.viewport(0,0,1,1); 372 373 const DRAW_BUFFERS = []; 374 for (const i of range(NUM_OUTPUTS)) { 375 const tex = gl.createTexture(); 376 gl.bindTexture(gl.TEXTURE_2D, tex); 377 gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, 1, 1); 378 const ca = gl.COLOR_ATTACHMENT0+i; 379 DRAW_BUFFERS.push(ca) 380 gl.framebufferTexture2D(gl.FRAMEBUFFER, ca, 381 gl.TEXTURE_2D, tex, 0); 382 } 383 shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE'); 384 385 gl.drawBuffers(DRAW_BUFFERS); 386 gl.colorMask(1, 1, 1, 1); 387 gl.disable(gl.BLEND); 388 389 gl.clearColor(0, 0, 0, 0); 390 gl.clear(gl.COLOR_BUFFER_BIT); 391 392 for (const i of range(NUM_OUTPUTS)) { 393 gl.readBuffer(gl.COLOR_ATTACHMENT0+i); 394 wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 0, 0, 0], `COLOR_ATTACHMENT${i} initially black`); 395 } 396 397 for (const validOutput of range(NUM_OUTPUTS)) { 398 const invalidOutput = validOutput ^ 0b11; 399 debug(`validOutput: ${validOutput}, invalidOutput: ${invalidOutput}`); 400 const prog = wtu.setupProgram(gl, [ 401 `\ 402 #version 300 es 403 void main() { 404 gl_Position = vec4(0,0,0,1); 405 gl_PointSize = 1.0f; 406 } 407 `, 408 `\ 409 #version 300 es 410 precision mediump float; 411 layout(location=${validOutput}) out vec4 o_color; 412 void main() { 413 o_color = vec4(1,1,1,1); 414 } 415 ` 416 ]); 417 gl.useProgram(prog); 418 419 wtu.glErrorShouldBe(gl, gl.NO_ERROR, 420 'After init.'); 421 422 gl.colorMask(1,1,1,1); 423 gl.drawBuffers(DRAW_BUFFERS); 424 gl.drawArrays(gl.POINTS, 0, 1); 425 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, 426 'Drawing with unmasked undefined color outputs.'); 427 428 gl.colorMask(0,0,0,0); 429 gl.drawBuffers(DRAW_BUFFERS); 430 gl.drawArrays(gl.POINTS, 0, 1); 431 wtu.glErrorShouldBe(gl, gl.NO_ERROR, 432 'Drawing with colorMask-masked-out undefined color outputs.'); 433 434 gl.colorMask(1,1,1,1); 435 gl.drawBuffers(DRAW_BUFFERS.map((x,i) => (i == invalidOutput) ? x : 0)); 436 gl.drawArrays(gl.POINTS, 0, 1); 437 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, 438 'Drawing with wrong-id drawBuffer-masked-out undefined color outputs.'); 439 440 gl.drawBuffers(DRAW_BUFFERS.map((x,i) => (i == validOutput) ? x : 0)); 441 gl.drawArrays(gl.POINTS, 0, 1); 442 wtu.glErrorShouldBe(gl, gl.NO_ERROR, 443 'Drawing with drawBuffer-masked-out undefined color outputs.'); 444 445 gl.colorMask(0,0,0,0); 446 gl.drawBuffers([]); 447 gl.drawArrays(gl.POINTS, 0, 1); 448 wtu.glErrorShouldBe(gl, gl.NO_ERROR, 449 'Drawing with colorMask+drawBuffer-masked-out undefined color outputs.'); 450 451 const testMask = (r,g,b,a) => { 452 debug(`testMask(${[r,g,b,a]})`); 453 gl.drawBuffers(DRAW_BUFFERS); 454 455 gl.colorMask(1,1,1,1); 456 gl.clearColor(0, 0, 0, 0); 457 gl.clear(gl.COLOR_BUFFER_BIT); 458 gl.colorMask(0,0,0,0); 459 ext.colorMaskiOES(validOutput, r,g,b,a); 460 gl.drawArrays(gl.POINTS, 0, 1); 461 wtu.glErrorShouldBe(gl, gl.NO_ERROR, 462 `Drawing with sole defined color${validOutput} output writemask: ${[r,g,b,a]}.`); 463 464 for (const i of range(NUM_OUTPUTS)) { 465 gl.readBuffer(gl.COLOR_ATTACHMENT0+i); 466 let expect = [0,0,0,0]; 467 if (i == validOutput) { 468 expect = [r,g,b,a].map(x => 0xff*x); 469 } 470 wtu.checkCanvasRect(gl, 0, 0, 1, 1, expect, `COLOR_ATTACHMENT${i}: [${expect}]`); 471 } 472 473 gl.colorMask(1,1,1,1); 474 gl.clearColor(0, 0, 0, 0); 475 gl.clear(gl.COLOR_BUFFER_BIT); 476 gl.colorMask(r,g,b,a); 477 for (const i of range(NUM_OUTPUTS)) { 478 if (i == validOutput) continue; 479 ext.colorMaskiOES(i, 0,0,0,0); 480 } 481 gl.drawArrays(gl.POINTS, 0, 1); 482 wtu.glErrorShouldBe(gl, gl.NO_ERROR, 483 `Drawing with sole remaining defined color${validOutput} output writemask: ${[r,g,b,a]}.`); 484 485 for (const i of range(NUM_OUTPUTS)) { 486 gl.readBuffer(gl.COLOR_ATTACHMENT0+i); 487 let expect = [0,0,0,0]; 488 if (i == validOutput) { 489 expect = [r,g,b,a].map(x => 0xff*x); 490 } 491 wtu.checkCanvasRect(gl, 0, 0, 1, 1, expect, `COLOR_ATTACHMENT${i}: [${expect}]`); 492 } 493 494 if (r || g || b || a) { 495 gl.colorMask(0,0,0,0); 496 ext.colorMaskiOES(invalidOutput, r,g,b,a); 497 gl.drawArrays(gl.POINTS, 0, 1); 498 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, 499 `Drawing with wrong-id undefined color output color masked: ${[r,g,b,a]}.`); 500 501 gl.drawBuffers([]); 502 gl.drawArrays(gl.POINTS, 0, 1); 503 wtu.glErrorShouldBe(gl, gl.NO_ERROR, 504 'Drawing with wrong-id colorMask, but all-off drawBuffers.'); 505 506 gl.drawBuffers(DRAW_BUFFERS.map((x,i) => (i == validOutput) ? x : 0)); 507 gl.drawArrays(gl.POINTS, 0, 1); 508 wtu.glErrorShouldBe(gl, gl.NO_ERROR, 509 'Drawing with wrong-id colorMask, but right-id drawBuffers masked.'); 510 } 511 }; 512 513 testMask(0,0,0,0); 514 testMask(1,0,0,0); 515 testMask(0,1,0,0); 516 testMask(0,0,1,0); 517 testMask(0,0,0,1); 518 testMask(1,1,1,1); 519 } 520 } 521 522 function testColorMaskAfterComposite() { 523 debug(''); 524 debug('testColorMaskAfterComposite') 525 526 const NUM_OUTPUTS = gl.getParameter(gl.MAX_COLOR_ATTACHMENTS); 527 shouldBeTrue(`${NUM_OUTPUTS} > 2`); 528 529 gl.bindFramebuffer(gl.FRAMEBUFFER, null); 530 gl.clear(gl.COLOR_BUFFER_BIT); 531 532 gl.colorMask(0, 0, 1, 0); 533 ext.colorMaskiOES(0, 1, 0, 0, 0); 534 ext.colorMaskiOES(1, 0, 1, 0, 0); 535 536 function check() { 537 gl.clear(gl.COLOR_BUFFER_BIT); 538 539 shouldBe('gl.getIndexedParameter(gl.COLOR_WRITEMASK, 0)', '[true, false, false, false]'); 540 shouldBe('gl.getIndexedParameter(gl.COLOR_WRITEMASK, 1)', '[false, true, false, false]'); 541 shouldBe('gl.getIndexedParameter(gl.COLOR_WRITEMASK, 2)', '[false, false, true, false]'); 542 finishTest(); 543 } 544 545 wtu.waitForComposite(check); 546 } 547 548 function runTest() { 549 if (!gl) { 550 testFailed("context does not exist"); 551 } else { 552 testPassed("context exists"); 553 554 runInvalidEnumsTest(); 555 556 ext = gl.getExtension("OES_draw_buffers_indexed"); 557 558 wtu.runExtensionSupportedTest(gl, "OES_draw_buffers_indexed", ext !== null); 559 560 if (ext !== null) { 561 runTestExtension(); 562 } else { 563 testPassed("No OES_draw_buffers_indexed support -- this is legal"); 564 } 565 } 566 } 567 568 runTest(); 569 570 var successfullyParsed = true; 571 </script> 572 </body> 573 </html>