Bumping manifests a=b2g-bump
[gecko.git] / dom / canvas / WebGLContextExtensions.cpp
blob56cedb6760062c93afd757394e56e91063e80d22
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"
9 #include "GLContext.h"
11 #include "nsString.h"
12 #include "mozilla/Preferences.h"
13 #include "AccessCheck.h"
15 namespace mozilla {
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;
26 if (!initialized) {
27 initialized = true;
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];
63 bool
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) {
84 switch (ext) {
85 case WebGLExtensionID::WEBGL_debug_renderer_info:
86 return true;
87 case WebGLExtensionID::WEBGL_debug_shaders:
88 return true;
89 default:
90 // For warnings-as-errors.
91 break;
95 return IsExtensionSupported(ext);
98 bool
99 WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const
101 if (mDisableExtensions)
102 return false;
104 // In alphabetical order
105 switch (ext) {
106 // ANGLE_
107 case WebGLExtensionID::ANGLE_instanced_arrays:
108 return WebGLExtensionInstancedArrays::IsSupported(this);
110 // EXT_
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);
124 // OES_
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:
143 return true;
145 // WEBGL_
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))
156 return true;
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))
164 return false;
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.
172 return true;
174 default:
175 // For warnings-as-errors.
176 break;
179 if (Preferences::GetBool("webgl.enable-draft-extensions", false) ||
180 IsWebGL2())
182 /* None for now.
183 switch (ext) {
184 default:
185 // For warnings-as-errors.
186 break;
191 return false;
194 static bool
195 CompareWebGLExtensionName(const nsACString& name, const char* other)
197 return name.Equals(other, nsCaseInsensitiveCStringComparator());
200 WebGLExtensionBase*
201 WebGLContext::EnableSupportedExtension(JSContext* js, WebGLExtensionID ext)
203 if (!IsExtensionEnabled(ext)) {
204 if (!IsExtensionSupported(js, ext))
205 return nullptr;
207 EnableExtension(ext);
210 return mExtensions[ext];
213 void
214 WebGLContext::GetExtension(JSContext* cx, const nsAString& wideName,
215 JS::MutableHandle<JSObject*> retval, ErrorResult& rv)
217 retval.set(nullptr);
219 if (IsContextLost())
220 return;
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))) {
231 ext = extension;
232 break;
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.",
263 name.get());
267 if (ext == WebGLExtensionID::Unknown)
268 return;
270 // step 2: check if the extension is supported
271 if (!IsExtensionSupported(cx, ext))
272 return;
274 // step 3: if the extension hadn't been previously been created, create it now, thus enabling it
275 WebGLExtensionBase* extObj = EnableSupportedExtension(cx, ext);
276 if (!extObj)
277 return;
279 // Step 4: Enable any implied extensions.
280 switch (ext) {
281 case WebGLExtensionID::OES_texture_float:
282 EnableSupportedExtension(cx, WebGLExtensionID::WEBGL_color_buffer_float);
283 break;
285 case WebGLExtensionID::OES_texture_half_float:
286 EnableSupportedExtension(cx, WebGLExtensionID::EXT_color_buffer_half_float);
287 break;
289 default:
290 break;
293 retval.set(WebGLObjectAsJSObject(cx, extObj, rv));
296 void
297 WebGLContext::EnableExtension(WebGLExtensionID ext)
299 MOZ_ASSERT(IsExtensionEnabled(ext) == false);
301 WebGLExtensionBase* obj = nullptr;
302 switch (ext) {
303 // ANGLE_
304 case WebGLExtensionID::ANGLE_instanced_arrays:
305 obj = new WebGLExtensionInstancedArrays(this);
306 break;
308 // EXT_
309 case WebGLExtensionID::EXT_blend_minmax:
310 obj = new WebGLExtensionBlendMinMax(this);
311 break;
312 case WebGLExtensionID::EXT_color_buffer_half_float:
313 obj = new WebGLExtensionColorBufferHalfFloat(this);
314 break;
315 case WebGLExtensionID::EXT_frag_depth:
316 obj = new WebGLExtensionFragDepth(this);
317 break;
318 case WebGLExtensionID::EXT_shader_texture_lod:
319 obj = new WebGLExtensionShaderTextureLod(this);
320 break;
321 case WebGLExtensionID::EXT_sRGB:
322 obj = new WebGLExtensionSRGB(this);
323 break;
324 case WebGLExtensionID::EXT_texture_filter_anisotropic:
325 obj = new WebGLExtensionTextureFilterAnisotropic(this);
326 break;
328 // OES_
329 case WebGLExtensionID::OES_element_index_uint:
330 obj = new WebGLExtensionElementIndexUint(this);
331 break;
332 case WebGLExtensionID::OES_standard_derivatives:
333 obj = new WebGLExtensionStandardDerivatives(this);
334 break;
335 case WebGLExtensionID::OES_texture_float:
336 obj = new WebGLExtensionTextureFloat(this);
337 break;
338 case WebGLExtensionID::OES_texture_float_linear:
339 obj = new WebGLExtensionTextureFloatLinear(this);
340 break;
341 case WebGLExtensionID::OES_texture_half_float:
342 obj = new WebGLExtensionTextureHalfFloat(this);
343 break;
344 case WebGLExtensionID::OES_texture_half_float_linear:
345 obj = new WebGLExtensionTextureHalfFloatLinear(this);
346 break;
347 case WebGLExtensionID::OES_vertex_array_object:
348 obj = new WebGLExtensionVertexArray(this);
349 break;
351 // WEBGL_
352 case WebGLExtensionID::WEBGL_color_buffer_float:
353 obj = new WebGLExtensionColorBufferFloat(this);
354 break;
355 case WebGLExtensionID::WEBGL_compressed_texture_atc:
356 obj = new WebGLExtensionCompressedTextureATC(this);
357 break;
358 case WebGLExtensionID::WEBGL_compressed_texture_etc1:
359 obj = new WebGLExtensionCompressedTextureETC1(this);
360 break;
361 case WebGLExtensionID::WEBGL_compressed_texture_pvrtc:
362 obj = new WebGLExtensionCompressedTexturePVRTC(this);
363 break;
364 case WebGLExtensionID::WEBGL_compressed_texture_s3tc:
365 obj = new WebGLExtensionCompressedTextureS3TC(this);
366 break;
367 case WebGLExtensionID::WEBGL_debug_renderer_info:
368 obj = new WebGLExtensionDebugRendererInfo(this);
369 break;
370 case WebGLExtensionID::WEBGL_debug_shaders:
371 obj = new WebGLExtensionDebugShaders(this);
372 break;
373 case WebGLExtensionID::WEBGL_depth_texture:
374 obj = new WebGLExtensionDepthTexture(this);
375 break;
376 case WebGLExtensionID::WEBGL_draw_buffers:
377 obj = new WebGLExtensionDrawBuffers(this);
378 break;
379 case WebGLExtensionID::WEBGL_lose_context:
380 obj = new WebGLExtensionLoseContext(this);
381 break;
383 default:
384 MOZ_ASSERT(false, "should not get there.");
387 mExtensions[ext] = obj;
390 void
391 WebGLContext::GetSupportedExtensions(JSContext* cx,
392 Nullable< nsTArray<nsString> >& retval)
394 retval.SetNull();
395 if (IsContextLost())
396 return;
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