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"
17 static bool TestShaderCompile(gl::GLContext
* const gl
, const GLenum type
,
18 const std::string
& source
) {
19 const auto shader
= gl
->fCreateShader(type
);
20 const auto cleanup
= MakeScopeExit([&]() { gl
->fDeleteShader(shader
); });
22 const std::array
<const char*, 1> parts
= {source
.c_str()};
23 gl
->fShaderSource(shader
, parts
.size(), parts
.data(), nullptr);
24 gl
->fCompileShader(shader
);
27 gl
->fGetShaderiv(shader
, LOCAL_GL_COMPILE_STATUS
, &status
);
29 if (status
== LOCAL_GL_TRUE
) return true;
31 std::vector
<char> chars
;
33 gl
->fGetShaderInfoLog(shader
, LazyAssertedCast(chars
.size() - 1), nullptr,
35 printf_stderr("GetShaderInfoLog() ->\n%s\n", chars
.data());
37 gl
->fGetShaderSource(shader
, LazyAssertedCast(chars
.size() - 1), nullptr,
39 printf_stderr("GetShaderSource() ->\n%s\n", chars
.data());
46 WebGLExtensionBlendMinMax::WebGLExtensionBlendMinMax(WebGLContext
* webgl
)
47 : WebGLExtensionBase(webgl
) {
48 MOZ_ASSERT(IsSupported(webgl
), "Don't construct extension if unsupported.");
51 bool WebGLExtensionBlendMinMax::IsSupported(const WebGLContext
* webgl
) {
52 if (webgl
->IsWebGL2()) return false;
54 return webgl
->GL()->IsSupported(gl::GLFeature::blend_minmax
);
59 WebGLExtensionColorBufferFloat::WebGLExtensionColorBufferFloat(
61 : WebGLExtensionBase(webgl
) {
62 MOZ_ASSERT(IsSupported(webgl
), "Don't construct extension if unsupported.");
63 SetRenderable(webgl::FormatRenderableState::Implicit(
64 WebGLExtensionID::WEBGL_color_buffer_float
));
67 void WebGLExtensionColorBufferFloat::SetRenderable(
68 const webgl::FormatRenderableState state
) {
69 auto& fua
= mContext
->mFormatUsage
;
71 auto fnUpdateUsage
= [&](GLenum sizedFormat
,
72 webgl::EffectiveFormat effFormat
) {
73 auto usage
= fua
->EditUsage(effFormat
);
74 usage
->SetRenderable(state
);
75 fua
->AllowRBFormat(sizedFormat
, usage
);
78 #define FOO(x) fnUpdateUsage(LOCAL_GL_##x, webgl::EffectiveFormat::x)
80 // The extension doesn't actually add RGB32F; only RGBA32F.
86 void WebGLExtensionColorBufferFloat::OnSetExplicit() {
87 SetRenderable(webgl::FormatRenderableState::Explicit());
90 bool WebGLExtensionColorBufferFloat::IsSupported(const WebGLContext
* webgl
) {
91 if (webgl
->IsWebGL2()) return false;
93 const auto& gl
= webgl
->gl
;
94 return gl
->IsSupported(gl::GLFeature::renderbuffer_color_float
) &&
95 gl
->IsSupported(gl::GLFeature::frag_color_float
);
100 WebGLExtensionColorBufferHalfFloat::WebGLExtensionColorBufferHalfFloat(
102 : WebGLExtensionBase(webgl
) {
103 MOZ_ASSERT(IsSupported(webgl
), "Don't construct extension if unsupported.");
104 SetRenderable(webgl::FormatRenderableState::Implicit(
105 WebGLExtensionID::EXT_color_buffer_half_float
));
108 void WebGLExtensionColorBufferHalfFloat::SetRenderable(
109 const webgl::FormatRenderableState state
) {
110 auto& fua
= mContext
->mFormatUsage
;
112 auto fnUpdateUsage
= [&](GLenum sizedFormat
, webgl::EffectiveFormat effFormat
,
113 const bool renderable
) {
114 auto usage
= fua
->EditUsage(effFormat
);
116 usage
->SetRenderable(state
);
118 fua
->AllowRBFormat(sizedFormat
, usage
, renderable
);
121 #define FOO(x, y) fnUpdateUsage(LOCAL_GL_##x, webgl::EffectiveFormat::x, y)
124 FOO(RGB16F
, false); // It's not required, thus not portable. (Also there's a
125 // wicked driver bug on Mac+Intel)
130 void WebGLExtensionColorBufferHalfFloat::OnSetExplicit() {
131 SetRenderable(webgl::FormatRenderableState::Explicit());
134 bool WebGLExtensionColorBufferHalfFloat::IsSupported(
135 const WebGLContext
* webgl
) {
136 if (webgl
->IsWebGL2()) return false;
138 const auto& gl
= webgl
->gl
;
139 return gl
->IsSupported(gl::GLFeature::renderbuffer_color_half_float
) &&
140 gl
->IsSupported(gl::GLFeature::frag_color_float
);
145 WebGLExtensionCompressedTextureASTC::WebGLExtensionCompressedTextureASTC(
147 : WebGLExtensionBase(webgl
) {
148 MOZ_ASSERT(IsSupported(webgl
), "Don't construct extension if unsupported.");
150 RefPtr
<WebGLContext
> webgl_
= webgl
; // Bug 1201275
151 const auto fnAdd
= [&webgl_
](GLenum sizedFormat
,
152 webgl::EffectiveFormat effFormat
) {
153 auto& fua
= webgl_
->mFormatUsage
;
155 auto usage
= fua
->EditUsage(effFormat
);
156 usage
->isFilterable
= true;
157 fua
->AllowSizedTexFormat(sizedFormat
, usage
);
160 #define FOO(x) LOCAL_GL_##x, webgl::EffectiveFormat::x
162 fnAdd(FOO(COMPRESSED_RGBA_ASTC_4x4_KHR
));
163 fnAdd(FOO(COMPRESSED_RGBA_ASTC_5x4_KHR
));
164 fnAdd(FOO(COMPRESSED_RGBA_ASTC_5x5_KHR
));
165 fnAdd(FOO(COMPRESSED_RGBA_ASTC_6x5_KHR
));
166 fnAdd(FOO(COMPRESSED_RGBA_ASTC_6x6_KHR
));
167 fnAdd(FOO(COMPRESSED_RGBA_ASTC_8x5_KHR
));
168 fnAdd(FOO(COMPRESSED_RGBA_ASTC_8x6_KHR
));
169 fnAdd(FOO(COMPRESSED_RGBA_ASTC_8x8_KHR
));
170 fnAdd(FOO(COMPRESSED_RGBA_ASTC_10x5_KHR
));
171 fnAdd(FOO(COMPRESSED_RGBA_ASTC_10x6_KHR
));
172 fnAdd(FOO(COMPRESSED_RGBA_ASTC_10x8_KHR
));
173 fnAdd(FOO(COMPRESSED_RGBA_ASTC_10x10_KHR
));
174 fnAdd(FOO(COMPRESSED_RGBA_ASTC_12x10_KHR
));
175 fnAdd(FOO(COMPRESSED_RGBA_ASTC_12x12_KHR
));
177 fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR
));
178 fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR
));
179 fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR
));
180 fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR
));
181 fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR
));
182 fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR
));
183 fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR
));
184 fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR
));
185 fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR
));
186 fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR
));
187 fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR
));
188 fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR
));
189 fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR
));
190 fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR
));
195 bool WebGLExtensionCompressedTextureASTC::IsSupported(
196 const WebGLContext
* webgl
) {
197 gl::GLContext
* gl
= webgl
->GL();
198 return gl
->IsExtensionSupported(
199 gl::GLContext::KHR_texture_compression_astc_ldr
);
204 WebGLExtensionCompressedTextureBPTC::WebGLExtensionCompressedTextureBPTC(
205 WebGLContext
* const webgl
)
206 : WebGLExtensionBase(webgl
) {
207 MOZ_ASSERT(IsSupported(webgl
), "Don't construct extension if unsupported.");
209 auto& fua
= webgl
->mFormatUsage
;
211 const auto fnAdd
= [&](const GLenum sizedFormat
,
212 const webgl::EffectiveFormat effFormat
) {
213 auto usage
= fua
->EditUsage(effFormat
);
214 usage
->isFilterable
= true;
215 fua
->AllowSizedTexFormat(sizedFormat
, usage
);
218 #define _(X) LOCAL_GL_##X, webgl::EffectiveFormat::X
220 fnAdd(_(COMPRESSED_RGBA_BPTC_UNORM
));
221 fnAdd(_(COMPRESSED_SRGB_ALPHA_BPTC_UNORM
));
222 fnAdd(_(COMPRESSED_RGB_BPTC_SIGNED_FLOAT
));
223 fnAdd(_(COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT
));
228 bool WebGLExtensionCompressedTextureBPTC::IsSupported(
229 const WebGLContext
* const webgl
) {
230 return webgl
->gl
->IsSupported(gl::GLFeature::texture_compression_bptc
);
235 WebGLExtensionCompressedTextureES3::WebGLExtensionCompressedTextureES3(
237 : WebGLExtensionBase(webgl
) {
238 // GLES 3.0.4, p147, table 3.19
239 // GLES 3.0.4, p286+, $C.1 "ETC Compressed Texture Image Formats"
240 // Note that all compressed texture formats are filterable:
242 // "[A] texture is complete unless any of the following conditions hold true:
244 // * The effective internal format specified for the texture arrays is a
245 // sized internal color format that is not texture-filterable (see table
246 // 3.13) and [the mag filter requires filtering]."
247 // Compressed formats are not sized internal color formats, and indeed they
248 // are not listed in table 3.13.
250 RefPtr
<WebGLContext
> webgl_
= webgl
; // Bug 1201275
251 const auto fnAdd
= [&webgl_
](GLenum sizedFormat
,
252 webgl::EffectiveFormat effFormat
) {
253 auto& fua
= webgl_
->mFormatUsage
;
255 auto usage
= fua
->EditUsage(effFormat
);
256 usage
->isFilterable
= true;
257 fua
->AllowSizedTexFormat(sizedFormat
, usage
);
260 #define FOO(x) LOCAL_GL_##x, webgl::EffectiveFormat::x
262 fnAdd(FOO(COMPRESSED_R11_EAC
));
263 fnAdd(FOO(COMPRESSED_SIGNED_R11_EAC
));
264 fnAdd(FOO(COMPRESSED_RG11_EAC
));
265 fnAdd(FOO(COMPRESSED_SIGNED_RG11_EAC
));
266 fnAdd(FOO(COMPRESSED_RGB8_ETC2
));
267 fnAdd(FOO(COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
));
268 fnAdd(FOO(COMPRESSED_RGBA8_ETC2_EAC
));
270 // sRGB support is manadatory in GL 4.3 and GL ES 3.0, which are the only
271 // versions to support ETC2.
272 fnAdd(FOO(COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
));
273 fnAdd(FOO(COMPRESSED_SRGB8_ETC2
));
274 fnAdd(FOO(COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
));
281 WebGLExtensionCompressedTextureETC1::WebGLExtensionCompressedTextureETC1(
283 : WebGLExtensionBase(webgl
) {
284 RefPtr
<WebGLContext
> webgl_
= webgl
; // Bug 1201275
285 const auto fnAdd
= [&webgl_
](GLenum sizedFormat
,
286 webgl::EffectiveFormat effFormat
) {
287 auto& fua
= webgl_
->mFormatUsage
;
289 auto usage
= fua
->EditUsage(effFormat
);
290 usage
->isFilterable
= true;
291 fua
->AllowSizedTexFormat(sizedFormat
, usage
);
294 #define FOO(x) LOCAL_GL_##x, webgl::EffectiveFormat::x
296 fnAdd(FOO(ETC1_RGB8_OES
));
303 WebGLExtensionCompressedTexturePVRTC::WebGLExtensionCompressedTexturePVRTC(
305 : WebGLExtensionBase(webgl
) {
306 RefPtr
<WebGLContext
> webgl_
= webgl
; // Bug 1201275
307 const auto fnAdd
= [&webgl_
](GLenum sizedFormat
,
308 webgl::EffectiveFormat effFormat
) {
309 auto& fua
= webgl_
->mFormatUsage
;
311 auto usage
= fua
->EditUsage(effFormat
);
312 usage
->isFilterable
= true;
313 fua
->AllowSizedTexFormat(sizedFormat
, usage
);
316 #define FOO(x) LOCAL_GL_##x, webgl::EffectiveFormat::x
318 fnAdd(FOO(COMPRESSED_RGB_PVRTC_4BPPV1
));
319 fnAdd(FOO(COMPRESSED_RGB_PVRTC_2BPPV1
));
320 fnAdd(FOO(COMPRESSED_RGBA_PVRTC_4BPPV1
));
321 fnAdd(FOO(COMPRESSED_RGBA_PVRTC_2BPPV1
));
328 WebGLExtensionCompressedTextureRGTC::WebGLExtensionCompressedTextureRGTC(
329 WebGLContext
* const webgl
)
330 : WebGLExtensionBase(webgl
) {
331 MOZ_ASSERT(IsSupported(webgl
), "Don't construct extension if unsupported.");
333 auto& fua
= webgl
->mFormatUsage
;
335 const auto fnAdd
= [&](const GLenum sizedFormat
,
336 const webgl::EffectiveFormat effFormat
) {
337 auto usage
= fua
->EditUsage(effFormat
);
338 usage
->isFilterable
= true;
339 fua
->AllowSizedTexFormat(sizedFormat
, usage
);
342 #define _(X) LOCAL_GL_##X, webgl::EffectiveFormat::X
344 fnAdd(_(COMPRESSED_RED_RGTC1
));
345 fnAdd(_(COMPRESSED_SIGNED_RED_RGTC1
));
346 fnAdd(_(COMPRESSED_RG_RGTC2
));
347 fnAdd(_(COMPRESSED_SIGNED_RG_RGTC2
));
352 bool WebGLExtensionCompressedTextureRGTC::IsSupported(
353 const WebGLContext
* const webgl
) {
354 return webgl
->gl
->IsSupported(gl::GLFeature::texture_compression_rgtc
);
359 WebGLExtensionCompressedTextureS3TC::WebGLExtensionCompressedTextureS3TC(
361 : WebGLExtensionBase(webgl
) {
362 RefPtr
<WebGLContext
> webgl_
= webgl
; // Bug 1201275
363 const auto fnAdd
= [&webgl_
](GLenum sizedFormat
,
364 webgl::EffectiveFormat effFormat
) {
365 auto& fua
= webgl_
->mFormatUsage
;
367 auto usage
= fua
->EditUsage(effFormat
);
368 usage
->isFilterable
= true;
369 fua
->AllowSizedTexFormat(sizedFormat
, usage
);
372 #define FOO(x) LOCAL_GL_##x, webgl::EffectiveFormat::x
374 fnAdd(FOO(COMPRESSED_RGB_S3TC_DXT1_EXT
));
375 fnAdd(FOO(COMPRESSED_RGBA_S3TC_DXT1_EXT
));
376 fnAdd(FOO(COMPRESSED_RGBA_S3TC_DXT3_EXT
));
377 fnAdd(FOO(COMPRESSED_RGBA_S3TC_DXT5_EXT
));
382 bool WebGLExtensionCompressedTextureS3TC::IsSupported(
383 const WebGLContext
* webgl
) {
384 gl::GLContext
* gl
= webgl
->GL();
385 if (gl
->IsExtensionSupported(gl::GLContext::EXT_texture_compression_s3tc
))
388 return gl
->IsExtensionSupported(
389 gl::GLContext::EXT_texture_compression_dxt1
) &&
390 gl
->IsExtensionSupported(
391 gl::GLContext::ANGLE_texture_compression_dxt3
) &&
392 gl
->IsExtensionSupported(
393 gl::GLContext::ANGLE_texture_compression_dxt5
);
398 WebGLExtensionCompressedTextureS3TC_SRGB::
399 WebGLExtensionCompressedTextureS3TC_SRGB(WebGLContext
* webgl
)
400 : WebGLExtensionBase(webgl
) {
401 RefPtr
<WebGLContext
> webgl_
= webgl
; // Bug 1201275
402 const auto fnAdd
= [&webgl_
](GLenum sizedFormat
,
403 webgl::EffectiveFormat effFormat
) {
404 auto& fua
= webgl_
->mFormatUsage
;
406 auto usage
= fua
->EditUsage(effFormat
);
407 usage
->isFilterable
= true;
408 fua
->AllowSizedTexFormat(sizedFormat
, usage
);
411 #define FOO(x) LOCAL_GL_##x, webgl::EffectiveFormat::x
413 fnAdd(FOO(COMPRESSED_SRGB_S3TC_DXT1_EXT
));
414 fnAdd(FOO(COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT
));
415 fnAdd(FOO(COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT
));
416 fnAdd(FOO(COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT
));
421 bool WebGLExtensionCompressedTextureS3TC_SRGB::IsSupported(
422 const WebGLContext
* webgl
) {
423 gl::GLContext
* gl
= webgl
->GL();
425 return gl
->IsExtensionSupported(
426 gl::GLContext::EXT_texture_compression_s3tc_srgb
);
428 // Desktop GL is more complicated: It's EXT_texture_sRGB, when
429 // EXT_texture_compression_s3tc is supported, that enables srgb+s3tc.
430 return gl
->IsExtensionSupported(gl::GLContext::EXT_texture_sRGB
) &&
431 gl
->IsExtensionSupported(gl::GLContext::EXT_texture_compression_s3tc
);
436 WebGLExtensionDepthClamp::WebGLExtensionDepthClamp(WebGLContext
* const webgl
)
437 : WebGLExtensionBase(webgl
) {
438 webgl
->mIsEnabledMapKeys
.insert(LOCAL_GL_DEPTH_CLAMP
);
443 WebGLExtensionDepthTexture::WebGLExtensionDepthTexture(
444 WebGLContext
* const webgl
)
445 : WebGLExtensionBase(webgl
) {
446 auto& fua
= webgl
->mFormatUsage
;
448 const auto fnAdd
= [&fua
](webgl::EffectiveFormat effFormat
,
449 GLenum unpackFormat
, GLenum unpackType
) {
450 auto usage
= fua
->EditUsage(effFormat
);
451 MOZ_ASSERT(usage
->isFilterable
);
452 MOZ_ASSERT(usage
->IsRenderable());
454 const webgl::PackingInfo pi
= {unpackFormat
, unpackType
};
455 const webgl::DriverUnpackInfo dui
= {unpackFormat
, unpackFormat
,
457 fua
->AddTexUnpack(usage
, pi
, dui
);
458 fua
->AllowUnsizedTexFormat(pi
, usage
);
461 fnAdd(webgl::EffectiveFormat::DEPTH_COMPONENT16
, LOCAL_GL_DEPTH_COMPONENT
,
462 LOCAL_GL_UNSIGNED_SHORT
);
463 fnAdd(webgl::EffectiveFormat::DEPTH_COMPONENT24
, LOCAL_GL_DEPTH_COMPONENT
,
464 LOCAL_GL_UNSIGNED_INT
);
465 fnAdd(webgl::EffectiveFormat::DEPTH24_STENCIL8
, LOCAL_GL_DEPTH_STENCIL
,
466 LOCAL_GL_UNSIGNED_INT_24_8
);
469 bool WebGLExtensionDepthTexture::IsSupported(const WebGLContext
* const webgl
) {
470 if (webgl
->IsWebGL2()) return false;
472 // WEBGL_depth_texture supports DEPTH_STENCIL textures
473 const auto& gl
= webgl
->gl
;
474 if (!gl
->IsSupported(gl::GLFeature::packed_depth_stencil
)) return false;
476 return gl
->IsSupported(gl::GLFeature::depth_texture
) ||
477 gl
->IsExtensionSupported(gl::GLContext::ANGLE_depth_texture
);
482 WebGLExtensionDisjointTimerQuery::WebGLExtensionDisjointTimerQuery(
484 : WebGLExtensionBase(webgl
) {
485 MOZ_ASSERT(IsSupported(webgl
), "Don't construct extension if unsupported.");
488 bool WebGLExtensionDisjointTimerQuery::IsSupported(
489 const WebGLContext
* const webgl
) {
490 if (!StaticPrefs::webgl_enable_privileged_extensions()) return false;
492 gl::GLContext
* gl
= webgl
->GL();
493 return gl
->IsSupported(gl::GLFeature::query_objects
) &&
494 gl
->IsSupported(gl::GLFeature::get_query_object_i64v
) &&
496 gl::GLFeature::query_counter
); // provides GL_TIMESTAMP
501 WebGLExtensionDrawBuffers::WebGLExtensionDrawBuffers(WebGLContext
* webgl
)
502 : WebGLExtensionBase(webgl
) {
503 MOZ_ASSERT(IsSupported(webgl
), "Don't construct extension if unsupported.");
506 bool WebGLExtensionDrawBuffers::IsSupported(const WebGLContext
* webgl
) {
507 if (!webgl
->mIsSupportedCache_DrawBuffers
) {
508 webgl
->mIsSupportedCache_DrawBuffers
= [&]() {
509 gl::GLContext
* const gl
= webgl
->GL();
511 if (webgl
->IsWebGL2()) return false;
512 if (!gl
->IsSupported(gl::GLFeature::draw_buffers
)) return false;
514 if (gl
->IsGLES() && gl
->Version() >= 300) {
515 // ANGLE's shader translator can't translate ESSL1 exts to ESSL3. (bug
517 // The spec (and some implementations of ES3) don't require support for
518 // any extensions in ESSL 100, but an implementation can choose to
519 // support them anyway. So let's check!
520 const bool ok
= TestShaderCompile(gl
, LOCAL_GL_FRAGMENT_SHADER
, R
"(
521 #extension GL_EXT_draw_buffers: require
524 if (!ok
) return false;
531 return *webgl
->mIsSupportedCache_DrawBuffers
;
536 WebGLExtensionExplicitPresent::WebGLExtensionExplicitPresent(
537 WebGLContext
* const webgl
)
538 : WebGLExtensionBase(webgl
) {
539 if (!IsSupported(webgl
)) {
541 "Constructing WebGLExtensionExplicitPresent but IsSupported() is "
543 // This was previously an assert, but it seems like we get races against
544 // StaticPrefs changes/initialization?
548 bool WebGLExtensionExplicitPresent::IsSupported(
549 const WebGLContext
* const webgl
) {
550 return StaticPrefs::webgl_enable_draft_extensions();
555 WebGLExtensionEXTColorBufferFloat::WebGLExtensionEXTColorBufferFloat(
557 : WebGLExtensionBase(webgl
) {
558 MOZ_ASSERT(IsSupported(webgl
), "Don't construct extension if unsupported.");
560 auto& fua
= webgl
->mFormatUsage
;
562 auto fnUpdateUsage
= [&fua
](GLenum sizedFormat
,
563 webgl::EffectiveFormat effFormat
) {
564 auto usage
= fua
->EditUsage(effFormat
);
565 usage
->SetRenderable();
566 fua
->AllowRBFormat(sizedFormat
, usage
);
569 #define FOO(x) fnUpdateUsage(LOCAL_GL_##x, webgl::EffectiveFormat::x)
585 bool WebGLExtensionEXTColorBufferFloat::IsSupported(const WebGLContext
* webgl
) {
586 if (!webgl
->IsWebGL2()) return false;
588 const gl::GLContext
* gl
= webgl
->GL();
589 return gl
->IsSupported(gl::GLFeature::EXT_color_buffer_float
);
594 WebGLExtensionFBORenderMipmap::WebGLExtensionFBORenderMipmap(
595 WebGLContext
* const webgl
)
596 : WebGLExtensionBase(webgl
) {
597 MOZ_ASSERT(IsSupported(webgl
), "Don't construct extension if unsupported.");
600 bool WebGLExtensionFBORenderMipmap::IsSupported(
601 const WebGLContext
* const webgl
) {
602 if (webgl
->IsWebGL2()) return false;
604 const auto& gl
= webgl
->gl
;
605 if (!gl
->IsGLES()) return true;
606 if (gl
->Version() >= 300) return true;
607 return gl
->IsExtensionSupported(gl::GLContext::OES_fbo_render_mipmap
);
612 WebGLExtensionFloatBlend::WebGLExtensionFloatBlend(WebGLContext
* const webgl
)
613 : WebGLExtensionBase(webgl
) {
614 MOZ_ASSERT(IsSupported(webgl
), "Don't construct extension if unsupported.");
617 bool WebGLExtensionFloatBlend::IsSupported(const WebGLContext
* const webgl
) {
618 if (!WebGLExtensionColorBufferFloat::IsSupported(webgl
) &&
619 !WebGLExtensionEXTColorBufferFloat::IsSupported(webgl
))
622 const auto& gl
= webgl
->gl
;
623 if (!gl
->IsGLES() && gl
->Version() >= 300) return true;
624 if (gl
->IsGLES() && gl
->Version() >= 320) return true;
625 return gl
->IsExtensionSupported(gl::GLContext::EXT_float_blend
);
630 WebGLExtensionFragDepth::WebGLExtensionFragDepth(WebGLContext
* webgl
)
631 : WebGLExtensionBase(webgl
) {
632 MOZ_ASSERT(IsSupported(webgl
), "Don't construct extension if unsupported.");
635 bool WebGLExtensionFragDepth::IsSupported(const WebGLContext
* const webgl
) {
636 if (!webgl
->mIsSupportedCache_FragDepth
) {
637 webgl
->mIsSupportedCache_FragDepth
= [&]() {
638 gl::GLContext
* const gl
= webgl
->GL();
640 if (webgl
->IsWebGL2()) return false;
641 if (!gl
->IsSupported(gl::GLFeature::frag_depth
)) return false;
643 if (gl
->IsGLES() && gl
->Version() >= 300) {
644 // ANGLE's shader translator can't translate ESSL1 exts to ESSL3. (bug
646 // The spec (and some implementations of ES3) don't require support for
647 // any extensions in ESSL 100, but an implementation can choose to
648 // support them anyway. So let's check!
649 const bool ok
= TestShaderCompile(gl
, LOCAL_GL_FRAGMENT_SHADER
, R
"(
650 #extension GL_EXT_frag_depth: require
653 if (!ok
) return false;
660 return *webgl
->mIsSupportedCache_FragDepth
;
665 WebGLExtensionInstancedArrays::WebGLExtensionInstancedArrays(
667 : WebGLExtensionBase(webgl
) {
668 MOZ_ASSERT(IsSupported(webgl
), "Don't construct extension if unsupported.");
671 bool WebGLExtensionInstancedArrays::IsSupported(const WebGLContext
* webgl
) {
672 if (webgl
->IsWebGL2()) return false;
674 gl::GLContext
* gl
= webgl
->GL();
675 return gl
->IsSupported(gl::GLFeature::draw_instanced
) &&
676 gl
->IsSupported(gl::GLFeature::instanced_arrays
);
681 WebGLExtensionMultiview::WebGLExtensionMultiview(WebGLContext
* const webgl
)
682 : WebGLExtensionBase(webgl
) {
683 MOZ_ASSERT(IsSupported(webgl
), "Don't construct extension if unsupported.");
686 bool WebGLExtensionMultiview::IsSupported(const WebGLContext
* const webgl
) {
687 if (!webgl
->IsWebGL2()) return false;
689 const auto& gl
= webgl
->gl
;
690 return gl
->IsSupported(gl::GLFeature::multiview
);
695 WebGLExtensionShaderTextureLod::WebGLExtensionShaderTextureLod(
697 : WebGLExtensionBase(webgl
) {
698 MOZ_ASSERT(IsSupported(webgl
), "Don't construct extension if unsupported.");
701 bool WebGLExtensionShaderTextureLod::IsSupported(const WebGLContext
* webgl
) {
702 if (!webgl
->mIsSupportedCache_ShaderTextureLod
) {
703 webgl
->mIsSupportedCache_ShaderTextureLod
= [&]() {
704 gl::GLContext
* const gl
= webgl
->GL();
706 if (webgl
->IsWebGL2()) return false;
707 if (!gl
->IsSupported(gl::GLFeature::shader_texture_lod
)) return false;
709 if (gl
->IsGLES() && gl
->Version() >= 300) {
710 // ANGLE's shader translator doesn't yet translate
711 // WebGL1+EXT_shader_texture_lod to ES3. (Bug 1491221)
712 // The spec (and some implementations of ES3) don't require support for
713 // any extensions in ESSL 100, but an implementation can choose to
714 // support them anyway. So let's check!
715 const bool ok
= TestShaderCompile(gl
, LOCAL_GL_FRAGMENT_SHADER
, R
"(
716 #extension GL_EXT_shader_texture_lod: require
719 if (!ok
) return false;
725 return *webgl
->mIsSupportedCache_ShaderTextureLod
;
730 WebGLExtensionSRGB::WebGLExtensionSRGB(WebGLContext
* webgl
)
731 : WebGLExtensionBase(webgl
) {
732 MOZ_ASSERT(IsSupported(webgl
), "Don't construct extension if unsupported.");
734 gl::GLContext
* gl
= webgl
->GL();
736 // Desktop OpenGL requires the following to be enabled in order to
737 // support sRGB operations on framebuffers.
738 gl
->fEnable(LOCAL_GL_FRAMEBUFFER_SRGB_EXT
);
741 auto& fua
= webgl
->mFormatUsage
;
743 RefPtr
<gl::GLContext
> gl_
= gl
; // Bug 1201275
744 const auto fnAdd
= [&fua
, &gl_
](webgl::EffectiveFormat effFormat
,
745 GLenum format
, GLenum desktopUnpackFormat
) {
746 auto usage
= fua
->EditUsage(effFormat
);
747 usage
->isFilterable
= true;
749 webgl::DriverUnpackInfo dui
= {format
, format
, LOCAL_GL_UNSIGNED_BYTE
};
750 const auto pi
= dui
.ToPacking();
752 if (!gl_
->IsGLES()) dui
.unpackFormat
= desktopUnpackFormat
;
754 fua
->AddTexUnpack(usage
, pi
, dui
);
756 fua
->AllowUnsizedTexFormat(pi
, usage
);
759 fnAdd(webgl::EffectiveFormat::SRGB8
, LOCAL_GL_SRGB
, LOCAL_GL_RGB
);
760 fnAdd(webgl::EffectiveFormat::SRGB8_ALPHA8
, LOCAL_GL_SRGB_ALPHA
,
763 auto usage
= fua
->EditUsage(webgl::EffectiveFormat::SRGB8_ALPHA8
);
764 usage
->SetRenderable();
765 fua
->AllowRBFormat(LOCAL_GL_SRGB8_ALPHA8
, usage
);
768 bool WebGLExtensionSRGB::IsSupported(const WebGLContext
* const webgl
) {
769 if (webgl
->IsWebGL2()) return false;
771 return webgl
->gl
->IsSupported(gl::GLFeature::sRGB
);
776 WebGLExtensionTextureFloat::WebGLExtensionTextureFloat(WebGLContext
* webgl
)
777 : WebGLExtensionBase(webgl
) {
778 MOZ_ASSERT(IsSupported(webgl
));
780 auto& fua
= webgl
->mFormatUsage
;
781 gl::GLContext
* gl
= webgl
->GL();
783 webgl::PackingInfo pi
;
784 webgl::DriverUnpackInfo dui
;
785 const GLint
* swizzle
= nullptr;
787 const auto fnAdd
= [&](webgl::EffectiveFormat effFormat
) {
788 MOZ_ASSERT_IF(swizzle
, gl
->IsSupported(gl::GLFeature::texture_swizzle
));
790 auto usage
= fua
->EditUsage(effFormat
);
791 usage
->textureSwizzleRGBA
= swizzle
;
792 fua
->AddTexUnpack(usage
, pi
, dui
);
794 fua
->AllowUnsizedTexFormat(pi
, usage
);
797 bool useSizedFormats
= true;
798 const bool hasSizedLegacyFormats
= gl
->IsCompatibilityProfile();
799 if (gl
->IsGLES() && gl
->Version() < 300) {
800 useSizedFormats
= false;
805 pi
= {LOCAL_GL_RGBA
, LOCAL_GL_FLOAT
};
806 dui
= {pi
.format
, pi
.format
, pi
.type
};
808 if (useSizedFormats
|| gl
->IsExtensionSupported(
809 gl::GLContext::CHROMIUM_color_buffer_float_rgba
)) {
810 // ANGLE only exposes renderable RGBA32F via
811 // CHROMIUM_color_buffer_float_rgba, which uses sized formats.
812 dui
.internalFormat
= LOCAL_GL_RGBA32F
;
814 fnAdd(webgl::EffectiveFormat::RGBA32F
);
818 pi
= {LOCAL_GL_RGB
, LOCAL_GL_FLOAT
};
819 dui
= {pi
.format
, pi
.format
, pi
.type
};
821 if (useSizedFormats
) {
822 dui
.internalFormat
= LOCAL_GL_RGB32F
;
824 fnAdd(webgl::EffectiveFormat::RGB32F
);
828 pi
= {LOCAL_GL_LUMINANCE
, LOCAL_GL_FLOAT
};
829 dui
= {pi
.format
, pi
.format
, pi
.type
};
831 if (useSizedFormats
) {
832 if (hasSizedLegacyFormats
) {
833 dui
.internalFormat
= LOCAL_GL_LUMINANCE32F_ARB
;
835 dui
.internalFormat
= LOCAL_GL_R32F
;
836 dui
.unpackFormat
= LOCAL_GL_RED
;
837 swizzle
= webgl::FormatUsageInfo::kLuminanceSwizzleRGBA
;
840 fnAdd(webgl::EffectiveFormat::Luminance32F
);
844 pi
= {LOCAL_GL_ALPHA
, LOCAL_GL_FLOAT
};
845 dui
= {pi
.format
, pi
.format
, pi
.type
};
847 if (useSizedFormats
) {
848 if (hasSizedLegacyFormats
) {
849 dui
.internalFormat
= LOCAL_GL_ALPHA32F_ARB
;
851 dui
.internalFormat
= LOCAL_GL_R32F
;
852 dui
.unpackFormat
= LOCAL_GL_RED
;
853 swizzle
= webgl::FormatUsageInfo::kAlphaSwizzleRGBA
;
856 fnAdd(webgl::EffectiveFormat::Alpha32F
);
860 pi
= {LOCAL_GL_LUMINANCE_ALPHA
, LOCAL_GL_FLOAT
};
861 dui
= {pi
.format
, pi
.format
, pi
.type
};
863 if (useSizedFormats
) {
864 if (hasSizedLegacyFormats
) {
865 dui
.internalFormat
= LOCAL_GL_LUMINANCE_ALPHA32F_ARB
;
867 dui
.internalFormat
= LOCAL_GL_RG32F
;
868 dui
.unpackFormat
= LOCAL_GL_RG
;
869 swizzle
= webgl::FormatUsageInfo::kLumAlphaSwizzleRGBA
;
872 fnAdd(webgl::EffectiveFormat::Luminance32FAlpha32F
);
875 bool WebGLExtensionTextureFloat::IsSupported(const WebGLContext
* webgl
) {
876 if (webgl
->IsWebGL2()) return false;
878 gl::GLContext
* gl
= webgl
->GL();
879 if (!gl
->IsSupported(gl::GLFeature::texture_float
)) return false;
881 const bool needsSwizzle
= gl
->IsCoreProfile();
882 const bool hasSwizzle
= gl
->IsSupported(gl::GLFeature::texture_swizzle
);
883 if (needsSwizzle
&& !hasSwizzle
) return false;
890 WebGLExtensionTextureFloatLinear::WebGLExtensionTextureFloatLinear(
892 : WebGLExtensionBase(webgl
) {
893 auto& fua
= webgl
->mFormatUsage
;
895 fua
->EditUsage(webgl::EffectiveFormat::RGBA32F
)->isFilterable
= true;
896 fua
->EditUsage(webgl::EffectiveFormat::RGB32F
)->isFilterable
= true;
898 if (webgl
->IsWebGL2()) {
899 fua
->EditUsage(webgl::EffectiveFormat::R32F
)->isFilterable
= true;
900 fua
->EditUsage(webgl::EffectiveFormat::RG32F
)->isFilterable
= true;
902 fua
->EditUsage(webgl::EffectiveFormat::Luminance32FAlpha32F
)->isFilterable
=
904 fua
->EditUsage(webgl::EffectiveFormat::Luminance32F
)->isFilterable
= true;
905 fua
->EditUsage(webgl::EffectiveFormat::Alpha32F
)->isFilterable
= true;
911 WebGLExtensionTextureHalfFloat::WebGLExtensionTextureHalfFloat(
913 : WebGLExtensionBase(webgl
) {
914 auto& fua
= webgl
->mFormatUsage
;
915 gl::GLContext
* gl
= webgl
->GL();
917 webgl::PackingInfo pi
;
918 webgl::DriverUnpackInfo dui
;
919 const GLint
* swizzle
= nullptr;
921 const auto fnAdd
= [&](webgl::EffectiveFormat effFormat
) {
922 MOZ_ASSERT_IF(swizzle
, gl
->IsSupported(gl::GLFeature::texture_swizzle
));
924 auto usage
= fua
->EditUsage(effFormat
);
925 usage
->textureSwizzleRGBA
= swizzle
;
926 fua
->AddTexUnpack(usage
, pi
, dui
);
928 fua
->AllowUnsizedTexFormat(pi
, usage
);
931 bool useSizedFormats
= true;
932 const bool hasSizedLegacyFormats
= gl
->IsCompatibilityProfile();
933 if (gl
->IsGLES() && gl
->Version() < 300) {
934 useSizedFormats
= false;
937 GLenum driverUnpackType
= LOCAL_GL_HALF_FLOAT
;
938 if (!gl
->IsSupported(gl::GLFeature::texture_half_float
)) {
939 MOZ_ASSERT(gl
->IsExtensionSupported(gl::GLContext::OES_texture_half_float
));
940 driverUnpackType
= LOCAL_GL_HALF_FLOAT_OES
;
945 pi
= {LOCAL_GL_RGBA
, LOCAL_GL_HALF_FLOAT_OES
};
946 dui
= {pi
.format
, pi
.format
, driverUnpackType
};
948 if (useSizedFormats
) {
949 dui
.internalFormat
= LOCAL_GL_RGBA16F
;
951 fnAdd(webgl::EffectiveFormat::RGBA16F
);
955 pi
= {LOCAL_GL_RGB
, LOCAL_GL_HALF_FLOAT_OES
};
956 dui
= {pi
.format
, pi
.format
, driverUnpackType
};
958 if (useSizedFormats
) {
959 dui
.internalFormat
= LOCAL_GL_RGB16F
;
961 fnAdd(webgl::EffectiveFormat::RGB16F
);
965 pi
= {LOCAL_GL_LUMINANCE
, LOCAL_GL_HALF_FLOAT_OES
};
966 dui
= {pi
.format
, pi
.format
, driverUnpackType
};
968 if (useSizedFormats
) {
969 if (hasSizedLegacyFormats
) {
970 dui
.internalFormat
= LOCAL_GL_LUMINANCE16F_ARB
;
972 dui
.internalFormat
= LOCAL_GL_R16F
;
973 dui
.unpackFormat
= LOCAL_GL_RED
;
974 swizzle
= webgl::FormatUsageInfo::kLuminanceSwizzleRGBA
;
977 fnAdd(webgl::EffectiveFormat::Luminance16F
);
981 pi
= {LOCAL_GL_ALPHA
, LOCAL_GL_HALF_FLOAT_OES
};
982 dui
= {pi
.format
, pi
.format
, driverUnpackType
};
984 if (useSizedFormats
) {
985 if (hasSizedLegacyFormats
) {
986 dui
.internalFormat
= LOCAL_GL_ALPHA16F_ARB
;
988 dui
.internalFormat
= LOCAL_GL_R16F
;
989 dui
.unpackFormat
= LOCAL_GL_RED
;
990 swizzle
= webgl::FormatUsageInfo::kAlphaSwizzleRGBA
;
993 fnAdd(webgl::EffectiveFormat::Alpha16F
);
997 pi
= {LOCAL_GL_LUMINANCE_ALPHA
, LOCAL_GL_HALF_FLOAT_OES
};
998 dui
= {pi
.format
, pi
.format
, driverUnpackType
};
1000 if (useSizedFormats
) {
1001 if (hasSizedLegacyFormats
) {
1002 dui
.internalFormat
= LOCAL_GL_LUMINANCE_ALPHA16F_ARB
;
1004 dui
.internalFormat
= LOCAL_GL_RG16F
;
1005 dui
.unpackFormat
= LOCAL_GL_RG
;
1006 swizzle
= webgl::FormatUsageInfo::kLumAlphaSwizzleRGBA
;
1009 fnAdd(webgl::EffectiveFormat::Luminance16FAlpha16F
);
1012 bool WebGLExtensionTextureHalfFloat::IsSupported(const WebGLContext
* webgl
) {
1013 if (webgl
->IsWebGL2()) return false;
1015 gl::GLContext
* gl
= webgl
->GL();
1016 if (!gl
->IsSupported(gl::GLFeature::texture_half_float
) &&
1017 !gl
->IsExtensionSupported(gl::GLContext::OES_texture_half_float
)) {
1021 const bool needsSwizzle
= gl
->IsCoreProfile();
1022 const bool hasSwizzle
= gl
->IsSupported(gl::GLFeature::texture_swizzle
);
1023 if (needsSwizzle
&& !hasSwizzle
) return false;
1030 WebGLExtensionTextureHalfFloatLinear::WebGLExtensionTextureHalfFloatLinear(
1031 WebGLContext
* webgl
)
1032 : WebGLExtensionBase(webgl
) {
1033 MOZ_ASSERT(!webgl
->IsWebGL2());
1034 auto& fua
= webgl
->mFormatUsage
;
1036 fua
->EditUsage(webgl::EffectiveFormat::RGBA16F
)->isFilterable
= true;
1037 fua
->EditUsage(webgl::EffectiveFormat::RGB16F
)->isFilterable
= true;
1038 fua
->EditUsage(webgl::EffectiveFormat::Luminance16FAlpha16F
)->isFilterable
=
1040 fua
->EditUsage(webgl::EffectiveFormat::Luminance16F
)->isFilterable
= true;
1041 fua
->EditUsage(webgl::EffectiveFormat::Alpha16F
)->isFilterable
= true;
1046 bool WebGLExtensionTextureNorm16::IsSupported(const WebGLContext
* const webgl
) {
1047 if (!StaticPrefs::webgl_enable_draft_extensions()) return false;
1048 if (!webgl
->IsWebGL2()) return false;
1050 const auto& gl
= webgl
->gl
;
1052 // ANGLE's support is broken in our checkout.
1053 if (gl
->IsANGLE()) return false;
1055 return gl
->IsSupported(gl::GLFeature::texture_norm16
);
1058 WebGLExtensionTextureNorm16::WebGLExtensionTextureNorm16(WebGLContext
* webgl
)
1059 : WebGLExtensionBase(webgl
) {
1060 if (!IsSupported(webgl
)) {
1062 "Constructing WebGLExtensionTextureNorm16 but IsSupported() is "
1064 // This was previously an assert, but it seems like we get races against
1065 // StaticPrefs changes/initialization?
1068 auto& fua
= *webgl
->mFormatUsage
;
1070 const auto fnAdd
= [&](webgl::EffectiveFormat effFormat
,
1071 const bool renderable
, const webgl::PackingInfo
& pi
) {
1072 auto& usage
= *fua
.EditUsage(effFormat
);
1073 const auto& format
= *usage
.format
;
1076 webgl::DriverUnpackInfo
{format
.sizedFormat
, pi
.format
, pi
.type
};
1077 fua
.AddTexUnpack(&usage
, pi
, dui
);
1079 fua
.AllowSizedTexFormat(format
.sizedFormat
, &usage
);
1080 fua
.AllowUnsizedTexFormat(pi
, &usage
);
1083 usage
.SetRenderable();
1084 fua
.AllowRBFormat(format
.sizedFormat
, &usage
);
1088 fnAdd(webgl::EffectiveFormat::R16
, true,
1089 {LOCAL_GL_RED
, LOCAL_GL_UNSIGNED_SHORT
});
1090 fnAdd(webgl::EffectiveFormat::RG16
, true,
1091 {LOCAL_GL_RG
, LOCAL_GL_UNSIGNED_SHORT
});
1092 fnAdd(webgl::EffectiveFormat::RGB16
, false,
1093 {LOCAL_GL_RGB
, LOCAL_GL_UNSIGNED_SHORT
});
1094 fnAdd(webgl::EffectiveFormat::RGBA16
, true,
1095 {LOCAL_GL_RGBA
, LOCAL_GL_UNSIGNED_SHORT
});
1097 fnAdd(webgl::EffectiveFormat::R16_SNORM
, false,
1098 {LOCAL_GL_RED
, LOCAL_GL_SHORT
});
1099 fnAdd(webgl::EffectiveFormat::RG16_SNORM
, false,
1100 {LOCAL_GL_RG
, LOCAL_GL_SHORT
});
1101 fnAdd(webgl::EffectiveFormat::RGB16_SNORM
, false,
1102 {LOCAL_GL_RGB
, LOCAL_GL_SHORT
});
1103 fnAdd(webgl::EffectiveFormat::RGBA16_SNORM
, false,
1104 {LOCAL_GL_RGBA
, LOCAL_GL_SHORT
});
1107 } // namespace mozilla