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 <title>texStorage2D conformance test
</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 <canvas id=
"canvas" width=
"64" height=
"64"> </canvas>
19 <div id=
"console"></div>
24 description("This test verifies the functionality of texStorage2D.");
28 var wtu
= WebGLTestUtils
;
29 var canvas
= document
.getElementById("canvas");
30 var gl
= wtu
.create3DContext(canvas
, null, 2);
34 testFailed("WebGL context does not exist");
36 testPassed("WebGL context exists");
38 runTexStorage2DTest();
40 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "there should be no errors");
43 function enumToString(value
) {
44 return wtu
.glEnumToString(gl
, value
);
47 function runTexStorage2DTest()
49 var texStorage2DTestCases
= [
51 target
: gl
.TEXTURE_2D
,
53 sizedformat
: gl
.RGBA8
,
54 unsizedformat
: gl
.RGBA
,
55 type
: gl
.UNSIGNED_BYTE
,
57 redpixel
: new Uint8Array([0xff, 0x00, 0x00, 0x00]),
60 target
: gl
.TEXTURE_2D
,
62 sizedformat
: gl
.R11F_G11F_B10F
,
63 unsizedformat
: gl
.RGB
,
64 type
: gl
.UNSIGNED_INT_10F_11F_11F_REV
,
66 // Red is unsigned floating point with 5 exponent bits followed by 6 mantissa bits.
67 // The effective value is 2^(exponent - 15) * (1 + mantissa / 64)
68 // See OpenGL ES 3.0.3 spec, section 2.1.3
69 // Here we want to encode the value 1.0, which we achieve with a zero mantissa
70 // and an exponent of 15.
71 redpixel
: new Uint32Array([15<<6]),
74 target
: gl
.TEXTURE_2D
,
76 sizedformat
: gl
.RGBA32F
,
77 unsizedformat
: gl
.RGBA
,
80 redpixel
: new Float32Array([1, 0, 0, 0]),
83 target
: gl
.TEXTURE_CUBE_MAP
,
85 sizedformat
: gl
.RGBA8
,
86 unsizedformat
: gl
.RGBA
,
87 type
: gl
.UNSIGNED_BYTE
,
89 redpixel
: new Uint8Array([0xff, 0x00, 0x00, 0x00]),
92 target
: gl
.TEXTURE_CUBE_MAP
,
95 unsizedformat
: gl
.RGB
,
96 type
: gl
.UNSIGNED_BYTE
,
98 redpixel
: new Uint8Array([0xff, 0x00, 0x00]),
101 target
: gl
.TEXTURE_CUBE_MAP
,
103 sizedformat
: gl
.RGB10_A2UI
,
104 unsizedformat
: gl
.UNSIGNED_INT_2_10_10_10_REV
, // type enum, bad as format
107 target
: gl
.TEXTURE_CUBE_MAP
,
109 sizedformat
: gl
.R11F_G11F_B10F
,
110 unsizedformat
: gl
.RGB
,
114 texStorage2DTestCases
.forEach(function(testcase
){
115 var target
= testcase
.target
;
118 if (target
== gl
.TEXTURE_2D
) {
119 imageTargets
= [ gl
.TEXTURE_2D
];
121 imageTargets
= [ gl
.TEXTURE_CUBE_MAP_POSITIVE_X
,
122 gl
.TEXTURE_CUBE_MAP_NEGATIVE_X
,
123 gl
.TEXTURE_CUBE_MAP_POSITIVE_Y
,
124 gl
.TEXTURE_CUBE_MAP_NEGATIVE_Y
,
125 gl
.TEXTURE_CUBE_MAP_POSITIVE_Z
,
126 gl
.TEXTURE_CUBE_MAP_NEGATIVE_Z
];
129 var tex
= gl
.createTexture();
130 gl
.bindTexture(target
, tex
);
132 var levels
= testcase
.mipmap
133 ? Math
.floor(Math
.log(texsize
) / Math
.log(2)) + 1
137 debug("Testing texStorage2D with target " + enumToString(target
) + ", " +
138 (testcase
.mipmap
? "mipmap" : "no mipmap") + ", " +
139 "internalformat: " + enumToString(testcase
.sizedformat
));
141 gl
.texStorage2D(target
, levels
, testcase
.sizedformat
,
143 wtu
.glErrorShouldBe(gl
, gl
.INVALID_VALUE
, "texStorage2D should fail for zero width");
144 gl
.texStorage2D(target
, levels
, testcase
.sizedformat
,
146 wtu
.glErrorShouldBe(gl
, gl
.INVALID_VALUE
, "texStorage2D should fail for zero height");
147 gl
.texStorage2D(target
, levels
, testcase
.sizedformat
,
149 wtu
.glErrorShouldBe(gl
, gl
.INVALID_VALUE
, "texStorage2D should fail for negative height");
150 gl
.texStorage2D(target
, 0, testcase
.sizedformat
,
152 wtu
.glErrorShouldBe(gl
, gl
.INVALID_VALUE
, "texStorage2D should fail for zero levels");
153 gl
.texStorage2D(target
,
154 Math
.ceil(Math
.log(texsize
) / Math
.log(2)) + 2,
155 testcase
.sizedformat
,
157 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "texStorage2D should fail for too many levels");
158 gl
.texStorage2D(gl
.TEXTURE_CUBE_MAP_NEGATIVE_X
, levels
, testcase
.sizedformat
,
160 wtu
.glErrorShouldBe(gl
, gl
.INVALID_ENUM
, "texStorage2D should fail for bad target TEXTURE_CUBE_MAP_NEGATIVE_X");
162 gl
.bindTexture(target
, null);
163 gl
.texStorage2D(target
, levels
, testcase
.sizedformat
,
165 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "texStorage2D should fail when no texture is bound");
166 gl
.bindTexture(target
, tex
);
168 // texStorage2D should only accept sized internalformats
169 gl
.texStorage2D(target
, levels
, testcase
.unsizedformat
,
171 wtu
.glErrorShouldBe(gl
, gl
.INVALID_ENUM
, "texStorage2D should fail for bad internalformat " + enumToString(testcase
.unsizedformat
));
173 // OK, now let's finally do the successfull texStorage2D call
174 gl
.texStorage2D(target
, levels
, testcase
.sizedformat
,
176 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "texStorage2D should succeed with a good sized internalformat");
178 // check TEXTURE_IMMUTABLE_FORMAT
179 var immutable
= gl
.getTexParameter(target
, gl
.TEXTURE_IMMUTABLE_FORMAT
);
180 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "getTexParameter should succeed with TEXTURE_IMMUTABLE_FORMAT");
181 assertMsg(immutable
!= 0, "getTexParameter with TEXTURE_IMMUTABLE_FORMAT should not return 0");
183 // check operations disallowed on immutable texture
184 gl
.texImage2D(imageTargets
[0], 0, gl
.RGBA
, texsize
, texsize
, 0,
185 gl
.RGBA
, gl
.UNSIGNED_BYTE
, null);
186 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "texImage2D should fail on immutable texture");
187 var s3tc
= gl
.getExtension("WEBGL_compressed_texture_s3tc");
188 // FIXME - should eventually use a compressed format that's core in WebGL2, but
189 // I wanted something that I can run in Firefox today, which doesn't support the new formats yet.
191 gl
.compressedTexImage2D(imageTargets
[0], 0, s3tc
.COMPRESSED_RGBA_S3TC_DXT3_EXT
,
193 new Uint8Array(texsize
* texsize
));
194 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "compressedTexImage2D should fail on immutable texture");
196 gl
.copyTexImage2D(imageTargets
[0], 0, gl
.RGBA
, 0, 0, texsize
, texsize
, 0);
197 wtu
.glErrorShouldBe(gl
, gl
.INVALID_OPERATION
, "copyTexImage2D should fail on immutable texture");
199 if ('redpixel' in testcase
) {
200 // At this point, the texture images have only been defined by
201 // texStorage2D, which per spec should be equivalent to having
202 // defined texture images with null data, which should sample as RGBA 0,0,0,0.
203 gl
.texParameteri(target
, gl
.TEXTURE_MIN_FILTER
,
204 testcase
.mipmap
? gl
.NEAREST_MIPMAP_NEAREST
: gl
.NEAREST
);
205 if (testcase
.type
== gl
.FLOAT
) {
206 gl
.texParameteri(target
, gl
.TEXTURE_MAG_FILTER
, gl
.NEAREST
);
209 // Now upload some red texture data
212 if (testcase
.redpixel
instanceof Uint8Array
) {
213 pixels
= new Uint8Array(texsize
* texsize
* testcase
.redpixel
.length
);
214 } else if (testcase
.redpixel
instanceof Uint16Array
) {
215 pixels
= new Uint16Array(texsize
* texsize
* testcase
.redpixel
.length
);
216 } else if (testcase
.redpixel
instanceof Uint32Array
) {
217 pixels
= new Uint32Array(texsize
* texsize
* testcase
.redpixel
.length
);
218 } else if (testcase
.redpixel
instanceof Float32Array
) {
219 pixels
= new Float32Array(texsize
* texsize
* testcase
.redpixel
.length
);
221 for (var i
= 0; i
< texsize
* texsize
; i
++) {
222 for (var j
= 0; j
< testcase
.redpixel
.length
; j
++) {
223 pixels
[i
* testcase
.redpixel
.length
+ j
] = testcase
.redpixel
[j
];
227 if (target
== gl
.TEXTURE_2D
) {
228 wtu
.setupTexturedQuad(gl
);
229 } else if (target
== gl
.TEXTURE_CUBE_MAP
) {
230 wtu
.setupTexturedQuadWithCubeMap(gl
);
233 wtu
.clearAndDrawUnitQuad(gl
);
234 var alpha
= testcase
.alpha
? 0 : 255;
235 wtu
.checkCanvas(gl
, [0, 0, 0, alpha
], "texture should sample as uninitialized texture after texStorage2D");
237 if (target
== gl
.TEXTURE_2D
) {
238 for (var l
= 0; l
< levels
; l
++) {
239 gl
.texSubImage2D(gl
.TEXTURE_2D
,
242 testcase
.unsizedformat
, testcase
.type
,
244 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "texSubImage2D should succeed on immutable texture as long as the format is compatible");
247 } else if (target
== gl
.TEXTURE_CUBE_MAP
) {
248 for (var l
= 0; l
< levels
; l
++) {
249 for (var f
= 0; f
< 6; f
++) {
250 gl
.texSubImage2D(gl
.TEXTURE_CUBE_MAP_POSITIVE_X
+ f
,
253 testcase
.unsizedformat
, testcase
.type
,
255 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "texSubImage2D should succeed on immutable texture as long as the format is compatible");
261 wtu
.clearAndDrawUnitQuad(gl
);
262 wtu
.checkCanvas(gl
, [255, 0, 0, alpha
], "texture should sample as red after uploading red pixels with texSubImage2D");
267 debug("Test non-square images:");
269 const maxSize
= 1 << (levels
-1);
271 function expectOk(x
,y
) {
272 const tex
= gl
.createTexture();
273 gl
.bindTexture(gl
.TEXTURE_2D
, tex
);
274 gl
.texStorage2D(gl
.TEXTURE_2D
, levels
, gl
.RGBA8
, x
, y
);
275 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
,
276 "texStorage2D should succeed with size [" + ([x
,y
].join(', ')) + "].");
277 gl
.deleteTexture(tex
);
279 expectOk(maxSize
, maxSize
);
280 expectOk(maxSize
, 1);
281 expectOk( 1, maxSize
);
285 var successfullyParsed
= true;
287 <script src=
"../../../js/js-test-post.js"></script>