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.
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>
17 <canvas width=
"20" height=
"20" style=
"border: 1px solid blue;" id=
"c"></canvas>
18 <div id=
"description"></div>
19 <div id=
"console"></div>
22 description("This test verifies the functionality of the OES_draw_buffers_indexed extension, if it is available.");
26 var wtu
= WebGLTestUtils
;
27 var gl
= wtu
.create3DContext("c", null, 2);
30 const vs
= `#version 300 es
31 layout(location=0) in vec4 vPosition;
34 gl_Position = vPosition;
38 const fs
= `#version 300 es
40 layout(location = 0) out vec4 o_color0;
41 layout(location = 1) out vec4 o_color1;
44 o_color0 = vec4(1, 0, 0, 0);
45 o_color1 = vec4(1, 0, 0, 0);
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');
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');
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');
65 const attachments
= [gl
.COLOR_ATTACHMENT0
, gl
.COLOR_ATTACHMENT1
];
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');
73 gl
.drawBuffers(attachments
);
74 wtu
.glErrorShouldBe(gl
, 0, 'Set draw buffers without errors');
77 function enableDisableTest() {
78 debug("Testing enableiOES/disableiOES");
81 ext
.enableiOES(gl
.DEPTH_TEST
, 0);
82 wtu
.glErrorShouldBe(gl
, gl
.INVALID_ENUM
, 'target could only be gl.BLEND');
84 ext
.disableiOES(gl
.DEPTH_TEST
, 0);
85 wtu
.glErrorShouldBe(gl
, gl
.INVALID_ENUM
, 'target could only be gl.BLEND');
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');
96 shouldBe('gl.isEnabled(gl.BLEND)', 'true');
97 wtu
.glErrorShouldBe(gl
, 0, 'No errors from enable and disable draw buffers blend state');
100 function constantAlphaBlendColorValidationTest() {
101 debug("Testing CONSTANT_COLOR/ALPHA blend functions limit validation");
102 function isConstantColorAndAlphaBlendFunctions(first
, second
)
104 return (first
== gl
.CONSTANT_COLOR
|| first
== gl
.ONE_MINUS_CONSTANT_COLOR
) &&
105 (second
== gl
.CONSTANT_ALPHA
|| second
== gl
.ONE_MINUS_CONSTANT_ALPHA
);
108 function checkBlendFunctions(src
, dst
)
110 if (isConstantColorAndAlphaBlendFunctions(src
, dst
) ||
111 isConstantColorAndAlphaBlendFunctions(dst
, src
))
113 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, 'invalid combinations');
118 wtu
.glErrorShouldBe(gl
, 0, 'No error');
127 gl
.ONE_MINUS_SRC_COLOR
,
129 gl
.ONE_MINUS_DST_COLOR
,
131 gl
.ONE_MINUS_SRC_ALPHA
,
133 gl
.ONE_MINUS_DST_ALPHA
,
135 gl
.ONE_MINUS_CONSTANT_COLOR
,
137 gl
.ONE_MINUS_CONSTANT_ALPHA
,
138 gl
.SRC_ALPHA_SATURATE
,
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
,
153 // CONSTANT_COLOR/ALPHA invalid combination check
154 for (let i
= 0, leni
= srcFunc
.length
; i
< leni
; i
++)
157 for (let j
= 0, lenj
= dstFunc
.length
; j
< lenj
; 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
);
168 function indexedBlendColorTest() {
170 debug("Testing blendEquationiOES and blendFunciOES");
171 wtu
.glErrorShouldBe(gl
, 0, 'top of indexedBlendColorTest');
173 gl
.clearColor(0, 0, 1, 1);
174 gl
.clear(gl
.COLOR_BUFFER_BIT
);
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');
183 gl
.readBuffer(gl
.COLOR_ATTACHMENT0
);
184 wtu
.checkCanvasRect(gl
, 0, 0, 1, 1, [255, 0, 255, 255]);
186 gl
.readBuffer(gl
.COLOR_ATTACHMENT1
);
187 wtu
.checkCanvasRect(gl
, 0, 0, 1, 1, [0, 0, 255, 255]);
189 debug("Testing blendEquationSeparateiOES and blendFuncSeparateiOES");
190 gl
.clear(gl
.COLOR_BUFFER_BIT
);
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');
199 gl
.readBuffer(gl
.COLOR_ATTACHMENT0
);
200 wtu
.checkCanvasRect(gl
, 0, 0, 1, 1, [255, 0, 255, 0]);
202 gl
.readBuffer(gl
.COLOR_ATTACHMENT1
);
203 wtu
.checkCanvasRect(gl
, 0, 0, 1, 1, [0, 0, 255, 0]);
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);
210 gl
.drawArrays(gl
.TRIANGLES
, 0, 6);
211 wtu
.glErrorShouldBe(gl
, 0, 'Draw quad without errors');
213 gl
.readBuffer(gl
.COLOR_ATTACHMENT0
);
214 wtu
.checkCanvasRect(gl
, 0, 0, 1, 1, [0, 0, 255, 255]);
216 gl
.readBuffer(gl
.COLOR_ATTACHMENT1
);
217 wtu
.checkCanvasRect(gl
, 0, 0, 1, 1, [0, 0, 255, 0]);
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');
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');
243 shouldBe('gl.getIndexedParameter(gl.COLOR_WRITEMASK, 0)', '[false, false, false, false]');
244 shouldBe('gl.getIndexedParameter(gl.COLOR_WRITEMASK, 1)', '[true, true, true, true]');
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]');
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');
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]');
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');
282 shouldBe('gl.getIndexedParameter(gl.COLOR_WRITEMASK, 0)', '[true, false, true, false]');
283 shouldBe('gl.getIndexedParameter(gl.COLOR_WRITEMASK, 1)', '[true, false, true, false]');
286 function runTestExtension() {
293 // blending should be enabled for drawBuffers 0 and 1 at this point
295 constantAlphaBlendColorValidationTest();
297 indexedBlendColorTest();
299 testColorMaskDrawNoOp();
301 testColorMaskAfterComposite();
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');
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})`);
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})`);
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)`);
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)`);
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)`);
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)`);
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)`);
355 for (let i
= 0; i
< n
; i
++) {
360 function testColorMaskDrawNoOp() {
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`);
369 const fb
= gl
.createFramebuffer();
370 gl
.bindFramebuffer(gl
.FRAMEBUFFER
, fb
);
371 gl
.viewport(0,0,1,1);
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);
383 shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE');
385 gl
.drawBuffers(DRAW_BUFFERS
);
386 gl
.colorMask(1, 1, 1, 1);
387 gl
.disable(gl
.BLEND
);
389 gl
.clearColor(0, 0, 0, 0);
390 gl
.clear(gl
.COLOR_BUFFER_BIT
);
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`);
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
, [
404 gl_Position = vec4(0,0,0,1);
410 precision mediump float;
411 layout(location=${validOutput}) out vec4 o_color;
413 o_color = vec4(1,1,1,1);
419 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
,
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.');
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.');
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.');
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.');
445 gl
.colorMask(0,0,0,0);
447 gl
.drawArrays(gl
.POINTS
, 0, 1);
448 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
,
449 'Drawing with colorMask+drawBuffer-masked-out undefined color outputs.');
451 const testMask
= (r
,g
,b
,a
) => {
452 debug(`testMask(${[r,g,b,a]})`);
453 gl
.drawBuffers(DRAW_BUFFERS
);
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]}.`);
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
);
470 wtu
.checkCanvasRect(gl
, 0, 0, 1, 1, expect
, `COLOR_ATTACHMENT${i}: [${expect}]`);
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);
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]}.`);
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
);
491 wtu
.checkCanvasRect(gl
, 0, 0, 1, 1, expect
, `COLOR_ATTACHMENT${i}: [${expect}]`);
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]}.`);
502 gl
.drawArrays(gl
.POINTS
, 0, 1);
503 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
,
504 'Drawing with wrong-id colorMask, but all-off drawBuffers.');
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.');
522 function testColorMaskAfterComposite() {
524 debug('testColorMaskAfterComposite')
526 const NUM_OUTPUTS
= gl
.getParameter(gl
.MAX_COLOR_ATTACHMENTS
);
527 shouldBeTrue(`${NUM_OUTPUTS} > 2`);
529 gl
.bindFramebuffer(gl
.FRAMEBUFFER
, null);
530 gl
.clear(gl
.COLOR_BUFFER_BIT
);
532 gl
.colorMask(0, 0, 1, 0);
533 ext
.colorMaskiOES(0, 1, 0, 0, 0);
534 ext
.colorMaskiOES(1, 0, 1, 0, 0);
537 gl
.clear(gl
.COLOR_BUFFER_BIT
);
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]');
545 wtu
.waitForComposite(check
);
550 testFailed("context does not exist");
552 testPassed("context exists");
554 runInvalidEnumsTest();
556 ext
= gl
.getExtension("OES_draw_buffers_indexed");
558 wtu
.runExtensionSupportedTest(gl
, "OES_draw_buffers_indexed", ext
!== null);
563 testPassed("No OES_draw_buffers_indexed support -- this is legal");
570 var successfullyParsed
= true;