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"
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*>
23 static names_array_t sExtensionNamesEnumeratedArray
;
25 static bool initialized
= false;
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
];
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
) {
84 case WebGLExtensionID::WEBGL_debug_renderer_info
:
86 case WebGLExtensionID::WEBGL_debug_shaders
:
89 // For warnings-as-errors.
94 return IsExtensionSupported(ext
);
97 bool WebGLContext::IsExtensionSupported(WebGLExtensionID ext
) const
99 if (mDisableExtensions
) {
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.
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
)) {
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
))
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
)) {
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
);
162 // For warnings-as-errors.
166 if (Preferences::GetBool("webgl.enable-draft-extensions", false) || IsWebGL2()) {
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);
175 // For warnings-as-errors.
184 CompareWebGLExtensionName(const nsACString
& name
, const char *other
)
186 return name
.Equals(other
, nsCaseInsensitiveCStringComparator());
190 WebGLContext::GetExtension(JSContext
*cx
, const nsAString
& aName
,
191 JS::MutableHandle
<JSObject
*> aRetval
,
194 if (IsContextLost()) {
195 aRetval
.set(nullptr);
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
))) {
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.",
245 if (ext
== WebGLExtensionID::Unknown
) {
246 aRetval
.set(nullptr);
250 // step 2: check if the extension is supported
251 if (!IsExtensionSupported(cx
, ext
)) {
252 aRetval
.set(nullptr);
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
));
265 WebGLContext::EnableExtension(WebGLExtensionID ext
)
267 MOZ_ASSERT(IsExtensionEnabled(ext
) == false);
269 WebGLExtensionBase
* obj
= nullptr;
271 case WebGLExtensionID::OES_element_index_uint
:
272 obj
= new WebGLExtensionElementIndexUint(this);
274 case WebGLExtensionID::OES_standard_derivatives
:
275 obj
= new WebGLExtensionStandardDerivatives(this);
277 case WebGLExtensionID::EXT_texture_filter_anisotropic
:
278 obj
= new WebGLExtensionTextureFilterAnisotropic(this);
280 case WebGLExtensionID::WEBGL_lose_context
:
281 obj
= new WebGLExtensionLoseContext(this);
283 case WebGLExtensionID::WEBGL_compressed_texture_s3tc
:
284 obj
= new WebGLExtensionCompressedTextureS3TC(this);
286 case WebGLExtensionID::WEBGL_compressed_texture_atc
:
287 obj
= new WebGLExtensionCompressedTextureATC(this);
289 case WebGLExtensionID::WEBGL_compressed_texture_etc1
:
290 obj
= new WebGLExtensionCompressedTextureETC1(this);
292 case WebGLExtensionID::WEBGL_compressed_texture_pvrtc
:
293 obj
= new WebGLExtensionCompressedTexturePVRTC(this);
295 case WebGLExtensionID::WEBGL_debug_renderer_info
:
296 obj
= new WebGLExtensionDebugRendererInfo(this);
298 case WebGLExtensionID::WEBGL_debug_shaders
:
299 obj
= new WebGLExtensionDebugShaders(this);
301 case WebGLExtensionID::WEBGL_depth_texture
:
302 obj
= new WebGLExtensionDepthTexture(this);
304 case WebGLExtensionID::OES_texture_float
:
305 obj
= new WebGLExtensionTextureFloat(this);
307 case WebGLExtensionID::OES_texture_float_linear
:
308 obj
= new WebGLExtensionTextureFloatLinear(this);
310 case WebGLExtensionID::OES_texture_half_float
:
311 obj
= new WebGLExtensionTextureHalfFloat(this);
313 case WebGLExtensionID::OES_texture_half_float_linear
:
314 obj
= new WebGLExtensionTextureHalfFloatLinear(this);
316 case WebGLExtensionID::WEBGL_color_buffer_float
:
317 obj
= new WebGLExtensionColorBufferFloat(this);
319 case WebGLExtensionID::EXT_color_buffer_half_float
:
320 obj
= new WebGLExtensionColorBufferHalfFloat(this);
322 case WebGLExtensionID::WEBGL_draw_buffers
:
323 obj
= new WebGLExtensionDrawBuffers(this);
325 case WebGLExtensionID::OES_vertex_array_object
:
326 obj
= new WebGLExtensionVertexArray(this);
328 case WebGLExtensionID::ANGLE_instanced_arrays
:
329 obj
= new WebGLExtensionInstancedArrays(this);
331 case WebGLExtensionID::EXT_sRGB
:
332 obj
= new WebGLExtensionSRGB(this);
334 case WebGLExtensionID::EXT_frag_depth
:
335 obj
= new WebGLExtensionFragDepth(this);
337 case WebGLExtensionID::EXT_blend_minmax
:
338 obj
= new WebGLExtensionBlendMinMax(this);
340 case WebGLExtensionID::EXT_shader_texture_lod
:
341 obj
= new WebGLExtensionShaderTextureLod(this);
344 MOZ_ASSERT(false, "should not get there.");
347 mExtensions
[ext
] = obj
;
351 WebGLContext::GetSupportedExtensions(JSContext
*cx
, Nullable
< nsTArray
<nsString
> > &retval
)
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"));