tor-browser

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

WebGLFormats.cpp (62165B)


      1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* This Source Code Form is subject to the terms of the Mozilla Public
      3 * License, v. 2.0. If a copy of the MPL was not distributed with this
      4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      5 
      6 #include "WebGLFormats.h"
      7 
      8 #include "GLContext.h"
      9 #include "GLDefs.h"
     10 #include "mozilla/StaticMutex.h"
     11 #include "mozilla/gfx/Logging.h"
     12 
     13 namespace mozilla::webgl {
     14 
     15 const char* ToString(const ComponentType type) {
     16  switch (type) {
     17    case ComponentType::Int:
     18      return "Int";
     19    case ComponentType::UInt:
     20      return "UInt";
     21    case ComponentType::NormInt:
     22      return "NormInt";
     23    case ComponentType::NormUInt:
     24      return "NormUInt";
     25    case ComponentType::Float:
     26      return "Float";
     27  }
     28  MOZ_CRASH("pacify gcc6 warning");
     29 }
     30 
     31 static TextureBaseType ToBaseType(const ComponentType type) {
     32  switch (type) {
     33    case ComponentType::Int:
     34      return TextureBaseType::Int;
     35    case ComponentType::UInt:
     36      return TextureBaseType::UInt;
     37    case ComponentType::NormInt:
     38    case ComponentType::NormUInt:
     39    case ComponentType::Float:
     40      // case ComponentType::Depth:
     41      return TextureBaseType::Float;
     42  }
     43  MOZ_CRASH("pacify gcc6 warning");
     44 }
     45 
     46 const char* ToString(const TextureBaseType x) {
     47  switch (x) {
     48    case webgl::TextureBaseType::Float:
     49      return "FLOAT";
     50    case webgl::TextureBaseType::Int:
     51      return "INT";
     52    case webgl::TextureBaseType::UInt:
     53      return "UINT";
     54  }
     55  MOZ_CRASH("pacify gcc6 warning");
     56 }
     57 
     58 // -
     59 
     60 template <typename K, typename V, typename K2, typename V2>
     61 static inline void AlwaysInsert(std::map<K, V>& dest, const K2& key,
     62                                const V2& val) {
     63  auto res = dest.insert({key, val});
     64  bool didInsert = res.second;
     65  MOZ_ALWAYS_TRUE(didInsert);
     66 }
     67 
     68 template <typename K, typename V, typename K2>
     69 static inline V* FindOrNull(const std::map<K, V*>& dest, const K2& key) {
     70  auto itr = dest.find(key);
     71  if (itr == dest.end()) return nullptr;
     72 
     73  return itr->second;
     74 }
     75 
     76 // Returns a pointer to the in-place value for `key`.
     77 template <typename C, typename K2>
     78 static inline auto FindPtrOrNull(C& container, const K2& key) {
     79  auto itr = container.find(key);
     80  using R = decltype(&(itr->second));
     81  if (itr == container.end()) return R{nullptr};
     82 
     83  return &(itr->second);
     84 }
     85 
     86 //////////////////////////////////////////////////////////////////////////////////////////
     87 
     88 MOZ_RUNINIT std::map<EffectiveFormat, const CompressedFormatInfo>
     89    gCompressedFormatInfoMap;
     90 MOZ_RUNINIT std::map<EffectiveFormat, FormatInfo> gFormatInfoMap;
     91 
     92 static inline const CompressedFormatInfo* GetCompressedFormatInfo(
     93    EffectiveFormat format) {
     94  MOZ_ASSERT(!gCompressedFormatInfoMap.empty());
     95  return FindPtrOrNull(gCompressedFormatInfoMap, format);
     96 }
     97 
     98 static inline FormatInfo* GetFormatInfo_NoLock(EffectiveFormat format) {
     99  MOZ_ASSERT(!gFormatInfoMap.empty());
    100  return FindPtrOrNull(gFormatInfoMap, format);
    101 }
    102 
    103 //////////////////////////////////////////////////////////////////////////////////////////
    104 
    105 static void AddCompressedFormatInfo(EffectiveFormat format,
    106                                    uint16_t bitsPerBlock, uint8_t blockWidth,
    107                                    uint8_t blockHeight,
    108                                    CompressionFamily family) {
    109  MOZ_ASSERT(bitsPerBlock % 8 == 0);
    110  uint16_t bytesPerBlock = bitsPerBlock / 8;  // The specs always state these in
    111                                              // bits, but it's only ever useful
    112                                              // to us as bytes.
    113  MOZ_ASSERT(bytesPerBlock <= 255);
    114 
    115  const CompressedFormatInfo info = {format, uint8_t(bytesPerBlock), blockWidth,
    116                                     blockHeight, family};
    117  AlwaysInsert(gCompressedFormatInfoMap, format, info);
    118 }
    119 
    120 static void InitCompressedFormatInfo() {
    121  // clang-format off
    122 
    123    // GLES 3.0.4, p147, table 3.19
    124    // GLES 3.0.4, p286+, $C.1 "ETC Compressed Texture Image Formats"
    125    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGB8_ETC2                     ,  64, 4, 4, CompressionFamily::ES3);
    126    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ETC2                    ,  64, 4, 4, CompressionFamily::ES3);
    127    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA8_ETC2_EAC                , 128, 4, 4, CompressionFamily::ES3);
    128    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC         , 128, 4, 4, CompressionFamily::ES3);
    129    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_R11_EAC                       ,  64, 4, 4, CompressionFamily::ES3);
    130    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RG11_EAC                      , 128, 4, 4, CompressionFamily::ES3);
    131    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SIGNED_R11_EAC                ,  64, 4, 4, CompressionFamily::ES3);
    132    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SIGNED_RG11_EAC               , 128, 4, 4, CompressionFamily::ES3);
    133    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 ,  64, 4, 4, CompressionFamily::ES3);
    134    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2,  64, 4, 4, CompressionFamily::ES3);
    135 
    136    // EXT_texture_compression_bptc
    137    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_BPTC_UNORM        , 16*8, 4, 4, CompressionFamily::BPTC);
    138    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB_ALPHA_BPTC_UNORM  , 16*8, 4, 4, CompressionFamily::BPTC);
    139    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGB_BPTC_SIGNED_FLOAT  , 16*8, 4, 4, CompressionFamily::BPTC);
    140    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT, 16*8, 4, 4, CompressionFamily::BPTC);
    141 
    142    // EXT_texture_compression_rgtc
    143    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RED_RGTC1       ,  8*8, 4, 4, CompressionFamily::RGTC);
    144    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SIGNED_RED_RGTC1,  8*8, 4, 4, CompressionFamily::RGTC);
    145    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RG_RGTC2        , 16*8, 4, 4, CompressionFamily::RGTC);
    146    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SIGNED_RG_RGTC2 , 16*8, 4, 4, CompressionFamily::RGTC);
    147 
    148    // EXT_texture_compression_s3tc
    149    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGB_S3TC_DXT1_EXT ,  64, 4, 4, CompressionFamily::S3TC);
    150    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_S3TC_DXT1_EXT,  64, 4, 4, CompressionFamily::S3TC);
    151    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_S3TC_DXT3_EXT, 128, 4, 4, CompressionFamily::S3TC);
    152    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_S3TC_DXT5_EXT, 128, 4, 4, CompressionFamily::S3TC);
    153 
    154    // EXT_texture_compression_s3tc_srgb
    155    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB_S3TC_DXT1_EXT ,       64, 4, 4, CompressionFamily::S3TC);
    156    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT,  64, 4, 4, CompressionFamily::S3TC);
    157    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 128, 4, 4, CompressionFamily::S3TC);
    158    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 128, 4, 4, CompressionFamily::S3TC);
    159 
    160    // KHR_texture_compression_astc_ldr
    161    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_ASTC_4x4_KHR          , 128,  4,  4, CompressionFamily::ASTC);
    162    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_ASTC_5x4_KHR          , 128,  5,  4, CompressionFamily::ASTC);
    163    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_ASTC_5x5_KHR          , 128,  5,  5, CompressionFamily::ASTC);
    164    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_ASTC_6x5_KHR          , 128,  6,  5, CompressionFamily::ASTC);
    165    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_ASTC_6x6_KHR          , 128,  6,  6, CompressionFamily::ASTC);
    166    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_ASTC_8x5_KHR          , 128,  8,  5, CompressionFamily::ASTC);
    167    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_ASTC_8x6_KHR          , 128,  8,  6, CompressionFamily::ASTC);
    168    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_ASTC_8x8_KHR          , 128,  8,  8, CompressionFamily::ASTC);
    169    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_ASTC_10x5_KHR         , 128, 10,  5, CompressionFamily::ASTC);
    170    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_ASTC_10x6_KHR         , 128, 10,  6, CompressionFamily::ASTC);
    171    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_ASTC_10x8_KHR         , 128, 10,  8, CompressionFamily::ASTC);
    172    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_ASTC_10x10_KHR        , 128, 10, 10, CompressionFamily::ASTC);
    173    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_ASTC_12x10_KHR        , 128, 12, 10, CompressionFamily::ASTC);
    174    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_ASTC_12x12_KHR        , 128, 12, 12, CompressionFamily::ASTC);
    175 
    176    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR  , 128,  4,  4, CompressionFamily::ASTC);
    177    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR  , 128,  5,  4, CompressionFamily::ASTC);
    178    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR  , 128,  5,  5, CompressionFamily::ASTC);
    179    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR  , 128,  6,  5, CompressionFamily::ASTC);
    180    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR  , 128,  6,  6, CompressionFamily::ASTC);
    181    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR  , 128,  8,  5, CompressionFamily::ASTC);
    182    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR  , 128,  8,  6, CompressionFamily::ASTC);
    183    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR  , 128,  8,  8, CompressionFamily::ASTC);
    184    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR , 128, 10,  5, CompressionFamily::ASTC);
    185    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR , 128, 10,  6, CompressionFamily::ASTC);
    186    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR , 128, 10,  8, CompressionFamily::ASTC);
    187    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, 128, 10, 10, CompressionFamily::ASTC);
    188    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, 128, 12, 10, CompressionFamily::ASTC);
    189    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, 128, 12, 12, CompressionFamily::ASTC);
    190 
    191    // IMG_texture_compression_pvrtc
    192    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGB_PVRTC_4BPPV1 , 256,  8, 8, CompressionFamily::PVRTC);
    193    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_PVRTC_4BPPV1, 256,  8, 8, CompressionFamily::PVRTC);
    194    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGB_PVRTC_2BPPV1 , 256, 16, 8, CompressionFamily::PVRTC);
    195    AddCompressedFormatInfo(EffectiveFormat::COMPRESSED_RGBA_PVRTC_2BPPV1, 256, 16, 8, CompressionFamily::PVRTC);
    196 
    197    // OES_compressed_ETC1_RGB8_texture
    198    AddCompressedFormatInfo(EffectiveFormat::ETC1_RGB8_OES, 64, 4, 4, CompressionFamily::ETC1);
    199 
    200  // clang-format on
    201 }
    202 
    203 //////////////////////////////////////////////////////////////////////////////////////////
    204 
    205 static void AddFormatInfo(EffectiveFormat format, const char* name,
    206                          GLenum sizedFormat, uint8_t bytesPerPixel, uint8_t r,
    207                          uint8_t g, uint8_t b, uint8_t a, uint8_t d, uint8_t s,
    208                          UnsizedFormat unsizedFormat, bool isSRGB,
    209                          ComponentType componentType) {
    210  switch (unsizedFormat) {
    211    case UnsizedFormat::R:
    212      MOZ_ASSERT(r && !g && !b && !a && !d && !s);
    213      break;
    214 
    215    case UnsizedFormat::RG:
    216      MOZ_ASSERT(r && g && !b && !a && !d && !s);
    217      break;
    218 
    219    case UnsizedFormat::RGB:
    220      MOZ_ASSERT(r && g && b && !a && !d && !s);
    221      break;
    222 
    223    case UnsizedFormat::RGBA:
    224      MOZ_ASSERT(r && g && b && a && !d && !s);
    225      break;
    226 
    227    case UnsizedFormat::L:
    228      MOZ_ASSERT(r && !g && !b && !a && !d && !s);
    229      break;
    230 
    231    case UnsizedFormat::A:
    232      MOZ_ASSERT(!r && !g && !b && a && !d && !s);
    233      break;
    234 
    235    case UnsizedFormat::LA:
    236      MOZ_ASSERT(r && !g && !b && a && !d && !s);
    237      break;
    238 
    239    case UnsizedFormat::D:
    240      MOZ_ASSERT(!r && !g && !b && !a && d && !s);
    241      break;
    242 
    243    case UnsizedFormat::S:
    244      MOZ_ASSERT(!r && !g && !b && !a && !d && s);
    245      break;
    246 
    247    case UnsizedFormat::DEPTH_STENCIL:
    248      MOZ_ASSERT(!r && !g && !b && !a && d && s);
    249      break;
    250  }
    251 
    252  const CompressedFormatInfo* compressedFormatInfo =
    253      GetCompressedFormatInfo(format);
    254  MOZ_ASSERT(!bytesPerPixel == bool(compressedFormatInfo));
    255 
    256 #ifdef DEBUG
    257  uint8_t totalBits = r + g + b + a + d + s;
    258  if (format == EffectiveFormat::RGB9_E5) {
    259    totalBits = 9 + 9 + 9 + 5;
    260  }
    261 
    262  if (compressedFormatInfo) {
    263    MOZ_ASSERT(totalBits);
    264    MOZ_ASSERT(!bytesPerPixel);
    265  } else {
    266    MOZ_ASSERT(totalBits == bytesPerPixel * 8);
    267  }
    268 #endif
    269 
    270  const FormatInfo info = {format,
    271                           name,
    272                           sizedFormat,
    273                           unsizedFormat,
    274                           componentType,
    275                           ToBaseType(componentType),
    276                           isSRGB,
    277                           compressedFormatInfo,
    278                           bytesPerPixel,
    279                           r,
    280                           g,
    281                           b,
    282                           a,
    283                           d,
    284                           s};
    285  AlwaysInsert(gFormatInfoMap, format, info);
    286 }
    287 
    288 static void InitFormatInfo() {
    289  // This function is full of expressive formatting, so:
    290  // clang-format off
    291 
    292 #define FOO(x) EffectiveFormat::x, #x, LOCAL_GL_ ## x
    293 
    294    // GLES 3.0.4, p130-132, table 3.13
    295    //           |     format        | renderable | filterable |
    296    AddFormatInfo(FOO(R8            ),  1,  8, 0, 0, 0,  0,0, UnsizedFormat::R   , false, ComponentType::NormUInt);
    297    AddFormatInfo(FOO(R8_SNORM      ),  1,  8, 0, 0, 0,  0,0, UnsizedFormat::R   , false, ComponentType::NormInt );
    298    AddFormatInfo(FOO(RG8           ),  2,  8, 8, 0, 0,  0,0, UnsizedFormat::RG  , false, ComponentType::NormUInt);
    299    AddFormatInfo(FOO(RG8_SNORM     ),  2,  8, 8, 0, 0,  0,0, UnsizedFormat::RG  , false, ComponentType::NormInt );
    300    AddFormatInfo(FOO(RGB8          ),  3,  8, 8, 8, 0,  0,0, UnsizedFormat::RGB , false, ComponentType::NormUInt);
    301    AddFormatInfo(FOO(RGB8_SNORM    ),  3,  8, 8, 8, 0,  0,0, UnsizedFormat::RGB , false, ComponentType::NormInt );
    302    AddFormatInfo(FOO(RGB565        ),  2,  5, 6, 5, 0,  0,0, UnsizedFormat::RGB , false, ComponentType::NormUInt);
    303    AddFormatInfo(FOO(RGBA4         ),  2,  4, 4, 4, 4,  0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
    304    AddFormatInfo(FOO(RGB5_A1       ),  2,  5, 5, 5, 1,  0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
    305    AddFormatInfo(FOO(RGBA8         ),  4,  8, 8, 8, 8,  0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
    306    AddFormatInfo(FOO(RGBA8_SNORM   ),  4,  8, 8, 8, 8,  0,0, UnsizedFormat::RGBA, false, ComponentType::NormInt );
    307    AddFormatInfo(FOO(RGB10_A2      ),  4, 10,10,10, 2,  0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
    308    AddFormatInfo(FOO(RGB10_A2UI    ),  4, 10,10,10, 2,  0,0, UnsizedFormat::RGBA, false, ComponentType::UInt    );
    309 
    310    AddFormatInfo(FOO(SRGB8         ),  3,  8, 8, 8, 0,  0,0, UnsizedFormat::RGB , true , ComponentType::NormUInt);
    311    AddFormatInfo(FOO(SRGB8_ALPHA8  ),  4,  8, 8, 8, 8,  0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
    312 
    313    AddFormatInfo(FOO(R16F          ),  2, 16, 0, 0, 0,  0,0, UnsizedFormat::R   , false, ComponentType::Float   );
    314    AddFormatInfo(FOO(RG16F         ),  4, 16,16, 0, 0,  0,0, UnsizedFormat::RG  , false, ComponentType::Float   );
    315    AddFormatInfo(FOO(RGB16F        ),  6, 16,16,16, 0,  0,0, UnsizedFormat::RGB , false, ComponentType::Float   );
    316    AddFormatInfo(FOO(RGBA16F       ),  8, 16,16,16,16,  0,0, UnsizedFormat::RGBA, false, ComponentType::Float   );
    317    AddFormatInfo(FOO(R32F          ),  4, 32, 0, 0, 0,  0,0, UnsizedFormat::R   , false, ComponentType::Float   );
    318    AddFormatInfo(FOO(RG32F         ),  8, 32,32, 0, 0,  0,0, UnsizedFormat::RG  , false, ComponentType::Float   );
    319    AddFormatInfo(FOO(RGB32F        ), 12, 32,32,32, 0,  0,0, UnsizedFormat::RGB , false, ComponentType::Float   );
    320    AddFormatInfo(FOO(RGBA32F       ), 16, 32,32,32,32,  0,0, UnsizedFormat::RGBA, false, ComponentType::Float   );
    321 
    322    AddFormatInfo(FOO(R11F_G11F_B10F),  4, 11,11,10, 0,  0,0, UnsizedFormat::RGB , false, ComponentType::Float   );
    323    AddFormatInfo(FOO(RGB9_E5       ),  4, 14,14,14, 0,  0,0, UnsizedFormat::RGB , false, ComponentType::Float   );
    324 
    325    AddFormatInfo(FOO(R8I           ),  1,  8, 0, 0, 0,  0,0, UnsizedFormat::R   , false, ComponentType::Int     );
    326    AddFormatInfo(FOO(R8UI          ),  1,  8, 0, 0, 0,  0,0, UnsizedFormat::R   , false, ComponentType::UInt    );
    327    AddFormatInfo(FOO(R16I          ),  2, 16, 0, 0, 0,  0,0, UnsizedFormat::R   , false, ComponentType::Int     );
    328    AddFormatInfo(FOO(R16UI         ),  2, 16, 0, 0, 0,  0,0, UnsizedFormat::R   , false, ComponentType::UInt    );
    329    AddFormatInfo(FOO(R32I          ),  4, 32, 0, 0, 0,  0,0, UnsizedFormat::R   , false, ComponentType::Int     );
    330    AddFormatInfo(FOO(R32UI         ),  4, 32, 0, 0, 0,  0,0, UnsizedFormat::R   , false, ComponentType::UInt    );
    331 
    332    AddFormatInfo(FOO(RG8I          ),  2,  8, 8, 0, 0,  0,0, UnsizedFormat::RG  , false, ComponentType::Int     );
    333    AddFormatInfo(FOO(RG8UI         ),  2,  8, 8, 0, 0,  0,0, UnsizedFormat::RG  , false, ComponentType::UInt    );
    334    AddFormatInfo(FOO(RG16I         ),  4, 16,16, 0, 0,  0,0, UnsizedFormat::RG  , false, ComponentType::Int     );
    335    AddFormatInfo(FOO(RG16UI        ),  4, 16,16, 0, 0,  0,0, UnsizedFormat::RG  , false, ComponentType::UInt    );
    336    AddFormatInfo(FOO(RG32I         ),  8, 32,32, 0, 0,  0,0, UnsizedFormat::RG  , false, ComponentType::Int     );
    337    AddFormatInfo(FOO(RG32UI        ),  8, 32,32, 0, 0,  0,0, UnsizedFormat::RG  , false, ComponentType::UInt    );
    338 
    339    AddFormatInfo(FOO(RGB8I         ),  3,  8, 8, 8, 0,  0,0, UnsizedFormat::RGB , false, ComponentType::Int     );
    340    AddFormatInfo(FOO(RGB8UI        ),  3,  8, 8, 8, 0,  0,0, UnsizedFormat::RGB , false, ComponentType::UInt    );
    341    AddFormatInfo(FOO(RGB16I        ),  6, 16,16,16, 0,  0,0, UnsizedFormat::RGB , false, ComponentType::Int     );
    342    AddFormatInfo(FOO(RGB16UI       ),  6, 16,16,16, 0,  0,0, UnsizedFormat::RGB , false, ComponentType::UInt    );
    343    AddFormatInfo(FOO(RGB32I        ), 12, 32,32,32, 0,  0,0, UnsizedFormat::RGB , false, ComponentType::Int     );
    344    AddFormatInfo(FOO(RGB32UI       ), 12, 32,32,32, 0,  0,0, UnsizedFormat::RGB , false, ComponentType::UInt    );
    345 
    346    AddFormatInfo(FOO(RGBA8I        ),  4,  8, 8, 8, 8,  0,0, UnsizedFormat::RGBA, false, ComponentType::Int     );
    347    AddFormatInfo(FOO(RGBA8UI       ),  4,  8, 8, 8, 8,  0,0, UnsizedFormat::RGBA, false, ComponentType::UInt    );
    348    AddFormatInfo(FOO(RGBA16I       ),  8, 16,16,16,16,  0,0, UnsizedFormat::RGBA, false, ComponentType::Int     );
    349    AddFormatInfo(FOO(RGBA16UI      ),  8, 16,16,16,16,  0,0, UnsizedFormat::RGBA, false, ComponentType::UInt    );
    350    AddFormatInfo(FOO(RGBA32I       ), 16, 32,32,32,32,  0,0, UnsizedFormat::RGBA, false, ComponentType::Int     );
    351    AddFormatInfo(FOO(RGBA32UI      ), 16, 32,32,32,32,  0,0, UnsizedFormat::RGBA, false, ComponentType::UInt    );
    352 
    353    // GLES 3.0.4, p133, table 3.14
    354    AddFormatInfo(FOO(DEPTH_COMPONENT16 ), 2, 0,0,0,0, 16,0, UnsizedFormat::D , false, ComponentType::NormUInt);
    355    AddFormatInfo(FOO(DEPTH_COMPONENT24 ), 3, 0,0,0,0, 24,0, UnsizedFormat::D , false, ComponentType::NormUInt);
    356    AddFormatInfo(FOO(DEPTH_COMPONENT32F), 4, 0,0,0,0, 32,0, UnsizedFormat::D , false, ComponentType::Float);
    357    // DEPTH_STENCIL types are sampled as their depth component.
    358    AddFormatInfo(FOO(DEPTH24_STENCIL8  ), 4, 0,0,0,0, 24,8, UnsizedFormat::DEPTH_STENCIL, false, ComponentType::NormUInt);
    359    AddFormatInfo(FOO(DEPTH32F_STENCIL8 ), 5, 0,0,0,0, 32,8, UnsizedFormat::DEPTH_STENCIL, false, ComponentType::Float);
    360 
    361    // GLES 3.0.4, p205-206, "Required Renderbuffer Formats"
    362    AddFormatInfo(FOO(STENCIL_INDEX8), 1, 0,0,0,0, 0,8, UnsizedFormat::S, false, ComponentType::Int);
    363 
    364    // GLES 3.0.4, p147, table 3.19
    365    // GLES 3.0.4  p286+  $C.1 "ETC Compressed Texture Image Formats"
    366    AddFormatInfo(FOO(COMPRESSED_RGB8_ETC2                     ), 0, 1,1,1,0, 0,0, UnsizedFormat::RGB , false, ComponentType::NormUInt);
    367    AddFormatInfo(FOO(COMPRESSED_SRGB8_ETC2                    ), 0, 1,1,1,0, 0,0, UnsizedFormat::RGB , true , ComponentType::NormUInt);
    368    AddFormatInfo(FOO(COMPRESSED_RGBA8_ETC2_EAC                ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
    369    AddFormatInfo(FOO(COMPRESSED_SRGB8_ALPHA8_ETC2_EAC         ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
    370    AddFormatInfo(FOO(COMPRESSED_R11_EAC                       ), 0, 1,0,0,0, 0,0, UnsizedFormat::R   , false, ComponentType::NormUInt);
    371    AddFormatInfo(FOO(COMPRESSED_RG11_EAC                      ), 0, 1,1,0,0, 0,0, UnsizedFormat::RG  , false, ComponentType::NormUInt);
    372    AddFormatInfo(FOO(COMPRESSED_SIGNED_R11_EAC                ), 0, 1,0,0,0, 0,0, UnsizedFormat::R   , false, ComponentType::NormInt );
    373    AddFormatInfo(FOO(COMPRESSED_SIGNED_RG11_EAC               ), 0, 1,1,0,0, 0,0, UnsizedFormat::RG  , false, ComponentType::NormInt );
    374    AddFormatInfo(FOO(COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2 ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
    375    AddFormatInfo(FOO(COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
    376 
    377    // EXT_texture_compression_bptc
    378    AddFormatInfo(FOO(COMPRESSED_RGBA_BPTC_UNORM        ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
    379    AddFormatInfo(FOO(COMPRESSED_SRGB_ALPHA_BPTC_UNORM  ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
    380    AddFormatInfo(FOO(COMPRESSED_RGB_BPTC_SIGNED_FLOAT  ), 0, 1,1,1,0, 0,0, UnsizedFormat::RGB , false, ComponentType::Float   );
    381    AddFormatInfo(FOO(COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT), 0, 1,1,1,0, 0,0, UnsizedFormat::RGB , false, ComponentType::Float   );
    382 
    383    // EXT_texture_compression_rgtc
    384    AddFormatInfo(FOO(COMPRESSED_RED_RGTC1       ), 0, 1,0,0,0, 0,0, UnsizedFormat::R , false, ComponentType::NormUInt);
    385    AddFormatInfo(FOO(COMPRESSED_SIGNED_RED_RGTC1), 0, 1,0,0,0, 0,0, UnsizedFormat::R , false, ComponentType::NormInt );
    386    AddFormatInfo(FOO(COMPRESSED_RG_RGTC2        ), 0, 1,1,0,0, 0,0, UnsizedFormat::RG, false, ComponentType::NormUInt);
    387    AddFormatInfo(FOO(COMPRESSED_SIGNED_RG_RGTC2 ), 0, 1,1,0,0, 0,0, UnsizedFormat::RG, false, ComponentType::NormInt );
    388 
    389    // EXT_texture_compression_s3tc
    390    AddFormatInfo(FOO(COMPRESSED_RGB_S3TC_DXT1_EXT ), 0, 1,1,1,0, 0,0, UnsizedFormat::RGB , false, ComponentType::NormUInt);
    391    AddFormatInfo(FOO(COMPRESSED_RGBA_S3TC_DXT1_EXT), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
    392    AddFormatInfo(FOO(COMPRESSED_RGBA_S3TC_DXT3_EXT), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
    393    AddFormatInfo(FOO(COMPRESSED_RGBA_S3TC_DXT5_EXT), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
    394 
    395    // EXT_texture_compression_s3tc_srgb
    396    AddFormatInfo(FOO(COMPRESSED_SRGB_S3TC_DXT1_EXT ), 0, 1,1,1,0, 0,0, UnsizedFormat::RGB , true, ComponentType::NormUInt);
    397    AddFormatInfo(FOO(COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true, ComponentType::NormUInt);
    398    AddFormatInfo(FOO(COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true, ComponentType::NormUInt);
    399    AddFormatInfo(FOO(COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true, ComponentType::NormUInt);
    400 
    401    // KHR_texture_compression_astc_ldr
    402    AddFormatInfo(FOO(COMPRESSED_RGBA_ASTC_4x4_KHR          ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
    403    AddFormatInfo(FOO(COMPRESSED_RGBA_ASTC_5x4_KHR          ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
    404    AddFormatInfo(FOO(COMPRESSED_RGBA_ASTC_5x5_KHR          ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
    405    AddFormatInfo(FOO(COMPRESSED_RGBA_ASTC_6x5_KHR          ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
    406    AddFormatInfo(FOO(COMPRESSED_RGBA_ASTC_6x6_KHR          ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
    407    AddFormatInfo(FOO(COMPRESSED_RGBA_ASTC_8x5_KHR          ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
    408    AddFormatInfo(FOO(COMPRESSED_RGBA_ASTC_8x6_KHR          ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
    409    AddFormatInfo(FOO(COMPRESSED_RGBA_ASTC_8x8_KHR          ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
    410    AddFormatInfo(FOO(COMPRESSED_RGBA_ASTC_10x5_KHR         ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
    411    AddFormatInfo(FOO(COMPRESSED_RGBA_ASTC_10x6_KHR         ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
    412    AddFormatInfo(FOO(COMPRESSED_RGBA_ASTC_10x8_KHR         ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
    413    AddFormatInfo(FOO(COMPRESSED_RGBA_ASTC_10x10_KHR        ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
    414    AddFormatInfo(FOO(COMPRESSED_RGBA_ASTC_12x10_KHR        ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
    415    AddFormatInfo(FOO(COMPRESSED_RGBA_ASTC_12x12_KHR        ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
    416 
    417    AddFormatInfo(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR  ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
    418    AddFormatInfo(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR  ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
    419    AddFormatInfo(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR  ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
    420    AddFormatInfo(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR  ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
    421    AddFormatInfo(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR  ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
    422    AddFormatInfo(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR  ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
    423    AddFormatInfo(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR  ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
    424    AddFormatInfo(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR  ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
    425    AddFormatInfo(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
    426    AddFormatInfo(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
    427    AddFormatInfo(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR ), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
    428    AddFormatInfo(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
    429    AddFormatInfo(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
    430    AddFormatInfo(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, true , ComponentType::NormUInt);
    431 
    432    // IMG_texture_compression_pvrtc
    433    AddFormatInfo(FOO(COMPRESSED_RGB_PVRTC_4BPPV1 ), 0, 1,1,1,0, 0,0, UnsizedFormat::RGB , false, ComponentType::NormUInt);
    434    AddFormatInfo(FOO(COMPRESSED_RGBA_PVRTC_4BPPV1), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
    435    AddFormatInfo(FOO(COMPRESSED_RGB_PVRTC_2BPPV1 ), 0, 1,1,1,0, 0,0, UnsizedFormat::RGB , false, ComponentType::NormUInt);
    436    AddFormatInfo(FOO(COMPRESSED_RGBA_PVRTC_2BPPV1), 0, 1,1,1,1, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
    437 
    438    // OES_compressed_ETC1_RGB8_texture
    439    AddFormatInfo(FOO(ETC1_RGB8_OES), 0, 1,1,1,0, 0,0, UnsizedFormat::RGB, false, ComponentType::NormUInt);
    440 
    441    // EXT_texture_norm16
    442    AddFormatInfo(FOO(R16   ), 2, 16, 0, 0, 0, 0,0, UnsizedFormat::R   , false, ComponentType::NormUInt);
    443    AddFormatInfo(FOO(RG16  ), 4, 16,16, 0, 0, 0,0, UnsizedFormat::RG  , false, ComponentType::NormUInt);
    444    AddFormatInfo(FOO(RGB16 ), 6, 16,16,16, 0, 0,0, UnsizedFormat::RGB , false, ComponentType::NormUInt);
    445    AddFormatInfo(FOO(RGBA16), 8, 16,16,16,16, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormUInt);
    446 
    447    AddFormatInfo(FOO(R16_SNORM   ), 2, 16, 0, 0, 0, 0,0, UnsizedFormat::R   , false, ComponentType::NormInt);
    448    AddFormatInfo(FOO(RG16_SNORM  ), 4, 16,16, 0, 0, 0,0, UnsizedFormat::RG  , false, ComponentType::NormInt);
    449    AddFormatInfo(FOO(RGB16_SNORM ), 6, 16,16,16, 0, 0,0, UnsizedFormat::RGB , false, ComponentType::NormInt);
    450    AddFormatInfo(FOO(RGBA16_SNORM), 8, 16,16,16,16, 0,0, UnsizedFormat::RGBA, false, ComponentType::NormInt);
    451 
    452 #undef FOO
    453 
    454    // 'Virtual' effective formats have no sizedFormat.
    455 #define FOO(x) EffectiveFormat::x, #x, 0
    456 
    457    // GLES 3.0.4, p128, table 3.12.
    458    AddFormatInfo(FOO(Luminance8Alpha8), 2, 8,0,0,8, 0,0, UnsizedFormat::LA, false, ComponentType::NormUInt);
    459    AddFormatInfo(FOO(Luminance8      ), 1, 8,0,0,0, 0,0, UnsizedFormat::L , false, ComponentType::NormUInt);
    460    AddFormatInfo(FOO(Alpha8          ), 1, 0,0,0,8, 0,0, UnsizedFormat::A , false, ComponentType::NormUInt);
    461 
    462    // OES_texture_float
    463    AddFormatInfo(FOO(Luminance32FAlpha32F), 8, 32,0,0,32, 0,0, UnsizedFormat::LA, false, ComponentType::Float);
    464    AddFormatInfo(FOO(Luminance32F        ), 4, 32,0,0, 0, 0,0, UnsizedFormat::L , false, ComponentType::Float);
    465    AddFormatInfo(FOO(Alpha32F            ), 4,  0,0,0,32, 0,0, UnsizedFormat::A , false, ComponentType::Float);
    466 
    467    // OES_texture_half_float
    468    AddFormatInfo(FOO(Luminance16FAlpha16F), 4, 16,0,0,16, 0,0, UnsizedFormat::LA, false, ComponentType::Float);
    469    AddFormatInfo(FOO(Luminance16F        ), 2, 16,0,0, 0, 0,0, UnsizedFormat::L , false, ComponentType::Float);
    470    AddFormatInfo(FOO(Alpha16F            ), 2,  0,0,0,16, 0,0, UnsizedFormat::A , false, ComponentType::Float);
    471 
    472 #undef FOO
    473 
    474    ////////////////////////////////////////////////////////////////////////////
    475 
    476    const auto fnSetCopyDecay = [](EffectiveFormat src, EffectiveFormat asR,
    477                                   EffectiveFormat asRG, EffectiveFormat asRGB,
    478                                   EffectiveFormat asRGBA, EffectiveFormat asL,
    479                                   EffectiveFormat asA, EffectiveFormat asLA)
    480    {
    481        auto& map = GetFormatInfo_NoLock(src)->copyDecayFormats;
    482 
    483        const auto fnSet = [&map](UnsizedFormat uf, EffectiveFormat ef) {
    484            if (ef == EffectiveFormat::MAX)
    485                return;
    486 
    487            const auto* format = GetFormatInfo_NoLock(ef);
    488            MOZ_ASSERT(format->unsizedFormat == uf);
    489            AlwaysInsert(map, uf, format);
    490        };
    491 
    492        fnSet(UnsizedFormat::R   , asR);
    493        fnSet(UnsizedFormat::RG  , asRG);
    494        fnSet(UnsizedFormat::RGB , asRGB);
    495        fnSet(UnsizedFormat::RGBA, asRGBA);
    496        fnSet(UnsizedFormat::L   , asL);
    497        fnSet(UnsizedFormat::A   , asA);
    498        fnSet(UnsizedFormat::LA  , asLA);
    499    };
    500 
    501 #define SET_COPY_DECAY(src,asR,asRG,asRGB,asRGBA,asL,asA,asLA) \
    502    fnSetCopyDecay(EffectiveFormat::src, EffectiveFormat::asR, EffectiveFormat::asRG,     \
    503                   EffectiveFormat::asRGB, EffectiveFormat::asRGBA, EffectiveFormat::asL, \
    504                   EffectiveFormat::asA, EffectiveFormat::asLA);
    505 
    506    //////
    507 
    508 #define SET_BY_SUFFIX(X) \
    509        SET_COPY_DECAY(   R##X, R##X,   MAX,    MAX,     MAX, Luminance##X,      MAX,                    MAX) \
    510        SET_COPY_DECAY(  RG##X, R##X, RG##X,    MAX,     MAX, Luminance##X,      MAX,                    MAX) \
    511        SET_COPY_DECAY( RGB##X, R##X, RG##X, RGB##X,     MAX, Luminance##X,      MAX,                    MAX) \
    512        SET_COPY_DECAY(RGBA##X, R##X, RG##X, RGB##X, RGBA##X, Luminance##X, Alpha##X, Luminance##X##Alpha##X)
    513 
    514    SET_BY_SUFFIX(8)   // WebGL decided that RGB8 should be guaranteed renderable.
    515    SET_BY_SUFFIX(16F) // RGB16F is renderable in EXT_color_buffer_half_float, though not
    516                       // EXT_color_buffer_float.
    517    SET_BY_SUFFIX(32F) // Technically RGB32F is never renderable, but no harm here.
    518 
    519 #undef SET_BY_SUFFIX
    520 
    521 
    522    //////
    523 
    524 #define SET_BY_SUFFIX(X) \
    525        SET_COPY_DECAY(   R##X, R##X,   MAX,    MAX,     MAX, MAX, MAX, MAX) \
    526        SET_COPY_DECAY(  RG##X, R##X, RG##X,    MAX,     MAX, MAX, MAX, MAX) \
    527        SET_COPY_DECAY(RGBA##X, R##X, RG##X, RGB##X, RGBA##X, MAX, MAX, MAX)
    528 
    529    SET_BY_SUFFIX(8I)
    530    SET_BY_SUFFIX(8UI)
    531 
    532    SET_BY_SUFFIX(16)
    533    SET_BY_SUFFIX(16I)
    534    SET_BY_SUFFIX(16UI)
    535 
    536    SET_BY_SUFFIX(32I)
    537    SET_BY_SUFFIX(32UI)
    538 
    539 #undef SET_BY_SUFFIX
    540 
    541    //////
    542 
    543    SET_COPY_DECAY(    RGB565, R8, RG8, RGB565,      MAX, Luminance8,    MAX,              MAX)
    544    SET_COPY_DECAY(     RGBA4, R8, RG8, RGB565,    RGBA4, Luminance8, Alpha8, Luminance8Alpha8)
    545    SET_COPY_DECAY(   RGB5_A1, R8, RG8, RGB565,  RGB5_A1, Luminance8, Alpha8, Luminance8Alpha8)
    546    SET_COPY_DECAY(  RGB10_A2, R8, RG8,   RGB8, RGB10_A2, Luminance8, Alpha8,              MAX)
    547 
    548    SET_COPY_DECAY(RGB10_A2UI, R8UI, RG8UI, RGB8UI, RGB10_A2UI, MAX, MAX, MAX)
    549 
    550    SET_COPY_DECAY(SRGB8_ALPHA8, MAX, MAX, MAX, SRGB8_ALPHA8, MAX, Alpha8, MAX)
    551 
    552    SET_COPY_DECAY(R11F_G11F_B10F, R16F, RG16F, R11F_G11F_B10F, MAX, Luminance16F, MAX, MAX)
    553 
    554 #undef SET_COPY_DECAY
    555 
    556  // clang-format on
    557 }
    558 
    559 //////////////////////////////////////////////////////////////////////////////////////////
    560 
    561 bool gAreFormatTablesInitialized = false;
    562 
    563 static void EnsureInitFormatTables(
    564    const StaticMutexAutoLock&)  // Prove that you locked it!
    565 {
    566  if (MOZ_LIKELY(gAreFormatTablesInitialized)) return;
    567 
    568  gAreFormatTablesInitialized = true;
    569 
    570  InitCompressedFormatInfo();
    571  InitFormatInfo();
    572 }
    573 
    574 //////////////////////////////////////////////////////////////////////////////////////////
    575 // Public funcs
    576 
    577 StaticMutex gFormatMapMutex;
    578 
    579 const FormatInfo* GetFormat(EffectiveFormat format) {
    580  StaticMutexAutoLock lock(gFormatMapMutex);
    581  EnsureInitFormatTables(lock);
    582 
    583  return GetFormatInfo_NoLock(format);
    584 }
    585 
    586 //////////////////////////////////////////////////////////////////////////////////////////
    587 
    588 const FormatInfo* FormatInfo::GetCopyDecayFormat(UnsizedFormat uf) const {
    589  return FindOrNull(this->copyDecayFormats, uf);
    590 }
    591 
    592 Maybe<PackingInfoInfo> PackingInfoInfo::For(const PackingInfo& pi) {
    593  PackingInfoInfo ret{};
    594 
    595  switch (pi.type) {
    596    case LOCAL_GL_UNSIGNED_SHORT_4_4_4_4:
    597    case LOCAL_GL_UNSIGNED_SHORT_5_5_5_1:
    598    case LOCAL_GL_UNSIGNED_SHORT_5_6_5:
    599      ret = {2, 1, true};
    600      break;
    601 
    602    case LOCAL_GL_UNSIGNED_INT_10F_11F_11F_REV:
    603    case LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV:
    604    case LOCAL_GL_UNSIGNED_INT_24_8:
    605    case LOCAL_GL_UNSIGNED_INT_5_9_9_9_REV:
    606      ret = {4, 1, true};
    607      break;
    608 
    609    case LOCAL_GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
    610      ret = {8, 1, true};
    611      break;
    612 
    613      // Alright, that's all the fixed-size unpackTypes.
    614 
    615    case LOCAL_GL_BYTE:
    616    case LOCAL_GL_UNSIGNED_BYTE:
    617      ret = {1, 0, false};
    618      break;
    619 
    620    case LOCAL_GL_SHORT:
    621    case LOCAL_GL_UNSIGNED_SHORT:
    622    case LOCAL_GL_HALF_FLOAT:
    623    case LOCAL_GL_HALF_FLOAT_OES:
    624      ret = {2, 0, false};
    625      break;
    626 
    627    case LOCAL_GL_INT:
    628    case LOCAL_GL_UNSIGNED_INT:
    629    case LOCAL_GL_FLOAT:
    630      ret = {4, 0, false};
    631      break;
    632 
    633    default:
    634      return {};
    635  }
    636 
    637  if (!ret.isPacked) {
    638    switch (pi.format) {
    639      case LOCAL_GL_RED:
    640      case LOCAL_GL_RED_INTEGER:
    641      case LOCAL_GL_LUMINANCE:
    642      case LOCAL_GL_ALPHA:
    643      case LOCAL_GL_DEPTH_COMPONENT:
    644        ret.elementsPerPixel = 1;
    645        break;
    646 
    647      case LOCAL_GL_RG:
    648      case LOCAL_GL_RG_INTEGER:
    649      case LOCAL_GL_LUMINANCE_ALPHA:
    650        ret.elementsPerPixel = 2;
    651        break;
    652 
    653      case LOCAL_GL_RGB:
    654      case LOCAL_GL_RGB_INTEGER:
    655      case LOCAL_GL_SRGB:
    656        ret.elementsPerPixel = 3;
    657        break;
    658 
    659      case LOCAL_GL_BGRA:
    660      case LOCAL_GL_RGBA:
    661      case LOCAL_GL_RGBA_INTEGER:
    662      case LOCAL_GL_SRGB_ALPHA:
    663        ret.elementsPerPixel = 4;
    664        break;
    665 
    666      default:
    667        return {};
    668    }
    669  }
    670 
    671  return Some(ret);
    672 }
    673 
    674 //////////////////////////////////////////////////////////////////////////////////////////
    675 //////////////////////////////////////////////////////////////////////////////////////////
    676 //////////////////////////////////////////////////////////////////////////////////////////
    677 //////////////////////////////////////////////////////////////////////////////////////////
    678 //////////////////////////////////////////////////////////////////////////////////////////
    679 //////////////////////////////////////////////////////////////////////////////////////////
    680 //////////////////////////////////////////////////////////////////////////////////////////
    681 //////////////////////////////////////////////////////////////////////////////////////////
    682 // FormatUsageAuthority
    683 
    684 bool FormatUsageInfo::IsUnpackValid(
    685    const PackingInfo& key, const DriverUnpackInfo** const out_value) const {
    686  auto itr = validUnpacks.find(key);
    687  if (itr == validUnpacks.end()) return false;
    688 
    689  *out_value = &(itr->second);
    690  return true;
    691 }
    692 
    693 void FormatUsageInfo::ResolveMaxSamples(gl::GLContext& gl) const {
    694  MOZ_ASSERT(gl.IsCurrent());
    695  MOZ_ASSERT(!this->maxSamplesKnown);
    696  MOZ_ASSERT(!this->maxSamples);
    697  this->maxSamplesKnown = true;
    698 
    699  const GLenum internalFormat = this->format->sizedFormat;
    700  if (!internalFormat) return;
    701  if (!gl.IsSupported(gl::GLFeature::internalformat_query)) return;
    702 
    703  // GL_SAMPLES returns a list in descending order, so ask for just one elem to
    704  // get the max.
    705  gl.fGetInternalformativ(LOCAL_GL_RENDERBUFFER, internalFormat,
    706                          LOCAL_GL_SAMPLES, 1,
    707                          reinterpret_cast<GLint*>(&this->maxSamples));
    708 }
    709 
    710 ////////////////////////////////////////
    711 
    712 static void AddSimpleUnsized(FormatUsageAuthority* fua, GLenum unpackFormat,
    713                             GLenum unpackType, EffectiveFormat effFormat) {
    714  auto usage = fua->EditUsage(effFormat);
    715  usage->isFilterable = true;
    716 
    717  const PackingInfo pi = {unpackFormat, unpackType};
    718  const DriverUnpackInfo dui = {unpackFormat, unpackFormat, unpackType};
    719  fua->AddTexUnpack(usage, pi, dui);
    720 
    721  fua->AllowUnsizedTexFormat(pi, usage);
    722 };
    723 
    724 /*static*/ const GLint FormatUsageInfo::kLuminanceSwizzleRGBA[4] = {
    725    LOCAL_GL_RED, LOCAL_GL_RED, LOCAL_GL_RED, LOCAL_GL_ONE};
    726 /*static*/ const GLint FormatUsageInfo::kAlphaSwizzleRGBA[4] = {
    727    LOCAL_GL_ZERO, LOCAL_GL_ZERO, LOCAL_GL_ZERO, LOCAL_GL_RED};
    728 /*static*/ const GLint FormatUsageInfo::kLumAlphaSwizzleRGBA[4] = {
    729    LOCAL_GL_RED, LOCAL_GL_RED, LOCAL_GL_RED, LOCAL_GL_GREEN};
    730 
    731 static bool AddLegacyFormats_LA8(FormatUsageAuthority* fua, gl::GLContext* gl) {
    732  if (gl->IsCoreProfile()) {
    733    if (!gl->IsSupported(gl::GLFeature::texture_swizzle)) return false;
    734 
    735    PackingInfo pi;
    736    DriverUnpackInfo dui;
    737 
    738    const auto fnAdd = [fua, &pi, &dui](EffectiveFormat effFormat,
    739                                        const GLint* swizzle) {
    740      auto usage = fua->EditUsage(effFormat);
    741      usage->isFilterable = true;
    742      usage->textureSwizzleRGBA = swizzle;
    743 
    744      fua->AddTexUnpack(usage, pi, dui);
    745 
    746      fua->AllowUnsizedTexFormat(pi, usage);
    747    };
    748 
    749    pi = {LOCAL_GL_LUMINANCE, LOCAL_GL_UNSIGNED_BYTE};
    750    dui = {LOCAL_GL_R8, LOCAL_GL_RED, LOCAL_GL_UNSIGNED_BYTE};
    751    fnAdd(EffectiveFormat::Luminance8, FormatUsageInfo::kLuminanceSwizzleRGBA);
    752 
    753    pi = {LOCAL_GL_ALPHA, LOCAL_GL_UNSIGNED_BYTE};
    754    dui = {LOCAL_GL_R8, LOCAL_GL_RED, LOCAL_GL_UNSIGNED_BYTE};
    755    fnAdd(EffectiveFormat::Alpha8, FormatUsageInfo::kAlphaSwizzleRGBA);
    756 
    757    pi = {LOCAL_GL_LUMINANCE_ALPHA, LOCAL_GL_UNSIGNED_BYTE};
    758    dui = {LOCAL_GL_RG8, LOCAL_GL_RG, LOCAL_GL_UNSIGNED_BYTE};
    759    fnAdd(EffectiveFormat::Luminance8Alpha8,
    760          FormatUsageInfo::kLumAlphaSwizzleRGBA);
    761  } else {
    762    // clang-format off
    763        AddSimpleUnsized(fua, LOCAL_GL_LUMINANCE      , LOCAL_GL_UNSIGNED_BYTE, EffectiveFormat::Luminance8      );
    764        AddSimpleUnsized(fua, LOCAL_GL_ALPHA          , LOCAL_GL_UNSIGNED_BYTE, EffectiveFormat::Alpha8          );
    765        AddSimpleUnsized(fua, LOCAL_GL_LUMINANCE_ALPHA, LOCAL_GL_UNSIGNED_BYTE, EffectiveFormat::Luminance8Alpha8);
    766    // clang-format on
    767  }
    768 
    769  return true;
    770 }
    771 
    772 static bool AddUnsizedFormats(FormatUsageAuthority* fua, gl::GLContext* gl) {
    773  // clang-format off
    774 
    775    // GLES 2.0.25, p63, Table 3.4
    776    AddSimpleUnsized(fua, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE         , EffectiveFormat::RGBA8  );
    777    AddSimpleUnsized(fua, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_SHORT_4_4_4_4, EffectiveFormat::RGBA4  );
    778    AddSimpleUnsized(fua, LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_SHORT_5_5_5_1, EffectiveFormat::RGB5_A1);
    779    AddSimpleUnsized(fua, LOCAL_GL_RGB , LOCAL_GL_UNSIGNED_BYTE         , EffectiveFormat::RGB8   );
    780    AddSimpleUnsized(fua, LOCAL_GL_RGB , LOCAL_GL_UNSIGNED_SHORT_5_6_5  , EffectiveFormat::RGB565 );
    781 
    782    // L, A, LA
    783    return AddLegacyFormats_LA8(fua, gl);
    784 
    785  // clang-format on
    786 }
    787 
    788 void FormatUsageInfo::SetRenderable(const FormatRenderableState& state) {
    789  if (!renderableState.IsExplicit()) {
    790    renderableState = state;
    791  }
    792 
    793 #ifdef DEBUG
    794  const auto format = this->format;
    795  if (format->IsColorFormat()) {
    796    const auto& map = format->copyDecayFormats;
    797    const auto itr = map.find(format->unsizedFormat);
    798    MOZ_ASSERT(itr != map.end(),
    799               "Renderable formats must be in copyDecayFormats.");
    800    MOZ_ASSERT(itr->second == format);
    801  }
    802 #endif
    803 }
    804 
    805 std::unique_ptr<FormatUsageAuthority> FormatUsageAuthority::CreateForWebGL1(
    806    gl::GLContext* gl) {
    807  std::unique_ptr<FormatUsageAuthority> ret(new FormatUsageAuthority);
    808  const auto ptr = ret.get();
    809 
    810  ////////////////////////////////////////////////////////////////////////////
    811  // Usages
    812 
    813  const auto fnSet = [ptr](EffectiveFormat effFormat, bool isRenderable,
    814                           bool isFilterable) {
    815    MOZ_ASSERT(!ptr->GetUsage(effFormat));
    816 
    817    auto usage = ptr->EditUsage(effFormat);
    818    usage->isFilterable = isFilterable;
    819 
    820    if (isRenderable) {
    821      usage->SetRenderable();
    822    }
    823  };
    824 
    825  // Largely from GLES 2.0.25, p117, Table 4.5, but also:
    826  // * RGBA8: Made renderable in WebGL 1.0, "Framebuffer Object Attachments".
    827  // * RGB8: Not guaranteed by ES2 to be renderable, but we should allow it for
    828  //   web-compat. Min-capability mode should mark this as non-renderable.
    829 
    830  constexpr bool ALWAYS = true;  // For better contrast with `false` in tables.
    831 
    832  // clang-format off
    833  //   |              format              | renderable | filterable |
    834  fnSet(EffectiveFormat::RGBA8            , ALWAYS     , ALWAYS     );
    835  fnSet(EffectiveFormat::RGBA4            , ALWAYS     , ALWAYS     );
    836  fnSet(EffectiveFormat::RGB5_A1          , ALWAYS     , ALWAYS     );
    837  fnSet(EffectiveFormat::RGB565           , ALWAYS     , ALWAYS     );
    838  fnSet(EffectiveFormat::RGB8             , ALWAYS     , ALWAYS     );
    839  // "Legacy" formats
    840  fnSet(EffectiveFormat::Luminance8Alpha8 , false      , ALWAYS     );
    841  fnSet(EffectiveFormat::Luminance8       , false      , ALWAYS     );
    842  fnSet(EffectiveFormat::Alpha8           , false      , ALWAYS     );
    843  // Depth/stencil
    844  fnSet(EffectiveFormat::DEPTH_COMPONENT16, ALWAYS     , ALWAYS     );
    845  fnSet(EffectiveFormat::DEPTH_COMPONENT24, ALWAYS     , ALWAYS     );
    846  fnSet(EffectiveFormat::STENCIL_INDEX8   , ALWAYS     , false      );
    847  // Added in WebGL 1.0 spec:
    848  fnSet(EffectiveFormat::DEPTH24_STENCIL8 , ALWAYS     , ALWAYS     );
    849  //   |              format              | renderable | filterable |
    850  // clang-format on
    851 
    852  ////////////////////////////////////
    853  // RB formats
    854 
    855 #define FOO(x) \
    856  ptr->AllowRBFormat(LOCAL_GL_##x, ptr->GetUsage(EffectiveFormat::x))
    857 
    858  FOO(RGBA4);
    859  FOO(RGB5_A1);
    860  FOO(RGB565);
    861  FOO(DEPTH_COMPONENT16);
    862  FOO(STENCIL_INDEX8);
    863  // FOO(DEPTH24_STENCIL8 ); // WebGL 1 uses DEPTH_STENCIL instead of
    864  // DEPTH24_STENCIL8.
    865 
    866 #undef FOO
    867 
    868  ptr->AllowRBFormat(LOCAL_GL_DEPTH_STENCIL,
    869                     ptr->GetUsage(EffectiveFormat::DEPTH24_STENCIL8));
    870 
    871  ////////////////////////////////////////////////////////////////////////////
    872 
    873  if (!AddUnsizedFormats(ptr, gl)) return nullptr;
    874 
    875  return ret;
    876 }
    877 
    878 std::unique_ptr<FormatUsageAuthority> FormatUsageAuthority::CreateForWebGL2(
    879    gl::GLContext* gl) {
    880  std::unique_ptr<FormatUsageAuthority> ret(new FormatUsageAuthority);
    881  const auto ptr = ret.get();
    882 
    883  ////////////////////////////////////////////////////////////////////////////
    884  // GLES 3.0.4 p111-113
    885 
    886  const auto fnAddSizedUnpack = [ptr](EffectiveFormat effFormat,
    887                                      GLenum internalFormat,
    888                                      GLenum unpackFormat, GLenum unpackType) {
    889    auto usage = ptr->EditUsage(effFormat);
    890 
    891    const PackingInfo pi = {unpackFormat, unpackType};
    892    const DriverUnpackInfo dui = {internalFormat, unpackFormat, unpackType};
    893    ptr->AddTexUnpack(usage, pi, dui);
    894  };
    895 
    896  // clang-format off
    897 #define FOO(x) EffectiveFormat::x, LOCAL_GL_ ## x
    898 
    899    // RGBA
    900    fnAddSizedUnpack(FOO(RGBA8       ), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE              );
    901    fnAddSizedUnpack(FOO(RGBA4       ), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_SHORT_4_4_4_4     );
    902    fnAddSizedUnpack(FOO(RGBA4       ), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE              );
    903    fnAddSizedUnpack(FOO(RGB5_A1     ), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_SHORT_5_5_5_1     );
    904    fnAddSizedUnpack(FOO(RGB5_A1     ), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE              );
    905    fnAddSizedUnpack(FOO(RGB5_A1     ), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV);
    906    fnAddSizedUnpack(FOO(SRGB8_ALPHA8), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_BYTE              );
    907    fnAddSizedUnpack(FOO(RGBA8_SNORM ), LOCAL_GL_RGBA, LOCAL_GL_BYTE                       );
    908    fnAddSizedUnpack(FOO(RGB10_A2    ), LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV);
    909    fnAddSizedUnpack(FOO(RGBA16F     ), LOCAL_GL_RGBA, LOCAL_GL_HALF_FLOAT                 );
    910    fnAddSizedUnpack(FOO(RGBA16F     ), LOCAL_GL_RGBA, LOCAL_GL_FLOAT                      );
    911    fnAddSizedUnpack(FOO(RGBA32F     ), LOCAL_GL_RGBA, LOCAL_GL_FLOAT                      );
    912 
    913    // RGBA_INTEGER
    914    fnAddSizedUnpack(FOO(RGBA8UI   ), LOCAL_GL_RGBA_INTEGER, LOCAL_GL_UNSIGNED_BYTE              );
    915    fnAddSizedUnpack(FOO(RGBA8I    ), LOCAL_GL_RGBA_INTEGER, LOCAL_GL_BYTE                       );
    916    fnAddSizedUnpack(FOO(RGBA16UI  ), LOCAL_GL_RGBA_INTEGER, LOCAL_GL_UNSIGNED_SHORT             );
    917    fnAddSizedUnpack(FOO(RGBA16I   ), LOCAL_GL_RGBA_INTEGER, LOCAL_GL_SHORT                      );
    918    fnAddSizedUnpack(FOO(RGBA32UI  ), LOCAL_GL_RGBA_INTEGER, LOCAL_GL_UNSIGNED_INT               );
    919    fnAddSizedUnpack(FOO(RGBA32I   ), LOCAL_GL_RGBA_INTEGER, LOCAL_GL_INT                        );
    920    fnAddSizedUnpack(FOO(RGB10_A2UI), LOCAL_GL_RGBA_INTEGER, LOCAL_GL_UNSIGNED_INT_2_10_10_10_REV);
    921 
    922    // RGB
    923    fnAddSizedUnpack(FOO(RGB8          ), LOCAL_GL_RGB, LOCAL_GL_UNSIGNED_BYTE               );
    924    fnAddSizedUnpack(FOO(SRGB8         ), LOCAL_GL_RGB, LOCAL_GL_UNSIGNED_BYTE               );
    925    fnAddSizedUnpack(FOO(RGB565        ), LOCAL_GL_RGB, LOCAL_GL_UNSIGNED_SHORT_5_6_5        );
    926    fnAddSizedUnpack(FOO(RGB565        ), LOCAL_GL_RGB, LOCAL_GL_UNSIGNED_BYTE               );
    927    fnAddSizedUnpack(FOO(RGB8_SNORM    ), LOCAL_GL_RGB, LOCAL_GL_BYTE                        );
    928    fnAddSizedUnpack(FOO(R11F_G11F_B10F), LOCAL_GL_RGB, LOCAL_GL_UNSIGNED_INT_10F_11F_11F_REV);
    929    fnAddSizedUnpack(FOO(R11F_G11F_B10F), LOCAL_GL_RGB, LOCAL_GL_HALF_FLOAT                  );
    930    fnAddSizedUnpack(FOO(R11F_G11F_B10F), LOCAL_GL_RGB, LOCAL_GL_FLOAT                       );
    931    fnAddSizedUnpack(FOO(RGB16F        ), LOCAL_GL_RGB, LOCAL_GL_HALF_FLOAT                  );
    932    fnAddSizedUnpack(FOO(RGB16F        ), LOCAL_GL_RGB, LOCAL_GL_FLOAT                       );
    933    fnAddSizedUnpack(FOO(RGB9_E5       ), LOCAL_GL_RGB, LOCAL_GL_UNSIGNED_INT_5_9_9_9_REV    );
    934    fnAddSizedUnpack(FOO(RGB9_E5       ), LOCAL_GL_RGB, LOCAL_GL_HALF_FLOAT                  );
    935    fnAddSizedUnpack(FOO(RGB9_E5       ), LOCAL_GL_RGB, LOCAL_GL_FLOAT                       );
    936    fnAddSizedUnpack(FOO(RGB32F        ), LOCAL_GL_RGB, LOCAL_GL_FLOAT                       );
    937 
    938    // RGB_INTEGER
    939    fnAddSizedUnpack(FOO(RGB8UI ), LOCAL_GL_RGB_INTEGER, LOCAL_GL_UNSIGNED_BYTE );
    940    fnAddSizedUnpack(FOO(RGB8I  ), LOCAL_GL_RGB_INTEGER, LOCAL_GL_BYTE          );
    941    fnAddSizedUnpack(FOO(RGB16UI), LOCAL_GL_RGB_INTEGER, LOCAL_GL_UNSIGNED_SHORT);
    942    fnAddSizedUnpack(FOO(RGB16I ), LOCAL_GL_RGB_INTEGER, LOCAL_GL_SHORT         );
    943    fnAddSizedUnpack(FOO(RGB32UI), LOCAL_GL_RGB_INTEGER, LOCAL_GL_UNSIGNED_INT  );
    944    fnAddSizedUnpack(FOO(RGB32I ), LOCAL_GL_RGB_INTEGER, LOCAL_GL_INT           );
    945 
    946    // RG
    947    fnAddSizedUnpack(FOO(RG8      ), LOCAL_GL_RG, LOCAL_GL_UNSIGNED_BYTE);
    948    fnAddSizedUnpack(FOO(RG8_SNORM), LOCAL_GL_RG, LOCAL_GL_BYTE         );
    949    fnAddSizedUnpack(FOO(RG16F    ), LOCAL_GL_RG, LOCAL_GL_HALF_FLOAT   );
    950    fnAddSizedUnpack(FOO(RG16F    ), LOCAL_GL_RG, LOCAL_GL_FLOAT        );
    951    fnAddSizedUnpack(FOO(RG32F    ), LOCAL_GL_RG, LOCAL_GL_FLOAT        );
    952 
    953    // RG_INTEGER
    954    fnAddSizedUnpack(FOO(RG8UI ), LOCAL_GL_RG_INTEGER, LOCAL_GL_UNSIGNED_BYTE );
    955    fnAddSizedUnpack(FOO(RG8I  ), LOCAL_GL_RG_INTEGER, LOCAL_GL_BYTE          );
    956    fnAddSizedUnpack(FOO(RG16UI), LOCAL_GL_RG_INTEGER, LOCAL_GL_UNSIGNED_SHORT);
    957    fnAddSizedUnpack(FOO(RG16I ), LOCAL_GL_RG_INTEGER, LOCAL_GL_SHORT         );
    958    fnAddSizedUnpack(FOO(RG32UI), LOCAL_GL_RG_INTEGER, LOCAL_GL_UNSIGNED_INT  );
    959    fnAddSizedUnpack(FOO(RG32I ), LOCAL_GL_RG_INTEGER, LOCAL_GL_INT           );
    960 
    961    // RED
    962    fnAddSizedUnpack(FOO(R8      ), LOCAL_GL_RED, LOCAL_GL_UNSIGNED_BYTE);
    963    fnAddSizedUnpack(FOO(R8_SNORM), LOCAL_GL_RED, LOCAL_GL_BYTE         );
    964    fnAddSizedUnpack(FOO(R16F    ), LOCAL_GL_RED, LOCAL_GL_HALF_FLOAT   );
    965    fnAddSizedUnpack(FOO(R16F    ), LOCAL_GL_RED, LOCAL_GL_FLOAT        );
    966    fnAddSizedUnpack(FOO(R32F    ), LOCAL_GL_RED, LOCAL_GL_FLOAT        );
    967 
    968    // RED_INTEGER
    969    fnAddSizedUnpack(FOO(R8UI ), LOCAL_GL_RED_INTEGER, LOCAL_GL_UNSIGNED_BYTE );
    970    fnAddSizedUnpack(FOO(R8I  ), LOCAL_GL_RED_INTEGER, LOCAL_GL_BYTE          );
    971    fnAddSizedUnpack(FOO(R16UI), LOCAL_GL_RED_INTEGER, LOCAL_GL_UNSIGNED_SHORT);
    972    fnAddSizedUnpack(FOO(R16I ), LOCAL_GL_RED_INTEGER, LOCAL_GL_SHORT         );
    973    fnAddSizedUnpack(FOO(R32UI), LOCAL_GL_RED_INTEGER, LOCAL_GL_UNSIGNED_INT  );
    974    fnAddSizedUnpack(FOO(R32I ), LOCAL_GL_RED_INTEGER, LOCAL_GL_INT           );
    975 
    976    // DEPTH_COMPONENT
    977    fnAddSizedUnpack(FOO(DEPTH_COMPONENT16 ), LOCAL_GL_DEPTH_COMPONENT, LOCAL_GL_UNSIGNED_SHORT);
    978    fnAddSizedUnpack(FOO(DEPTH_COMPONENT16 ), LOCAL_GL_DEPTH_COMPONENT, LOCAL_GL_UNSIGNED_INT  );
    979    fnAddSizedUnpack(FOO(DEPTH_COMPONENT24 ), LOCAL_GL_DEPTH_COMPONENT, LOCAL_GL_UNSIGNED_INT  );
    980    fnAddSizedUnpack(FOO(DEPTH_COMPONENT32F), LOCAL_GL_DEPTH_COMPONENT, LOCAL_GL_FLOAT         );
    981 
    982    // DEPTH_STENCIL
    983    fnAddSizedUnpack(FOO(DEPTH24_STENCIL8 ), LOCAL_GL_DEPTH_STENCIL, LOCAL_GL_UNSIGNED_INT_24_8             );
    984    fnAddSizedUnpack(FOO(DEPTH32F_STENCIL8), LOCAL_GL_DEPTH_STENCIL, LOCAL_GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
    985 
    986 #undef FOO
    987  // clang-format on
    988 
    989  ////////////////////////////////////////////////////////////////////////////
    990 
    991  // For renderable, see GLES 3.0.4, p212 "Framebuffer Completeness"
    992  // For filterable, see GLES 3.0.4, p161 "...a texture is complete unless..."
    993 
    994  const auto fnAllowES3TexFormat = [ptr](GLenum sizedFormat,
    995                                         EffectiveFormat effFormat,
    996                                         bool isRenderable, bool isFilterable) {
    997    auto usage = ptr->EditUsage(effFormat);
    998    usage->isFilterable = isFilterable;
    999 
   1000    if (isRenderable) {
   1001      usage->SetRenderable();
   1002    }
   1003 
   1004    ptr->AllowSizedTexFormat(sizedFormat, usage);
   1005 
   1006    if (isRenderable) {
   1007      ptr->AllowRBFormat(sizedFormat, usage);
   1008    }
   1009  };
   1010 
   1011  constexpr bool ALWAYS = true;  // For better contrast with `false` in tables.
   1012 
   1013  // clang-format off
   1014 #define _(x)  LOCAL_GL_##x, EffectiveFormat::x
   1015 
   1016  // GLES 3.0.4, p128-129 "Required Texture Formats"
   1017  // GLES 3.0.4, p130-132, table 3.13
   1018  //                 |     format          | renderable | filterable |
   1019  fnAllowES3TexFormat(_(R8)                , ALWAYS     , ALWAYS     );
   1020  fnAllowES3TexFormat(_(R8_SNORM)          , false      , ALWAYS     );
   1021  fnAllowES3TexFormat(_(RG8)               , ALWAYS     , ALWAYS     );
   1022  fnAllowES3TexFormat(_(RG8_SNORM)         , false      , ALWAYS     );
   1023  fnAllowES3TexFormat(_(RGB8)              , ALWAYS     , ALWAYS     );
   1024  fnAllowES3TexFormat(_(RGB8_SNORM)        , false      , ALWAYS     );
   1025  fnAllowES3TexFormat(_(RGB565)            , ALWAYS     , ALWAYS     );
   1026  fnAllowES3TexFormat(_(RGBA4)             , ALWAYS     , ALWAYS     );
   1027  fnAllowES3TexFormat(_(RGB5_A1)           , ALWAYS     , ALWAYS     );
   1028  fnAllowES3TexFormat(_(RGBA8)             , ALWAYS     , ALWAYS     );
   1029  fnAllowES3TexFormat(_(RGBA8_SNORM)       , false      , ALWAYS     );
   1030  fnAllowES3TexFormat(_(RGB10_A2)          , ALWAYS     , ALWAYS     );
   1031  fnAllowES3TexFormat(_(RGB10_A2UI)        , ALWAYS     , false      );
   1032 
   1033  fnAllowES3TexFormat(_(SRGB8)             , false      , ALWAYS     );
   1034  fnAllowES3TexFormat(_(SRGB8_ALPHA8)      , ALWAYS     , ALWAYS     );
   1035  //                 |     format          | renderable | filterable |
   1036  fnAllowES3TexFormat(_(R16F)              , false      , ALWAYS     );
   1037  fnAllowES3TexFormat(_(RG16F)             , false      , ALWAYS     );
   1038  fnAllowES3TexFormat(_(RGB16F)            , false      , ALWAYS     );
   1039  fnAllowES3TexFormat(_(RGBA16F)           , false      , ALWAYS     );
   1040 
   1041  fnAllowES3TexFormat(_(R32F)              , false      , false      );
   1042  fnAllowES3TexFormat(_(RG32F)             , false      , false      );
   1043  fnAllowES3TexFormat(_(RGB32F)            , false      , false      );
   1044  fnAllowES3TexFormat(_(RGBA32F)           , false      , false      );
   1045 
   1046  fnAllowES3TexFormat(_(R11F_G11F_B10F)    , false      , ALWAYS     );
   1047  fnAllowES3TexFormat(_(RGB9_E5)           , false      , ALWAYS     );
   1048  //                 |     format          | renderable | filterable |
   1049  fnAllowES3TexFormat(_(R8I)               , ALWAYS     , false      );
   1050  fnAllowES3TexFormat(_(R8UI)              , ALWAYS     , false      );
   1051  fnAllowES3TexFormat(_(R16I)              , ALWAYS     , false      );
   1052  fnAllowES3TexFormat(_(R16UI)             , ALWAYS     , false      );
   1053  fnAllowES3TexFormat(_(R32I)              , ALWAYS     , false      );
   1054  fnAllowES3TexFormat(_(R32UI)             , ALWAYS     , false      );
   1055 
   1056  fnAllowES3TexFormat(_(RG8I)              , ALWAYS     , false      );
   1057  fnAllowES3TexFormat(_(RG8UI)             , ALWAYS     , false      );
   1058  fnAllowES3TexFormat(_(RG16I)             , ALWAYS     , false      );
   1059  fnAllowES3TexFormat(_(RG16UI)            , ALWAYS     , false      );
   1060  fnAllowES3TexFormat(_(RG32I)             , ALWAYS     , false      );
   1061  fnAllowES3TexFormat(_(RG32UI)            , ALWAYS     , false      );
   1062  //                 |     format          | renderable | filterable |
   1063  fnAllowES3TexFormat(_(RGB8I)             , false      , false      );
   1064  fnAllowES3TexFormat(_(RGB8UI)            , false      , false      );
   1065  fnAllowES3TexFormat(_(RGB16I)            , false      , false      );
   1066  fnAllowES3TexFormat(_(RGB16UI)           , false      , false      );
   1067  fnAllowES3TexFormat(_(RGB32I)            , false      , false      );
   1068  fnAllowES3TexFormat(_(RGB32UI)           , false      , false      );
   1069 
   1070  fnAllowES3TexFormat(_(RGBA8I)            , ALWAYS     , false      );
   1071  fnAllowES3TexFormat(_(RGBA8UI)           , ALWAYS     , false      );
   1072  fnAllowES3TexFormat(_(RGBA16I)           , ALWAYS     , false      );
   1073  fnAllowES3TexFormat(_(RGBA16UI)          , ALWAYS     , false      );
   1074  fnAllowES3TexFormat(_(RGBA32I)           , ALWAYS     , false      );
   1075  fnAllowES3TexFormat(_(RGBA32UI)          , ALWAYS     , false      );
   1076  //                 |     format          | renderable | filterable |
   1077  fnAllowES3TexFormat(_(DEPTH_COMPONENT16) , ALWAYS     , false      ); // [1]
   1078  fnAllowES3TexFormat(_(DEPTH_COMPONENT24) , ALWAYS     , false      ); // [1]
   1079  fnAllowES3TexFormat(_(DEPTH_COMPONENT32F), ALWAYS     , false      ); // [1]
   1080  fnAllowES3TexFormat(_(DEPTH24_STENCIL8)  , ALWAYS     , false      ); // [1]
   1081  fnAllowES3TexFormat(_(DEPTH32F_STENCIL8) , ALWAYS     , false      ); // [1]
   1082 
   1083  // [1]: Sized depth or depth-stencil formats are not filterable
   1084  //      per GLES 3.0.6 p161.
   1085  //      Specifically, they're texture-incomplete if depth-compare:none and
   1086  //      not NEAREST.
   1087 
   1088 #undef _
   1089  // clang-format on
   1090 
   1091  // GLES 3.0.4, p206, "Required Renderbuffer Formats":
   1092  // "Implementations are also required to support STENCIL_INDEX8. Requesting
   1093  // this internal format for a renderbuffer will allocate at least 8 stencil
   1094  // bit planes."
   1095 
   1096  auto usage = ptr->EditUsage(EffectiveFormat::STENCIL_INDEX8);
   1097  usage->SetRenderable();
   1098  ptr->AllowRBFormat(LOCAL_GL_STENCIL_INDEX8, usage);
   1099 
   1100  ////////////////
   1101  // Legacy formats
   1102 
   1103  if (!AddUnsizedFormats(ptr, gl)) return nullptr;
   1104 
   1105  ptr->AllowRBFormat(LOCAL_GL_DEPTH_STENCIL,
   1106                     ptr->GetUsage(EffectiveFormat::DEPTH24_STENCIL8));
   1107 
   1108  ////////////////////////////////////
   1109 
   1110  return ret;
   1111 }
   1112 
   1113 //////////////////////////////////////////////////////////////////////////////////////////
   1114 
   1115 void FormatUsageAuthority::AddTexUnpack(FormatUsageInfo* usage,
   1116                                        const PackingInfo& pi,
   1117                                        const DriverUnpackInfo& dui) {
   1118  // Don't AlwaysInsert here, since we'll see duplicates from sized and unsized
   1119  // formats.
   1120  auto res = usage->validUnpacks.insert({pi, dui});
   1121  auto itr = res.first;
   1122 
   1123  if (!usage->idealUnpack) {
   1124    // First one!
   1125    usage->idealUnpack = &(itr->second);
   1126  }
   1127 
   1128  mValidTexUnpackFormats.insert(pi.format);
   1129  mValidTexUnpackTypes.insert(pi.type);
   1130 }
   1131 
   1132 static bool Contains(const std::set<GLenum>& set, GLenum key) {
   1133  return set.find(key) != set.end();
   1134 }
   1135 
   1136 bool FormatUsageAuthority::IsInternalFormatEnumValid(
   1137    GLenum internalFormat) const {
   1138  return Contains(mValidTexInternalFormats, internalFormat);
   1139 }
   1140 
   1141 bool FormatUsageAuthority::AreUnpackEnumsValid(GLenum unpackFormat,
   1142                                               GLenum unpackType) const {
   1143  return (Contains(mValidTexUnpackFormats, unpackFormat) &&
   1144          Contains(mValidTexUnpackTypes, unpackType));
   1145 }
   1146 
   1147 ////////////////////
   1148 
   1149 void FormatUsageAuthority::AllowRBFormat(GLenum sizedFormat,
   1150                                         const FormatUsageInfo* usage,
   1151                                         const bool expectRenderable) {
   1152  MOZ_ASSERT(!usage->format->compression);
   1153  MOZ_ASSERT(usage->format->sizedFormat);
   1154  MOZ_ASSERT(usage->IsRenderable() || !expectRenderable);
   1155 
   1156  const auto& found = mRBFormatMap.find(sizedFormat);
   1157  if (found != mRBFormatMap.end()) {
   1158    MOZ_ASSERT(found->second == usage);
   1159    return;
   1160  }
   1161  AlwaysInsert(mRBFormatMap, sizedFormat, usage);
   1162 }
   1163 
   1164 void FormatUsageAuthority::AllowSizedTexFormat(GLenum sizedFormat,
   1165                                               const FormatUsageInfo* usage) {
   1166  if (usage->format->compression) {
   1167    MOZ_ASSERT(usage->isFilterable, "Compressed formats should be filterable.");
   1168  } else {
   1169    MOZ_ASSERT(!usage->validUnpacks.empty() && usage->idealUnpack,
   1170               "AddTexUnpack() first.");
   1171  }
   1172 
   1173  AlwaysInsert(mSizedTexFormatMap, sizedFormat, usage);
   1174 
   1175  mValidTexInternalFormats.insert(sizedFormat);
   1176 }
   1177 
   1178 void FormatUsageAuthority::AllowUnsizedTexFormat(const PackingInfo& pi,
   1179                                                 const FormatUsageInfo* usage) {
   1180  MOZ_ASSERT(!usage->format->compression);
   1181  MOZ_ASSERT(!usage->validUnpacks.empty() && usage->idealUnpack,
   1182             "AddTexUnpack() first.");
   1183 
   1184  AlwaysInsert(mUnsizedTexFormatMap, pi, usage);
   1185 
   1186  mValidTexInternalFormats.insert(pi.format);
   1187  mValidTexUnpackFormats.insert(pi.format);
   1188  mValidTexUnpackTypes.insert(pi.type);
   1189 }
   1190 
   1191 const FormatUsageInfo* FormatUsageAuthority::GetRBUsage(
   1192    GLenum sizedFormat) const {
   1193  return FindOrNull(mRBFormatMap, sizedFormat);
   1194 }
   1195 
   1196 const FormatUsageInfo* FormatUsageAuthority::GetSizedTexUsage(
   1197    GLenum sizedFormat) const {
   1198  return FindOrNull(mSizedTexFormatMap, sizedFormat);
   1199 }
   1200 
   1201 const FormatUsageInfo* FormatUsageAuthority::GetUnsizedTexUsage(
   1202    const PackingInfo& pi) const {
   1203  return FindOrNull(mUnsizedTexFormatMap, pi);
   1204 }
   1205 
   1206 FormatUsageInfo* FormatUsageAuthority::EditUsage(EffectiveFormat format) {
   1207  auto itr = mUsageMap.find(format);
   1208 
   1209  if (itr == mUsageMap.end()) {
   1210    const FormatInfo* formatInfo = GetFormat(format);
   1211    MOZ_RELEASE_ASSERT(formatInfo, "GFX: no format info set.");
   1212 
   1213    FormatUsageInfo usage(formatInfo);
   1214 
   1215    auto res = mUsageMap.insert({format, usage});
   1216    DebugOnly<bool> didInsert = res.second;
   1217    MOZ_ASSERT(didInsert);
   1218 
   1219    itr = res.first;
   1220  }
   1221 
   1222  return &(itr->second);
   1223 }
   1224 
   1225 const FormatUsageInfo* FormatUsageAuthority::GetUsage(
   1226    EffectiveFormat format) const {
   1227  auto itr = mUsageMap.find(format);
   1228  if (itr == mUsageMap.end()) return nullptr;
   1229 
   1230  return &(itr->second);
   1231 }
   1232 
   1233 ////////////////////////////////////////////////////////////////////////////////
   1234 
   1235 }  // namespace mozilla::webgl