Source code

Revision control

Copy as Markdown

Other Tools

<!--
Copyright (c) 2020 The Khronos Group Inc.
Use of this source code is governed by an MIT-style license that can be
found in the LICENSE.txt file.
-->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>WebGL OES_draw_buffers_indexed Conformance Tests</title>
<LINK rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../js/js-test-pre.js"></script>
<script src="../../js/webgl-test-utils.js"></script>
</head>
<body>
<canvas width="20" height="20" style="border: 1px solid blue;" id="c"></canvas>
<div id="description"></div>
<div id="console"></div>
<script>
"use strict";
description("This test verifies the functionality of the OES_draw_buffers_indexed extension, if it is available.");
debug("");
var wtu = WebGLTestUtils;
var gl = wtu.create3DContext("c", null, 2);
var ext;
const vs = `#version 300 es
layout(location=0) in vec4 vPosition;
void main()
{
gl_Position = vPosition;
}
`;
const fs = `#version 300 es
precision lowp float;
layout(location = 0) out vec4 o_color0;
layout(location = 1) out vec4 o_color1;
void main()
{
o_color0 = vec4(1, 0, 0, 0);
o_color1 = vec4(1, 0, 0, 0);
}
`;
function setup() {
const program = wtu.setupProgram(gl, [vs, fs]);
gl.useProgram(program);
wtu.setupUnitQuad(gl, 0);
wtu.glErrorShouldBe(gl, 0, 'No errors from program');
const tex1 = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex1);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
wtu.glErrorShouldBe(gl, 0, 'Create texture 1 successfully');
const tex2 = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex2);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
wtu.glErrorShouldBe(gl, 0, 'Create texture 2 successfully');
const attachments = [gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1];
const fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
gl.framebufferTexture2D(gl.FRAMEBUFFER, attachments[0], gl.TEXTURE_2D, tex1, 0);
gl.framebufferTexture2D(gl.FRAMEBUFFER, attachments[1], gl.TEXTURE_2D, tex2, 0);
shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
gl.drawBuffers(attachments);
wtu.glErrorShouldBe(gl, 0, 'Set draw buffers without errors');
}
function enableDisableTest() {
debug("Testing enableiOES/disableiOES");
// Invalid input
ext.enableiOES(gl.DEPTH_TEST, 0);
wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, 'target could only be gl.BLEND');
ext.disableiOES(gl.DEPTH_TEST, 0);
wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, 'target could only be gl.BLEND');
gl.disable(gl.BLEND);
// Valid input
ext.enableiOES(gl.BLEND, 0);
shouldBe('gl.isEnabled(gl.BLEND)', 'true');
ext.disableiOES(gl.BLEND, 0);
ext.enableiOES(gl.BLEND, 1);
shouldBe('gl.isEnabled(gl.BLEND)', 'false');
gl.enable(gl.BLEND);
shouldBe('gl.isEnabled(gl.BLEND)', 'true');
wtu.glErrorShouldBe(gl, 0, 'No errors from enable and disable draw buffers blend state');
}
function constantAlphaBlendColorValidationTest() {
debug("Testing CONSTANT_COLOR/ALPHA blend functions limit validation");
function isConstantColorAndAlphaBlendFunctions(first, second)
{
return (first == gl.CONSTANT_COLOR || first == gl.ONE_MINUS_CONSTANT_COLOR) &&
(second == gl.CONSTANT_ALPHA || second == gl.ONE_MINUS_CONSTANT_ALPHA);
}
function checkBlendFunctions(src, dst)
{
if (isConstantColorAndAlphaBlendFunctions(src, dst) ||
isConstantColorAndAlphaBlendFunctions(dst, src))
{
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, 'invalid combinations');
return false;
}
else
{
wtu.glErrorShouldBe(gl, 0, 'No error');
return true;
}
}
const srcFunc = [
gl.ZERO,
gl.ONE,
gl.SRC_COLOR,
gl.ONE_MINUS_SRC_COLOR,
gl.DST_COLOR,
gl.ONE_MINUS_DST_COLOR,
gl.SRC_ALPHA,
gl.ONE_MINUS_SRC_ALPHA,
gl.DST_ALPHA,
gl.ONE_MINUS_DST_ALPHA,
gl.CONSTANT_COLOR,
gl.ONE_MINUS_CONSTANT_COLOR,
gl.CONSTANT_ALPHA,
gl.ONE_MINUS_CONSTANT_ALPHA,
gl.SRC_ALPHA_SATURATE,
];
const dstFunc = [
gl.ZERO, gl.ONE,
gl.SRC_COLOR, gl.ONE_MINUS_SRC_COLOR,
gl.DST_COLOR, gl.ONE_MINUS_DST_COLOR,
gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA,
gl.DST_ALPHA, gl.ONE_MINUS_DST_ALPHA,
gl.CONSTANT_COLOR, gl.ONE_MINUS_CONSTANT_COLOR,
gl.CONSTANT_ALPHA, gl.ONE_MINUS_CONSTANT_ALPHA,
];
let src, dst;
// CONSTANT_COLOR/ALPHA invalid combination check
for (let i = 0, leni = srcFunc.length; i < leni; i++)
{
src = srcFunc[i];
for (let j = 0, lenj = dstFunc.length; j < lenj; j++)
{
dst = dstFunc[j];
ext.blendFunciOES(0, src, dst);
checkBlendFunctions(src, dst);
ext.blendFuncSeparateiOES(0, src, dst, gl.ONE, gl.ONE);
checkBlendFunctions(src, dst);
}
}
}
function indexedBlendColorTest() {
debug('');
debug("Testing blendEquationiOES and blendFunciOES");
wtu.glErrorShouldBe(gl, 0, 'top of indexedBlendColorTest');
gl.clearColor(0, 0, 1, 1);
gl.clear(gl.COLOR_BUFFER_BIT);
ext.blendEquationiOES(0, gl.FUNC_ADD);
ext.blendFunciOES(0, gl.ONE, gl.ONE);
ext.blendEquationiOES(1, gl.FUNC_ADD);
ext.blendFunciOES(1, gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
gl.drawArrays(gl.TRIANGLES, 0, 6);
wtu.glErrorShouldBe(gl, 0, 'Draw quad without errors');
gl.readBuffer(gl.COLOR_ATTACHMENT0);
wtu.checkCanvasRect(gl, 0, 0, 1, 1, [255, 0, 255, 255]);
gl.readBuffer(gl.COLOR_ATTACHMENT1);
wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 0, 255, 255]);
debug("Testing blendEquationSeparateiOES and blendFuncSeparateiOES");
gl.clear(gl.COLOR_BUFFER_BIT);
ext.blendEquationSeparateiOES(0, gl.FUNC_ADD, gl.FUNC_SUBTRACT);
ext.blendFuncSeparateiOES(0, gl.ONE, gl.ONE, gl.ZERO, gl.ZERO);
ext.blendEquationSeparateiOES(1, gl.FUNC_ADD, gl.FUNC_SUBTRACT);
ext.blendFuncSeparateiOES(1, gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ZERO, gl.ZERO);
gl.drawArrays(gl.TRIANGLES, 0, 6);
wtu.glErrorShouldBe(gl, 0, 'Draw quad without errors');
gl.readBuffer(gl.COLOR_ATTACHMENT0);
wtu.checkCanvasRect(gl, 0, 0, 1, 1, [255, 0, 255, 0]);
gl.readBuffer(gl.COLOR_ATTACHMENT1);
wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 0, 255, 0]);
debug("Testing colorMaskiOES");
gl.clear(gl.COLOR_BUFFER_BIT);
ext.colorMaskiOES(0, false, false, false, false);
ext.colorMaskiOES(1, true, true, true, true);
gl.drawArrays(gl.TRIANGLES, 0, 6);
wtu.glErrorShouldBe(gl, 0, 'Draw quad without errors');
gl.readBuffer(gl.COLOR_ATTACHMENT0);
wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 0, 255, 255]);
gl.readBuffer(gl.COLOR_ATTACHMENT1);
wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 0, 255, 0]);
debug('');
debug(`Testing that new tokens aren't on the extension.`);
shouldBe('ext.BLEND_EQUATION_RGB', 'undefined');
shouldBe('ext.BLEND_EQUATION_ALPHA', 'undefined');
shouldBe('ext.BLEND_SRC_RGB', 'undefined');
shouldBe('ext.BLEND_SRC_ALPHA', 'undefined');
shouldBe('ext.BLEND_DST_RGB', 'undefined');
shouldBe('ext.BLEND_DST_ALPHA', 'undefined');
shouldBe('ext.COLOR_WRITEMASK', 'undefined');
debug("Testing new tokens for getIndexedParameterTest");
shouldBe('gl.getIndexedParameter(gl.BLEND_EQUATION_RGB, 0)', 'gl.FUNC_ADD');
shouldBe('gl.getIndexedParameter(gl.BLEND_EQUATION_ALPHA, 0)', 'gl.FUNC_SUBTRACT');
shouldBe('gl.getIndexedParameter(gl.BLEND_SRC_RGB, 0)', 'gl.ONE');
shouldBe('gl.getIndexedParameter(gl.BLEND_DST_RGB, 0)', 'gl.ONE');
shouldBe('gl.getIndexedParameter(gl.BLEND_SRC_ALPHA, 0)', 'gl.ZERO');
shouldBe('gl.getIndexedParameter(gl.BLEND_DST_ALPHA, 0)', 'gl.ZERO');
shouldBe('gl.getIndexedParameter(gl.BLEND_EQUATION_RGB, 1)', 'gl.FUNC_ADD');
shouldBe('gl.getIndexedParameter(gl.BLEND_EQUATION_ALPHA, 1)', 'gl.FUNC_SUBTRACT');
shouldBe('gl.getIndexedParameter(gl.BLEND_SRC_RGB, 1)', 'gl.SRC_ALPHA');
shouldBe('gl.getIndexedParameter(gl.BLEND_DST_RGB, 1)', 'gl.ONE_MINUS_SRC_ALPHA');
shouldBe('gl.getIndexedParameter(gl.BLEND_SRC_ALPHA, 1)', 'gl.ZERO');
shouldBe('gl.getIndexedParameter(gl.BLEND_DST_ALPHA, 1)', 'gl.ZERO');
shouldBe('gl.getIndexedParameter(gl.COLOR_WRITEMASK, 0)', '[false, false, false, false]');
shouldBe('gl.getIndexedParameter(gl.COLOR_WRITEMASK, 1)', '[true, true, true, true]');
debug("Testing non-indexed getParamter get state from draw buffer 0");
shouldBe('gl.getParameter(gl.BLEND_SRC_RGB)', 'gl.ONE');
shouldBe('gl.getParameter(gl.BLEND_DST_RGB)', 'gl.ONE');
shouldBe('gl.getParameter(gl.BLEND_SRC_ALPHA)', 'gl.ZERO');
shouldBe('gl.getParameter(gl.BLEND_DST_ALPHA)', 'gl.ZERO');
shouldBe('gl.getParameter(gl.BLEND_EQUATION_RGB)', 'gl.FUNC_ADD');
shouldBe('gl.getParameter(gl.BLEND_EQUATION_ALPHA)', 'gl.FUNC_SUBTRACT');
shouldBe('gl.getParameter(gl.COLOR_WRITEMASK)', '[false, false, false, false]');
debug("Testing non-indexed calls modify all draw buffers state");
gl.blendEquationSeparate(gl.FUNC_SUBTRACT, gl.FUNC_ADD);
gl.blendFuncSeparate(gl.ONE_MINUS_DST_ALPHA, gl.DST_ALPHA, gl.ONE, gl.ONE);
gl.colorMask(true, false, true, false);
wtu.glErrorShouldBe(gl, 0, 'Non-indexed state set without errors');
shouldBe('gl.getParameter(gl.BLEND_EQUATION_RGB)', 'gl.FUNC_SUBTRACT');
shouldBe('gl.getParameter(gl.BLEND_EQUATION_ALPHA)', 'gl.FUNC_ADD');
shouldBe('gl.getParameter(gl.BLEND_SRC_RGB)', 'gl.ONE_MINUS_DST_ALPHA');
shouldBe('gl.getParameter(gl.BLEND_DST_RGB)', 'gl.DST_ALPHA');
shouldBe('gl.getParameter(gl.BLEND_SRC_ALPHA)', 'gl.ONE');
shouldBe('gl.getParameter(gl.BLEND_DST_ALPHA)', 'gl.ONE');
shouldBe('gl.getParameter(gl.COLOR_WRITEMASK)', '[true, false, true, false]');
shouldBe('gl.getIndexedParameter(gl.BLEND_EQUATION_RGB, 0)', 'gl.FUNC_SUBTRACT');
shouldBe('gl.getIndexedParameter(gl.BLEND_EQUATION_ALPHA, 0)', 'gl.FUNC_ADD');
shouldBe('gl.getIndexedParameter(gl.BLEND_SRC_RGB, 0)', 'gl.ONE_MINUS_DST_ALPHA');
shouldBe('gl.getIndexedParameter(gl.BLEND_DST_RGB, 0)', 'gl.DST_ALPHA');
shouldBe('gl.getIndexedParameter(gl.BLEND_SRC_ALPHA, 0)', 'gl.ONE');
shouldBe('gl.getIndexedParameter(gl.BLEND_DST_ALPHA, 0)', 'gl.ONE');
shouldBe('gl.getIndexedParameter(gl.BLEND_EQUATION_RGB, 1)', 'gl.FUNC_SUBTRACT');
shouldBe('gl.getIndexedParameter(gl.BLEND_EQUATION_ALPHA, 1)', 'gl.FUNC_ADD');
shouldBe('gl.getIndexedParameter(gl.BLEND_SRC_RGB, 1)', 'gl.ONE_MINUS_DST_ALPHA');
shouldBe('gl.getIndexedParameter(gl.BLEND_DST_RGB, 1)', 'gl.DST_ALPHA');
shouldBe('gl.getIndexedParameter(gl.BLEND_SRC_ALPHA, 1)', 'gl.ONE');
shouldBe('gl.getIndexedParameter(gl.BLEND_DST_ALPHA, 1)', 'gl.ONE');
shouldBe('gl.getIndexedParameter(gl.COLOR_WRITEMASK, 0)', '[true, false, true, false]');
shouldBe('gl.getIndexedParameter(gl.COLOR_WRITEMASK, 1)', '[true, false, true, false]');
}
function runTestExtension() {
setup();
testInvalidValues();
enableDisableTest();
// blending should be enabled for drawBuffers 0 and 1 at this point
constantAlphaBlendColorValidationTest();
indexedBlendColorTest();
testColorMaskDrawNoOp();
testColorMaskAfterComposite();
}
function runInvalidEnumsTest() {
debug("Testing new enums for getIndexedParameterTest being invalid before requesting the extension");
shouldBeNull("gl.getIndexedParameter(0x8009, 0)"); // BLEND_EQUATION_RGB
wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, 'BLEND_EQUATION_RGB');
shouldBeNull("gl.getIndexedParameter(0x883D, 0)"); // BLEND_EQUATION_ALPHA
wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, 'BLEND_EQUATION_ALPHA');
shouldBeNull("gl.getIndexedParameter(0x80C9, 0)"); // BLEND_SRC_RGB
wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, 'BLEND_SRC_RGB');
shouldBeNull("gl.getIndexedParameter(0x80CB, 0)"); // BLEND_SRC_ALPHA
wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, 'BLEND_SRC_ALPHA');
shouldBeNull("gl.getIndexedParameter(0x80C8, 0)"); // BLEND_DST_RGB
wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, 'BLEND_DST_RGB');
shouldBeNull("gl.getIndexedParameter(0x80CA, 0)"); // BLEND_DST_ALPHA
wtu.glErrorShouldBe(gl, gl.INVALID_ENUM, 'BLEND_DST_ALPHA');
shouldBeNull("gl.getIndexedParameter(0x0C23, 0)"); // COLOR_WRITEMASK
wtu.glErrorShouldBe(gl, [gl.INVALID_OPERATION, gl.INVALID_ENUM], 'invalid operations or invalid enums for COLOR_WRITEMASK');
}
function testInvalidValues() {
const numDrawBuffers = gl.getParameter(gl.MAX_DRAW_BUFFERS);
if (!numDrawBuffers) throw new Error('!numDrawBuffers');
wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.enableiOES(gl.BLEND, -1)`);
wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.enableiOES(gl.BLEND, ${numDrawBuffers})`);
wtu.shouldGenerateGLError(gl, 0, `ext.enableiOES(gl.BLEND, ${numDrawBuffers-1})`);
wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.disableiOES(gl.BLEND, -1)`);
wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.disableiOES(gl.BLEND, ${numDrawBuffers})`);
wtu.shouldGenerateGLError(gl, 0, `ext.disableiOES(gl.BLEND, ${numDrawBuffers-1})`);
wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.blendEquationiOES(-1, gl.FUNC_ADD)`);
wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.blendEquationiOES(${numDrawBuffers}, gl.FUNC_ADD)`);
wtu.shouldGenerateGLError(gl, 0, `ext.blendEquationiOES(${numDrawBuffers-1}, gl.FUNC_ADD)`);
wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.blendEquationSeparateiOES(-1, gl.FUNC_ADD, gl.FUNC_ADD)`);
wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.blendEquationSeparateiOES(${numDrawBuffers}, gl.FUNC_ADD, gl.FUNC_ADD)`);
wtu.shouldGenerateGLError(gl, 0, `ext.blendEquationSeparateiOES(${numDrawBuffers-1}, gl.FUNC_ADD, gl.FUNC_ADD)`);
wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.blendFunciOES(-1, gl.ONE, gl.ONE)`);
wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.blendFunciOES(${numDrawBuffers}, gl.ONE, gl.ONE)`);
wtu.shouldGenerateGLError(gl, 0, `ext.blendFunciOES(${numDrawBuffers-1}, gl.ONE, gl.ONE)`);
wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.blendFuncSeparateiOES(-1, gl.ONE, gl.ZERO, gl.ONE, gl.ZERO)`);
wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.blendFuncSeparateiOES(${numDrawBuffers}, gl.ONE, gl.ZERO, gl.ONE, gl.ZERO)`);
wtu.shouldGenerateGLError(gl, 0, `ext.blendFuncSeparateiOES(${numDrawBuffers-1}, gl.ONE, gl.ZERO, gl.ONE, gl.ZERO)`);
wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.colorMaskiOES(-1, 1,1,1,1)`);
wtu.shouldGenerateGLError(gl, gl.INVALID_VALUE, `ext.colorMaskiOES(${numDrawBuffers}, 1,1,1,1)`);
wtu.shouldGenerateGLError(gl, 0, `ext.colorMaskiOES(${numDrawBuffers-1}, 1,1,1,1)`);
}
function* range(n) {
for (let i = 0; i < n; i++) {
yield i;
}
}
function testColorMaskDrawNoOp() {
debug('');
debug('testColorMaskDrawNoOp')
// > If any draw buffer with an attachment does not have a defined
// fragment shader output, draws generate INVALID_OPERATION,
// unless all 4 channels of colorMask are set to false.
const NUM_OUTPUTS = gl.getParameter(gl.MAX_COLOR_ATTACHMENTS);
shouldBeTrue(`${NUM_OUTPUTS} > 1`);
const fb = gl.createFramebuffer();
gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
gl.viewport(0,0,1,1);
const DRAW_BUFFERS = [];
for (const i of range(NUM_OUTPUTS)) {
const tex = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, tex);
gl.texStorage2D(gl.TEXTURE_2D, 1, gl.RGBA8, 1, 1);
const ca = gl.COLOR_ATTACHMENT0+i;
DRAW_BUFFERS.push(ca)
gl.framebufferTexture2D(gl.FRAMEBUFFER, ca,
gl.TEXTURE_2D, tex, 0);
}
shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
gl.drawBuffers(DRAW_BUFFERS);
gl.colorMask(1, 1, 1, 1);
gl.disable(gl.BLEND);
gl.clearColor(0, 0, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
for (const i of range(NUM_OUTPUTS)) {
gl.readBuffer(gl.COLOR_ATTACHMENT0+i);
wtu.checkCanvasRect(gl, 0, 0, 1, 1, [0, 0, 0, 0], `COLOR_ATTACHMENT${i} initially black`);
}
for (const validOutput of range(NUM_OUTPUTS)) {
const invalidOutput = validOutput ^ 0b11;
debug(`validOutput: ${validOutput}, invalidOutput: ${invalidOutput}`);
const prog = wtu.setupProgram(gl, [
`\
#version 300 es
void main() {
gl_Position = vec4(0,0,0,1);
gl_PointSize = 1.0f;
}
`,
`\
#version 300 es
precision mediump float;
layout(location=${validOutput}) out vec4 o_color;
void main() {
o_color = vec4(1,1,1,1);
}
`
]);
gl.useProgram(prog);
wtu.glErrorShouldBe(gl, gl.NO_ERROR,
'After init.');
gl.colorMask(1,1,1,1);
gl.drawBuffers(DRAW_BUFFERS);
gl.drawArrays(gl.POINTS, 0, 1);
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
'Drawing with unmasked undefined color outputs.');
gl.colorMask(0,0,0,0);
gl.drawBuffers(DRAW_BUFFERS);
gl.drawArrays(gl.POINTS, 0, 1);
wtu.glErrorShouldBe(gl, gl.NO_ERROR,
'Drawing with colorMask-masked-out undefined color outputs.');
gl.colorMask(1,1,1,1);
gl.drawBuffers(DRAW_BUFFERS.map((x,i) => (i == invalidOutput) ? x : 0));
gl.drawArrays(gl.POINTS, 0, 1);
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
'Drawing with wrong-id drawBuffer-masked-out undefined color outputs.');
gl.drawBuffers(DRAW_BUFFERS.map((x,i) => (i == validOutput) ? x : 0));
gl.drawArrays(gl.POINTS, 0, 1);
wtu.glErrorShouldBe(gl, gl.NO_ERROR,
'Drawing with drawBuffer-masked-out undefined color outputs.');
gl.colorMask(0,0,0,0);
gl.drawBuffers([]);
gl.drawArrays(gl.POINTS, 0, 1);
wtu.glErrorShouldBe(gl, gl.NO_ERROR,
'Drawing with colorMask+drawBuffer-masked-out undefined color outputs.');
const testMask = (r,g,b,a) => {
debug(`testMask(${[r,g,b,a]})`);
gl.drawBuffers(DRAW_BUFFERS);
gl.colorMask(1,1,1,1);
gl.clearColor(0, 0, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.colorMask(0,0,0,0);
ext.colorMaskiOES(validOutput, r,g,b,a);
gl.drawArrays(gl.POINTS, 0, 1);
wtu.glErrorShouldBe(gl, gl.NO_ERROR,
`Drawing with sole defined color${validOutput} output writemask: ${[r,g,b,a]}.`);
for (const i of range(NUM_OUTPUTS)) {
gl.readBuffer(gl.COLOR_ATTACHMENT0+i);
let expect = [0,0,0,0];
if (i == validOutput) {
expect = [r,g,b,a].map(x => 0xff*x);
}
wtu.checkCanvasRect(gl, 0, 0, 1, 1, expect, `COLOR_ATTACHMENT${i}: [${expect}]`);
}
gl.colorMask(1,1,1,1);
gl.clearColor(0, 0, 0, 0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.colorMask(r,g,b,a);
for (const i of range(NUM_OUTPUTS)) {
if (i == validOutput) continue;
ext.colorMaskiOES(i, 0,0,0,0);
}
gl.drawArrays(gl.POINTS, 0, 1);
wtu.glErrorShouldBe(gl, gl.NO_ERROR,
`Drawing with sole remaining defined color${validOutput} output writemask: ${[r,g,b,a]}.`);
for (const i of range(NUM_OUTPUTS)) {
gl.readBuffer(gl.COLOR_ATTACHMENT0+i);
let expect = [0,0,0,0];
if (i == validOutput) {
expect = [r,g,b,a].map(x => 0xff*x);
}
wtu.checkCanvasRect(gl, 0, 0, 1, 1, expect, `COLOR_ATTACHMENT${i}: [${expect}]`);
}
if (r || g || b || a) {
gl.colorMask(0,0,0,0);
ext.colorMaskiOES(invalidOutput, r,g,b,a);
gl.drawArrays(gl.POINTS, 0, 1);
wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION,
`Drawing with wrong-id undefined color output color masked: ${[r,g,b,a]}.`);
gl.drawBuffers([]);
gl.drawArrays(gl.POINTS, 0, 1);
wtu.glErrorShouldBe(gl, gl.NO_ERROR,
'Drawing with wrong-id colorMask, but all-off drawBuffers.');
gl.drawBuffers(DRAW_BUFFERS.map((x,i) => (i == validOutput) ? x : 0));
gl.drawArrays(gl.POINTS, 0, 1);
wtu.glErrorShouldBe(gl, gl.NO_ERROR,
'Drawing with wrong-id colorMask, but right-id drawBuffers masked.');
}
};
testMask(0,0,0,0);
testMask(1,0,0,0);
testMask(0,1,0,0);
testMask(0,0,1,0);
testMask(0,0,0,1);
testMask(1,1,1,1);
}
}
function testColorMaskAfterComposite() {
debug('');
debug('testColorMaskAfterComposite')
const NUM_OUTPUTS = gl.getParameter(gl.MAX_COLOR_ATTACHMENTS);
shouldBeTrue(`${NUM_OUTPUTS} > 2`);
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.colorMask(0, 0, 1, 0);
ext.colorMaskiOES(0, 1, 0, 0, 0);
ext.colorMaskiOES(1, 0, 1, 0, 0);
function check() {
gl.clear(gl.COLOR_BUFFER_BIT);
shouldBe('gl.getIndexedParameter(gl.COLOR_WRITEMASK, 0)', '[true, false, false, false]');
shouldBe('gl.getIndexedParameter(gl.COLOR_WRITEMASK, 1)', '[false, true, false, false]');
shouldBe('gl.getIndexedParameter(gl.COLOR_WRITEMASK, 2)', '[false, false, true, false]');
finishTest();
}
wtu.waitForComposite(check);
}
function runTest() {
if (!gl) {
testFailed("context does not exist");
} else {
testPassed("context exists");
runInvalidEnumsTest();
ext = gl.getExtension("OES_draw_buffers_indexed");
wtu.runExtensionSupportedTest(gl, "OES_draw_buffers_indexed", ext !== null);
if (ext !== null) {
runTestExtension();
} else {
testPassed("No OES_draw_buffers_indexed support -- this is legal");
}
}
}
runTest();
var successfullyParsed = true;
</script>
</body>
</html>