Bug 1941128 - Turn off network.dns.native_https_query on Mac again
[gecko.git] / dom / canvas / WebGLExtensions.cpp
blobbe9323ca716c67603e3c723fd70347777553a35d
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/. */
6 #include "WebGLExtensions.h"
8 #include "GLContext.h"
9 #include "mozilla/Casting.h"
10 #include "mozilla/dom/WebGLRenderingContextBinding.h"
11 #include "mozilla/ScopeExit.h"
12 #include "mozilla/StaticPrefs_webgl.h"
13 #include "WebGLContext.h"
14 #include "WebGLFormats.h"
16 namespace mozilla {
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); });
23 const std::array<const char*, 1> parts = {source.c_str()};
24 gl->fShaderSource(shader, parts.size(), parts.data(), nullptr);
25 gl->fCompileShader(shader);
27 GLint status = 0;
28 gl->fGetShaderiv(shader, LOCAL_GL_COMPILE_STATUS, &status);
30 if (status == LOCAL_GL_TRUE) return true;
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());
38 gl->fGetShaderSource(shader, LazyAssertedCast(chars.size() - 1), nullptr,
39 chars.data());
40 printf_stderr("GetShaderSource() ->\n%s\n", chars.data());
42 return false;
45 // -
47 WebGLExtensionBlendMinMax::WebGLExtensionBlendMinMax(WebGLContext* webgl)
48 : WebGLExtensionBase(webgl) {
49 MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
52 bool WebGLExtensionBlendMinMax::IsSupported(const WebGLContext* webgl) {
53 if (webgl->IsWebGL2()) return false;
55 return webgl->GL()->IsSupported(gl::GLFeature::blend_minmax);
58 // -
60 WebGLExtensionColorBufferFloat::WebGLExtensionColorBufferFloat(
61 WebGLContext* webgl)
62 : WebGLExtensionBase(webgl) {
63 MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
64 SetRenderable(webgl::FormatRenderableState::Implicit(
65 WebGLExtensionID::WEBGL_color_buffer_float));
68 void WebGLExtensionColorBufferFloat::SetRenderable(
69 const webgl::FormatRenderableState& state) {
70 auto& fua = mContext->mFormatUsage;
72 auto fnUpdateUsage = [&](GLenum sizedFormat,
73 webgl::EffectiveFormat effFormat) {
74 auto usage = fua->EditUsage(effFormat);
75 usage->SetRenderable(state);
76 fua->AllowRBFormat(sizedFormat, usage);
79 #define FOO(x) fnUpdateUsage(LOCAL_GL_##x, webgl::EffectiveFormat::x)
81 // The extension doesn't actually add RGB32F; only RGBA32F.
82 FOO(RGBA32F);
84 #undef FOO
87 void WebGLExtensionColorBufferFloat::OnSetExplicit() {
88 SetRenderable(webgl::FormatRenderableState::Explicit());
91 bool WebGLExtensionColorBufferFloat::IsSupported(const WebGLContext* webgl) {
92 if (webgl->IsWebGL2()) return false;
94 const auto& gl = webgl->gl;
95 return gl->IsSupported(gl::GLFeature::renderbuffer_color_float) &&
96 gl->IsSupported(gl::GLFeature::frag_color_float);
99 // -
101 WebGLExtensionColorBufferHalfFloat::WebGLExtensionColorBufferHalfFloat(
102 WebGLContext* webgl)
103 : WebGLExtensionBase(webgl) {
104 MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
105 SetRenderable(webgl::FormatRenderableState::Implicit(
106 WebGLExtensionID::EXT_color_buffer_half_float));
109 void WebGLExtensionColorBufferHalfFloat::SetRenderable(
110 const webgl::FormatRenderableState& state) {
111 auto& fua = mContext->mFormatUsage;
113 auto fnUpdateUsage = [&](GLenum sizedFormat, webgl::EffectiveFormat effFormat,
114 const bool renderable) {
115 auto usage = fua->EditUsage(effFormat);
116 if (renderable) {
117 usage->SetRenderable(state);
119 fua->AllowRBFormat(sizedFormat, usage, renderable);
122 #define FOO(x, y) fnUpdateUsage(LOCAL_GL_##x, webgl::EffectiveFormat::x, y)
124 FOO(RGBA16F, true);
125 FOO(RGB16F, false); // It's not required, thus not portable. (Also there's a
126 // wicked driver bug on Mac+Intel)
128 #undef FOO
131 void WebGLExtensionColorBufferHalfFloat::OnSetExplicit() {
132 SetRenderable(webgl::FormatRenderableState::Explicit());
135 bool WebGLExtensionColorBufferHalfFloat::IsSupported(
136 const WebGLContext* webgl) {
137 if (webgl->IsWebGL2()) return false;
139 const auto& gl = webgl->gl;
140 return gl->IsSupported(gl::GLFeature::renderbuffer_color_half_float) &&
141 gl->IsSupported(gl::GLFeature::frag_color_float);
144 // -
146 WebGLExtensionCompressedTextureASTC::WebGLExtensionCompressedTextureASTC(
147 WebGLContext* webgl)
148 : WebGLExtensionBase(webgl) {
149 MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
151 RefPtr<WebGLContext> webgl_ = webgl; // Bug 1201275
152 const auto fnAdd = [&webgl_](GLenum sizedFormat,
153 webgl::EffectiveFormat effFormat) {
154 auto& fua = webgl_->mFormatUsage;
156 auto usage = fua->EditUsage(effFormat);
157 usage->isFilterable = true;
158 fua->AllowSizedTexFormat(sizedFormat, usage);
161 #define FOO(x) LOCAL_GL_##x, webgl::EffectiveFormat::x
163 fnAdd(FOO(COMPRESSED_RGBA_ASTC_4x4_KHR));
164 fnAdd(FOO(COMPRESSED_RGBA_ASTC_5x4_KHR));
165 fnAdd(FOO(COMPRESSED_RGBA_ASTC_5x5_KHR));
166 fnAdd(FOO(COMPRESSED_RGBA_ASTC_6x5_KHR));
167 fnAdd(FOO(COMPRESSED_RGBA_ASTC_6x6_KHR));
168 fnAdd(FOO(COMPRESSED_RGBA_ASTC_8x5_KHR));
169 fnAdd(FOO(COMPRESSED_RGBA_ASTC_8x6_KHR));
170 fnAdd(FOO(COMPRESSED_RGBA_ASTC_8x8_KHR));
171 fnAdd(FOO(COMPRESSED_RGBA_ASTC_10x5_KHR));
172 fnAdd(FOO(COMPRESSED_RGBA_ASTC_10x6_KHR));
173 fnAdd(FOO(COMPRESSED_RGBA_ASTC_10x8_KHR));
174 fnAdd(FOO(COMPRESSED_RGBA_ASTC_10x10_KHR));
175 fnAdd(FOO(COMPRESSED_RGBA_ASTC_12x10_KHR));
176 fnAdd(FOO(COMPRESSED_RGBA_ASTC_12x12_KHR));
178 fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR));
179 fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR));
180 fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR));
181 fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR));
182 fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR));
183 fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR));
184 fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR));
185 fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR));
186 fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR));
187 fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR));
188 fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR));
189 fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR));
190 fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR));
191 fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR));
193 #undef FOO
196 bool WebGLExtensionCompressedTextureASTC::IsSupported(
197 const WebGLContext* webgl) {
198 gl::GLContext* gl = webgl->GL();
199 return gl->IsExtensionSupported(
200 gl::GLContext::KHR_texture_compression_astc_ldr);
203 // -
205 WebGLExtensionCompressedTextureBPTC::WebGLExtensionCompressedTextureBPTC(
206 WebGLContext* const webgl)
207 : WebGLExtensionBase(webgl) {
208 MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
210 auto& fua = webgl->mFormatUsage;
212 const auto fnAdd = [&](const GLenum sizedFormat,
213 const webgl::EffectiveFormat effFormat) {
214 auto usage = fua->EditUsage(effFormat);
215 usage->isFilterable = true;
216 fua->AllowSizedTexFormat(sizedFormat, usage);
219 #define _(X) LOCAL_GL_##X, webgl::EffectiveFormat::X
221 fnAdd(_(COMPRESSED_RGBA_BPTC_UNORM));
222 fnAdd(_(COMPRESSED_SRGB_ALPHA_BPTC_UNORM));
223 fnAdd(_(COMPRESSED_RGB_BPTC_SIGNED_FLOAT));
224 fnAdd(_(COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT));
226 #undef _
229 bool WebGLExtensionCompressedTextureBPTC::IsSupported(
230 const WebGLContext* const webgl) {
231 return webgl->gl->IsSupported(gl::GLFeature::texture_compression_bptc);
234 // -
236 WebGLExtensionCompressedTextureES3::WebGLExtensionCompressedTextureES3(
237 WebGLContext* webgl)
238 : WebGLExtensionBase(webgl) {
239 // GLES 3.0.4, p147, table 3.19
240 // GLES 3.0.4, p286+, $C.1 "ETC Compressed Texture Image Formats"
241 // Note that all compressed texture formats are filterable:
242 // GLES 3.0.4 p161:
243 // "[A] texture is complete unless any of the following conditions hold true:
244 // [...]
245 // * The effective internal format specified for the texture arrays is a
246 // sized internal color format that is not texture-filterable (see table
247 // 3.13) and [the mag filter requires filtering]."
248 // Compressed formats are not sized internal color formats, and indeed they
249 // are not listed in table 3.13.
251 RefPtr<WebGLContext> webgl_ = webgl; // Bug 1201275
252 const auto fnAdd = [&webgl_](GLenum sizedFormat,
253 webgl::EffectiveFormat effFormat) {
254 auto& fua = webgl_->mFormatUsage;
256 auto usage = fua->EditUsage(effFormat);
257 usage->isFilterable = true;
258 fua->AllowSizedTexFormat(sizedFormat, usage);
261 #define FOO(x) LOCAL_GL_##x, webgl::EffectiveFormat::x
263 fnAdd(FOO(COMPRESSED_R11_EAC));
264 fnAdd(FOO(COMPRESSED_SIGNED_R11_EAC));
265 fnAdd(FOO(COMPRESSED_RG11_EAC));
266 fnAdd(FOO(COMPRESSED_SIGNED_RG11_EAC));
267 fnAdd(FOO(COMPRESSED_RGB8_ETC2));
268 fnAdd(FOO(COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2));
269 fnAdd(FOO(COMPRESSED_RGBA8_ETC2_EAC));
271 // sRGB support is manadatory in GL 4.3 and GL ES 3.0, which are the only
272 // versions to support ETC2.
273 fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ETC2_EAC));
274 fnAdd(FOO(COMPRESSED_SRGB8_ETC2));
275 fnAdd(FOO(COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2));
277 #undef FOO
280 // -
282 WebGLExtensionCompressedTextureETC1::WebGLExtensionCompressedTextureETC1(
283 WebGLContext* webgl)
284 : WebGLExtensionBase(webgl) {
285 RefPtr<WebGLContext> webgl_ = webgl; // Bug 1201275
286 const auto fnAdd = [&webgl_](GLenum sizedFormat,
287 webgl::EffectiveFormat effFormat) {
288 auto& fua = webgl_->mFormatUsage;
290 auto usage = fua->EditUsage(effFormat);
291 usage->isFilterable = true;
292 fua->AllowSizedTexFormat(sizedFormat, usage);
295 #define FOO(x) LOCAL_GL_##x, webgl::EffectiveFormat::x
297 fnAdd(FOO(ETC1_RGB8_OES));
299 #undef FOO
302 // -
304 WebGLExtensionCompressedTexturePVRTC::WebGLExtensionCompressedTexturePVRTC(
305 WebGLContext* webgl)
306 : WebGLExtensionBase(webgl) {
307 RefPtr<WebGLContext> webgl_ = webgl; // Bug 1201275
308 const auto fnAdd = [&webgl_](GLenum sizedFormat,
309 webgl::EffectiveFormat effFormat) {
310 auto& fua = webgl_->mFormatUsage;
312 auto usage = fua->EditUsage(effFormat);
313 usage->isFilterable = true;
314 fua->AllowSizedTexFormat(sizedFormat, usage);
317 #define FOO(x) LOCAL_GL_##x, webgl::EffectiveFormat::x
319 fnAdd(FOO(COMPRESSED_RGB_PVRTC_4BPPV1));
320 fnAdd(FOO(COMPRESSED_RGB_PVRTC_2BPPV1));
321 fnAdd(FOO(COMPRESSED_RGBA_PVRTC_4BPPV1));
322 fnAdd(FOO(COMPRESSED_RGBA_PVRTC_2BPPV1));
324 #undef FOO
327 // -
329 WebGLExtensionCompressedTextureRGTC::WebGLExtensionCompressedTextureRGTC(
330 WebGLContext* const webgl)
331 : WebGLExtensionBase(webgl) {
332 MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
334 auto& fua = webgl->mFormatUsage;
336 const auto fnAdd = [&](const GLenum sizedFormat,
337 const webgl::EffectiveFormat effFormat) {
338 auto usage = fua->EditUsage(effFormat);
339 usage->isFilterable = true;
340 fua->AllowSizedTexFormat(sizedFormat, usage);
343 #define _(X) LOCAL_GL_##X, webgl::EffectiveFormat::X
345 fnAdd(_(COMPRESSED_RED_RGTC1));
346 fnAdd(_(COMPRESSED_SIGNED_RED_RGTC1));
347 fnAdd(_(COMPRESSED_RG_RGTC2));
348 fnAdd(_(COMPRESSED_SIGNED_RG_RGTC2));
350 #undef _
353 bool WebGLExtensionCompressedTextureRGTC::IsSupported(
354 const WebGLContext* const webgl) {
355 return webgl->gl->IsSupported(gl::GLFeature::texture_compression_rgtc);
358 // -
360 WebGLExtensionCompressedTextureS3TC::WebGLExtensionCompressedTextureS3TC(
361 WebGLContext* webgl)
362 : WebGLExtensionBase(webgl) {
363 RefPtr<WebGLContext> webgl_ = webgl; // Bug 1201275
364 const auto fnAdd = [&webgl_](GLenum sizedFormat,
365 webgl::EffectiveFormat effFormat) {
366 auto& fua = webgl_->mFormatUsage;
368 auto usage = fua->EditUsage(effFormat);
369 usage->isFilterable = true;
370 fua->AllowSizedTexFormat(sizedFormat, usage);
373 #define FOO(x) LOCAL_GL_##x, webgl::EffectiveFormat::x
375 fnAdd(FOO(COMPRESSED_RGB_S3TC_DXT1_EXT));
376 fnAdd(FOO(COMPRESSED_RGBA_S3TC_DXT1_EXT));
377 fnAdd(FOO(COMPRESSED_RGBA_S3TC_DXT3_EXT));
378 fnAdd(FOO(COMPRESSED_RGBA_S3TC_DXT5_EXT));
380 #undef FOO
383 bool WebGLExtensionCompressedTextureS3TC::IsSupported(
384 const WebGLContext* webgl) {
385 gl::GLContext* gl = webgl->GL();
386 if (gl->IsExtensionSupported(gl::GLContext::EXT_texture_compression_s3tc))
387 return true;
389 return gl->IsExtensionSupported(
390 gl::GLContext::EXT_texture_compression_dxt1) &&
391 gl->IsExtensionSupported(
392 gl::GLContext::ANGLE_texture_compression_dxt3) &&
393 gl->IsExtensionSupported(
394 gl::GLContext::ANGLE_texture_compression_dxt5);
397 // -
399 WebGLExtensionCompressedTextureS3TC_SRGB::
400 WebGLExtensionCompressedTextureS3TC_SRGB(WebGLContext* webgl)
401 : WebGLExtensionBase(webgl) {
402 RefPtr<WebGLContext> webgl_ = webgl; // Bug 1201275
403 const auto fnAdd = [&webgl_](GLenum sizedFormat,
404 webgl::EffectiveFormat effFormat) {
405 auto& fua = webgl_->mFormatUsage;
407 auto usage = fua->EditUsage(effFormat);
408 usage->isFilterable = true;
409 fua->AllowSizedTexFormat(sizedFormat, usage);
412 #define FOO(x) LOCAL_GL_##x, webgl::EffectiveFormat::x
414 fnAdd(FOO(COMPRESSED_SRGB_S3TC_DXT1_EXT));
415 fnAdd(FOO(COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT));
416 fnAdd(FOO(COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT));
417 fnAdd(FOO(COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT));
419 #undef FOO
422 bool WebGLExtensionCompressedTextureS3TC_SRGB::IsSupported(
423 const WebGLContext* webgl) {
424 gl::GLContext* gl = webgl->GL();
425 if (gl->IsGLES())
426 return gl->IsExtensionSupported(
427 gl::GLContext::EXT_texture_compression_s3tc_srgb);
429 // Desktop GL is more complicated: It's EXT_texture_sRGB, when
430 // EXT_texture_compression_s3tc is supported, that enables srgb+s3tc.
431 return gl->IsExtensionSupported(gl::GLContext::EXT_texture_sRGB) &&
432 gl->IsExtensionSupported(gl::GLContext::EXT_texture_compression_s3tc);
435 // -
437 WebGLExtensionDepthClamp::WebGLExtensionDepthClamp(WebGLContext* const webgl)
438 : WebGLExtensionBase(webgl) {
439 webgl->mIsEnabledMapKeys.insert(LOCAL_GL_DEPTH_CLAMP);
442 // -
444 WebGLExtensionDepthTexture::WebGLExtensionDepthTexture(
445 WebGLContext* const webgl)
446 : WebGLExtensionBase(webgl) {
447 auto& fua = webgl->mFormatUsage;
449 const auto fnAdd = [&fua](webgl::EffectiveFormat effFormat,
450 GLenum unpackFormat, GLenum unpackType) {
451 auto usage = fua->EditUsage(effFormat);
452 MOZ_ASSERT(usage->isFilterable);
453 MOZ_ASSERT(usage->IsRenderable());
455 const webgl::PackingInfo pi = {unpackFormat, unpackType};
456 const webgl::DriverUnpackInfo dui = {unpackFormat, unpackFormat,
457 unpackType};
458 fua->AddTexUnpack(usage, pi, dui);
459 fua->AllowUnsizedTexFormat(pi, usage);
462 fnAdd(webgl::EffectiveFormat::DEPTH_COMPONENT16, LOCAL_GL_DEPTH_COMPONENT,
463 LOCAL_GL_UNSIGNED_SHORT);
464 fnAdd(webgl::EffectiveFormat::DEPTH_COMPONENT24, LOCAL_GL_DEPTH_COMPONENT,
465 LOCAL_GL_UNSIGNED_INT);
466 fnAdd(webgl::EffectiveFormat::DEPTH24_STENCIL8, LOCAL_GL_DEPTH_STENCIL,
467 LOCAL_GL_UNSIGNED_INT_24_8);
470 bool WebGLExtensionDepthTexture::IsSupported(const WebGLContext* const webgl) {
471 if (webgl->IsWebGL2()) return false;
473 // WEBGL_depth_texture supports DEPTH_STENCIL textures
474 const auto& gl = webgl->gl;
475 if (!gl->IsSupported(gl::GLFeature::packed_depth_stencil)) return false;
477 return gl->IsSupported(gl::GLFeature::depth_texture) ||
478 gl->IsExtensionSupported(gl::GLContext::ANGLE_depth_texture);
481 // -
483 WebGLExtensionDisjointTimerQuery::WebGLExtensionDisjointTimerQuery(
484 WebGLContext* webgl)
485 : WebGLExtensionBase(webgl) {
486 MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
489 bool WebGLExtensionDisjointTimerQuery::IsSupported(
490 const WebGLContext* const webgl) {
491 if (!StaticPrefs::webgl_enable_privileged_extensions()) return false;
493 gl::GLContext* gl = webgl->GL();
494 return gl->IsSupported(gl::GLFeature::query_objects) &&
495 gl->IsSupported(gl::GLFeature::get_query_object_i64v) &&
496 gl->IsSupported(
497 gl::GLFeature::query_counter); // provides GL_TIMESTAMP
500 // -
502 WebGLExtensionDrawBuffers::WebGLExtensionDrawBuffers(WebGLContext* webgl)
503 : WebGLExtensionBase(webgl) {
504 MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
507 bool WebGLExtensionDrawBuffers::IsSupported(const WebGLContext* webgl) {
508 if (!webgl->mIsSupportedCache_DrawBuffers) {
509 webgl->mIsSupportedCache_DrawBuffers = [&]() {
510 gl::GLContext* const gl = webgl->GL();
512 if (webgl->IsWebGL2()) return false;
513 if (!gl->IsSupported(gl::GLFeature::draw_buffers)) return false;
515 if (gl->IsGLES() && gl->Version() >= 300) {
516 // ANGLE's shader translator can't translate ESSL1 exts to ESSL3. (bug
517 // 1524804)
518 // The spec (and some implementations of ES3) don't require support for
519 // any extensions in ESSL 100, but an implementation can choose to
520 // support them anyway. So let's check!
521 const bool ok = TestShaderCompile(gl, LOCAL_GL_FRAGMENT_SHADER, R"(
522 #extension GL_EXT_draw_buffers: require
523 void main() {}
524 )");
525 if (!ok) return false;
528 return true;
529 }();
532 return *webgl->mIsSupportedCache_DrawBuffers;
535 // -
537 WebGLExtensionExplicitPresent::WebGLExtensionExplicitPresent(
538 WebGLContext* const webgl)
539 : WebGLExtensionBase(webgl) {
540 if (!IsSupported(webgl)) {
541 NS_WARNING(
542 "Constructing WebGLExtensionExplicitPresent but IsSupported() is "
543 "false!");
544 // This was previously an assert, but it seems like we get races against
545 // StaticPrefs changes/initialization?
549 bool WebGLExtensionExplicitPresent::IsSupported(
550 const WebGLContext* const webgl) {
551 return StaticPrefs::webgl_enable_draft_extensions();
554 // -
556 WebGLExtensionEXTColorBufferFloat::WebGLExtensionEXTColorBufferFloat(
557 WebGLContext* webgl)
558 : WebGLExtensionBase(webgl) {
559 MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
561 auto& fua = webgl->mFormatUsage;
563 auto fnUpdateUsage = [&fua](GLenum sizedFormat,
564 webgl::EffectiveFormat effFormat) {
565 auto usage = fua->EditUsage(effFormat);
566 usage->SetRenderable();
567 fua->AllowRBFormat(sizedFormat, usage);
570 #define FOO(x) fnUpdateUsage(LOCAL_GL_##x, webgl::EffectiveFormat::x)
572 FOO(R16F);
573 FOO(RG16F);
574 FOO(RGBA16F);
576 FOO(R32F);
577 FOO(RG32F);
578 FOO(RGBA32F);
580 FOO(R11F_G11F_B10F);
582 #undef FOO
585 /*static*/
586 bool WebGLExtensionEXTColorBufferFloat::IsSupported(const WebGLContext* webgl) {
587 if (!webgl->IsWebGL2()) return false;
589 const gl::GLContext* gl = webgl->GL();
590 return gl->IsSupported(gl::GLFeature::EXT_color_buffer_float);
593 // -
595 WebGLExtensionFBORenderMipmap::WebGLExtensionFBORenderMipmap(
596 WebGLContext* const webgl)
597 : WebGLExtensionBase(webgl) {
598 MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
601 bool WebGLExtensionFBORenderMipmap::IsSupported(
602 const WebGLContext* const webgl) {
603 if (webgl->IsWebGL2()) return false;
605 const auto& gl = webgl->gl;
606 if (!gl->IsGLES()) return true;
607 if (gl->Version() >= 300) return true;
608 return gl->IsExtensionSupported(gl::GLContext::OES_fbo_render_mipmap);
611 // -
613 WebGLExtensionFloatBlend::WebGLExtensionFloatBlend(WebGLContext* const webgl)
614 : WebGLExtensionBase(webgl) {
615 MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
618 bool WebGLExtensionFloatBlend::IsSupported(const WebGLContext* const webgl) {
619 if (!WebGLExtensionColorBufferFloat::IsSupported(webgl) &&
620 !WebGLExtensionEXTColorBufferFloat::IsSupported(webgl))
621 return false;
623 const auto& gl = webgl->gl;
624 if (!gl->IsGLES() && gl->Version() >= 300) return true;
625 if (gl->IsGLES() && gl->Version() >= 320) return true;
626 return gl->IsExtensionSupported(gl::GLContext::EXT_float_blend);
629 // -
631 WebGLExtensionFragDepth::WebGLExtensionFragDepth(WebGLContext* webgl)
632 : WebGLExtensionBase(webgl) {
633 MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
636 bool WebGLExtensionFragDepth::IsSupported(const WebGLContext* const webgl) {
637 if (!webgl->mIsSupportedCache_FragDepth) {
638 webgl->mIsSupportedCache_FragDepth = [&]() {
639 gl::GLContext* const gl = webgl->GL();
641 if (webgl->IsWebGL2()) return false;
642 if (!gl->IsSupported(gl::GLFeature::frag_depth)) return false;
644 if (gl->IsGLES() && gl->Version() >= 300) {
645 // ANGLE's shader translator can't translate ESSL1 exts to ESSL3. (bug
646 // 1524804)
647 // The spec (and some implementations of ES3) don't require support for
648 // any extensions in ESSL 100, but an implementation can choose to
649 // support them anyway. So let's check!
650 const bool ok = TestShaderCompile(gl, LOCAL_GL_FRAGMENT_SHADER, R"(
651 #extension GL_EXT_frag_depth: require
652 void main() {}
653 )");
654 if (!ok) return false;
657 return true;
658 }();
661 return *webgl->mIsSupportedCache_FragDepth;
664 // -
666 WebGLExtensionInstancedArrays::WebGLExtensionInstancedArrays(
667 WebGLContext* webgl)
668 : WebGLExtensionBase(webgl) {
669 MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
672 bool WebGLExtensionInstancedArrays::IsSupported(const WebGLContext* webgl) {
673 if (webgl->IsWebGL2()) return false;
675 gl::GLContext* gl = webgl->GL();
676 return gl->IsSupported(gl::GLFeature::draw_instanced) &&
677 gl->IsSupported(gl::GLFeature::instanced_arrays);
680 // -
682 WebGLExtensionMultiview::WebGLExtensionMultiview(WebGLContext* const webgl)
683 : WebGLExtensionBase(webgl) {
684 MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
687 bool WebGLExtensionMultiview::IsSupported(const WebGLContext* const webgl) {
688 if (!webgl->IsWebGL2()) return false;
690 const auto& gl = webgl->gl;
691 return gl->IsSupported(gl::GLFeature::multiview);
694 // -
696 WebGLExtensionShaderTextureLod::WebGLExtensionShaderTextureLod(
697 WebGLContext* webgl)
698 : WebGLExtensionBase(webgl) {
699 MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
702 bool WebGLExtensionShaderTextureLod::IsSupported(const WebGLContext* webgl) {
703 if (!webgl->mIsSupportedCache_ShaderTextureLod) {
704 webgl->mIsSupportedCache_ShaderTextureLod = [&]() {
705 gl::GLContext* const gl = webgl->GL();
707 if (webgl->IsWebGL2()) return false;
708 if (!gl->IsSupported(gl::GLFeature::shader_texture_lod)) return false;
710 if (gl->IsGLES() && gl->Version() >= 300) {
711 // ANGLE's shader translator doesn't yet translate
712 // WebGL1+EXT_shader_texture_lod to ES3. (Bug 1491221)
713 // The spec (and some implementations of ES3) don't require support for
714 // any extensions in ESSL 100, but an implementation can choose to
715 // support them anyway. So let's check!
716 const bool ok = TestShaderCompile(gl, LOCAL_GL_FRAGMENT_SHADER, R"(
717 #extension GL_EXT_shader_texture_lod: require
718 void main() {}
719 )");
720 if (!ok) return false;
723 return true;
724 }();
726 return *webgl->mIsSupportedCache_ShaderTextureLod;
729 // -
731 WebGLExtensionSRGB::WebGLExtensionSRGB(WebGLContext* webgl)
732 : WebGLExtensionBase(webgl) {
733 MOZ_ASSERT(IsSupported(webgl), "Don't construct extension if unsupported.");
735 gl::GLContext* gl = webgl->GL();
736 if (!gl->IsGLES()) {
737 // Desktop OpenGL requires the following to be enabled in order to
738 // support sRGB operations on framebuffers.
739 gl->fEnable(LOCAL_GL_FRAMEBUFFER_SRGB_EXT);
742 auto& fua = webgl->mFormatUsage;
744 RefPtr<gl::GLContext> gl_ = gl; // Bug 1201275
745 const auto fnAdd = [&fua, &gl_](webgl::EffectiveFormat effFormat,
746 GLenum format, GLenum desktopUnpackFormat) {
747 auto usage = fua->EditUsage(effFormat);
748 usage->isFilterable = true;
750 webgl::DriverUnpackInfo dui = {format, format, LOCAL_GL_UNSIGNED_BYTE};
751 const auto pi = dui.ToPacking();
753 if (!gl_->IsGLES()) dui.unpackFormat = desktopUnpackFormat;
755 fua->AddTexUnpack(usage, pi, dui);
757 fua->AllowUnsizedTexFormat(pi, usage);
760 fnAdd(webgl::EffectiveFormat::SRGB8, LOCAL_GL_SRGB, LOCAL_GL_RGB);
761 fnAdd(webgl::EffectiveFormat::SRGB8_ALPHA8, LOCAL_GL_SRGB_ALPHA,
762 LOCAL_GL_RGBA);
764 auto usage = fua->EditUsage(webgl::EffectiveFormat::SRGB8_ALPHA8);
765 usage->SetRenderable();
766 fua->AllowRBFormat(LOCAL_GL_SRGB8_ALPHA8, usage);
769 bool WebGLExtensionSRGB::IsSupported(const WebGLContext* const webgl) {
770 if (webgl->IsWebGL2()) return false;
772 return webgl->gl->IsSupported(gl::GLFeature::sRGB);
775 // -
777 WebGLExtensionTextureFloat::WebGLExtensionTextureFloat(WebGLContext* webgl)
778 : WebGLExtensionBase(webgl) {
779 MOZ_ASSERT(IsSupported(webgl));
781 auto& fua = webgl->mFormatUsage;
782 gl::GLContext* gl = webgl->GL();
784 webgl::PackingInfo pi;
785 webgl::DriverUnpackInfo dui;
786 const GLint* swizzle = nullptr;
788 const auto fnAdd = [&](webgl::EffectiveFormat effFormat) {
789 MOZ_ASSERT_IF(swizzle, gl->IsSupported(gl::GLFeature::texture_swizzle));
791 auto usage = fua->EditUsage(effFormat);
792 usage->textureSwizzleRGBA = swizzle;
793 fua->AddTexUnpack(usage, pi, dui);
795 fua->AllowUnsizedTexFormat(pi, usage);
798 bool useSizedFormats = true;
799 const bool hasSizedLegacyFormats = gl->IsCompatibilityProfile();
800 if (gl->IsGLES() && gl->Version() < 300) {
801 useSizedFormats = false;
804 ////////////////
806 pi = {LOCAL_GL_RGBA, LOCAL_GL_FLOAT};
807 dui = {pi.format, pi.format, pi.type};
808 swizzle = nullptr;
809 if (useSizedFormats || gl->IsExtensionSupported(
810 gl::GLContext::CHROMIUM_color_buffer_float_rgba)) {
811 // ANGLE only exposes renderable RGBA32F via
812 // CHROMIUM_color_buffer_float_rgba, which uses sized formats.
813 dui.internalFormat = LOCAL_GL_RGBA32F;
815 fnAdd(webgl::EffectiveFormat::RGBA32F);
817 //////
819 pi = {LOCAL_GL_RGB, LOCAL_GL_FLOAT};
820 dui = {pi.format, pi.format, pi.type};
821 swizzle = nullptr;
822 if (useSizedFormats) {
823 dui.internalFormat = LOCAL_GL_RGB32F;
825 fnAdd(webgl::EffectiveFormat::RGB32F);
827 //////
829 pi = {LOCAL_GL_LUMINANCE, LOCAL_GL_FLOAT};
830 dui = {pi.format, pi.format, pi.type};
831 swizzle = nullptr;
832 if (useSizedFormats) {
833 if (hasSizedLegacyFormats) {
834 dui.internalFormat = LOCAL_GL_LUMINANCE32F_ARB;
835 } else {
836 dui.internalFormat = LOCAL_GL_R32F;
837 dui.unpackFormat = LOCAL_GL_RED;
838 swizzle = webgl::FormatUsageInfo::kLuminanceSwizzleRGBA;
841 fnAdd(webgl::EffectiveFormat::Luminance32F);
843 //////
845 pi = {LOCAL_GL_ALPHA, LOCAL_GL_FLOAT};
846 dui = {pi.format, pi.format, pi.type};
847 swizzle = nullptr;
848 if (useSizedFormats) {
849 if (hasSizedLegacyFormats) {
850 dui.internalFormat = LOCAL_GL_ALPHA32F_ARB;
851 } else {
852 dui.internalFormat = LOCAL_GL_R32F;
853 dui.unpackFormat = LOCAL_GL_RED;
854 swizzle = webgl::FormatUsageInfo::kAlphaSwizzleRGBA;
857 fnAdd(webgl::EffectiveFormat::Alpha32F);
859 //////
861 pi = {LOCAL_GL_LUMINANCE_ALPHA, LOCAL_GL_FLOAT};
862 dui = {pi.format, pi.format, pi.type};
863 swizzle = nullptr;
864 if (useSizedFormats) {
865 if (hasSizedLegacyFormats) {
866 dui.internalFormat = LOCAL_GL_LUMINANCE_ALPHA32F_ARB;
867 } else {
868 dui.internalFormat = LOCAL_GL_RG32F;
869 dui.unpackFormat = LOCAL_GL_RG;
870 swizzle = webgl::FormatUsageInfo::kLumAlphaSwizzleRGBA;
873 fnAdd(webgl::EffectiveFormat::Luminance32FAlpha32F);
876 bool WebGLExtensionTextureFloat::IsSupported(const WebGLContext* webgl) {
877 if (webgl->IsWebGL2()) return false;
879 gl::GLContext* gl = webgl->GL();
880 if (!gl->IsSupported(gl::GLFeature::texture_float)) return false;
882 const bool needsSwizzle = gl->IsCoreProfile();
883 const bool hasSwizzle = gl->IsSupported(gl::GLFeature::texture_swizzle);
884 if (needsSwizzle && !hasSwizzle) return false;
886 return true;
889 // -
891 WebGLExtensionTextureFloatLinear::WebGLExtensionTextureFloatLinear(
892 WebGLContext* webgl)
893 : WebGLExtensionBase(webgl) {
894 auto& fua = webgl->mFormatUsage;
896 fua->EditUsage(webgl::EffectiveFormat::RGBA32F)->isFilterable = true;
897 fua->EditUsage(webgl::EffectiveFormat::RGB32F)->isFilterable = true;
899 if (webgl->IsWebGL2()) {
900 fua->EditUsage(webgl::EffectiveFormat::R32F)->isFilterable = true;
901 fua->EditUsage(webgl::EffectiveFormat::RG32F)->isFilterable = true;
902 } else {
903 fua->EditUsage(webgl::EffectiveFormat::Luminance32FAlpha32F)->isFilterable =
904 true;
905 fua->EditUsage(webgl::EffectiveFormat::Luminance32F)->isFilterable = true;
906 fua->EditUsage(webgl::EffectiveFormat::Alpha32F)->isFilterable = true;
910 // -
912 WebGLExtensionTextureHalfFloat::WebGLExtensionTextureHalfFloat(
913 WebGLContext* webgl)
914 : WebGLExtensionBase(webgl) {
915 auto& fua = webgl->mFormatUsage;
916 gl::GLContext* gl = webgl->GL();
918 webgl::PackingInfo pi;
919 webgl::DriverUnpackInfo dui;
920 const GLint* swizzle = nullptr;
922 const auto fnAdd = [&](webgl::EffectiveFormat effFormat) {
923 MOZ_ASSERT_IF(swizzle, gl->IsSupported(gl::GLFeature::texture_swizzle));
925 auto usage = fua->EditUsage(effFormat);
926 usage->textureSwizzleRGBA = swizzle;
927 fua->AddTexUnpack(usage, pi, dui);
929 fua->AllowUnsizedTexFormat(pi, usage);
932 bool useSizedFormats = true;
933 const bool hasSizedLegacyFormats = gl->IsCompatibilityProfile();
934 if (gl->IsGLES() && gl->Version() < 300) {
935 useSizedFormats = false;
938 GLenum driverUnpackType = LOCAL_GL_HALF_FLOAT;
939 if (!gl->IsSupported(gl::GLFeature::texture_half_float)) {
940 MOZ_ASSERT(gl->IsExtensionSupported(gl::GLContext::OES_texture_half_float));
941 driverUnpackType = LOCAL_GL_HALF_FLOAT_OES;
944 ////////////////
946 pi = {LOCAL_GL_RGBA, LOCAL_GL_HALF_FLOAT_OES};
947 dui = {pi.format, pi.format, driverUnpackType};
948 swizzle = nullptr;
949 if (useSizedFormats) {
950 dui.internalFormat = LOCAL_GL_RGBA16F;
952 fnAdd(webgl::EffectiveFormat::RGBA16F);
954 //////
956 pi = {LOCAL_GL_RGB, LOCAL_GL_HALF_FLOAT_OES};
957 dui = {pi.format, pi.format, driverUnpackType};
958 swizzle = nullptr;
959 if (useSizedFormats) {
960 dui.internalFormat = LOCAL_GL_RGB16F;
962 fnAdd(webgl::EffectiveFormat::RGB16F);
964 //////
966 pi = {LOCAL_GL_LUMINANCE, LOCAL_GL_HALF_FLOAT_OES};
967 dui = {pi.format, pi.format, driverUnpackType};
968 swizzle = nullptr;
969 if (useSizedFormats) {
970 if (hasSizedLegacyFormats) {
971 dui.internalFormat = LOCAL_GL_LUMINANCE16F_ARB;
972 } else {
973 dui.internalFormat = LOCAL_GL_R16F;
974 dui.unpackFormat = LOCAL_GL_RED;
975 swizzle = webgl::FormatUsageInfo::kLuminanceSwizzleRGBA;
978 fnAdd(webgl::EffectiveFormat::Luminance16F);
980 //////
982 pi = {LOCAL_GL_ALPHA, LOCAL_GL_HALF_FLOAT_OES};
983 dui = {pi.format, pi.format, driverUnpackType};
984 swizzle = nullptr;
985 if (useSizedFormats) {
986 if (hasSizedLegacyFormats) {
987 dui.internalFormat = LOCAL_GL_ALPHA16F_ARB;
988 } else {
989 dui.internalFormat = LOCAL_GL_R16F;
990 dui.unpackFormat = LOCAL_GL_RED;
991 swizzle = webgl::FormatUsageInfo::kAlphaSwizzleRGBA;
994 fnAdd(webgl::EffectiveFormat::Alpha16F);
996 //////
998 pi = {LOCAL_GL_LUMINANCE_ALPHA, LOCAL_GL_HALF_FLOAT_OES};
999 dui = {pi.format, pi.format, driverUnpackType};
1000 swizzle = nullptr;
1001 if (useSizedFormats) {
1002 if (hasSizedLegacyFormats) {
1003 dui.internalFormat = LOCAL_GL_LUMINANCE_ALPHA16F_ARB;
1004 } else {
1005 dui.internalFormat = LOCAL_GL_RG16F;
1006 dui.unpackFormat = LOCAL_GL_RG;
1007 swizzle = webgl::FormatUsageInfo::kLumAlphaSwizzleRGBA;
1010 fnAdd(webgl::EffectiveFormat::Luminance16FAlpha16F);
1013 bool WebGLExtensionTextureHalfFloat::IsSupported(const WebGLContext* webgl) {
1014 if (webgl->IsWebGL2()) return false;
1016 gl::GLContext* gl = webgl->GL();
1017 if (!gl->IsSupported(gl::GLFeature::texture_half_float) &&
1018 !gl->IsExtensionSupported(gl::GLContext::OES_texture_half_float)) {
1019 return false;
1022 const bool needsSwizzle = gl->IsCoreProfile();
1023 const bool hasSwizzle = gl->IsSupported(gl::GLFeature::texture_swizzle);
1024 if (needsSwizzle && !hasSwizzle) return false;
1026 return true;
1029 // -
1031 WebGLExtensionTextureHalfFloatLinear::WebGLExtensionTextureHalfFloatLinear(
1032 WebGLContext* webgl)
1033 : WebGLExtensionBase(webgl) {
1034 MOZ_ASSERT(!webgl->IsWebGL2());
1035 auto& fua = webgl->mFormatUsage;
1037 fua->EditUsage(webgl::EffectiveFormat::RGBA16F)->isFilterable = true;
1038 fua->EditUsage(webgl::EffectiveFormat::RGB16F)->isFilterable = true;
1039 fua->EditUsage(webgl::EffectiveFormat::Luminance16FAlpha16F)->isFilterable =
1040 true;
1041 fua->EditUsage(webgl::EffectiveFormat::Luminance16F)->isFilterable = true;
1042 fua->EditUsage(webgl::EffectiveFormat::Alpha16F)->isFilterable = true;
1045 // -
1047 bool WebGLExtensionTextureNorm16::IsSupported(const WebGLContext* const webgl) {
1048 if (!StaticPrefs::webgl_enable_draft_extensions()) return false;
1049 if (!webgl->IsWebGL2()) return false;
1051 const auto& gl = webgl->gl;
1053 // ANGLE's support is broken in our checkout.
1054 if (gl->IsANGLE()) return false;
1056 return gl->IsSupported(gl::GLFeature::texture_norm16);
1059 WebGLExtensionTextureNorm16::WebGLExtensionTextureNorm16(WebGLContext* webgl)
1060 : WebGLExtensionBase(webgl) {
1061 if (!IsSupported(webgl)) {
1062 NS_WARNING(
1063 "Constructing WebGLExtensionTextureNorm16 but IsSupported() is "
1064 "false!");
1065 // This was previously an assert, but it seems like we get races against
1066 // StaticPrefs changes/initialization?
1069 auto& fua = *webgl->mFormatUsage;
1071 const auto fnAdd = [&](webgl::EffectiveFormat effFormat,
1072 const bool renderable, const webgl::PackingInfo& pi) {
1073 auto& usage = *fua.EditUsage(effFormat);
1074 const auto& format = *usage.format;
1076 const auto dui =
1077 webgl::DriverUnpackInfo{format.sizedFormat, pi.format, pi.type};
1078 fua.AddTexUnpack(&usage, pi, dui);
1080 fua.AllowSizedTexFormat(format.sizedFormat, &usage);
1081 fua.AllowUnsizedTexFormat(pi, &usage);
1083 if (renderable) {
1084 usage.SetRenderable();
1085 fua.AllowRBFormat(format.sizedFormat, &usage);
1089 fnAdd(webgl::EffectiveFormat::R16, true,
1090 {LOCAL_GL_RED, LOCAL_GL_UNSIGNED_SHORT});
1091 fnAdd(webgl::EffectiveFormat::RG16, true,
1092 {LOCAL_GL_RG, LOCAL_GL_UNSIGNED_SHORT});
1093 fnAdd(webgl::EffectiveFormat::RGB16, false,
1094 {LOCAL_GL_RGB, LOCAL_GL_UNSIGNED_SHORT});
1095 fnAdd(webgl::EffectiveFormat::RGBA16, true,
1096 {LOCAL_GL_RGBA, LOCAL_GL_UNSIGNED_SHORT});
1098 fnAdd(webgl::EffectiveFormat::R16_SNORM, false,
1099 {LOCAL_GL_RED, LOCAL_GL_SHORT});
1100 fnAdd(webgl::EffectiveFormat::RG16_SNORM, false,
1101 {LOCAL_GL_RG, LOCAL_GL_SHORT});
1102 fnAdd(webgl::EffectiveFormat::RGB16_SNORM, false,
1103 {LOCAL_GL_RGB, LOCAL_GL_SHORT});
1104 fnAdd(webgl::EffectiveFormat::RGBA16_SNORM, false,
1105 {LOCAL_GL_RGBA, LOCAL_GL_SHORT});
1108 } // namespace mozilla