tor-browser

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

WebGLExtensions.cpp (35362B)


      1 /* -*- Mode: C++; tab-width: 20; 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 "WebGLExtensions.h"
      7 
      8 #include "GLContext.h"
      9 #include "WebGLContext.h"
     10 #include "WebGLFormats.h"
     11 #include "mozilla/Casting.h"
     12 #include "mozilla/ScopeExit.h"
     13 #include "mozilla/StaticPrefs_webgl.h"
     14 #include "mozilla/dom/WebGLRenderingContextBinding.h"
     15 
     16 namespace mozilla {
     17 
     18 static bool TestShaderCompile(gl::GLContext* const gl, const GLenum type,
     19                              const std::string& source) {
     20  const auto shader = gl->fCreateShader(type);
     21  const auto cleanup = MakeScopeExit([&]() { gl->fDeleteShader(shader); });
     22 
     23  const std::array<const char*, 1> parts = {source.c_str()};
     24  gl->fShaderSource(shader, parts.size(), parts.data(), nullptr);
     25  gl->fCompileShader(shader);
     26 
     27  GLint status = 0;
     28  gl->fGetShaderiv(shader, LOCAL_GL_COMPILE_STATUS, &status);
     29 
     30  if (status == LOCAL_GL_TRUE) return true;
     31 
     32  std::vector<char> chars;
     33  chars.resize(1000);
     34  gl->fGetShaderInfoLog(shader, LazyAssertedCast(chars.size() - 1), nullptr,
     35                        chars.data());
     36  printf_stderr("GetShaderInfoLog() ->\n%s\n", chars.data());
     37 
     38 #if defined(MOZ_WIDGET_ANDROID) && (defined(_M_IX86) || defined(__i386__) || \
     39                                    defined(__x86_64__) || defined(__amd64__))
     40  // Flakey gl on x86 android emulators in CI sometimes crash on the first
     41  // GetShaderSource call.
     42  printf_stderr("source ->\n%s\n", source.c_str());
     43 #else
     44  gl->fGetShaderSource(shader, LazyAssertedCast(chars.size() - 1), nullptr,
     45                       chars.data());
     46  printf_stderr("GetShaderSource() ->\n%s\n", chars.data());
     47 #endif
     48 
     49  return false;
     50 }
     51 
     52 // -
     53 
     54 WebGLExtensionBlendMinMax::WebGLExtensionBlendMinMax(WebGLContext* webgl)
     55    : WebGLExtensionBase(webgl) {
     56  MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
     57 }
     58 
     59 bool WebGLExtensionBlendMinMax::IsSupported(const WebGLContext* webgl) {
     60  if (webgl->IsWebGL2()) return false;
     61 
     62  return webgl->GL()->IsSupported(gl::GLFeature::blend_minmax);
     63 }
     64 
     65 // -
     66 
     67 WebGLExtensionColorBufferFloat::WebGLExtensionColorBufferFloat(
     68    WebGLContext* webgl)
     69    : WebGLExtensionBase(webgl) {
     70  MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
     71  SetRenderable(webgl::FormatRenderableState::Implicit(
     72      WebGLExtensionID::WEBGL_color_buffer_float));
     73 }
     74 
     75 void WebGLExtensionColorBufferFloat::SetRenderable(
     76    const webgl::FormatRenderableState& state) {
     77  auto& fua = mContext->mFormatUsage;
     78 
     79  auto fnUpdateUsage = [&](GLenum sizedFormat,
     80                           webgl::EffectiveFormat effFormat) {
     81    auto usage = fua->EditUsage(effFormat);
     82    usage->SetRenderable(state);
     83    fua->AllowRBFormat(sizedFormat, usage);
     84  };
     85 
     86 #define FOO(x) fnUpdateUsage(LOCAL_GL_##x, webgl::EffectiveFormat::x)
     87 
     88  // The extension doesn't actually add RGB32F; only RGBA32F.
     89  FOO(RGBA32F);
     90 
     91 #undef FOO
     92 }
     93 
     94 void WebGLExtensionColorBufferFloat::OnSetExplicit() {
     95  SetRenderable(webgl::FormatRenderableState::Explicit());
     96 }
     97 
     98 bool WebGLExtensionColorBufferFloat::IsSupported(const WebGLContext* webgl) {
     99  if (webgl->IsWebGL2()) return false;
    100 
    101  const auto& gl = webgl->gl;
    102  return gl->IsSupported(gl::GLFeature::renderbuffer_color_float) &&
    103         gl->IsSupported(gl::GLFeature::frag_color_float);
    104 }
    105 
    106 // -
    107 
    108 WebGLExtensionColorBufferHalfFloat::WebGLExtensionColorBufferHalfFloat(
    109    WebGLContext* webgl)
    110    : WebGLExtensionBase(webgl) {
    111  MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
    112  SetRenderable(webgl::FormatRenderableState::Implicit(
    113      WebGLExtensionID::EXT_color_buffer_half_float));
    114 }
    115 
    116 void WebGLExtensionColorBufferHalfFloat::SetRenderable(
    117    const webgl::FormatRenderableState& state) {
    118  auto& fua = mContext->mFormatUsage;
    119 
    120  auto fnUpdateUsage = [&](GLenum sizedFormat, webgl::EffectiveFormat effFormat,
    121                           const bool renderable) {
    122    auto usage = fua->EditUsage(effFormat);
    123    if (renderable) {
    124      usage->SetRenderable(state);
    125    }
    126    fua->AllowRBFormat(sizedFormat, usage, renderable);
    127  };
    128 
    129 #define FOO(x, y) fnUpdateUsage(LOCAL_GL_##x, webgl::EffectiveFormat::x, y)
    130 
    131  FOO(RGBA16F, true);
    132  FOO(RGB16F, false);  // It's not required, thus not portable. (Also there's a
    133                       // wicked driver bug on Mac+Intel)
    134 
    135 #undef FOO
    136 }
    137 
    138 void WebGLExtensionColorBufferHalfFloat::OnSetExplicit() {
    139  SetRenderable(webgl::FormatRenderableState::Explicit());
    140 }
    141 
    142 bool WebGLExtensionColorBufferHalfFloat::IsSupported(
    143    const WebGLContext* webgl) {
    144  if (webgl->IsWebGL2()) return false;
    145 
    146  const auto& gl = webgl->gl;
    147  return gl->IsSupported(gl::GLFeature::renderbuffer_color_half_float) &&
    148         gl->IsSupported(gl::GLFeature::frag_color_float);
    149 }
    150 
    151 // -
    152 
    153 WebGLExtensionCompressedTextureASTC::WebGLExtensionCompressedTextureASTC(
    154    WebGLContext* webgl)
    155    : WebGLExtensionBase(webgl) {
    156  MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
    157 
    158  RefPtr<WebGLContext> webgl_ = webgl;  // Bug 1201275
    159  const auto fnAdd = [&webgl_](GLenum sizedFormat,
    160                               webgl::EffectiveFormat effFormat) {
    161    auto& fua = webgl_->mFormatUsage;
    162 
    163    auto usage = fua->EditUsage(effFormat);
    164    usage->isFilterable = true;
    165    fua->AllowSizedTexFormat(sizedFormat, usage);
    166  };
    167 
    168 #define FOO(x) LOCAL_GL_##x, webgl::EffectiveFormat::x
    169 
    170  fnAdd(FOO(COMPRESSED_RGBA_ASTC_4x4_KHR));
    171  fnAdd(FOO(COMPRESSED_RGBA_ASTC_5x4_KHR));
    172  fnAdd(FOO(COMPRESSED_RGBA_ASTC_5x5_KHR));
    173  fnAdd(FOO(COMPRESSED_RGBA_ASTC_6x5_KHR));
    174  fnAdd(FOO(COMPRESSED_RGBA_ASTC_6x6_KHR));
    175  fnAdd(FOO(COMPRESSED_RGBA_ASTC_8x5_KHR));
    176  fnAdd(FOO(COMPRESSED_RGBA_ASTC_8x6_KHR));
    177  fnAdd(FOO(COMPRESSED_RGBA_ASTC_8x8_KHR));
    178  fnAdd(FOO(COMPRESSED_RGBA_ASTC_10x5_KHR));
    179  fnAdd(FOO(COMPRESSED_RGBA_ASTC_10x6_KHR));
    180  fnAdd(FOO(COMPRESSED_RGBA_ASTC_10x8_KHR));
    181  fnAdd(FOO(COMPRESSED_RGBA_ASTC_10x10_KHR));
    182  fnAdd(FOO(COMPRESSED_RGBA_ASTC_12x10_KHR));
    183  fnAdd(FOO(COMPRESSED_RGBA_ASTC_12x12_KHR));
    184 
    185  fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR));
    186  fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR));
    187  fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR));
    188  fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR));
    189  fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR));
    190  fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR));
    191  fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR));
    192  fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR));
    193  fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR));
    194  fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR));
    195  fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR));
    196  fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR));
    197  fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR));
    198  fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR));
    199 
    200 #undef FOO
    201 }
    202 
    203 bool WebGLExtensionCompressedTextureASTC::IsSupported(
    204    const WebGLContext* webgl) {
    205  gl::GLContext* gl = webgl->GL();
    206  return gl->IsExtensionSupported(
    207      gl::GLContext::KHR_texture_compression_astc_ldr);
    208 }
    209 
    210 // -
    211 
    212 WebGLExtensionCompressedTextureBPTC::WebGLExtensionCompressedTextureBPTC(
    213    WebGLContext* const webgl)
    214    : WebGLExtensionBase(webgl) {
    215  MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
    216 
    217  auto& fua = webgl->mFormatUsage;
    218 
    219  const auto fnAdd = [&](const GLenum sizedFormat,
    220                         const webgl::EffectiveFormat effFormat) {
    221    auto usage = fua->EditUsage(effFormat);
    222    usage->isFilterable = true;
    223    fua->AllowSizedTexFormat(sizedFormat, usage);
    224  };
    225 
    226 #define _(X) LOCAL_GL_##X, webgl::EffectiveFormat::X
    227 
    228  fnAdd(_(COMPRESSED_RGBA_BPTC_UNORM));
    229  fnAdd(_(COMPRESSED_SRGB_ALPHA_BPTC_UNORM));
    230  fnAdd(_(COMPRESSED_RGB_BPTC_SIGNED_FLOAT));
    231  fnAdd(_(COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT));
    232 
    233 #undef _
    234 }
    235 
    236 bool WebGLExtensionCompressedTextureBPTC::IsSupported(
    237    const WebGLContext* const webgl) {
    238  return webgl->gl->IsSupported(gl::GLFeature::texture_compression_bptc);
    239 }
    240 
    241 // -
    242 
    243 WebGLExtensionCompressedTextureES3::WebGLExtensionCompressedTextureES3(
    244    WebGLContext* webgl)
    245    : WebGLExtensionBase(webgl) {
    246  // GLES 3.0.4, p147, table 3.19
    247  // GLES 3.0.4, p286+, $C.1 "ETC Compressed Texture Image Formats"
    248  // Note that all compressed texture formats are filterable:
    249  // GLES 3.0.4 p161:
    250  // "[A] texture is complete unless any of the following conditions hold true:
    251  //  [...]
    252  //  * The effective internal format specified for the texture arrays is a
    253  //    sized internal color format that is not texture-filterable (see table
    254  //    3.13) and [the mag filter requires filtering]."
    255  // Compressed formats are not sized internal color formats, and indeed they
    256  // are not listed in table 3.13.
    257 
    258  RefPtr<WebGLContext> webgl_ = webgl;  // Bug 1201275
    259  const auto fnAdd = [&webgl_](GLenum sizedFormat,
    260                               webgl::EffectiveFormat effFormat) {
    261    auto& fua = webgl_->mFormatUsage;
    262 
    263    auto usage = fua->EditUsage(effFormat);
    264    usage->isFilterable = true;
    265    fua->AllowSizedTexFormat(sizedFormat, usage);
    266  };
    267 
    268 #define FOO(x) LOCAL_GL_##x, webgl::EffectiveFormat::x
    269 
    270  fnAdd(FOO(COMPRESSED_R11_EAC));
    271  fnAdd(FOO(COMPRESSED_SIGNED_R11_EAC));
    272  fnAdd(FOO(COMPRESSED_RG11_EAC));
    273  fnAdd(FOO(COMPRESSED_SIGNED_RG11_EAC));
    274  fnAdd(FOO(COMPRESSED_RGB8_ETC2));
    275  fnAdd(FOO(COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2));
    276  fnAdd(FOO(COMPRESSED_RGBA8_ETC2_EAC));
    277 
    278  // sRGB support is manadatory in GL 4.3 and GL ES 3.0, which are the only
    279  // versions to support ETC2.
    280  fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ETC2_EAC));
    281  fnAdd(FOO(COMPRESSED_SRGB8_ETC2));
    282  fnAdd(FOO(COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2));
    283 
    284 #undef FOO
    285 }
    286 
    287 // -
    288 
    289 WebGLExtensionCompressedTextureETC1::WebGLExtensionCompressedTextureETC1(
    290    WebGLContext* webgl)
    291    : WebGLExtensionBase(webgl) {
    292  RefPtr<WebGLContext> webgl_ = webgl;  // Bug 1201275
    293  const auto fnAdd = [&webgl_](GLenum sizedFormat,
    294                               webgl::EffectiveFormat effFormat) {
    295    auto& fua = webgl_->mFormatUsage;
    296 
    297    auto usage = fua->EditUsage(effFormat);
    298    usage->isFilterable = true;
    299    fua->AllowSizedTexFormat(sizedFormat, usage);
    300  };
    301 
    302 #define FOO(x) LOCAL_GL_##x, webgl::EffectiveFormat::x
    303 
    304  fnAdd(FOO(ETC1_RGB8_OES));
    305 
    306 #undef FOO
    307 }
    308 
    309 // -
    310 
    311 WebGLExtensionCompressedTexturePVRTC::WebGLExtensionCompressedTexturePVRTC(
    312    WebGLContext* webgl)
    313    : WebGLExtensionBase(webgl) {
    314  RefPtr<WebGLContext> webgl_ = webgl;  // Bug 1201275
    315  const auto fnAdd = [&webgl_](GLenum sizedFormat,
    316                               webgl::EffectiveFormat effFormat) {
    317    auto& fua = webgl_->mFormatUsage;
    318 
    319    auto usage = fua->EditUsage(effFormat);
    320    usage->isFilterable = true;
    321    fua->AllowSizedTexFormat(sizedFormat, usage);
    322  };
    323 
    324 #define FOO(x) LOCAL_GL_##x, webgl::EffectiveFormat::x
    325 
    326  fnAdd(FOO(COMPRESSED_RGB_PVRTC_4BPPV1));
    327  fnAdd(FOO(COMPRESSED_RGB_PVRTC_2BPPV1));
    328  fnAdd(FOO(COMPRESSED_RGBA_PVRTC_4BPPV1));
    329  fnAdd(FOO(COMPRESSED_RGBA_PVRTC_2BPPV1));
    330 
    331 #undef FOO
    332 }
    333 
    334 // -
    335 
    336 WebGLExtensionCompressedTextureRGTC::WebGLExtensionCompressedTextureRGTC(
    337    WebGLContext* const webgl)
    338    : WebGLExtensionBase(webgl) {
    339  MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
    340 
    341  auto& fua = webgl->mFormatUsage;
    342 
    343  const auto fnAdd = [&](const GLenum sizedFormat,
    344                         const webgl::EffectiveFormat effFormat) {
    345    auto usage = fua->EditUsage(effFormat);
    346    usage->isFilterable = true;
    347    fua->AllowSizedTexFormat(sizedFormat, usage);
    348  };
    349 
    350 #define _(X) LOCAL_GL_##X, webgl::EffectiveFormat::X
    351 
    352  fnAdd(_(COMPRESSED_RED_RGTC1));
    353  fnAdd(_(COMPRESSED_SIGNED_RED_RGTC1));
    354  fnAdd(_(COMPRESSED_RG_RGTC2));
    355  fnAdd(_(COMPRESSED_SIGNED_RG_RGTC2));
    356 
    357 #undef _
    358 }
    359 
    360 bool WebGLExtensionCompressedTextureRGTC::IsSupported(
    361    const WebGLContext* const webgl) {
    362  return webgl->gl->IsSupported(gl::GLFeature::texture_compression_rgtc);
    363 }
    364 
    365 // -
    366 
    367 WebGLExtensionCompressedTextureS3TC::WebGLExtensionCompressedTextureS3TC(
    368    WebGLContext* webgl)
    369    : WebGLExtensionBase(webgl) {
    370  RefPtr<WebGLContext> webgl_ = webgl;  // Bug 1201275
    371  const auto fnAdd = [&webgl_](GLenum sizedFormat,
    372                               webgl::EffectiveFormat effFormat) {
    373    auto& fua = webgl_->mFormatUsage;
    374 
    375    auto usage = fua->EditUsage(effFormat);
    376    usage->isFilterable = true;
    377    fua->AllowSizedTexFormat(sizedFormat, usage);
    378  };
    379 
    380 #define FOO(x) LOCAL_GL_##x, webgl::EffectiveFormat::x
    381 
    382  fnAdd(FOO(COMPRESSED_RGB_S3TC_DXT1_EXT));
    383  fnAdd(FOO(COMPRESSED_RGBA_S3TC_DXT1_EXT));
    384  fnAdd(FOO(COMPRESSED_RGBA_S3TC_DXT3_EXT));
    385  fnAdd(FOO(COMPRESSED_RGBA_S3TC_DXT5_EXT));
    386 
    387 #undef FOO
    388 }
    389 
    390 bool WebGLExtensionCompressedTextureS3TC::IsSupported(
    391    const WebGLContext* webgl) {
    392  gl::GLContext* gl = webgl->GL();
    393  if (gl->IsExtensionSupported(gl::GLContext::EXT_texture_compression_s3tc))
    394    return true;
    395 
    396  return gl->IsExtensionSupported(
    397             gl::GLContext::EXT_texture_compression_dxt1) &&
    398         gl->IsExtensionSupported(
    399             gl::GLContext::ANGLE_texture_compression_dxt3) &&
    400         gl->IsExtensionSupported(
    401             gl::GLContext::ANGLE_texture_compression_dxt5);
    402 }
    403 
    404 // -
    405 
    406 WebGLExtensionCompressedTextureS3TC_SRGB::
    407    WebGLExtensionCompressedTextureS3TC_SRGB(WebGLContext* webgl)
    408    : WebGLExtensionBase(webgl) {
    409  RefPtr<WebGLContext> webgl_ = webgl;  // Bug 1201275
    410  const auto fnAdd = [&webgl_](GLenum sizedFormat,
    411                               webgl::EffectiveFormat effFormat) {
    412    auto& fua = webgl_->mFormatUsage;
    413 
    414    auto usage = fua->EditUsage(effFormat);
    415    usage->isFilterable = true;
    416    fua->AllowSizedTexFormat(sizedFormat, usage);
    417  };
    418 
    419 #define FOO(x) LOCAL_GL_##x, webgl::EffectiveFormat::x
    420 
    421  fnAdd(FOO(COMPRESSED_SRGB_S3TC_DXT1_EXT));
    422  fnAdd(FOO(COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT));
    423  fnAdd(FOO(COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT));
    424  fnAdd(FOO(COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT));
    425 
    426 #undef FOO
    427 }
    428 
    429 bool WebGLExtensionCompressedTextureS3TC_SRGB::IsSupported(
    430    const WebGLContext* webgl) {
    431  gl::GLContext* gl = webgl->GL();
    432  if (gl->IsGLES())
    433    return gl->IsExtensionSupported(
    434        gl::GLContext::EXT_texture_compression_s3tc_srgb);
    435 
    436  // Desktop GL is more complicated: It's EXT_texture_sRGB, when
    437  // EXT_texture_compression_s3tc is supported, that enables srgb+s3tc.
    438  return gl->IsExtensionSupported(gl::GLContext::EXT_texture_sRGB) &&
    439         gl->IsExtensionSupported(gl::GLContext::EXT_texture_compression_s3tc);
    440 }
    441 
    442 // -
    443 
    444 WebGLExtensionDepthClamp::WebGLExtensionDepthClamp(WebGLContext* const webgl)
    445    : WebGLExtensionBase(webgl) {
    446  webgl->mIsEnabledMapKeys.insert(LOCAL_GL_DEPTH_CLAMP);
    447 }
    448 
    449 // -
    450 
    451 WebGLExtensionDepthTexture::WebGLExtensionDepthTexture(
    452    WebGLContext* const webgl)
    453    : WebGLExtensionBase(webgl) {
    454  auto& fua = webgl->mFormatUsage;
    455 
    456  const auto fnAdd = [&fua](webgl::EffectiveFormat effFormat,
    457                            GLenum unpackFormat, GLenum unpackType) {
    458    auto usage = fua->EditUsage(effFormat);
    459    MOZ_ASSERT(usage->isFilterable);
    460    MOZ_ASSERT(usage->IsRenderable());
    461 
    462    const webgl::PackingInfo pi = {unpackFormat, unpackType};
    463    const webgl::DriverUnpackInfo dui = {unpackFormat, unpackFormat,
    464                                         unpackType};
    465    fua->AddTexUnpack(usage, pi, dui);
    466    fua->AllowUnsizedTexFormat(pi, usage);
    467  };
    468 
    469  fnAdd(webgl::EffectiveFormat::DEPTH_COMPONENT16, LOCAL_GL_DEPTH_COMPONENT,
    470        LOCAL_GL_UNSIGNED_SHORT);
    471  fnAdd(webgl::EffectiveFormat::DEPTH_COMPONENT24, LOCAL_GL_DEPTH_COMPONENT,
    472        LOCAL_GL_UNSIGNED_INT);
    473  fnAdd(webgl::EffectiveFormat::DEPTH24_STENCIL8, LOCAL_GL_DEPTH_STENCIL,
    474        LOCAL_GL_UNSIGNED_INT_24_8);
    475 }
    476 
    477 bool WebGLExtensionDepthTexture::IsSupported(const WebGLContext* const webgl) {
    478  if (webgl->IsWebGL2()) return false;
    479 
    480  // WEBGL_depth_texture supports DEPTH_STENCIL textures
    481  const auto& gl = webgl->gl;
    482  if (!gl->IsSupported(gl::GLFeature::packed_depth_stencil)) return false;
    483 
    484  return gl->IsSupported(gl::GLFeature::depth_texture) ||
    485         gl->IsExtensionSupported(gl::GLContext::ANGLE_depth_texture);
    486 }
    487 
    488 // -
    489 
    490 WebGLExtensionDisjointTimerQuery::WebGLExtensionDisjointTimerQuery(
    491    WebGLContext* webgl)
    492    : WebGLExtensionBase(webgl) {
    493  MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
    494 }
    495 
    496 bool WebGLExtensionDisjointTimerQuery::IsSupported(
    497    const WebGLContext* const webgl) {
    498  if (!StaticPrefs::webgl_enable_privileged_extensions()) return false;
    499 
    500  gl::GLContext* gl = webgl->GL();
    501  return gl->IsSupported(gl::GLFeature::query_objects) &&
    502         gl->IsSupported(gl::GLFeature::get_query_object_i64v) &&
    503         gl->IsSupported(
    504             gl::GLFeature::query_counter);  // provides GL_TIMESTAMP
    505 }
    506 
    507 // -
    508 
    509 WebGLExtensionDrawBuffers::WebGLExtensionDrawBuffers(WebGLContext* webgl)
    510    : WebGLExtensionBase(webgl) {
    511  MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
    512 }
    513 
    514 bool WebGLExtensionDrawBuffers::IsSupported(const WebGLContext* webgl) {
    515  if (!webgl->mIsSupportedCache_DrawBuffers) {
    516    webgl->mIsSupportedCache_DrawBuffers = [&]() {
    517      gl::GLContext* const gl = webgl->GL();
    518 
    519      if (webgl->IsWebGL2()) return false;
    520      if (!gl->IsSupported(gl::GLFeature::draw_buffers)) return false;
    521 
    522      if (gl->IsGLES() && gl->Version() >= 300) {
    523        // ANGLE's shader translator can't translate ESSL1 exts to ESSL3. (bug
    524        // 1524804)
    525        // The spec (and some implementations of ES3) don't require support for
    526        // any extensions in ESSL 100, but an implementation can choose to
    527        // support them anyway. So let's check!
    528        const bool ok = TestShaderCompile(gl, LOCAL_GL_FRAGMENT_SHADER, R"(
    529 #extension GL_EXT_draw_buffers: require
    530 void main() {}
    531 )");
    532        if (!ok) return false;
    533      }
    534 
    535      return true;
    536    }();
    537  }
    538 
    539  return *webgl->mIsSupportedCache_DrawBuffers;
    540 }
    541 
    542 // -
    543 
    544 WebGLExtensionExplicitPresent::WebGLExtensionExplicitPresent(
    545    WebGLContext* const webgl)
    546    : WebGLExtensionBase(webgl) {
    547  if (!IsSupported(webgl)) {
    548    NS_WARNING(
    549        "Constructing WebGLExtensionExplicitPresent but IsSupported() is "
    550        "false!");
    551    // This was previously an assert, but it seems like we get races against
    552    // StaticPrefs changes/initialization?
    553  }
    554 }
    555 
    556 bool WebGLExtensionExplicitPresent::IsSupported(
    557    const WebGLContext* const webgl) {
    558  return StaticPrefs::webgl_enable_draft_extensions();
    559 }
    560 
    561 // -
    562 
    563 WebGLExtensionEXTColorBufferFloat::WebGLExtensionEXTColorBufferFloat(
    564    WebGLContext* webgl)
    565    : WebGLExtensionBase(webgl) {
    566  MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
    567 
    568  auto& fua = webgl->mFormatUsage;
    569 
    570  auto fnUpdateUsage = [&fua](GLenum sizedFormat,
    571                              webgl::EffectiveFormat effFormat) {
    572    auto usage = fua->EditUsage(effFormat);
    573    usage->SetRenderable();
    574    fua->AllowRBFormat(sizedFormat, usage);
    575  };
    576 
    577 #define FOO(x) fnUpdateUsage(LOCAL_GL_##x, webgl::EffectiveFormat::x)
    578 
    579  FOO(R16F);
    580  FOO(RG16F);
    581  FOO(RGBA16F);
    582 
    583  FOO(R32F);
    584  FOO(RG32F);
    585  FOO(RGBA32F);
    586 
    587  FOO(R11F_G11F_B10F);
    588 
    589 #undef FOO
    590 }
    591 
    592 /*static*/
    593 bool WebGLExtensionEXTColorBufferFloat::IsSupported(const WebGLContext* webgl) {
    594  if (!webgl->IsWebGL2()) return false;
    595 
    596  const gl::GLContext* gl = webgl->GL();
    597  return gl->IsSupported(gl::GLFeature::EXT_color_buffer_float);
    598 }
    599 
    600 // -
    601 
    602 WebGLExtensionFBORenderMipmap::WebGLExtensionFBORenderMipmap(
    603    WebGLContext* const webgl)
    604    : WebGLExtensionBase(webgl) {
    605  MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
    606 }
    607 
    608 bool WebGLExtensionFBORenderMipmap::IsSupported(
    609    const WebGLContext* const webgl) {
    610  if (webgl->IsWebGL2()) return false;
    611 
    612  const auto& gl = webgl->gl;
    613  if (!gl->IsGLES()) return true;
    614  if (gl->Version() >= 300) return true;
    615  return gl->IsExtensionSupported(gl::GLContext::OES_fbo_render_mipmap);
    616 }
    617 
    618 // -
    619 
    620 WebGLExtensionFloatBlend::WebGLExtensionFloatBlend(WebGLContext* const webgl)
    621    : WebGLExtensionBase(webgl) {
    622  MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
    623 }
    624 
    625 bool WebGLExtensionFloatBlend::IsSupported(const WebGLContext* const webgl) {
    626  if (!WebGLExtensionColorBufferFloat::IsSupported(webgl) &&
    627      !WebGLExtensionEXTColorBufferFloat::IsSupported(webgl))
    628    return false;
    629 
    630  const auto& gl = webgl->gl;
    631  if (!gl->IsGLES() && gl->Version() >= 300) return true;
    632  if (gl->IsGLES() && gl->Version() >= 320) return true;
    633  return gl->IsExtensionSupported(gl::GLContext::EXT_float_blend);
    634 }
    635 
    636 // -
    637 
    638 WebGLExtensionFragDepth::WebGLExtensionFragDepth(WebGLContext* webgl)
    639    : WebGLExtensionBase(webgl) {
    640  MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
    641 }
    642 
    643 bool WebGLExtensionFragDepth::IsSupported(const WebGLContext* const webgl) {
    644  if (!webgl->mIsSupportedCache_FragDepth) {
    645    webgl->mIsSupportedCache_FragDepth = [&]() {
    646      gl::GLContext* const gl = webgl->GL();
    647 
    648      if (webgl->IsWebGL2()) return false;
    649      if (!gl->IsSupported(gl::GLFeature::frag_depth)) return false;
    650 
    651      if (gl->IsGLES() && gl->Version() >= 300) {
    652        // ANGLE's shader translator can't translate ESSL1 exts to ESSL3. (bug
    653        // 1524804)
    654        // The spec (and some implementations of ES3) don't require support for
    655        // any extensions in ESSL 100, but an implementation can choose to
    656        // support them anyway. So let's check!
    657        const bool ok = TestShaderCompile(gl, LOCAL_GL_FRAGMENT_SHADER, R"(
    658 #extension GL_EXT_frag_depth: require
    659 void main() {}
    660 )");
    661        if (!ok) return false;
    662      }
    663 
    664      return true;
    665    }();
    666  }
    667 
    668  return *webgl->mIsSupportedCache_FragDepth;
    669 }
    670 
    671 // -
    672 
    673 WebGLExtensionInstancedArrays::WebGLExtensionInstancedArrays(
    674    WebGLContext* webgl)
    675    : WebGLExtensionBase(webgl) {
    676  MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
    677 }
    678 
    679 bool WebGLExtensionInstancedArrays::IsSupported(const WebGLContext* webgl) {
    680  if (webgl->IsWebGL2()) return false;
    681 
    682  gl::GLContext* gl = webgl->GL();
    683  return gl->IsSupported(gl::GLFeature::draw_instanced) &&
    684         gl->IsSupported(gl::GLFeature::instanced_arrays);
    685 }
    686 
    687 // -
    688 
    689 WebGLExtensionMultiview::WebGLExtensionMultiview(WebGLContext* const webgl)
    690    : WebGLExtensionBase(webgl) {
    691  MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
    692 }
    693 
    694 bool WebGLExtensionMultiview::IsSupported(const WebGLContext* const webgl) {
    695  if (!webgl->IsWebGL2()) return false;
    696 
    697  const auto& gl = webgl->gl;
    698  return gl->IsSupported(gl::GLFeature::multiview);
    699 }
    700 
    701 // -
    702 
    703 WebGLExtensionShaderTextureLod::WebGLExtensionShaderTextureLod(
    704    WebGLContext* webgl)
    705    : WebGLExtensionBase(webgl) {
    706  MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
    707 }
    708 
    709 bool WebGLExtensionShaderTextureLod::IsSupported(const WebGLContext* webgl) {
    710  if (!webgl->mIsSupportedCache_ShaderTextureLod) {
    711    webgl->mIsSupportedCache_ShaderTextureLod = [&]() {
    712      gl::GLContext* const gl = webgl->GL();
    713 
    714      if (webgl->IsWebGL2()) return false;
    715      if (!gl->IsSupported(gl::GLFeature::shader_texture_lod)) return false;
    716 
    717      if (gl->IsGLES() && gl->Version() >= 300) {
    718        // ANGLE's shader translator doesn't yet translate
    719        // WebGL1+EXT_shader_texture_lod to ES3. (Bug 1491221)
    720        // The spec (and some implementations of ES3) don't require support for
    721        // any extensions in ESSL 100, but an implementation can choose to
    722        // support them anyway. So let's check!
    723        const bool ok = TestShaderCompile(gl, LOCAL_GL_FRAGMENT_SHADER, R"(
    724 #extension GL_EXT_shader_texture_lod: require
    725 void main() {}
    726 )");
    727        if (!ok) return false;
    728      }
    729 
    730      return true;
    731    }();
    732  }
    733  return *webgl->mIsSupportedCache_ShaderTextureLod;
    734 }
    735 
    736 // -
    737 
    738 WebGLExtensionSRGB::WebGLExtensionSRGB(WebGLContext* webgl)
    739    : WebGLExtensionBase(webgl) {
    740  MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
    741 
    742  gl::GLContext* gl = webgl->GL();
    743  if (!gl->IsGLES()) {
    744    // Desktop OpenGL requires the following to be enabled in order to
    745    // support sRGB operations on framebuffers.
    746    gl->fEnable(LOCAL_GL_FRAMEBUFFER_SRGB_EXT);
    747  }
    748 
    749  auto& fua = webgl->mFormatUsage;
    750 
    751  RefPtr<gl::GLContext> gl_ = gl;  // Bug 1201275
    752  const auto fnAdd = [&fua, &gl_](webgl::EffectiveFormat effFormat,
    753                                  GLenum format, GLenum desktopUnpackFormat) {
    754    auto usage = fua->EditUsage(effFormat);
    755    usage->isFilterable = true;
    756 
    757    webgl::DriverUnpackInfo dui = {format, format, LOCAL_GL_UNSIGNED_BYTE};
    758    const auto pi = dui.ToPacking();
    759 
    760    if (!gl_->IsGLES()) dui.unpackFormat = desktopUnpackFormat;
    761 
    762    fua->AddTexUnpack(usage, pi, dui);
    763 
    764    fua->AllowUnsizedTexFormat(pi, usage);
    765  };
    766 
    767  fnAdd(webgl::EffectiveFormat::SRGB8, LOCAL_GL_SRGB, LOCAL_GL_RGB);
    768  fnAdd(webgl::EffectiveFormat::SRGB8_ALPHA8, LOCAL_GL_SRGB_ALPHA,
    769        LOCAL_GL_RGBA);
    770 
    771  auto usage = fua->EditUsage(webgl::EffectiveFormat::SRGB8_ALPHA8);
    772  usage->SetRenderable();
    773  fua->AllowRBFormat(LOCAL_GL_SRGB8_ALPHA8, usage);
    774 }
    775 
    776 bool WebGLExtensionSRGB::IsSupported(const WebGLContext* const webgl) {
    777  if (webgl->IsWebGL2()) return false;
    778 
    779  return webgl->gl->IsSupported(gl::GLFeature::sRGB);
    780 }
    781 
    782 // -
    783 
    784 WebGLExtensionTextureFloat::WebGLExtensionTextureFloat(WebGLContext* webgl)
    785    : WebGLExtensionBase(webgl) {
    786  MOZ_ASSERT(IsSupported(webgl));
    787 
    788  auto& fua = webgl->mFormatUsage;
    789  gl::GLContext* gl = webgl->GL();
    790 
    791  webgl::PackingInfo pi;
    792  webgl::DriverUnpackInfo dui;
    793  const GLint* swizzle = nullptr;
    794 
    795  const auto fnAdd = [&](webgl::EffectiveFormat effFormat) {
    796    MOZ_ASSERT_IF(swizzle, gl->IsSupported(gl::GLFeature::texture_swizzle));
    797 
    798    auto usage = fua->EditUsage(effFormat);
    799    usage->textureSwizzleRGBA = swizzle;
    800    fua->AddTexUnpack(usage, pi, dui);
    801 
    802    fua->AllowUnsizedTexFormat(pi, usage);
    803  };
    804 
    805  bool useSizedFormats = true;
    806  const bool hasSizedLegacyFormats = gl->IsCompatibilityProfile();
    807  if (gl->IsGLES() && gl->Version() < 300) {
    808    useSizedFormats = false;
    809  }
    810 
    811  ////////////////
    812 
    813  pi = {LOCAL_GL_RGBA, LOCAL_GL_FLOAT};
    814  dui = {pi.format, pi.format, pi.type};
    815  swizzle = nullptr;
    816  if (useSizedFormats || gl->IsExtensionSupported(
    817                             gl::GLContext::CHROMIUM_color_buffer_float_rgba)) {
    818    // ANGLE only exposes renderable RGBA32F via
    819    // CHROMIUM_color_buffer_float_rgba, which uses sized formats.
    820    dui.internalFormat = LOCAL_GL_RGBA32F;
    821  }
    822  fnAdd(webgl::EffectiveFormat::RGBA32F);
    823 
    824  //////
    825 
    826  pi = {LOCAL_GL_RGB, LOCAL_GL_FLOAT};
    827  dui = {pi.format, pi.format, pi.type};
    828  swizzle = nullptr;
    829  if (useSizedFormats) {
    830    dui.internalFormat = LOCAL_GL_RGB32F;
    831  }
    832  fnAdd(webgl::EffectiveFormat::RGB32F);
    833 
    834  //////
    835 
    836  pi = {LOCAL_GL_LUMINANCE, LOCAL_GL_FLOAT};
    837  dui = {pi.format, pi.format, pi.type};
    838  swizzle = nullptr;
    839  if (useSizedFormats) {
    840    if (hasSizedLegacyFormats) {
    841      dui.internalFormat = LOCAL_GL_LUMINANCE32F_ARB;
    842    } else {
    843      dui.internalFormat = LOCAL_GL_R32F;
    844      dui.unpackFormat = LOCAL_GL_RED;
    845      swizzle = webgl::FormatUsageInfo::kLuminanceSwizzleRGBA;
    846    }
    847  }
    848  fnAdd(webgl::EffectiveFormat::Luminance32F);
    849 
    850  //////
    851 
    852  pi = {LOCAL_GL_ALPHA, LOCAL_GL_FLOAT};
    853  dui = {pi.format, pi.format, pi.type};
    854  swizzle = nullptr;
    855  if (useSizedFormats) {
    856    if (hasSizedLegacyFormats) {
    857      dui.internalFormat = LOCAL_GL_ALPHA32F_ARB;
    858    } else {
    859      dui.internalFormat = LOCAL_GL_R32F;
    860      dui.unpackFormat = LOCAL_GL_RED;
    861      swizzle = webgl::FormatUsageInfo::kAlphaSwizzleRGBA;
    862    }
    863  }
    864  fnAdd(webgl::EffectiveFormat::Alpha32F);
    865 
    866  //////
    867 
    868  pi = {LOCAL_GL_LUMINANCE_ALPHA, LOCAL_GL_FLOAT};
    869  dui = {pi.format, pi.format, pi.type};
    870  swizzle = nullptr;
    871  if (useSizedFormats) {
    872    if (hasSizedLegacyFormats) {
    873      dui.internalFormat = LOCAL_GL_LUMINANCE_ALPHA32F_ARB;
    874    } else {
    875      dui.internalFormat = LOCAL_GL_RG32F;
    876      dui.unpackFormat = LOCAL_GL_RG;
    877      swizzle = webgl::FormatUsageInfo::kLumAlphaSwizzleRGBA;
    878    }
    879  }
    880  fnAdd(webgl::EffectiveFormat::Luminance32FAlpha32F);
    881 }
    882 
    883 bool WebGLExtensionTextureFloat::IsSupported(const WebGLContext* webgl) {
    884  if (webgl->IsWebGL2()) return false;
    885 
    886  gl::GLContext* gl = webgl->GL();
    887  if (!gl->IsSupported(gl::GLFeature::texture_float)) return false;
    888 
    889  const bool needsSwizzle = gl->IsCoreProfile();
    890  const bool hasSwizzle = gl->IsSupported(gl::GLFeature::texture_swizzle);
    891  if (needsSwizzle && !hasSwizzle) return false;
    892 
    893  return true;
    894 }
    895 
    896 // -
    897 
    898 WebGLExtensionTextureFloatLinear::WebGLExtensionTextureFloatLinear(
    899    WebGLContext* webgl)
    900    : WebGLExtensionBase(webgl) {
    901  auto& fua = webgl->mFormatUsage;
    902 
    903  fua->EditUsage(webgl::EffectiveFormat::RGBA32F)->isFilterable = true;
    904  fua->EditUsage(webgl::EffectiveFormat::RGB32F)->isFilterable = true;
    905 
    906  if (webgl->IsWebGL2()) {
    907    fua->EditUsage(webgl::EffectiveFormat::R32F)->isFilterable = true;
    908    fua->EditUsage(webgl::EffectiveFormat::RG32F)->isFilterable = true;
    909  } else {
    910    fua->EditUsage(webgl::EffectiveFormat::Luminance32FAlpha32F)->isFilterable =
    911        true;
    912    fua->EditUsage(webgl::EffectiveFormat::Luminance32F)->isFilterable = true;
    913    fua->EditUsage(webgl::EffectiveFormat::Alpha32F)->isFilterable = true;
    914  }
    915 }
    916 
    917 // -
    918 
    919 WebGLExtensionTextureHalfFloat::WebGLExtensionTextureHalfFloat(
    920    WebGLContext* webgl)
    921    : WebGLExtensionBase(webgl) {
    922  auto& fua = webgl->mFormatUsage;
    923  gl::GLContext* gl = webgl->GL();
    924 
    925  webgl::PackingInfo pi;
    926  webgl::DriverUnpackInfo dui;
    927  const GLint* swizzle = nullptr;
    928 
    929  const auto fnAdd = [&](webgl::EffectiveFormat effFormat) {
    930    MOZ_ASSERT_IF(swizzle, gl->IsSupported(gl::GLFeature::texture_swizzle));
    931 
    932    auto usage = fua->EditUsage(effFormat);
    933    usage->textureSwizzleRGBA = swizzle;
    934    fua->AddTexUnpack(usage, pi, dui);
    935 
    936    fua->AllowUnsizedTexFormat(pi, usage);
    937  };
    938 
    939  bool useSizedFormats = true;
    940  const bool hasSizedLegacyFormats = gl->IsCompatibilityProfile();
    941  if (gl->IsGLES() && gl->Version() < 300) {
    942    useSizedFormats = false;
    943  }
    944 
    945  GLenum driverUnpackType = LOCAL_GL_HALF_FLOAT;
    946  if (!gl->IsSupported(gl::GLFeature::texture_half_float)) {
    947    MOZ_ASSERT(gl->IsExtensionSupported(gl::GLContext::OES_texture_half_float));
    948    driverUnpackType = LOCAL_GL_HALF_FLOAT_OES;
    949  }
    950 
    951  ////////////////
    952 
    953  pi = {LOCAL_GL_RGBA, LOCAL_GL_HALF_FLOAT_OES};
    954  dui = {pi.format, pi.format, driverUnpackType};
    955  swizzle = nullptr;
    956  if (useSizedFormats) {
    957    dui.internalFormat = LOCAL_GL_RGBA16F;
    958  }
    959  fnAdd(webgl::EffectiveFormat::RGBA16F);
    960 
    961  //////
    962 
    963  pi = {LOCAL_GL_RGB, LOCAL_GL_HALF_FLOAT_OES};
    964  dui = {pi.format, pi.format, driverUnpackType};
    965  swizzle = nullptr;
    966  if (useSizedFormats) {
    967    dui.internalFormat = LOCAL_GL_RGB16F;
    968  }
    969  fnAdd(webgl::EffectiveFormat::RGB16F);
    970 
    971  //////
    972 
    973  pi = {LOCAL_GL_LUMINANCE, LOCAL_GL_HALF_FLOAT_OES};
    974  dui = {pi.format, pi.format, driverUnpackType};
    975  swizzle = nullptr;
    976  if (useSizedFormats) {
    977    if (hasSizedLegacyFormats) {
    978      dui.internalFormat = LOCAL_GL_LUMINANCE16F_ARB;
    979    } else {
    980      dui.internalFormat = LOCAL_GL_R16F;
    981      dui.unpackFormat = LOCAL_GL_RED;
    982      swizzle = webgl::FormatUsageInfo::kLuminanceSwizzleRGBA;
    983    }
    984  }
    985  fnAdd(webgl::EffectiveFormat::Luminance16F);
    986 
    987  //////
    988 
    989  pi = {LOCAL_GL_ALPHA, LOCAL_GL_HALF_FLOAT_OES};
    990  dui = {pi.format, pi.format, driverUnpackType};
    991  swizzle = nullptr;
    992  if (useSizedFormats) {
    993    if (hasSizedLegacyFormats) {
    994      dui.internalFormat = LOCAL_GL_ALPHA16F_ARB;
    995    } else {
    996      dui.internalFormat = LOCAL_GL_R16F;
    997      dui.unpackFormat = LOCAL_GL_RED;
    998      swizzle = webgl::FormatUsageInfo::kAlphaSwizzleRGBA;
    999    }
   1000  }
   1001  fnAdd(webgl::EffectiveFormat::Alpha16F);
   1002 
   1003  //////
   1004 
   1005  pi = {LOCAL_GL_LUMINANCE_ALPHA, LOCAL_GL_HALF_FLOAT_OES};
   1006  dui = {pi.format, pi.format, driverUnpackType};
   1007  swizzle = nullptr;
   1008  if (useSizedFormats) {
   1009    if (hasSizedLegacyFormats) {
   1010      dui.internalFormat = LOCAL_GL_LUMINANCE_ALPHA16F_ARB;
   1011    } else {
   1012      dui.internalFormat = LOCAL_GL_RG16F;
   1013      dui.unpackFormat = LOCAL_GL_RG;
   1014      swizzle = webgl::FormatUsageInfo::kLumAlphaSwizzleRGBA;
   1015    }
   1016  }
   1017  fnAdd(webgl::EffectiveFormat::Luminance16FAlpha16F);
   1018 }
   1019 
   1020 bool WebGLExtensionTextureHalfFloat::IsSupported(const WebGLContext* webgl) {
   1021  if (webgl->IsWebGL2()) return false;
   1022 
   1023  gl::GLContext* gl = webgl->GL();
   1024  if (!gl->IsSupported(gl::GLFeature::texture_half_float) &&
   1025      !gl->IsExtensionSupported(gl::GLContext::OES_texture_half_float)) {
   1026    return false;
   1027  }
   1028 
   1029  const bool needsSwizzle = gl->IsCoreProfile();
   1030  const bool hasSwizzle = gl->IsSupported(gl::GLFeature::texture_swizzle);
   1031  if (needsSwizzle && !hasSwizzle) return false;
   1032 
   1033  return true;
   1034 }
   1035 
   1036 // -
   1037 
   1038 WebGLExtensionTextureHalfFloatLinear::WebGLExtensionTextureHalfFloatLinear(
   1039    WebGLContext* webgl)
   1040    : WebGLExtensionBase(webgl) {
   1041  MOZ_ASSERT(!webgl->IsWebGL2());
   1042  auto& fua = webgl->mFormatUsage;
   1043 
   1044  fua->EditUsage(webgl::EffectiveFormat::RGBA16F)->isFilterable = true;
   1045  fua->EditUsage(webgl::EffectiveFormat::RGB16F)->isFilterable = true;
   1046  fua->EditUsage(webgl::EffectiveFormat::Luminance16FAlpha16F)->isFilterable =
   1047      true;
   1048  fua->EditUsage(webgl::EffectiveFormat::Luminance16F)->isFilterable = true;
   1049  fua->EditUsage(webgl::EffectiveFormat::Alpha16F)->isFilterable = true;
   1050 }
   1051 
   1052 // -
   1053 
   1054 bool WebGLExtensionTextureNorm16::IsSupported(const WebGLContext* const webgl) {
   1055  if (!StaticPrefs::webgl_enable_draft_extensions()) return false;
   1056  if (!webgl->IsWebGL2()) return false;
   1057 
   1058  const auto& gl = webgl->gl;
   1059 
   1060  // ANGLE's support is broken in our checkout.
   1061  if (gl->IsANGLE()) return false;
   1062 
   1063  return gl->IsSupported(gl::GLFeature::texture_norm16);
   1064 }
   1065 
   1066 WebGLExtensionTextureNorm16::WebGLExtensionTextureNorm16(WebGLContext* webgl)
   1067    : WebGLExtensionBase(webgl) {
   1068  if (!IsSupported(webgl)) {
   1069    NS_WARNING(
   1070        "Constructing WebGLExtensionTextureNorm16 but IsSupported() is "
   1071        "false!");
   1072    // This was previously an assert, but it seems like we get races against
   1073    // StaticPrefs changes/initialization?
   1074  }
   1075 
   1076  auto& fua = *webgl->mFormatUsage;
   1077 
   1078  const auto fnAdd = [&](webgl::EffectiveFormat effFormat,
   1079                         const bool renderable, const webgl::PackingInfo& pi) {
   1080    auto& usage = *fua.EditUsage(effFormat);
   1081    const auto& format = *usage.format;
   1082 
   1083    const auto dui =
   1084        webgl::DriverUnpackInfo{format.sizedFormat, pi.format, pi.type};
   1085    fua.AddTexUnpack(&usage, pi, dui);
   1086 
   1087    fua.AllowSizedTexFormat(format.sizedFormat, &usage);
   1088    fua.AllowUnsizedTexFormat(pi, &usage);
   1089 
   1090    if (renderable) {
   1091      usage.SetRenderable();
   1092      fua.AllowRBFormat(format.sizedFormat, &usage);
   1093    }
   1094  };
   1095 
   1096  fnAdd(webgl::EffectiveFormat::R16, true,
   1097        {LOCAL_GL_RED, LOCAL_GL_UNSIGNED_SHORT});
   1098  fnAdd(webgl::EffectiveFormat::RG16, true,
   1099        {LOCAL_GL_RG, LOCAL_GL_UNSIGNED_SHORT});
   1100  fnAdd(webgl::EffectiveFormat::RGB16, false,
   1101        {LOCAL_GL_RGB, LOCAL_GL_UNSIGNED_SHORT});
   1102  fnAdd(webgl::EffectiveFormat::RGBA16, true,
   1103        {LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_SHORT});
   1104 
   1105  fnAdd(webgl::EffectiveFormat::R16_SNORM, false,
   1106        {LOCAL_GL_RED, LOCAL_GL_SHORT});
   1107  fnAdd(webgl::EffectiveFormat::RG16_SNORM, false,
   1108        {LOCAL_GL_RG, LOCAL_GL_SHORT});
   1109  fnAdd(webgl::EffectiveFormat::RGB16_SNORM, false,
   1110        {LOCAL_GL_RGB, LOCAL_GL_SHORT});
   1111  fnAdd(webgl::EffectiveFormat::RGBA16_SNORM, false,
   1112        {LOCAL_GL_RGBA, LOCAL_GL_SHORT});
   1113 }
   1114 
   1115 }  // namespace mozilla