Bug 1288746 - Handle missing WebGL failure IDs. r=jrmuizel
MozReview-Commit-ID: 3kdr8Dwinqm
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -25,16 +25,17 @@
#include "mozilla/dom/BindingUtils.h"
#include "mozilla/dom/Event.h"
#include "mozilla/dom/HTMLVideoElement.h"
#include "mozilla/dom/ImageData.h"
#include "mozilla/dom/WebGLContextEvent.h"
#include "mozilla/EnumeratedArrayCycleCollection.h"
#include "mozilla/Preferences.h"
#include "mozilla/ProcessPriorityManager.h"
+#include "mozilla/ScopeExit.h"
#include "mozilla/Services.h"
#include "mozilla/Telemetry.h"
#include "nsContentUtils.h"
#include "nsDisplayList.h"
#include "nsError.h"
#include "nsIClassInfoImpl.h"
#include "nsIConsoleService.h"
#include "nsIDOMEvent.h"
@@ -839,16 +840,20 @@ WebGLContext::ThrowEvent_WebGLContextCre
GenerateWarning("Failed to create WebGL context: %s", text.BeginReading());
}
NS_IMETHODIMP
WebGLContext::SetDimensions(int32_t signedWidth, int32_t signedHeight)
{
if (signedWidth < 0 || signedHeight < 0) {
+ if (!gl) {
+ Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_FAILURE_ID,
+ NS_LITERAL_CSTRING("FEATURE_FAILURE_WEBGL_SIZE"));
+ }
GenerateWarning("Canvas size is too large (seems like a negative value wrapped)");
return NS_ERROR_OUT_OF_MEMORY;
}
uint32_t width = signedWidth;
uint32_t height = signedHeight;
// Early success return cases
@@ -894,16 +899,22 @@ WebGLContext::SetDimensions(int32_t sign
// everything's good, we're done here
mResetLayer = true;
mBackbufferNeedsClear = true;
return NS_OK;
}
+ nsCString failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_WEBGL_UNKOWN");
+ auto autoTelemetry = mozilla::MakeScopeExit([&] {
+ Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_FAILURE_ID,
+ failureId);
+ });
+
// End of early return cases.
// At this point we know that we're not just resizing an existing context,
// we are initializing a new context.
// if we exceeded either the global or the per-principal limit for WebGL contexts,
// lose the oldest-used context now to free resources. Note that we can't do that
// in the WebGLContext constructor as we don't have a canvas element yet there.
// Here is the right place to do so, as we are about to create the OpenGL context
@@ -915,50 +926,47 @@ WebGLContext::SetDimensions(int32_t sign
// context we're creating), we may have to dispatch a context lost
// event.
// If incrementing the generation would cause overflow,
// don't allow it. Allowing this would allow us to use
// resource handles created from older context generations.
if (!(mGeneration + 1).isValid()) {
// exit without changing the value of mGeneration
- Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_FAILURE_ID,
- NS_LITERAL_CSTRING("FEATURE_FAILURE_WEBGL_TOO_MANY"));
+ failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_WEBGL_TOO_MANY");
const nsLiteralCString text("Too many WebGL contexts created this run.");
ThrowEvent_WebGLContextCreationError(text);
return NS_ERROR_FAILURE;
}
// increment the generation number - Do this early because later
// in CreateOffscreenGL(), "default" objects are created that will
// pick up the old generation.
++mGeneration;
bool disabled = gfxPrefs::WebGLDisabled();
// TODO: When we have software webgl support we should use that instead.
disabled |= gfxPlatform::InSafeMode();
if (disabled) {
- Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_FAILURE_ID,
- NS_LITERAL_CSTRING("FEATURE_FAILURE_WEBGL_DISABLED"));
+ failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_WEBGL_DISABLED");
const nsLiteralCString text("WebGL is currently disabled.");
ThrowEvent_WebGLContextCreationError(text);
return NS_ERROR_FAILURE;
}
if (gfxPrefs::WebGLDisableFailIfMajorPerformanceCaveat()) {
mOptions.failIfMajorPerformanceCaveat = false;
}
if (mOptions.failIfMajorPerformanceCaveat) {
nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
if (!HasAcceleratedLayers(gfxInfo)) {
- Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_FAILURE_ID,
- NS_LITERAL_CSTRING("FEATURE_FAILURE_WEBGL_PERF_CAVEAT"));
+ failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_WEBGL_PERF_CAVEAT");
const nsLiteralCString text("failIfMajorPerformanceCaveat: Compositor is not"
" hardware-accelerated.");
ThrowEvent_WebGLContextCreationError(text);
return NS_ERROR_FAILURE;
}
}
// Alright, now let's start trying.
@@ -970,50 +978,50 @@ WebGLContext::SetDimensions(int32_t sign
if (!CreateAndInitGL(forceEnabled, &failReasons)) {
nsCString text("WebGL creation failed: ");
for (const auto& cur : failReasons) {
Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_FAILURE_ID, cur.key);
text.AppendASCII("\n* ");
text.Append(cur.info);
}
+ failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_REASON");
ThrowEvent_WebGLContextCreationError(text);
return NS_ERROR_FAILURE;
}
MOZ_ASSERT(gl);
MOZ_ASSERT_IF(mOptions.alpha, gl->Caps().alpha);
if (mOptions.failIfMajorPerformanceCaveat) {
if (gl->IsWARP()) {
gl = nullptr;
- Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_FAILURE_ID,
- NS_LITERAL_CSTRING("FEATURE_FAILURE_PERF_WARP"));
+ failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_WEBGL_PERF_WARP");
const nsLiteralCString text("failIfMajorPerformanceCaveat: Driver is not"
" hardware-accelerated.");
ThrowEvent_WebGLContextCreationError(text);
return NS_ERROR_FAILURE;
}
#ifdef XP_WIN
if (gl->GetContextType() == gl::GLContextType::WGL &&
!gl::sWGLLib.HasDXInterop2())
{
gl = nullptr;
+ failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_WEBGL_DXGL_INTEROP2");
const nsLiteralCString text("Caveat: WGL without DXGLInterop2.");
ThrowEvent_WebGLContextCreationError(text);
return NS_ERROR_FAILURE;
}
#endif
}
if (!ResizeBackbuffer(width, height)) {
- Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_FAILURE_ID,
- NS_LITERAL_CSTRING("FEATURE_FAILURE_WEBGL_RESIZE"));
+ failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_WEBGL_BACKBUFFER");
const nsLiteralCString text("Initializing WebGL backbuffer failed.");
ThrowEvent_WebGLContextCreationError(text);
return NS_ERROR_FAILURE;
}
if (GLContext::ShouldSpew()) {
printf_stderr("--- WebGL context created: %p\n", gl.get());
}
@@ -1088,18 +1096,17 @@ WebGLContext::SetDimensions(int32_t sign
ClearBackbufferIfNeeded();
mShouldPresent = true;
//////
reporter.SetSuccessful();
- Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_FAILURE_ID,
- NS_LITERAL_CSTRING("SUCCESS"));
+ failureId = NS_LITERAL_CSTRING("SUCCESS");
return NS_OK;
}
void
WebGLContext::ClearBackbufferIfNeeded()
{
if (!mBackbufferNeedsClear)
return;