tor-browser

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

framebuffer-render-to-layer.html (25246B)


      1 <!--
      2 Copyright (c) 2020 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 can render to layers in 3D and 2D_ARRAY textures</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 <script id="vshader" type="x-shader/x-vertex">#version 300 es
     16 void main(void) {
     17  gl_Position = vec4(0, 0, 0, 1);
     18  gl_PointSize = 1.0;
     19 }
     20 </script>
     21 </head>
     22 <body>
     23 <canvas id="example" width="100", height="100"></canvas>
     24 <div id="description"></div>
     25 <div id="console"></div>
     26 <script>
     27 "use strict";
     28 debug("");
     29 
     30 description("Test that WebGL2 can render to layers in 3D and 2D_ARRAY textures");
     31 
     32 var wtu = WebGLTestUtils;
     33 var gl = wtu.create3DContext("example", undefined, 2);
     34 
     35 if (!gl) {
     36    testFailed("WebGL context creation failed");
     37 } else {
     38    testPassed("WebGL context creation succeeded");
     39    runTest();
     40 }
     41 
     42 function runTest() {
     43    const texWidth = 1;
     44    const texHeight = 1;
     45    const texDepth = 2;
     46 
     47    function makeFragmentShader(typeInfo) {
     48        const src = `#version 300 es
     49            precision mediump float;
     50            out ${typeInfo.outType} color;
     51            void main() {
     52                color = ${typeInfo.outValue};
     53            }
     54        `;
     55        return src;
     56    }
     57 
     58  const textureInternalFormatInfo = {};
     59  {
     60      const t = textureInternalFormatInfo;
     61      // unsized formats
     62      // If understand correctly these 3 unsized formats are not required to be color renderable
     63      t[gl.ALPHA]              = { textureFormat: gl.ALPHA,           colorRenderable: false, textureFilterable: true,  bytesPerElement: [1, 2, 2, 4],        type: [gl.UNSIGNED_BYTE, gl.HALF_FLOAT, gl.HALF_FLOAT_OES, gl.FLOAT], };
     64      t[gl.LUMINANCE]          = { textureFormat: gl.LUMINANCE,       colorRenderable: false, textureFilterable: true,  bytesPerElement: [1, 2, 2, 4],        type: [gl.UNSIGNED_BYTE, gl.HALF_FLOAT, gl.HALF_FLOAT_OES, gl.FLOAT], };
     65      t[gl.LUMINANCE_ALPHA]    = { textureFormat: gl.LUMINANCE_ALPHA, colorRenderable: false, textureFilterable: true,  bytesPerElement: [2, 4, 4, 8],        type: [gl.UNSIGNED_BYTE, gl.HALF_FLOAT, gl.HALF_FLOAT_OES, gl.FLOAT], };
     66 
     67      t[gl.RGB]                = { textureFormat: gl.RGB,             colorRenderable: true,  textureFilterable: true,  bytesPerElement: [3, 6, 6, 12, 2],    type: [gl.UNSIGNED_BYTE, gl.HALF_FLOAT, gl.HALF_FLOAT_OES, gl.FLOAT, gl.UNSIGNED_SHORT_5_6_5], };
     68      t[gl.RGBA]               = { textureFormat: gl.RGBA,            colorRenderable: true,  textureFilterable: true,  bytesPerElement: [4, 8, 8, 16, 2, 2], type: [gl.UNSIGNED_BYTE, gl.HALF_FLOAT, gl.HALF_FLOAT_OES, gl.FLOAT, gl.UNSIGNED_SHORT_4_4_4_4, gl.UNSIGNED_SHORT_5_5_5_1], };
     69 
     70      // sized formats
     71      t[gl.R8]                 = { textureFormat: gl.RED,             colorRenderable: true,  textureFilterable: true,  bytesPerElement: [1],        type: [gl.UNSIGNED_BYTE], };
     72      t[gl.R8_SNORM]           = { textureFormat: gl.RED,             colorRenderable: false, textureFilterable: true,  bytesPerElement: [1],        type: [gl.BYTE], };
     73      t[gl.R16F]               = { textureFormat: gl.RED,             colorRenderable: false, textureFilterable: true,  bytesPerElement: [4, 2],     type: [gl.FLOAT, gl.HALF_FLOAT], };
     74      t[gl.R32F]               = { textureFormat: gl.RED,             colorRenderable: false, textureFilterable: false, bytesPerElement: [4],        type: [gl.FLOAT], };
     75      t[gl.R8UI]               = { textureFormat: gl.RED_INTEGER,     colorRenderable: true,  textureFilterable: false, bytesPerElement: [1],        type: [gl.UNSIGNED_BYTE], };
     76      t[gl.R8I]                = { textureFormat: gl.RED_INTEGER,     colorRenderable: true,  textureFilterable: false, bytesPerElement: [1],        type: [gl.BYTE], };
     77      t[gl.R16UI]              = { textureFormat: gl.RED_INTEGER,     colorRenderable: true,  textureFilterable: false, bytesPerElement: [2],        type: [gl.UNSIGNED_SHORT], };
     78      t[gl.R16I]               = { textureFormat: gl.RED_INTEGER,     colorRenderable: true,  textureFilterable: false, bytesPerElement: [2],        type: [gl.SHORT], };
     79      t[gl.R32UI]              = { textureFormat: gl.RED_INTEGER,     colorRenderable: true,  textureFilterable: false, bytesPerElement: [4],        type: [gl.UNSIGNED_INT], };
     80      t[gl.R32I]               = { textureFormat: gl.RED_INTEGER,     colorRenderable: true,  textureFilterable: false, bytesPerElement: [4],        type: [gl.INT], };
     81      t[gl.RG8]                = { textureFormat: gl.RG,              colorRenderable: true,  textureFilterable: true,  bytesPerElement: [2],        type: [gl.UNSIGNED_BYTE], };
     82      t[gl.RG8_SNORM]          = { textureFormat: gl.RG,              colorRenderable: false, textureFilterable: true,  bytesPerElement: [2],        type: [gl.BYTE], };
     83      t[gl.RG16F]              = { textureFormat: gl.RG,              colorRenderable: false, textureFilterable: true,  bytesPerElement: [8, 4],     type: [gl.FLOAT, gl.HALF_FLOAT], };
     84      t[gl.RG32F]              = { textureFormat: gl.RG,              colorRenderable: false, textureFilterable: false, bytesPerElement: [8],        type: [gl.FLOAT], };
     85      t[gl.RG8UI]              = { textureFormat: gl.RG_INTEGER,      colorRenderable: true,  textureFilterable: false, bytesPerElement: [2],        type: [gl.UNSIGNED_BYTE], };
     86      t[gl.RG8I]               = { textureFormat: gl.RG_INTEGER,      colorRenderable: true,  textureFilterable: false, bytesPerElement: [2],        type: [gl.BYTE], };
     87      t[gl.RG16UI]             = { textureFormat: gl.RG_INTEGER,      colorRenderable: true,  textureFilterable: false, bytesPerElement: [4],        type: [gl.UNSIGNED_SHORT], };
     88      t[gl.RG16I]              = { textureFormat: gl.RG_INTEGER,      colorRenderable: true,  textureFilterable: false, bytesPerElement: [4],        type: [gl.SHORT], };
     89      t[gl.RG32UI]             = { textureFormat: gl.RG_INTEGER,      colorRenderable: true,  textureFilterable: false, bytesPerElement: [8],        type: [gl.UNSIGNED_INT], };
     90      t[gl.RG32I]              = { textureFormat: gl.RG_INTEGER,      colorRenderable: true,  textureFilterable: false, bytesPerElement: [8],        type: [gl.INT], };
     91      t[gl.RGB8]               = { textureFormat: gl.RGB,             colorRenderable: true,  textureFilterable: true,  bytesPerElement: [3],        type: [gl.UNSIGNED_BYTE], };
     92      t[gl.SRGB8]              = { textureFormat: gl.RGB,             colorRenderable: false, textureFilterable: true,  bytesPerElement: [3],        type: [gl.UNSIGNED_BYTE], };
     93      t[gl.RGB565]             = { textureFormat: gl.RGB,             colorRenderable: true,  textureFilterable: true,  bytesPerElement: [3, 2],     type: [gl.UNSIGNED_BYTE, gl.UNSIGNED_SHORT_5_6_5], };
     94      t[gl.RGB8_SNORM]         = { textureFormat: gl.RGB,             colorRenderable: false, textureFilterable: true,  bytesPerElement: [3],        type: [gl.BYTE], };
     95      t[gl.R11F_G11F_B10F]     = { textureFormat: gl.RGB,             colorRenderable: false, textureFilterable: true,  bytesPerElement: [12, 6, 4], type: [gl.FLOAT, gl.HALF_FLOAT, gl.UNSIGNED_INT_10F_11F_11F_REV], };
     96      t[gl.RGB9_E5]            = { textureFormat: gl.RGB,             colorRenderable: false, textureFilterable: true,  bytesPerElement: [12, 6, 4], type: [gl.FLOAT, gl.HALF_FLOAT, gl.UNSIGNED_INT_5_9_9_9_REV], };
     97      t[gl.RGB16F]             = { textureFormat: gl.RGB,             colorRenderable: false, textureFilterable: true,  bytesPerElement: [12, 6],    type: [gl.FLOAT, gl.HALF_FLOAT], };
     98      t[gl.RGB32F]             = { textureFormat: gl.RGB,             colorRenderable: false, textureFilterable: false, bytesPerElement: [12],       type: [gl.FLOAT], };
     99      t[gl.RGB8UI]             = { textureFormat: gl.RGB_INTEGER,     colorRenderable: false, textureFilterable: false, bytesPerElement: [3],        type: [gl.UNSIGNED_BYTE], };
    100      t[gl.RGB8I]              = { textureFormat: gl.RGB_INTEGER,     colorRenderable: false, textureFilterable: false, bytesPerElement: [3],        type: [gl.BYTE], };
    101      t[gl.RGB16UI]            = { textureFormat: gl.RGB_INTEGER,     colorRenderable: false, textureFilterable: false, bytesPerElement: [6],        type: [gl.UNSIGNED_SHORT], };
    102      t[gl.RGB16I]             = { textureFormat: gl.RGB_INTEGER,     colorRenderable: false, textureFilterable: false, bytesPerElement: [6],        type: [gl.SHORT], };
    103      t[gl.RGB32UI]            = { textureFormat: gl.RGB_INTEGER,     colorRenderable: false, textureFilterable: false, bytesPerElement: [12],       type: [gl.UNSIGNED_INT], };
    104      t[gl.RGB32I]             = { textureFormat: gl.RGB_INTEGER,     colorRenderable: false, textureFilterable: false, bytesPerElement: [12],       type: [gl.INT], };
    105      t[gl.RGBA8]              = { textureFormat: gl.RGBA,            colorRenderable: true,  textureFilterable: true,  bytesPerElement: [4],        type: [gl.UNSIGNED_BYTE], };
    106      t[gl.SRGB8_ALPHA8]       = { textureFormat: gl.RGBA,            colorRenderable: true,  textureFilterable: true,  bytesPerElement: [4],        type: [gl.UNSIGNED_BYTE], };
    107      t[gl.RGBA8_SNORM]        = { textureFormat: gl.RGBA,            colorRenderable: false, textureFilterable: true,  bytesPerElement: [4],        type: [gl.BYTE], };
    108      t[gl.RGB5_A1]            = { textureFormat: gl.RGBA,            colorRenderable: true,  textureFilterable: true,  bytesPerElement: [4, 2, 4],  type: [gl.UNSIGNED_BYTE, gl.UNSIGNED_SHORT_5_5_5_1, gl.UNSIGNED_INT_2_10_10_10_REV], };
    109      t[gl.RGBA4]              = { textureFormat: gl.RGBA,            colorRenderable: true,  textureFilterable: true,  bytesPerElement: [4, 2],     type: [gl.UNSIGNED_BYTE, gl.UNSIGNED_SHORT_4_4_4_4], };
    110      t[gl.RGB10_A2]           = { textureFormat: gl.RGBA,            colorRenderable: true,  textureFilterable: true,  bytesPerElement: [4],        type: [gl.UNSIGNED_INT_2_10_10_10_REV], };
    111      t[gl.RGBA16F]            = { textureFormat: gl.RGBA,            colorRenderable: false, textureFilterable: true,  bytesPerElement: [16, 8],    type: [gl.FLOAT, gl.HALF_FLOAT], };
    112      t[gl.RGBA32F]            = { textureFormat: gl.RGBA,            colorRenderable: false, textureFilterable: false, bytesPerElement: [16],       type: [gl.FLOAT], };
    113      t[gl.RGBA8UI]            = { textureFormat: gl.RGBA_INTEGER,    colorRenderable: true,  textureFilterable: false, bytesPerElement: [4],        type: [gl.UNSIGNED_BYTE], };
    114      t[gl.RGBA8I]             = { textureFormat: gl.RGBA_INTEGER,    colorRenderable: true,  textureFilterable: false, bytesPerElement: [4],        type: [gl.BYTE], };
    115      t[gl.RGB10_A2UI]         = { textureFormat: gl.RGBA_INTEGER,    colorRenderable: true,  textureFilterable: false, bytesPerElement: [4],        type: [gl.UNSIGNED_INT_2_10_10_10_REV], };
    116      t[gl.RGBA16UI]           = { textureFormat: gl.RGBA_INTEGER,    colorRenderable: true,  textureFilterable: false, bytesPerElement: [8],        type: [gl.UNSIGNED_SHORT], };
    117      t[gl.RGBA16I]            = { textureFormat: gl.RGBA_INTEGER,    colorRenderable: true,  textureFilterable: false, bytesPerElement: [8],        type: [gl.SHORT], };
    118      t[gl.RGBA32I]            = { textureFormat: gl.RGBA_INTEGER,    colorRenderable: true,  textureFilterable: false, bytesPerElement: [16],       type: [gl.INT], };
    119      t[gl.RGBA32UI]           = { textureFormat: gl.RGBA_INTEGER,    colorRenderable: true,  textureFilterable: false, bytesPerElement: [16],       type: [gl.UNSIGNED_INT], };
    120 
    121      // Sized Internal
    122      t[gl.DEPTH_COMPONENT16]  = { textureFormat: gl.DEPTH_COMPONENT, colorRenderable: true,  textureFilterable: false, bytesPerElement: [2, 4],     type: [gl.UNSIGNED_SHORT, gl.UNSIGNED_INT], };
    123      t[gl.DEPTH_COMPONENT24]  = { textureFormat: gl.DEPTH_COMPONENT, colorRenderable: true,  textureFilterable: false, bytesPerElement: [4],        type: [gl.UNSIGNED_INT], };
    124      t[gl.DEPTH_COMPONENT32F] = { textureFormat: gl.DEPTH_COMPONENT, colorRenderable: true,  textureFilterable: false, bytesPerElement: [4],        type: [gl.FLOAT], };
    125      t[gl.DEPTH24_STENCIL8]   = { textureFormat: gl.DEPTH_STENCIL,   colorRenderable: true,  textureFilterable: false, bytesPerElement: [4],        type: [gl.UNSIGNED_INT_24_8], };
    126      t[gl.DEPTH32F_STENCIL8]  = { textureFormat: gl.DEPTH_STENCIL,   colorRenderable: true,  textureFilterable: false, bytesPerElement: [4],        type: [gl.FLOAT_32_UNSIGNED_INT_24_8_REV], };
    127 
    128      Object.keys(t).forEach(function(internalFormat) {
    129          const info = t[internalFormat];
    130          info.bytesPerElementMap = {};
    131          info.bytesPerElement.forEach(function(bytesPerElement, ndx) {
    132              const type = info.type[ndx];
    133              info.bytesPerElementMap[type] = bytesPerElement;
    134          });
    135      });
    136  }
    137 
    138  const validChannelsByTextureFormat = {};
    139  {
    140      const v = validChannelsByTextureFormat;
    141      v[gl.RED]          = [1, 0, 0, 0];
    142      v[gl.RG]           = [1, 1, 0, 0];
    143      v[gl.RGB]          = [1, 1, 1, 0];
    144      v[gl.RGBA]         = [1, 1, 1, 1];
    145      v[gl.RED_INTEGER]  = [1, 0, 0, 0];
    146      v[gl.RG_INTEGER]   = [1, 1, 0, 0];
    147      v[gl.RGB_INTEGER]  = [1, 1, 1, 0];
    148      v[gl.RGBA_INTEGER] = [1, 1, 1, 1];
    149  }
    150 
    151  const depthTextureFormats = [
    152      gl.DEPTH_COMPONENT16,
    153      gl.DEPTH_COMPONENT24,
    154      gl.DEPTH_COMPONENT32F,
    155      gl.DEPTH24_STENCIL8,
    156      gl.DEPTH32F_STENCIL8,
    157  ];
    158 
    159  const intTextureFormats = [
    160      gl.R8I,
    161      gl.R16I,
    162      gl.R32I,
    163      gl.RG8I,
    164      gl.RG16I,
    165      gl.RG32I,
    166      gl.RGB8I,
    167      gl.RGB16I,
    168      gl.RGB32I,
    169      gl.RGBA8I,
    170      gl.RGBA16I,
    171      gl.RGBA32I,
    172  ];
    173 
    174  const unsignedIntTextureFormats = [
    175      gl.R8UI,
    176      gl.R16UI,
    177      gl.R32UI,
    178      gl.RG8UI,
    179      gl.RG16UI,
    180      gl.RG32UI,
    181      gl.RGB8UI,
    182      gl.RGB16UI,
    183      gl.RGB32UI,
    184      gl.RGBA8UI,
    185      gl.RGB10_A2UI,
    186      gl.RGBA16UI,
    187      gl.RGBA32UI,
    188  ];
    189 
    190  const floatTextureFormats = Object.keys(textureInternalFormatInfo).map(function(v) {
    191      return parseInt(v);
    192  }).filter(function(format) {
    193      return intTextureFormats.indexOf(format) < 0 &&
    194             unsignedIntTextureFormats.indexOf(format) < 0 &&
    195             depthTextureFormats.indexOf(format);
    196  });
    197 
    198  const expectedColorByInternalFormat = {};
    199  expectedColorByInternalFormat[gl.SRGB8_ALPHA8] = [225, 188, 137, 255];
    200 
    201  function clearFloat(gl) {
    202      gl.clearBufferfv(gl.COLOR, 0, [0, 0, 0, 0]);
    203  }
    204 
    205  function clearInt(gl) {
    206      gl.clearBufferiv(gl.COLOR, 0, [0, 0, 0, 0]);
    207  }
    208 
    209  function clearUint(gl) {
    210      gl.clearBufferuiv(gl.COLOR, 0, [0, 0, 0, 0]);
    211  }
    212 
    213 
    214  function checkData(data, expected, internalFormat, tolerance) {
    215      const internalFormatInfo = textureInternalFormatInfo[internalFormat];
    216      const validChannels = validChannelsByTextureFormat[internalFormatInfo.textureFormat];
    217      if (!validChannels) {
    218          testFailed('oops');
    219          return;
    220      }
    221      for (let y = 0; y < texHeight; ++y) {
    222          for (let x = 0; x < texWidth; ++x) {
    223              for (let c = 0; c < validChannels.length; ++c) {
    224                  if (validChannels[c]) {
    225                      const offset = (y * texWidth + x) * 4 + c;
    226                      const pixel = data[offset];
    227                      const diff = Math.abs(pixel - expected[c]);
    228                      if (diff > tolerance) {
    229                          testFailed(`pixel ${x},${y} channel ${c} was ${pixel} expected ${expected[c]} +/- ${tolerance}`);
    230                          return;
    231                      }
    232                  }
    233              }
    234          }
    235      }
    236      testPassed(`data was ${expected.join(',')}`);
    237  }
    238 
    239  function checkFloat(gl, textureInfo, expected) {
    240      const data = new Uint8Array(texWidth * texHeight * 4);
    241      gl.readPixels(0, 0, texWidth, texHeight, gl.RGBA, gl.UNSIGNED_BYTE, data);
    242      const internalFormat = textureInfo.internalFormat;
    243      wtu.glErrorShouldBe(gl, gl.NO_ERROR, `No errors from readPixels with ${wtu.glEnumToString(gl, internalFormat)}`);
    244      checkData(data, expected, internalFormat, 9);
    245  }
    246 
    247  function checkInt(gl, textureInfo, expected) {
    248      const data = new Int32Array(texWidth * texHeight * 4);
    249      gl.readPixels(0, 0, texWidth, texHeight, gl.RGBA_INTEGER, gl.INT, data);
    250      const internalFormat = textureInfo.internalFormat;
    251      wtu.glErrorShouldBe(gl, gl.NO_ERROR, `No errors from readPixels with ${wtu.glEnumToString(gl, internalFormat)}`);
    252      checkData(data, expected, internalFormat, 0);
    253  }
    254 
    255  function checkUint(gl, textureInfo, expected) {
    256      const data = new Uint32Array(texWidth * texHeight * 4);
    257      gl.readPixels(0, 0, texWidth, texHeight, gl.RGBA_INTEGER, gl.UNSIGNED_INT, data);
    258      const internalFormat = textureInfo.internalFormat;
    259      wtu.glErrorShouldBe(gl, gl.NO_ERROR, `No errors from readPixels with ${wtu.glEnumToString(gl, internalFormat)}`);
    260      checkData(data, expected, internalFormat, 0);
    261  }
    262 
    263  const expectedFloatColor = [.75 * 255 | 0, .5 * 255 | 0, .25 * 255 | 0, 1 * 255 | 0];
    264  const floatTypes = [
    265      { outType: 'vec4', outValue: 'vec4(.75, .5, .25, 1)', expected: expectedFloatColor, clear: clearFloat, check: checkFloat, target: gl.TEXTURE_2D, },
    266      { outType: 'vec4', outValue: 'vec4(.75, .5, .25, 1)', expected: expectedFloatColor, clear: clearFloat, check: checkFloat, target: gl.TEXTURE_3D, },
    267      { outType: 'vec4', outValue: 'vec4(.75, .5, .25, 1)', expected: expectedFloatColor, clear: clearFloat, check: checkFloat, target: gl.TEXTURE_2D_ARRAY, },
    268  ];
    269 
    270  const expectedIntColor = [1, 2, 4, 3];
    271  const signedIntTypes = [
    272      { outType: 'ivec4', outValue: 'ivec4(1, 2, 4, 3)', expected: expectedIntColor, clear: clearInt, check: checkInt, target: gl.TEXTURE_2D, },
    273      { outType: 'ivec4', outValue: 'ivec4(1, 2, 4, 3)', expected: expectedIntColor, clear: clearInt, check: checkInt, target: gl.TEXTURE_3D, },
    274      { outType: 'ivec4', outValue: 'ivec4(1, 2, 4, 3)', expected: expectedIntColor, clear: clearInt, check: checkInt, target: gl.TEXTURE_2D_ARRAY, },
    275  ];
    276 
    277  const expectedUintColor = [1, 2, 4, 3];
    278  const unsignedIntTypes = [
    279      { outType: 'uvec4', outValue: 'uvec4(1, 2, 4, 3)', expected: expectedUintColor, clear: clearUint, check: checkUint, target: gl.TEXTURE_2D, },
    280      { outType: 'uvec4', outValue: 'uvec4(1, 2, 4, 3)', expected: expectedUintColor, clear: clearUint, check: checkUint, target: gl.TEXTURE_3D, },
    281      { outType: 'uvec4', outValue: 'uvec4(1, 2, 4, 3)', expected: expectedUintColor, clear: clearUint, check: checkUint, target: gl.TEXTURE_2D_ARRAY, },
    282  ];
    283 
    284  /**
    285   * Gets the number of bytes per element for a given internalFormat / type
    286   * @param {number} internalFormat The internalFormat parameter from texImage2D etc..
    287   * @param {number} type The type parameter for texImage2D etc..
    288   * @return {number} the number of bytes per element for the given internalFormat, type combo
    289   * @memberOf module:twgl/textures
    290   */
    291  function getBytesPerElementForInternalFormat(internalFormat, type) {
    292      const info = textureInternalFormatInfo[internalFormat];
    293      if (!info) {
    294          throw "unknown internal format";
    295      }
    296      const bytesPerElement = info.bytesPerElementMap[type];
    297      if (bytesPerElement === undefined) {
    298          throw "unknown internal format";
    299      }
    300      return bytesPerElement;
    301  }
    302 
    303  function make2DTexture(gl, target, internalFormat, format, type) {
    304      gl.texImage2D(target, 0, internalFormat, texWidth, texHeight, 0, format, type, null);
    305  }
    306 
    307  function make3DTexture(gl, target, internalFormat, format, type) {
    308      gl.texImage3D(target, 0, internalFormat, texWidth, texHeight, texDepth, 0, format, type, null);
    309  }
    310 
    311  function attach2DTexture(gl, target, texture) {
    312      const level = 0;
    313      gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, target, texture, level);
    314  }
    315 
    316  function attach3DTexture(gl, target, texture) {
    317      const level = 0;
    318      const slice = texDepth - 1;
    319      gl.framebufferTextureLayer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, texture, level, slice);
    320  }
    321 
    322  const targets = {};
    323  targets[gl.TEXTURE_2D]       = { make: make2DTexture, attach: attach2DTexture, },
    324  targets[gl.TEXTURE_3D]       = { make: make3DTexture, attach: attach3DTexture, },
    325  targets[gl.TEXTURE_2D_ARRAY] = { make: make3DTexture, attach: attach3DTexture, },
    326 
    327  debug("create textures");
    328  Object.keys(targets).forEach(function(target) {
    329      debug("");
    330      target = parseInt(target);
    331      debug(wtu.glEnumToString(gl, target))
    332      const targetInfo = targets[target];
    333      targetInfo.textures = [];
    334      Object.keys(textureInternalFormatInfo).forEach(function(internalFormat) {
    335          internalFormat = parseInt(internalFormat);
    336          const isDepthFormat = depthTextureFormats.indexOf(internalFormat) >= 0;
    337          if (isDepthFormat) {
    338              return;
    339          }
    340          const info = textureInternalFormatInfo[internalFormat];
    341          if (!info.colorRenderable) {
    342              return;
    343          }
    344          const texture = gl.createTexture();
    345          gl.bindTexture(target, texture);
    346          targetInfo.make(gl, target, internalFormat, info.textureFormat, info.type[0]);
    347          targetInfo.textures.push({
    348              internalFormat: internalFormat,
    349              texture: texture,
    350          });
    351          gl.texParameteri(target, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
    352          gl.texParameteri(target, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
    353          wtu.glErrorShouldBe(gl, gl.NO_ERROR, `No errors from setup for ${wtu.glEnumToString(gl, target)} ${wtu.glEnumToString(gl, internalFormat)}`);
    354      });
    355  });
    356 
    357  // set the canvas to a known color
    358  const half = 127 / 255;
    359  gl.clearColor(half, half, half, half);
    360  gl.clear(gl.COLOR_BUFFER_BIT);
    361  gl.clearColor(0, 0, 0, 0);
    362 
    363  const framebuffer = gl.createFramebuffer();
    364  gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer);
    365  gl.viewport(0, 0, texWidth, texHeight);
    366 
    367  const rb = gl.createRenderbuffer();
    368  gl.bindRenderbuffer(gl.RENDERBUFFER, rb);
    369  gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, texWidth, texHeight);
    370 
    371  testTypes('float', floatTypes, floatTextureFormats);
    372  testTypes('int', signedIntTypes, intTextureFormats);
    373  testTypes('unsigned', unsignedIntTypes, unsignedIntTextureFormats);
    374 
    375  gl.bindFramebuffer(gl.FRAMEBUFFER, null);
    376  wtu.checkCanvas(gl, [127, 127, 127, 127], "canvas should be [127, 127, 127, 127]");
    377 
    378  function testTypes(label, types, compatibleFormats) {
    379      debug('');
    380      types.forEach(function(typeInfo) {
    381          debug(`\nchecking ${wtu.glEnumToString(gl, typeInfo.target)} with ${label} texture formats`);
    382          const program = wtu.setupProgram(gl, ['vshader', makeFragmentShader(typeInfo)], [], console.log.bind(console));
    383          if (!program) {
    384              testFailed("Loading program failed");
    385              return;
    386          }
    387          testPassed("Loading program succeeded");
    388 
    389          const target = typeInfo.target;
    390          const targetInfo = targets[target];
    391          targetInfo.textures.filter(function(textureInfo) {
    392            return compatibleFormats.indexOf(textureInfo.internalFormat) >= 0;
    393          }).forEach(function(textureInfo) {
    394              const internalFormat = textureInfo.internalFormat;
    395              const desc = `${wtu.glEnumToString(gl, target)} ${wtu.glEnumToString(gl, internalFormat)}`;
    396              const expected = expectedColorByInternalFormat[internalFormat] || typeInfo.expected;
    397 
    398              debug('');
    399              debug(desc);
    400 
    401              targetInfo.attach(gl, target, textureInfo.texture);
    402              wtu.framebufferStatusShouldBe(gl, gl.FRAMEBUFFER, gl.FRAMEBUFFER_COMPLETE, `for ${desc}`);
    403              typeInfo.clear(gl);
    404              if (wtu.glErrorShouldBe(gl, gl.NO_ERROR, `No errors from clear to ${desc}`)) {
    405                return;
    406              }
    407              typeInfo.check(gl, textureInfo, [0, 0, 0, 0]);
    408              gl.drawArrays(gl.POINTS, 0, 1);
    409              if (wtu.glErrorShouldBe(gl, gl.NO_ERROR, `No errors from render to ${desc}`)) {
    410                return;
    411              }
    412              typeInfo.check(gl, textureInfo, expected);
    413 
    414              typeInfo.clear(gl);
    415              if (wtu.glErrorShouldBe(gl, gl.NO_ERROR, `No errors from clear to ${desc}`)) {
    416                return;
    417              }
    418              typeInfo.check(gl, textureInfo, [0, 0, 0, 0]);
    419 
    420              gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, rb);
    421              wtu.framebufferStatusShouldBe(gl, gl.FRAMEBUFFER, gl.FRAMEBUFFER_COMPLETE, `for ${desc} with depth renderbuffer`);
    422              gl.clearBufferfv(gl.DEPTH, 0, [1]);
    423              gl.drawArrays(gl.POINTS, 0, 1);
    424              gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, null);
    425 
    426              wtu.glErrorShouldBe(gl, gl.NO_ERROR, `No errors from render to ${desc}`);
    427 
    428              typeInfo.check(gl, textureInfo, expected);
    429          });
    430      });
    431  }
    432 }
    433 
    434 debug("");
    435 var successfullyParsed = true;
    436 </script>
    437 <script src="../../js/js-test-post.js"></script>
    438 
    439 </body>
    440 </html>