Bug 1287182 - log angle failureid via ANGLEPlatformInitialize. r=jrmuizel
authorBenoit Girard <b56girard@gmail.com>
Fri, 15 Jul 2016 18:12:46 -0400
changeset 346130 cfb99ceaac776f343540d912f97d49994ca7bed7
parent 346129 67186c2d647ed2807eacc51cc834ca7932d38fba
child 346131 4db532e50f209cd019ec7682dca780f56672d0b4
push id6389
push userraliiev@mozilla.com
push dateMon, 19 Sep 2016 13:38:22 +0000
treeherdermozilla-beta@01d67bfe6c81 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1287182
milestone50.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1287182 - log angle failureid via ANGLEPlatformInitialize. r=jrmuizel MozReview-Commit-ID: 7Cg8AOVij1z
gfx/angle/moz.build
gfx/gl/GLLibraryEGL.cpp
gfx/gl/GLLibraryEGL.h
--- a/gfx/angle/moz.build
+++ b/gfx/angle/moz.build
@@ -158,17 +158,18 @@ DEFINES['EGLAPI'] = ""
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     DIRS += [ 'src/libANGLE', 'src/libGLESv2', 'src/libEGL' ]
 
 DEFINES['ANGLE_ENABLE_HLSL'] = "1"
 DEFINES['ANGLE_ENABLE_GLSL'] = "1"
 DEFINES['ANGLE_ENABLE_ESSL'] = "1"
 DEFINES['ANGLE_ENABLE_KEYEDMUTEX'] = "1"
 
-EXPORTS.angle += [ 'include/GLSLANG/ShaderLang.h', 'include/GLSLANG/ShaderVars.h' ]
+EXPORTS.angle += [ 'include/GLSLANG/ShaderLang.h', 'include/GLSLANG/ShaderVars.h', 'include/platform/Platform.h' ]
+
 EXPORTS.angle.KHR += [ 'include/KHR/khrplatform.h' ]
 
 LOCAL_INCLUDES += [ 'include', 'src', 'src/common/third_party/numerics' ]
 
 # We allow warnings for third-party code that can be updated from upstream.
 ALLOW_COMPILER_WARNINGS = True
 
 FINAL_LIBRARY = 'gkmedias'
--- a/gfx/gl/GLLibraryEGL.cpp
+++ b/gfx/gl/GLLibraryEGL.cpp
@@ -1,20 +1,23 @@
 /* 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 "GLLibraryEGL.h"
 
+#include "angle/Platform.h"
 #include "gfxConfig.h"
 #include "gfxCrashReporterUtils.h"
 #include "gfxUtils.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Assertions.h"
 #include "mozilla/Telemetry.h"
+#include "mozilla/Tokenizer.h"
+#include "mozilla/ScopeExit.h"
 #include "mozilla/unused.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsDirectoryServiceUtils.h"
 #include "nsIGfxInfo.h"
 #include "nsPrintfCString.h"
 #ifdef XP_WIN
 #include "nsWindowsHelpers.h"
 #endif
@@ -167,32 +170,86 @@ GetAndInitDisplay(GLLibraryEGL& egl, voi
         return EGL_NO_DISPLAY;
 
     if (!egl.fInitialize(display, nullptr, nullptr))
         return EGL_NO_DISPLAY;
 
     return display;
 }
 
+class AngleErrorReporting: public angle::Platform {
+public:
+    AngleErrorReporting()
+    {
+      // No static constructor
+    }
+
+    void SetFailureId(nsACString* const aFailureId)
+    {
+      mFailureId = aFailureId;
+    }
+
+    void logError(const char *errorMessage) override
+    {
+        nsCString str(errorMessage);
+        Tokenizer tokenizer(str);
+
+        // Parse "ANGLE Display::initialize error " << error.getID() << ": "
+        //       << error.getMessage()
+        nsCString currWord;
+        Tokenizer::Token intToken;
+        if (tokenizer.CheckWord("ANGLE") &&
+            tokenizer.CheckWhite() &&
+            tokenizer.CheckWord("Display") &&
+            tokenizer.CheckChar(':') &&
+            tokenizer.CheckChar(':') &&
+            tokenizer.CheckWord("initialize") &&
+            tokenizer.CheckWhite() &&
+            tokenizer.CheckWord("error") &&
+            tokenizer.CheckWhite() &&
+            tokenizer.Check(Tokenizer::TOKEN_INTEGER, intToken)) {
+            *mFailureId = "FAILURE_ID_ANGLE_ID_";
+            mFailureId->AppendPrintf("%i", intToken.AsInteger());
+        } else {
+            *mFailureId = "FAILURE_ID_ANGLE_UNKNOWN";
+        }
+    }
+private:
+    nsACString* mFailureId;
+};
+
+AngleErrorReporting gAngleErrorReporter;
+
 static EGLDisplay
-GetAndInitDisplayForAccelANGLE(GLLibraryEGL& egl)
+GetAndInitDisplayForAccelANGLE(GLLibraryEGL& egl, nsACString* const out_failureId)
 {
     EGLDisplay ret = 0;
 
     FeatureState& d3d11ANGLE = gfxConfig::GetFeature(Feature::D3D11_HW_ANGLE);
 
     if (!gfxPrefs::WebGLANGLETryD3D11())
         d3d11ANGLE.UserDisable("User disabled D3D11 ANGLE by pref",
                                NS_LITERAL_CSTRING("FAILURE_ID_ANGLE_PREF"));
 
     if (gfxPrefs::WebGLANGLEForceD3D11())
         d3d11ANGLE.UserForceEnable("User force-enabled D3D11 ANGLE on disabled hardware");
 
-    if (gfxConfig::IsForcedOnByUser(Feature::D3D11_HW_ANGLE))
+    gAngleErrorReporter.SetFailureId(out_failureId);
+    egl.fANGLEPlatformInitialize(&gAngleErrorReporter);
+
+    auto guardShutdown = mozilla::MakeScopeExit([&] {
+        gAngleErrorReporter.SetFailureId(nullptr);
+        // NOTE: Ideally we should be calling ANGLEPlatformShutdown after the
+        //       ANGLE display is destroyed. However gAngleErrorReporter
+        //       will live longer than the ANGLE display so we're fine.
+    });
+
+    if (gfxConfig::IsForcedOnByUser(Feature::D3D11_HW_ANGLE)) {
         return GetAndInitDisplay(egl, LOCAL_EGL_D3D11_ONLY_DISPLAY_ANGLE);
+    }
 
     if (d3d11ANGLE.IsEnabled()) {
         ret = GetAndInitDisplay(egl, LOCAL_EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE);
     }
 
     if (!ret) {
         ret = GetAndInitDisplay(egl, EGL_DEFAULT_DISPLAY);
     }
@@ -367,17 +424,19 @@ GLLibraryEGL::EnsureInitialized(bool for
     InitClientExtensions();
 
     const auto lookupFunction =
         (GLLibraryLoader::PlatformLookupFunction)mSymbols.fGetProcAddress;
 
     // Client exts are ready. (But not display exts!)
     if (IsExtensionSupported(ANGLE_platform_angle_d3d)) {
         GLLibraryLoader::SymLoadStruct d3dSymbols[] = {
-            { (PRFuncPtr*)&mSymbols.fGetPlatformDisplayEXT, { "eglGetPlatformDisplayEXT", nullptr } },
+            { (PRFuncPtr*)&mSymbols.fANGLEPlatformInitialize, { "ANGLEPlatformInitialize", nullptr } },
+            { (PRFuncPtr*)&mSymbols.fANGLEPlatformShutdown,   { "ANGLEPlatformShutdown", nullptr } },
+            { (PRFuncPtr*)&mSymbols.fGetPlatformDisplayEXT,   { "eglGetPlatformDisplayEXT", nullptr } },
             { nullptr, { nullptr } }
         };
 
         bool success = GLLibraryLoader::LoadSymbols(mEGLLibrary,
                                                     &d3dSymbols[0],
                                                     lookupFunction);
         if (!success) {
             NS_ERROR("EGL supports ANGLE_platform_angle_d3d without exposing its functions!");
@@ -402,17 +461,17 @@ GLLibraryEGL::EnsureInitialized(bool for
         // If WARP preferred, will override ANGLE support
         if (gfxPrefs::WebGLANGLEForceWARP()) {
             shouldTryWARP = true;
             shouldTryAccel = false;
         }
 
         // Hardware accelerated ANGLE path (supported or force accel)
         if (shouldTryAccel) {
-            chosenDisplay = GetAndInitDisplayForAccelANGLE(*this);
+            chosenDisplay = GetAndInitDisplayForAccelANGLE(*this, out_failureId);
         }
 
         // Fallback to a WARP display if ANGLE fails, or if WARP is forced
         if (!chosenDisplay && shouldTryWARP) {
             chosenDisplay = GetAndInitWARPDisplay(*this, EGL_DEFAULT_DISPLAY);
             if (!chosenDisplay) {
                 if (out_failureId->IsEmpty()) {
                     *out_failureId = NS_LITERAL_CSTRING("FEATURE_FAILURE_WARP_FALLBACK");
--- a/gfx/gl/GLLibraryEGL.h
+++ b/gfx/gl/GLLibraryEGL.h
@@ -47,16 +47,20 @@
 #endif
 
 #if defined(MOZ_X11)
 #define EGL_DEFAULT_DISPLAY  ((EGLNativeDisplayType)mozilla::DefaultXDisplay())
 #else
 #define EGL_DEFAULT_DISPLAY  ((EGLNativeDisplayType)0)
 #endif
 
+namespace angle {
+class Platform;
+}
+
 namespace mozilla {
 
 namespace gfx {
 class DataSourceSurface;
 }
 
 namespace gl {
 
@@ -111,16 +115,18 @@ public:
           mEGLDisplay(EGL_NO_DISPLAY),
           mIsANGLE(false),
           mIsWARP(false)
     {
         ClearSymbols();
     }
 
     void ClearSymbols() {
+        mSymbols.fANGLEPlatformInitialize = nullptr;
+        mSymbols.fANGLEPlatformShutdown = nullptr;
         mSymbols.fGetDisplay = nullptr;
         mSymbols.fGetPlatformDisplayEXT = nullptr;
         mSymbols.fTerminate = nullptr;
         mSymbols.fGetCurrentSurface = nullptr;
         mSymbols.fGetCurrentContext = nullptr;
         mSymbols.fMakeCurrent = nullptr;
         mSymbols.fDestroyContext = nullptr;
         mSymbols.fCreateContext = nullptr;
@@ -493,16 +499,32 @@ public:
     {
         MOZ_ASSERT(mSymbols.fDupNativeFenceFDANDROID);
         BEFORE_GL_CALL;
         EGLint ret = mSymbols.fDupNativeFenceFDANDROID(dpy, sync);
         AFTER_GL_CALL;
         return ret;
     }
 
+    void fANGLEPlatformInitialize(angle::Platform* platform)
+    {
+        MOZ_ASSERT(mSymbols.fANGLEPlatformInitialize);
+        BEFORE_GL_CALL;
+        mSymbols.fANGLEPlatformInitialize(platform);
+        AFTER_GL_CALL;
+    }
+
+    void fANGLEPlatformShutdown()
+    {
+        MOZ_ASSERT(mSymbols.fANGLEPlatformShutdown);
+        BEFORE_GL_CALL;
+        mSymbols.fANGLEPlatformShutdown();
+        AFTER_GL_CALL;
+    }
+
     EGLDisplay Display() {
         MOZ_ASSERT(mInitialized);
         return mEGLDisplay;
     }
 
     bool IsANGLE() const {
         MOZ_ASSERT(mInitialized);
         return mIsANGLE;
@@ -617,16 +639,21 @@ public:
         typedef EGLBoolean (GLAPIENTRY * pfnDestroySync)(EGLDisplay dpy, EGLSync sync);
         pfnDestroySync fDestroySync;
         typedef EGLint (GLAPIENTRY * pfnClientWaitSync)(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout);
         pfnClientWaitSync fClientWaitSync;
         typedef EGLBoolean (GLAPIENTRY * pfnGetSyncAttrib)(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLint* value);
         pfnGetSyncAttrib fGetSyncAttrib;
         typedef EGLint (GLAPIENTRY * pfnDupNativeFenceFDANDROID)(EGLDisplay dpy, EGLSync sync);
         pfnDupNativeFenceFDANDROID fDupNativeFenceFDANDROID;
+
+        typedef void (GLAPIENTRY * pfnANGLEPlatformInitialize)(angle::Platform* platform);
+        pfnANGLEPlatformInitialize fANGLEPlatformInitialize;
+        typedef void (GLAPIENTRY * pfnANGLEPlatformShutdown)();
+        pfnANGLEPlatformShutdown fANGLEPlatformShutdown;
     } mSymbols;
 
 #ifdef DEBUG
     static void BeforeGLCall(const char* glFunction);
     static void AfterGLCall(const char* glFunction);
 #endif
 
 #ifdef MOZ_B2G