2 Copyright (c) 2023 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 WEBGL_render_shared_exponent 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 <div id=
"description"></div>
18 <div id=
"console"></div>
21 description("This test verifies the functionality of the WEBGL_render_shared_exponent extension, if it is available.");
25 var wtu
= WebGLTestUtils
;
26 var gl
= wtu
.create3DContext(null, null, 2);
28 const color
= [64.0, 32.0, 16.0, 1.0];
31 wtu
.clearAndDrawUnitQuad(gl
);
33 wtu
.checkCanvasRect(gl
, 0, 0, 1, 1, color
,
34 "reading with the RGBA format and FLOAT type", 1,
35 new Float32Array(4), gl
.FLOAT
, gl
.RGBA
);
37 const implementationType
= gl
.getParameter(gl
.IMPLEMENTATION_COLOR_READ_TYPE
);
38 const implementationFormat
= gl
.getParameter(gl
.IMPLEMENTATION_COLOR_READ_FORMAT
);
39 if (implementationFormat
== gl
.RGB
&& implementationType
== gl
.UNSIGNED_INT_5_9_9_9_REV
) {
40 // Shared exponent value may be implementation
41 // specific, so compare decoded values.
42 const value
= new Uint32Array(1);
43 gl
.readPixels(0, 0, 1, 1, gl
.RGB
, gl
.UNSIGNED_INT_5_9_9_9_REV
, value
);
44 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
);
46 let r
= (value
>> 0) & 0x1FF;
47 let g
= (value
>> 9) & 0x1FF;
48 let b
= (value
>> 18) & 0x1FF;
49 let e
= (value
>> 27) & 0x01F;
50 debug(`Raw value: 0x${value[0].toString(16).toUpperCase()}, ` +
51 `Raw components: R = ${r}, G = ${g}, B = ${b}, E = ${e}`);
53 e
= Math
.pow(2, e
- 24);
57 debug(`Decoded color: (${r}, ${g}, ${b})`);
59 if (r
== color
[0] && g
== color
[1] && b
== color
[2]) {
60 testPassed("reading with the exact format/type");
62 testFailed("reading with the exact format/type");
67 function renderbufferTest(isSupported
) {
69 debug(`RGB9_E5 renderbuffer: ` +
70 `${!isSupported ? "NOT " : ""}supported`);
72 const rbo
= gl
.createRenderbuffer();
73 gl
.bindRenderbuffer(gl
.RENDERBUFFER
, rbo
);
74 gl
.renderbufferStorage(gl
.RENDERBUFFER
, gl
.RGB9_E5
, 1, 1);
76 wtu
.glErrorShouldBe(gl
, gl
.INVALID_ENUM
, "renderbuffer allocation failed");
79 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "renderbuffer allocation succeeded");
81 const fbo
= gl
.createFramebuffer();
82 gl
.bindFramebuffer(gl
.FRAMEBUFFER
, fbo
);
83 gl
.framebufferRenderbuffer(gl
.FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, gl
.RENDERBUFFER
, rbo
);
85 wtu
.framebufferStatusShouldBe(gl
, gl
.FRAMEBUFFER
, gl
.FRAMEBUFFER_COMPLETE
);
90 function textureTest(isRenderable
) {
92 debug(`RGB9_E5 texture: ` +
93 `${!isRenderable ? "NOT " : ""}renderable`);
95 const tex
= gl
.createTexture();
96 gl
.bindTexture(gl
.TEXTURE_2D
, tex
);
97 gl
.texImage2D(gl
.TEXTURE_2D
, 0, gl
.RGB9_E5
, 1, 1, 0, gl
.RGB
, gl
.UNSIGNED_INT_5_9_9_9_REV
, null);
98 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "texture allocation succeeded");
100 const fbo
= gl
.createFramebuffer();
101 gl
.bindFramebuffer(gl
.FRAMEBUFFER
, fbo
);
102 gl
.framebufferTexture2D(gl
.FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, gl
.TEXTURE_2D
, tex
, 0);
105 wtu
.framebufferStatusShouldBe(gl
, gl
.FRAMEBUFFER
, gl
.FRAMEBUFFER_INCOMPLETE_ATTACHMENT
);
108 wtu
.framebufferStatusShouldBe(gl
, gl
.FRAMEBUFFER
, gl
.FRAMEBUFFER_COMPLETE
);
113 function formatTest(isEnabled
) {
114 const program
= wtu
.setupProgram(gl
, [wtu
.simpleVertexShader
,
115 wtu
.simpleColorFragmentShader
]);
116 gl
.useProgram(program
);
117 gl
.uniform4fv(gl
.getUniformLocation(program
, "u_color"), color
);
119 wtu
.setupUnitQuad(gl
);
121 renderbufferTest(isEnabled
);
122 textureTest(isEnabled
);
125 function colorMaskTest() {
127 debug("Test color write masks with shared exponent color buffers");
129 const fs
= `#version 300 es
130 precision highp float;
131 layout(location = 0) out vec4 color0;
132 layout(location = 1) out vec4 color1;
134 color0 = vec4(1.0, 0.0, 0.0, 1.0);
135 color1 = vec4(0.0, 1.0, 0.0, 1.0);
137 const program
= wtu
.setupProgram(gl
, [wtu
.simpleVertexShaderESSL300
, fs
]);
138 gl
.useProgram(program
);
140 const fbo
= gl
.createFramebuffer();
141 gl
.bindFramebuffer(gl
.FRAMEBUFFER
, fbo
);
143 const rb0
= gl
.createRenderbuffer();
144 gl
.bindRenderbuffer(gl
.RENDERBUFFER
, rb0
);
145 gl
.renderbufferStorage(gl
.RENDERBUFFER
, gl
.RGB9_E5
, 4, 4);
146 gl
.framebufferRenderbuffer(gl
.FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, gl
.RENDERBUFFER
, rb0
);
148 const rb1
= gl
.createRenderbuffer();
149 gl
.bindRenderbuffer(gl
.RENDERBUFFER
, rb1
);
150 gl
.renderbufferStorage(gl
.RENDERBUFFER
, gl
.RGBA8
, 4, 4);
151 gl
.framebufferRenderbuffer(gl
.FRAMEBUFFER
, gl
.COLOR_ATTACHMENT1
, gl
.RENDERBUFFER
, rb1
);
153 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
);
154 wtu
.framebufferStatusShouldBe(gl
, gl
.FRAMEBUFFER
, gl
.FRAMEBUFFER_COMPLETE
);
156 const clearValue
= new Float32Array(4);
157 const dbiExt
= gl
.getExtension("OES_draw_buffers_indexed");
159 function expectError(enabled
, effectiveMask
, operation
) {
161 effectiveMask
== 0x0 /* 0000 */ ||
162 effectiveMask
== 0x8 /* 000A */ ||
163 effectiveMask
== 0x7 /* RGB0 */ ||
164 effectiveMask
== 0xF /* RGBA */ ) {
165 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, operation
);
167 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, operation
);
171 function runOps(enabled
, mask0
) {
172 wtu
.drawUnitQuad(gl
);
173 expectError(enabled
, mask0
, "draw");
175 gl
.clear(gl
.COLOR_BUFFER_BIT
);
176 expectError(enabled
, mask0
, "clear");
178 gl
.clearBufferfv(gl
.COLOR
, 0, clearValue
);
179 expectError(enabled
, mask0
, "clearBufferfv(RGB9_E5)");
180 gl
.clearBufferfv(gl
.COLOR
, 1, clearValue
);
181 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "clearBufferfv(RGBA8)");
184 for (let mask
= 0; mask
< 16; mask
++) {
185 for (const enabled
of [false, true]) {
187 debug(`Setting common color mask ` +
188 `${mask & 1 ? "R" : "0"}` +
189 `${mask & 2 ? "G" : "0"}` +
190 `${mask & 4 ? "B" : "0"}` +
191 `${mask & 8 ? "A" : "0"}` +
192 " with RGB9_E5 attachment " +
193 (enabled
? "enabled" : "disabled"));
194 gl
.colorMask(mask
& 1, mask
& 2, mask
& 4, mask
& 8);
195 gl
.drawBuffers([enabled
? gl
.COLOR_ATTACHMENT0
: gl
.NONE
,
196 gl
.COLOR_ATTACHMENT1
]);
198 runOps(enabled
, mask
);
201 debug("Setting incompatible color mask on unused draw buffer")
202 dbiExt
.colorMaskiOES(2, true, false, false, false);
203 runOps(enabled
, mask
); // common mask remains on draw buffer 0
205 debug("Setting incompatible color mask on RGBA8 draw buffer")
206 dbiExt
.colorMaskiOES(1, true, false, false, false);
207 runOps(enabled
, mask
); // common mask remains on draw buffer 0
209 debug("Setting incompatible color mask on RGB9_E5 draw buffer")
210 dbiExt
.colorMaskiOES(0, true, false, false, false);
211 runOps(enabled
, 1); // overridden
213 debug("Setting compatible color mask on RGB9_E5 draw buffer")
214 dbiExt
.colorMaskiOES(0, true, true, true, false);
215 runOps(enabled
, 7); // overridden
223 testFailed("context does not exist");
226 testPassed("context exists");
229 debug("Testing shared exponent rendering with extension disabled");
232 ext
= gl
.getExtension("WEBGL_render_shared_exponent");
233 wtu
.runExtensionSupportedTest(gl
, "WEBGL_render_shared_exponent", ext
!== null);
237 debug("Testing shared exponent rendering with extension enabled");
241 testPassed("No WEBGL_render_shared_exponent support -- this is legal");
247 var successfullyParsed
= true;
249 <script src=
"../../js/js-test-post.js"></script>