Bug 1272808 - Expose context creation error to telemetry. r=jgilbert draft
authorBenoit Girard <b56girard@gmail.com>
Fri, 20 May 2016 13:14:15 -0400
changeset 369197 7871e153914b76f7c8081b7529a2c02626bc7d2a
parent 368365 c4449eab07d39e20ea315603f1b1863eeed7dcfe
child 369234 d08b65582a8fa46cb8f1594009fd640eb3e3845e
push id18777
push userb56girard@gmail.com
push dateFri, 20 May 2016 17:14:35 +0000
reviewersjgilbert
bugs1272808
milestone49.0a1
Bug 1272808 - Expose context creation error to telemetry. r=jgilbert MozReview-Commit-ID: JQ4rHZf71RW
dom/canvas/WebGL2Context.cpp
dom/canvas/WebGLContext.cpp
dom/canvas/WebGLContext.h
dom/canvas/WebGLContextValidate.cpp
toolkit/components/telemetry/Histograms.json
--- a/dom/canvas/WebGL2Context.cpp
+++ b/dom/canvas/WebGL2Context.cpp
@@ -91,26 +91,27 @@ static const gl::GLFeature kRequiredFeat
     gl::GLFeature::texture_storage,
     gl::GLFeature::transform_feedback2,
     gl::GLFeature::uniform_buffer_object,
     gl::GLFeature::uniform_matrix_nonsquare,
     gl::GLFeature::vertex_array_object
 };
 
 bool
-WebGLContext::InitWebGL2(nsACString* const out_failReason)
+WebGLContext::InitWebGL2(nsACString* const out_failReason, nsACString* const out_failureId)
 {
     MOZ_ASSERT(IsWebGL2(), "WebGLContext is not a WebGL 2 context!");
 
     // check OpenGL features
     if (!gl->IsSupported(gl::GLFeature::occlusion_query) &&
         !gl->IsSupported(gl::GLFeature::occlusion_query_boolean))
     {
         // On desktop, we fake occlusion_query_boolean with occlusion_query if
         // necessary. (See WebGL2ContextQueries.cpp)
+        *out_failureId = "FEATURE_FAILURE_WEBGL2_OCCL";
         out_failReason->AssignASCII("WebGL 2 requires occlusion query support.");
         return false;
     }
 
     std::vector<gl::GLFeature> missingList;
 
     for (size_t i = 0; i < ArrayLength(kRequiredFeatures); i++) {
         if (!gl->IsSupported(kRequiredFeatures[i])) {
@@ -129,16 +130,17 @@ WebGLContext::InitWebGL2(nsACString* con
 
     if (missingList.size()) {
         nsAutoCString exts;
         for (auto itr = missingList.begin(); itr != missingList.end(); ++itr) {
             exts.AppendLiteral("\n  ");
             exts.Append(gl::GLContext::GetFeatureName(*itr));
         }
 
+        *out_failureId = "FEATURE_FAILURE_WEBGL2_FEATURE";
         const nsPrintfCString reason("WebGL 2 requires support for the following"
                                      " features: %s",
                                      exts.BeginReading());
         out_failReason->Assign(reason);
         return false;
     }
 
     // we initialise WebGL 2 related stuff.
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -426,22 +426,21 @@ WebGLContext::GetHeight() const
  *
  * That is, try to create headless contexts based on the platform API.
  * Next, create dummy-sized backbuffers for the contexts with the right
  * caps. Finally, resize the backbuffer to an acceptable size given the
  * requested size.
  */
 
 static bool
-IsFeatureInBlacklist(const nsCOMPtr<nsIGfxInfo>& gfxInfo, int32_t feature)
+IsFeatureInBlacklist(const nsCOMPtr<nsIGfxInfo>& gfxInfo, int32_t feature, nsACString* const out_failureId)
 {
     int32_t status;
-    nsCString discardFailureId;
     if (!NS_SUCCEEDED(gfxUtils::ThreadSafeGetFeatureStatus(gfxInfo, feature,
-                                                           discardFailureId, &status)))
+                                                           *out_failureId, &status)))
         return false;
 
     return status != nsIGfxInfo::FEATURE_STATUS_OK;
 }
 
 static bool
 HasAcceleratedLayers(const nsCOMPtr<nsIGfxInfo>& gfxInfo)
 {
@@ -557,81 +556,87 @@ BaseCaps(const WebGLContextOptions& opti
         baseCaps.surfaceAllocator = static_cast<layers::ISurfaceAllocator*>(forwarder);
     } while (false);
 #endif
 
     // Done with baseCaps construction.
 
     bool forceAllowAA = gfxPrefs::WebGLForceMSAA();
     nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
+    nsCString discardFailureId;
     if (!forceAllowAA &&
-        IsFeatureInBlacklist(gfxInfo, nsIGfxInfo::FEATURE_WEBGL_MSAA))
+        IsFeatureInBlacklist(gfxInfo, nsIGfxInfo::FEATURE_WEBGL_MSAA, &discardFailureId))
     {
         webgl->GenerateWarning("Disallowing antialiased backbuffers due"
                                " to blacklisting.");
         baseCaps.antialias = false;
     }
 
     return baseCaps;
 }
 
 ////////////////////////////////////////
 
 static already_AddRefed<gl::GLContext>
 CreateGLWithEGL(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
-                WebGLContext* webgl, nsACString* const out_failReason)
+                WebGLContext* webgl, nsACString* const out_failReason,
+                nsACString* const out_failureId)
 {
     const gfx::IntSize dummySize(16, 16);
     RefPtr<GLContext> gl = gl::GLContextProviderEGL::CreateOffscreen(dummySize, caps,
                                                                      flags);
     if (gl && gl->IsANGLE()) {
         gl = nullptr;
     }
 
     if (!gl) {
         if (out_failReason->Length()) {
             out_failReason->AppendLiteral("\n");
         }
         out_failReason->AppendLiteral("Error during EGL OpenGL init.");
+        *out_failureId = "FEATURE_FAILURE_WEBGL_EGL_INIT";
         return nullptr;
     }
 
     return gl.forget();
 }
 
 static already_AddRefed<GLContext>
 CreateGLWithANGLE(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
-                  WebGLContext* webgl, nsACString* const out_failReason)
+                  WebGLContext* webgl, nsACString* const out_failReason,
+                  nsACString* const out_failureId)
 {
     const gfx::IntSize dummySize(16, 16);
     RefPtr<GLContext> gl = gl::GLContextProviderEGL::CreateOffscreen(dummySize, caps,
                                                                      flags);
     if (gl && !gl->IsANGLE()) {
         gl = nullptr;
     }
 
     if (!gl) {
         if (out_failReason->Length()) {
             out_failReason->AppendLiteral("\n");
         }
         out_failReason->AppendLiteral("Error during ANGLE OpenGL init.");
+        *out_failureId = "FEATURE_FAILURE_WEBGL_ANGLE_INIT";
         return nullptr;
     }
 
     return gl.forget();
 }
 
 static already_AddRefed<gl::GLContext>
 CreateGLWithDefault(const gl::SurfaceCaps& caps, gl::CreateContextFlags flags,
-                    WebGLContext* webgl, nsACString* const out_failReason)
+                    WebGLContext* webgl, nsACString* const out_failReason,
+                    nsACString* const out_failureId)
 {
     nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
 
     if (!(flags & CreateContextFlags::FORCE_ENABLE_HARDWARE) &&
-        IsFeatureInBlacklist(gfxInfo, nsIGfxInfo::FEATURE_WEBGL_OPENGL))
+        IsFeatureInBlacklist(gfxInfo, nsIGfxInfo::FEATURE_WEBGL_OPENGL, out_failureId))
     {
         if (out_failReason->Length()) {
             out_failReason->AppendASCII("\n");
         }
         out_failReason->AppendASCII("Refused to create native OpenGL context because of"
                                     " blacklisting.");
         return nullptr;
     }
@@ -643,57 +648,60 @@ CreateGLWithDefault(const gl::SurfaceCap
         gl = nullptr;
     }
 
     if (!gl) {
         if (out_failReason->Length()) {
             out_failReason->AppendASCII("\n");
         }
         out_failReason->AppendASCII("Error during native OpenGL init.");
+        *out_failureId = "FEATURE_FAILURE_WEBGL_DEFAULT_INIT";
         return nullptr;
     }
 
     return gl.forget();
 }
 
 ////////////////////////////////////////
 
 bool
 WebGLContext::CreateAndInitGLWith(FnCreateGL_T fnCreateGL,
                                   const gl::SurfaceCaps& baseCaps,
                                   gl::CreateContextFlags flags,
-                                  nsACString* const out_failReason)
+                                  nsACString* const out_failReason,
+                                  nsACString* const out_failureId)
 {
     std::queue<gl::SurfaceCaps> fallbackCaps;
     PopulateCapFallbackQueue(baseCaps, &fallbackCaps);
 
     MOZ_RELEASE_ASSERT(!gl);
     gl = nullptr;
     while (!fallbackCaps.empty()) {
         gl::SurfaceCaps& caps = fallbackCaps.front();
 
-        gl = fnCreateGL(caps, flags, this, out_failReason);
+        gl = fnCreateGL(caps, flags, this, out_failReason, out_failureId);
         if (gl)
             break;
 
         fallbackCaps.pop();
     }
     if (!gl)
         return false;
 
-    if (!InitAndValidateGL(out_failReason)) {
+    if (!InitAndValidateGL(out_failReason, out_failureId)) {
+        // The fail reason here should be specific enough for now.
         gl = nullptr;
         return false;
     }
 
     return true;
 }
 
 bool
-WebGLContext::CreateAndInitGL(bool forceEnabled, nsACString* const out_failReason)
+WebGLContext::CreateAndInitGL(bool forceEnabled, nsACString* const out_failReason, nsACString* const out_failureId)
 {
     const bool useEGL = PR_GetEnv("MOZ_WEBGL_PREFER_EGL");
 
     bool useANGLE = false;
 #ifdef XP_WIN
     const bool disableANGLE = (gfxPrefs::WebGLDisableANGLE() ||
                                PR_GetEnv("MOZ_WEBGL_FORCE_OPENGL"));
     useANGLE = !disableANGLE;
@@ -702,22 +710,22 @@ WebGLContext::CreateAndInitGL(bool force
     gl::CreateContextFlags flags = gl::CreateContextFlags::NONE;
     if (forceEnabled) flags |= gl::CreateContextFlags::FORCE_ENABLE_HARDWARE;
     if (!IsWebGL2())  flags |= gl::CreateContextFlags::REQUIRE_COMPAT_PROFILE;
     if (IsWebGL2())   flags |= gl::CreateContextFlags::PREFER_ES3;
 
     const gl::SurfaceCaps baseCaps = BaseCaps(mOptions, this);
 
     if (useEGL)
-        return CreateAndInitGLWith(CreateGLWithEGL, baseCaps, flags, out_failReason);
+        return CreateAndInitGLWith(CreateGLWithEGL, baseCaps, flags, out_failReason, out_failureId);
 
     if (useANGLE)
-        return CreateAndInitGLWith(CreateGLWithANGLE, baseCaps, flags, out_failReason);
+        return CreateAndInitGLWith(CreateGLWithANGLE, baseCaps, flags, out_failReason, out_failureId);
 
-    return CreateAndInitGLWith(CreateGLWithDefault, baseCaps, flags, out_failReason);
+    return CreateAndInitGLWith(CreateGLWithDefault, baseCaps, flags, out_failReason, out_failureId);
 }
 
 // Fallback for resizes:
 bool
 WebGLContext::ResizeBackbuffer(uint32_t requestedWidth,
                                uint32_t requestedHeight)
 {
     uint32_t width = requestedWidth;
@@ -859,68 +867,78 @@ 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"));
         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"));
         const nsLiteralCString text("WebGL is currently disabled.");
         ThrowEvent_WebGLContextCreationError(text);
         return NS_ERROR_FAILURE;
     }
 
     bool failIfPerfCaveat = mOptions.failIfMajorPerformanceCaveat;
     if (gfxPrefs::WebGLDisableFailIfMajorPerformanceCaveat())
         failIfPerfCaveat = false;
 
     if (failIfPerfCaveat) {
         nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
         if (!HasAcceleratedLayers(gfxInfo)) {
+            Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_FAILURE_ID,
+                                  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.
     bool forceEnabled = gfxPrefs::WebGLForceEnabled();
     ScopedGfxFeatureReporter reporter("WebGL", forceEnabled);
 
     MOZ_ASSERT(!gl);
     nsCString failReason;
-    if (!CreateAndInitGL(forceEnabled, &failReason)) {
+    nsCString failureId;
+    if (!CreateAndInitGL(forceEnabled, &failReason, &failureId)) {
+        Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_FAILURE_ID, failureId);
         const nsPrintfCString text("WebGL creation failed: %s",
                                    failReason.BeginReading());
         ThrowEvent_WebGLContextCreationError(text);
         return NS_ERROR_FAILURE;
     }
     MOZ_ASSERT(gl);
 
     MOZ_ASSERT_IF(mOptions.alpha, gl->Caps().alpha);
 
     if (!ResizeBackbuffer(width, height)) {
+        Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_FAILURE_ID,
+                              NS_LITERAL_CSTRING("FEATURE_FAILURE_WEBGL_RESIZE"));
         const nsLiteralCString text("Initializing WebGL backbuffer failed.");
         ThrowEvent_WebGLContextCreationError(text);
         return NS_ERROR_FAILURE;
     }
 
 #ifdef DEBUG
     if (gl->DebugMode())
         printf_stderr("--- WebGL context created: %p\n", gl.get());
@@ -993,16 +1011,19 @@ WebGLContext::SetDimensions(int32_t sign
 
     MOZ_ASSERT(gl->Caps().antialias == mOptions.antialias);
     MOZ_ASSERT(gl->Caps().preserve == mOptions.preserveDrawingBuffer);
 
     AssertCachedBindings();
     AssertCachedState();
 
     reporter.SetSuccessful();
+
+    Telemetry::Accumulate(Telemetry::CANVAS_WEBGL_FAILURE_ID,
+                          NS_LITERAL_CSTRING("SUCCESS"));
     return NS_OK;
 }
 
 void
 WebGLContext::ClearBackbufferIfNeeded()
 {
     if (!mBackbufferNeedsClear)
         return;
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -1196,34 +1196,36 @@ protected:
     nsTArray<GLenum> mCompressedTextureFormats;
 
     // -------------------------------------------------------------------------
     // WebGL 2 specifics (implemented in WebGL2Context.cpp)
 public:
     virtual bool IsWebGL2() const = 0;
 
 protected:
-    bool InitWebGL2(nsACString* const out_failReason);
+    bool InitWebGL2(nsACString* const out_failReason, nsACString* const out_failureId);
 
-    bool CreateAndInitGL(bool forceEnabled, nsACString* const out_failReason);
+    bool CreateAndInitGL(bool forceEnabled, nsACString* const out_failReason, nsACString* const out_failureId);
     bool ResizeBackbuffer(uint32_t width, uint32_t height);
 
     typedef already_AddRefed<gl::GLContext> FnCreateGL_T(const gl::SurfaceCaps& caps,
                                                          gl::CreateContextFlags flags,
                                                          WebGLContext* webgl,
-                                                         nsACString* const out_failReason);
+                                                         nsACString* const out_failReason,
+                                                         nsACString* const out_failureId);
 
     bool CreateAndInitGLWith(FnCreateGL_T fnCreateGL, const gl::SurfaceCaps& baseCaps,
                              gl::CreateContextFlags flags,
-                             nsACString* const out_failReason);
+                             nsACString* const out_failReason,
+                             nsACString* const out_failureId);
     void ThrowEvent_WebGLContextCreationError(const nsACString& text);
 
     // -------------------------------------------------------------------------
     // Validation functions (implemented in WebGLContextValidate.cpp)
-    bool InitAndValidateGL(nsACString* const out_failReason);
+    bool InitAndValidateGL(nsACString* const out_failReason, nsACString* const out_failureId);
     bool ValidateBlendEquationEnum(GLenum cap, const char* info);
     bool ValidateBlendFuncDstEnum(GLenum mode, const char* info);
     bool ValidateBlendFuncSrcEnum(GLenum mode, const char* info);
     bool ValidateBlendFuncEnumsCompatibility(GLenum sfactor, GLenum dfactor,
                                              const char* info);
     bool ValidateDataOffsetSize(WebGLintptr offset, WebGLsizeiptr size, WebGLsizeiptr bufferSize, const char* info);
     bool ValidateDataRanges(WebGLintptr readOffset, WebGLintptr writeOffset, WebGLsizeiptr size, const char* info);
     bool ValidateTextureTargetEnum(GLenum target, const char* info);
--- a/dom/canvas/WebGLContextValidate.cpp
+++ b/dom/canvas/WebGLContextValidate.cpp
@@ -640,31 +640,33 @@ FloorPOT(int32_t x)
         if (x < pot*2)
             break;
         pot *= 2;
     }
     return pot;
 }
 
 bool
-WebGLContext::InitAndValidateGL(nsACString* const out_failReason)
+WebGLContext::InitAndValidateGL(nsACString* const out_failReason, nsACString* const out_failureId)
 {
     MOZ_RELEASE_ASSERT(gl);
 
     // Unconditionally create a new format usage authority. This is
     // important when restoring contexts and extensions need to add
     // formats back into the authority.
     mFormatUsage = CreateFormatUsage(gl);
     if (!mFormatUsage) {
+        *out_failureId = "FEATURE_FAILURE_WEBGL_FORMAT";
         out_failReason->AssignLiteral("Failed to create mFormatUsage.");
         return false;
     }
 
     GLenum error = gl->fGetError();
     if (error != LOCAL_GL_NO_ERROR) {
+        *out_failureId = "FEATURE_FAILURE_WEBGL_GLERR_1";
         const nsPrintfCString reason("GL error 0x%x occurred during OpenGL context"
                                      " initialization, before WebGL initialization!",
                                      error);
         out_failReason->Assign(reason);
         return false;
     }
 
     mMinCapability = gfxPrefs::WebGLMinCapabilityMode();
@@ -747,31 +749,33 @@ WebGLContext::InitAndValidateGL(nsACStri
         gl->fEnableVertexAttribArray(0);
 
     if (MinCapabilityMode())
         mGLMaxVertexAttribs = MINVALUE_GL_MAX_VERTEX_ATTRIBS;
     else
         gl->fGetIntegerv(LOCAL_GL_MAX_VERTEX_ATTRIBS, &mGLMaxVertexAttribs);
 
     if (mGLMaxVertexAttribs < 8) {
+        *out_failureId = "FEATURE_FAILURE_WEBGL_V_ATRB";
         const nsPrintfCString reason("GL_MAX_VERTEX_ATTRIBS: %d is < 8!",
                                      mGLMaxVertexAttribs);
         out_failReason->Assign(reason);
         return false;
     }
 
     // Note: GL_MAX_TEXTURE_UNITS is fixed at 4 for most desktop hardware,
     // even though the hardware supports much more.  The
     // GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS value is the accurate value.
     if (MinCapabilityMode())
         mGLMaxTextureUnits = MINVALUE_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS;
     else
         gl->fGetIntegerv(LOCAL_GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &mGLMaxTextureUnits);
 
     if (mGLMaxTextureUnits < 8) {
+        *out_failureId = "FEATURE_FAILURE_WEBGL_T_UNIT";
         const nsPrintfCString reason("GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS: %d is < 8!",
                                      mGLMaxTextureUnits);
         out_failReason->Assign(reason);
         return false;
     }
 
     mBound2DTextures.SetLength(mGLMaxTextureUnits);
     mBoundCubeMapTextures.SetLength(mGLMaxTextureUnits);
@@ -920,39 +924,41 @@ WebGLContext::InitAndValidateGL(nsACStri
         gl->fEnable(LOCAL_GL_TEXTURE_CUBE_MAP_SEAMLESS);
     }
 
     // Check the shader validator pref
     mBypassShaderValidation = gfxPrefs::WebGLBypassShaderValidator();
 
     // initialize shader translator
     if (!ShInitialize()) {
+        *out_failureId = "FEATURE_FAILURE_WEBGL_GLSL";
         out_failReason->AssignLiteral("GLSL translator initialization failed!");
         return false;
     }
 
     // Mesa can only be detected with the GL_VERSION string, of the form
     // "2.1 Mesa 7.11.0"
     const char* versionStr = (const char*)(gl->fGetString(LOCAL_GL_VERSION));
     mIsMesa = strstr(versionStr, "Mesa");
 
     // Notice that the point of calling fGetError here is not only to check for
     // errors, but also to reset the error flags so that a subsequent WebGL
     // getError call will give the correct result.
     error = gl->fGetError();
     if (error != LOCAL_GL_NO_ERROR) {
+        *out_failureId = "FEATURE_FAILURE_WEBGL_GLERR_2";
         const nsPrintfCString reason("GL error 0x%x occurred during WebGL context"
                                      " initialization!",
                                      error);
         out_failReason->Assign(reason);
         return false;
     }
 
     if (IsWebGL2() &&
-        !InitWebGL2(out_failReason))
+        !InitWebGL2(out_failReason, out_failureId))
     {
         // Todo: Bug 898404: Only allow WebGL2 on GL>=3.0 on desktop GL.
         return false;
     }
 
     // Default value for all disabled vertex attributes is [0, 0, 0, 1]
     mVertexAttribType = MakeUnique<GLenum[]>(mGLMaxVertexAttribs);
     for (int32_t index = 0; index < mGLMaxVertexAttribs; ++index) {
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -1048,28 +1048,36 @@
     "n_buckets": 50,
     "description": "PNG image decode speed (Kbytes/sec)"
   },
   "CANVAS_2D_USED": {
     "expires_in_version": "never",
     "kind": "boolean",
     "description": "2D canvas used"
   },
-  "CANVAS_WEBGL_USED": {
-    "expires_in_version": "never",
-    "kind": "boolean",
-    "description": "WebGL canvas used"
+  "CANVAS_WEBGL_FAILURE_ID": {
+    "alert_emails": ["bgirard@mozilla.com"],
+    "expires_in_version": "never",
+    "kind": "count",
+    "keyed": true,
+    "description": "WebGL runtime and dynamic failure IDs. This will record a count for each context creation success or failure. Each failure id is a unique identifier that can be traced back to a particular failure branch or blocklist rule.",
+    "bug_numbers": [1272808]
   },
   "CANVAS_WEBGL_SUCCESS": {
     "alert_emails": ["jmuizelaar@mozilla.com"],
     "expires_in_version": "never",
     "kind": "boolean",
     "description": "WebGL1 creation success",
     "bug_numbers": [1247327]
   },
+  "CANVAS_WEBGL_USED": {
+    "expires_in_version": "never",
+    "kind": "boolean",
+    "description": "WebGL canvas used"
+  },
   "CANVAS_WEBGL2_SUCCESS": {
     "alert_emails": ["jmuizelaar@mozilla.com"],
     "expires_in_version": "never",
     "kind": "boolean",
     "description": "WebGL2 creation success",
     "bug_numbers": [1247327]
   },
   "TOTAL_CONTENT_PAGE_LOAD_TIME": {