1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 "WebGLContextUtils.h"
8 #include "WebGLExtensions.h"
12 #include "mozilla/Preferences.h"
13 #include "AccessCheck.h"
17 /*static*/ const char*
18 WebGLContext::GetExtensionString(WebGLExtensionID ext
)
20 typedef EnumeratedArray
<WebGLExtensionID
, WebGLExtensionID::Max
,
21 const char*> names_array_t
;
23 static names_array_t sExtensionNamesEnumeratedArray
;
24 static bool initialized
= false;
29 #define WEBGL_EXTENSION_IDENTIFIER(x) \
30 sExtensionNamesEnumeratedArray[WebGLExtensionID::x] = #x;
32 WEBGL_EXTENSION_IDENTIFIER(ANGLE_instanced_arrays
)
33 WEBGL_EXTENSION_IDENTIFIER(EXT_blend_minmax
)
34 WEBGL_EXTENSION_IDENTIFIER(EXT_color_buffer_half_float
)
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_filter_anisotropic
)
39 WEBGL_EXTENSION_IDENTIFIER(OES_element_index_uint
)
40 WEBGL_EXTENSION_IDENTIFIER(OES_standard_derivatives
)
41 WEBGL_EXTENSION_IDENTIFIER(OES_texture_float
)
42 WEBGL_EXTENSION_IDENTIFIER(OES_texture_float_linear
)
43 WEBGL_EXTENSION_IDENTIFIER(OES_texture_half_float
)
44 WEBGL_EXTENSION_IDENTIFIER(OES_texture_half_float_linear
)
45 WEBGL_EXTENSION_IDENTIFIER(OES_vertex_array_object
)
46 WEBGL_EXTENSION_IDENTIFIER(WEBGL_color_buffer_float
)
47 WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_atc
)
48 WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_etc1
)
49 WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_pvrtc
)
50 WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_s3tc
)
51 WEBGL_EXTENSION_IDENTIFIER(WEBGL_debug_renderer_info
)
52 WEBGL_EXTENSION_IDENTIFIER(WEBGL_debug_shaders
)
53 WEBGL_EXTENSION_IDENTIFIER(WEBGL_depth_texture
)
54 WEBGL_EXTENSION_IDENTIFIER(WEBGL_draw_buffers
)
55 WEBGL_EXTENSION_IDENTIFIER(WEBGL_lose_context
)
57 #undef WEBGL_EXTENSION_IDENTIFIER
60 return sExtensionNamesEnumeratedArray
[ext
];
64 WebGLContext::IsExtensionEnabled(WebGLExtensionID ext
) const
66 return mExtensions
[ext
];
69 bool WebGLContext::IsExtensionSupported(JSContext
* cx
,
70 WebGLExtensionID ext
) const
72 bool allowPrivilegedExts
= false;
74 // Chrome contexts need access to debug information even when
75 // webgl.disable-extensions is set. This is used in the graphics
76 // section of about:support.
77 if (xpc::AccessCheck::isChrome(js::GetContextCompartment(cx
)))
78 allowPrivilegedExts
= true;
80 if (Preferences::GetBool("webgl.enable-privileged-extensions", false))
81 allowPrivilegedExts
= true;
83 if (allowPrivilegedExts
) {
85 case WebGLExtensionID::WEBGL_debug_renderer_info
:
87 case WebGLExtensionID::WEBGL_debug_shaders
:
90 // For warnings-as-errors.
95 return IsExtensionSupported(ext
);
99 WebGLContext::IsExtensionSupported(WebGLExtensionID ext
) const
101 if (mDisableExtensions
)
104 // In alphabetical order
107 case WebGLExtensionID::ANGLE_instanced_arrays
:
108 return WebGLExtensionInstancedArrays::IsSupported(this);
111 case WebGLExtensionID::EXT_blend_minmax
:
112 return WebGLExtensionBlendMinMax::IsSupported(this);
113 case WebGLExtensionID::EXT_color_buffer_half_float
:
114 return WebGLExtensionColorBufferHalfFloat::IsSupported(this);
115 case WebGLExtensionID::EXT_frag_depth
:
116 return WebGLExtensionFragDepth::IsSupported(this);
117 case WebGLExtensionID::EXT_shader_texture_lod
:
118 return gl
->IsExtensionSupported(gl::GLContext::EXT_shader_texture_lod
);
119 case WebGLExtensionID::EXT_sRGB
:
120 return WebGLExtensionSRGB::IsSupported(this);
121 case WebGLExtensionID::EXT_texture_filter_anisotropic
:
122 return gl
->IsExtensionSupported(gl::GLContext::EXT_texture_filter_anisotropic
);
125 case WebGLExtensionID::OES_element_index_uint
:
126 return gl
->IsSupported(gl::GLFeature::element_index_uint
);
127 case WebGLExtensionID::OES_standard_derivatives
:
128 return gl
->IsSupported(gl::GLFeature::standard_derivatives
);
129 case WebGLExtensionID::OES_texture_float
:
130 return gl
->IsSupported(gl::GLFeature::texture_float
);
131 case WebGLExtensionID::OES_texture_float_linear
:
132 return gl
->IsSupported(gl::GLFeature::texture_float_linear
);
133 case WebGLExtensionID::OES_texture_half_float
:
134 // If we have Feature::texture_half_float, we must not be on ES2
135 // and need to translate HALF_FLOAT_OES -> HALF_FLOAT. We do that
136 // right before making the relevant calls.
137 return gl
->IsExtensionSupported(gl::GLContext::OES_texture_half_float
) ||
138 gl
->IsSupported(gl::GLFeature::texture_half_float
);
140 case WebGLExtensionID::OES_texture_half_float_linear
:
141 return gl
->IsSupported(gl::GLFeature::texture_half_float_linear
);
142 case WebGLExtensionID::OES_vertex_array_object
:
146 case WebGLExtensionID::WEBGL_color_buffer_float
:
147 return WebGLExtensionColorBufferFloat::IsSupported(this);
148 case WebGLExtensionID::WEBGL_compressed_texture_atc
:
149 return gl
->IsExtensionSupported(gl::GLContext::AMD_compressed_ATC_texture
);
150 case WebGLExtensionID::WEBGL_compressed_texture_etc1
:
151 return gl
->IsExtensionSupported(gl::GLContext::OES_compressed_ETC1_RGB8_texture
);
152 case WebGLExtensionID::WEBGL_compressed_texture_pvrtc
:
153 return gl
->IsExtensionSupported(gl::GLContext::IMG_texture_compression_pvrtc
);
154 case WebGLExtensionID::WEBGL_compressed_texture_s3tc
:
155 if (gl
->IsExtensionSupported(gl::GLContext::EXT_texture_compression_s3tc
))
158 return gl
->IsExtensionSupported(gl::GLContext::EXT_texture_compression_dxt1
) &&
159 gl
->IsExtensionSupported(gl::GLContext::ANGLE_texture_compression_dxt3
) &&
160 gl
->IsExtensionSupported(gl::GLContext::ANGLE_texture_compression_dxt5
);
161 case WebGLExtensionID::WEBGL_depth_texture
:
162 // WEBGL_depth_texture supports DEPTH_STENCIL textures
163 if (!gl
->IsSupported(gl::GLFeature::packed_depth_stencil
))
166 return gl
->IsSupported(gl::GLFeature::depth_texture
) ||
167 gl
->IsExtensionSupported(gl::GLContext::ANGLE_depth_texture
);
168 case WebGLExtensionID::WEBGL_draw_buffers
:
169 return WebGLExtensionDrawBuffers::IsSupported(this);
170 case WebGLExtensionID::WEBGL_lose_context
:
171 // We always support this extension.
175 // For warnings-as-errors.
179 if (Preferences::GetBool("webgl.enable-draft-extensions", false) ||
185 // For warnings-as-errors.
195 CompareWebGLExtensionName(const nsACString
& name
, const char* other
)
197 return name
.Equals(other
, nsCaseInsensitiveCStringComparator());
201 WebGLContext::EnableSupportedExtension(JSContext
* js
, WebGLExtensionID ext
)
203 if (!IsExtensionEnabled(ext
)) {
204 if (!IsExtensionSupported(js
, ext
))
207 EnableExtension(ext
);
210 return mExtensions
[ext
];
214 WebGLContext::GetExtension(JSContext
* cx
, const nsAString
& wideName
,
215 JS::MutableHandle
<JSObject
*> retval
, ErrorResult
& rv
)
222 NS_LossyConvertUTF16toASCII
name(wideName
);
224 WebGLExtensionID ext
= WebGLExtensionID::Unknown
;
226 // step 1: figure what extension is wanted
227 for (size_t i
= 0; i
< size_t(WebGLExtensionID::Max
); i
++) {
228 WebGLExtensionID extension
= WebGLExtensionID(i
);
230 if (CompareWebGLExtensionName(name
, GetExtensionString(extension
))) {
236 if (ext
== WebGLExtensionID::Unknown
) {
237 // We keep backward compatibility for these deprecated vendor-prefixed
238 // alias. Do not add new ones anymore. Hide it behind the
239 // webgl.enable-draft-extensions flag instead.
241 if (CompareWebGLExtensionName(name
, "MOZ_WEBGL_lose_context")) {
242 ext
= WebGLExtensionID::WEBGL_lose_context
;
244 } else if (CompareWebGLExtensionName(name
, "MOZ_WEBGL_compressed_texture_s3tc")) {
245 ext
= WebGLExtensionID::WEBGL_compressed_texture_s3tc
;
247 } else if (CompareWebGLExtensionName(name
, "MOZ_WEBGL_compressed_texture_atc")) {
248 ext
= WebGLExtensionID::WEBGL_compressed_texture_atc
;
250 } else if (CompareWebGLExtensionName(name
, "MOZ_WEBGL_compressed_texture_pvrtc")) {
251 ext
= WebGLExtensionID::WEBGL_compressed_texture_pvrtc
;
253 } else if (CompareWebGLExtensionName(name
, "MOZ_WEBGL_depth_texture")) {
254 ext
= WebGLExtensionID::WEBGL_depth_texture
;
257 if (ext
!= WebGLExtensionID::Unknown
) {
258 GenerateWarning("getExtension('%s'): MOZ_ prefixed WebGL extension"
259 " strings are deprecated. Support for them will be"
260 " removed in the future. Use unprefixed extension"
261 " strings. To get draft extensions, set the"
262 " webgl.enable-draft-extensions preference.",
267 if (ext
== WebGLExtensionID::Unknown
)
270 // step 2: check if the extension is supported
271 if (!IsExtensionSupported(cx
, ext
))
274 // step 3: if the extension hadn't been previously been created, create it now, thus enabling it
275 WebGLExtensionBase
* extObj
= EnableSupportedExtension(cx
, ext
);
279 // Step 4: Enable any implied extensions.
281 case WebGLExtensionID::OES_texture_float
:
282 EnableSupportedExtension(cx
, WebGLExtensionID::WEBGL_color_buffer_float
);
285 case WebGLExtensionID::OES_texture_half_float
:
286 EnableSupportedExtension(cx
, WebGLExtensionID::EXT_color_buffer_half_float
);
293 retval
.set(WebGLObjectAsJSObject(cx
, extObj
, rv
));
297 WebGLContext::EnableExtension(WebGLExtensionID ext
)
299 MOZ_ASSERT(IsExtensionEnabled(ext
) == false);
301 WebGLExtensionBase
* obj
= nullptr;
304 case WebGLExtensionID::ANGLE_instanced_arrays
:
305 obj
= new WebGLExtensionInstancedArrays(this);
309 case WebGLExtensionID::EXT_blend_minmax
:
310 obj
= new WebGLExtensionBlendMinMax(this);
312 case WebGLExtensionID::EXT_color_buffer_half_float
:
313 obj
= new WebGLExtensionColorBufferHalfFloat(this);
315 case WebGLExtensionID::EXT_frag_depth
:
316 obj
= new WebGLExtensionFragDepth(this);
318 case WebGLExtensionID::EXT_shader_texture_lod
:
319 obj
= new WebGLExtensionShaderTextureLod(this);
321 case WebGLExtensionID::EXT_sRGB
:
322 obj
= new WebGLExtensionSRGB(this);
324 case WebGLExtensionID::EXT_texture_filter_anisotropic
:
325 obj
= new WebGLExtensionTextureFilterAnisotropic(this);
329 case WebGLExtensionID::OES_element_index_uint
:
330 obj
= new WebGLExtensionElementIndexUint(this);
332 case WebGLExtensionID::OES_standard_derivatives
:
333 obj
= new WebGLExtensionStandardDerivatives(this);
335 case WebGLExtensionID::OES_texture_float
:
336 obj
= new WebGLExtensionTextureFloat(this);
338 case WebGLExtensionID::OES_texture_float_linear
:
339 obj
= new WebGLExtensionTextureFloatLinear(this);
341 case WebGLExtensionID::OES_texture_half_float
:
342 obj
= new WebGLExtensionTextureHalfFloat(this);
344 case WebGLExtensionID::OES_texture_half_float_linear
:
345 obj
= new WebGLExtensionTextureHalfFloatLinear(this);
347 case WebGLExtensionID::OES_vertex_array_object
:
348 obj
= new WebGLExtensionVertexArray(this);
352 case WebGLExtensionID::WEBGL_color_buffer_float
:
353 obj
= new WebGLExtensionColorBufferFloat(this);
355 case WebGLExtensionID::WEBGL_compressed_texture_atc
:
356 obj
= new WebGLExtensionCompressedTextureATC(this);
358 case WebGLExtensionID::WEBGL_compressed_texture_etc1
:
359 obj
= new WebGLExtensionCompressedTextureETC1(this);
361 case WebGLExtensionID::WEBGL_compressed_texture_pvrtc
:
362 obj
= new WebGLExtensionCompressedTexturePVRTC(this);
364 case WebGLExtensionID::WEBGL_compressed_texture_s3tc
:
365 obj
= new WebGLExtensionCompressedTextureS3TC(this);
367 case WebGLExtensionID::WEBGL_debug_renderer_info
:
368 obj
= new WebGLExtensionDebugRendererInfo(this);
370 case WebGLExtensionID::WEBGL_debug_shaders
:
371 obj
= new WebGLExtensionDebugShaders(this);
373 case WebGLExtensionID::WEBGL_depth_texture
:
374 obj
= new WebGLExtensionDepthTexture(this);
376 case WebGLExtensionID::WEBGL_draw_buffers
:
377 obj
= new WebGLExtensionDrawBuffers(this);
379 case WebGLExtensionID::WEBGL_lose_context
:
380 obj
= new WebGLExtensionLoseContext(this);
384 MOZ_ASSERT(false, "should not get there.");
387 mExtensions
[ext
] = obj
;
391 WebGLContext::GetSupportedExtensions(JSContext
* cx
,
392 Nullable
< nsTArray
<nsString
> >& retval
)
398 nsTArray
<nsString
>& arr
= retval
.SetValue();
400 for (size_t i
= 0; i
< size_t(WebGLExtensionID::Max
); i
++) {
401 WebGLExtensionID extension
= WebGLExtensionID(i
);
403 if (IsExtensionSupported(cx
, extension
)) {
404 const char* extStr
= GetExtensionString(extension
);
405 arr
.AppendElement(NS_ConvertUTF8toUTF16(extStr
));
410 * We keep backward compatibility for these deprecated vendor-prefixed
411 * alias. Do not add new ones anymore. Hide it behind the
412 * webgl.enable-draft-extensions flag instead.
414 if (IsExtensionSupported(cx
, WebGLExtensionID::WEBGL_lose_context
))
415 arr
.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_lose_context"));
416 if (IsExtensionSupported(cx
, WebGLExtensionID::WEBGL_compressed_texture_s3tc
))
417 arr
.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_s3tc"));
418 if (IsExtensionSupported(cx
, WebGLExtensionID::WEBGL_compressed_texture_atc
))
419 arr
.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_atc"));
420 if (IsExtensionSupported(cx
, WebGLExtensionID::WEBGL_compressed_texture_pvrtc
))
421 arr
.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_pvrtc"));
422 if (IsExtensionSupported(cx
, WebGLExtensionID::WEBGL_depth_texture
))
423 arr
.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_depth_texture"));
426 } // namespace mozilla