Bug 1700051: part 26) Correct typo in comment of `mozInlineSpellWordUtil::BuildSoftTe...
[gecko.git] / dom / canvas / WebGLContextExtensions.cpp
blob2cebde0fffe1359b437479ddb381a6cd67915a20
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "WebGLContext.h"
7 #include "ClientWebGLExtensions.h"
8 #include "GLContext.h"
9 #include "mozilla/dom/BindingDeclarations.h"
10 #include "mozilla/dom/ToJSValue.h"
11 #include "mozilla/EnumeratedRange.h"
12 #include "nsString.h"
13 #include "WebGLContextUtils.h"
14 #include "WebGLExtensions.h"
16 namespace mozilla {
18 const char* GetExtensionName(const WebGLExtensionID ext) {
19 static EnumeratedArray<WebGLExtensionID, WebGLExtensionID::Max, const char*>
20 sExtensionNamesEnumeratedArray;
21 static bool initialized = false;
23 if (!initialized) {
24 initialized = true;
26 #define WEBGL_EXTENSION_IDENTIFIER(x) \
27 sExtensionNamesEnumeratedArray[WebGLExtensionID::x] = #x;
29 WEBGL_EXTENSION_IDENTIFIER(ANGLE_instanced_arrays)
30 WEBGL_EXTENSION_IDENTIFIER(EXT_blend_minmax)
31 WEBGL_EXTENSION_IDENTIFIER(EXT_color_buffer_float)
32 WEBGL_EXTENSION_IDENTIFIER(EXT_color_buffer_half_float)
33 WEBGL_EXTENSION_IDENTIFIER(EXT_disjoint_timer_query)
34 WEBGL_EXTENSION_IDENTIFIER(EXT_float_blend)
35 WEBGL_EXTENSION_IDENTIFIER(EXT_frag_depth)
36 WEBGL_EXTENSION_IDENTIFIER(EXT_shader_texture_lod)
37 WEBGL_EXTENSION_IDENTIFIER(EXT_sRGB)
38 WEBGL_EXTENSION_IDENTIFIER(EXT_texture_compression_bptc)
39 WEBGL_EXTENSION_IDENTIFIER(EXT_texture_compression_rgtc)
40 WEBGL_EXTENSION_IDENTIFIER(EXT_texture_filter_anisotropic)
41 WEBGL_EXTENSION_IDENTIFIER(EXT_texture_norm16)
42 WEBGL_EXTENSION_IDENTIFIER(MOZ_debug)
43 WEBGL_EXTENSION_IDENTIFIER(OES_element_index_uint)
44 WEBGL_EXTENSION_IDENTIFIER(OES_fbo_render_mipmap)
45 WEBGL_EXTENSION_IDENTIFIER(OES_standard_derivatives)
46 WEBGL_EXTENSION_IDENTIFIER(OES_texture_float)
47 WEBGL_EXTENSION_IDENTIFIER(OES_texture_float_linear)
48 WEBGL_EXTENSION_IDENTIFIER(OES_texture_half_float)
49 WEBGL_EXTENSION_IDENTIFIER(OES_texture_half_float_linear)
50 WEBGL_EXTENSION_IDENTIFIER(OES_vertex_array_object)
51 WEBGL_EXTENSION_IDENTIFIER(OVR_multiview2)
52 WEBGL_EXTENSION_IDENTIFIER(WEBGL_color_buffer_float)
53 WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_astc)
54 WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_etc)
55 WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_etc1)
56 WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_pvrtc)
57 WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_s3tc)
58 WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_s3tc_srgb)
59 WEBGL_EXTENSION_IDENTIFIER(WEBGL_debug_renderer_info)
60 WEBGL_EXTENSION_IDENTIFIER(WEBGL_debug_shaders)
61 WEBGL_EXTENSION_IDENTIFIER(WEBGL_depth_texture)
62 WEBGL_EXTENSION_IDENTIFIER(WEBGL_draw_buffers)
63 WEBGL_EXTENSION_IDENTIFIER(WEBGL_explicit_present)
64 WEBGL_EXTENSION_IDENTIFIER(WEBGL_lose_context)
66 #undef WEBGL_EXTENSION_IDENTIFIER
69 return sExtensionNamesEnumeratedArray[ext];
72 // ----------------------------
73 // ClientWebGLContext
75 void ClientWebGLContext::GetExtension(JSContext* cx, const nsAString& wideName,
76 JS::MutableHandle<JSObject*> retval,
77 dom::CallerType callerType,
78 ErrorResult& rv) {
79 retval.set(nullptr);
80 const FuncScope funcScope(*this, "getExtension");
81 if (IsContextLost()) return;
83 const auto name = NS_ConvertUTF16toUTF8(wideName);
85 auto ext = WebGLExtensionID::Max;
87 // step 1: figure what extension is wanted
88 for (const auto extension : MakeEnumeratedRange(WebGLExtensionID::Max)) {
89 const auto& curName = GetExtensionName(extension);
90 if (name.Equals(curName, nsCaseInsensitiveCStringComparator)) {
91 ext = extension;
92 break;
96 if (ext == WebGLExtensionID::Max) return;
98 RefPtr<ClientWebGLExtensionBase> extObj;
99 if (ext == WebGLExtensionID::WEBGL_lose_context) {
100 extObj = mExtLoseContext;
101 } else {
102 extObj = GetExtension(ext, callerType);
104 if (!extObj) return;
106 // Ugh, this would be easier returning `any` than `object`.
107 JS::Rooted<JS::Value> v(cx);
108 MOZ_ALWAYS_TRUE(dom::ToJSValue(cx, extObj, &v));
109 if (v.isObject()) {
110 retval.set(&v.toObject());
114 RefPtr<ClientWebGLExtensionBase> ClientWebGLContext::GetExtension(
115 const WebGLExtensionID ext, const dom::CallerType callerType) {
116 if (ext == WebGLExtensionID::WEBGL_lose_context) {
117 // Always the same.
118 return mExtLoseContext;
121 if (!mNotLost) return nullptr;
123 if (!IsSupported(ext, callerType)) return nullptr;
125 auto& extSlot = mNotLost->extensions[UnderlyingValue(ext)];
126 if (MOZ_UNLIKELY(!extSlot)) {
127 extSlot = [&]() -> RefPtr<ClientWebGLExtensionBase> {
128 switch (ext) {
129 // ANGLE_
130 case WebGLExtensionID::ANGLE_instanced_arrays:
131 return new ClientWebGLExtensionInstancedArrays(*this);
133 // EXT_
134 case WebGLExtensionID::EXT_blend_minmax:
135 return new ClientWebGLExtensionBlendMinMax(*this);
136 case WebGLExtensionID::EXT_color_buffer_float:
137 return new ClientWebGLExtensionEXTColorBufferFloat(*this);
138 case WebGLExtensionID::EXT_color_buffer_half_float:
139 return new ClientWebGLExtensionColorBufferHalfFloat(*this);
140 case WebGLExtensionID::EXT_disjoint_timer_query:
141 return new ClientWebGLExtensionDisjointTimerQuery(*this);
142 case WebGLExtensionID::EXT_float_blend:
143 return new ClientWebGLExtensionFloatBlend(*this);
144 case WebGLExtensionID::EXT_frag_depth:
145 return new ClientWebGLExtensionFragDepth(*this);
146 case WebGLExtensionID::EXT_shader_texture_lod:
147 return new ClientWebGLExtensionShaderTextureLod(*this);
148 case WebGLExtensionID::EXT_sRGB:
149 return new ClientWebGLExtensionSRGB(*this);
150 case WebGLExtensionID::EXT_texture_compression_bptc:
151 return new ClientWebGLExtensionCompressedTextureBPTC(*this);
152 case WebGLExtensionID::EXT_texture_compression_rgtc:
153 return new ClientWebGLExtensionCompressedTextureRGTC(*this);
154 case WebGLExtensionID::EXT_texture_filter_anisotropic:
155 return new ClientWebGLExtensionTextureFilterAnisotropic(*this);
156 case WebGLExtensionID::EXT_texture_norm16:
157 return new ClientWebGLExtensionTextureNorm16(*this);
159 // MOZ_
160 case WebGLExtensionID::MOZ_debug:
161 return new ClientWebGLExtensionMOZDebug(*this);
163 // OES_
164 case WebGLExtensionID::OES_element_index_uint:
165 return new ClientWebGLExtensionElementIndexUint(*this);
166 case WebGLExtensionID::OES_fbo_render_mipmap:
167 return new ClientWebGLExtensionFBORenderMipmap(*this);
168 case WebGLExtensionID::OES_standard_derivatives:
169 return new ClientWebGLExtensionStandardDerivatives(*this);
170 case WebGLExtensionID::OES_texture_float:
171 return new ClientWebGLExtensionTextureFloat(*this);
172 case WebGLExtensionID::OES_texture_float_linear:
173 return new ClientWebGLExtensionTextureFloatLinear(*this);
174 case WebGLExtensionID::OES_texture_half_float:
175 return new ClientWebGLExtensionTextureHalfFloat(*this);
176 case WebGLExtensionID::OES_texture_half_float_linear:
177 return new ClientWebGLExtensionTextureHalfFloatLinear(*this);
178 case WebGLExtensionID::OES_vertex_array_object:
179 return new ClientWebGLExtensionVertexArray(*this);
181 // OVR_
182 case WebGLExtensionID::OVR_multiview2:
183 return new ClientWebGLExtensionMultiview(*this);
185 // WEBGL_
186 case WebGLExtensionID::WEBGL_color_buffer_float:
187 return new ClientWebGLExtensionColorBufferFloat(*this);
188 case WebGLExtensionID::WEBGL_compressed_texture_astc:
189 return new ClientWebGLExtensionCompressedTextureASTC(*this);
190 case WebGLExtensionID::WEBGL_compressed_texture_etc:
191 return new ClientWebGLExtensionCompressedTextureES3(*this);
192 case WebGLExtensionID::WEBGL_compressed_texture_etc1:
193 return new ClientWebGLExtensionCompressedTextureETC1(*this);
194 case WebGLExtensionID::WEBGL_compressed_texture_pvrtc:
195 return new ClientWebGLExtensionCompressedTexturePVRTC(*this);
196 case WebGLExtensionID::WEBGL_compressed_texture_s3tc:
197 return new ClientWebGLExtensionCompressedTextureS3TC(*this);
198 case WebGLExtensionID::WEBGL_compressed_texture_s3tc_srgb:
199 return new ClientWebGLExtensionCompressedTextureS3TC_SRGB(*this);
200 case WebGLExtensionID::WEBGL_debug_renderer_info:
201 return new ClientWebGLExtensionDebugRendererInfo(*this);
202 case WebGLExtensionID::WEBGL_debug_shaders:
203 return new ClientWebGLExtensionDebugShaders(*this);
204 case WebGLExtensionID::WEBGL_depth_texture:
205 return new ClientWebGLExtensionDepthTexture(*this);
206 case WebGLExtensionID::WEBGL_draw_buffers:
207 return new ClientWebGLExtensionDrawBuffers(*this);
208 case WebGLExtensionID::WEBGL_explicit_present:
209 return new ClientWebGLExtensionExplicitPresent(*this);
211 case WebGLExtensionID::WEBGL_lose_context:
212 case WebGLExtensionID::Max:
213 break;
215 MOZ_CRASH("illegal extension enum");
216 }();
217 MOZ_ASSERT(extSlot);
218 RequestExtension(ext);
221 return extSlot;
224 // ----------------------------
225 // WebGLContext
227 bool WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const {
228 switch (ext) {
229 case WebGLExtensionID::MOZ_debug:
230 case WebGLExtensionID::WEBGL_debug_renderer_info:
231 case WebGLExtensionID::WEBGL_debug_shaders:
232 case WebGLExtensionID::WEBGL_lose_context:
233 // Always supported.
234 return true;
236 // In alphabetical order
237 // ANGLE_
238 case WebGLExtensionID::ANGLE_instanced_arrays:
239 return WebGLExtensionInstancedArrays::IsSupported(this);
241 // EXT_
242 case WebGLExtensionID::EXT_blend_minmax:
243 return WebGLExtensionBlendMinMax::IsSupported(this);
245 case WebGLExtensionID::EXT_color_buffer_float:
246 return WebGLExtensionEXTColorBufferFloat::IsSupported(this);
248 case WebGLExtensionID::EXT_color_buffer_half_float:
249 return WebGLExtensionColorBufferHalfFloat::IsSupported(this);
251 case WebGLExtensionID::EXT_disjoint_timer_query:
252 return WebGLExtensionDisjointTimerQuery::IsSupported(this);
254 case WebGLExtensionID::EXT_float_blend:
255 return WebGLExtensionFloatBlend::IsSupported(this);
257 case WebGLExtensionID::EXT_frag_depth:
258 return WebGLExtensionFragDepth::IsSupported(this);
260 case WebGLExtensionID::EXT_shader_texture_lod:
261 return WebGLExtensionShaderTextureLod::IsSupported(this);
263 case WebGLExtensionID::EXT_sRGB:
264 return WebGLExtensionSRGB::IsSupported(this);
266 case WebGLExtensionID::EXT_texture_compression_bptc:
267 return WebGLExtensionCompressedTextureBPTC::IsSupported(this);
269 case WebGLExtensionID::EXT_texture_compression_rgtc:
270 return WebGLExtensionCompressedTextureRGTC::IsSupported(this);
272 case WebGLExtensionID::EXT_texture_filter_anisotropic:
273 return gl->IsExtensionSupported(
274 gl::GLContext::EXT_texture_filter_anisotropic);
276 case WebGLExtensionID::EXT_texture_norm16:
277 return WebGLExtensionTextureNorm16::IsSupported(this);
279 // OES_
280 case WebGLExtensionID::OES_element_index_uint:
281 if (IsWebGL2()) return false;
282 return gl->IsSupported(gl::GLFeature::element_index_uint);
284 case WebGLExtensionID::OES_fbo_render_mipmap:
285 return WebGLExtensionFBORenderMipmap::IsSupported(this);
287 case WebGLExtensionID::OES_standard_derivatives:
288 if (IsWebGL2()) return false;
289 return gl->IsSupported(gl::GLFeature::standard_derivatives);
291 case WebGLExtensionID::OES_texture_float:
292 return WebGLExtensionTextureFloat::IsSupported(this);
294 case WebGLExtensionID::OES_texture_float_linear:
295 return gl->IsSupported(gl::GLFeature::texture_float_linear);
297 case WebGLExtensionID::OES_texture_half_float:
298 return WebGLExtensionTextureHalfFloat::IsSupported(this);
300 case WebGLExtensionID::OES_texture_half_float_linear:
301 if (IsWebGL2()) return false;
302 return gl->IsSupported(gl::GLFeature::texture_half_float_linear);
304 case WebGLExtensionID::OES_vertex_array_object:
305 return !IsWebGL2(); // Always supported in webgl1.
307 // OVR_
308 case WebGLExtensionID::OVR_multiview2:
309 return WebGLExtensionMultiview::IsSupported(this);
311 // WEBGL_
312 case WebGLExtensionID::WEBGL_color_buffer_float:
313 return WebGLExtensionColorBufferFloat::IsSupported(this);
315 case WebGLExtensionID::WEBGL_compressed_texture_astc:
316 return WebGLExtensionCompressedTextureASTC::IsSupported(this);
318 case WebGLExtensionID::WEBGL_compressed_texture_etc:
319 return gl->IsSupported(gl::GLFeature::ES3_compatibility) &&
320 !gl->IsANGLE();
322 case WebGLExtensionID::WEBGL_compressed_texture_etc1:
323 return gl->IsExtensionSupported(
324 gl::GLContext::OES_compressed_ETC1_RGB8_texture) &&
325 !gl->IsANGLE();
327 case WebGLExtensionID::WEBGL_compressed_texture_pvrtc:
328 return gl->IsExtensionSupported(
329 gl::GLContext::IMG_texture_compression_pvrtc);
331 case WebGLExtensionID::WEBGL_compressed_texture_s3tc:
332 return WebGLExtensionCompressedTextureS3TC::IsSupported(this);
334 case WebGLExtensionID::WEBGL_compressed_texture_s3tc_srgb:
335 return WebGLExtensionCompressedTextureS3TC_SRGB::IsSupported(this);
337 case WebGLExtensionID::WEBGL_depth_texture:
338 return WebGLExtensionDepthTexture::IsSupported(this);
340 case WebGLExtensionID::WEBGL_draw_buffers:
341 return WebGLExtensionDrawBuffers::IsSupported(this);
343 case WebGLExtensionID::WEBGL_explicit_present:
344 return WebGLExtensionExplicitPresent::IsSupported(this);
346 case WebGLExtensionID::Max:
347 break;
350 MOZ_CRASH();
353 bool WebGLContext::IsExtensionExplicit(const WebGLExtensionID ext) const {
354 return mExtensions[ext] && mExtensions[ext]->IsExplicit();
357 void WebGLContext::WarnIfImplicit(const WebGLExtensionID ext) const {
358 const auto& extension = mExtensions[ext];
359 if (!extension || extension->IsExplicit()) return;
361 GenerateWarning(
362 "Using format enabled by implicitly enabled extension: %s. "
363 "For maximal portability enable it explicitly.",
364 GetExtensionName(ext));
367 void WebGLContext::RequestExtension(const WebGLExtensionID ext,
368 const bool explicitly) {
369 const auto& limits = Limits();
370 if (!limits.supportedExtensions[ext]) return;
372 auto& slot = mExtensions[ext];
373 switch (ext) {
374 // ANGLE_
375 case WebGLExtensionID::ANGLE_instanced_arrays:
376 slot.reset(new WebGLExtensionInstancedArrays(this));
377 break;
379 // EXT_
380 case WebGLExtensionID::EXT_blend_minmax:
381 slot.reset(new WebGLExtensionBlendMinMax(this));
382 break;
383 case WebGLExtensionID::EXT_color_buffer_float:
384 slot.reset(new WebGLExtensionEXTColorBufferFloat(this));
385 break;
386 case WebGLExtensionID::EXT_color_buffer_half_float:
387 slot.reset(new WebGLExtensionColorBufferHalfFloat(this));
388 break;
389 case WebGLExtensionID::EXT_disjoint_timer_query:
390 slot.reset(new WebGLExtensionDisjointTimerQuery(this));
391 break;
392 case WebGLExtensionID::EXT_float_blend:
393 slot.reset(new WebGLExtensionFloatBlend(this));
394 break;
395 case WebGLExtensionID::EXT_frag_depth:
396 slot.reset(new WebGLExtensionFragDepth(this));
397 break;
398 case WebGLExtensionID::EXT_shader_texture_lod:
399 slot.reset(new WebGLExtensionShaderTextureLod(this));
400 break;
401 case WebGLExtensionID::EXT_sRGB:
402 slot.reset(new WebGLExtensionSRGB(this));
403 break;
404 case WebGLExtensionID::EXT_texture_compression_bptc:
405 slot.reset(new WebGLExtensionCompressedTextureBPTC(this));
406 break;
407 case WebGLExtensionID::EXT_texture_compression_rgtc:
408 slot.reset(new WebGLExtensionCompressedTextureRGTC(this));
409 break;
410 case WebGLExtensionID::EXT_texture_filter_anisotropic:
411 slot.reset(new WebGLExtensionTextureFilterAnisotropic(this));
412 break;
413 case WebGLExtensionID::EXT_texture_norm16:
414 slot.reset(new WebGLExtensionTextureNorm16(this));
415 break;
417 // MOZ_
418 case WebGLExtensionID::MOZ_debug:
419 slot.reset(new WebGLExtensionMOZDebug(this));
420 break;
422 // OES_
423 case WebGLExtensionID::OES_element_index_uint:
424 slot.reset(new WebGLExtensionElementIndexUint(this));
425 break;
426 case WebGLExtensionID::OES_fbo_render_mipmap:
427 slot.reset(new WebGLExtensionFBORenderMipmap(this));
428 break;
429 case WebGLExtensionID::OES_standard_derivatives:
430 slot.reset(new WebGLExtensionStandardDerivatives(this));
431 break;
432 case WebGLExtensionID::OES_texture_float:
433 slot.reset(new WebGLExtensionTextureFloat(this));
434 break;
435 case WebGLExtensionID::OES_texture_float_linear:
436 slot.reset(new WebGLExtensionTextureFloatLinear(this));
437 break;
438 case WebGLExtensionID::OES_texture_half_float:
439 slot.reset(new WebGLExtensionTextureHalfFloat(this));
440 break;
441 case WebGLExtensionID::OES_texture_half_float_linear:
442 slot.reset(new WebGLExtensionTextureHalfFloatLinear(this));
443 break;
444 case WebGLExtensionID::OES_vertex_array_object:
445 slot.reset(new WebGLExtensionVertexArray(this));
446 break;
448 // WEBGL_
449 case WebGLExtensionID::OVR_multiview2:
450 slot.reset(new WebGLExtensionMultiview(this));
451 break;
453 // WEBGL_
454 case WebGLExtensionID::WEBGL_color_buffer_float:
455 slot.reset(new WebGLExtensionColorBufferFloat(this));
456 break;
457 case WebGLExtensionID::WEBGL_compressed_texture_astc:
458 slot.reset(new WebGLExtensionCompressedTextureASTC(this));
459 break;
460 case WebGLExtensionID::WEBGL_compressed_texture_etc:
461 slot.reset(new WebGLExtensionCompressedTextureES3(this));
462 break;
463 case WebGLExtensionID::WEBGL_compressed_texture_etc1:
464 slot.reset(new WebGLExtensionCompressedTextureETC1(this));
465 break;
466 case WebGLExtensionID::WEBGL_compressed_texture_pvrtc:
467 slot.reset(new WebGLExtensionCompressedTexturePVRTC(this));
468 break;
469 case WebGLExtensionID::WEBGL_compressed_texture_s3tc:
470 slot.reset(new WebGLExtensionCompressedTextureS3TC(this));
471 break;
472 case WebGLExtensionID::WEBGL_compressed_texture_s3tc_srgb:
473 slot.reset(new WebGLExtensionCompressedTextureS3TC_SRGB(this));
474 break;
475 case WebGLExtensionID::WEBGL_debug_renderer_info:
476 slot.reset(new WebGLExtensionDebugRendererInfo(this));
477 break;
478 case WebGLExtensionID::WEBGL_debug_shaders:
479 slot.reset(new WebGLExtensionDebugShaders(this));
480 break;
481 case WebGLExtensionID::WEBGL_depth_texture:
482 slot.reset(new WebGLExtensionDepthTexture(this));
483 break;
484 case WebGLExtensionID::WEBGL_draw_buffers:
485 slot.reset(new WebGLExtensionDrawBuffers(this));
486 break;
487 case WebGLExtensionID::WEBGL_explicit_present:
488 slot.reset(new WebGLExtensionExplicitPresent(this));
489 break;
490 case WebGLExtensionID::WEBGL_lose_context:
491 slot.reset(new WebGLExtensionLoseContext(this));
492 break;
494 case WebGLExtensionID::Max:
495 MOZ_CRASH();
497 MOZ_ASSERT(slot);
498 const auto& obj = slot;
500 if (explicitly && !obj->IsExplicit()) {
501 obj->SetExplicit();
504 // Also enable implied extensions.
505 switch (ext) {
506 case WebGLExtensionID::EXT_color_buffer_float:
507 RequestExtension(WebGLExtensionID::EXT_float_blend, false);
508 break;
510 case WebGLExtensionID::OES_texture_float:
511 RequestExtension(WebGLExtensionID::EXT_float_blend, false);
512 RequestExtension(WebGLExtensionID::WEBGL_color_buffer_float, false);
513 break;
515 case WebGLExtensionID::OES_texture_half_float:
516 RequestExtension(WebGLExtensionID::EXT_color_buffer_half_float, false);
517 break;
519 case WebGLExtensionID::WEBGL_color_buffer_float:
520 RequestExtension(WebGLExtensionID::EXT_float_blend, false);
521 break;
523 default:
524 break;
528 } // namespace mozilla