content/canvas/src/WebGLContextExtensions.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial