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"
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"
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
);
28 gl
->fGetShaderiv(shader
, LOCAL_GL_COMPILE_STATUS
, &status
);
30 if (status
== LOCAL_GL_TRUE
) return true;
32 std::vector
<char> chars
;
34 gl
->fGetShaderInfoLog(shader
, LazyAssertedCast(chars
.size() - 1), nullptr,
36 printf_stderr("GetShaderInfoLog() ->\n%s\n", chars
.data());
38 gl
->fGetShaderSource(shader
, LazyAssertedCast(chars
.size() - 1), nullptr,
40 printf_stderr("GetShaderSource() ->\n%s\n", chars
.data());
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
);
60 WebGLExtensionColorBufferFloat::WebGLExtensionColorBufferFloat(
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.
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
);
101 WebGLExtensionColorBufferHalfFloat::WebGLExtensionColorBufferHalfFloat(
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
);
117 usage
->SetRenderable(state
);
119 fua
->AllowRBFormat(sizedFormat
, usage
, renderable
);
122 #define FOO(x, y) fnUpdateUsage(LOCAL_GL_##x, webgl::EffectiveFormat::x, y)
125 FOO(RGB16F
, false); // It's not required, thus not portable. (Also there's a
126 // wicked driver bug on Mac+Intel)
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
);
146 WebGLExtensionCompressedTextureASTC::WebGLExtensionCompressedTextureASTC(
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
));
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
);
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
));
229 bool WebGLExtensionCompressedTextureBPTC::IsSupported(
230 const WebGLContext
* const webgl
) {
231 return webgl
->gl
->IsSupported(gl::GLFeature::texture_compression_bptc
);
236 WebGLExtensionCompressedTextureES3::WebGLExtensionCompressedTextureES3(
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:
243 // "[A] texture is complete unless any of the following conditions hold true:
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
));
282 WebGLExtensionCompressedTextureETC1::WebGLExtensionCompressedTextureETC1(
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
));
304 WebGLExtensionCompressedTexturePVRTC::WebGLExtensionCompressedTexturePVRTC(
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
));
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
));
353 bool WebGLExtensionCompressedTextureRGTC::IsSupported(
354 const WebGLContext
* const webgl
) {
355 return webgl
->gl
->IsSupported(gl::GLFeature::texture_compression_rgtc
);
360 WebGLExtensionCompressedTextureS3TC::WebGLExtensionCompressedTextureS3TC(
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
));
383 bool WebGLExtensionCompressedTextureS3TC::IsSupported(
384 const WebGLContext
* webgl
) {
385 gl::GLContext
* gl
= webgl
->GL();
386 if (gl
->IsExtensionSupported(gl::GLContext::EXT_texture_compression_s3tc
))
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
);
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
));
422 bool WebGLExtensionCompressedTextureS3TC_SRGB::IsSupported(
423 const WebGLContext
* webgl
) {
424 gl::GLContext
* gl
= webgl
->GL();
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
);
437 WebGLExtensionDepthClamp::WebGLExtensionDepthClamp(WebGLContext
* const webgl
)
438 : WebGLExtensionBase(webgl
) {
439 webgl
->mIsEnabledMapKeys
.insert(LOCAL_GL_DEPTH_CLAMP
);
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
,
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
);
483 WebGLExtensionDisjointTimerQuery::WebGLExtensionDisjointTimerQuery(
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
) &&
497 gl::GLFeature::query_counter
); // provides GL_TIMESTAMP
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
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
525 if (!ok
) return false;
532 return *webgl
->mIsSupportedCache_DrawBuffers
;
537 WebGLExtensionExplicitPresent::WebGLExtensionExplicitPresent(
538 WebGLContext
* const webgl
)
539 : WebGLExtensionBase(webgl
) {
540 if (!IsSupported(webgl
)) {
542 "Constructing WebGLExtensionExplicitPresent but IsSupported() is "
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();
556 WebGLExtensionEXTColorBufferFloat::WebGLExtensionEXTColorBufferFloat(
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)
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
);
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
);
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
))
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
);
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
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
654 if (!ok
) return false;
661 return *webgl
->mIsSupportedCache_FragDepth
;
666 WebGLExtensionInstancedArrays::WebGLExtensionInstancedArrays(
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
);
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
);
696 WebGLExtensionShaderTextureLod::WebGLExtensionShaderTextureLod(
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
720 if (!ok
) return false;
726 return *webgl
->mIsSupportedCache_ShaderTextureLod
;
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();
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
,
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
);
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;
806 pi
= {LOCAL_GL_RGBA
, LOCAL_GL_FLOAT
};
807 dui
= {pi
.format
, pi
.format
, pi
.type
};
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
);
819 pi
= {LOCAL_GL_RGB
, LOCAL_GL_FLOAT
};
820 dui
= {pi
.format
, pi
.format
, pi
.type
};
822 if (useSizedFormats
) {
823 dui
.internalFormat
= LOCAL_GL_RGB32F
;
825 fnAdd(webgl::EffectiveFormat::RGB32F
);
829 pi
= {LOCAL_GL_LUMINANCE
, LOCAL_GL_FLOAT
};
830 dui
= {pi
.format
, pi
.format
, pi
.type
};
832 if (useSizedFormats
) {
833 if (hasSizedLegacyFormats
) {
834 dui
.internalFormat
= LOCAL_GL_LUMINANCE32F_ARB
;
836 dui
.internalFormat
= LOCAL_GL_R32F
;
837 dui
.unpackFormat
= LOCAL_GL_RED
;
838 swizzle
= webgl::FormatUsageInfo::kLuminanceSwizzleRGBA
;
841 fnAdd(webgl::EffectiveFormat::Luminance32F
);
845 pi
= {LOCAL_GL_ALPHA
, LOCAL_GL_FLOAT
};
846 dui
= {pi
.format
, pi
.format
, pi
.type
};
848 if (useSizedFormats
) {
849 if (hasSizedLegacyFormats
) {
850 dui
.internalFormat
= LOCAL_GL_ALPHA32F_ARB
;
852 dui
.internalFormat
= LOCAL_GL_R32F
;
853 dui
.unpackFormat
= LOCAL_GL_RED
;
854 swizzle
= webgl::FormatUsageInfo::kAlphaSwizzleRGBA
;
857 fnAdd(webgl::EffectiveFormat::Alpha32F
);
861 pi
= {LOCAL_GL_LUMINANCE_ALPHA
, LOCAL_GL_FLOAT
};
862 dui
= {pi
.format
, pi
.format
, pi
.type
};
864 if (useSizedFormats
) {
865 if (hasSizedLegacyFormats
) {
866 dui
.internalFormat
= LOCAL_GL_LUMINANCE_ALPHA32F_ARB
;
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;
891 WebGLExtensionTextureFloatLinear::WebGLExtensionTextureFloatLinear(
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;
903 fua
->EditUsage(webgl::EffectiveFormat::Luminance32FAlpha32F
)->isFilterable
=
905 fua
->EditUsage(webgl::EffectiveFormat::Luminance32F
)->isFilterable
= true;
906 fua
->EditUsage(webgl::EffectiveFormat::Alpha32F
)->isFilterable
= true;
912 WebGLExtensionTextureHalfFloat::WebGLExtensionTextureHalfFloat(
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
;
946 pi
= {LOCAL_GL_RGBA
, LOCAL_GL_HALF_FLOAT_OES
};
947 dui
= {pi
.format
, pi
.format
, driverUnpackType
};
949 if (useSizedFormats
) {
950 dui
.internalFormat
= LOCAL_GL_RGBA16F
;
952 fnAdd(webgl::EffectiveFormat::RGBA16F
);
956 pi
= {LOCAL_GL_RGB
, LOCAL_GL_HALF_FLOAT_OES
};
957 dui
= {pi
.format
, pi
.format
, driverUnpackType
};
959 if (useSizedFormats
) {
960 dui
.internalFormat
= LOCAL_GL_RGB16F
;
962 fnAdd(webgl::EffectiveFormat::RGB16F
);
966 pi
= {LOCAL_GL_LUMINANCE
, LOCAL_GL_HALF_FLOAT_OES
};
967 dui
= {pi
.format
, pi
.format
, driverUnpackType
};
969 if (useSizedFormats
) {
970 if (hasSizedLegacyFormats
) {
971 dui
.internalFormat
= LOCAL_GL_LUMINANCE16F_ARB
;
973 dui
.internalFormat
= LOCAL_GL_R16F
;
974 dui
.unpackFormat
= LOCAL_GL_RED
;
975 swizzle
= webgl::FormatUsageInfo::kLuminanceSwizzleRGBA
;
978 fnAdd(webgl::EffectiveFormat::Luminance16F
);
982 pi
= {LOCAL_GL_ALPHA
, LOCAL_GL_HALF_FLOAT_OES
};
983 dui
= {pi
.format
, pi
.format
, driverUnpackType
};
985 if (useSizedFormats
) {
986 if (hasSizedLegacyFormats
) {
987 dui
.internalFormat
= LOCAL_GL_ALPHA16F_ARB
;
989 dui
.internalFormat
= LOCAL_GL_R16F
;
990 dui
.unpackFormat
= LOCAL_GL_RED
;
991 swizzle
= webgl::FormatUsageInfo::kAlphaSwizzleRGBA
;
994 fnAdd(webgl::EffectiveFormat::Alpha16F
);
998 pi
= {LOCAL_GL_LUMINANCE_ALPHA
, LOCAL_GL_HALF_FLOAT_OES
};
999 dui
= {pi
.format
, pi
.format
, driverUnpackType
};
1001 if (useSizedFormats
) {
1002 if (hasSizedLegacyFormats
) {
1003 dui
.internalFormat
= LOCAL_GL_LUMINANCE_ALPHA16F_ARB
;
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
)) {
1022 const bool needsSwizzle
= gl
->IsCoreProfile();
1023 const bool hasSwizzle
= gl
->IsSupported(gl::GLFeature::texture_swizzle
);
1024 if (needsSwizzle
&& !hasSwizzle
) return false;
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
=
1041 fua
->EditUsage(webgl::EffectiveFormat::Luminance16F
)->isFilterable
= true;
1042 fua
->EditUsage(webgl::EffectiveFormat::Alpha16F
)->isFilterable
= true;
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
)) {
1063 "Constructing WebGLExtensionTextureNorm16 but IsSupported() is "
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
;
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
);
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