tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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>