Bumping gaia.json for 2 gaia revision(s) a=gaia-bump
[gecko.git] / dom / canvas / WebGLContextExtensions.cpp
blob8d1839cf7a1b3a17168470e760a66a8d85f7c4ae
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 using namespace mozilla;
16 using namespace mozilla::gl;
18 /* static */ const char*
19 WebGLContext::GetExtensionString(WebGLExtensionID ext)
21 typedef EnumeratedArray<WebGLExtensionID, WebGLExtensionID::Max, const char*>
22 names_array_t;
23 static names_array_t sExtensionNamesEnumeratedArray;
25 static bool initialized = false;
27 if (!initialized) {
28 initialized = true;
30 #define WEBGL_EXTENSION_IDENTIFIER(x) \
31 sExtensionNamesEnumeratedArray[WebGLExtensionID::x] = #x;
33 WEBGL_EXTENSION_IDENTIFIER(ANGLE_instanced_arrays)
34 WEBGL_EXTENSION_IDENTIFIER(EXT_blend_minmax)
35 WEBGL_EXTENSION_IDENTIFIER(EXT_color_buffer_half_float)
36 WEBGL_EXTENSION_IDENTIFIER(EXT_frag_depth)
37 WEBGL_EXTENSION_IDENTIFIER(EXT_sRGB)
38 WEBGL_EXTENSION_IDENTIFIER(EXT_shader_texture_lod)
39 WEBGL_EXTENSION_IDENTIFIER(EXT_texture_filter_anisotropic)
40 WEBGL_EXTENSION_IDENTIFIER(OES_element_index_uint)
41 WEBGL_EXTENSION_IDENTIFIER(OES_standard_derivatives)
42 WEBGL_EXTENSION_IDENTIFIER(OES_texture_float)
43 WEBGL_EXTENSION_IDENTIFIER(OES_texture_float_linear)
44 WEBGL_EXTENSION_IDENTIFIER(OES_texture_half_float)
45 WEBGL_EXTENSION_IDENTIFIER(OES_texture_half_float_linear)
46 WEBGL_EXTENSION_IDENTIFIER(OES_vertex_array_object)
47 WEBGL_EXTENSION_IDENTIFIER(WEBGL_color_buffer_float)
48 WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_atc)
49 WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_etc1)
50 WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_pvrtc)
51 WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_s3tc)
52 WEBGL_EXTENSION_IDENTIFIER(WEBGL_debug_renderer_info)
53 WEBGL_EXTENSION_IDENTIFIER(WEBGL_debug_shaders)
54 WEBGL_EXTENSION_IDENTIFIER(WEBGL_depth_texture)
55 WEBGL_EXTENSION_IDENTIFIER(WEBGL_draw_buffers)
56 WEBGL_EXTENSION_IDENTIFIER(WEBGL_lose_context)
58 #undef WEBGL_EXTENSION_IDENTIFIER
61 return sExtensionNamesEnumeratedArray[ext];
64 bool
65 WebGLContext::IsExtensionEnabled(WebGLExtensionID ext) const {
66 return mExtensions[ext];
69 bool WebGLContext::IsExtensionSupported(JSContext *cx, WebGLExtensionID ext) const
71 bool allowPrivilegedExts = false;
73 // Chrome contexts need access to debug information even when
74 // webgl.disable-extensions is set. This is used in the graphics
75 // section of about:support.
76 if (xpc::AccessCheck::isChrome(js::GetContextCompartment(cx)))
77 allowPrivilegedExts = true;
79 if (Preferences::GetBool("webgl.enable-privileged-extensions", false))
80 allowPrivilegedExts = true;
82 if (allowPrivilegedExts) {
83 switch (ext) {
84 case WebGLExtensionID::WEBGL_debug_renderer_info:
85 return true;
86 case WebGLExtensionID::WEBGL_debug_shaders:
87 return true;
88 default:
89 // For warnings-as-errors.
90 break;
94 return IsExtensionSupported(ext);
97 bool WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const
99 if (mDisableExtensions) {
100 return false;
103 switch (ext) {
104 case WebGLExtensionID::OES_element_index_uint:
105 return gl->IsSupported(GLFeature::element_index_uint);
106 case WebGLExtensionID::OES_standard_derivatives:
107 return gl->IsSupported(GLFeature::standard_derivatives);
108 case WebGLExtensionID::WEBGL_lose_context:
109 // We always support this extension.
110 return true;
111 case WebGLExtensionID::OES_texture_float:
112 return gl->IsSupported(GLFeature::texture_float);
113 case WebGLExtensionID::OES_texture_float_linear:
114 return gl->IsSupported(GLFeature::texture_float_linear);
115 case WebGLExtensionID::OES_texture_half_float:
116 // If we have Feature::texture_half_float, we must not be on ES2
117 // and need to translate HALF_FLOAT_OES -> HALF_FLOAT. We do that
118 // right before making the relevant calls.
119 return gl->IsExtensionSupported(GLContext::OES_texture_half_float) ||
120 gl->IsSupported(GLFeature::texture_half_float);
121 case WebGLExtensionID::OES_texture_half_float_linear:
122 return gl->IsSupported(GLFeature::texture_half_float_linear);
123 case WebGLExtensionID::OES_vertex_array_object:
124 return WebGLExtensionVertexArray::IsSupported(this);
125 case WebGLExtensionID::EXT_texture_filter_anisotropic:
126 return gl->IsExtensionSupported(GLContext::EXT_texture_filter_anisotropic);
127 case WebGLExtensionID::WEBGL_compressed_texture_s3tc:
128 if (gl->IsExtensionSupported(GLContext::EXT_texture_compression_s3tc)) {
129 return true;
131 else if (gl->IsExtensionSupported(GLContext::EXT_texture_compression_dxt1) &&
132 gl->IsExtensionSupported(GLContext::ANGLE_texture_compression_dxt3) &&
133 gl->IsExtensionSupported(GLContext::ANGLE_texture_compression_dxt5))
135 return true;
137 return false;
138 case WebGLExtensionID::WEBGL_compressed_texture_atc:
139 return gl->IsExtensionSupported(GLContext::AMD_compressed_ATC_texture);
140 case WebGLExtensionID::WEBGL_compressed_texture_etc1:
141 return gl->IsExtensionSupported(GLContext::OES_compressed_ETC1_RGB8_texture);
142 case WebGLExtensionID::WEBGL_compressed_texture_pvrtc:
143 return gl->IsExtensionSupported(GLContext::IMG_texture_compression_pvrtc);
144 case WebGLExtensionID::WEBGL_depth_texture:
145 // WEBGL_depth_texture supports DEPTH_STENCIL textures
146 if (!gl->IsSupported(GLFeature::packed_depth_stencil)) {
147 return false;
149 return gl->IsSupported(GLFeature::depth_texture) ||
150 gl->IsExtensionSupported(GLContext::ANGLE_depth_texture);
151 case WebGLExtensionID::ANGLE_instanced_arrays:
152 return WebGLExtensionInstancedArrays::IsSupported(this);
153 case WebGLExtensionID::EXT_sRGB:
154 return WebGLExtensionSRGB::IsSupported(this);
155 case WebGLExtensionID::WEBGL_draw_buffers:
156 return WebGLExtensionDrawBuffers::IsSupported(this);
157 case WebGLExtensionID::EXT_frag_depth:
158 return WebGLExtensionFragDepth::IsSupported(this);
159 case WebGLExtensionID::EXT_shader_texture_lod:
160 return gl->IsExtensionSupported(GLContext::EXT_shader_texture_lod);
161 default:
162 // For warnings-as-errors.
163 break;
166 if (Preferences::GetBool("webgl.enable-draft-extensions", false) || IsWebGL2()) {
167 switch (ext) {
168 case WebGLExtensionID::EXT_blend_minmax:
169 return WebGLExtensionBlendMinMax::IsSupported(this);
170 case WebGLExtensionID::EXT_color_buffer_half_float:
171 return WebGLExtensionColorBufferHalfFloat::IsSupported(this);
172 case WebGLExtensionID::WEBGL_color_buffer_float:
173 return WebGLExtensionColorBufferFloat::IsSupported(this);
174 default:
175 // For warnings-as-errors.
176 break;
180 return false;
183 static bool
184 CompareWebGLExtensionName(const nsACString& name, const char *other)
186 return name.Equals(other, nsCaseInsensitiveCStringComparator());
189 void
190 WebGLContext::GetExtension(JSContext *cx, const nsAString& aName,
191 JS::MutableHandle<JSObject*> aRetval,
192 ErrorResult& rv)
194 if (IsContextLost()) {
195 aRetval.set(nullptr);
196 return;
199 NS_LossyConvertUTF16toASCII name(aName);
201 WebGLExtensionID ext = WebGLExtensionID::Unknown;
203 // step 1: figure what extension is wanted
204 for (size_t i = 0; i < size_t(WebGLExtensionID::Max); i++)
206 WebGLExtensionID extension = WebGLExtensionID(i);
208 if (CompareWebGLExtensionName(name, GetExtensionString(extension))) {
209 ext = extension;
210 break;
214 if (ext == WebGLExtensionID::Unknown)
217 * We keep backward compatibility for these deprecated vendor-prefixed
218 * alias. Do not add new ones anymore. Hide it behind the
219 * webgl.enable-draft-extensions flag instead.
221 if (CompareWebGLExtensionName(name, "MOZ_WEBGL_lose_context")) {
222 ext = WebGLExtensionID::WEBGL_lose_context;
224 else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_compressed_texture_s3tc")) {
225 ext = WebGLExtensionID::WEBGL_compressed_texture_s3tc;
227 else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_compressed_texture_atc")) {
228 ext = WebGLExtensionID::WEBGL_compressed_texture_atc;
230 else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_compressed_texture_pvrtc")) {
231 ext = WebGLExtensionID::WEBGL_compressed_texture_pvrtc;
233 else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_depth_texture")) {
234 ext = WebGLExtensionID::WEBGL_depth_texture;
237 if (ext != WebGLExtensionID::Unknown) {
238 GenerateWarning("getExtension('%s'): MOZ_ prefixed WebGL extension strings are deprecated. "
239 "Support for them will be removed in the future. Use unprefixed extension strings. "
240 "To get draft extensions, set the webgl.enable-draft-extensions preference.",
241 name.get());
245 if (ext == WebGLExtensionID::Unknown) {
246 aRetval.set(nullptr);
247 return;
250 // step 2: check if the extension is supported
251 if (!IsExtensionSupported(cx, ext)) {
252 aRetval.set(nullptr);
253 return;
256 // step 3: if the extension hadn't been previously been created, create it now, thus enabling it
257 if (!IsExtensionEnabled(ext)) {
258 EnableExtension(ext);
261 aRetval.set(WebGLObjectAsJSObject(cx, mExtensions[ext].get(), rv));
264 void
265 WebGLContext::EnableExtension(WebGLExtensionID ext)
267 MOZ_ASSERT(IsExtensionEnabled(ext) == false);
269 WebGLExtensionBase* obj = nullptr;
270 switch (ext) {
271 case WebGLExtensionID::OES_element_index_uint:
272 obj = new WebGLExtensionElementIndexUint(this);
273 break;
274 case WebGLExtensionID::OES_standard_derivatives:
275 obj = new WebGLExtensionStandardDerivatives(this);
276 break;
277 case WebGLExtensionID::EXT_texture_filter_anisotropic:
278 obj = new WebGLExtensionTextureFilterAnisotropic(this);
279 break;
280 case WebGLExtensionID::WEBGL_lose_context:
281 obj = new WebGLExtensionLoseContext(this);
282 break;
283 case WebGLExtensionID::WEBGL_compressed_texture_s3tc:
284 obj = new WebGLExtensionCompressedTextureS3TC(this);
285 break;
286 case WebGLExtensionID::WEBGL_compressed_texture_atc:
287 obj = new WebGLExtensionCompressedTextureATC(this);
288 break;
289 case WebGLExtensionID::WEBGL_compressed_texture_etc1:
290 obj = new WebGLExtensionCompressedTextureETC1(this);
291 break;
292 case WebGLExtensionID::WEBGL_compressed_texture_pvrtc:
293 obj = new WebGLExtensionCompressedTexturePVRTC(this);
294 break;
295 case WebGLExtensionID::WEBGL_debug_renderer_info:
296 obj = new WebGLExtensionDebugRendererInfo(this);
297 break;
298 case WebGLExtensionID::WEBGL_debug_shaders:
299 obj = new WebGLExtensionDebugShaders(this);
300 break;
301 case WebGLExtensionID::WEBGL_depth_texture:
302 obj = new WebGLExtensionDepthTexture(this);
303 break;
304 case WebGLExtensionID::OES_texture_float:
305 obj = new WebGLExtensionTextureFloat(this);
306 break;
307 case WebGLExtensionID::OES_texture_float_linear:
308 obj = new WebGLExtensionTextureFloatLinear(this);
309 break;
310 case WebGLExtensionID::OES_texture_half_float:
311 obj = new WebGLExtensionTextureHalfFloat(this);
312 break;
313 case WebGLExtensionID::OES_texture_half_float_linear:
314 obj = new WebGLExtensionTextureHalfFloatLinear(this);
315 break;
316 case WebGLExtensionID::WEBGL_color_buffer_float:
317 obj = new WebGLExtensionColorBufferFloat(this);
318 break;
319 case WebGLExtensionID::EXT_color_buffer_half_float:
320 obj = new WebGLExtensionColorBufferHalfFloat(this);
321 break;
322 case WebGLExtensionID::WEBGL_draw_buffers:
323 obj = new WebGLExtensionDrawBuffers(this);
324 break;
325 case WebGLExtensionID::OES_vertex_array_object:
326 obj = new WebGLExtensionVertexArray(this);
327 break;
328 case WebGLExtensionID::ANGLE_instanced_arrays:
329 obj = new WebGLExtensionInstancedArrays(this);
330 break;
331 case WebGLExtensionID::EXT_sRGB:
332 obj = new WebGLExtensionSRGB(this);
333 break;
334 case WebGLExtensionID::EXT_frag_depth:
335 obj = new WebGLExtensionFragDepth(this);
336 break;
337 case WebGLExtensionID::EXT_blend_minmax:
338 obj = new WebGLExtensionBlendMinMax(this);
339 break;
340 case WebGLExtensionID::EXT_shader_texture_lod:
341 obj = new WebGLExtensionShaderTextureLod(this);
342 break;
343 default:
344 MOZ_ASSERT(false, "should not get there.");
347 mExtensions[ext] = obj;
350 void
351 WebGLContext::GetSupportedExtensions(JSContext *cx, Nullable< nsTArray<nsString> > &retval)
353 retval.SetNull();
354 if (IsContextLost())
355 return;
357 nsTArray<nsString>& arr = retval.SetValue();
359 for (size_t i = 0; i < size_t(WebGLExtensionID::Max); i++)
361 WebGLExtensionID extension = WebGLExtensionID(i);
363 if (IsExtensionSupported(cx, extension)) {
364 arr.AppendElement(NS_ConvertUTF8toUTF16(GetExtensionString(extension)));
369 * We keep backward compatibility for these deprecated vendor-prefixed
370 * alias. Do not add new ones anymore. Hide it behind the
371 * webgl.enable-draft-extensions flag instead.
373 if (IsExtensionSupported(cx, WebGLExtensionID::WEBGL_lose_context))
374 arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_lose_context"));
375 if (IsExtensionSupported(cx, WebGLExtensionID::WEBGL_compressed_texture_s3tc))
376 arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_s3tc"));
377 if (IsExtensionSupported(cx, WebGLExtensionID::WEBGL_compressed_texture_atc))
378 arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_atc"));
379 if (IsExtensionSupported(cx, WebGLExtensionID::WEBGL_compressed_texture_pvrtc))
380 arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_pvrtc"));
381 if (IsExtensionSupported(cx, WebGLExtensionID::WEBGL_depth_texture))
382 arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_depth_texture"));