content/canvas/test/webgl-conformance/conformance/extensions/webgl-compressed-texture-s3tc.html

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

michael@0 1 <!--
michael@0 2 Copyright (c) 2012 The Chromium Authors. All rights reserved.
michael@0 3 Use of this source code is governed by a BSD-style license that can be
michael@0 4 found in the LICENSE file.
michael@0 5 -->
michael@0 6 <!DOCTYPE html>
michael@0 7 <html>
michael@0 8 <head>
michael@0 9 <meta charset="utf-8">
michael@0 10 <link rel="stylesheet" href="../../resources/js-test-style.css"/>
michael@0 11 <script src="../../resources/js-test-pre.js"></script>
michael@0 12 <script src="../resources/webgl-test.js"></script>
michael@0 13 <script src="../resources/webgl-test-utils.js"></script>
michael@0 14 <title>WebGL WEBGL_compressed_texture_s3tc Conformance Tests</title>
michael@0 15 <style>
michael@0 16 img {
michael@0 17 border: 1px solid black;
michael@0 18 margin-right: 1em;
michael@0 19 }
michael@0 20 .testimages {
michael@0 21 }
michael@0 22
michael@0 23 .testimages br {
michael@0 24 clear: both;
michael@0 25 }
michael@0 26
michael@0 27 .testimages > div {
michael@0 28 float: left;
michael@0 29 margin: 1em;
michael@0 30 }
michael@0 31 </style>
michael@0 32 </head>
michael@0 33 <body>
michael@0 34 <div id="description"></div>
michael@0 35 <canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas>
michael@0 36 <div id="console"></div>
michael@0 37 <script>
michael@0 38 description("This test verifies the functionality of the WEBGL_compressed_texture_s3tc extension, if it is available.");
michael@0 39
michael@0 40 debug("");
michael@0 41
michael@0 42 var img_4x4_rgba_raw = new Uint8Array([
michael@0 43 0xff,0x00,0x00,0x69,0x00,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,
michael@0 44 ]);
michael@0 45 var img_4x4_rgb_dxt1 = new Uint8Array([
michael@0 46 0xe0,0x07,0x00,0xf8,0x11,0x10,0x15,0x00,
michael@0 47 ]);
michael@0 48 var img_4x4_rgba_dxt1 = new Uint8Array([
michael@0 49 0xe0,0x07,0x00,0xf8,0x13,0x10,0x15,0x00,
michael@0 50 ]);
michael@0 51 var img_4x4_rgba_dxt3 = new Uint8Array([
michael@0 52 0xf6,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0xf8,0xe0,0x07,0x44,0x45,0x40,0x55,
michael@0 53 ]);
michael@0 54 var img_4x4_rgba_dxt5 = new Uint8Array([
michael@0 55 0xf6,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x00,0xf8,0xe0,0x07,0x44,0x45,0x40,0x55,
michael@0 56 ]);
michael@0 57 var img_8x8_rgba_raw = new Uint8Array([
michael@0 58 0xff,0x00,0x00,0x69,0x00,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0x00,0x69,0x00,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0xff,0x00,0x00,0xff,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0x00,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0x00,0xff,0xff,0x00,0xff,0xff,0x00,0xff,0x00,0xff,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0x00,0xff,0x00,0xff,0xff,0x00,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0x00,0x69,0x00,0xff,0x00,0xff,0x00,0xff,0x00,0xff,0xff,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0x00,0xff,0xff,0x00,0xff,0xff,0xff,0xff,0x00,0xff,0x69,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,0x00,0xff,0xff,0xff,
michael@0 59 ]);
michael@0 60 var img_8x8_rgb_dxt1 = new Uint8Array([
michael@0 61 0xe0,0x07,0x00,0xf8,0x11,0x10,0x15,0x00,0x1f,0x00,0xe0,0xff,0x11,0x10,0x15,0x00,0xe0,0x07,0x1f,0xf8,0x44,0x45,0x40,0x55,0x1f,0x00,0xff,0x07,0x44,0x45,0x40,0x55,
michael@0 62 ]);
michael@0 63 var img_8x8_rgba_dxt1 = new Uint8Array([
michael@0 64 0xe0,0x07,0x00,0xf8,0x13,0x13,0x15,0x00,0x1f,0x00,0xe0,0xff,0x11,0x10,0x15,0x00,0xe0,0x07,0x1f,0xf8,0x44,0x45,0x43,0x57,0x1f,0x00,0xff,0x07,0x44,0x45,0x40,0x55,
michael@0 65 ]);
michael@0 66 var img_8x8_rgba_dxt3 = new Uint8Array([
michael@0 67 0xf6,0xff,0xf6,0xff,0xff,0xff,0xff,0xff,0x00,0xf8,0xe0,0x07,0x44,0x45,0x40,0x55,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xe0,0xff,0x1f,0x00,0x44,0x45,0x40,0x55,0xff,0xff,0xff,0xff,0xf6,0xff,0xf6,0xff,0x1f,0xf8,0xe0,0x07,0x11,0x10,0x15,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x07,0x1f,0x00,0x11,0x10,0x15,0x00,
michael@0 68 ]);
michael@0 69 var img_8x8_rgba_dxt5 = new Uint8Array([
michael@0 70 0xff,0x69,0x01,0x10,0x00,0x00,0x00,0x00,0x00,0xf8,0xe0,0x07,0x44,0x45,0x40,0x55,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xe0,0xff,0x1f,0x00,0x44,0x45,0x40,0x55,0xff,0x69,0x00,0x00,0x00,0x01,0x10,0x00,0x1f,0xf8,0xe0,0x07,0x11,0x10,0x15,0x00,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0x07,0x1f,0x00,0x11,0x10,0x15,0x00,
michael@0 71 ]);
michael@0 72
michael@0 73 var wtu = WebGLTestUtils;
michael@0 74 var canvas = document.getElementById("canvas");
michael@0 75 var gl = wtu.create3DContext(canvas, {antialias: false});
michael@0 76 var program = wtu.setupTexturedQuad(gl);
michael@0 77 var ext = null;
michael@0 78 var vao = null;
michael@0 79 var validFormats = {
michael@0 80 COMPRESSED_RGB_S3TC_DXT1_EXT : 0x83F0,
michael@0 81 COMPRESSED_RGBA_S3TC_DXT1_EXT : 0x83F1,
michael@0 82 COMPRESSED_RGBA_S3TC_DXT3_EXT : 0x83F2,
michael@0 83 COMPRESSED_RGBA_S3TC_DXT5_EXT : 0x83F3,
michael@0 84 };
michael@0 85 var name;
michael@0 86 var supportedFormats;
michael@0 87
michael@0 88 if (!gl) {
michael@0 89 testFailed("WebGL context does not exist");
michael@0 90 } else {
michael@0 91 testPassed("WebGL context exists");
michael@0 92
michael@0 93 // Run tests with extension disabled
michael@0 94 runTestDisabled();
michael@0 95
michael@0 96 // Query the extension and store globally so shouldBe can access it
michael@0 97 ext = gl.getExtension("WEBGL_compressed_texture_s3tc");
michael@0 98 if (!ext) {
michael@0 99 ext = gl.getExtension("WEBKIT_WEBGL_compressed_texture_s3tc");
michael@0 100 }
michael@0 101 if (!ext) {
michael@0 102 testPassed("No WEBGL_compressed_texture_s3tc support -- this is legal");
michael@0 103 runSupportedTest(false);
michael@0 104 } else {
michael@0 105 testPassed("Successfully enabled WEBGL_compressed_texture_s3tc extension");
michael@0 106
michael@0 107 runSupportedTest(true);
michael@0 108 runTestExtension();
michael@0 109 }
michael@0 110 }
michael@0 111
michael@0 112 function runSupportedTest(extensionEnabled) {
michael@0 113 var supported = gl.getSupportedExtensions();
michael@0 114 if (supported.indexOf("WEBGL_compressed_texture_s3tc") >= 0 ||
michael@0 115 supported.indexOf("WEBKIT_WEBGL_compressed_texture_s3tc") >= 0) {
michael@0 116 if (extensionEnabled) {
michael@0 117 testPassed("WEBGL_compressed_texture_s3tc listed as supported and getExtension succeeded");
michael@0 118 } else {
michael@0 119 testFailed("WEBGL_compressed_texture_s3tc listed as supported but getExtension failed");
michael@0 120 }
michael@0 121 } else {
michael@0 122 if (extensionEnabled) {
michael@0 123 testFailed("WEBGL_compressed_texture_s3tc not listed as supported but getExtension succeeded");
michael@0 124 } else {
michael@0 125 testPassed("WEBGL_compressed_texture_s3tc not listed as supported and getExtension failed -- this is legal");
michael@0 126 }
michael@0 127 }
michael@0 128 }
michael@0 129
michael@0 130
michael@0 131 function runTestDisabled() {
michael@0 132 debug("Testing binding enum with extension disabled");
michael@0 133
michael@0 134 shouldBe('gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS)', '[]');
michael@0 135 }
michael@0 136
michael@0 137 function formatExists(format, supportedFormats) {
michael@0 138 for (var ii = 0; ii < supportedFormats.length; ++ii) {
michael@0 139 if (format == supportedFormats[ii]) {
michael@0 140 testPassed("supported format " + formatToString(format) + " is exists");
michael@0 141 return;
michael@0 142 }
michael@0 143 }
michael@0 144 testFailed("supported format " + formatToString(format) + " does not exist");
michael@0 145 }
michael@0 146
michael@0 147 function formatToString(format) {
michael@0 148 for (var p in ext) {
michael@0 149 if (ext[p] == format) {
michael@0 150 return p;
michael@0 151 }
michael@0 152 }
michael@0 153 return "0x" + format.toString(16);
michael@0 154 }
michael@0 155
michael@0 156 function runTestExtension() {
michael@0 157 debug("Testing WEBGL_compressed_texture_s3tc");
michael@0 158
michael@0 159 // check that all format enums exist.
michael@0 160 for (name in validFormats) {
michael@0 161 var expected = "0x" + validFormats[name].toString(16);
michael@0 162 var actual = "ext['" + name + "']";
michael@0 163 shouldBe(actual, expected);
michael@0 164 }
michael@0 165
michael@0 166 supportedFormats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS);
michael@0 167 // There should be exactly 4 formats
michael@0 168 shouldBe("supportedFormats.length", "4");
michael@0 169
michael@0 170 // check that all 4 formats exist
michael@0 171 for (var name in validFormats.length) {
michael@0 172 formatExists(validFormats[name], supportedFormats);
michael@0 173 }
michael@0 174
michael@0 175 // Test each format
michael@0 176 testDXT1_RGB();
michael@0 177 testDXT1_RGBA();
michael@0 178 testDXT3_RGBA();
michael@0 179 testDXT5_RGBA();
michael@0 180 }
michael@0 181
michael@0 182 function testDXT1_RGB() {
michael@0 183 var tests = [
michael@0 184 { width: 4,
michael@0 185 height: 4,
michael@0 186 channels: 3,
michael@0 187 data: img_4x4_rgb_dxt1,
michael@0 188 format: ext.COMPRESSED_RGB_S3TC_DXT1_EXT
michael@0 189 },
michael@0 190 { width: 8,
michael@0 191 height: 8,
michael@0 192 channels: 3,
michael@0 193 data: img_8x8_rgb_dxt1,
michael@0 194 format: ext.COMPRESSED_RGB_S3TC_DXT1_EXT
michael@0 195 }
michael@0 196 ];
michael@0 197 testDXTTextures(tests);
michael@0 198 }
michael@0 199
michael@0 200 function testDXT1_RGBA() {
michael@0 201 var tests = [
michael@0 202 { width: 4,
michael@0 203 height: 4,
michael@0 204 channels: 4,
michael@0 205 data: img_4x4_rgba_dxt1,
michael@0 206 format: ext.COMPRESSED_RGBA_S3TC_DXT1_EXT
michael@0 207 },
michael@0 208 { width: 8,
michael@0 209 height: 8,
michael@0 210 channels: 4,
michael@0 211 data: img_8x8_rgba_dxt1,
michael@0 212 format: ext.COMPRESSED_RGBA_S3TC_DXT1_EXT
michael@0 213 }
michael@0 214 ];
michael@0 215 testDXTTextures(tests);
michael@0 216 }
michael@0 217
michael@0 218 function testDXT3_RGBA() {
michael@0 219 var tests = [
michael@0 220 { width: 4,
michael@0 221 height: 4,
michael@0 222 channels: 4,
michael@0 223 data: img_4x4_rgba_dxt3,
michael@0 224 format: ext.COMPRESSED_RGBA_S3TC_DXT3_EXT
michael@0 225 },
michael@0 226 { width: 8,
michael@0 227 height: 8,
michael@0 228 channels: 4,
michael@0 229 data: img_8x8_rgba_dxt3,
michael@0 230 format: ext.COMPRESSED_RGBA_S3TC_DXT3_EXT
michael@0 231 }
michael@0 232 ];
michael@0 233 testDXTTextures(tests);
michael@0 234 }
michael@0 235
michael@0 236 function testDXT5_RGBA() {
michael@0 237 var tests = [
michael@0 238 { width: 4,
michael@0 239 height: 4,
michael@0 240 channels: 4,
michael@0 241 data: img_4x4_rgba_dxt5,
michael@0 242 format: ext.COMPRESSED_RGBA_S3TC_DXT5_EXT
michael@0 243 },
michael@0 244 { width: 8,
michael@0 245 height: 8,
michael@0 246 channels: 4,
michael@0 247 data: img_8x8_rgba_dxt5,
michael@0 248 format: ext.COMPRESSED_RGBA_S3TC_DXT5_EXT
michael@0 249 }
michael@0 250 ];
michael@0 251 testDXTTextures(tests);
michael@0 252 }
michael@0 253
michael@0 254 function testDXTTextures(tests) {
michael@0 255 debug("<hr/>");
michael@0 256 for (var ii = 0; ii < tests.length; ++ii) {
michael@0 257 testDXTTexture(tests[ii]);
michael@0 258 }
michael@0 259 }
michael@0 260
michael@0 261 function uncompressDXTBlock(
michael@0 262 destBuffer, destX, destY, destWidth, src, srcOffset, format) {
michael@0 263 function make565(src, offset) {
michael@0 264 return src[offset + 0] + src[offset + 1] * 256;
michael@0 265 }
michael@0 266 function make8888From565(c) {
michael@0 267 return [
michael@0 268 Math.floor(((c >> 11) & 0x1F) * 255 / 31),
michael@0 269 Math.floor(((c >> 5) & 0x3F) * 255 / 63),
michael@0 270 Math.floor(((c >> 0) & 0x1F) * 255 / 31),
michael@0 271 255
michael@0 272 ];
michael@0 273 }
michael@0 274 function mix(mult, c0, c1, div) {
michael@0 275 var r = [];
michael@0 276 for (var ii = 0; ii < c0.length; ++ii) {
michael@0 277 r[ii] = Math.floor((c0[ii] * mult + c1[ii]) / div);
michael@0 278 }
michael@0 279 return r;
michael@0 280 }
michael@0 281 var isDXT1 = format == ext.COMPRESSED_RGB_S3TC_DXT1_EXT ||
michael@0 282 format == ext.COMPRESSED_RGBA_S3TC_DXT1_EXT;
michael@0 283 var colorOffset = srcOffset + (isDXT1 ? 0 : 8);
michael@0 284 var color0 = make565(src, colorOffset + 0);
michael@0 285 var color1 = make565(src, colorOffset + 2);
michael@0 286 var c0gtc1 = color0 > color1 || !isDXT1;
michael@0 287 var rgba0 = make8888From565(color0);
michael@0 288 var rgba1 = make8888From565(color1);
michael@0 289 var colors = [
michael@0 290 rgba0,
michael@0 291 rgba1,
michael@0 292 c0gtc1 ? mix(2, rgba0, rgba1, 3) : mix(1, rgba0, rgba1, 2),
michael@0 293 c0gtc1 ? mix(2, rgba1, rgba0, 3) : [0, 0, 0, 255]
michael@0 294 ];
michael@0 295
michael@0 296 // yea I know there is a lot of math in this inner loop.
michael@0 297 // so sue me.
michael@0 298 for (var yy = 0; yy < 4; ++yy) {
michael@0 299 var pixels = src[colorOffset + 4 + yy];
michael@0 300 for (var xx = 0; xx < 4; ++xx) {
michael@0 301 var dstOff = ((destY + yy) * destWidth + destX + xx) * 4;
michael@0 302 var code = (pixels >> (xx * 2)) & 0x3;
michael@0 303 var srcColor = colors[code];
michael@0 304 var alpha;
michael@0 305 switch (format) {
michael@0 306 case ext.COMPRESSED_RGB_S3TC_DXT1_EXT:
michael@0 307 alpha = 255;
michael@0 308 break;
michael@0 309 case ext.COMPRESSED_RGBA_S3TC_DXT1_EXT:
michael@0 310 alpha = (code == 3 && !c0gtc1) ? 0 : 255;
michael@0 311 break;
michael@0 312 case ext.COMPRESSED_RGBA_S3TC_DXT3_EXT:
michael@0 313 {
michael@0 314 var alpha0 = src[srcOffset + yy * 2 + Math.floor(xx / 2)];
michael@0 315 var alpha1 = (alpha0 >> ((xx % 2) * 4)) & 0xF;
michael@0 316 alpha = alpha1 | (alpha1 << 4);
michael@0 317 }
michael@0 318 break;
michael@0 319 case ext.COMPRESSED_RGBA_S3TC_DXT5_EXT:
michael@0 320 {
michael@0 321 var alpha0 = src[srcOffset + 0];
michael@0 322 var alpha1 = src[srcOffset + 1];
michael@0 323 var alphaOff = Math.floor(yy / 2) * 3 + 2;
michael@0 324 var alphaBits =
michael@0 325 src[srcOffset + alphaOff + 0] +
michael@0 326 src[srcOffset + alphaOff + 1] * 256 +
michael@0 327 src[srcOffset + alphaOff + 2] * 65536;
michael@0 328 var alphaShift = (yy % 2) * 12 + xx * 3;
michael@0 329 var alphaCode = (alphaBits >> alphaShift) & 0x7;
michael@0 330 if (alpha0 > alpha1) {
michael@0 331 switch (alphaCode) {
michael@0 332 case 0:
michael@0 333 alpha = alpha0;
michael@0 334 break;
michael@0 335 case 1:
michael@0 336 alpha = alpha1;
michael@0 337 break;
michael@0 338 default:
michael@0 339 alpha = ((8 - alphaCode) * alpha0 + (alphaCode - 1) * alpha1) / 7;
michael@0 340 break;
michael@0 341 }
michael@0 342 } else {
michael@0 343 switch (alphaCode) {
michael@0 344 case 0:
michael@0 345 alpha = alpha0;
michael@0 346 break;
michael@0 347 case 1:
michael@0 348 alpha = alpha1;
michael@0 349 break;
michael@0 350 case 6:
michael@0 351 alpha = 0;
michael@0 352 break;
michael@0 353 case 7:
michael@0 354 alpha = 255;
michael@0 355 break;
michael@0 356 default:
michael@0 357 alpha = ((6 - alphaCode) * alpha0 + (alphaCode - 1) * alpha1) / 5;
michael@0 358 break;
michael@0 359 }
michael@0 360 }
michael@0 361 }
michael@0 362 break;
michael@0 363 default:
michael@0 364 throw "bad format";
michael@0 365 }
michael@0 366 destBuffer[dstOff + 0] = srcColor[0];
michael@0 367 destBuffer[dstOff + 1] = srcColor[1];
michael@0 368 destBuffer[dstOff + 2] = srcColor[2];
michael@0 369 destBuffer[dstOff + 3] = alpha;
michael@0 370 }
michael@0 371 }
michael@0 372 }
michael@0 373
michael@0 374 function getBlockSize(format) {
michael@0 375 var isDXT1 = format == ext.COMPRESSED_RGB_S3TC_DXT1_EXT ||
michael@0 376 format == ext.COMPRESSED_RGBA_S3TC_DXT1_EXT;
michael@0 377 return isDXT1 ? 8 : 16;
michael@0 378 }
michael@0 379
michael@0 380 function uncompressDXT(width, height, data, format) {
michael@0 381 if (width % 4 || height % 4) throw "bad width or height";
michael@0 382
michael@0 383 var dest = new Uint8Array(width * height * 4);
michael@0 384 var blocksAcross = width / 4;
michael@0 385 var blocksDown = height / 4;
michael@0 386 var blockSize = getBlockSize(format);
michael@0 387 for (var yy = 0; yy < blocksDown; ++yy) {
michael@0 388 for (var xx = 0; xx < blocksAcross; ++xx) {
michael@0 389 uncompressDXTBlock(
michael@0 390 dest, xx * 4, yy * 4, width, data,
michael@0 391 (yy * blocksAcross + xx) * blockSize, format);
michael@0 392 }
michael@0 393 }
michael@0 394 return dest;
michael@0 395 }
michael@0 396
michael@0 397 function copyRect(data, srcX, srcY, dstX, dstY, width, height, stride) {
michael@0 398 var bytesPerLine = width * 4;
michael@0 399 var srcOffset = srcX * 4 + srcY * stride;
michael@0 400 var dstOffset = dstX * 4 + dstY * stride;
michael@0 401 for (; height > 0; --height) {
michael@0 402 for (var ii = 0; ii < bytesPerLine; ++ii) {
michael@0 403 data[dstOffset + ii] = data[srcOffset + ii];
michael@0 404 }
michael@0 405 srcOffset += stride;
michael@0 406 dstOffset += stride;
michael@0 407 }
michael@0 408 }
michael@0 409
michael@0 410 function testDXTTexture(test) {
michael@0 411 var data = new Uint8Array(test.data);
michael@0 412 var width = test.width;
michael@0 413 var height = test.height;
michael@0 414 var format = test.format;
michael@0 415
michael@0 416 var uncompressedData = uncompressDXT(width, height, data, format);
michael@0 417
michael@0 418 canvas.width = width;
michael@0 419 canvas.height = height;
michael@0 420 gl.viewport(0, 0, width, height);
michael@0 421 debug("testing " + formatToString(format) + " " + width + "x" + height);
michael@0 422 var tex = gl.createTexture();
michael@0 423 gl.bindTexture(gl.TEXTURE_2D, tex);
michael@0 424 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
michael@0 425 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
michael@0 426 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
michael@0 427 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
michael@0 428 gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, data);
michael@0 429 glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture");
michael@0 430 wtu.drawQuad(gl);
michael@0 431 compareRect(width, height, test.channels, width, height, uncompressedData, data, format);
michael@0 432
michael@0 433 gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 1, data);
michael@0 434 glErrorShouldBe(gl, gl.INVALID_VALUE, "non 0 border");
michael@0 435
michael@0 436 gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width + 4, height, 0, data);
michael@0 437 glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
michael@0 438 gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height + 4, 0, data);
michael@0 439 glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
michael@0 440 gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 4, height, 0, data);
michael@0 441 glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
michael@0 442 gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 4, 0, data);
michael@0 443 glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
michael@0 444
michael@0 445 gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 1, height, 0, data);
michael@0 446 glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
michael@0 447 gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 2, height, 0, data);
michael@0 448 glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
michael@0 449 gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 1, 0, data);
michael@0 450 glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
michael@0 451 gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 2, 0, data);
michael@0 452 glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
michael@0 453
michael@0 454 if (width == 4) {
michael@0 455 gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, 1, height, 0, data);
michael@0 456 glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0");
michael@0 457 gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, 2, height, 0, data);
michael@0 458 glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0");
michael@0 459 }
michael@0 460 if (height == 4) {
michael@0 461 gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, width, 1, 0, data);
michael@0 462 glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0");
michael@0 463 gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, width, 2, 0, data);
michael@0 464 glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0");
michael@0 465 }
michael@0 466
michael@0 467 // pick a wrong format that uses the same amount of data.
michael@0 468 var wrongFormat;
michael@0 469 switch (format) {
michael@0 470 case ext.COMPRESSED_RGB_S3TC_DXT1_EXT:
michael@0 471 wrongFormat = ext.COMPRESSED_RGBA_S3TC_DXT1_EXT;
michael@0 472 break;
michael@0 473 case ext.COMPRESSED_RGBA_S3TC_DXT1_EXT:
michael@0 474 wrongFormat = ext.COMPRESSED_RGB_S3TC_DXT1_EXT;
michael@0 475 break;
michael@0 476 case ext.COMPRESSED_RGBA_S3TC_DXT3_EXT:
michael@0 477 wrongFormat = ext.COMPRESSED_RGBA_S3TC_DXT5_EXT;
michael@0 478 break;
michael@0 479 case ext.COMPRESSED_RGBA_S3TC_DXT5_EXT:
michael@0 480 wrongFormat = ext.COMPRESSED_RGBA_S3TC_DXT3_EXT;
michael@0 481 break;
michael@0 482 }
michael@0 483
michael@0 484 gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, wrongFormat, data);
michael@0 485 glErrorShouldBe(gl, gl.INVALID_OPERATION, "format does not match");
michael@0 486
michael@0 487 gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width + 4, height, format, data);
michael@0 488 glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
michael@0 489 gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height + 4, format, data);
michael@0 490 glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
michael@0 491 gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width - 4, height, format, data);
michael@0 492 glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
michael@0 493 gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height - 4, format, data);
michael@0 494 glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions");
michael@0 495
michael@0 496 gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width - 1, height, format, data);
michael@0 497 glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
michael@0 498 gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width - 2, height, format, data);
michael@0 499 glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
michael@0 500 gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height - 1, format, data);
michael@0 501 glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
michael@0 502 gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height - 2, format, data);
michael@0 503 glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions");
michael@0 504
michael@0 505 var subData = new Uint8Array(data.buffer, 0, getBlockSize(format));
michael@0 506
michael@0 507 if (width == 8 && height == 8) {
michael@0 508 gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 1, 0, 4, 4, format, subData);
michael@0 509 glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid offset");
michael@0 510 gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 1, 4, 4, format, subData);
michael@0 511 glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid offset");
michael@0 512 }
michael@0 513
michael@0 514 var stride = width * 4;
michael@0 515 for (var yoff = 0; yoff < height; yoff += 4) {
michael@0 516 for (var xoff = 0; xoff < width; xoff += 4) {
michael@0 517 copyRect(uncompressedData, 0, 0, xoff, yoff, 4, 4, stride);
michael@0 518 gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, xoff, yoff, 4, 4, format, subData);
michael@0 519 glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture");
michael@0 520 wtu.drawQuad(gl);
michael@0 521 compareRect(width, height, test.channels, width, height, uncompressedData, data, format);
michael@0 522 }
michael@0 523 }
michael@0 524 }
michael@0 525
michael@0 526 function insertImg(element, caption, img) {
michael@0 527 var div = document.createElement("div");
michael@0 528 div.appendChild(img);
michael@0 529 var label = document.createElement("div");
michael@0 530 label.appendChild(document.createTextNode(caption));
michael@0 531 div.appendChild(label);
michael@0 532 element.appendChild(div);
michael@0 533 }
michael@0 534
michael@0 535 function makeImage(imageWidth, imageHeight, dataWidth, data, alpha) {
michael@0 536 var scale = 8;
michael@0 537 var c = document.createElement("canvas");
michael@0 538 c.width = imageWidth * scale;
michael@0 539 c.height = imageHeight * scale;
michael@0 540 var ctx = c.getContext("2d");
michael@0 541 for (var yy = 0; yy < imageWidth; ++yy) {
michael@0 542 for (var xx = 0; xx < imageHeight; ++xx) {
michael@0 543 var offset = (yy * dataWidth + xx) * 4;
michael@0 544 ctx.fillStyle = "rgba(" +
michael@0 545 data[offset + 0] + "," +
michael@0 546 data[offset + 1] + "," +
michael@0 547 data[offset + 2] + "," +
michael@0 548 (alpha ? data[offset + 3] / 255 : 1) + ")";
michael@0 549 ctx.fillRect(xx * scale, yy * scale, scale, scale);
michael@0 550 }
michael@0 551 }
michael@0 552 var img = document.createElement("img");
michael@0 553 img.src = c.toDataURL();
michael@0 554 return img;
michael@0 555 }
michael@0 556 function compareRect(
michael@0 557 actualWidth, actualHeight, actualChannels,
michael@0 558 dataWidth, dataHeight, expectedData,
michael@0 559 testData, testFormat) {
michael@0 560 var actual = new Uint8Array(actualWidth * actualHeight * 4);
michael@0 561 gl.readPixels(
michael@0 562 0, 0, actualWidth, actualHeight, gl.RGBA, gl.UNSIGNED_BYTE, actual);
michael@0 563
michael@0 564 var div = document.createElement("div");
michael@0 565 div.className = "testimages";
michael@0 566 insertImg(div, "expected", makeImage(
michael@0 567 actualWidth, actualHeight, dataWidth, expectedData,
michael@0 568 actualChannels == 4));
michael@0 569 insertImg(div, "actual", makeImage(
michael@0 570 actualWidth, actualHeight, actualWidth, actual,
michael@0 571 actualChannels == 4));
michael@0 572 div.appendChild(document.createElement('br'));
michael@0 573 document.getElementById("console").appendChild(div);
michael@0 574
michael@0 575 var failed = false;
michael@0 576 for (var yy = 0; yy < actualHeight; ++yy) {
michael@0 577 for (var xx = 0; xx < actualWidth; ++xx) {
michael@0 578 var actualOffset = (yy * actualWidth + xx) * 4;
michael@0 579 var expectedOffset = (yy * dataWidth + xx) * 4;
michael@0 580 var expected = [
michael@0 581 expectedData[expectedOffset + 0],
michael@0 582 expectedData[expectedOffset + 1],
michael@0 583 expectedData[expectedOffset + 2],
michael@0 584 (actualChannels == 3 ? 255 : expectedData[expectedOffset + 3])
michael@0 585 ];
michael@0 586 for (var jj = 0; jj < 4; ++jj) {
michael@0 587 if (actual[actualOffset + jj] != expected[jj]) {
michael@0 588 failed = true;
michael@0 589 var was = actual[actualOffset + 0].toString();
michael@0 590 for (j = 1; j < 4; ++j) {
michael@0 591 was += "," + actual[actualOffset + j];
michael@0 592 }
michael@0 593 testFailed('at (' + xx + ', ' + yy +
michael@0 594 ') expected: ' + expected + ' was ' + was);
michael@0 595 }
michael@0 596 }
michael@0 597 }
michael@0 598 }
michael@0 599 if (!failed) {
michael@0 600 testPassed("texture rendered correctly");
michael@0 601 }
michael@0 602 }
michael@0 603
michael@0 604 function testPVRTCTextures() {
michael@0 605 testFailed("PVRTC test not yet implemented");
michael@0 606 }
michael@0 607
michael@0 608 debug("");
michael@0 609 successfullyParsed = true;
michael@0 610 </script>
michael@0 611 <script>finishTest();</script>
michael@0 612
michael@0 613 </body>
michael@0 614 </html>

mercurial