tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

tex-unpack-params.html (27074B)


      1 <!--
      2 Copyright (c) 2019 The Khronos Group Inc.
      3 Use of this source code is governed by an MIT-style license that can be
      4 found in the LICENSE.txt file.
      5 -->
      6 
      7 <!DOCTYPE html>
      8 <html>
      9 <head>
     10 <meta charset="utf-8">
     11 <title>WebGL2 texture unpack parameters conformance test.</title>
     12 <link rel="stylesheet" href="../../../resources/js-test-style.css"/>
     13 <script src="../../../js/js-test-pre.js"></script>
     14 <script src="../../../js/webgl-test-utils.js"></script>
     15 </head>
     16 <body>
     17 <canvas id="example" width="4" height="4"></canvas>
     18 <div id="description"></div>
     19 <div id="console"></div>
     20 <script>
     21 "use strict";
     22 
     23 var wtu = WebGLTestUtils;
     24 var __verbose__ = false;
     25 
     26 // Some drivers (for example, NVIDIA Linux) incorrectly require padding for
     27 // the last row. The below flag is only for testing convenience. Browsers should
     28 // work around the bug.
     29 var __apply_alignment_workaround__ = false;
     30 
     31 function setupArrayBuffer(size, initData) {
     32  var array = new Uint8Array(size);
     33  if (initData) {
     34    for (var ii = 0; ii < size; ++ii) {
     35      array[ii] = ii % 255;
     36    }
     37  }
     38  return array;
     39 }
     40 
     41 function calculatePaddingBytes(bytesPerPixel, alignment, width) {
     42  var padding = 0;
     43  switch (alignment) {
     44    case 1:
     45    case 2:
     46    case 4:
     47    case 8:
     48      padding = (bytesPerPixel * width) % alignment;
     49      if (padding > 0)
     50        padding = alignment - padding;
     51      return padding;
     52    default:
     53      testFailed("should not reach here");
     54      return;
     55  }
     56 }
     57 
     58 function computeImageSizes2D(width, height, testCase) {
     59  // Assume RGB8/UNSIGNED_BYTE
     60  var bytesPerPixel = 3;
     61  var actualWidth = testCase.rowLength == 0 ? width : testCase.rowLength;
     62  var padding = calculatePaddingBytes(bytesPerPixel, testCase.alignment, actualWidth);
     63  var bytesPerRow = actualWidth * bytesPerPixel + padding;
     64  var bytesLastRow = bytesPerPixel * width;
     65  var size = bytesPerRow * (height - 1) + bytesLastRow;
     66  var skipSize = 0;
     67  if (testCase.skipPixels > 0)
     68    skipSize += bytesPerPixel * testCase.skipPixels;
     69  if (testCase.skipRows > 0)
     70    skipSize += bytesPerRow * testCase.skipRows;
     71  return {size: size,
     72          bytesPerRow: bytesPerRow,
     73          bytesLastRow: bytesLastRow,
     74          padding: padding,
     75          skipSize: skipSize,
     76          totalSize: size + skipSize};
     77 }
     78 
     79 function computeImageSizes3D(width, height, depth, testCase) {
     80  // Assume RGB8/UNSIGNED_BYTE
     81  var bytesPerPixel = 3;
     82  var actualWidth = testCase.rowLength == 0 ? width : testCase.rowLength;
     83  var actualHeight = testCase.imageHeight == 0 ? height : testCase.imageHeight;
     84  var padding = calculatePaddingBytes(bytesPerPixel, testCase.alignment, actualWidth);
     85  var bytesPerRow = actualWidth * bytesPerPixel + padding;
     86  var bytesLastRow = bytesPerPixel * width;
     87  var bytesPerImage = bytesPerRow * actualHeight;
     88  var bytesLastImage = bytesPerRow * (height - 1) + bytesLastRow;
     89  var size = bytesPerImage * (depth - 1) + bytesLastImage;
     90  var skipSize = 0;
     91  if (testCase.skipPixels > 0)
     92    skipSize += bytesPerPixel * testCase.skipPixels;
     93  if (testCase.skipRows > 0)
     94    skipSize += bytesPerRow * testCase.skipRows;
     95  if (testCase.skipImages > 0)
     96    skipSize += bytesPerImage * testCase.skipImages;
     97  return {size: size,
     98          bytesPerRow: bytesPerRow,
     99          bytesLastRow: bytesLastRow,
    100          bytesPerImage: bytesPerImage,
    101          bytesLastImage: bytesLastImage,
    102          padding: padding,
    103          skipSize: skipSize,
    104          totalSize: size + skipSize};
    105 }
    106 
    107 function copyData(srcData, srcIndex, dstData, dstIndex, size) {
    108  for (var ii = 0; ii < size; ++ii)
    109    dstData[dstIndex + ii] = srcData[srcIndex + ii];
    110 }
    111 
    112 function unpackPixels(srcData, width, height, depth, imageSizes) {
    113  var bytesPerPixel = 3;
    114  var unpackedSize = width * height * depth * bytesPerPixel;
    115  var dstData = setupArrayBuffer(unpackedSize, false);
    116  var srcIndex = imageSizes.skipSize;
    117  var dstIndex = 0;
    118  for (var z = 0; z < depth; ++z) {
    119    var srcIndexPerImage = srcIndex;
    120    for (var y = 0; y < height; ++y) {
    121      copyData(srcData, srcIndexPerImage, dstData, dstIndex, width * 3);
    122      srcIndexPerImage += imageSizes.bytesPerRow;
    123      dstIndex += width * 3;
    124    }
    125    if (depth > 1)
    126      srcIndex += imageSizes.bytesPerImage;
    127  }
    128  return dstData;
    129 }
    130 
    131 function getPixelsFromTexture2D(gl, tex, xoffset, yoffset, width, height) {
    132  var fbo = gl.createFramebuffer();
    133  gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
    134  gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
    135  var bytesPerReadbackPixel = 4;
    136  var readbackBuffer = setupArrayBuffer(width * height * bytesPerReadbackPixel, false);
    137  gl.readPixels(xoffset, yoffset, width, height, gl.RGBA, gl.UNSIGNED_BYTE, readbackBuffer);
    138  wtu.glErrorShouldBe(gl, gl.NO_ERROR, "read back texture pixels should succeed");
    139  var bytesPerPixel = 3;
    140  var buffer = setupArrayBuffer(width * height * bytesPerPixel, false);
    141  var srcIndex = 0;
    142  var dstIndex = 0;
    143  for (var y = 0; y < height; ++y) {
    144    for (var x = 0; x < width; ++x) {
    145      buffer[dstIndex++] = readbackBuffer[srcIndex++]; // R
    146      buffer[dstIndex++] = readbackBuffer[srcIndex++]; // G
    147      buffer[dstIndex++] = readbackBuffer[srcIndex++]; // B
    148      srcIndex++;                                      // A
    149    }
    150  }
    151  gl.bindFramebuffer(gl.FRAMEBUFFER, null);
    152  gl.deleteFramebuffer(fbo);
    153  return buffer;
    154 }
    155 
    156 function getPixelsFromTexture3D(gl, tex, xoffset, yoffset, zoffset, width, height, depth) {
    157  var fbo = gl.createFramebuffer();
    158  gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
    159  var bytesPerReadbackPixel = 4;
    160  var readbackBuffer = setupArrayBuffer(width * height * bytesPerReadbackPixel, false);
    161  var bytesPerPixel = 3;
    162  var buffer = setupArrayBuffer(width * height * depth * bytesPerPixel, false);
    163  var dstIndex = 0;
    164  for (var zz = 0; zz < depth; ++zz) {
    165    gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, tex, 0, zz + zoffset);
    166    gl.readPixels(xoffset, yoffset, width, height, gl.RGBA, gl.UNSIGNED_BYTE, readbackBuffer);
    167    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "read back texture pixels should succeed");
    168    var srcIndex = 0;
    169    for (var y = 0; y < height; ++y) {
    170      for (var x = 0; x < width; ++x) {
    171        buffer[dstIndex++] = readbackBuffer[srcIndex++]; // R
    172        buffer[dstIndex++] = readbackBuffer[srcIndex++]; // G
    173        buffer[dstIndex++] = readbackBuffer[srcIndex++]; // B
    174        srcIndex++;                                      // A
    175      }
    176    }
    177  }
    178  gl.bindFramebuffer(gl.FRAMEBUFFER, null);
    179  gl.deleteFramebuffer(fbo);
    180  return buffer;
    181 }
    182 
    183 function comparePixels(buffer1, buffer2) {
    184  if (buffer1.length != buffer2.length || buffer1.length % 3 != 0) {
    185    testFailed("compare pixels: invalid buffer size");
    186    return;
    187  }
    188  var count = 0;
    189  for (var ii = 0; ii < buffer1.length / 3; ++ii) {
    190    if (buffer1[ii * 3] != buffer2[ii * 3] ||
    191        buffer1[ii * 3 + 1] != buffer2[ii * 3 + 1] ||
    192        buffer1[ii * 3 + 2] != buffer2[ii * 3 + 2]) {
    193      if (__verbose__) {
    194        debug("Pixel " + ii + ": expected (" +
    195              [buffer1[ii * 3], buffer1[ii * 3 + 1], buffer1[ii * 3 + 2]] + "), got (" +
    196              [buffer2[ii * 3], buffer2[ii * 3 + 1], buffer2[ii * 3 + 2]] + ")");
    197      }
    198      count++;
    199    }
    200  }
    201  if (count > 0) {
    202    testFailed("compare pixels: " + count + " pixels differ");
    203  } else {
    204    testPassed("compare pixels: as expected");
    205  }
    206 }
    207 
    208 function runTestIteration2D(gl, testCase, useUnpackBuffer) {
    209  debug("");
    210  debug("Texture upload from " + (useUnpackBuffer ? "unpack buffer" : "client data") +
    211        " : alignment = " + testCase.alignment + ", rowLength = " + testCase.rowLength +
    212        ", skipPixels = " + testCase.skipPixels + ", skipRows = " + testCase.skipRows);
    213  debug("TexImage2D : size = (" + testCase.width + ", " + testCase.height + ")");
    214  gl.pixelStorei(gl.UNPACK_ALIGNMENT, testCase.alignment);
    215  gl.pixelStorei(gl.UNPACK_ROW_LENGTH, testCase.rowLength);
    216  gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, testCase.skipPixels);
    217  gl.pixelStorei(gl.UNPACK_SKIP_ROWS, testCase.skipRows);
    218  wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Set up pixel store parameters should succeed");
    219 
    220  var tex = gl.createTexture();
    221  gl.bindTexture(gl.TEXTURE_2D, tex);
    222 
    223  var imageSizes = computeImageSizes2D(testCase.width, testCase.height, testCase);
    224  var bufferSize = imageSizes.totalSize;
    225  var buffer = null;
    226  var array;
    227 
    228  // Verify buffer with less than enough size will fail.
    229  if (useUnpackBuffer) {
    230    buffer = gl.createBuffer();
    231    gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, buffer);
    232    gl.bufferData(gl.PIXEL_UNPACK_BUFFER, bufferSize - 1, gl.DYNAMIC_DRAW);
    233    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB8, testCase.width, testCase.height, 0,
    234                  gl.RGB, gl.UNSIGNED_BYTE, 0);
    235  } else {
    236    array = setupArrayBuffer(bufferSize - 1, false);
    237    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB8, testCase.width, testCase.height, 0,
    238                  gl.RGB, gl.UNSIGNED_BYTE, array);
    239  }
    240  wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "buffer too small");
    241 
    242  if (__apply_alignment_workaround__)
    243    bufferSize += imageSizes.padding;
    244  array = setupArrayBuffer(bufferSize, true);
    245  if (useUnpackBuffer) {
    246    gl.bufferData(gl.PIXEL_UNPACK_BUFFER, array, gl.DYNAMIC_DRAW);
    247  }
    248  gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB8, testCase.width, testCase.height, 0,
    249                gl.RGB, gl.UNSIGNED_BYTE, useUnpackBuffer ? 0 : array);
    250  if (testCase.validUnpackParams2D) {
    251    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texImage2D with correct buffer size should succeed");
    252  } else {
    253    wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid unpack params combination");
    254    if (!useUnpackBuffer) {
    255      gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB8, testCase.width, testCase.height, 0,
    256                    gl.RGB, gl.UNSIGNED_BYTE, null);
    257      wtu.glErrorShouldBe(gl, gl.NO_ERROR, "unpack param constraints do not apply if no data are uploaded.");
    258    }
    259    return;
    260  }
    261 
    262  var buffer1 = unpackPixels(array, testCase.width, testCase.height, 1, imageSizes);
    263  var buffer2 = getPixelsFromTexture2D(gl, tex, 0, 0, testCase.width, testCase.height);
    264  comparePixels(buffer1, buffer2);
    265 
    266  var subWidth = testCase.width - testCase.xoffset;
    267  var subHeight = testCase.height - testCase.yoffset;
    268  debug("TexSubImage2D : offset = (" + testCase.xoffset + ", " + testCase.yoffset +
    269        "), size = (" + subWidth + ", " + subHeight + ")");
    270  imageSizes = computeImageSizes2D(subWidth, subHeight, testCase);
    271  bufferSize = imageSizes.totalSize;
    272 
    273  if (useUnpackBuffer) {
    274    gl.bufferData(gl.PIXEL_UNPACK_BUFFER, bufferSize - 1, gl.DYNAMIC_DRAW);
    275    gl.texSubImage2D(gl.TEXTURE_2D, 0, testCase.xoffset, testCase.yoffset,
    276                     subWidth, subHeight, gl.RGB, gl.UNSIGNED_BYTE, 0);
    277  } else {
    278    array = setupArrayBuffer(bufferSize - 1, false);
    279    gl.texSubImage2D(gl.TEXTURE_2D, 0, testCase.xoffset, testCase.yoffset,
    280                     subWidth, subHeight, gl.RGB, gl.UNSIGNED_BYTE, array);
    281  }
    282  wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "buffer too small");
    283 
    284  if (__apply_alignment_workaround__)
    285    bufferSize += imageSizes.padding;
    286  array = setupArrayBuffer(bufferSize, true);
    287  if (useUnpackBuffer) {
    288    gl.bufferData(gl.PIXEL_UNPACK_BUFFER, array, gl.DYNAMIC_DRAW);
    289  }
    290  gl.texSubImage2D(gl.TEXTURE_2D, 0, testCase.xoffset, testCase.yoffset, subWidth, subHeight,
    291                   gl.RGB, gl.UNSIGNED_BYTE, useUnpackBuffer ? 0 : array);
    292  if (testCase.validUnpackParamsForSub2D) {
    293    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage2D with correct buffer size should succeed");
    294  } else {
    295    wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid unpack params combination");
    296    return;
    297  }
    298 
    299  var buffer1 = unpackPixels(array, subWidth, subHeight, 1, imageSizes);
    300  var buffer2 = getPixelsFromTexture2D(
    301      gl, tex, testCase.xoffset, testCase.yoffset, subWidth, subHeight);
    302  comparePixels(buffer1, buffer2);
    303 
    304  if (buffer) {
    305    gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, null);
    306    gl.deleteBuffer(buffer);
    307  }
    308  gl.bindTexture(gl.TEXTURE_2D, null);
    309  gl.deleteTexture(tex);
    310  wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no error");
    311 }
    312 
    313 function runTestIteration3D(gl, testCase, useUnpackBuffer) {
    314  debug("");
    315  debug("Texture upload from "  + (useUnpackBuffer ? "unpack buffer" : "client data") +
    316        " : alignment = " + testCase.alignment + ", rowLength = " + testCase.rowLength +
    317        ", imageHeight = " + testCase.imageHeight + ", skipPixels = " + testCase.skipPixels +
    318        ", skipRows = " + testCase.skipRows + ", skipImages = " + testCase.skipImages);
    319  debug("TexImage3D : size = (" + testCase.width + ", " + testCase.height + ", " + testCase.depth + ")");
    320  gl.pixelStorei(gl.UNPACK_ALIGNMENT, testCase.alignment);
    321  gl.pixelStorei(gl.UNPACK_ROW_LENGTH, testCase.rowLength);
    322  gl.pixelStorei(gl.UNPACK_IMAGE_HEIGHT, testCase.imageHeight);
    323  gl.pixelStorei(gl.UNPACK_SKIP_PIXELS, testCase.skipPixels);
    324  gl.pixelStorei(gl.UNPACK_SKIP_ROWS, testCase.skipRows);
    325  gl.pixelStorei(gl.UNPACK_SKIP_IMAGES, testCase.skipImages);
    326  wtu.glErrorShouldBe(gl, gl.NO_ERROR, "Set up pixel store parameters should succeed");
    327 
    328  var tex = gl.createTexture();
    329  gl.bindTexture(gl.TEXTURE_3D, tex);
    330 
    331  var imageSizes = computeImageSizes3D(testCase.width, testCase.height, testCase.depth, testCase);
    332  var buffer = null;
    333  var array;
    334  var bufferSize = imageSizes.totalSize;
    335 
    336  // Verify buffer with less than enough size will fail.
    337  if (useUnpackBuffer) {
    338    buffer = gl.createBuffer();
    339    gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, buffer);
    340    gl.bufferData(gl.PIXEL_UNPACK_BUFFER, bufferSize - 1, gl.DYNAMIC_DRAW);
    341    gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGB8, testCase.width, testCase.height, testCase.depth, 0,
    342                  gl.RGB, gl.UNSIGNED_BYTE, 0);
    343  } else {
    344    array = setupArrayBuffer(bufferSize - 1, false);
    345    gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGB8, testCase.width, testCase.height, testCase.depth, 0,
    346                  gl.RGB, gl.UNSIGNED_BYTE, array);
    347  }
    348  wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "buffer too small");
    349 
    350  if (__apply_alignment_workaround__)
    351    bufferSize += imageSizes.padding;
    352  array = setupArrayBuffer(bufferSize, true);
    353  if (useUnpackBuffer) {
    354    gl.bufferData(gl.PIXEL_UNPACK_BUFFER, array, gl.DYNAMIC_DRAW);
    355  }
    356  gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGB8, testCase.width, testCase.height, testCase.depth, 0,
    357                gl.RGB, gl.UNSIGNED_BYTE, useUnpackBuffer ? 0 : array);
    358  if (testCase.validUnpackParams3D) {
    359    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texImage3D with correct buffer size should succeed");
    360  } else {
    361    wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid unpack params combination");
    362    if (!useUnpackBuffer) {
    363      gl.texImage3D(gl.TEXTURE_3D, 0, gl.RGB8, testCase.width, testCase.height, testCase.depth, 0,
    364                    gl.RGB, gl.UNSIGNED_BYTE, null);
    365      wtu.glErrorShouldBe(gl, gl.NO_ERROR, "unpack param constraints do not apply if no data are uploaded.");
    366    }
    367    return;
    368  }
    369 
    370  var buffer1 = unpackPixels(array, testCase.width, testCase.height, testCase.depth, imageSizes);
    371  var buffer2 = getPixelsFromTexture3D(
    372      gl, tex, 0, 0, 0, testCase.width, testCase.height, testCase.depth);
    373  comparePixels(buffer1, buffer2);
    374 
    375  var subWidth = testCase.width - testCase.xoffset;
    376  var subHeight = testCase.height - testCase.yoffset;
    377  var subDepth = testCase.depth - testCase.zoffset;
    378  debug("TexSubImage3D : offset = (" + testCase.xoffset + ", " + testCase.yoffset + ", " +
    379        testCase.zoffset + "), size = (" + subWidth + ", " + subHeight + ", " + subDepth + ")");
    380  imageSizes = computeImageSizes3D(subWidth, subHeight, subDepth, testCase);
    381  bufferSize = imageSizes.totalSize;
    382 
    383  if (useUnpackBuffer) {
    384    gl.bufferData(gl.PIXEL_UNPACK_BUFFER, bufferSize - 1, gl.DYNAMIC_DRAW);
    385    gl.texSubImage3D(gl.TEXTURE_3D, 0, testCase.xoffset, testCase.yoffset, testCase.zoffset,
    386                     subWidth, subHeight, subDepth, gl.RGB, gl.UNSIGNED_BYTE, 0);
    387  } else {
    388    array = setupArrayBuffer(bufferSize - 1, false);
    389    gl.texSubImage3D(gl.TEXTURE_3D, 0, testCase.xoffset, testCase.yoffset, testCase.zoffset,
    390                     subWidth, subHeight, subDepth, gl.RGB, gl.UNSIGNED_BYTE, array);
    391  }
    392  wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "buffer too small");
    393 
    394  if (__apply_alignment_workaround__)
    395    bufferSize += imageSizes.padding;
    396  array = setupArrayBuffer(bufferSize, true);
    397  if (useUnpackBuffer) {
    398    gl.bufferData(gl.PIXEL_UNPACK_BUFFER, array, gl.DYNAMIC_DRAW);
    399  }
    400  gl.texSubImage3D(gl.TEXTURE_3D, 0, testCase.xoffset, testCase.yoffset, testCase.zoffset,
    401                   subWidth, subHeight, subDepth,
    402                   gl.RGB, gl.UNSIGNED_BYTE, useUnpackBuffer ? 0 : array);
    403  if (testCase.validUnpackParamsForSub3D) {
    404    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "texSubImage3D with correct buffer size should succeed");
    405  } else {
    406    wtu.glErrorShouldBe(gl, gl.INVALID_OPERATION, "invalid unpack params combination");
    407    return;
    408  }
    409 
    410  buffer1 = unpackPixels(array, subWidth, subHeight, subDepth, imageSizes);
    411  buffer2 = getPixelsFromTexture3D(gl, tex, testCase.xoffset, testCase.yoffset, testCase.zoffset,
    412                                   subWidth, subHeight, subDepth);
    413  comparePixels(buffer1, buffer2);
    414 
    415  if (buffer) {
    416    gl.bindBuffer(gl.PIXEL_UNPACK_BUFFER, null);
    417    gl.deleteBuffer(buffer);
    418  }
    419  gl.bindTexture(gl.TEXTURE_3D, null);
    420  gl.deleteTexture(tex);
    421  wtu.glErrorShouldBe(gl, gl.NO_ERROR, "no error");
    422 }
    423 
    424 function runTests() {
    425  var gl = wtu.create3DContext("example", undefined, 2);
    426  if (!gl) {
    427    testFailed("Fail to get a WebGL context");
    428    return;
    429  }
    430 
    431  // For 2D cases, depth, zoffset, imageHeight, skipImages are ignored.
    432  var testCases = [
    433    { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
    434      alignment: 1, rowLength: 0, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0,
    435      validUnpackParams2D: true, validUnpackParamsForSub2D: true,
    436      validUnpackParams3D: true, validUnpackParamsForSub3D: true },
    437    { width: 5, height: 7, depth: 4, xoffset: 2, yoffset: 3, zoffset: 1,
    438      alignment: 2, rowLength: 0, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0,
    439      validUnpackParams2D: true, validUnpackParamsForSub2D: true,
    440      validUnpackParams3D: true, validUnpackParamsForSub3D: true },
    441    { width: 6, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
    442      alignment: 4, rowLength: 0, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0,
    443      validUnpackParams2D: true, validUnpackParamsForSub2D: true,
    444      validUnpackParams3D: true, validUnpackParamsForSub3D: true },
    445    { width: 5, height: 8, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
    446      alignment: 8, rowLength: 0, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0,
    447      validUnpackParams2D: true, validUnpackParamsForSub2D: true,
    448      validUnpackParams3D: true, validUnpackParamsForSub3D: true },
    449 
    450    // ROW_LENGTH == width
    451    { width: 10, height: 9, depth: 2, xoffset: 2, yoffset: 3, zoffset: 1,
    452      alignment: 4, rowLength: 10, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0,
    453      validUnpackParams2D: true, validUnpackParamsForSub2D: true,
    454      validUnpackParams3D: true, validUnpackParamsForSub3D: true },
    455 
    456    // ROW_LENGTH < width
    457    { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
    458      alignment: 1, rowLength: 4, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0,
    459      validUnpackParams2D: false, validUnpackParams3D: false },
    460    { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
    461      alignment: 2, rowLength: 4, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0,
    462      validUnpackParams2D: false, validUnpackParams3D: false },
    463    { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
    464      alignment: 4, rowLength: 4, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0,
    465      validUnpackParams2D: false, validUnpackParams3D: false },
    466    { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
    467      alignment: 8, rowLength: 4, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0,
    468      validUnpackParams2D: false, validUnpackParams3D: false },
    469 
    470    // ROW_LENGTH > width
    471    { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
    472      alignment: 1, rowLength: 6, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0,
    473      validUnpackParams2D: true, validUnpackParamsForSub2D: true,
    474      validUnpackParams3D: true, validUnpackParamsForSub3D: true },
    475    { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
    476      alignment: 2, rowLength: 7, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0,
    477      validUnpackParams2D: true, validUnpackParamsForSub2D: true,
    478      validUnpackParams3D: true, validUnpackParamsForSub3D: true },
    479    { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
    480      alignment: 4, rowLength: 8, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0,
    481      validUnpackParams2D: true, validUnpackParamsForSub2D: true,
    482      validUnpackParams3D: true, validUnpackParamsForSub3D: true },
    483    { width: 5, height: 7, depth: 5, xoffset: 2, yoffset: 3, zoffset: 2,
    484      alignment: 8, rowLength: 9, imageHeight: 0, skipPixels: 0, skipRows: 0, skipImages: 0,
    485      validUnpackParams2D: true, validUnpackParamsForSub2D: true,
    486      validUnpackParams3D: true, validUnpackParamsForSub3D: true },
    487 
    488    // IMAGE_HEIGHT == height
    489    { width: 6, height: 7, depth: 4, xoffset: 2, yoffset: 3, zoffset: 1,
    490      alignment: 8, rowLength: 0, imageHeight: 7, skipPixels: 0, skipRows: 0, skipImages: 0,
    491      validUnpackParams2D: true, validUnpackParamsForSub2D: true,
    492      validUnpackParams3D: true, validUnpackParamsForSub3D: true },
    493 
    494    // IMAGE_HEIGHT < height
    495    { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
    496      alignment: 1, rowLength: 0, imageHeight: 6, skipPixels: 0, skipRows: 0, skipImages: 0,
    497      validUnpackParams2D: true, validUnpackParamsForSub2D: true,
    498      validUnpackParams3D: false },
    499    { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
    500      alignment: 2, rowLength: 0, imageHeight: 6, skipPixels: 0, skipRows: 0, skipImages: 0,
    501      validUnpackParams2D: true, validUnpackParamsForSub2D: true,
    502      validUnpackParams3D: false },
    503    { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
    504      alignment: 4, rowLength: 0, imageHeight: 6, skipPixels: 0, skipRows: 0, skipImages: 0,
    505      validUnpackParams2D: true, validUnpackParamsForSub2D: true,
    506      validUnpackParams3D: false },
    507    { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
    508      alignment: 8, rowLength: 0, imageHeight: 6, skipPixels: 0, skipRows: 0, skipImages: 0,
    509      validUnpackParams2D: true, validUnpackParamsForSub2D: true,
    510      validUnpackParams3D: false },
    511 
    512    // IMAGE_HEIGHT > height
    513    { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
    514      alignment: 1, rowLength: 0, imageHeight: 8, skipPixels: 0, skipRows: 0, skipImages: 0,
    515      validUnpackParams2D: true, validUnpackParamsForSub2D: true,
    516      validUnpackParams3D: true, validUnpackParamsForSub3D: true },
    517    { width: 6, height: 7, depth: 3, xoffset: 2, yoffset: 2, zoffset: 1,
    518      alignment: 2, rowLength: 0, imageHeight: 9, skipPixels: 0, skipRows: 0, skipImages: 0,
    519      validUnpackParams2D: true, validUnpackParamsForSub2D: true,
    520      validUnpackParams3D: true, validUnpackParamsForSub3D: true },
    521    { width: 7, height: 7, depth: 3, xoffset: 2, yoffset: 4, zoffset: 1,
    522      alignment: 4, rowLength: 0, imageHeight: 10, skipPixels: 0, skipRows: 0, skipImages: 0,
    523      validUnpackParams2D: true, validUnpackParamsForSub2D: true,
    524      validUnpackParams3D: true, validUnpackParamsForSub3D: true },
    525    { width: 8, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
    526      alignment: 8, rowLength: 0, imageHeight: 11, skipPixels: 0, skipRows: 0, skipImages: 0,
    527      validUnpackParams2D: true, validUnpackParamsForSub2D: true,
    528      validUnpackParams3D: true, validUnpackParamsForSub3D: true },
    529 
    530    // SKIP parameters
    531    { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
    532      alignment: 1, rowLength: 0, imageHeight: 0, skipPixels: 10, skipRows: 0, skipImages: 0,
    533      validUnpackParams2D: false, validUnpackParams3D: false },
    534    { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
    535      alignment: 2, rowLength: 0, imageHeight: 0, skipPixels: 2, skipRows: 8, skipImages: 0,
    536      validUnpackParams2D: false, validUnpackParams3D: false },
    537    { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
    538      alignment: 4, rowLength: 0, imageHeight: 0, skipPixels: 3, skipRows: 5, skipImages: 1,
    539      validUnpackParams2D: false, validUnpackParams3D: false },
    540    { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
    541      alignment: 8, rowLength: 0, imageHeight: 0, skipPixels: 7, skipRows: 0, skipImages: 2,
    542      validUnpackParams2D: false, validUnpackParams3D: false },
    543 
    544    // all mixed.
    545    { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
    546      alignment: 1, rowLength: 6, imageHeight: 6, skipPixels: 3, skipRows: 5, skipImages: 1,
    547      validUnpackParams2D: false, validUnpackParams3D: false },
    548    { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
    549      alignment: 2, rowLength: 4, imageHeight: 8, skipPixels: 7, skipRows: 2, skipImages: 2,
    550      validUnpackParams2D: false, validUnpackParams3D: false },
    551    { width: 5, height: 7, depth: 3, xoffset: 2, yoffset: 3, zoffset: 1,
    552      alignment: 4, rowLength: 10, imageHeight: 2, skipPixels: 0, skipRows: 3, skipImages: 1,
    553      validUnpackParams2D: true, validUnpackParamsForSub2D: true,
    554      validUnpackParams3D: false },
    555    { width: 1, height: 1, depth: 1, xoffset: 0, yoffset: 0, zoffset: 0,
    556      alignment: 2, rowLength: 3, imageHeight: 2, skipPixels: 3, skipRows: 5, skipImages: 1,
    557      validUnpackParams2D: false, validUnpackParams3D: false },
    558    { width: 17, height: 6, depth: 4, xoffset: 12, yoffset: 3, zoffset: 2,
    559      alignment: 2, rowLength: 4, imageHeight: 8, skipPixels: 1, skipRows: 4, skipImages: 2,
    560      validUnpackParams2D: false, validUnpackParams3D: false },
    561    { width: 8, height: 17, depth: 3, xoffset: 2, yoffset: 13, zoffset: 1,
    562      alignment: 4, rowLength: 9, imageHeight: 2, skipPixels: 0, skipRows: 3, skipImages: 1,
    563      validUnpackParams2D: true, validUnpackParamsForSub2D: true,
    564      validUnpackParams3D: false },
    565  ];
    566 
    567  // Upload textures from client data
    568  var useUnpackBuffer = false;
    569  for (var ii = 0; ii < testCases.length; ++ii) {
    570    var testCase = testCases[ii];
    571    runTestIteration2D(gl, testCase, useUnpackBuffer);
    572    runTestIteration3D(gl, testCase, useUnpackBuffer);
    573  }
    574 
    575  // Upload textures from unpack buffer
    576  useUnpackBuffer = true;
    577  for (var ii = 0; ii < testCases.length; ++ii) {
    578    var testCase = testCases[ii];
    579    runTestIteration2D(gl, testCase, useUnpackBuffer);
    580    runTestIteration3D(gl, testCase, useUnpackBuffer);
    581  }
    582 }
    583 
    584 runTests();
    585 
    586 debug("");
    587 var successfullyParsed = true;
    588 </script>
    589 <script src="../../../js/js-test-post.js"></script>
    590 </body>
    591 </html>