Files
palemoon27/dom/canvas/WebGLContextExtensions.cpp
T
roytam1 78ceb79db1 import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1248863 - IonMonkey: MIPS: Fix MDefinition::constantValue re-factored. r=luke (c38ce4f8dd)
- Bug 1231024 - narrow the live range for values. r=jandem (bfe06e964d)
- Bug 1248007 part 1 - Refactor useBox and friends to work more like useRegister. r=nbp (8585828647)
- Bug 1248007 part 2 - Remove unused This operands from LCallDirectEval. r=nbp (ca16fc594e)
- Bug 1248598 part 3 - Enable i64 on x64 and various related changes. r=sunfish (75311df85c)
- Bug 1248863 - IonMonkey: MIPS32: Fix LIRGeneratorMIPS::visitBox. r=arai (2d6f64ed18)
- Bug 1244889 - Handle all SIMD types in js::SimdTypeToName. r=bbouvier (7e8952b52d)
- Bug 1244889 - Add support for Uint32x4 as an asm.js type. r=luke (cab8e0e725)
- Bug 1244889 - Fix Float32x4toUint32x4 for asm.js. r=bbouvier (3b34875729)
- Bug 1244889 - Disallow unsigned SIMD types for global variables. r=luke (cde605325d)
- Bug 1201934 - Remove SIMD shiftRight***ByScalar. r=sunfish (db2a308c6f)
- Bug 1246800 - Masked shift-by-scalar amounts. r=sunfish (58f335a1cf)
- Bug 1226017 - Drop support for b2g desktop in reftests, r=jgriffin (b71bfbea26)
- Bug 1231261 - Append plugins to extra profile files instead of overwriting. r=dbaron (cce158e2bf)
- Bug 1193223 - Add reftest support to mach test, r=chmanchester (44e12e1622)
- Bug 1087791 - Add |mach {reftest,crashtest,jstestbrowser}| for mobile/android. r=nalexander (711a6eb376)
- Bug 1087791 - Follow-up on 340c1df41b69 (pushed wrong version of patch); r=nalexander (d4e7b53834)
- Bug 1228636 - Add mach support for running reftests on mulet, r=jgriffin (25fa23feb4)
- Bug 1232792 - Convert JS callsites to use open2 within layout/ (r=sicking) (8ee4616658)
- Bug 1196831 - Add 'run-until-failure' and 'repeat' flags to reftest. r=jmaher (7792c9fa22)
- Bug 1215148 - Object-count based leak checking for Mochitest. r=jgriffin (afe3a307b2)
- Bug 1219371 - Add suppression for Aurora-only Windows leak. r=erahm (2e74e92da2)
- Bug 1218393 - Give a summary for object-count leak checking. r=jgriffin (b1bd4844e9)
- Bug 1219919 - Add suppressions for Windows-specific content process graphics leaks. r=erahm (a651f412b3)
- Bug 1140394 - Protect standard output from interleaving. r=ahal (0ef5d8f71f)
- Bug 1034290 - Use structured log output for test results in reftest, r=jmaher (3e93bd862b)
- Bug 1249787 - OdinMonkey: Add offset and align fields to the encoding of load and store. r=luke (822e9b01f9)
- Bug 1248203 - streamline h2 stream flow control buffer r=hurley (739a39a255)
- Bug 1221320 - XMLHttpRequest authentication should not require auth prompt dialog, r=honzab.moz (12d9bcc6d0)
- Bug 1158543 - Remove SpdyConnectTransaction::mRequestHead and make the base class mRequestHead protected; r=mcmanus (9678015004)
- Bug 844948 - Allow changing padding of themed button on OS X. r=mstange,heycam (56cbcffbfe)
- Bug 1248983 - Fix spelling for nsCocoaWindow.mm. r=jdm (e185ad5889)
- Bug 917505 - Add WEBGL_compressed_texture_es3 support. r=jgilbert r=smaug (bf4ef11229)
- Bug 1243072 - Make GfxTexturesReporter work again r=nical,jgilbert (6942d70ecf)
2023-09-25 10:10:09 +08:00

455 lines
16 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "WebGLContext.h"
#include "WebGLContextUtils.h"
#include "WebGLExtensions.h"
#include "gfxPrefs.h"
#include "GLContext.h"
#include "nsString.h"
#include "mozilla/Preferences.h"
#include "AccessCheck.h"
namespace mozilla {
/*static*/ const char*
WebGLContext::GetExtensionString(WebGLExtensionID ext)
{
typedef EnumeratedArray<WebGLExtensionID, WebGLExtensionID::Max,
const char*> names_array_t;
static names_array_t sExtensionNamesEnumeratedArray;
static bool initialized = false;
if (!initialized) {
initialized = true;
#define WEBGL_EXTENSION_IDENTIFIER(x) \
sExtensionNamesEnumeratedArray[WebGLExtensionID::x] = #x;
WEBGL_EXTENSION_IDENTIFIER(ANGLE_instanced_arrays)
WEBGL_EXTENSION_IDENTIFIER(EXT_blend_minmax)
WEBGL_EXTENSION_IDENTIFIER(EXT_color_buffer_half_float)
WEBGL_EXTENSION_IDENTIFIER(EXT_frag_depth)
WEBGL_EXTENSION_IDENTIFIER(EXT_shader_texture_lod)
WEBGL_EXTENSION_IDENTIFIER(EXT_sRGB)
WEBGL_EXTENSION_IDENTIFIER(EXT_texture_filter_anisotropic)
WEBGL_EXTENSION_IDENTIFIER(EXT_disjoint_timer_query)
WEBGL_EXTENSION_IDENTIFIER(OES_element_index_uint)
WEBGL_EXTENSION_IDENTIFIER(OES_standard_derivatives)
WEBGL_EXTENSION_IDENTIFIER(OES_texture_float)
WEBGL_EXTENSION_IDENTIFIER(OES_texture_float_linear)
WEBGL_EXTENSION_IDENTIFIER(OES_texture_half_float)
WEBGL_EXTENSION_IDENTIFIER(OES_texture_half_float_linear)
WEBGL_EXTENSION_IDENTIFIER(OES_vertex_array_object)
WEBGL_EXTENSION_IDENTIFIER(WEBGL_color_buffer_float)
WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_atc)
WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_es3)
WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_etc1)
WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_pvrtc)
WEBGL_EXTENSION_IDENTIFIER(WEBGL_compressed_texture_s3tc)
WEBGL_EXTENSION_IDENTIFIER(WEBGL_debug_renderer_info)
WEBGL_EXTENSION_IDENTIFIER(WEBGL_debug_shaders)
WEBGL_EXTENSION_IDENTIFIER(WEBGL_depth_texture)
WEBGL_EXTENSION_IDENTIFIER(WEBGL_draw_buffers)
WEBGL_EXTENSION_IDENTIFIER(WEBGL_lose_context)
#undef WEBGL_EXTENSION_IDENTIFIER
}
return sExtensionNamesEnumeratedArray[ext];
}
bool
WebGLContext::IsExtensionEnabled(WebGLExtensionID ext) const
{
return mExtensions[ext];
}
bool WebGLContext::IsExtensionSupported(JSContext* cx,
WebGLExtensionID ext) const
{
bool allowPrivilegedExts = false;
// Chrome contexts need access to debug information even when
// webgl.disable-extensions is set. This is used in the graphics
// section of about:support
if (NS_IsMainThread() &&
xpc::AccessCheck::isChrome(js::GetContextCompartment(cx))) {
allowPrivilegedExts = true;
}
if (gfxPrefs::WebGLPrivilegedExtensionsEnabled()) {
allowPrivilegedExts = true;
}
if (allowPrivilegedExts) {
switch (ext) {
case WebGLExtensionID::WEBGL_debug_renderer_info:
return true;
case WebGLExtensionID::WEBGL_debug_shaders:
return true;
default:
// For warnings-as-errors.
break;
}
}
return IsExtensionSupported(ext);
}
bool
WebGLContext::IsExtensionSupported(WebGLExtensionID ext) const
{
if (mDisableExtensions)
return false;
// Extensions for both WebGL 1 and 2.
switch (ext) {
// In alphabetical order
// EXT_
case WebGLExtensionID::EXT_color_buffer_half_float:
return WebGLExtensionColorBufferHalfFloat::IsSupported(this);
case WebGLExtensionID::EXT_texture_filter_anisotropic:
return gl->IsExtensionSupported(gl::GLContext::EXT_texture_filter_anisotropic);
// OES_
case WebGLExtensionID::OES_texture_float_linear:
return gl->IsSupported(gl::GLFeature::texture_float_linear);
case WebGLExtensionID::OES_texture_half_float_linear:
return gl->IsSupported(gl::GLFeature::texture_half_float_linear);
// WEBGL_
case WebGLExtensionID::WEBGL_color_buffer_float:
return WebGLExtensionColorBufferFloat::IsSupported(this);
case WebGLExtensionID::WEBGL_compressed_texture_atc:
return gl->IsExtensionSupported(gl::GLContext::AMD_compressed_ATC_texture);
case WebGLExtensionID::WEBGL_compressed_texture_etc1:
return gl->IsExtensionSupported(gl::GLContext::OES_compressed_ETC1_RGB8_texture);
case WebGLExtensionID::WEBGL_compressed_texture_pvrtc:
return gl->IsExtensionSupported(gl::GLContext::IMG_texture_compression_pvrtc);
case WebGLExtensionID::WEBGL_compressed_texture_s3tc:
if (gl->IsExtensionSupported(gl::GLContext::EXT_texture_compression_s3tc))
return true;
return gl->IsExtensionSupported(gl::GLContext::EXT_texture_compression_dxt1) &&
gl->IsExtensionSupported(gl::GLContext::ANGLE_texture_compression_dxt3) &&
gl->IsExtensionSupported(gl::GLContext::ANGLE_texture_compression_dxt5);
case WebGLExtensionID::WEBGL_debug_renderer_info:
return Preferences::GetBool("webgl.enable-debug-renderer-info", false);
case WebGLExtensionID::WEBGL_lose_context:
// We always support this extension.
return true;
default:
// For warnings-as-errors.
break;
}
if (!IsWebGL2()) {
// WebGL1-only extensions
switch (ext) {
// ANGLE_
case WebGLExtensionID::ANGLE_instanced_arrays:
return WebGLExtensionInstancedArrays::IsSupported(this);
// EXT_
case WebGLExtensionID::EXT_blend_minmax:
return WebGLExtensionBlendMinMax::IsSupported(this);
case WebGLExtensionID::EXT_frag_depth:
return WebGLExtensionFragDepth::IsSupported(this);
case WebGLExtensionID::EXT_shader_texture_lod:
return gl->IsExtensionSupported(gl::GLContext::EXT_shader_texture_lod);
case WebGLExtensionID::EXT_sRGB:
return WebGLExtensionSRGB::IsSupported(this);
// OES_
case WebGLExtensionID::OES_element_index_uint:
return gl->IsSupported(gl::GLFeature::element_index_uint);
case WebGLExtensionID::OES_standard_derivatives:
return gl->IsSupported(gl::GLFeature::standard_derivatives);
case WebGLExtensionID::OES_texture_float:
return WebGLExtensionTextureFloat::IsSupported(this);
case WebGLExtensionID::OES_texture_half_float:
return WebGLExtensionTextureHalfFloat::IsSupported(this);
case WebGLExtensionID::OES_vertex_array_object:
return true;
// WEBGL_
case WebGLExtensionID::WEBGL_depth_texture:
// WEBGL_depth_texture supports DEPTH_STENCIL textures
if (!gl->IsSupported(gl::GLFeature::packed_depth_stencil))
return false;
return gl->IsSupported(gl::GLFeature::depth_texture) ||
gl->IsExtensionSupported(gl::GLContext::ANGLE_depth_texture);
case WebGLExtensionID::WEBGL_draw_buffers:
return WebGLExtensionDrawBuffers::IsSupported(this);
default:
// For warnings-as-errors.
break;
}
if (gfxPrefs::WebGLDraftExtensionsEnabled()) {
switch (ext) {
case WebGLExtensionID::EXT_disjoint_timer_query:
return WebGLExtensionDisjointTimerQuery::IsSupported(this);
case WebGLExtensionID::WEBGL_compressed_texture_es3:
return gl->IsExtensionSupported(gl::GLContext::ARB_ES3_compatibility);
default:
// For warnings-as-errors.
break;
}
}
}
return false;
}
static bool
CompareWebGLExtensionName(const nsACString& name, const char* other)
{
return name.Equals(other, nsCaseInsensitiveCStringComparator());
}
WebGLExtensionBase*
WebGLContext::EnableSupportedExtension(JSContext* js, WebGLExtensionID ext)
{
if (!IsExtensionEnabled(ext)) {
if (!IsExtensionSupported(js, ext))
return nullptr;
EnableExtension(ext);
}
return mExtensions[ext];
}
void
WebGLContext::GetExtension(JSContext* cx, const nsAString& wideName,
JS::MutableHandle<JSObject*> retval, ErrorResult& rv)
{
retval.set(nullptr);
if (IsContextLost())
return;
NS_LossyConvertUTF16toASCII name(wideName);
WebGLExtensionID ext = WebGLExtensionID::Unknown;
// step 1: figure what extension is wanted
for (size_t i = 0; i < size_t(WebGLExtensionID::Max); i++) {
WebGLExtensionID extension = WebGLExtensionID(i);
if (CompareWebGLExtensionName(name, GetExtensionString(extension))) {
ext = extension;
break;
}
}
if (ext == WebGLExtensionID::Unknown) {
// We keep backward compatibility for these deprecated vendor-prefixed
// alias. Do not add new ones anymore. Hide it behind the
// webgl.enable-draft-extensions flag instead.
if (CompareWebGLExtensionName(name, "MOZ_WEBGL_lose_context")) {
ext = WebGLExtensionID::WEBGL_lose_context;
} else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_compressed_texture_s3tc")) {
ext = WebGLExtensionID::WEBGL_compressed_texture_s3tc;
} else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_compressed_texture_atc")) {
ext = WebGLExtensionID::WEBGL_compressed_texture_atc;
} else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_compressed_texture_pvrtc")) {
ext = WebGLExtensionID::WEBGL_compressed_texture_pvrtc;
} else if (CompareWebGLExtensionName(name, "MOZ_WEBGL_depth_texture")) {
ext = WebGLExtensionID::WEBGL_depth_texture;
}
if (ext != WebGLExtensionID::Unknown) {
GenerateWarning("getExtension('%s'): MOZ_ prefixed WebGL extension"
" strings are deprecated. Support for them will be"
" removed in the future. Use unprefixed extension"
" strings. To get draft extensions, set the"
" webgl.enable-draft-extensions preference.",
name.get());
}
}
if (ext == WebGLExtensionID::Unknown)
return;
// step 2: check if the extension is supported
if (!IsExtensionSupported(cx, ext))
return;
// step 3: if the extension hadn't been previously been created, create it now, thus enabling it
WebGLExtensionBase* extObj = EnableSupportedExtension(cx, ext);
if (!extObj)
return;
// Step 4: Enable any implied extensions.
switch (ext) {
case WebGLExtensionID::OES_texture_float:
EnableSupportedExtension(cx, WebGLExtensionID::WEBGL_color_buffer_float);
break;
case WebGLExtensionID::OES_texture_half_float:
EnableSupportedExtension(cx, WebGLExtensionID::EXT_color_buffer_half_float);
break;
default:
break;
}
retval.set(WebGLObjectAsJSObject(cx, extObj, rv));
}
void
WebGLContext::EnableExtension(WebGLExtensionID ext)
{
MOZ_ASSERT(IsExtensionEnabled(ext) == false);
WebGLExtensionBase* obj = nullptr;
switch (ext) {
// ANGLE_
case WebGLExtensionID::ANGLE_instanced_arrays:
obj = new WebGLExtensionInstancedArrays(this);
break;
// EXT_
case WebGLExtensionID::EXT_blend_minmax:
obj = new WebGLExtensionBlendMinMax(this);
break;
case WebGLExtensionID::EXT_color_buffer_half_float:
obj = new WebGLExtensionColorBufferHalfFloat(this);
break;
case WebGLExtensionID::EXT_disjoint_timer_query:
obj = new WebGLExtensionDisjointTimerQuery(this);
break;
case WebGLExtensionID::EXT_frag_depth:
obj = new WebGLExtensionFragDepth(this);
break;
case WebGLExtensionID::EXT_shader_texture_lod:
obj = new WebGLExtensionShaderTextureLod(this);
break;
case WebGLExtensionID::EXT_sRGB:
obj = new WebGLExtensionSRGB(this);
break;
case WebGLExtensionID::EXT_texture_filter_anisotropic:
obj = new WebGLExtensionTextureFilterAnisotropic(this);
break;
// OES_
case WebGLExtensionID::OES_element_index_uint:
obj = new WebGLExtensionElementIndexUint(this);
break;
case WebGLExtensionID::OES_standard_derivatives:
obj = new WebGLExtensionStandardDerivatives(this);
break;
case WebGLExtensionID::OES_texture_float:
obj = new WebGLExtensionTextureFloat(this);
break;
case WebGLExtensionID::OES_texture_float_linear:
obj = new WebGLExtensionTextureFloatLinear(this);
break;
case WebGLExtensionID::OES_texture_half_float:
obj = new WebGLExtensionTextureHalfFloat(this);
break;
case WebGLExtensionID::OES_texture_half_float_linear:
obj = new WebGLExtensionTextureHalfFloatLinear(this);
break;
case WebGLExtensionID::OES_vertex_array_object:
obj = new WebGLExtensionVertexArray(this);
break;
// WEBGL_
case WebGLExtensionID::WEBGL_color_buffer_float:
obj = new WebGLExtensionColorBufferFloat(this);
break;
case WebGLExtensionID::WEBGL_compressed_texture_atc:
obj = new WebGLExtensionCompressedTextureATC(this);
break;
case WebGLExtensionID::WEBGL_compressed_texture_es3:
obj = new WebGLExtensionCompressedTextureES3(this);
break;
case WebGLExtensionID::WEBGL_compressed_texture_etc1:
obj = new WebGLExtensionCompressedTextureETC1(this);
break;
case WebGLExtensionID::WEBGL_compressed_texture_pvrtc:
obj = new WebGLExtensionCompressedTexturePVRTC(this);
break;
case WebGLExtensionID::WEBGL_compressed_texture_s3tc:
obj = new WebGLExtensionCompressedTextureS3TC(this);
break;
case WebGLExtensionID::WEBGL_debug_renderer_info:
obj = new WebGLExtensionDebugRendererInfo(this);
break;
case WebGLExtensionID::WEBGL_debug_shaders:
obj = new WebGLExtensionDebugShaders(this);
break;
case WebGLExtensionID::WEBGL_depth_texture:
obj = new WebGLExtensionDepthTexture(this);
break;
case WebGLExtensionID::WEBGL_draw_buffers:
obj = new WebGLExtensionDrawBuffers(this);
break;
case WebGLExtensionID::WEBGL_lose_context:
obj = new WebGLExtensionLoseContext(this);
break;
default:
MOZ_ASSERT(false, "should not get there.");
}
mExtensions[ext] = obj;
}
void
WebGLContext::GetSupportedExtensions(JSContext* cx,
dom::Nullable< nsTArray<nsString> >& retval)
{
retval.SetNull();
if (IsContextLost())
return;
nsTArray<nsString>& arr = retval.SetValue();
for (size_t i = 0; i < size_t(WebGLExtensionID::Max); i++) {
WebGLExtensionID extension = WebGLExtensionID(i);
if (IsExtensionSupported(cx, extension)) {
const char* extStr = GetExtensionString(extension);
arr.AppendElement(NS_ConvertUTF8toUTF16(extStr));
}
}
/**
* We keep backward compatibility for these deprecated vendor-prefixed
* alias. Do not add new ones anymore. Hide it behind the
* webgl.enable-draft-extensions flag instead.
*/
if (IsExtensionSupported(cx, WebGLExtensionID::WEBGL_lose_context))
arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_lose_context"));
if (IsExtensionSupported(cx, WebGLExtensionID::WEBGL_compressed_texture_s3tc))
arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_s3tc"));
if (IsExtensionSupported(cx, WebGLExtensionID::WEBGL_compressed_texture_atc))
arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_atc"));
if (IsExtensionSupported(cx, WebGLExtensionID::WEBGL_compressed_texture_pvrtc))
arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_compressed_texture_pvrtc"));
if (IsExtensionSupported(cx, WebGLExtensionID::WEBGL_depth_texture))
arr.AppendElement(NS_LITERAL_STRING("MOZ_WEBGL_depth_texture"));
}
} // namespace mozilla