Backed out changeset b462e7b742d8 (bug 1908261) for causing multiple reftest failures...
[gecko.git] / dom / canvas / test / webgl-conf / checkout / conformance / extensions / webgl-compressed-texture-pvrtc.html
blob465f44a9cdac10df13db230ea1274764a1d6320b
1 <!--
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.
5 -->
7 <!DOCTYPE html>
8 <html>
9 <head>
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>
14 <title>WebGL WEBGL_compressed_texture_pvrtc Conformance Tests</title>
15 <style>
16 img {
17 border: 1px solid black;
18 margin-right: 1em;
20 .testimages {
23 .testimages br {
24 clear: both;
27 .testimages > div {
28 float: left;
29 margin: 1em;
31 </style>
32 </head>
33 <body>
34 <div id="description"></div>
35 <canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas>
36 <div id="console"></div>
37 <script>
38 "use strict";
39 description("This test verifies the functionality of the WEBGL_compressed_texture_pvrtc extension, if it is available.");
41 debug("");
43 var pvrtc_4x4_2bpp = new Uint8Array([
44 0x77, 0x22, 0x77, 0x22, 0xbb, 0x2b, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
45 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
46 ]);
48 var pvrtc_4x4_4bpp = new Uint8Array([
49 0x1b, 0x1b, 0x1b, 0x1b, 0xba, 0x2b, 0x00, 0x80, 0x1b, 0x1b, 0x1b, 0x1b, 0xba, 0x2b, 0x00, 0x80,
50 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
51 ]);
53 var pvrtc_4x4_rgba_decoded = new Uint8Array([
54 0x00, 0x00, 0x00, 0xff, 0x46, 0x46, 0x46, 0xb8, 0x76, 0x76, 0x71, 0x8a, 0xbd, 0xbd, 0xba, 0x44,
55 0x00, 0x00, 0x00, 0xff, 0x46, 0x46, 0x43, 0xb8, 0x76, 0x76, 0x71, 0x8a, 0xbd, 0xbd, 0xb5, 0x44,
56 0x00, 0x00, 0x00, 0xff, 0x46, 0x46, 0x43, 0xb8, 0x76, 0x76, 0x71, 0x8a, 0xbd, 0xbd, 0xb5, 0x44,
57 0x00, 0x00, 0x00, 0xff, 0x46, 0x46, 0x46, 0xb8, 0x76, 0x76, 0x71, 0x8a, 0xbd, 0xbd, 0xb7, 0x44,
58 ]);
60 var pvrtc_4x4_rgb_decoded = new Uint8Array([
61 0x00, 0x00, 0x00, 0xff, 0x46, 0x46, 0x46, 0xff, 0x76, 0x76, 0x71, 0xff, 0xbd, 0xbd, 0xba, 0xff,
62 0x00, 0x00, 0x00, 0xff, 0x46, 0x46, 0x43, 0xff, 0x76, 0x76, 0x71, 0xff, 0xbd, 0xbd, 0xb5, 0xff,
63 0x00, 0x00, 0x00, 0xff, 0x46, 0x46, 0x43, 0xff, 0x76, 0x76, 0x71, 0xff, 0xbd, 0xbd, 0xb5, 0xff,
64 0x00, 0x00, 0x00, 0xff, 0x46, 0x46, 0x46, 0xff, 0x76, 0x76, 0x71, 0xff, 0xbd, 0xbd, 0xb7, 0xff,
65 ]);
67 var wtu = WebGLTestUtils;
68 var contextVersion = wtu.getDefault3DContextVersion();
69 var canvas = document.getElementById("canvas");
70 var gl = wtu.create3DContext(canvas, {antialias: false});
71 var program = wtu.setupTexturedQuad(gl);
72 var ext = null;
73 var vao = null;
74 var validFormats = {
75 COMPRESSED_RGB_PVRTC_4BPPV1_IMG : 0x8C00,
76 COMPRESSED_RGB_PVRTC_2BPPV1_IMG : 0x8C01,
77 COMPRESSED_RGBA_PVRTC_4BPPV1_IMG : 0x8C02,
78 COMPRESSED_RGBA_PVRTC_2BPPV1_IMG : 0x8C03,
80 var name;
81 var supportedFormats;
83 if (!gl) {
84 testFailed("WebGL context does not exist");
85 } else {
86 testPassed("WebGL context exists");
88 // Run tests with extension disabled
89 runTestDisabled();
91 // Query the extension and store globally so shouldBe can access it
92 ext = wtu.getExtensionWithKnownPrefixes(gl, "WEBGL_compressed_texture_pvrtc");
93 if (!ext) {
94 testPassed("No WEBGL_compressed_texture_pvrtc support -- this is legal");
95 runSupportedTest(false);
96 } else {
97 testPassed("Successfully enabled WEBGL_compressed_texture_pvrtc extension");
99 runSupportedTest(true);
100 runTestExtension();
104 function runSupportedTest(extensionEnabled) {
105 var name = wtu.getSupportedExtensionWithKnownPrefixes(gl, "WEBGL_compressed_texture_pvrtc");
106 if (name !== undefined) {
107 if (extensionEnabled) {
108 testPassed("WEBGL_compressed_texture_pvrtc listed as supported and getExtension succeeded");
109 } else {
110 testFailed("WEBGL_compressed_texture_pvrtc listed as supported but getExtension failed");
112 } else {
113 if (extensionEnabled) {
114 testFailed("WEBGL_compressed_texture_pvrtc not listed as supported but getExtension succeeded");
115 } else {
116 testPassed("WEBGL_compressed_texture_pvrtc not listed as supported and getExtension failed -- this is legal");
122 function runTestDisabled() {
123 debug("Testing binding enum with extension disabled");
125 supportedFormats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS);
126 shouldBe("supportedFormats", "[]");
129 function formatExists(format, supportedFormats) {
130 for (var ii = 0; ii < supportedFormats.length; ++ii) {
131 if (format == supportedFormats[ii]) {
132 testPassed("supported format " + formatToString(format) + " is exists");
133 return;
136 testFailed("supported format " + formatToString(format) + " does not exist");
139 function formatToString(format) {
140 for (var p in ext) {
141 if (ext[p] == format) {
142 return p;
145 return "0x" + format.toString(16);
148 function runTestExtension() {
149 debug("Testing WEBGL_compressed_texture_pvrtc");
151 // check that all format enums exist.
152 for (name in validFormats) {
153 var expected = "0x" + validFormats[name].toString(16);
154 var actual = "ext['" + name + "']";
155 shouldBe(actual, expected);
158 supportedFormats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS);
159 // There should be exactly 4 formats for both WebGL 1.0 and WebGL 2.0.
160 shouldBe("supportedFormats.length", "4");
162 // check that all 4 formats exist
163 for (var name in validFormats.length) {
164 formatExists(validFormats[name], supportedFormats);
167 // Test each format
168 testPVRTC_RGBA_2BPP();
169 testPVRTC_RGB_2BPP();
170 testPVRTC_RGBA_4BPP();
171 testPVRTC_RGB_4BPP();
174 function testPVRTC_RGBA_2BPP() {
175 var tests = [
176 { width: 4,
177 height: 4,
178 channels: 4,
179 data: pvrtc_4x4_2bpp,
180 raw: pvrtc_4x4_rgba_decoded,
181 format: ext.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG
184 testPVRTCTextures(tests);
187 function testPVRTC_RGB_2BPP() {
188 var tests = [
189 { width: 4,
190 height: 4,
191 channels: 4,
192 data: pvrtc_4x4_2bpp,
193 raw: pvrtc_4x4_rgb_decoded,
194 format: ext.COMPRESSED_RGB_PVRTC_2BPPV1_IMG
197 testPVRTCTextures(tests);
200 function testPVRTC_RGBA_4BPP() {
201 var tests = [
202 { width: 4,
203 height: 4,
204 channels: 4,
205 data: pvrtc_4x4_4bpp,
206 raw: pvrtc_4x4_rgba_decoded,
207 format: ext.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG
210 testPVRTCTextures(tests);
213 function testPVRTC_RGB_4BPP() {
214 var tests = [
215 { width: 4,
216 height: 4,
217 channels: 4,
218 data: pvrtc_4x4_4bpp,
219 raw: pvrtc_4x4_rgb_decoded,
220 format: ext.COMPRESSED_RGB_PVRTC_4BPPV1_IMG
223 testPVRTCTextures(tests);
226 function testPVRTCTextures(tests) {
227 debug("<hr/>");
228 for (var ii = 0; ii < tests.length; ++ii) {
229 testPVRTCTexture(tests[ii]);
233 function testPVRTCTexture(test) {
234 var data = new Uint8Array(test.data);
235 var width = test.width;
236 var height = test.height;
237 var format = test.format;
238 var uncompressedData = test.raw;
240 canvas.width = width;
241 canvas.height = height;
242 gl.viewport(0, 0, width, height);
243 debug("testing " + formatToString(format) + " " + width + "x" + height);
245 var tex = gl.createTexture();
246 gl.bindTexture(gl.TEXTURE_2D, tex);
247 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
248 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
249 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
250 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
251 gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, data);
252 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture");
253 gl.generateMipmap(gl.TEXTURE_2D);
254 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "trying to generate mipmaps from compressed texture");
255 wtu.clearAndDrawUnitQuad(gl);
256 compareRect(width, height, test.channels, width, height, uncompressedData, data, format, undefined, "NEAREST");
257 // Test again with linear filtering.
258 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
259 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
260 wtu.clearAndDrawUnitQuad(gl);
261 compareRect(width, height, test.channels, width, height, uncompressedData, data, format, undefined, "LINEAR");
263 gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 1, data);
264 wtu.glErrorShouldBe(gl, gl.INVALID_VALUE, "non 0 border");
266 gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 1, height, 0, data);
267 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
268 gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 2, height, 0, data);
269 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
270 gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 1, 0, data);
271 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
272 gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 2, 0, data);
273 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
275 gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, format, data);
276 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "compressedTexSubImage2D allowed for reloading of complete textures");
278 gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width - 2, height, format, data);
279 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "compressedTexSubImage2D not allowed for partial texture updates");
280 gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height - 2, format, data);
281 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "compressedTexSubImage2D not allowed for partial texture updates");
282 gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 2, 0, width - 2, height, format, data);
283 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "compressedTexSubImage2D not allowed for partial texture updates");
284 gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 2, width, height - 2, format, data);
285 wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "compressedTexSubImage2D not allowed for partial texture updates");
288 function insertImg(element, caption, img) {
289 var div = document.createElement("div");
290 div.appendChild(img);
291 var label = document.createElement("div");
292 label.appendChild(document.createTextNode(caption));
293 div.appendChild(label);
294 element.appendChild(div);
297 function makeImage(imageWidth, imageHeight, dataWidth, data, alpha) {
298 var scale = 8;
299 var c = document.createElement("canvas");
300 c.width = imageWidth * scale;
301 c.height = imageHeight * scale;
302 var ctx = c.getContext("2d");
303 for (var yy = 0; yy < imageHeight; ++yy) {
304 for (var xx = 0; xx < imageWidth; ++xx) {
305 var offset = (yy * dataWidth + xx) * 4;
306 ctx.fillStyle = "rgba(" +
307 data[offset + 0] + "," +
308 data[offset + 1] + "," +
309 data[offset + 2] + "," +
310 (alpha ? data[offset + 3] / 255 : 1) + ")";
311 ctx.fillRect(xx * scale, yy * scale, scale, scale);
314 return wtu.makeImageFromCanvas(c);
316 function compareRect(
317 actualWidth, actualHeight, actualChannels,
318 dataWidth, dataHeight, expectedData,
319 testData, testFormat, tolerance, filteringMode) {
320 if(typeof(tolerance) == 'undefined') { tolerance = 5; }
321 var actual = new Uint8Array(actualWidth * actualHeight * 4);
322 gl.readPixels(
323 0, 0, actualWidth, actualHeight, gl.RGBA, gl.UNSIGNED_BYTE, actual);
325 var div = document.createElement("div");
326 div.className = "testimages";
327 insertImg(div, "expected", makeImage(
328 actualWidth, actualHeight, dataWidth, expectedData,
329 actualChannels == 4));
330 insertImg(div, "actual", makeImage(
331 actualWidth, actualHeight, actualWidth, actual,
332 actualChannels == 4));
333 div.appendChild(document.createElement('br'));
334 document.getElementById("console").appendChild(div);
336 var failed = false;
337 for (var yy = 0; yy < actualHeight; ++yy) {
338 for (var xx = 0; xx < actualWidth; ++xx) {
339 var actualOffset = (yy * actualWidth + xx) * 4;
340 var expectedOffset = (yy * dataWidth + xx) * 4;
341 var expected = [
342 expectedData[expectedOffset + 0],
343 expectedData[expectedOffset + 1],
344 expectedData[expectedOffset + 2],
345 (actualChannels == 3 ? 255 : expectedData[expectedOffset + 3])
347 for (var jj = 0; jj < 4; ++jj) {
348 if (Math.abs(actual[actualOffset + jj] - expected[jj]) > tolerance) {
349 failed = true;
350 var was = actual[actualOffset + 0].toString();
351 for (var j = 1; j < 4; ++j) {
352 was += "," + actual[actualOffset + j];
354 testFailed('at (' + xx + ', ' + yy +
355 ') expected: ' + expected + ' was ' + was);
360 if (!failed) {
361 testPassed("texture rendered correctly with " + filteringMode + " filtering");
365 debug("");
366 var successfullyParsed = true;
367 </script>
368 <script src="../../js/js-test-post.js"></script>
370 </body>
371 </html>