Bug 1421481 - Increase allowed number of webgl contexts on mobile. r?snorp
This was previously limited to 2 per principal and 4 total on
mobile. Mobile GPU drivers have progressed a lot since the limit was
put in place, and the strict limit is causing webcompat issues on
google maps.
Increase to 8 per principal and 16 in total, bringing us
closer in line with Chrome. Make these limits contrallable via a pref
so that if there are any problems it is easy to change.
MozReview-Commit-ID: 8Tsbrjr4KCE
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -1,15 +1,16 @@
/* -*- Mode: C++; tab-width: 20; 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 <algorithm>
#include <queue>
#include "AccessCheck.h"
#include "gfxContext.h"
#include "gfxCrashReporterUtils.h"
#include "gfxPattern.h"
#include "gfxPrefs.h"
#include "gfxUtils.h"
@@ -1148,40 +1149,37 @@ WebGLContext::ClearBackbufferIfNeeded()
ClearScreen();
mBackbufferNeedsClear = false;
}
void
WebGLContext::LoseOldestWebGLContextIfLimitExceeded()
{
-#ifdef MOZ_GFX_OPTIMIZE_MOBILE
- // some mobile devices can't have more than 8 GL contexts overall
- const size_t kMaxWebGLContextsPerPrincipal = 2;
- const size_t kMaxWebGLContexts = 4;
-#else
- const size_t kMaxWebGLContextsPerPrincipal = 16;
- const size_t kMaxWebGLContexts = 32;
-#endif
- MOZ_ASSERT(kMaxWebGLContextsPerPrincipal < kMaxWebGLContexts);
+ const size_t maxWebGLContexts = gfxPrefs::WebGLMaxContexts();
+ size_t maxWebGLContextsPerPrincipal = gfxPrefs::WebGLMaxContextsPerPrincipal();
+
+ // maxWebGLContextsPerPrincipal must be less than maxWebGLContexts
+ MOZ_ASSERT(maxWebGLContextsPerPrincipal < maxWebGLContexts);
+ maxWebGLContextsPerPrincipal = std::min(maxWebGLContextsPerPrincipal, maxWebGLContexts - 1);
if (!NS_IsMainThread()) {
// XXX mtseng: bug 709490, WebGLMemoryTracker is not thread safe.
return;
}
// it's important to update the index on a new context before losing old contexts,
// otherwise new unused contexts would all have index 0 and we couldn't distinguish older ones
// when choosing which one to lose first.
UpdateLastUseIndex();
WebGLMemoryTracker::ContextsArrayType& contexts = WebGLMemoryTracker::Contexts();
// quick exit path, should cover a majority of cases
- if (contexts.Length() <= kMaxWebGLContextsPerPrincipal)
+ if (contexts.Length() <= maxWebGLContextsPerPrincipal)
return;
// note that here by "context" we mean "non-lost context". See the check for
// IsContextLost() below. Indeed, the point of this function is to maybe lose
// some currently non-lost context.
uint64_t oldestIndex = UINT64_MAX;
uint64_t oldestIndexThisPrincipal = UINT64_MAX;
@@ -1220,24 +1218,24 @@ WebGLContext::LoseOldestWebGLContextIfLi
numContextsThisPrincipal++;
if (contexts[i]->mLastUseIndex < oldestIndexThisPrincipal) {
oldestIndexThisPrincipal = contexts[i]->mLastUseIndex;
oldestContextThisPrincipal = contexts[i];
}
}
}
- if (numContextsThisPrincipal > kMaxWebGLContextsPerPrincipal) {
+ if (numContextsThisPrincipal > maxWebGLContextsPerPrincipal) {
GenerateWarning("Exceeded %zu live WebGL contexts for this principal, losing the "
- "least recently used one.", kMaxWebGLContextsPerPrincipal);
+ "least recently used one.", maxWebGLContextsPerPrincipal);
MOZ_ASSERT(oldestContextThisPrincipal); // if we reach this point, this can't be null
const_cast<WebGLContext*>(oldestContextThisPrincipal)->LoseContext();
- } else if (numContexts > kMaxWebGLContexts) {
+ } else if (numContexts > maxWebGLContexts) {
GenerateWarning("Exceeded %zu live WebGL contexts, losing the least "
- "recently used one.", kMaxWebGLContexts);
+ "recently used one.", maxWebGLContexts);
MOZ_ASSERT(oldestContext); // if we reach this point, this can't be null
const_cast<WebGLContext*>(oldestContext)->LoseContext();
}
}
UniquePtr<uint8_t[]>
WebGLContext::GetImageBuffer(int32_t* out_format)
{
--- a/gfx/thebes/gfxPrefs.h
+++ b/gfx/thebes/gfxPrefs.h
@@ -735,16 +735,18 @@ private:
DECL_GFX_PREF(Live, "webgl.enable-draft-extensions", WebGLDraftExtensionsEnabled, bool, false);
DECL_GFX_PREF(Live, "webgl.enable-privileged-extensions", WebGLPrivilegedExtensionsEnabled, bool, false);
DECL_GFX_PREF(Live, "webgl.enable-surface-texture", WebGLSurfaceTextureEnabled, bool, false);
DECL_GFX_PREF(Live, "webgl.enable-webgl2", WebGL2Enabled, bool, true);
DECL_GFX_PREF(Live, "webgl.force-enabled", WebGLForceEnabled, bool, false);
DECL_GFX_PREF(Once, "webgl.force-layers-readback", WebGLForceLayersReadback, bool, false);
DECL_GFX_PREF(Live, "webgl.force-index-validation", WebGLForceIndexValidation, int32_t, 0);
DECL_GFX_PREF(Live, "webgl.lose-context-on-memory-pressure", WebGLLoseContextOnMemoryPressure, bool, false);
+ DECL_GFX_PREF(Once, "webgl.max-contexts", WebGLMaxContexts, uint32_t, 32);
+ DECL_GFX_PREF(Once, "webgl.max-contexts-per-principal", WebGLMaxContextsPerPrincipal, uint32_t, 16);
DECL_GFX_PREF(Live, "webgl.max-warnings-per-context", WebGLMaxWarningsPerContext, uint32_t, 32);
DECL_GFX_PREF(Live, "webgl.min_capability_mode", WebGLMinCapabilityMode, bool, false);
DECL_GFX_PREF(Live, "webgl.msaa-force", WebGLForceMSAA, bool, false);
DECL_GFX_PREF(Live, "webgl.prefer-16bpp", WebGLPrefer16bpp, bool, false);
DECL_GFX_PREF(Live, "webgl.restore-context-when-visible", WebGLRestoreWhenVisible, bool, true);
DECL_GFX_PREF(Live, "webgl.allow-immediate-queries", WebGLImmediateQueries, bool, false);
DECL_GFX_PREF(Live, "webgl.allow-fb-invalidation", WebGLFBInvalidation, bool, false);
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -4666,16 +4666,23 @@ pref("webgl.disable-extensions", false);
pref("webgl.msaa-force", false);
pref("webgl.prefer-16bpp", false);
pref("webgl.default-no-alpha", false);
pref("webgl.force-layers-readback", false);
pref("webgl.force-index-validation", 0);
pref("webgl.lose-context-on-memory-pressure", false);
pref("webgl.can-lose-context-in-foreground", true);
pref("webgl.restore-context-when-visible", true);
+#ifdef ANDROID
+pref("webgl.max-contexts", 16);
+pref("webgl.max-contexts-per-principal", 8);
+#else
+pref("webgl.max-contexts", 32);
+pref("webgl.max-contexts-per-principal", 16);
+#endif
pref("webgl.max-warnings-per-context", 32);
pref("webgl.enable-draft-extensions", false);
pref("webgl.enable-privileged-extensions", false);
pref("webgl.bypass-shader-validation", false);
pref("webgl.disable-fail-if-major-performance-caveat", false);
pref("webgl.disable-DOM-blit-uploads", false);
pref("webgl.allow-fb-invalidation", false);
pref("webgl.webgl2-compat-mode", false);