test_webgl_compressed_texture_es3.html (25461B)
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <script src="/tests/SimpleTest/SimpleTest.js"></script> 6 <link rel="stylesheet" href="/tests/SimpleTest/test.css"> 7 <script src="webgl-util.js"></script> 8 <script src="es3-data.js"></script> 9 <title>WebGL test: test WEBGL_compressed_texture_etc extension</title> 10 <style> 11 img { 12 border: 1px solid black; 13 margin-right: 1em; 14 } 15 .testimages { 16 } 17 18 .testimages br { 19 clear: both; 20 } 21 22 .testimages > div { 23 float: left; 24 margin: 1em; 25 } 26 </style> 27 </head> 28 <body> 29 <div id="description"></div> 30 <canvas id="canvas" width="8" height="8"></canvas> 31 <div id="console"></div> 32 <script id="vshader" type="x-shader/x-vertex"> 33 attribute vec4 vPosition; 34 attribute vec2 texCoord0; 35 varying vec2 texCoord; 36 void main() { 37 gl_Position = vPosition; 38 texCoord = texCoord0; 39 } 40 </script> 41 <script id="fshader" type="x-shader/x-fragment"> 42 precision mediump float; 43 uniform sampler2D tex; 44 varying vec2 texCoord; 45 void main() { 46 gl_FragData[0] = texture2D(tex, texCoord); 47 } 48 </script> 49 <script id="fshader-r" type="x-shader/x-fragment"> 50 precision mediump float; 51 uniform sampler2D tex; 52 varying vec2 texCoord; 53 void main() { 54 vec4 pixel = (texture2D(tex, texCoord)); 55 pixel.r = (pixel.r + 1.0) / 2.0; 56 gl_FragData[0] = pixel; 57 } 58 </script> 59 <script id="fshader-rg" type="x-shader/x-fragment"> 60 precision mediump float; 61 uniform sampler2D tex; 62 varying vec2 texCoord; 63 void main() { 64 vec4 pixel = (texture2D(tex, texCoord)); 65 pixel.rg = (pixel.rg + 1.0) / 2.0; 66 gl_FragData[0] = pixel; 67 } 68 </script> 69 <script> 70 "use strict"; 71 var ext = null; 72 var vao = null; 73 var gl = null; 74 var validFormats = { 75 COMPRESSED_R11_EAC : 0x9270, 76 COMPRESSED_SIGNED_R11_EAC : 0x9271, 77 COMPRESSED_RG11_EAC : 0x9272, 78 COMPRESSED_SIGNED_RG11_EAC : 0x9273, 79 COMPRESSED_RGB8_ETC2 : 0x9274, 80 COMPRESSED_SRGB8_ETC2 : 0x9275, 81 COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 : 0x9276, 82 COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 : 0x9277, 83 COMPRESSED_RGBA8_ETC2_EAC : 0x9278, 84 COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : 0x9279, 85 }; 86 87 function setupUnitQuad() { 88 var vertexObject = gl.createBuffer(); 89 gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject); 90 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 91 1.0, 1.0, 0.0, 92 -1.0, 1.0, 0.0, 93 -1.0, -1.0, 0.0, 94 1.0, 1.0, 0.0, 95 -1.0, -1.0, 0.0, 96 1.0, -1.0, 0.0]), gl.STATIC_DRAW); 97 gl.enableVertexAttribArray(0); 98 gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0); 99 100 var vertexObject = gl.createBuffer(); 101 gl.bindBuffer(gl.ARRAY_BUFFER, vertexObject); 102 gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([ 103 1.0, 1.0, 104 0.0, 1.0, 105 0.0, 0.0, 106 1.0, 1.0, 107 0.0, 0.0, 108 1.0, 0.0]), gl.STATIC_DRAW); 109 gl.enableVertexAttribArray(1); 110 gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 0, 0); 111 } 112 113 function runTest() { 114 gl = canvas.getContext('webgl', {antialias: false}); 115 if (!gl) { 116 ok(false, "WebGL context does not exist"); 117 } else { 118 ok(true, "WebGL context exists"); 119 setupUnitQuad(); 120 121 // Run tests with extension disabled 122 runTestDisabled(); 123 124 // Query the extension and store globally so shouldBe can access it 125 ext = gl.getExtension("WEBGL_compressed_texture_etc"); 126 if (!ext) { 127 ok(true, "No WEBGL_compressed_texture_etc support -- this is legal"); 128 runSupportedTest(false); 129 } else { 130 ok(true, "Successfully enabled WEBGL_compressed_texture_etc extension"); 131 132 runSupportedTest(true); 133 runTestExtension(); 134 } 135 } 136 SimpleTest.finish(); 137 } 138 139 function runSupportedTest(extensionEnabled) { 140 var supported = gl.getSupportedExtensions(); 141 if (supported.includes("WEBGL_compressed_texture_etc")) { 142 if (extensionEnabled) { 143 ok(true, "WEBGL_compressed_texture_etc listed as supported and getExtension succeeded"); 144 } else { 145 ok(false, "WEBGL_compressed_texture_etc listed as supported but getExtension failed"); 146 } 147 } else { 148 if (extensionEnabled) { 149 ok(false, "WEBGL_compressed_texture_etc not listed as supported but getExtension succeeded"); 150 } else { 151 ok(true, "WEBGL_compressed_texture_etc not listed as supported and getExtension failed -- this is legal"); 152 } 153 } 154 } 155 156 function runTestDisabled() { 157 is(gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS).length, 0, 158 "Should be no compressed texture formats"); 159 } 160 161 function formatExists(format, supportedFormats) { 162 for (var ii = 0; ii < supportedFormats.length; ++ii) { 163 if (format == supportedFormats[ii]) { 164 ok(true, "supported format " + formatToString(format) + " is exists"); 165 return; 166 } 167 } 168 ok(false, "supported format " + formatToString(format) + " does not exist"); 169 } 170 171 function formatToString(format) { 172 for (var p in ext) { 173 if (ext[p] == format) { 174 return p; 175 } 176 } 177 return "0x" + format.toString(16); 178 } 179 180 function runTestExtension() { 181 // check that all format enums exist. 182 for (let name in validFormats) { 183 is(ext[name], validFormats[name], "format is match"); 184 } 185 186 let supportedFormats = gl.getParameter(gl.COMPRESSED_TEXTURE_FORMATS); 187 // There should be exactly 10 formats 188 is(supportedFormats.length, 10, "Should be exactly 10 formats"); 189 190 // check that all 10 formats exist 191 for (let name in validFormats.length) { 192 formatExists(validFormats[name], supportedFormats); 193 } 194 195 // Test each format 196 testETC2_RGB(); 197 } 198 199 function testETC2_RGB() { 200 var tests = [ 201 { 202 width: 4, 203 height: 4, 204 channels: 1, 205 data: img_4x4_r11_eac, 206 format: ext.COMPRESSED_R11_EAC 207 }, 208 { 209 width: 4, 210 height: 4, 211 channels: 1, 212 data: img_4x4_signed_r11_eac, 213 format: ext.COMPRESSED_SIGNED_R11_EAC 214 }, 215 { 216 width: 4, 217 height: 4, 218 channels: 2, 219 data: img_4x4_rg11_eac, 220 format: ext.COMPRESSED_RG11_EAC 221 }, 222 { 223 width: 4, 224 height: 4, 225 channels: 2, 226 data: img_4x4_signed_rg11_eac, 227 format: ext.COMPRESSED_SIGNED_RG11_EAC 228 }, 229 { 230 width: 4, 231 height: 4, 232 channels: 3, 233 data: img_4x4_rgb_etc2, 234 format: ext.COMPRESSED_RGB8_ETC2 235 }, 236 { 237 width: 4, 238 height: 4, 239 channels: 3, 240 data: img_4x4_rgb_etc2, 241 format: ext.COMPRESSED_SRGB8_ETC2 242 }, 243 { 244 width: 4, 245 height: 4, 246 channels: 4, 247 data: img_4x4_rgb_punchthrough_etc2, 248 format: ext.COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 249 }, 250 { 251 width: 4, 252 height: 4, 253 channels: 4, 254 data: img_4x4_rgb_punchthrough_etc2, 255 format: ext.COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 256 }, 257 { 258 width: 4, 259 height: 4, 260 channels: 4, 261 data: img_4x4_rgba_etc2, 262 format: ext.COMPRESSED_RGBA8_ETC2_EAC 263 }, 264 { 265 width: 4, 266 height: 4, 267 channels: 4, 268 data: img_4x4_rgba_etc2, 269 format: ext.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 270 }, 271 { 272 width: 8, 273 height: 8, 274 channels: 1, 275 data: img_8x8_r11_eac, 276 format: ext.COMPRESSED_R11_EAC 277 }, 278 { 279 width: 8, 280 height: 8, 281 channels: 1, 282 data: img_8x8_signed_r11_eac, 283 format: ext.COMPRESSED_SIGNED_R11_EAC 284 }, 285 { 286 width: 8, 287 height: 8, 288 channels: 2, 289 data: img_8x8_rg11_eac, 290 format: ext.COMPRESSED_RG11_EAC 291 }, 292 { 293 width: 8, 294 height: 8, 295 channels: 2, 296 data: img_8x8_signed_rg11_eac, 297 format: ext.COMPRESSED_SIGNED_RG11_EAC 298 }, 299 { 300 width: 8, 301 height: 8, 302 channels: 3, 303 data: img_8x8_rgb_etc2, 304 format: ext.COMPRESSED_RGB8_ETC2 305 }, 306 { 307 width: 8, 308 height: 8, 309 channels: 3, 310 data: img_8x8_rgb_etc2, 311 format: ext.COMPRESSED_SRGB8_ETC2 312 }, 313 { 314 width: 8, 315 height: 8, 316 channels: 4, 317 data: img_8x8_rgb_punchthrough_etc2, 318 format: ext.COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 319 }, 320 { 321 width: 8, 322 height: 8, 323 channels: 4, 324 data: img_8x8_rgb_punchthrough_etc2, 325 format: ext.COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 326 }, 327 { 328 width: 8, 329 height: 8, 330 channels: 4, 331 data: img_8x8_rgba_etc2, 332 format: ext.COMPRESSED_RGBA8_ETC2_EAC 333 }, 334 { 335 width: 8, 336 height: 8, 337 channels: 4, 338 data: img_8x8_rgba_etc2, 339 format: ext.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 340 }, 341 { 342 width: 32, 343 height: 32, 344 channels: 1, 345 data: img_32x32_r11_eac, 346 format: ext.COMPRESSED_R11_EAC 347 }, 348 { 349 width: 32, 350 height: 32, 351 channels: 1, 352 data: img_32x32_signed_r11_eac, 353 format: ext.COMPRESSED_SIGNED_R11_EAC 354 }, 355 { 356 width: 32, 357 height: 32, 358 channels: 2, 359 data: img_32x32_rg11_eac, 360 format: ext.COMPRESSED_RG11_EAC 361 }, 362 { 363 width: 32, 364 height: 32, 365 channels: 2, 366 data: img_32x32_signed_rg11_eac, 367 format: ext.COMPRESSED_SIGNED_RG11_EAC 368 }, 369 { 370 width: 32, 371 height: 32, 372 channels: 3, 373 data: img_32x32_rgb_etc2, 374 format: ext.COMPRESSED_RGB8_ETC2 375 }, 376 { 377 width: 32, 378 height: 32, 379 channels: 3, 380 data: img_32x32_rgb_etc2, 381 format: ext.COMPRESSED_SRGB8_ETC2 382 }, 383 { 384 width: 32, 385 height: 32, 386 channels: 4, 387 data: img_32x32_rgb_punchthrough_etc2, 388 format: ext.COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 389 }, 390 { 391 width: 32, 392 height: 32, 393 channels: 4, 394 data: img_32x32_rgb_punchthrough_etc2, 395 format: ext.COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2 396 }, 397 { 398 width: 32, 399 height: 32, 400 channels: 4, 401 data: img_32x32_rgba_etc2, 402 format: ext.COMPRESSED_RGBA8_ETC2_EAC 403 }, 404 { 405 width: 32, 406 height: 32, 407 channels: 4, 408 data: img_32x32_rgba_etc2, 409 format: ext.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC 410 }, 411 ]; 412 testETCTextures(tests); 413 } 414 415 function testETCTextures(tests) { 416 for (var ii = 0; ii < tests.length; ++ii) { 417 testETCTexture(tests[ii]); 418 } 419 } 420 421 /* Return the size of block in bytes */ 422 function getBlockSize(format) { 423 switch (format) { 424 case ext.COMPRESSED_R11_EAC: 425 case ext.COMPRESSED_SIGNED_R11_EAC: 426 case ext.COMPRESSED_RGB8_ETC2: 427 case ext.COMPRESSED_SRGB8_ETC2: 428 case ext.COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: 429 case ext.COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: 430 return 8; 431 case ext.COMPRESSED_RG11_EAC: 432 case ext.COMPRESSED_SIGNED_RG11_EAC: 433 case ext.COMPRESSED_RGBA8_ETC2_EAC: 434 case ext.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: 435 return 16 436 } 437 throw new Error(`Unexpected format ${format}`); 438 } 439 440 function copyRect(data, srcX, srcY, dstX, dstY, width, height, stride) { 441 var bytesPerLine = width * 4; 442 var srcOffset = srcX * 4 + srcY * stride; 443 var dstOffset = dstX * 4 + dstY * stride; 444 for (var jj = height; jj > 0; --jj) { 445 for (var ii = 0; ii < bytesPerLine; ++ii) { 446 data[dstOffset + ii] = data[srcOffset + ii]; 447 } 448 srcOffset += stride; 449 dstOffset += stride; 450 } 451 } 452 453 function testETCTexture(test) { 454 var data = new Uint8Array(test.data.compressed); 455 var width = test.width; 456 var height = test.height; 457 var format = test.format; 458 459 var uncompressedData = new Uint8Array(test.data.decompressed); 460 var glErrorShouldBe = (glInner, glError, msg) => { 461 msg = msg || ""; 462 var err = glInner.getError(); 463 var getGLErrorAsString = error => { 464 if (error === glInner.NO_ERROR) { 465 return "NO_ERROR"; 466 } 467 for (let name in glInner) { 468 if (glInner[name] === error) { 469 return name; 470 } 471 } 472 return error.toString(); 473 } 474 475 if (err != glError) { 476 ok(false, "getError expected: " + getGLErrorAsString(glError) + 477 ". Was " + getGLErrorAsString(err) + " : " + msg); 478 } else { 479 ok(true, "getError was expected value: " + 480 getGLErrorAsString(glError) + " : " + msg); 481 } 482 }; 483 484 canvas.width = width; 485 canvas.height = height; 486 gl.viewport(0, 0, width, height); 487 488 var tex = gl.createTexture(); 489 gl.bindTexture(gl.TEXTURE_2D, tex); 490 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 491 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 492 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); 493 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); 494 gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, data); 495 glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture"); 496 gl.generateMipmap(gl.TEXTURE_2D); 497 glErrorShouldBe(gl, gl.INVALID_OPERATION, "trying to generate mipmaps from compressed texture"); 498 if (format == ext.COMPRESSED_SIGNED_R11_EAC) { 499 var program = WebGLUtil.createProgramByIds(gl, 'vshader', 'fshader-r'); 500 } else if (format == ext.COMPRESSED_SIGNED_RG11_EAC) { 501 var program = WebGLUtil.createProgramByIds(gl, 'vshader', 'fshader-rg'); 502 } else { 503 var program = WebGLUtil.createProgramByIds(gl, 'vshader', 'fshader'); 504 } 505 gl.bindAttribLocation(program, 0, 'vPosition'); 506 gl.bindAttribLocation(program, 1, 'texCoord0'); 507 gl.useProgram(program); 508 509 gl.clearColor(1.0, 1.0, 1.0, 1.0); 510 gl.clear(gl.COLOR_BUFFER_BIT); 511 gl.drawArrays(gl.TRIANGLES, 0, 6); 512 compareRect(width, height, test.channels, width, height, uncompressedData, data, format); 513 514 gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 1, data); 515 glErrorShouldBe(gl, gl.INVALID_VALUE, "non 0 border"); 516 517 gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width + 4, height, 0, data); 518 glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions"); 519 gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height + 4, 0, data); 520 glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions"); 521 gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 4, height, 0, data); 522 glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions"); 523 gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 4, 0, data); 524 glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions"); 525 526 gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 1, height, 0, data); 527 glErrorShouldBe(gl, gl.NO_ERROR, "non multiple-of-4 supported"); 528 gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width - 2, height, 0, data); 529 glErrorShouldBe(gl, gl.NO_ERROR, "non multiple-of-4 supported"); 530 gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 1, 0, data); 531 glErrorShouldBe(gl, gl.NO_ERROR, "non multiple-of-4 supported"); 532 gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height - 2, 0, data); 533 glErrorShouldBe(gl, gl.NO_ERROR, "non multiple-of-4 supported"); 534 535 if (width == 4) { 536 gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, 1, height, 0, data); 537 glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0"); 538 gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, 2, height, 0, data); 539 glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0"); 540 } 541 if (height == 4) { 542 gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, width, 1, 0, data); 543 glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0"); 544 gl.compressedTexImage2D(gl.TEXTURE_2D, 1, format, width, 2, 0, data); 545 glErrorShouldBe(gl, gl.NO_ERROR, "valid dimensions for level > 0"); 546 } 547 548 // pick a wrong format that uses the same amount of data. 549 var wrongFormat; 550 switch (format) { 551 case ext.COMPRESSED_R11_EAC: 552 wrongFormat = ext.COMPRESSED_SIGNED_R11_EAC; 553 break; 554 case ext.COMPRESSED_SIGNED_R11_EAC: 555 wrongFormat = ext.COMPRESSED_R11_EAC; 556 break; 557 case ext.COMPRESSED_RG11_EAC: 558 wrongFormat = ext.COMPRESSED_SIGNED_RG11_EAC; 559 break; 560 case ext.COMPRESSED_SIGNED_RG11_EAC: 561 wrongFormat = ext.COMPRESSED_RG11_EAC; 562 break; 563 case ext.COMPRESSED_RGB8_ETC2: 564 wrongFormat = ext.COMPRESSED_SRGB8_ETC2; 565 break; 566 case ext.COMPRESSED_SRGB8_ETC2: 567 wrongFormat = ext.COMPRESSED_RGB8_ETC2; 568 break; 569 case ext.COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: 570 wrongFormat = ext.COMPRESSED_RGB8_ETC2; 571 break; 572 case ext.COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: 573 wrongFormat = ext.COMPRESSED_RGB8_ETC2; 574 break; 575 case ext.COMPRESSED_RGBA8_ETC2_EAC: 576 wrongFormat = ext.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC; 577 break; 578 case ext.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: 579 wrongFormat = ext.COMPRESSED_RGBA8_ETC2_EAC; 580 break; 581 } 582 583 // Restore original texture. 584 gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, data); 585 glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture"); 586 587 gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height, wrongFormat, data); 588 glErrorShouldBe(gl, gl.INVALID_OPERATION, "format does not match"); 589 590 gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width + 4, height, format, data); 591 glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions"); 592 gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height + 4, format, data); 593 glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions"); 594 gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width - 4, height, format, data); 595 glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions"); 596 gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height - 4, format, data); 597 glErrorShouldBe(gl, gl.INVALID_VALUE, "data size does not match dimensions"); 598 599 gl.compressedTexImage2D(gl.TEXTURE_2D, 0, format, width, height, 0, data); 600 glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture"); 601 gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width - 1, height, format, data); 602 glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions"); 603 gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width - 2, height, format, data); 604 glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions"); 605 gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height - 1, format, data); 606 glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions"); 607 gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, width, height - 2, format, data); 608 glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid dimensions"); 609 610 var subData = new Uint8Array(data.buffer, 0, getBlockSize(format)); 611 612 if (width == 8 && height == 8) { 613 gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 1, 0, 4, 4, format, subData); 614 glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid offset"); 615 gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, 0, 1, 4, 4, format, subData); 616 glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid offset"); 617 } 618 619 if (width < 32 && height < 32) { 620 var stride = width * 4; 621 for (var yoff = 0; yoff < height; yoff += 4) { 622 for (var xoff = 0; xoff < width; xoff += 4) { 623 copyRect(uncompressedData, 0, 0, xoff, yoff, 4, 4, stride); 624 gl.compressedTexSubImage2D(gl.TEXTURE_2D, 0, xoff, yoff, 4, 4, format, subData); 625 glErrorShouldBe(gl, gl.NO_ERROR, "uploading compressed texture"); 626 gl.clearColor(1.0, 1.0, 1.0, 1.0); 627 gl.clear(gl.COLOR_BUFFER_BIT); 628 gl.drawArrays(gl.TRIANGLES, 0, 6); 629 compareRect(width, height, test.channels, width, height, uncompressedData, data, format); 630 } 631 } 632 } 633 } 634 635 function insertImg(element, caption, img) { 636 var div = document.createElement("div"); 637 div.appendChild(img); 638 var label = document.createElement("div"); 639 label.appendChild(document.createTextNode(caption)); 640 div.appendChild(label); 641 element.appendChild(div); 642 } 643 644 function convertToSRGB(val) { 645 var norm = val / 255.0; 646 var res = 0; 647 if (norm <= 0.04045) { 648 res = norm / 12.92; 649 } else { 650 res = Math.pow(((norm + 0.055)/1.055), 2.4); 651 } 652 653 return res * 255.0; 654 } 655 656 function makeImage(imageWidth, imageHeight, dataWidth, data, alpha) { 657 var scale = 8; 658 var c = document.createElement("canvas"); 659 c.width = imageWidth * scale; 660 c.height = imageHeight * scale; 661 var ctx = c.getContext("2d"); 662 for (var yy = 0; yy < imageHeight; ++yy) { 663 for (var xx = 0; xx < imageWidth; ++xx) { 664 var offset = (yy * dataWidth + xx) * 4; 665 ctx.fillStyle = "rgba(" + 666 data[offset + 0] + "," + 667 data[offset + 1] + "," + 668 data[offset + 2] + "," + 669 (alpha ? data[offset + 3] / 255 : 1) + ")"; 670 ctx.fillRect(xx * scale, yy * scale, scale, scale); 671 } 672 } 673 var img = document.createElement("img"); 674 img.src = c.toDataURL(); 675 return img; 676 } 677 678 function compareRect(actualWidth, actualHeight, actualChannels, 679 dataWidth, dataHeight, expectedData, 680 testData, testFormat) 681 { 682 var actual = new Uint8Array(actualWidth * actualHeight * 4); 683 gl.readPixels( 684 0, 0, actualWidth, actualHeight, gl.RGBA, gl.UNSIGNED_BYTE, actual); 685 686 var div = document.createElement("div"); 687 div.className = "testimages"; 688 var hasAlpha = actualChannels == 4; 689 var imgExpected = makeImage(actualWidth, actualHeight, dataWidth, expectedData, hasAlpha); 690 var imgActual = makeImage(actualWidth, actualHeight, actualWidth, actual, hasAlpha); 691 insertImg(div, "expected", imgExpected); 692 insertImg(div, "actual", imgActual); 693 div.appendChild(document.createElement('br')); 694 document.getElementById("console").appendChild(div); 695 696 var failed = false; 697 for (var yy = 0; yy < actualHeight; ++yy) { 698 for (var xx = 0; xx < actualWidth; ++xx) { 699 var actualOffset = (yy * actualWidth + xx) * 4; 700 var expectedOffset = (yy * dataWidth + xx) * 4; 701 var expected = expectedData.slice(expectedOffset, expectedOffset + 4); 702 703 var maxDiffPixel = 0; 704 switch (testFormat) { 705 case ext.COMPRESSED_SRGB8_ETC2: 706 case ext.COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: 707 case ext.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: 708 709 // Alpha shouldn't do conversion. 710 for (var i = 0; i < 3; ++i) { 711 expected[i] = convertToSRGB(expected[i]); 712 } 713 //fallthrough 714 case ext.COMPRESSED_R11_EAC: 715 case ext.COMPRESSED_RG11_EAC: 716 case ext.COMPRESSED_SIGNED_R11_EAC: 717 case ext.COMPRESSED_SIGNED_RG11_EAC: 718 // Due to floating round error, we need fuzzy test here. 719 var maxDiffPixel = 1; 720 break; 721 default: 722 var maxDiffPixel = 0; 723 break; 724 } 725 726 for (var channel = 0; channel < actualChannels; ++channel) { 727 var diff = Math.abs(expected[channel] - actual[actualOffset + channel]); 728 729 if (diff > maxDiffPixel) { 730 failed = true; 731 var was = actual.slice(actualOffset, actualOffset + 4).join(); 732 ok(false, 'at (' + xx + ', ' + yy + 733 ') expected: ' + expected.join() + ' was ' + was); 734 break; 735 } 736 } 737 } 738 } 739 if (!failed) { 740 ok(true, "texture rendered correctly"); 741 } 742 } 743 744 var prefArrArr = [ 745 ['webgl.enable-draft-extensions', true], 746 ]; 747 var prefEnv = {'set': prefArrArr}; 748 SimpleTest.waitForExplicitFinish(); 749 SpecialPowers.pushPrefEnv(prefEnv, runTest); 750 </script> 751 </body> 752 </html>