1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/content/canvas/test/webgl-conformance/conformance/extensions/webgl-compressed-texture-etc1.html Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,506 @@ 1.4 +<!-- 1.5 + 1.6 +/* 1.7 +** Copyright (c) 2012 The Khronos Group Inc. 1.8 +** 1.9 +** Permission is hereby granted, free of charge, to any person obtaining a 1.10 +** copy of this software and/or associated documentation files (the 1.11 +** "Materials"), to deal in the Materials without restriction, including 1.12 +** without limitation the rights to use, copy, modify, merge, publish, 1.13 +** distribute, sublicense, and/or sell copies of the Materials, and to 1.14 +** permit persons to whom the Materials are furnished to do so, subject to 1.15 +** the following conditions: 1.16 +** 1.17 +** The above copyright notice and this permission notice shall be included 1.18 +** in all copies or substantial portions of the Materials. 1.19 +** 1.20 +** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 1.21 +** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1.22 +** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 1.23 +** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 1.24 +** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 1.25 +** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 1.26 +** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. 1.27 +*/ 1.28 + 1.29 +--> 1.30 + 1.31 +<!DOCTYPE html> 1.32 +<html> 1.33 +<head> 1.34 +<meta charset="utf-8"> 1.35 +<link rel="stylesheet" href="../../resources/js-test-style.css"/> 1.36 +<script src="../../resources/js-test-pre.js"></script> 1.37 +<script src="../resources/webgl-test.js"></script> 1.38 +<script src="../resources/webgl-test-utils.js"></script> 1.39 +<title>WebGL WEBGL_compressed_texture_etc1 Conformance Tests</title> 1.40 +<style> 1.41 +img { 1.42 + border: 1px solid black; 1.43 + margin-right: 1em; 1.44 +} 1.45 +.testimages { 1.46 +} 1.47 + 1.48 +.testimages br { 1.49 + clear: both; 1.50 +} 1.51 + 1.52 +.testimages > div { 1.53 + float: left; 1.54 + margin: 1em; 1.55 +} 1.56 +</style> 1.57 +</head> 1.58 +<body> 1.59 +<div id="description"></div> 1.60 +<canvas id="canvas" width="8" height="8" style="width: 8px; height: 8px;"></canvas> 1.61 +<div id="console"></div> 1.62 +<script> 1.63 +"use strict"; 1.64 +description("This test verifies the functionality of the WEBGL_compressed_texture_etc1 extension, if it is available."); 1.65 + 1.66 +debug(""); 1.67 + 1.68 +var img_4x4_rgb_etc1 = new Uint8Array([ 1.69 + 0x00, 0xc0, 0x00, 0xff, 0x07, 0x45, 0x07, 0x45 1.70 +]); 1.71 +var img_8x8_rgb_etc1 = new Uint8Array([ 1.72 + 0x00, 0xff, 0x55, 0xfc, 0xff, 0xff, 0x07, 0x45, 1.73 + 0x11, 0x11, 0xff, 0xfc, 0xf8, 0xba, 0x07, 0x45, 1.74 + 0xee, 0x00, 0xee, 0xfc, 0x07, 0x45, 0x07, 0x45, 1.75 + 0x00, 0x90, 0xf8, 0x92, 0x07, 0x45, 0xff, 0xff, 1.76 +]); 1.77 + 1.78 +var wtu = WebGLTestUtils; 1.79 +var canvas = document.getElementById("canvas"); 1.80 +var gl = wtu.create3DContext(canvas, {antialias: false}); 1.81 +var program = wtu.setupTexturedQuad(gl); 1.82 +var ext = null; 1.83 +var vao = null; 1.84 +var validFormats = { 1.85 + COMPRESSED_RGB_ETC1_WEBGL : 0x8D64 1.86 +}; 1.87 +var name; 1.88 +var supportedFormats; 1.89 + 1.90 +if (!gl) { 1.91 + testFailed("WebGL context does not exist"); 1.92 +} else { 1.93 + testPassed("WebGL context exists"); 1.94 + 1.95 + // Run tests with extension disabled 1.96 + runTestDisabled(); 1.97 + 1.98 + // Query the extension and store globally so shouldBe can access it 1.99 + ext = wtu.getExtensionWithKnownPrefixes(gl, "WEBGL_compressed_texture_etc1"); 1.100 + if (!ext) { 1.101 + testPassed("No WEBGL_compressed_texture_etc1 support -- this is legal"); 1.102 + runSupportedTest(false); 1.103 + } else { 1.104 + testPassed("Successfully enabled WEBGL_compressed_texture_etc1 extension"); 1.105 + 1.106 + runSupportedTest(true); 1.107 + runTestExtension(); 1.108 + } 1.109 +} 1.110 + 1.111 +function runSupportedTest(extensionEnabled) { 1.112 + var name = wtu.getSupportedExtensionWithKnownPrefixes(gl, "WEBGL_compressed_texture_etc1"); 1.113 + if (name !== undefined) { 1.114 + if (extensionEnabled) { 1.115 + testPassed("WEBGL_compressed_texture_etc1 listed as supported and getExtension succeeded"); 1.116 + } else { 1.117 + testFailed("WEBGL_compressed_texture_etc1 listed as supported but getExtension failed"); 1.118 + } 1.119 + } else { 1.120 + if (extensionEnabled) { 1.121 + testFailed("WEBGL_compressed_texture_etc1 not listed as supported but getExtension succeeded"); 1.122 + } else { 1.123 + testPassed("WEBGL_compressed_texture_etc1 not listed as supported and getExtension failed -- this is legal"); 1.124 + } 1.125 + } 1.126 +} 1.127 + 1.128 + 1.129 +function runTestDisabled() { 1.130 + debug("Testing binding enum with extension disabled"); 1.131 + 1.132 + shouldBe('gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS)', '[]'); 1.133 +} 1.134 + 1.135 +function formatExists(format, supportedFormats) { 1.136 + for (var ii = 0; ii < supportedFormats.length; ++ii) { 1.137 + if (format == supportedFormats[ii]) { 1.138 + testPassed("supported format " + formatToString(format) + " is exists"); 1.139 + return; 1.140 + } 1.141 + } 1.142 + testFailed("supported format " + formatToString(format) + " does not exist"); 1.143 +} 1.144 + 1.145 +function formatToString(format) { 1.146 + for (var p in ext) { 1.147 + if (ext[p] == format) { 1.148 + return p; 1.149 + } 1.150 + } 1.151 + return "0x" + format.toString(16); 1.152 +} 1.153 + 1.154 +function runTestExtension() { 1.155 + debug("Testing WEBGL_compressed_texture_etc1"); 1.156 + 1.157 + // check that all format enums exist. 1.158 + for (name in validFormats) { 1.159 + var expected = "0x" + validFormats[name].toString(16); 1.160 + var actual = "ext['" + name + "']"; 1.161 + shouldBe(actual, expected); 1.162 + } 1.163 + 1.164 + supportedFormats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS); 1.165 + // There should be exactly 4 formats 1.166 + shouldBe("supportedFormats.length", "1"); 1.167 + 1.168 + // check that all 4 formats exist 1.169 + for (var name in validFormats.length) { 1.170 + formatExists(validFormats[name], supportedFormats); 1.171 + } 1.172 + 1.173 + // Test each format 1.174 + testETC1_RGB(); 1.175 +} 1.176 + 1.177 +function testETC1_RGB() { 1.178 + var tests = [ 1.179 + { width: 4, 1.180 + height: 4, 1.181 + channels: 3, 1.182 + data: img_4x4_rgb_etc1, 1.183 + format: ext.COMPRESSED_RGB_ETC1_WEBGL 1.184 + }, 1.185 + { width: 8, 1.186 + height: 8, 1.187 + channels: 3, 1.188 + data: img_8x8_rgb_etc1, 1.189 + format: ext.COMPRESSED_RGB_ETC1_WEBGL 1.190 + } 1.191 + ]; 1.192 + testETCTextures(tests); 1.193 +} 1.194 + 1.195 +function testETCTextures(tests) { 1.196 + for (var ii = 0; ii < tests.length; ++ii) { 1.197 + debug("<hr/>"); 1.198 + testETCTexture(tests[ii]); 1.199 + } 1.200 +} 1.201 + 1.202 +function offset_color(c, o) { 1.203 + return [ 1.204 + Math.min(Math.max(0, c[0] + o), 255), 1.205 + Math.min(Math.max(0, c[1] + o), 255), 1.206 + Math.min(Math.max(0, c[2] + o), 255), 1.207 + c[3] 1.208 + ]; 1.209 +} 1.210 + 1.211 +function uncompressETC1Block(destBuffer, destX, destY, destWidth, src) { 1.212 + 'use strict'; 1.213 + var xx, yy, basecols; 1.214 + var _deltatable = [ 0, 1, 2, 3, -4, -3, -2, -1 ]; 1.215 + var _modtable = [ 1.216 + [ 2, 8, -2, -8 ], 1.217 + [ 5, 17, -5, -17 ], 1.218 + [ 9, 29, -9, -29 ], 1.219 + [ 13, 42, -13, -42 ], 1.220 + [ 18, 60, -18, -60 ], 1.221 + [ 24, 80, -24, -80 ], 1.222 + [ 33, 106, -33, -106 ], 1.223 + [ 47, 183, -47, -183 ] 1.224 + ]; 1.225 + var _sl = [ 1.226 + 0x00, 0x01, 0x04, 0x05, 1.227 + 0x10, 0x11, 0x14, 0x15, 1.228 + 0x40, 0x41, 0x44, 0x45, 1.229 + 0x50, 0x51, 0x54, 0x55 1.230 + ]; 1.231 + var _sh = [ 1.232 + 0x00, 0x02, 0x08, 0x0a, 1.233 + 0x20, 0x22, 0x28, 0x2a, 1.234 + 0x80, 0x82, 0x88, 0x8a, 1.235 + 0xa0, 0xa2, 0xa8, 0xaa 1.236 + ]; 1.237 + 1.238 + function extend_4to8bits(r, g, b) { 1.239 + return [ 1.240 + (r & 0xf0) | ((r >> 4) & 0x0f), 1.241 + (g & 0xf0) | ((g >> 4) & 0x0f), 1.242 + (b & 0xf0) | ((b >> 4) & 0x0f), 1.243 + 255 1.244 + ]; 1.245 + } 1.246 + 1.247 + function extend_5to8bits(r, g, b) { 1.248 + return [ 1.249 + (r & 0xf8) | ((r >> 5) & 0x07), 1.250 + (g & 0xf8) | ((g >> 5) & 0x07), 1.251 + (b & 0xf8) | ((b >> 5) & 0x07), 1.252 + 255 1.253 + ]; 1.254 + } 1.255 + 1.256 + function base_colors(src, mode) { 1.257 + var col_1, col_2, didx, d; 1.258 + if (mode === 'I') { 1.259 + col_1 = extend_4to8bits(src[0], src[1], src[2]); 1.260 + col_2 = extend_4to8bits(src[0] << 4, src[1] << 4, src[2] << 4); 1.261 + return [ col_1, col_2 ]; 1.262 + } 1.263 + 1.264 + if (mode === 'D') { 1.265 + col_1 = extend_5to8bits(src[0], src[1], src[2]); 1.266 + col_2 = extend_5to8bits(src[0] + 8 * _deltatable[(src[0] & 0x7)], 1.267 + src[1] + 8 * _deltatable[(src[1] & 0x7)], 1.268 + src[2] + 8 * _deltatable[(src[2] & 0x7)]); 1.269 + return [ col_1, col_2 ]; 1.270 + } 1.271 + 1.272 + return []; 1.273 + } 1.274 + 1.275 + function mode(src) { 1.276 + return (src[3] & 0x2) ? 'D' : 'I'; 1.277 + } 1.278 + 1.279 + function flip(src) { 1.280 + return (src[3] & 0x1) === 0x1; 1.281 + } 1.282 + 1.283 + function subblock_modtable(src, sb) { 1.284 + var shift = (sb ? 2 : 5); 1.285 + var idx = (src[3] >> shift) & 0x7; 1.286 + return _modtable[idx]; 1.287 + } 1.288 + 1.289 + function interleave_table_indices(src) { 1.290 + var result = 1.291 + (_sl[src[7] & 0xf] | _sh[src[5] & 0xf]) | 1.292 + ((_sl[(src[7] >> 4) & 0xf] | _sh[(src[5] >> 4) & 0xf]) << 8) | 1.293 + ((_sl[src[6] & 0xf] | _sh[src[4] & 0xf]) << 16) | 1.294 + ((_sl[(src[6] >> 4) & 0xf] | _sh[(src[4] >> 4) & 0xf]) << 24); 1.295 + return result; 1.296 + } 1.297 + 1.298 + function subblock(n, flip) { 1.299 + var mask = flip ? 0x2 : 0x8; 1.300 + return (n & mask) ? 1 : 0; 1.301 + } 1.302 + 1.303 + var m = mode(src); 1.304 + basecols = base_colors(src, m); 1.305 + 1.306 + var alpha = 255; 1.307 + var flipbit = flip(src); 1.308 + var table_indices = interleave_table_indices(src); 1.309 + 1.310 + var n = 0; 1.311 + for (xx = 0; xx < 4; ++xx) { 1.312 + for (yy = 0; yy < 4; ++yy) { 1.313 + var dstOff = ((destY + yy) * destWidth + destX + xx) * 4; 1.314 + 1.315 + var sb = subblock(n, flipbit); 1.316 + var mod = subblock_modtable(src, sb); 1.317 + var offset = mod[(table_indices & 0x3)]; 1.318 + var col = offset_color(basecols[sb], offset); 1.319 + 1.320 + destBuffer[dstOff] = col[0]; 1.321 + destBuffer[dstOff + 1] = col[1]; 1.322 + destBuffer[dstOff + 2] = col[2]; 1.323 + destBuffer[dstOff + 3] = alpha; 1.324 + table_indices >>= 2; 1.325 + n++; 1.326 + } 1.327 + } 1.328 +} 1.329 + 1.330 +function uncompressETC1(width, height, data, format) { 1.331 + if (width % 4 || height % 4) throw "bad width or height"; 1.332 + 1.333 + var dest = new Uint8Array(width * height * 4); 1.334 + var blocksAcross = width / 4; 1.335 + var blocksDown = height / 4; 1.336 + var blockSize = 8; 1.337 + for (var yy = 0; yy < blocksDown; ++yy) { 1.338 + for (var xx = 0; xx < blocksAcross; ++xx) { 1.339 + var srcOffset = (yy * blocksAcross + xx) * blockSize; 1.340 + var srcblk = data.subarray(srcOffset, srcOffset + blockSize); 1.341 + uncompressETC1Block(dest, xx * 4, yy * 4, width, srcblk); 1.342 + } 1.343 + } 1.344 + return dest; 1.345 +} 1.346 + 1.347 +function testETCTexture(test) { 1.348 + var data = new Uint8Array(test.data); 1.349 + var width = test.width; 1.350 + var height = test.height; 1.351 + var format = test.format; 1.352 + 1.353 + var uncompressedData = uncompressETC1(width, height, data, format); 1.354 + 1.355 + canvas.width = width; 1.356 + canvas.height = height; 1.357 + gl.viewport(0, 0, width, height); 1.358 + debug("testing " + formatToString(format) + " " + width + "x" + height); 1.359 + 1.360 + var tex = gl.createTexture(); 1.361 + gl.bindTexture(gl.TEXTURE_2D, tex); 1.362 + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 1.363 + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 1.364 + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); 1.365 + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); 1.366 + gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, data); 1.367 + glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture"); 1.368 + gl.generateMipmap(gl.TEXTURE_2D); 1.369 + glErrorShouldBe(gl, gl.INVALID_OPERATION, "trying to generate mipmaps from compressed texture"); 1.370 + wtu.clearAndDrawUnitQuad(gl); 1.371 + compareRect(width, height, test.channels, width, height, uncompressedData, data, format); 1.372 + 1.373 + gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 1, data); 1.374 + glErrorShouldBe(gl, gl.INVALID_VALUE, "non 0 border"); 1.375 + 1.376 + gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width + 4, height, 0, data); 1.377 + glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions"); 1.378 + gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height + 4, 0, data); 1.379 + glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions"); 1.380 + gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 4, height, 0, data); 1.381 + glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions"); 1.382 + gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 4, 0, data); 1.383 + glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions"); 1.384 + 1.385 + gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 1, height, 0, data); 1.386 + glErrorShouldBe(gl, gl.NO_ERROR, "non multiple-of-4 supported"); 1.387 + gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 2, height, 0, data); 1.388 + glErrorShouldBe(gl, gl.NO_ERROR, "non multiple-of-4 supported"); 1.389 + gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 1, 0, data); 1.390 + glErrorShouldBe(gl, gl.NO_ERROR, "non multiple-of-4 supported"); 1.391 + gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 2, 0, data); 1.392 + glErrorShouldBe(gl, gl.NO_ERROR, "non multiple-of-4 supported"); 1.393 + 1.394 + if (width == 4) { 1.395 + gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, 1, height, 0, data); 1.396 + glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0"); 1.397 + gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, 2, height, 0, data); 1.398 + glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0"); 1.399 + } 1.400 + if (height == 4) { 1.401 + gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, width, 1, 0, data); 1.402 + glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0"); 1.403 + gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, width, 2, 0, data); 1.404 + glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0"); 1.405 + } 1.406 + 1.407 + // Reupload the complete texture before SubImage tests. 1.408 + gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, data); 1.409 + glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture"); 1.410 + 1.411 + /* OES_compressed_ETC1_RGB8_texture: 1.412 + * INVALID_OPERATION is generated by CompressedTexSubImage2D, 1.413 + * TexSubImage2D, or CopyTexSubImage2D if the texture image 1.414 + * <level> bound to <target> has internal format ETC1_RGB8_OES. 1.415 + */ 1.416 + gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, format, data); 1.417 + glErrorShouldBe(gl, gl.INVALID_OPERATION, "ETC1 should not support compressedTexSubImage2D."); 1.418 +} 1.419 + 1.420 +function insertImg(element, caption, img) { 1.421 + var div = document.createElement("div"); 1.422 + div.appendChild(img); 1.423 + var label = document.createElement("div"); 1.424 + label.appendChild(document.createTextNode(caption)); 1.425 + div.appendChild(label); 1.426 + element.appendChild(div); 1.427 +} 1.428 + 1.429 +function makeImage(imageWidth, imageHeight, dataWidth, data, alpha) { 1.430 + var scale = 8; 1.431 + var c = document.createElement("canvas"); 1.432 + c.width = imageWidth * scale; 1.433 + c.height = imageHeight * scale; 1.434 + var ctx = c.getContext("2d"); 1.435 + for (var yy = 0; yy < imageHeight; ++yy) { 1.436 + for (var xx = 0; xx < imageWidth; ++xx) { 1.437 + var offset = (yy * dataWidth + xx) * 4; 1.438 + ctx.fillStyle = "rgba(" + 1.439 + data[offset + 0] + "," + 1.440 + data[offset + 1] + "," + 1.441 + data[offset + 2] + "," + 1.442 + (alpha ? data[offset + 3] / 255 : 1) + ")"; 1.443 + ctx.fillRect(xx * scale, yy * scale, scale, scale); 1.444 + } 1.445 + } 1.446 + var img = document.createElement("img"); 1.447 + img.src = c.toDataURL(); 1.448 + return img; 1.449 +} 1.450 + 1.451 +function compareRect(actualWidth, actualHeight, actualChannels, 1.452 + dataWidth, dataHeight, expectedData, 1.453 + testData, testFormat) 1.454 +{ 1.455 + var actual = new Uint8Array(actualWidth * actualHeight * 4); 1.456 + gl.readPixels(0, 0, actualWidth, actualHeight, 1.457 + gl.RGBA, gl.UNSIGNED_BYTE, actual); 1.458 + 1.459 + var div = document.createElement("div"); 1.460 + div.className = "testimages"; 1.461 + insertImg(div, "expected", makeImage( 1.462 + actualWidth, actualHeight, dataWidth, expectedData, 1.463 + actualChannels == 4)); 1.464 + insertImg(div, "actual", makeImage( 1.465 + actualWidth, actualHeight, actualWidth, actual, 1.466 + actualChannels == 4)); 1.467 + div.appendChild(document.createElement('br')); 1.468 + document.getElementById("console").appendChild(div); 1.469 + 1.470 + var failed = false; 1.471 + for (var yy = 0; yy < actualHeight; ++yy) { 1.472 + for (var xx = 0; xx < actualWidth; ++xx) { 1.473 + var actualOffset = (yy * actualWidth + xx) * 4; 1.474 + var expectedOffset = (yy * dataWidth + xx) * 4; 1.475 + var expected = [ 1.476 + expectedData[expectedOffset + 0], 1.477 + expectedData[expectedOffset + 1], 1.478 + expectedData[expectedOffset + 2], 1.479 + (actualChannels == 3 ? 255 1.480 + : expectedData[expectedOffset + 3]) 1.481 + ]; 1.482 + 1.483 + if (actual[actualOffset + 0] != expected[0] || 1.484 + actual[actualOffset + 1] != expected[1] || 1.485 + actual[actualOffset + 2] != expected[2] || 1.486 + actual[actualOffset + 3] != expected[3]) 1.487 + { 1.488 + failed = true; 1.489 + var was = actual[actualOffset + 0].toString(); 1.490 + for (var j = 1; j < 4; ++j) { 1.491 + was += "," + actual[actualOffset + j]; 1.492 + } 1.493 + testFailed('at (' + xx + ', ' + yy + 1.494 + ') expected: ' + expected + ' was ' + was); 1.495 + } 1.496 + } 1.497 + } 1.498 + if (!failed) { 1.499 + testPassed("texture rendered correctly"); 1.500 + } 1.501 +} 1.502 + 1.503 +debug(""); 1.504 +var successfullyParsed = true; 1.505 +</script> 1.506 +<script>finishTest();</script> 1.507 + 1.508 +</body> 1.509 +</html>