2 Copyright (c) 2019 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 <link rel=
"stylesheet" href=
"../../resources/js-test-style.css"/>
12 <script src=
"../../js/js-test-pre.js"></script>
13 <script src=
"../../js/webgl-test-utils.js"></script>
15 <script id=
"eVsSrc" type=
"text/plain">
19 gl_Position = vec4(
0,
0,
0,
1);
23 <script id=
"eFsSrc" type=
"text/plain">
24 precision mediump float;
29 gl_FragColor = uColor;
35 <div id=
"description"></div>
36 <div id=
"console"></div>
39 description('Blending tests');
41 const wtu
= WebGLTestUtils
;
43 function CreateContext() {
44 const gl
= wtu
.create3DContext();
45 gl
.viewport(0, 0, 1, 1);
47 gl
.prog
= wtu
.setupProgram(gl
, [eVsSrc
.innerHTML
, eFsSrc
.innerHTML
]);
48 gl
.prog
.uColor
= (() => {
49 const loc
= gl
.getUniformLocation(gl
.prog
, 'uColor');
50 return x
=> gl
.uniform4fv(loc
, x
);
52 gl
.useProgram(gl
.prog
);
53 gl
.prog
.uColor([1 / 255, 2 / 255, 3 / 255, 4 / 255]);
55 gl
.drawAndRead
= type
=> {
56 gl
.drawArrays(gl
.POINTS
, 0, 1);
58 if (type
== gl
.UNSIGNED_BYTE
) {
59 ret
= new Uint8Array(4);
60 } else if (type
== gl
.FLOAT
) {
61 ret
= new Float32Array(4);
63 gl
.readPixels(0, 0, 1, 1, gl
.RGBA
, type
, ret
);
68 gl
.blendFunc(gl
.CONSTANT_COLOR
, gl
.ZERO
);
73 function CreateValidFb(gl
, formats
) {
74 const fb
= gl
.createFramebuffer();
75 gl
.bindFramebuffer(gl
.FRAMEBUFFER
, fb
);
77 for (let i
in formats
) {
78 i
= i
|0; // Otherwise i is a string. :(
83 const rb
= gl
.createRenderbuffer();
84 gl
.bindRenderbuffer(gl
.RENDERBUFFER
, rb
);
85 gl
.renderbufferStorage(gl
.RENDERBUFFER
, f
[0], 1, 1);
86 gl
.framebufferRenderbuffer(gl
.FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
+i
,
91 let internalFormat
= f
[0];
92 if (internalFormat
=== undefined) {
93 internalFormat
= f
[1];
96 const tex
= gl
.createTexture();
97 gl
.bindTexture(gl
.TEXTURE_2D
, tex
);
98 gl
.texImage2D(gl
.TEXTURE_2D
, 0, internalFormat
, 1,1,0, f
[1],f
[2], null);
99 gl
.framebufferTexture2D(gl
.FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
+i
,
100 gl
.TEXTURE_2D
, tex
, 0);
103 throw new Error('Invalid format length: ' + f
);
106 const status
= gl
.checkFramebufferStatus(gl
.FRAMEBUFFER
);
107 if (status
!= gl
.FRAMEBUFFER_COMPLETE
) {
108 gl
.deleteFramebuffer(fb
);
119 debug('Clamping of blendColor args:');
121 const gl
= wtu
.create3DContext();
122 if (!gl
.texImage3D
) { // WebGL 1.0
123 // WebGL 1.0 clamps without EXT_color_buffer_half_float or WEBGL_color_buffer_float.
124 gl
.blendColor(1000, 1, 1, 1);
125 const was
= gl
.getParameter(gl
.BLEND_COLOR
);
126 expectArray(was
, [1, 1, 1, 1]);
128 const ext
= gl
.getExtension('EXT_color_buffer_half_float') ||
129 gl
.getExtension('WEBGL_color_buffer_float');
133 // WebGL 2.0 or extended WebGL 1.0 may still clamp the value on store
134 // when the underlying platform does the same.
135 gl
.blendColor(1000, 1, 1, 1);
136 const was
= gl
.getParameter(gl
.BLEND_COLOR
);
137 if (was
[0] == 1000) {
138 expectArray(was
, [1000, 1, 1, 1]);
140 debug("Platform does not support unclamped blend color.")
141 expectArray(was
, [1, 1, 1, 1]);
146 debug('Blending for RGBA8:');
148 const gl
= CreateContext();
149 fb
= CreateValidFb(gl
, [[gl
.RGBA8
, gl
.RGBA
, gl
.UNSIGNED_BYTE
]]);
150 shouldBeNonNull('fb');
152 // Regardless of the context version and enabled extensions,
153 // the value will be clamped at draw time,
154 gl
.blendColor(10, 1, 1, 1);
155 const was
= gl
.drawAndRead(gl
.UNSIGNED_BYTE
);
156 expectArray(was
, [1, 2, 3, 4]);
158 if (gl
.getExtension('EXT_color_buffer_half_float') ||
159 gl
.getExtension('WEBGL_color_buffer_float') ||
160 gl
.getExtension('EXT_color_buffer_float'))
162 debug('Enable floating-point color buffers and retest');
163 gl
.blendColor(1000, 1, 1, 1);
164 const was
= gl
.drawAndRead(gl
.UNSIGNED_BYTE
);
165 expectArray(was
, [1, 2, 3, 4]);
170 debug('Blending for RGBA16F:');
172 const gl
= CreateContext();
174 // Set the value before enabling the extension.
175 // It must be clamped only on WebGL 1.0 contexts.
176 gl
.blendColor(10, 1, 1, 1);
177 if (!gl
.getExtension('EXT_color_buffer_half_float')) {
178 testPassed('Missing ext EXT_color_buffer_half_float is optional, skipping.');
181 if (!gl
.texImage3D
) { // WebGL 1.0
182 const ext
= gl
.getExtension('OES_texture_half_float');
183 gl
.HALF_FLOAT
= ext
.HALF_FLOAT_OES
; // These aren't the same value, but this'll work.
186 fb
= CreateValidFb(gl
, [[gl
.RGBA16F
, gl
.RGBA
, gl
.HALF_FLOAT
]]);
187 shouldBeNonNull('fb');
188 gl
.prog
.uColor([1, 2, 3, 4]);
190 let was
= gl
.drawAndRead(gl
.FLOAT
);
191 if (!gl
.texImage3D
) { // WebGL 1.0
192 expectArray(was
, [1, 2, 3, 4]);
194 // Some WebGL 2.0 implementations may clamp the blend color anyway.
195 const r
= gl
.getParameter(gl
.BLEND_COLOR
)[0];
196 expectArray(was
, [r
, 2, 3, 4]);
199 // Re-set the value after the extension was enabled.
200 gl
.blendColor(100, 1, 1, 1);
201 const r
= gl
.getParameter(gl
.BLEND_COLOR
)[0];
202 was
= gl
.drawAndRead(gl
.FLOAT
);
203 expectArray(was
, [r
, 2, 3, 4]);
207 debug('Blending for RGBA32F:');
209 const gl
= CreateContext();
211 // Set the value before enabling the extension.
212 // It must be clamped only on WebGL 1.0 contexts.
213 gl
.blendColor(10, 1, 1, 1);
214 if (gl
.texImage3D
) { // WebGL 2.0
215 if (!gl
.getExtension('EXT_color_buffer_float')) {
216 testPassed('Missing ext EXT_color_buffer_float is optional, skipping.');
220 if (!gl
.getExtension('WEBGL_color_buffer_float')) {
221 testPassed('Missing ext WEBGL_color_buffer_float is optional, skipping.');
224 gl
.getExtension('OES_texture_float');
226 fb
= CreateValidFb(gl
, [[gl
.RGBA32F
, gl
.RGBA
, gl
.FLOAT
]]);
227 shouldBeNonNull('fb');
228 gl
.prog
.uColor([1, 2, 3, 4]);
230 let was
= gl
.drawAndRead(gl
.FLOAT
);
231 if (!gl
.texImage3D
) { // WebGL 1.0
232 expectArray(was
, [1, 2, 3, 4]);
234 // Some WebGL 2.0 implementations may clamp the blend color anyway.
235 const r
= gl
.getParameter(gl
.BLEND_COLOR
)[0];
236 expectArray(was
, [r
, 2, 3, 4]);
239 // Re-set the value after the extension was enabled.
240 gl
.blendColor(100, 1, 1, 1);
241 const r
= gl
.getParameter(gl
.BLEND_COLOR
)[0];
242 was
= gl
.drawAndRead(gl
.FLOAT
);
244 if (!gl
.getExtension('EXT_float_blend')) {
245 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, 'Should not be able to blend 32F formats.');
248 wtu
.glErrorShouldBe(gl
, 0, 'Should be able to blend 32F formats.');
249 expectArray(was
, [r
, 2, 3, 4]);
253 async
function Test() {
254 for (const fn
of TESTS
) {
255 await wtu
.dispatchPromise(fn
);
257 wtu
.destroyAllContexts();
263 var successfullyParsed
= true;