Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
michael@0 | 1 | <!-- |
michael@0 | 2 | |
michael@0 | 3 | /* |
michael@0 | 4 | ** Copyright (c) 2012 The Khronos Group Inc. |
michael@0 | 5 | ** |
michael@0 | 6 | ** Permission is hereby granted, free of charge, to any person obtaining a |
michael@0 | 7 | ** copy of this software and/or associated documentation files (the |
michael@0 | 8 | ** "Materials"), to deal in the Materials without restriction, including |
michael@0 | 9 | ** without limitation the rights to use, copy, modify, merge, publish, |
michael@0 | 10 | ** distribute, sublicense, and/or sell copies of the Materials, and to |
michael@0 | 11 | ** permit persons to whom the Materials are furnished to do so, subject to |
michael@0 | 12 | ** the following conditions: |
michael@0 | 13 | ** |
michael@0 | 14 | ** The above copyright notice and this permission notice shall be included |
michael@0 | 15 | ** in all copies or substantial portions of the Materials. |
michael@0 | 16 | ** |
michael@0 | 17 | ** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
michael@0 | 18 | ** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
michael@0 | 19 | ** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
michael@0 | 20 | ** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY |
michael@0 | 21 | ** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, |
michael@0 | 22 | ** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE |
michael@0 | 23 | ** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. |
michael@0 | 24 | */ |
michael@0 | 25 | |
michael@0 | 26 | --> |
michael@0 | 27 | |
michael@0 | 28 | <!DOCTYPE html> |
michael@0 | 29 | <html> |
michael@0 | 30 | <head> |
michael@0 | 31 | <meta charset="utf-8"> |
michael@0 | 32 | <link rel="stylesheet" href="../../resources/js-test-style.css"/> |
michael@0 | 33 | <script src="../../resources/js-test-pre.js"></script> |
michael@0 | 34 | <script src="../resources/webgl-test.js"></script> |
michael@0 | 35 | <script src="../resources/webgl-test-utils.js"></script> |
michael@0 | 36 | <title>WebGL WEBGL_compressed_texture_etc1 Conformance Tests</title> |
michael@0 | 37 | <style> |
michael@0 | 38 | img { |
michael@0 | 39 | border: 1px solid black; |
michael@0 | 40 | margin-right: 1em; |
michael@0 | 41 | } |
michael@0 | 42 | .testimages { |
michael@0 | 43 | } |
michael@0 | 44 | |
michael@0 | 45 | .testimages br { |
michael@0 | 46 | clear: both; |
michael@0 | 47 | } |
michael@0 | 48 | |
michael@0 | 49 | .testimages > div { |
michael@0 | 50 | float: left; |
michael@0 | 51 | margin: 1em; |
michael@0 | 52 | } |
michael@0 | 53 | </style> |
michael@0 | 54 | </head> |
michael@0 | 55 | <body> |
michael@0 | 56 | <div id="description"></div> |
michael@0 | 57 | <canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas> |
michael@0 | 58 | <div id="console"></div> |
michael@0 | 59 | <script> |
michael@0 | 60 | "use strict"; |
michael@0 | 61 | description("This test verifies the functionality of the WEBGL_compressed_texture_etc1 extension, if it is available."); |
michael@0 | 62 | |
michael@0 | 63 | debug(""); |
michael@0 | 64 | |
michael@0 | 65 | var img_4x4_rgb_etc1 = new Uint8Array([ |
michael@0 | 66 | 0x00, 0xc0, 0x00, 0xff, 0x07, 0x45, 0x07, 0x45 |
michael@0 | 67 | ]); |
michael@0 | 68 | var img_8x8_rgb_etc1 = new Uint8Array([ |
michael@0 | 69 | 0x00, 0xff, 0x55, 0xfc, 0xff, 0xff, 0x07, 0x45, |
michael@0 | 70 | 0x11, 0x11, 0xff, 0xfc, 0xf8, 0xba, 0x07, 0x45, |
michael@0 | 71 | 0xee, 0x00, 0xee, 0xfc, 0x07, 0x45, 0x07, 0x45, |
michael@0 | 72 | 0x00, 0x90, 0xf8, 0x92, 0x07, 0x45, 0xff, 0xff, |
michael@0 | 73 | ]); |
michael@0 | 74 | |
michael@0 | 75 | var wtu = WebGLTestUtils; |
michael@0 | 76 | var canvas = document.getElementById("canvas"); |
michael@0 | 77 | var gl = wtu.create3DContext(canvas, {antialias: false}); |
michael@0 | 78 | var program = wtu.setupTexturedQuad(gl); |
michael@0 | 79 | var ext = null; |
michael@0 | 80 | var vao = null; |
michael@0 | 81 | var validFormats = { |
michael@0 | 82 | COMPRESSED_RGB_ETC1_WEBGL : 0x8D64 |
michael@0 | 83 | }; |
michael@0 | 84 | var name; |
michael@0 | 85 | var supportedFormats; |
michael@0 | 86 | |
michael@0 | 87 | if (!gl) { |
michael@0 | 88 | testFailed("WebGL context does not exist"); |
michael@0 | 89 | } else { |
michael@0 | 90 | testPassed("WebGL context exists"); |
michael@0 | 91 | |
michael@0 | 92 | // Run tests with extension disabled |
michael@0 | 93 | runTestDisabled(); |
michael@0 | 94 | |
michael@0 | 95 | // Query the extension and store globally so shouldBe can access it |
michael@0 | 96 | ext = wtu.getExtensionWithKnownPrefixes(gl, "WEBGL_compressed_texture_etc1"); |
michael@0 | 97 | if (!ext) { |
michael@0 | 98 | testPassed("No WEBGL_compressed_texture_etc1 support -- this is legal"); |
michael@0 | 99 | runSupportedTest(false); |
michael@0 | 100 | } else { |
michael@0 | 101 | testPassed("Successfully enabled WEBGL_compressed_texture_etc1 extension"); |
michael@0 | 102 | |
michael@0 | 103 | runSupportedTest(true); |
michael@0 | 104 | runTestExtension(); |
michael@0 | 105 | } |
michael@0 | 106 | } |
michael@0 | 107 | |
michael@0 | 108 | function runSupportedTest(extensionEnabled) { |
michael@0 | 109 | var name = wtu.getSupportedExtensionWithKnownPrefixes(gl, "WEBGL_compressed_texture_etc1"); |
michael@0 | 110 | if (name !== undefined) { |
michael@0 | 111 | if (extensionEnabled) { |
michael@0 | 112 | testPassed("WEBGL_compressed_texture_etc1 listed as supported and getExtension succeeded"); |
michael@0 | 113 | } else { |
michael@0 | 114 | testFailed("WEBGL_compressed_texture_etc1 listed as supported but getExtension failed"); |
michael@0 | 115 | } |
michael@0 | 116 | } else { |
michael@0 | 117 | if (extensionEnabled) { |
michael@0 | 118 | testFailed("WEBGL_compressed_texture_etc1 not listed as supported but getExtension succeeded"); |
michael@0 | 119 | } else { |
michael@0 | 120 | testPassed("WEBGL_compressed_texture_etc1 not listed as supported and getExtension failed -- this is legal"); |
michael@0 | 121 | } |
michael@0 | 122 | } |
michael@0 | 123 | } |
michael@0 | 124 | |
michael@0 | 125 | |
michael@0 | 126 | function runTestDisabled() { |
michael@0 | 127 | debug("Testing binding enum with extension disabled"); |
michael@0 | 128 | |
michael@0 | 129 | shouldBe('gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS)', '[]'); |
michael@0 | 130 | } |
michael@0 | 131 | |
michael@0 | 132 | function formatExists(format, supportedFormats) { |
michael@0 | 133 | for (var ii = 0; ii < supportedFormats.length; ++ii) { |
michael@0 | 134 | if (format == supportedFormats[ii]) { |
michael@0 | 135 | testPassed("supported format " + formatToString(format) + " is exists"); |
michael@0 | 136 | return; |
michael@0 | 137 | } |
michael@0 | 138 | } |
michael@0 | 139 | testFailed("supported format " + formatToString(format) + " does not exist"); |
michael@0 | 140 | } |
michael@0 | 141 | |
michael@0 | 142 | function formatToString(format) { |
michael@0 | 143 | for (var p in ext) { |
michael@0 | 144 | if (ext[p] == format) { |
michael@0 | 145 | return p; |
michael@0 | 146 | } |
michael@0 | 147 | } |
michael@0 | 148 | return "0x" + format.toString(16); |
michael@0 | 149 | } |
michael@0 | 150 | |
michael@0 | 151 | function runTestExtension() { |
michael@0 | 152 | debug("Testing WEBGL_compressed_texture_etc1"); |
michael@0 | 153 | |
michael@0 | 154 | // check that all format enums exist. |
michael@0 | 155 | for (name in validFormats) { |
michael@0 | 156 | var expected = "0x" + validFormats[name].toString(16); |
michael@0 | 157 | var actual = "ext['" + name + "']"; |
michael@0 | 158 | shouldBe(actual, expected); |
michael@0 | 159 | } |
michael@0 | 160 | |
michael@0 | 161 | supportedFormats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS); |
michael@0 | 162 | // There should be exactly 4 formats |
michael@0 | 163 | shouldBe("supportedFormats.length", "1"); |
michael@0 | 164 | |
michael@0 | 165 | // check that all 4 formats exist |
michael@0 | 166 | for (var name in validFormats.length) { |
michael@0 | 167 | formatExists(validFormats[name], supportedFormats); |
michael@0 | 168 | } |
michael@0 | 169 | |
michael@0 | 170 | // Test each format |
michael@0 | 171 | testETC1_RGB(); |
michael@0 | 172 | } |
michael@0 | 173 | |
michael@0 | 174 | function testETC1_RGB() { |
michael@0 | 175 | var tests = [ |
michael@0 | 176 | { width: 4, |
michael@0 | 177 | height: 4, |
michael@0 | 178 | channels: 3, |
michael@0 | 179 | data: img_4x4_rgb_etc1, |
michael@0 | 180 | format: ext.COMPRESSED_RGB_ETC1_WEBGL |
michael@0 | 181 | }, |
michael@0 | 182 | { width: 8, |
michael@0 | 183 | height: 8, |
michael@0 | 184 | channels: 3, |
michael@0 | 185 | data: img_8x8_rgb_etc1, |
michael@0 | 186 | format: ext.COMPRESSED_RGB_ETC1_WEBGL |
michael@0 | 187 | } |
michael@0 | 188 | ]; |
michael@0 | 189 | testETCTextures(tests); |
michael@0 | 190 | } |
michael@0 | 191 | |
michael@0 | 192 | function testETCTextures(tests) { |
michael@0 | 193 | for (var ii = 0; ii < tests.length; ++ii) { |
michael@0 | 194 | debug("<hr/>"); |
michael@0 | 195 | testETCTexture(tests[ii]); |
michael@0 | 196 | } |
michael@0 | 197 | } |
michael@0 | 198 | |
michael@0 | 199 | function offset_color(c, o) { |
michael@0 | 200 | return [ |
michael@0 | 201 | Math.min(Math.max(0, c[0] + o), 255), |
michael@0 | 202 | Math.min(Math.max(0, c[1] + o), 255), |
michael@0 | 203 | Math.min(Math.max(0, c[2] + o), 255), |
michael@0 | 204 | c[3] |
michael@0 | 205 | ]; |
michael@0 | 206 | } |
michael@0 | 207 | |
michael@0 | 208 | function uncompressETC1Block(destBuffer, destX, destY, destWidth, src) { |
michael@0 | 209 | 'use strict'; |
michael@0 | 210 | var xx, yy, basecols; |
michael@0 | 211 | var _deltatable = [ 0, 1, 2, 3, -4, -3, -2, -1 ]; |
michael@0 | 212 | var _modtable = [ |
michael@0 | 213 | [ 2, 8, -2, -8 ], |
michael@0 | 214 | [ 5, 17, -5, -17 ], |
michael@0 | 215 | [ 9, 29, -9, -29 ], |
michael@0 | 216 | [ 13, 42, -13, -42 ], |
michael@0 | 217 | [ 18, 60, -18, -60 ], |
michael@0 | 218 | [ 24, 80, -24, -80 ], |
michael@0 | 219 | [ 33, 106, -33, -106 ], |
michael@0 | 220 | [ 47, 183, -47, -183 ] |
michael@0 | 221 | ]; |
michael@0 | 222 | var _sl = [ |
michael@0 | 223 | 0x00, 0x01, 0x04, 0x05, |
michael@0 | 224 | 0x10, 0x11, 0x14, 0x15, |
michael@0 | 225 | 0x40, 0x41, 0x44, 0x45, |
michael@0 | 226 | 0x50, 0x51, 0x54, 0x55 |
michael@0 | 227 | ]; |
michael@0 | 228 | var _sh = [ |
michael@0 | 229 | 0x00, 0x02, 0x08, 0x0a, |
michael@0 | 230 | 0x20, 0x22, 0x28, 0x2a, |
michael@0 | 231 | 0x80, 0x82, 0x88, 0x8a, |
michael@0 | 232 | 0xa0, 0xa2, 0xa8, 0xaa |
michael@0 | 233 | ]; |
michael@0 | 234 | |
michael@0 | 235 | function extend_4to8bits(r, g, b) { |
michael@0 | 236 | return [ |
michael@0 | 237 | (r & 0xf0) | ((r >> 4) & 0x0f), |
michael@0 | 238 | (g & 0xf0) | ((g >> 4) & 0x0f), |
michael@0 | 239 | (b & 0xf0) | ((b >> 4) & 0x0f), |
michael@0 | 240 | 255 |
michael@0 | 241 | ]; |
michael@0 | 242 | } |
michael@0 | 243 | |
michael@0 | 244 | function extend_5to8bits(r, g, b) { |
michael@0 | 245 | return [ |
michael@0 | 246 | (r & 0xf8) | ((r >> 5) & 0x07), |
michael@0 | 247 | (g & 0xf8) | ((g >> 5) & 0x07), |
michael@0 | 248 | (b & 0xf8) | ((b >> 5) & 0x07), |
michael@0 | 249 | 255 |
michael@0 | 250 | ]; |
michael@0 | 251 | } |
michael@0 | 252 | |
michael@0 | 253 | function base_colors(src, mode) { |
michael@0 | 254 | var col_1, col_2, didx, d; |
michael@0 | 255 | if (mode === 'I') { |
michael@0 | 256 | col_1 = extend_4to8bits(src[0], src[1], src[2]); |
michael@0 | 257 | col_2 = extend_4to8bits(src[0] << 4, src[1] << 4, src[2] << 4); |
michael@0 | 258 | return [ col_1, col_2 ]; |
michael@0 | 259 | } |
michael@0 | 260 | |
michael@0 | 261 | if (mode === 'D') { |
michael@0 | 262 | col_1 = extend_5to8bits(src[0], src[1], src[2]); |
michael@0 | 263 | col_2 = extend_5to8bits(src[0] + 8 * _deltatable[(src[0] & 0x7)], |
michael@0 | 264 | src[1] + 8 * _deltatable[(src[1] & 0x7)], |
michael@0 | 265 | src[2] + 8 * _deltatable[(src[2] & 0x7)]); |
michael@0 | 266 | return [ col_1, col_2 ]; |
michael@0 | 267 | } |
michael@0 | 268 | |
michael@0 | 269 | return []; |
michael@0 | 270 | } |
michael@0 | 271 | |
michael@0 | 272 | function mode(src) { |
michael@0 | 273 | return (src[3] & 0x2) ? 'D' : 'I'; |
michael@0 | 274 | } |
michael@0 | 275 | |
michael@0 | 276 | function flip(src) { |
michael@0 | 277 | return (src[3] & 0x1) === 0x1; |
michael@0 | 278 | } |
michael@0 | 279 | |
michael@0 | 280 | function subblock_modtable(src, sb) { |
michael@0 | 281 | var shift = (sb ? 2 : 5); |
michael@0 | 282 | var idx = (src[3] >> shift) & 0x7; |
michael@0 | 283 | return _modtable[idx]; |
michael@0 | 284 | } |
michael@0 | 285 | |
michael@0 | 286 | function interleave_table_indices(src) { |
michael@0 | 287 | var result = |
michael@0 | 288 | (_sl[src[7] & 0xf] | _sh[src[5] & 0xf]) | |
michael@0 | 289 | ((_sl[(src[7] >> 4) & 0xf] | _sh[(src[5] >> 4) & 0xf]) << 8) | |
michael@0 | 290 | ((_sl[src[6] & 0xf] | _sh[src[4] & 0xf]) << 16) | |
michael@0 | 291 | ((_sl[(src[6] >> 4) & 0xf] | _sh[(src[4] >> 4) & 0xf]) << 24); |
michael@0 | 292 | return result; |
michael@0 | 293 | } |
michael@0 | 294 | |
michael@0 | 295 | function subblock(n, flip) { |
michael@0 | 296 | var mask = flip ? 0x2 : 0x8; |
michael@0 | 297 | return (n & mask) ? 1 : 0; |
michael@0 | 298 | } |
michael@0 | 299 | |
michael@0 | 300 | var m = mode(src); |
michael@0 | 301 | basecols = base_colors(src, m); |
michael@0 | 302 | |
michael@0 | 303 | var alpha = 255; |
michael@0 | 304 | var flipbit = flip(src); |
michael@0 | 305 | var table_indices = interleave_table_indices(src); |
michael@0 | 306 | |
michael@0 | 307 | var n = 0; |
michael@0 | 308 | for (xx = 0; xx < 4; ++xx) { |
michael@0 | 309 | for (yy = 0; yy < 4; ++yy) { |
michael@0 | 310 | var dstOff = ((destY + yy) * destWidth + destX + xx) * 4; |
michael@0 | 311 | |
michael@0 | 312 | var sb = subblock(n, flipbit); |
michael@0 | 313 | var mod = subblock_modtable(src, sb); |
michael@0 | 314 | var offset = mod[(table_indices & 0x3)]; |
michael@0 | 315 | var col = offset_color(basecols[sb], offset); |
michael@0 | 316 | |
michael@0 | 317 | destBuffer[dstOff] = col[0]; |
michael@0 | 318 | destBuffer[dstOff + 1] = col[1]; |
michael@0 | 319 | destBuffer[dstOff + 2] = col[2]; |
michael@0 | 320 | destBuffer[dstOff + 3] = alpha; |
michael@0 | 321 | table_indices >>= 2; |
michael@0 | 322 | n++; |
michael@0 | 323 | } |
michael@0 | 324 | } |
michael@0 | 325 | } |
michael@0 | 326 | |
michael@0 | 327 | function uncompressETC1(width, height, data, format) { |
michael@0 | 328 | if (width % 4 || height % 4) throw "bad width or height"; |
michael@0 | 329 | |
michael@0 | 330 | var dest = new Uint8Array(width * height * 4); |
michael@0 | 331 | var blocksAcross = width / 4; |
michael@0 | 332 | var blocksDown = height / 4; |
michael@0 | 333 | var blockSize = 8; |
michael@0 | 334 | for (var yy = 0; yy < blocksDown; ++yy) { |
michael@0 | 335 | for (var xx = 0; xx < blocksAcross; ++xx) { |
michael@0 | 336 | var srcOffset = (yy * blocksAcross + xx) * blockSize; |
michael@0 | 337 | var srcblk = data.subarray(srcOffset, srcOffset + blockSize); |
michael@0 | 338 | uncompressETC1Block(dest, xx * 4, yy * 4, width, srcblk); |
michael@0 | 339 | } |
michael@0 | 340 | } |
michael@0 | 341 | return dest; |
michael@0 | 342 | } |
michael@0 | 343 | |
michael@0 | 344 | function testETCTexture(test) { |
michael@0 | 345 | var data = new Uint8Array(test.data); |
michael@0 | 346 | var width = test.width; |
michael@0 | 347 | var height = test.height; |
michael@0 | 348 | var format = test.format; |
michael@0 | 349 | |
michael@0 | 350 | var uncompressedData = uncompressETC1(width, height, data, format); |
michael@0 | 351 | |
michael@0 | 352 | canvas.width = width; |
michael@0 | 353 | canvas.height = height; |
michael@0 | 354 | gl.viewport(0, 0, width, height); |
michael@0 | 355 | debug("testing " + formatToString(format) + " " + width + "x" + height); |
michael@0 | 356 | |
michael@0 | 357 | var tex = gl.createTexture(); |
michael@0 | 358 | gl.bindTexture(gl.TEXTURE_2D, tex); |
michael@0 | 359 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); |
michael@0 | 360 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); |
michael@0 | 361 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); |
michael@0 | 362 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); |
michael@0 | 363 | gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, data); |
michael@0 | 364 | glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture"); |
michael@0 | 365 | gl.generateMipmap(gl.TEXTURE_2D); |
michael@0 | 366 | glErrorShouldBe(gl, gl.INVALID_OPERATION, "trying to generate mipmaps from compressed texture"); |
michael@0 | 367 | wtu.clearAndDrawUnitQuad(gl); |
michael@0 | 368 | compareRect(width, height, test.channels, width, height, uncompressedData, data, format); |
michael@0 | 369 | |
michael@0 | 370 | gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 1, data); |
michael@0 | 371 | glErrorShouldBe(gl, gl.INVALID_VALUE, "non 0 border"); |
michael@0 | 372 | |
michael@0 | 373 | gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width + 4, height, 0, data); |
michael@0 | 374 | glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions"); |
michael@0 | 375 | gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height + 4, 0, data); |
michael@0 | 376 | glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions"); |
michael@0 | 377 | gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 4, height, 0, data); |
michael@0 | 378 | glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions"); |
michael@0 | 379 | gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 4, 0, data); |
michael@0 | 380 | glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions"); |
michael@0 | 381 | |
michael@0 | 382 | gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 1, height, 0, data); |
michael@0 | 383 | glErrorShouldBe(gl, gl.NO_ERROR, "non multiple-of-4 supported"); |
michael@0 | 384 | gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 2, height, 0, data); |
michael@0 | 385 | glErrorShouldBe(gl, gl.NO_ERROR, "non multiple-of-4 supported"); |
michael@0 | 386 | gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 1, 0, data); |
michael@0 | 387 | glErrorShouldBe(gl, gl.NO_ERROR, "non multiple-of-4 supported"); |
michael@0 | 388 | gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 2, 0, data); |
michael@0 | 389 | glErrorShouldBe(gl, gl.NO_ERROR, "non multiple-of-4 supported"); |
michael@0 | 390 | |
michael@0 | 391 | if (width == 4) { |
michael@0 | 392 | gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, 1, height, 0, data); |
michael@0 | 393 | glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0"); |
michael@0 | 394 | gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, 2, height, 0, data); |
michael@0 | 395 | glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0"); |
michael@0 | 396 | } |
michael@0 | 397 | if (height == 4) { |
michael@0 | 398 | gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, width, 1, 0, data); |
michael@0 | 399 | glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0"); |
michael@0 | 400 | gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, width, 2, 0, data); |
michael@0 | 401 | glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0"); |
michael@0 | 402 | } |
michael@0 | 403 | |
michael@0 | 404 | // Reupload the complete texture before SubImage tests. |
michael@0 | 405 | gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, data); |
michael@0 | 406 | glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture"); |
michael@0 | 407 | |
michael@0 | 408 | /* OES_compressed_ETC1_RGB8_texture: |
michael@0 | 409 | * INVALID_OPERATION is generated by CompressedTexSubImage2D, |
michael@0 | 410 | * TexSubImage2D, or CopyTexSubImage2D if the texture image |
michael@0 | 411 | * <level> bound to <target> has internal format ETC1_RGB8_OES. |
michael@0 | 412 | */ |
michael@0 | 413 | gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, format, data); |
michael@0 | 414 | glErrorShouldBe(gl, gl.INVALID_OPERATION, "ETC1 should not support compressedTexSubImage2D."); |
michael@0 | 415 | } |
michael@0 | 416 | |
michael@0 | 417 | function insertImg(element, caption, img) { |
michael@0 | 418 | var div = document.createElement("div"); |
michael@0 | 419 | div.appendChild(img); |
michael@0 | 420 | var label = document.createElement("div"); |
michael@0 | 421 | label.appendChild(document.createTextNode(caption)); |
michael@0 | 422 | div.appendChild(label); |
michael@0 | 423 | element.appendChild(div); |
michael@0 | 424 | } |
michael@0 | 425 | |
michael@0 | 426 | function makeImage(imageWidth, imageHeight, dataWidth, data, alpha) { |
michael@0 | 427 | var scale = 8; |
michael@0 | 428 | var c = document.createElement("canvas"); |
michael@0 | 429 | c.width = imageWidth * scale; |
michael@0 | 430 | c.height = imageHeight * scale; |
michael@0 | 431 | var ctx = c.getContext("2d"); |
michael@0 | 432 | for (var yy = 0; yy < imageHeight; ++yy) { |
michael@0 | 433 | for (var xx = 0; xx < imageWidth; ++xx) { |
michael@0 | 434 | var offset = (yy * dataWidth + xx) * 4; |
michael@0 | 435 | ctx.fillStyle = "rgba(" + |
michael@0 | 436 | data[offset + 0] + "," + |
michael@0 | 437 | data[offset + 1] + "," + |
michael@0 | 438 | data[offset + 2] + "," + |
michael@0 | 439 | (alpha ? data[offset + 3] / 255 : 1) + ")"; |
michael@0 | 440 | ctx.fillRect(xx * scale, yy * scale, scale, scale); |
michael@0 | 441 | } |
michael@0 | 442 | } |
michael@0 | 443 | var img = document.createElement("img"); |
michael@0 | 444 | img.src = c.toDataURL(); |
michael@0 | 445 | return img; |
michael@0 | 446 | } |
michael@0 | 447 | |
michael@0 | 448 | function compareRect(actualWidth, actualHeight, actualChannels, |
michael@0 | 449 | dataWidth, dataHeight, expectedData, |
michael@0 | 450 | testData, testFormat) |
michael@0 | 451 | { |
michael@0 | 452 | var actual = new Uint8Array(actualWidth * actualHeight * 4); |
michael@0 | 453 | gl.readPixels(0, 0, actualWidth, actualHeight, |
michael@0 | 454 | gl.RGBA, gl.UNSIGNED_BYTE, actual); |
michael@0 | 455 | |
michael@0 | 456 | var div = document.createElement("div"); |
michael@0 | 457 | div.className = "testimages"; |
michael@0 | 458 | insertImg(div, "expected", makeImage( |
michael@0 | 459 | actualWidth, actualHeight, dataWidth, expectedData, |
michael@0 | 460 | actualChannels == 4)); |
michael@0 | 461 | insertImg(div, "actual", makeImage( |
michael@0 | 462 | actualWidth, actualHeight, actualWidth, actual, |
michael@0 | 463 | actualChannels == 4)); |
michael@0 | 464 | div.appendChild(document.createElement('br')); |
michael@0 | 465 | document.getElementById("console").appendChild(div); |
michael@0 | 466 | |
michael@0 | 467 | var failed = false; |
michael@0 | 468 | for (var yy = 0; yy < actualHeight; ++yy) { |
michael@0 | 469 | for (var xx = 0; xx < actualWidth; ++xx) { |
michael@0 | 470 | var actualOffset = (yy * actualWidth + xx) * 4; |
michael@0 | 471 | var expectedOffset = (yy * dataWidth + xx) * 4; |
michael@0 | 472 | var expected = [ |
michael@0 | 473 | expectedData[expectedOffset + 0], |
michael@0 | 474 | expectedData[expectedOffset + 1], |
michael@0 | 475 | expectedData[expectedOffset + 2], |
michael@0 | 476 | (actualChannels == 3 ? 255 |
michael@0 | 477 | : expectedData[expectedOffset + 3]) |
michael@0 | 478 | ]; |
michael@0 | 479 | |
michael@0 | 480 | if (actual[actualOffset + 0] != expected[0] || |
michael@0 | 481 | actual[actualOffset + 1] != expected[1] || |
michael@0 | 482 | actual[actualOffset + 2] != expected[2] || |
michael@0 | 483 | actual[actualOffset + 3] != expected[3]) |
michael@0 | 484 | { |
michael@0 | 485 | failed = true; |
michael@0 | 486 | var was = actual[actualOffset + 0].toString(); |
michael@0 | 487 | for (var j = 1; j < 4; ++j) { |
michael@0 | 488 | was += "," + actual[actualOffset + j]; |
michael@0 | 489 | } |
michael@0 | 490 | testFailed('at (' + xx + ', ' + yy + |
michael@0 | 491 | ') expected: ' + expected + ' was ' + was); |
michael@0 | 492 | } |
michael@0 | 493 | } |
michael@0 | 494 | } |
michael@0 | 495 | if (!failed) { |
michael@0 | 496 | testPassed("texture rendered correctly"); |
michael@0 | 497 | } |
michael@0 | 498 | } |
michael@0 | 499 | |
michael@0 | 500 | debug(""); |
michael@0 | 501 | var successfullyParsed = true; |
michael@0 | 502 | </script> |
michael@0 | 503 | <script>finishTest();</script> |
michael@0 | 504 | |
michael@0 | 505 | </body> |
michael@0 | 506 | </html> |