content/canvas/src/WebGLContextExtensions.cpp

branch
TOR_BUG_9701
changeset 11
deefc01c0e14
equal deleted inserted replaced
-1:000000000000 0:ebcd4c3764f1
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 "GLContext.h"
10
11 #include "nsString.h"
12 #include "mozilla/Preferences.h"
13 #include "AccessCheck.h"
14
15 using namespace mozilla;
16 using namespace mozilla::gl;
17
18 /* static */ const char*
19 WebGLContext::GetExtensionString(WebGLExtensionID ext)
20 {
21 // must match WebGLExtensionID.
22 // Once we can use variadic templates, EnumeratedArray should get a constructor
23 // allowing to initialize it directly without using this auxiliary plain array.
24 static const char *kExtensionNames[] = {
25 "ANGLE_instanced_arrays",
26 "EXT_color_buffer_half_float",
27 "EXT_frag_depth",
28 "EXT_sRGB",
29 "EXT_texture_filter_anisotropic",
30 "OES_element_index_uint",
31 "OES_standard_derivatives",
32 "OES_texture_float",
33 "OES_texture_float_linear",
34 "OES_texture_half_float",
35 "OES_texture_half_float_linear",
36 "OES_vertex_array_object",
37 "WEBGL_color_buffer_float",
38 "WEBGL_compressed_texture_atc",
39 "WEBGL_compressed_texture_etc1",
40 "WEBGL_compressed_texture_pvrtc",
41 "WEBGL_compressed_texture_s3tc",
42 "WEBGL_debug_renderer_info",
43 "WEBGL_debug_shaders",
44 "WEBGL_depth_texture",
45 "WEBGL_draw_buffers",
46 "WEBGL_lose_context"
47 };
48
49 typedef EnumeratedArray<WebGLExtensionID, WebGLExtensionID::Max, const char*>
50 names_array_t;
51 static const names_array_t kExtensionNamesEnumeratedArray(kExtensionNames);
52
53 return kExtensionNamesEnumeratedArray[ext];
54 }
55
56 bool
57 WebGLContext::IsExtensionEnabled(WebGLExtensionID ext) const {
58 return mExtensions[ext];
59 }
60
61 bool WebGLContext::IsExtensionSupported(JSContext *cx, WebGLExtensionID ext) const
62 {
63 bool allowPrivilegedExts = false;
64
65 // Chrome contexts need access to debug information even when
66 // webgl.disable-extensions is set. This is used in the graphics
67 // section of about:support.
68 if (xpc::AccessCheck::isChrome(js::GetContextCompartment(cx)))
69 allowPrivilegedExts = true;
70
71 if (Preferences::GetBool("webgl.enable-privileged-extensions", false))
72 allowPrivilegedExts = true;
73
74 if (allowPrivilegedExts) {
75 switch (ext) {
76 case WebGLExtensionID::WEBGL_debug_renderer_info:
77 return true;
78 case WebGLExtensionID::WEBGL_debug_shaders:
79 return true;
80 default:
81 // For warnings-as-errors.
82 break;
83 }
84 }
85
86 return IsExtensionSupported(ext);
87 }
88
89 bool WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const
90 {
91 if (mDisableExtensions) {
92 return false;
93 }
94
95 switch (ext) {
96 case WebGLExtensionID::OES_element_index_uint:
97 return gl->IsSupported(GLFeature::element_index_uint);
98 case WebGLExtensionID::OES_standard_derivatives:
99 return gl->IsSupported(GLFeature::standard_derivatives);
100 case WebGLExtensionID::WEBGL_lose_context:
101 // We always support this extension.
102 return true;
103 case WebGLExtensionID::OES_texture_float:
104 return gl->IsSupported(GLFeature::texture_float);
105 case WebGLExtensionID::OES_texture_float_linear:
106 return gl->IsSupported(GLFeature::texture_float_linear);
107 case WebGLExtensionID::OES_texture_half_float:
108 // If we have Feature::texture_half_float, we must not be on ES2
109 // and need to translate HALF_FLOAT_OES -> HALF_FLOAT. We do that
110 // right before making the relevant calls.
111 return gl->IsExtensionSupported(GLContext::OES_texture_half_float) ||
112 gl->IsSupported(GLFeature::texture_half_float);
113 case WebGLExtensionID::OES_texture_half_float_linear:
114 return gl->IsSupported(GLFeature::texture_half_float_linear);
115 case WebGLExtensionID::WEBGL_color_buffer_float:
116 return WebGLExtensionColorBufferFloat::IsSupported(this);
117 case WebGLExtensionID::EXT_color_buffer_half_float:
118 return WebGLExtensionColorBufferHalfFloat::IsSupported(this);
119 case WebGLExtensionID::OES_vertex_array_object:
120 return WebGLExtensionVertexArray::IsSupported(this);
121 case WebGLExtensionID::EXT_texture_filter_anisotropic:
122 return gl->IsExtensionSupported(GLContext::EXT_texture_filter_anisotropic);
123 case WebGLExtensionID::WEBGL_compressed_texture_s3tc:
124 if (gl->IsExtensionSupported(GLContext::EXT_texture_compression_s3tc)) {
125 return true;
126 }
127 else if (gl->IsExtensionSupported(GLContext::EXT_texture_compression_dxt1) &&
128 gl->IsExtensionSupported(GLContext::ANGLE_texture_compression_dxt3) &&
129 gl->IsExtensionSupported(GLContext::ANGLE_texture_compression_dxt5))
130 {
131 return true;
132 }
133 return false;
134 case WebGLExtensionID::WEBGL_compressed_texture_atc:
135 return gl->IsExtensionSupported(GLContext::AMD_compressed_ATC_texture);
136 case WebGLExtensionID::WEBGL_compressed_texture_etc1:
137 return gl->IsExtensionSupported(GLContext::OES_compressed_ETC1_RGB8_texture);
138 case WebGLExtensionID::WEBGL_compressed_texture_pvrtc:
139 return gl->IsExtensionSupported(GLContext::IMG_texture_compression_pvrtc);
140 case WebGLExtensionID::WEBGL_depth_texture:
141 // WEBGL_depth_texture supports DEPTH_STENCIL textures
142 if (!gl->IsSupported(GLFeature::packed_depth_stencil)) {
143 return false;
144 }
145 return gl->IsSupported(GLFeature::depth_texture) ||
146 gl->IsExtensionSupported(GLContext::ANGLE_depth_texture);
147 case WebGLExtensionID::ANGLE_instanced_arrays:
148 return WebGLExtensionInstancedArrays::IsSupported(this);
149 case WebGLExtensionID::EXT_sRGB:
150 return WebGLExtensionSRGB::IsSupported(this);
151 case WebGLExtensionID::WEBGL_draw_buffers:
152 return WebGLExtensionDrawBuffers::IsSupported(this);
153 case WebGLExtensionID::EXT_frag_depth:
154 return WebGLExtensionFragDepth::IsSupported(this);
155 default:
156 // For warnings-as-errors.
157 break;
158 }
159 // Uncomment this switch for any new extensions
160 #if 0
161 if (Preferences::GetBool("webgl.enable-draft-extensions", false) || IsWebGL2()) {
162 switch (ext) {
163 default:
164 // For warnings-as-errors.
165 break;
166 }
167 }
168 #endif
169
170 return false;
171 }
172
173 static bool
174 CompareWebGLExtensionName(const nsACString& name, const char *other)
175 {
176 return name.Equals(other, nsCaseInsensitiveCStringComparator());
177 }
178
179 void
180 WebGLContext::GetExtension(JSContext *cx, const nsAString& aName,
181 JS::MutableHandle<JSObject*> aRetval,
182 ErrorResult& rv)
183 {
184 if (IsContextLost()) {
185 aRetval.set(nullptr);
186 return;
187 }
188
189 NS_LossyConvertUTF16toASCII name(aName);
190
191 WebGLExtensionID ext = WebGLExtensionID::Unknown;
192
193 // step 1: figure what extension is wanted
194 for (size_t i = 0; i < size_t(WebGLExtensionID::Max); i++)
195 {
196 WebGLExtensionID extension = WebGLExtensionID(i);
197
198 if (CompareWebGLExtensionName(name, GetExtensionString(extension))) {
199 ext = extension;
200 break;
201 }
202 }
203
204 if (ext == WebGLExtensionID::Unknown)
205 {
206 /**
207 * We keep backward compatibility for these deprecated vendor-prefixed
208 * alias. Do not add new ones anymore. Hide it behind the
209 * webgl.enable-draft-extensions flag instead.
210 */
211 if (CompareWebGLExtensionName(name, "MOZ_WEBGL_lose_context")) {
212 ext = WebGLExtensionID::WEBGL_lose_context;
213 }
214 else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_compressed_texture_s3tc")) {
215 ext = WebGLExtensionID::WEBGL_compressed_texture_s3tc;
216 }
217 else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_compressed_texture_atc")) {
218 ext = WebGLExtensionID::WEBGL_compressed_texture_atc;
219 }
220 else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_compressed_texture_pvrtc")) {
221 ext = WebGLExtensionID::WEBGL_compressed_texture_pvrtc;
222 }
223 else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_depth_texture")) {
224 ext = WebGLExtensionID::WEBGL_depth_texture;
225 }
226
227 if (ext != WebGLExtensionID::Unknown) {
228 GenerateWarning("getExtension('%s'): MOZ_ prefixed WebGL extension strings are deprecated. "
229 "Support for them will be removed in the future. Use unprefixed extension strings. "
230 "To get draft extensions, set the webgl.enable-draft-extensions preference.",
231 name.get());
232 }
233 }
234
235 if (ext == WebGLExtensionID::Unknown) {
236 aRetval.set(nullptr);
237 return;
238 }
239
240 // step 2: check if the extension is supported
241 if (!IsExtensionSupported(cx, ext)) {
242 aRetval.set(nullptr);
243 return;
244 }
245
246 // step 3: if the extension hadn't been previously been created, create it now, thus enabling it
247 if (!IsExtensionEnabled(ext)) {
248 EnableExtension(ext);
249 }
250
251 aRetval.set(WebGLObjectAsJSObject(cx, mExtensions[ext].get(), rv));
252 }
253
254 void
255 WebGLContext::EnableExtension(WebGLExtensionID ext)
256 {
257 MOZ_ASSERT(IsExtensionEnabled(ext) == false);
258
259 WebGLExtensionBase* obj = nullptr;
260 switch (ext) {
261 case WebGLExtensionID::OES_element_index_uint:
262 obj = new WebGLExtensionElementIndexUint(this);
263 break;
264 case WebGLExtensionID::OES_standard_derivatives:
265 obj = new WebGLExtensionStandardDerivatives(this);
266 break;
267 case WebGLExtensionID::EXT_texture_filter_anisotropic:
268 obj = new WebGLExtensionTextureFilterAnisotropic(this);
269 break;
270 case WebGLExtensionID::WEBGL_lose_context:
271 obj = new WebGLExtensionLoseContext(this);
272 break;
273 case WebGLExtensionID::WEBGL_compressed_texture_s3tc:
274 obj = new WebGLExtensionCompressedTextureS3TC(this);
275 break;
276 case WebGLExtensionID::WEBGL_compressed_texture_atc:
277 obj = new WebGLExtensionCompressedTextureATC(this);
278 break;
279 case WebGLExtensionID::WEBGL_compressed_texture_etc1:
280 obj = new WebGLExtensionCompressedTextureETC1(this);
281 break;
282 case WebGLExtensionID::WEBGL_compressed_texture_pvrtc:
283 obj = new WebGLExtensionCompressedTexturePVRTC(this);
284 break;
285 case WebGLExtensionID::WEBGL_debug_renderer_info:
286 obj = new WebGLExtensionDebugRendererInfo(this);
287 break;
288 case WebGLExtensionID::WEBGL_debug_shaders:
289 obj = new WebGLExtensionDebugShaders(this);
290 break;
291 case WebGLExtensionID::WEBGL_depth_texture:
292 obj = new WebGLExtensionDepthTexture(this);
293 break;
294 case WebGLExtensionID::OES_texture_float:
295 obj = new WebGLExtensionTextureFloat(this);
296 break;
297 case WebGLExtensionID::OES_texture_float_linear:
298 obj = new WebGLExtensionTextureFloatLinear(this);
299 break;
300 case WebGLExtensionID::OES_texture_half_float:
301 obj = new WebGLExtensionTextureHalfFloat(this);
302 break;
303 case WebGLExtensionID::OES_texture_half_float_linear:
304 obj = new WebGLExtensionTextureHalfFloatLinear(this);
305 break;
306 case WebGLExtensionID::WEBGL_color_buffer_float:
307 obj = new WebGLExtensionColorBufferFloat(this);
308 break;
309 case WebGLExtensionID::EXT_color_buffer_half_float:
310 obj = new WebGLExtensionColorBufferHalfFloat(this);
311 break;
312 case WebGLExtensionID::WEBGL_draw_buffers:
313 obj = new WebGLExtensionDrawBuffers(this);
314 break;
315 case WebGLExtensionID::OES_vertex_array_object:
316 obj = new WebGLExtensionVertexArray(this);
317 break;
318 case WebGLExtensionID::ANGLE_instanced_arrays:
319 obj = new WebGLExtensionInstancedArrays(this);
320 break;
321 case WebGLExtensionID::EXT_sRGB:
322 obj = new WebGLExtensionSRGB(this);
323 break;
324 case WebGLExtensionID::EXT_frag_depth:
325 obj = new WebGLExtensionFragDepth(this);
326 break;
327 default:
328 MOZ_ASSERT(false, "should not get there.");
329 }
330
331 mExtensions[ext] = obj;
332 }
333
334 void
335 WebGLContext::GetSupportedExtensions(JSContext *cx, Nullable< nsTArray<nsString> > &retval)
336 {
337 retval.SetNull();
338 if (IsContextLost())
339 return;
340
341 nsTArray<nsString>& arr = retval.SetValue();
342
343 for (size_t i = 0; i < size_t(WebGLExtensionID::Max); i++)
344 {
345 WebGLExtensionID extension = WebGLExtensionID(i);
346
347 if (IsExtensionSupported(cx, extension)) {
348 arr.AppendElement(NS_ConvertUTF8toUTF16(GetExtensionString(extension)));
349 }
350 }
351
352 /**
353 * We keep backward compatibility for these deprecated vendor-prefixed
354 * alias. Do not add new ones anymore. Hide it behind the
355 * webgl.enable-draft-extensions flag instead.
356 */
357 if (IsExtensionSupported(cx, WebGLExtensionID::WEBGL_lose_context))
358 arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_lose_context"));
359 if (IsExtensionSupported(cx, WebGLExtensionID::WEBGL_compressed_texture_s3tc))
360 arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_s3tc"));
361 if (IsExtensionSupported(cx, WebGLExtensionID::WEBGL_compressed_texture_atc))
362 arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_atc"));
363 if (IsExtensionSupported(cx, WebGLExtensionID::WEBGL_compressed_texture_pvrtc))
364 arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_pvrtc"));
365 if (IsExtensionSupported(cx, WebGLExtensionID::WEBGL_depth_texture))
366 arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_depth_texture"));
367 }
368

mercurial