tor-browser

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

tex-image-and-sub-image-utils.js (31237B)


      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 var TexImageUtils = (function() {
      7 
      8  "use strict";
      9 
     10  var wtu = WebGLTestUtils;
     11 
     12  /**
     13   * A vertex shader for a single texture.
     14   * @type {string}
     15   */
     16  var simpleTextureVertexShaderES3 = [
     17    '#version 300 es',
     18    'in vec4 vPosition;',
     19    'in vec2 texCoord0;',
     20    'out vec2 texCoord;',
     21    'void main() {',
     22    '    gl_Position = vPosition;',
     23    '    texCoord = texCoord0;',
     24    '}'].join('\n');
     25 
     26  /**
     27   * A fragment shader for a single unsigned integer texture.
     28   * @type {string}
     29   */
     30  // Note we always output 1.0 for alpha because if the texture does not contain
     31  // alpha channel, sampling returns 1; for RGBA textures, sampling returns [0,255].
     32  var simpleUintTextureFragmentShaderES3 = [
     33    '#version 300 es',
     34    'precision mediump float;',
     35    'uniform mediump usampler2D tex;',
     36    'in vec2 texCoord;',
     37    'out vec4 fragData;',
     38    'void main() {',
     39    '    uvec4 data = texture(tex, texCoord);',
     40    '    fragData = vec4(float(data[0])/255.0,',
     41    '                    float(data[1])/255.0,',
     42    '                    float(data[2])/255.0,',
     43    '                    1.0);',
     44    '}'].join('\n');
     45 
     46  /**
     47   * A fragment shader for a single signed integer texture.
     48   * @type {string}
     49   */
     50  // Note we always output 1.0 for alpha because if the texture does not contain
     51  // alpha channel, sampling returns 1; for RGBA textures, sampling returns [0,255].
     52  var simpleIntTextureFragmentShaderES3 = [
     53    '#version 300 es',
     54    'precision mediump float;',
     55    'uniform mediump isampler2D tex;',
     56    'in vec2 texCoord;',
     57    'out vec4 fragData;',
     58    'void main() {',
     59    '    ivec4 data = texture(tex, texCoord);',
     60    '    fragData = vec4(float(data[0])/255.0,',
     61    '                    float(data[1])/255.0,',
     62    '                    float(data[2])/255.0,',
     63    '                    1.0);',
     64    '}'].join('\n');
     65 
     66  /**
     67   * A fragment shader for a single cube map unsigned integer texture.
     68   * @type {string}
     69   */
     70  // Note we always output 1.0 for alpha because if the texture does not contain
     71  // alpha channel, sampling returns 1; for RGBA textures, sampling returns [0,255].
     72  var simpleCubeMapUintTextureFragmentShaderES3 = [
     73    '#version 300 es',
     74    'precision mediump float;',
     75    'uniform mediump usamplerCube tex;',
     76    'uniform highp int face;',
     77    'in vec2 texCoord;',
     78    'out vec4 fragData;',
     79    'void main() {',
     80    // Transform [0, 1] -> [-1, 1]
     81    '    vec2 texC2 = (texCoord * 2.) - 1.;',
     82    // Transform 2d tex coord. to each face of TEXTURE_CUBE_MAP coord.
     83    '    vec3 texCube = vec3(0., 0., 0.);',
     84    '    if (face == 34069) {',         // TEXTURE_CUBE_MAP_POSITIVE_X
     85    '        texCube = vec3(1., -texC2.y, -texC2.x);',
     86    '    } else if (face == 34070) {',  // TEXTURE_CUBE_MAP_NEGATIVE_X
     87    '        texCube = vec3(-1., -texC2.y, texC2.x);',
     88    '    } else if (face == 34071) {',  // TEXTURE_CUBE_MAP_POSITIVE_Y
     89    '        texCube = vec3(texC2.x, 1., texC2.y);',
     90    '    } else if (face == 34072) {',  // TEXTURE_CUBE_MAP_NEGATIVE_Y
     91    '        texCube = vec3(texC2.x, -1., -texC2.y);',
     92    '    } else if (face == 34073) {',  // TEXTURE_CUBE_MAP_POSITIVE_Z
     93    '        texCube = vec3(texC2.x, -texC2.y, 1.);',
     94    '    } else if (face == 34074) {',  // TEXTURE_CUBE_MAP_NEGATIVE_Z
     95    '        texCube = vec3(-texC2.x, -texC2.y, -1.);',
     96    '    }',
     97    '    uvec4 data = texture(tex, texCube);',
     98    '    fragData = vec4(float(data[0])/255.0,',
     99    '                    float(data[1])/255.0,',
    100    '                    float(data[2])/255.0,',
    101    '                    1.0);',
    102    '}'].join('\n');
    103 
    104  /**
    105   * A fragment shader for a single cube map signed integer texture.
    106   * @type {string}
    107   */
    108  // Note we always output 1.0 for alpha because if the texture does not contain
    109  // alpha channel, sampling returns 1; for RGBA textures, sampling returns [0,255].
    110  var simpleCubeMapIntTextureFragmentShaderES3 = [
    111    '#version 300 es',
    112    'precision mediump float;',
    113    'uniform mediump isamplerCube tex;',
    114    'uniform highp int face;',
    115    'in vec2 texCoord;',
    116    'out vec4 fragData;',
    117    'void main() {',
    118    // Transform [0, 1] -> [-1, 1]
    119    '    vec2 texC2 = (texCoord * 2.) - 1.;',
    120    // Transform 2d tex coord. to each face of TEXTURE_CUBE_MAP coord.
    121    '    vec3 texCube = vec3(0., 0., 0.);',
    122    '    if (face == 34069) {',         // TEXTURE_CUBE_MAP_POSITIVE_X
    123    '        texCube = vec3(1., -texC2.y, -texC2.x);',
    124    '    } else if (face == 34070) {',  // TEXTURE_CUBE_MAP_NEGATIVE_X
    125    '        texCube = vec3(-1., -texC2.y, texC2.x);',
    126    '    } else if (face == 34071) {',  // TEXTURE_CUBE_MAP_POSITIVE_Y
    127    '        texCube = vec3(texC2.x, 1., texC2.y);',
    128    '    } else if (face == 34072) {',  // TEXTURE_CUBE_MAP_NEGATIVE_Y
    129    '        texCube = vec3(texC2.x, -1., -texC2.y);',
    130    '    } else if (face == 34073) {',  // TEXTURE_CUBE_MAP_POSITIVE_Z
    131    '        texCube = vec3(texC2.x, -texC2.y, 1.);',
    132    '    } else if (face == 34074) {',  // TEXTURE_CUBE_MAP_NEGATIVE_Z
    133    '        texCube = vec3(-texC2.x, -texC2.y, -1.);',
    134    '    }',
    135    '    ivec4 data = texture(tex, texCube);',
    136    '    fragData = vec4(float(data[0])/255.0,',
    137    '                    float(data[1])/255.0,',
    138    '                    float(data[2])/255.0,',
    139    '                    1.0);',
    140    '}'].join('\n');
    141 
    142  /**
    143   * A fragment shader for a single 3D texture.
    144   * @type {string}
    145   */
    146  // Note that the tex coordinate r (the uniform uRCoord) is set to 0.0 by default.
    147  var simple3DTextureFragmentShaderES3 = [
    148    '#version 300 es',
    149    'precision mediump float;',
    150    'uniform mediump sampler3D tex;',
    151    'in vec2 texCoord;',
    152    'uniform float uRCoord;',
    153    'out vec4 fragData;',
    154    'void main() {',
    155    '    fragData = vec4(texture(tex, vec3(texCoord, uRCoord)).rgb, 1.0);',
    156    '}'].join('\n');
    157 
    158  /**
    159   * A fragment shader for a single 3D unsigned integer texture.
    160   * @type {string}
    161   */
    162  // Note that the tex coordinate r (the uniform uRCoord) is set to 0.0 by default.
    163  // Note we always output 1.0 for alpha because if the texture does not contain
    164  // alpha channel, sampling returns 1; for RGBA textures, sampling returns [0,255].
    165  var simple3DUintTextureFragmentShaderES3 = [
    166    '#version 300 es',
    167    'precision mediump float;',
    168    'uniform mediump usampler3D tex;',
    169    'in vec2 texCoord;',
    170    'uniform float uRCoord;',
    171    'out vec4 fragData;',
    172    'void main() {',
    173    '    uvec4 data = texture(tex, vec3(texCoord, uRCoord));',
    174    '    fragData = vec4(float(data[0])/255.0,',
    175    '                    float(data[1])/255.0,',
    176    '                    float(data[2])/255.0,',
    177    '                    1.0);',
    178    '}'].join('\n');
    179 
    180  /**
    181   * A fragment shader for a single 3D signed integer texture.
    182   * @type {string}
    183   */
    184  // Note that the tex coordinate r (the uniform uRCoord) is set to 0.0 by default.
    185  // Note we always output 1.0 for alpha because if the texture does not contain
    186  // alpha channel, sampling returns 1; for RGBA textures, sampling returns [0,255].
    187  var simple3DIntTextureFragmentShaderES3 = [
    188    '#version 300 es',
    189    'precision mediump float;',
    190    'uniform mediump isampler3D tex;',
    191    'in vec2 texCoord;',
    192    'uniform float uRCoord;',
    193    'out vec4 fragData;',
    194    'void main() {',
    195    '    ivec4 data = texture(tex, vec3(texCoord, uRCoord));',
    196    '    fragData = vec4(float(data[0])/255.0,',
    197    '                    float(data[1])/255.0,',
    198    '                    float(data[2])/255.0,',
    199    '                    1.0);',
    200    '}'].join('\n');
    201 
    202  /**
    203   * A fragment shader for a single 2D_ARRAY texture.
    204   * @type {string}
    205   */
    206  // Note that the first image in the array (selected by the uniform
    207  // uRCoord) is used by default.
    208  var simple2DArrayTextureFragmentShaderES3 = [
    209    '#version 300 es',
    210    'precision mediump float;',
    211    'uniform mediump sampler2DArray tex;',
    212    'in vec2 texCoord;',
    213    'uniform float uRCoord;',
    214    'out vec4 fragData;',
    215    'void main() {',
    216    '    fragData = vec4(texture(tex, vec3(texCoord, uRCoord)).rgb, 1.0);',
    217    '}'].join('\n');
    218 
    219  /**
    220   * A fragment shader for a single 2D_ARRAY unsigned integer texture.
    221   * @type {string}
    222   */
    223  // Note that the first image in the array (selected by the uniform
    224  // uRCoord) is used by default.
    225  // Note we always output 1.0 for alpha because if the texture does not contain
    226  // alpha channel, sampling returns 1; for RGBA textures, sampling returns [0,255].
    227  var simple2DArrayUintTextureFragmentShaderES3 = [
    228    '#version 300 es',
    229    'precision mediump float;',
    230    'uniform mediump usampler2DArray tex;',
    231    'in vec2 texCoord;',
    232    'uniform float uRCoord;',
    233    'out vec4 fragData;',
    234    'void main() {',
    235    '    uvec4 data = texture(tex, vec3(texCoord, uRCoord));',
    236    '    fragData = vec4(float(data[0])/255.0,',
    237    '                    float(data[1])/255.0,',
    238    '                    float(data[2])/255.0,',
    239    '                    1.0);',
    240    '}'].join('\n');
    241 
    242  /**
    243   * A fragment shader for a single 2D_ARRAY signed integer texture.
    244   * @type {string}
    245   */
    246  // Note that the first image in the array (selected by the uniform
    247  // uRCoord) is used by default.
    248  // Note we always output 1.0 for alpha because if the texture does not contain
    249  // alpha channel, sampling returns 1; for RGBA textures, sampling returns [0,255].
    250  var simple2DArrayIntTextureFragmentShaderES3 = [
    251    '#version 300 es',
    252    'precision mediump float;',
    253    'uniform mediump isampler2DArray tex;',
    254    'in vec2 texCoord;',
    255    'uniform float uRCoord;',
    256    'out vec4 fragData;',
    257    'void main() {',
    258    '    ivec4 data = texture(tex, vec3(texCoord, uRCoord));',
    259    '    fragData = vec4(float(data[0])/255.0,',
    260    '                    float(data[1])/255.0,',
    261    '                    float(data[2])/255.0,',
    262    '                    1.0);',
    263    '}'].join('\n');
    264 
    265 
    266  /**
    267   * Creates a simple texture vertex shader.
    268   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
    269   * @return {!WebGLShader}
    270   */
    271  var setupSimpleTextureVertexShader = function(gl) {
    272    return WebGLTestUtils.loadShader(gl, simpleTextureVertexShaderES3, gl.VERTEX_SHADER);
    273  };
    274 
    275  /**
    276   * Creates a simple unsigned integer texture fragment shader.
    277   * Output is scaled by 1/255 to bring the result into normalized float range.
    278   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
    279   * @return {!WebGLShader}
    280   */
    281  var setupSimpleUintTextureFragmentShader = function(gl) {
    282    return WebGLTestUtils.loadShader(gl, simpleUintTextureFragmentShaderES3, gl.FRAGMENT_SHADER);
    283  };
    284 
    285  /**
    286   * Creates a simple signed integer texture fragment shader.
    287   * Output is scaled by 1/255 to bring the result into normalized float range.
    288   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
    289   * @return {!WebGLShader}
    290   */
    291  var setupSimpleIntTextureFragmentShader = function(gl) {
    292    return WebGLTestUtils.loadShader(gl, simpleIntTextureFragmentShaderES3, gl.FRAGMENT_SHADER);
    293  };
    294 
    295  /**
    296   * Creates a simple cube map unsigned integer texture fragment shader.
    297   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
    298   * @return {!WebGLShader}
    299   */
    300  var setupSimpleCubeMapUintTextureFragmentShader = function(gl) {
    301    return WebGLTestUtils.loadShader(gl, simpleCubeMapUintTextureFragmentShaderES3, gl.FRAGMENT_SHADER);
    302  };
    303 
    304  /**
    305   * Creates a simple cube map signed integer texture fragment shader.
    306   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
    307   * @return {!WebGLShader}
    308   */
    309  var setupSimpleCubeMapIntTextureFragmentShader = function(gl) {
    310    return WebGLTestUtils.loadShader(gl, simpleCubeMapIntTextureFragmentShaderES3, gl.FRAGMENT_SHADER);
    311  };
    312 
    313  /**
    314   * Creates a simple 3D texture fragment shader.
    315   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
    316   * @return {!WebGLShader}
    317   */
    318  var setupSimple3DTextureFragmentShader = function(gl) {
    319    return WebGLTestUtils.loadShader(gl, simple3DTextureFragmentShaderES3, gl.FRAGMENT_SHADER);
    320  };
    321 
    322  /**
    323   * Creates a simple 3D unsigned integer texture fragment shader.
    324   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
    325   * @return {!WebGLShader}
    326   */
    327  var setupSimple3DUintTextureFragmentShader = function(gl) {
    328    return WebGLTestUtils.loadShader(gl, simple3DUintTextureFragmentShaderES3, gl.FRAGMENT_SHADER);
    329  };
    330 
    331  /**
    332   * Creates a simple 3D signed integer texture fragment shader.
    333   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
    334   * @return {!WebGLShader}
    335   */
    336  var setupSimple3DIntTextureFragmentShader = function(gl) {
    337    return WebGLTestUtils.loadShader(gl, simple3DIntTextureFragmentShaderES3, gl.FRAGMENT_SHADER);
    338  };
    339 
    340  /**
    341   * Creates a simple 2D_ARRAY texture fragment shader.
    342   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
    343   * @return {!WebGLShader}
    344   */
    345  var setupSimple2DArrayTextureFragmentShader = function(gl) {
    346    return WebGLTestUtils.loadShader(gl, simple2DArrayTextureFragmentShaderES3, gl.FRAGMENT_SHADER);
    347  };
    348 
    349  /**
    350   * Creates a simple 2D_ARRAY integer texture fragment shader.
    351   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
    352   * @return {!WebGLShader}
    353   */
    354  var setupSimple2DArrayUintTextureFragmentShader = function(gl) {
    355    return WebGLTestUtils.loadShader(gl, simple2DArrayUintTextureFragmentShaderES3, gl.FRAGMENT_SHADER);
    356  };
    357 
    358  /**
    359   * Creates a simple unsigned integer texture program.
    360   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
    361   * @param {number} opt_positionLocation The attrib location for position.
    362   * @param {number} opt_texcoordLocation The attrib location for texture coords.
    363   * @return {WebGLProgram}
    364   */
    365  var setupSimpleUintTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation)
    366  {
    367    opt_positionLocation = opt_positionLocation || 0;
    368    opt_texcoordLocation = opt_texcoordLocation || 1;
    369    var vs = setupSimpleTextureVertexShader(gl),
    370        fs = setupSimpleUintTextureFragmentShader(gl);
    371    if (!vs || !fs) {
    372      return null;
    373    }
    374    var program = WebGLTestUtils.setupProgram(
    375      gl,
    376      [vs, fs],
    377      ['vPosition', 'texCoord0'],
    378      [opt_positionLocation, opt_texcoordLocation]);
    379    if (!program) {
    380      gl.deleteShader(fs);
    381      gl.deleteShader(vs);
    382    }
    383    gl.useProgram(program);
    384    return program;
    385  };
    386 
    387  /**
    388   * Creates a simple signed integer texture program.
    389   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
    390   * @param {number} opt_positionLocation The attrib location for position.
    391   * @param {number} opt_texcoordLocation The attrib location for texture coords.
    392   * @return {WebGLProgram}
    393   */
    394  var setupSimpleIntTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation)
    395  {
    396    opt_positionLocation = opt_positionLocation || 0;
    397    opt_texcoordLocation = opt_texcoordLocation || 1;
    398    var vs = setupSimpleTextureVertexShader(gl),
    399        fs = setupSimpleIntTextureFragmentShader(gl);
    400    if (!vs || !fs) {
    401      return null;
    402    }
    403    var program = WebGLTestUtils.setupProgram(
    404      gl,
    405      [vs, fs],
    406      ['vPosition', 'texCoord0'],
    407      [opt_positionLocation, opt_texcoordLocation]);
    408    if (!program) {
    409      gl.deleteShader(fs);
    410      gl.deleteShader(vs);
    411    }
    412    gl.useProgram(program);
    413    return program;
    414  };
    415 
    416  /**
    417   * Creates a simple cube map unsigned integer texture program.
    418   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
    419   * @param {number} opt_positionLocation The attrib location for position.
    420   * @param {number} opt_texcoordLocation The attrib location for texture coords.
    421   * @return {WebGLProgram}
    422   */
    423  var setupSimpleCubeMapUintTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation) {
    424    opt_positionLocation = opt_positionLocation || 0;
    425    opt_texcoordLocation = opt_texcoordLocation || 1;
    426    var vs = setupSimpleTextureVertexShader(gl);
    427    var fs = setupSimpleCubeMapUintTextureFragmentShader(gl);
    428    if (!vs || !fs) {
    429      return null;
    430    }
    431    var program = WebGLTestUtils.setupProgram(
    432      gl,
    433      [vs, fs],
    434      ['vPosition', 'texCoord0'],
    435      [opt_positionLocation, opt_texcoordLocation]);
    436    if (!program) {
    437      gl.deleteShader(fs);
    438      gl.deleteShader(vs);
    439    }
    440    gl.useProgram(program);
    441    return program;
    442  };
    443 
    444  /**
    445   * Creates a simple cube map signed integer texture program.
    446   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
    447   * @param {number} opt_positionLocation The attrib location for position.
    448   * @param {number} opt_texcoordLocation The attrib location for texture coords.
    449   * @return {WebGLProgram}
    450   */
    451  var setupSimpleCubeMapIntTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation) {
    452    opt_positionLocation = opt_positionLocation || 0;
    453    opt_texcoordLocation = opt_texcoordLocation || 1;
    454    var vs = setupSimpleTextureVertexShader(gl);
    455    var fs = setupSimpleCubeMapIntTextureFragmentShader(gl);
    456    if (!vs || !fs) {
    457      return null;
    458    }
    459    var program = WebGLTestUtils.setupProgram(
    460      gl,
    461      [vs, fs],
    462      ['vPosition', 'texCoord0'],
    463      [opt_positionLocation, opt_texcoordLocation]);
    464    if (!program) {
    465      gl.deleteShader(fs);
    466      gl.deleteShader(vs);
    467    }
    468    gl.useProgram(program);
    469    return program;
    470  };
    471 
    472  /**
    473   * Creates a simple 3D texture program.
    474   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
    475   * @param {number} opt_positionLocation The attrib location for position.
    476   * @param {number} opt_texcoordLocation The attrib location for texture coords.
    477   * @return {WebGLProgram}
    478   */
    479  var setupSimple3DTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation)
    480  {
    481    opt_positionLocation = opt_positionLocation || 0;
    482    opt_texcoordLocation = opt_texcoordLocation || 1;
    483    var vs = setupSimpleTextureVertexShader(gl),
    484        fs = setupSimple3DTextureFragmentShader(gl);
    485    if (!vs || !fs) {
    486      return null;
    487    }
    488    var program = WebGLTestUtils.setupProgram(
    489      gl,
    490      [vs, fs],
    491      ['vPosition', 'texCoord0'],
    492      [opt_positionLocation, opt_texcoordLocation]);
    493    if (!program) {
    494      gl.deleteShader(fs);
    495      gl.deleteShader(vs);
    496    }
    497    gl.useProgram(program);
    498    return program;
    499  };
    500 
    501  /**
    502   * Creates a simple 3D unsigned integer texture program.
    503   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
    504   * @param {number} opt_positionLocation The attrib location for position.
    505   * @param {number} opt_texcoordLocation The attrib location for texture coords.
    506   * @return {WebGLProgram}
    507   */
    508  var setupSimple3DUintTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation)
    509  {
    510    opt_positionLocation = opt_positionLocation || 0;
    511    opt_texcoordLocation = opt_texcoordLocation || 1;
    512    var vs = setupSimpleTextureVertexShader(gl),
    513        fs = setupSimple3DUintTextureFragmentShader(gl);
    514    if (!vs || !fs) {
    515      return null;
    516    }
    517    var program = WebGLTestUtils.setupProgram(
    518      gl,
    519      [vs, fs],
    520      ['vPosition', 'texCoord0'],
    521      [opt_positionLocation, opt_texcoordLocation]);
    522    if (!program) {
    523      gl.deleteShader(fs);
    524      gl.deleteShader(vs);
    525    }
    526    gl.useProgram(program);
    527    return program;
    528  };
    529 
    530  /**
    531   * Creates a simple 3D signed integer texture program.
    532   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
    533   * @param {number} opt_positionLocation The attrib location for position.
    534   * @param {number} opt_texcoordLocation The attrib location for texture coords.
    535   * @return {WebGLProgram}
    536   */
    537  var setupSimple3DIntTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation)
    538  {
    539    opt_positionLocation = opt_positionLocation || 0;
    540    opt_texcoordLocation = opt_texcoordLocation || 1;
    541    var vs = setupSimpleTextureVertexShader(gl),
    542        fs = setupSimple3DIntTextureFragmentShader(gl);
    543    if (!vs || !fs) {
    544      return null;
    545    }
    546    var program = WebGLTestUtils.setupProgram(
    547      gl,
    548      [vs, fs],
    549      ['vPosition', 'texCoord0'],
    550      [opt_positionLocation, opt_texcoordLocation]);
    551    if (!program) {
    552      gl.deleteShader(fs);
    553      gl.deleteShader(vs);
    554    }
    555    gl.useProgram(program);
    556    return program;
    557  };
    558 
    559  /**
    560   * Creates a simple 2D_ARRAY texture program.
    561   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
    562   * @param {number} opt_positionLocation The attrib location for position.
    563   * @param {number} opt_texcoordLocation The attrib location for texture coords.
    564   * @return {WebGLProgram}
    565   */
    566  var setupSimple2DArrayTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation)
    567  {
    568    opt_positionLocation = opt_positionLocation || 0;
    569    opt_texcoordLocation = opt_texcoordLocation || 1;
    570    var vs = setupSimpleTextureVertexShader(gl),
    571        fs = setupSimple2DArrayTextureFragmentShader(gl);
    572    if (!vs || !fs) {
    573      return null;
    574    }
    575    var program = WebGLTestUtils.setupProgram(
    576      gl,
    577      [vs, fs],
    578      ['vPosition', 'texCoord0'],
    579      [opt_positionLocation, opt_texcoordLocation]);
    580    if (!program) {
    581      gl.deleteShader(fs);
    582      gl.deleteShader(vs);
    583    }
    584    gl.useProgram(program);
    585    return program;
    586  };
    587 
    588  /**
    589   * Creates a simple 2D_ARRAY unsigned integer texture program.
    590   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
    591   * @param {number} opt_positionLocation The attrib location for position.
    592   * @param {number} opt_texcoordLocation The attrib location for texture coords.
    593   * @return {WebGLProgram}
    594   */
    595  var setupSimple2DArrayUintTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation)
    596  {
    597    opt_positionLocation = opt_positionLocation || 0;
    598    opt_texcoordLocation = opt_texcoordLocation || 1;
    599    var vs = setupSimpleTextureVertexShader(gl),
    600        fs = setupSimple2DArrayUintTextureFragmentShader(gl);
    601    if (!vs || !fs) {
    602      return null;
    603    }
    604    var program = WebGLTestUtils.setupProgram(
    605      gl,
    606      [vs, fs],
    607      ['vPosition', 'texCoord0'],
    608      [opt_positionLocation, opt_texcoordLocation]);
    609    if (!program) {
    610      gl.deleteShader(fs);
    611      gl.deleteShader(vs);
    612    }
    613    gl.useProgram(program);
    614    return program;
    615  };
    616 
    617  /**
    618   * Creates a simple 2D_ARRAY signed integer texture program.
    619   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
    620   * @param {number} opt_positionLocation The attrib location for position.
    621   * @param {number} opt_texcoordLocation The attrib location for texture coords.
    622   * @return {WebGLProgram}
    623   */
    624  var setupSimple2DArrayIntTextureProgram = function(gl, opt_positionLocation, opt_texcoordLocation)
    625  {
    626    opt_positionLocation = opt_positionLocation || 0;
    627    opt_texcoordLocation = opt_texcoordLocation || 1;
    628    var vs = setupSimpleTextureVertexShader(gl),
    629        fs = setupSimple2DArrayIntTextureFragmentShader(gl);
    630    if (!vs || !fs) {
    631      return null;
    632    }
    633    var program = WebGLTestUtils.setupProgram(
    634      gl,
    635      [vs, fs],
    636      ['vPosition', 'texCoord0'],
    637      [opt_positionLocation, opt_texcoordLocation]);
    638    if (!program) {
    639      gl.deleteShader(fs);
    640      gl.deleteShader(vs);
    641    }
    642    gl.useProgram(program);
    643    return program;
    644  };
    645 
    646  /**
    647   * Creates a program and buffers for rendering a unsigned integer textured quad.
    648   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
    649   * @return {!WebGLProgram}
    650   */
    651  var setupUintTexturedQuad = function(gl) {
    652    var program = setupSimpleUintTextureProgram(gl);
    653    wtu.setupUnitQuad(gl);
    654    return program;
    655  };
    656 
    657  /**
    658   * Creates a program and buffers for rendering a signed integer textured quad.
    659   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
    660   * @return {!WebGLProgram}
    661   */
    662  var setupIntTexturedQuad = function(gl) {
    663    var program = setupSimpleIntTextureProgram(gl);
    664    wtu.setupUnitQuad(gl);
    665    return program;
    666  };
    667 
    668  /**
    669   * Creates a program and buffers for rendering a textured quad with
    670   * a cube map unsigned integer texture.
    671   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
    672   * @return {!WebGLProgram}
    673   */
    674  var setupUintTexturedQuadWithCubeMap = function(gl)
    675  {
    676    var program = setupSimpleCubeMapUintTextureProgram(gl);
    677    wtu.setupUnitQuad(gl);
    678    return program;
    679  };
    680 
    681  /**
    682   * Creates a program and buffers for rendering a textured quad with
    683   * a cube map signed integer texture.
    684   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
    685   * @return {!WebGLProgram}
    686   */
    687  var setupIntTexturedQuadWithCubeMap = function(gl)
    688  {
    689    var program = setupSimpleCubeMapIntTextureProgram(gl);
    690    wtu.setupUnitQuad(gl);
    691    return program;
    692  };
    693 
    694  /**
    695   * Does the GL internal format represent an unsigned integer format
    696   * texture?
    697   * @return {boolean}
    698   */
    699  var isUintFormat = function(internalFormat)
    700  {
    701    return (internalFormat == "R8UI" || internalFormat == "RG8UI" || internalFormat == "RGB8UI" || internalFormat == "RGBA8UI" ||
    702            internalFormat == "R16UI" || internalFormat == "RG16UI" || internalFormat == "RGB16UI" || internalFormat == "RGBA16UI" ||
    703            internalFormat == "R32UI" || internalFormat == "RG32UI" || internalFormat == "RGB32UI" || internalFormat == "RGBA32UI");
    704  };
    705 
    706  /**
    707   * Does the GL internal format represent an signed integer format
    708   * texture?
    709   * @return {boolean}
    710   */
    711  var isIntFormat = function(internalFormat)
    712  {
    713    return (internalFormat == "R8I" || internalFormat == "RG8I" || internalFormat == "RGB8I" || internalFormat == "RGBA8I" ||
    714            internalFormat == "R16I" || internalFormat == "RG16I" || internalFormat == "RGB16I" || internalFormat == "RGBA16I" ||
    715            internalFormat == "R32I" || internalFormat == "RG32I" || internalFormat == "RGB32I" || internalFormat == "RGBA32I");
    716  };
    717 
    718  /**
    719   * Createa a program and buffers for rendering a textured quad for
    720   * tex-image-and-sub-image tests. Handle selection of correct
    721   * program to handle texture format.
    722   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
    723   * @param {string} internalFormat The internal format for texture to be tested.
    724   */
    725  var setupTexturedQuad = function(gl, internalFormat)
    726  {
    727    if (isUintFormat(internalFormat))
    728      return setupUintTexturedQuad(gl);
    729    if (isIntFormat(internalFormat))
    730      return setupIntTexturedQuad(gl);
    731    return wtu.setupTexturedQuad(gl);
    732  };
    733 
    734  /**
    735   * Createa a program and buffers for rendering a textured quad with
    736   * a cube map for tex-image-and-sub-image tests. Handle selection of
    737   * correct program to handle texture format.
    738   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
    739   * @param {string} internalFormat The internal format for texture to be tested.
    740   */
    741  function setupTexturedQuadWithCubeMap(gl, internalFormat)
    742  {
    743    if (isUintFormat(internalFormat))
    744      return setupUintTexturedQuadWithCubeMap(gl);
    745    if (isIntFormat(internalFormat))
    746      return setupIntTexturedQuadWithCubeMap(gl);
    747    return wtu.setupTexturedQuadWithCubeMap(gl);
    748  }
    749 
    750  /**
    751   * Createa a program and buffers for rendering a textured quad with a 3D texture
    752   * for tex-image-and-sub-image tests. Handle selection of correct
    753   * program to handle texture format.
    754   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
    755   * @param {string} internalFormat The internal format for texture to be tested.
    756   */
    757  var setupTexturedQuadWith3D = function(gl, internalFormat)
    758  {
    759    var program;
    760    if (isUintFormat(internalFormat))
    761      program = setupSimple3DUintTextureProgram(gl);
    762    else if (isIntFormat(internalFormat))
    763      program = setupSimple3DIntTextureProgram(gl);
    764    else
    765      program = setupSimple3DTextureProgram(gl);
    766    var uRCoordLoc = gl.getUniformLocation(program, 'uRCoord');
    767    gl.uniform1f(uRCoordLoc, 0.0);
    768    wtu.setupUnitQuad(gl);
    769    return program;
    770  };
    771 
    772  /**
    773   * Createa a program and buffers for rendering a textured quad with a 2D_ARRAY
    774   * texture for tex-image-and-sub-image tests. Handle selection of correct
    775   * program to handle texture format.
    776   * @param {!WebGLRenderingContext} gl The WebGLRenderingContext to use.
    777   * @param {string} internalFormat The internal format for texture to be tested.
    778   */
    779  var setupTexturedQuadWith2DArray = function(gl, internalFormat)
    780  {
    781    var program;
    782    if (isUintFormat(internalFormat))
    783      program = setupSimple2DArrayUintTextureProgram(gl);
    784    else if (isIntFormat(internalFormat))
    785      program = setupSimple2DArrayIntTextureProgram(gl);
    786    else
    787      program = setupSimple2DArrayTextureProgram(gl);
    788    var uRCoordLoc = gl.getUniformLocation(program, 'uRCoord');
    789    gl.uniform1f(uRCoordLoc, 0.0);
    790    wtu.setupUnitQuad(gl);
    791    return program;
    792  };
    793 
    794  /**
    795   * Return a list of unpack color spaces to test, supported by the specified
    796   * WebGLRenderingContext.
    797   */
    798  var unpackColorSpacesToTest = function(gl)
    799  {
    800    if ('unpackColorSpace' in gl)
    801      return ['srgb', 'display-p3'];
    802    else
    803      return [undefined];
    804  }
    805 
    806  /**
    807   * For each entry in unpackColorSpaces, duplicate all of cases, adding an
    808   * unpackColorSpace key with its value set to that entry to each case.
    809   */
    810  var crossProductTestCasesWithUnpackColorSpaces = function(testCaseList, unpackColorSpaces)
    811  {
    812    var testCaseWithUnpackColorSpace = function(testCase, colorSpace)
    813    {
    814      return {...testCase, ...{unpackColorSpace:colorSpace}};
    815    }
    816    var listOfTestCaseLists = unpackColorSpaces.map(colorSpace =>
    817        testCaseList.map(testCase => testCaseWithUnpackColorSpace(testCase, colorSpace)));
    818    return listOfTestCaseLists.flat();
    819  }
    820 
    821  /**
    822   * Given given an internalformat, format, and type, return the tolerance
    823   * that should be used when comparing an input 8-bit value to one that has
    824   * been truncated through the specified formats.
    825   */
    826  var tolerance = function(internalformat, format, type) {
    827    function typeTolerance(type) {
    828      switch(type) {
    829        case 'UNSIGNED_SHORT_5_6_5':
    830        case 'UNSIGNED_SHORT_5_5_5_1':
    831          return 255 / 31;
    832        case 'UNSIGNED_SHORT_4_4_4_4':
    833          return 255 / 15;
    834          break;
    835        default:
    836          return 1;
    837      }
    838    };
    839    function formatTolerance(format) {
    840      switch(format) {
    841        case 'RGB565':
    842        case 'RGB5_A1':
    843          return 255/31;
    844        case 'RGBA4':
    845          return 255/15;
    846        default:
    847          return 1;
    848      }
    849    };
    850    return Math.max(formatTolerance(internalformat),
    851                    formatTolerance(format),
    852                    typeTolerance(type));
    853  }
    854 
    855  return {
    856    setupTexturedQuad: setupTexturedQuad,
    857    setupTexturedQuadWithCubeMap: setupTexturedQuadWithCubeMap,
    858    setupTexturedQuadWith3D: setupTexturedQuadWith3D,
    859    setupTexturedQuadWith2DArray: setupTexturedQuadWith2DArray,
    860    unpackColorSpacesToTest: unpackColorSpacesToTest,
    861    crossProductTestCasesWithUnpackColorSpaces: crossProductTestCasesWithUnpackColorSpaces,
    862    tolerance: tolerance
    863  };
    864 
    865 }());