/src/mozilla-central/dom/canvas/WebGLContextExtensions.cpp
Line | Count | Source (jump to first uncovered line) |
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/. */ |
5 | | |
6 | | #include "WebGLContext.h" |
7 | | #include "WebGLContextUtils.h" |
8 | | #include "WebGLExtensions.h" |
9 | | #include "gfxPrefs.h" |
10 | | #include "GLContext.h" |
11 | | |
12 | | #include "nsString.h" |
13 | | #include "nsContentUtils.h" |
14 | | #include "mozilla/Preferences.h" |
15 | | #include "mozilla/dom/BindingDeclarations.h" |
16 | | #include "AccessCheck.h" |
17 | | |
18 | | namespace mozilla { |
19 | | |
20 | | /*static*/ const char* |
21 | | WebGLContext::GetExtensionString(WebGLExtensionID ext) |
22 | 0 | { |
23 | 0 | typedef EnumeratedArray<WebGLExtensionID, WebGLExtensionID::Max, |
24 | 0 | const char*> names_array_t; |
25 | 0 |
|
26 | 0 | static names_array_t sExtensionNamesEnumeratedArray; |
27 | 0 | static bool initialized = false; |
28 | 0 |
|
29 | 0 | if (!initialized) { |
30 | 0 | initialized = true; |
31 | 0 |
|
32 | 0 | #define WEBGL_EXTENSION_IDENTIFIER(x) \ |
33 | 0 | sExtensionNamesEnumeratedArray[WebGLExtensionID::x] = #x; |
34 | 0 |
|
35 | 0 | WEBGL_EXTENSION_IDENTIFIER(ANGLE_instanced_arrays) |
36 | 0 | WEBGL_EXTENSION_IDENTIFIER(EXT_blend_minmax) |
37 | 0 | WEBGL_EXTENSION_IDENTIFIER(EXT_color_buffer_float) |
38 | 0 | WEBGL_EXTENSION_IDENTIFIER(EXT_color_buffer_half_float) |
39 | 0 | WEBGL_EXTENSION_IDENTIFIER(EXT_frag_depth) |
40 | 0 | WEBGL_EXTENSION_IDENTIFIER(EXT_shader_texture_lod) |
41 | 0 | WEBGL_EXTENSION_IDENTIFIER(EXT_sRGB) |
42 | 0 | WEBGL_EXTENSION_IDENTIFIER(EXT_texture_filter_anisotropic) |
43 | 0 | WEBGL_EXTENSION_IDENTIFIER(EXT_disjoint_timer_query) |
44 | 0 | WEBGL_EXTENSION_IDENTIFIER(MOZ_debug) |
45 | 0 | WEBGL_EXTENSION_IDENTIFIER(OES_element_index_uint) |
46 | 0 | WEBGL_EXTENSION_IDENTIFIER(OES_standard_derivatives) |
47 | 0 | WEBGL_EXTENSION_IDENTIFIER(OES_texture_float) |
48 | 0 | WEBGL_EXTENSION_IDENTIFIER(OES_texture_float_linear) |
49 | 0 | WEBGL_EXTENSION_IDENTIFIER(OES_texture_half_float) |
50 | 0 | WEBGL_EXTENSION_IDENTIFIER(OES_texture_half_float_linear) |
51 | 0 | WEBGL_EXTENSION_IDENTIFIER(OES_vertex_array_object) |
52 | 0 | WEBGL_EXTENSION_IDENTIFIER(WEBGL_color_buffer_float) |
53 | 0 | WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_astc) |
54 | 0 | WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_atc) |
55 | 0 | WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_etc) |
56 | 0 | WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_etc1) |
57 | 0 | WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_pvrtc) |
58 | 0 | WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_s3tc) |
59 | 0 | WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_s3tc_srgb) |
60 | 0 | WEBGL_EXTENSION_IDENTIFIER(WEBGL_debug_renderer_info) |
61 | 0 | WEBGL_EXTENSION_IDENTIFIER(WEBGL_debug_shaders) |
62 | 0 | WEBGL_EXTENSION_IDENTIFIER(WEBGL_depth_texture) |
63 | 0 | WEBGL_EXTENSION_IDENTIFIER(WEBGL_draw_buffers) |
64 | 0 | WEBGL_EXTENSION_IDENTIFIER(WEBGL_lose_context) |
65 | 0 |
|
66 | 0 | #undef WEBGL_EXTENSION_IDENTIFIER |
67 | 0 | } |
68 | 0 |
|
69 | 0 | return sExtensionNamesEnumeratedArray[ext]; |
70 | 0 | } |
71 | | |
72 | | bool |
73 | | WebGLContext::IsExtensionEnabled(WebGLExtensionID ext) const |
74 | 0 | { |
75 | 0 | return mExtensions[ext]; |
76 | 0 | } |
77 | | |
78 | | bool WebGLContext::IsExtensionSupported(dom::CallerType callerType, |
79 | | WebGLExtensionID ext) const |
80 | 0 | { |
81 | 0 | bool allowPrivilegedExts = false; |
82 | 0 |
|
83 | 0 | // Chrome contexts need access to debug information even when |
84 | 0 | // webgl.disable-extensions is set. This is used in the graphics |
85 | 0 | // section of about:support |
86 | 0 | if (callerType == dom::CallerType::System) { |
87 | 0 | allowPrivilegedExts = true; |
88 | 0 | } |
89 | 0 |
|
90 | 0 | if (gfxPrefs::WebGLPrivilegedExtensionsEnabled()) { |
91 | 0 | allowPrivilegedExts = true; |
92 | 0 | } |
93 | 0 |
|
94 | 0 | if (allowPrivilegedExts) { |
95 | 0 | switch (ext) { |
96 | 0 | case WebGLExtensionID::EXT_disjoint_timer_query: |
97 | 0 | return WebGLExtensionDisjointTimerQuery::IsSupported(this); |
98 | 0 | case WebGLExtensionID::MOZ_debug: |
99 | 0 | return true; |
100 | 0 | case WebGLExtensionID::WEBGL_debug_renderer_info: |
101 | 0 | return true; |
102 | 0 | case WebGLExtensionID::WEBGL_debug_shaders: |
103 | 0 | return true; |
104 | 0 | default: |
105 | 0 | // For warnings-as-errors. |
106 | 0 | break; |
107 | 0 | } |
108 | 0 | } |
109 | 0 | |
110 | 0 | return IsExtensionSupported(ext); |
111 | 0 | } |
112 | | |
113 | | bool |
114 | | WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const |
115 | 0 | { |
116 | 0 | if (mDisableExtensions) |
117 | 0 | return false; |
118 | 0 | |
119 | 0 | // Extensions for both WebGL 1 and 2. |
120 | 0 | switch (ext) { |
121 | 0 | // In alphabetical order |
122 | 0 | // EXT_ |
123 | 0 | case WebGLExtensionID::EXT_texture_filter_anisotropic: |
124 | 0 | return gl->IsExtensionSupported(gl::GLContext::EXT_texture_filter_anisotropic); |
125 | 0 |
|
126 | 0 | // OES_ |
127 | 0 | case WebGLExtensionID::OES_texture_float_linear: |
128 | 0 | return gl->IsSupported(gl::GLFeature::texture_float_linear); |
129 | 0 |
|
130 | 0 | // WEBGL_ |
131 | 0 | case WebGLExtensionID::WEBGL_compressed_texture_astc: |
132 | 0 | return WebGLExtensionCompressedTextureASTC::IsSupported(this); |
133 | 0 | case WebGLExtensionID::WEBGL_compressed_texture_atc: |
134 | 0 | return gl->IsExtensionSupported(gl::GLContext::AMD_compressed_ATC_texture); |
135 | 0 | case WebGLExtensionID::WEBGL_compressed_texture_etc: |
136 | 0 | return gl->IsSupported(gl::GLFeature::ES3_compatibility) && |
137 | 0 | !gl->IsANGLE(); |
138 | 0 | case WebGLExtensionID::WEBGL_compressed_texture_etc1: |
139 | 0 | return gl->IsExtensionSupported(gl::GLContext::OES_compressed_ETC1_RGB8_texture) && |
140 | 0 | !gl->IsANGLE(); |
141 | 0 | case WebGLExtensionID::WEBGL_compressed_texture_pvrtc: |
142 | 0 | return gl->IsExtensionSupported(gl::GLContext::IMG_texture_compression_pvrtc); |
143 | 0 | case WebGLExtensionID::WEBGL_compressed_texture_s3tc: |
144 | 0 | return WebGLExtensionCompressedTextureS3TC::IsSupported(this); |
145 | 0 | case WebGLExtensionID::WEBGL_compressed_texture_s3tc_srgb: |
146 | 0 | return WebGLExtensionCompressedTextureS3TC_SRGB::IsSupported(this); |
147 | 0 | case WebGLExtensionID::WEBGL_debug_renderer_info: |
148 | 0 | return Preferences::GetBool("webgl.enable-debug-renderer-info", false) && |
149 | 0 | !nsContentUtils::ShouldResistFingerprinting(); |
150 | 0 | case WebGLExtensionID::WEBGL_debug_shaders: |
151 | 0 | return !nsContentUtils::ShouldResistFingerprinting(); |
152 | 0 | case WebGLExtensionID::WEBGL_lose_context: |
153 | 0 | // We always support this extension. |
154 | 0 | return true; |
155 | 0 |
|
156 | 0 | default: |
157 | 0 | // For warnings-as-errors. |
158 | 0 | break; |
159 | 0 | } |
160 | 0 | |
161 | 0 | if (IsWebGL2()) { |
162 | 0 | // WebGL2-only extensions |
163 | 0 | switch (ext) { |
164 | 0 | // EXT_ |
165 | 0 | case WebGLExtensionID::EXT_color_buffer_float: |
166 | 0 | return WebGLExtensionEXTColorBufferFloat::IsSupported(this); |
167 | 0 |
|
168 | 0 | default: |
169 | 0 | // For warnings-as-errors. |
170 | 0 | break; |
171 | 0 | } |
172 | 0 | } else { |
173 | 0 | // WebGL1-only extensions |
174 | 0 | switch (ext) { |
175 | 0 | // ANGLE_ |
176 | 0 | case WebGLExtensionID::ANGLE_instanced_arrays: |
177 | 0 | return WebGLExtensionInstancedArrays::IsSupported(this); |
178 | 0 |
|
179 | 0 | // EXT_ |
180 | 0 | case WebGLExtensionID::EXT_blend_minmax: |
181 | 0 | return WebGLExtensionBlendMinMax::IsSupported(this); |
182 | 0 | case WebGLExtensionID::EXT_color_buffer_half_float: |
183 | 0 | return WebGLExtensionColorBufferHalfFloat::IsSupported(this); |
184 | 0 | case WebGLExtensionID::EXT_frag_depth: |
185 | 0 | return WebGLExtensionFragDepth::IsSupported(this); |
186 | 0 | case WebGLExtensionID::EXT_shader_texture_lod: |
187 | 0 | return gl->IsSupported(gl::GLFeature::shader_texture_lod); |
188 | 0 | case WebGLExtensionID::EXT_sRGB: |
189 | 0 | return WebGLExtensionSRGB::IsSupported(this); |
190 | 0 |
|
191 | 0 | // OES_ |
192 | 0 | case WebGLExtensionID::OES_element_index_uint: |
193 | 0 | return gl->IsSupported(gl::GLFeature::element_index_uint); |
194 | 0 | case WebGLExtensionID::OES_standard_derivatives: |
195 | 0 | return gl->IsSupported(gl::GLFeature::standard_derivatives); |
196 | 0 | case WebGLExtensionID::OES_texture_float: |
197 | 0 | return WebGLExtensionTextureFloat::IsSupported(this); |
198 | 0 | case WebGLExtensionID::OES_texture_half_float: |
199 | 0 | return WebGLExtensionTextureHalfFloat::IsSupported(this); |
200 | 0 | case WebGLExtensionID::OES_texture_half_float_linear: |
201 | 0 | return gl->IsSupported(gl::GLFeature::texture_half_float_linear); |
202 | 0 |
|
203 | 0 | case WebGLExtensionID::OES_vertex_array_object: |
204 | 0 | return true; |
205 | 0 |
|
206 | 0 | // WEBGL_ |
207 | 0 | case WebGLExtensionID::WEBGL_color_buffer_float: |
208 | 0 | return WebGLExtensionColorBufferFloat::IsSupported(this); |
209 | 0 | case WebGLExtensionID::WEBGL_depth_texture: |
210 | 0 | // WEBGL_depth_texture supports DEPTH_STENCIL textures |
211 | 0 | if (!gl->IsSupported(gl::GLFeature::packed_depth_stencil)) |
212 | 0 | return false; |
213 | 0 | |
214 | 0 | return gl->IsSupported(gl::GLFeature::depth_texture) || |
215 | 0 | gl->IsExtensionSupported(gl::GLContext::ANGLE_depth_texture); |
216 | 0 | case WebGLExtensionID::WEBGL_draw_buffers: |
217 | 0 | return WebGLExtensionDrawBuffers::IsSupported(this); |
218 | 0 | default: |
219 | 0 | // For warnings-as-errors. |
220 | 0 | break; |
221 | 0 | } |
222 | 0 | |
223 | 0 | if (gfxPrefs::WebGLDraftExtensionsEnabled()) { |
224 | 0 | /* |
225 | 0 | switch (ext) { |
226 | 0 | default: |
227 | 0 | // For warnings-as-errors. |
228 | 0 | break; |
229 | 0 | } |
230 | 0 | */ |
231 | 0 | } |
232 | 0 | } |
233 | 0 |
|
234 | 0 | return false; |
235 | 0 | } |
236 | | |
237 | | static bool |
238 | | CompareWebGLExtensionName(const nsACString& name, const char* other) |
239 | 0 | { |
240 | 0 | return name.Equals(other, nsCaseInsensitiveCStringComparator()); |
241 | 0 | } |
242 | | |
243 | | WebGLExtensionBase* |
244 | | WebGLContext::EnableSupportedExtension(dom::CallerType callerType, |
245 | | WebGLExtensionID ext) |
246 | 0 | { |
247 | 0 | if (!IsExtensionEnabled(ext)) { |
248 | 0 | if (!IsExtensionSupported(callerType, ext)) |
249 | 0 | return nullptr; |
250 | 0 | |
251 | 0 | EnableExtension(ext); |
252 | 0 | } |
253 | 0 |
|
254 | 0 | return mExtensions[ext]; |
255 | 0 | } |
256 | | |
257 | | void |
258 | | WebGLContext::GetExtension(JSContext* cx, |
259 | | const nsAString& wideName, |
260 | | JS::MutableHandle<JSObject*> retval, |
261 | | dom::CallerType callerType, |
262 | | ErrorResult& rv) |
263 | 0 | { |
264 | 0 | retval.set(nullptr); |
265 | 0 | const FuncScope funcScope(*this, "getExtension"); |
266 | 0 | if (IsContextLost()) |
267 | 0 | return; |
268 | 0 | |
269 | 0 | NS_LossyConvertUTF16toASCII name(wideName); |
270 | 0 |
|
271 | 0 | WebGLExtensionID ext = WebGLExtensionID::Unknown; |
272 | 0 |
|
273 | 0 | // step 1: figure what extension is wanted |
274 | 0 | for (size_t i = 0; i < size_t(WebGLExtensionID::Max); i++) { |
275 | 0 | WebGLExtensionID extension = WebGLExtensionID(i); |
276 | 0 |
|
277 | 0 | if (CompareWebGLExtensionName(name, GetExtensionString(extension))) { |
278 | 0 | ext = extension; |
279 | 0 | break; |
280 | 0 | } |
281 | 0 | } |
282 | 0 |
|
283 | 0 | if (ext == WebGLExtensionID::Unknown) |
284 | 0 | return; |
285 | 0 | |
286 | 0 | // step 2: check if the extension is supported |
287 | 0 | if (!IsExtensionSupported(callerType, ext)) |
288 | 0 | return; |
289 | 0 | |
290 | 0 | // step 3: if the extension hadn't been previously been created, create it now, thus enabling it |
291 | 0 | WebGLExtensionBase* extObj = EnableSupportedExtension(callerType, ext); |
292 | 0 | if (!extObj) |
293 | 0 | return; |
294 | 0 | |
295 | 0 | // Step 4: Enable any implied extensions. |
296 | 0 | switch (ext) { |
297 | 0 | case WebGLExtensionID::OES_texture_float: |
298 | 0 | EnableSupportedExtension(callerType, |
299 | 0 | WebGLExtensionID::WEBGL_color_buffer_float); |
300 | 0 | break; |
301 | 0 |
|
302 | 0 | case WebGLExtensionID::OES_texture_half_float: |
303 | 0 | EnableSupportedExtension(callerType, |
304 | 0 | WebGLExtensionID::EXT_color_buffer_half_float); |
305 | 0 | break; |
306 | 0 |
|
307 | 0 | default: |
308 | 0 | break; |
309 | 0 | } |
310 | 0 | |
311 | 0 | retval.set(WebGLObjectAsJSObject(cx, extObj, rv)); |
312 | 0 | } |
313 | | |
314 | | void |
315 | | WebGLContext::EnableExtension(WebGLExtensionID ext) |
316 | 0 | { |
317 | 0 | MOZ_ASSERT(IsExtensionEnabled(ext) == false); |
318 | 0 |
|
319 | 0 | WebGLExtensionBase* obj = nullptr; |
320 | 0 | switch (ext) { |
321 | 0 | // ANGLE_ |
322 | 0 | case WebGLExtensionID::ANGLE_instanced_arrays: |
323 | 0 | obj = new WebGLExtensionInstancedArrays(this); |
324 | 0 | break; |
325 | 0 |
|
326 | 0 | // EXT_ |
327 | 0 | case WebGLExtensionID::EXT_blend_minmax: |
328 | 0 | obj = new WebGLExtensionBlendMinMax(this); |
329 | 0 | break; |
330 | 0 | case WebGLExtensionID::EXT_color_buffer_float: |
331 | 0 | obj = new WebGLExtensionEXTColorBufferFloat(this); |
332 | 0 | break; |
333 | 0 | case WebGLExtensionID::EXT_color_buffer_half_float: |
334 | 0 | obj = new WebGLExtensionColorBufferHalfFloat(this); |
335 | 0 | break; |
336 | 0 | case WebGLExtensionID::EXT_disjoint_timer_query: |
337 | 0 | obj = new WebGLExtensionDisjointTimerQuery(this); |
338 | 0 | break; |
339 | 0 | case WebGLExtensionID::EXT_frag_depth: |
340 | 0 | obj = new WebGLExtensionFragDepth(this); |
341 | 0 | break; |
342 | 0 | case WebGLExtensionID::EXT_shader_texture_lod: |
343 | 0 | obj = new WebGLExtensionShaderTextureLod(this); |
344 | 0 | break; |
345 | 0 | case WebGLExtensionID::EXT_sRGB: |
346 | 0 | obj = new WebGLExtensionSRGB(this); |
347 | 0 | break; |
348 | 0 | case WebGLExtensionID::EXT_texture_filter_anisotropic: |
349 | 0 | obj = new WebGLExtensionTextureFilterAnisotropic(this); |
350 | 0 | break; |
351 | 0 |
|
352 | 0 | // MOZ_ |
353 | 0 | case WebGLExtensionID::MOZ_debug: |
354 | 0 | obj = new WebGLExtensionMOZDebug(this); |
355 | 0 | break; |
356 | 0 |
|
357 | 0 | // OES_ |
358 | 0 | case WebGLExtensionID::OES_element_index_uint: |
359 | 0 | obj = new WebGLExtensionElementIndexUint(this); |
360 | 0 | break; |
361 | 0 | case WebGLExtensionID::OES_standard_derivatives: |
362 | 0 | obj = new WebGLExtensionStandardDerivatives(this); |
363 | 0 | break; |
364 | 0 | case WebGLExtensionID::OES_texture_float: |
365 | 0 | obj = new WebGLExtensionTextureFloat(this); |
366 | 0 | break; |
367 | 0 | case WebGLExtensionID::OES_texture_float_linear: |
368 | 0 | obj = new WebGLExtensionTextureFloatLinear(this); |
369 | 0 | break; |
370 | 0 | case WebGLExtensionID::OES_texture_half_float: |
371 | 0 | obj = new WebGLExtensionTextureHalfFloat(this); |
372 | 0 | break; |
373 | 0 | case WebGLExtensionID::OES_texture_half_float_linear: |
374 | 0 | obj = new WebGLExtensionTextureHalfFloatLinear(this); |
375 | 0 | break; |
376 | 0 | case WebGLExtensionID::OES_vertex_array_object: |
377 | 0 | obj = new WebGLExtensionVertexArray(this); |
378 | 0 | break; |
379 | 0 |
|
380 | 0 | // WEBGL_ |
381 | 0 | case WebGLExtensionID::WEBGL_color_buffer_float: |
382 | 0 | obj = new WebGLExtensionColorBufferFloat(this); |
383 | 0 | break; |
384 | 0 | case WebGLExtensionID::WEBGL_compressed_texture_astc: |
385 | 0 | obj = new WebGLExtensionCompressedTextureASTC(this); |
386 | 0 | break; |
387 | 0 | case WebGLExtensionID::WEBGL_compressed_texture_atc: |
388 | 0 | obj = new WebGLExtensionCompressedTextureATC(this); |
389 | 0 | break; |
390 | 0 | case WebGLExtensionID::WEBGL_compressed_texture_etc: |
391 | 0 | obj = new WebGLExtensionCompressedTextureES3(this); |
392 | 0 | break; |
393 | 0 | case WebGLExtensionID::WEBGL_compressed_texture_etc1: |
394 | 0 | obj = new WebGLExtensionCompressedTextureETC1(this); |
395 | 0 | break; |
396 | 0 | case WebGLExtensionID::WEBGL_compressed_texture_pvrtc: |
397 | 0 | obj = new WebGLExtensionCompressedTexturePVRTC(this); |
398 | 0 | break; |
399 | 0 | case WebGLExtensionID::WEBGL_compressed_texture_s3tc: |
400 | 0 | obj = new WebGLExtensionCompressedTextureS3TC(this); |
401 | 0 | break; |
402 | 0 | case WebGLExtensionID::WEBGL_compressed_texture_s3tc_srgb: |
403 | 0 | obj = new WebGLExtensionCompressedTextureS3TC_SRGB(this); |
404 | 0 | break; |
405 | 0 | case WebGLExtensionID::WEBGL_debug_renderer_info: |
406 | 0 | obj = new WebGLExtensionDebugRendererInfo(this); |
407 | 0 | break; |
408 | 0 | case WebGLExtensionID::WEBGL_debug_shaders: |
409 | 0 | obj = new WebGLExtensionDebugShaders(this); |
410 | 0 | break; |
411 | 0 | case WebGLExtensionID::WEBGL_depth_texture: |
412 | 0 | obj = new WebGLExtensionDepthTexture(this); |
413 | 0 | break; |
414 | 0 | case WebGLExtensionID::WEBGL_draw_buffers: |
415 | 0 | obj = new WebGLExtensionDrawBuffers(this); |
416 | 0 | break; |
417 | 0 | case WebGLExtensionID::WEBGL_lose_context: |
418 | 0 | obj = new WebGLExtensionLoseContext(this); |
419 | 0 | break; |
420 | 0 |
|
421 | 0 | default: |
422 | 0 | MOZ_ASSERT(false, "should not get there."); |
423 | 0 | } |
424 | 0 |
|
425 | 0 | mExtensions[ext] = obj; |
426 | 0 | } |
427 | | |
428 | | void |
429 | | WebGLContext::GetSupportedExtensions(dom::Nullable< nsTArray<nsString> >& retval, |
430 | | dom::CallerType callerType) |
431 | 0 | { |
432 | 0 | retval.SetNull(); |
433 | 0 | const FuncScope funcScope(*this, "getSupportedExtensions"); |
434 | 0 | if (IsContextLost()) |
435 | 0 | return; |
436 | 0 | |
437 | 0 | nsTArray<nsString>& arr = retval.SetValue(); |
438 | 0 |
|
439 | 0 | for (size_t i = 0; i < size_t(WebGLExtensionID::Max); i++) { |
440 | 0 | const auto extension = WebGLExtensionID(i); |
441 | 0 | if (extension == WebGLExtensionID::MOZ_debug) |
442 | 0 | continue; // Hide MOZ_debug from this list. |
443 | 0 | |
444 | 0 | if (IsExtensionSupported(callerType, extension)) { |
445 | 0 | const char* extStr = GetExtensionString(extension); |
446 | 0 | arr.AppendElement(NS_ConvertUTF8toUTF16(extStr)); |
447 | 0 | } |
448 | 0 | } |
449 | 0 | } |
450 | | |
451 | | } // namespace mozilla |