Bug 1297790 - Add GPU process feature status to the Telemetry environment r=dvander,gfritzsche data-review=bsmedberg
☠☠ backed out by 5d06681c5215 ☠ ☠
authorGeorge Wright <george@mozilla.com>
Thu, 27 Oct 2016 11:04:50 -0400
changeset 351850 364305744e4c027386acbd7e2d2a6d55b8729eb3
parent 351849 9e5ff7c0e899b12583deb2a74ea81f6ad197e33e
child 351851 9c1069e2a42e1f296ff040694da3e712ec449ab6
push id6795
push userjlund@mozilla.com
push dateMon, 23 Jan 2017 14:19:46 +0000
treeherdermozilla-esr52@76101b503191 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdvander, gfritzsche
bugs1297790
milestone52.0a1
Bug 1297790 - Add GPU process feature status to the Telemetry environment r=dvander,gfritzsche data-review=bsmedberg
gfx/ipc/GPUChild.cpp
toolkit/components/telemetry/TelemetryEnvironment.jsm
toolkit/components/telemetry/docs/data/environment.rst
toolkit/components/telemetry/tests/unit/test_TelemetryEnvironment.js
widget/GfxInfoBase.cpp
widget/nsIGfxInfo.idl
--- a/gfx/ipc/GPUChild.cpp
+++ b/gfx/ipc/GPUChild.cpp
@@ -166,16 +166,22 @@ GPUChild::ActorDestroy(ActorDestroyReaso
 #ifdef MOZ_CRASHREPORTER
     if (mCrashReporter) {
       mCrashReporter->GenerateCrashReport(OtherPid());
       mCrashReporter = nullptr;
     }
 #endif
     Telemetry::Accumulate(Telemetry::SUBPROCESS_ABNORMAL_ABORT,
         nsDependentCString(XRE_ChildProcessTypeToString(GeckoProcessType_GPU), 1));
+
+    // Notify the Telemetry environment so that we can refresh and do a subsession split
+    if (nsCOMPtr<nsIObserverService> obsvc = services::GetObserverService()) {
+      obsvc->NotifyObservers(nullptr, "compositor:process-aborted", nullptr);
+    }
+
   }
 
   gfxVars::RemoveReceiver(this);
   mHost->OnChannelClosed();
 }
 
 class DeferredDeleteGPUChild : public Runnable
 {
--- a/toolkit/components/telemetry/TelemetryEnvironment.jsm
+++ b/toolkit/components/telemetry/TelemetryEnvironment.jsm
@@ -203,16 +203,17 @@ const PREF_HOTFIX_LASTVERSION = "extensi
 const PREF_APP_PARTNER_BRANCH = "app.partner.";
 const PREF_PARTNER_ID = "mozilla.partner.id";
 const PREF_UPDATE_ENABLED = "app.update.enabled";
 const PREF_UPDATE_AUTODOWNLOAD = "app.update.auto";
 const PREF_SEARCH_COHORT = "browser.search.cohort";
 const PREF_E10S_COHORT = "e10s.rollout.cohort";
 
 const COMPOSITOR_CREATED_TOPIC = "compositor:created";
+const COMPOSITOR_PROCESS_ABORTED_TOPIC = "compositor:process-aborted";
 const DISTRIBUTION_CUSTOMIZATION_COMPLETE_TOPIC = "distribution-customization-complete";
 const EXPERIMENTS_CHANGED_TOPIC = "experiments-changed";
 const GFX_FEATURES_READY_TOPIC = "gfx-features-ready";
 const SEARCH_ENGINE_MODIFIED_TOPIC = "browser-search-engine-modified";
 const SEARCH_SERVICE_TOPIC = "browser-search-service";
 
 /**
  * Enforces the parameter to a boolean value.
@@ -937,24 +938,26 @@ EnvironmentCache.prototype = {
         Preferences.ignore(pref, this._onPrefChanged, this);
       }
     }
   },
 
   _addObservers: function () {
     // Watch the search engine change and service topics.
     Services.obs.addObserver(this, COMPOSITOR_CREATED_TOPIC, false);
+    Services.obs.addObserver(this, COMPOSITOR_PROCESS_ABORTED_TOPIC, false);
     Services.obs.addObserver(this, DISTRIBUTION_CUSTOMIZATION_COMPLETE_TOPIC, false);
     Services.obs.addObserver(this, GFX_FEATURES_READY_TOPIC, false);
     Services.obs.addObserver(this, SEARCH_ENGINE_MODIFIED_TOPIC, false);
     Services.obs.addObserver(this, SEARCH_SERVICE_TOPIC, false);
   },
 
   _removeObservers: function () {
     Services.obs.removeObserver(this, COMPOSITOR_CREATED_TOPIC);
+    Services.obs.removeObserver(this, COMPOSITOR_PROCESS_ABORTED_TOPIC);
     try {
       Services.obs.removeObserver(this, DISTRIBUTION_CUSTOMIZATION_COMPLETE_TOPIC);
     } catch (ex) {}
     Services.obs.removeObserver(this, GFX_FEATURES_READY_TOPIC);
     Services.obs.removeObserver(this, SEARCH_ENGINE_MODIFIED_TOPIC);
     Services.obs.removeObserver(this, SEARCH_SERVICE_TOPIC);
   },
 
@@ -977,16 +980,21 @@ EnvironmentCache.prototype = {
         break;
       case GFX_FEATURES_READY_TOPIC:
       case COMPOSITOR_CREATED_TOPIC:
         // Full graphics information is not available until we have created at
         // least one off-main-thread-composited window. Thus we wait for the
         // first compositor to be created and then query nsIGfxInfo again.
         this._updateGraphicsFeatures();
         break;
+      case COMPOSITOR_PROCESS_ABORTED_TOPIC:
+        // Our compositor process has been killed for whatever reason, so refresh
+        // our reported graphics features and trigger an environment change.
+        this._onCompositorProcessAborted();
+        break;
       case DISTRIBUTION_CUSTOMIZATION_COMPLETE_TOPIC:
         // Distribution customizations are applied after final-ui-startup. query
         // partner prefs again when they are ready.
         this._updatePartner();
         Services.obs.removeObserver(this, aTopic);
         break;
     }
   },
@@ -1050,16 +1058,30 @@ EnvironmentCache.prototype = {
 
     // Finally trigger the environment change notification.
     let oldEnvironment = Cu.cloneInto(this._currentEnvironment, myScope);
     this._updateSearchEngine();
     this._onEnvironmentChange("search-engine-changed", oldEnvironment);
   },
 
   /**
+   * Refresh the Telemetry environment and trigger an environment change due to
+   * a change in compositor process (normally this will mean we've fallen back
+   * from out-of-process to in-process compositing).
+   */
+  _onCompositorProcessAborted: function () {
+    this._log.trace("_onCompositorProcessAborted");
+
+    // Trigger the environment change notification.
+    let oldEnvironment = Cu.cloneInto(this._currentEnvironment, myScope);
+    this._updateGraphicsFeatures();
+    this._onEnvironmentChange("gfx-features-changed", oldEnvironment);
+  },
+
+  /**
    * Update the graphics features object.
    */
   _updateGraphicsFeatures: function () {
     let gfxData = this._currentEnvironment.system.gfx;
     try {
       let gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo);
       gfxData.features = gfxInfo.getFeatures();
     } catch (e) {
--- a/toolkit/components/telemetry/docs/data/environment.rst
+++ b/toolkit/components/telemetry/docs/data/environment.rst
@@ -173,28 +173,31 @@ Structure:
               // Each the following features can have one of the following statuses:
               //   "unused"      - This feature has not been requested.
               //   "unavailable" - Safe Mode or OS restriction prevents use.
               //   "blocked"     - Blocked due to an internal condition such as safe mode.
               //   "blacklisted" - Blocked due to a blacklist restriction.
               //   "disabled"    - User explicitly disabled this default feature.
               //   "failed"      - This feature was attempted but failed to initialize.
               //   "available"   - User has this feature available.
-              "d3d11" { // This feature is Windows-only.
+              d3d11: { // This feature is Windows-only.
                 status: <string>,
                 warp: <bool>,           // Software rendering (WARP) mode was chosen.
                 textureSharing: <bool>  // Whether or not texture sharing works.
                 version: <number>,      // The D3D11 device feature level.
                 blacklisted: <bool>,    // Whether D3D11 is blacklisted; use to see whether WARP
                                         // was blacklist induced or driver-failure induced.
               },
-              "d2d" { // This feature is Windows-only.
+              d2d: { // This feature is Windows-only.
                 status: <string>,
                 version: <string>,      // Either "1.0" or "1.1".
               },
+              gpuProcess: { // Out-of-process compositing ("GPU process") feature
+                status: <string>, // "Available" means currently in use
+              },
             },
           },
       },
       addons: {
         activeAddons: { // the currently enabled addons
           <addon id>: {
             blocklisted: <bool>,
             description: <string>, // null if not available
--- a/toolkit/components/telemetry/tests/unit/test_TelemetryEnvironment.js
+++ b/toolkit/components/telemetry/tests/unit/test_TelemetryEnvironment.js
@@ -630,28 +630,32 @@ function checkSystemSection(data) {
     if (gIsMac) {
       Assert.equal(typeof gfxData.monitors[0].scale, "number");
     }
   }
 
   Assert.equal(typeof gfxData.features, "object");
   Assert.equal(typeof gfxData.features.compositor, "string");
 
+  Assert.equal(typeof gfxData.features.gpuProcess, "object");
+  Assert.equal(typeof gfxData.features.gpuProcess.status, "string");
+
   try {
     // If we've not got nsIGfxInfoDebug, then this will throw and stop us doing
     // this test.
     let gfxInfo = Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfoDebug);
 
     if (gIsWindows || gIsMac) {
       Assert.equal(GFX_VENDOR_ID, gfxData.adapters[0].vendorID);
       Assert.equal(GFX_DEVICE_ID, gfxData.adapters[0].deviceID);
     }
 
     let features = gfxInfo.getFeatures();
     Assert.equal(features.compositor, gfxData.features.compositor);
+    Assert.equal(features.gpuProcess.status, gfxData.features.gpuProcess.status);
     Assert.equal(features.opengl, gfxData.features.opengl);
     Assert.equal(features.webgl, gfxData.features.webgl);
   }
   catch (e) {}
 }
 
 function checkActiveAddon(data) {
   let signedState = mozinfo.addon_signing ? "number" : "undefined";
--- a/widget/GfxInfoBase.cpp
+++ b/widget/GfxInfoBase.cpp
@@ -1326,16 +1326,19 @@ GfxInfoBase::BuildFeatureStateLog(JSCont
   });
 
   return true;
 }
 
 void
 GfxInfoBase::DescribeFeatures(JSContext* aCx, JS::Handle<JSObject*> aObj)
 {
+  JS::Rooted<JSObject*> obj(aCx);
+  gfx::FeatureStatus gpuProcess = gfxConfig::GetValue(Feature::GPU_PROCESS);
+  InitFeatureObject(aCx, aObj, "gpuProcess", FEATURE_GPU_PROCESS, Some(gpuProcess), &obj);
 }
 
 bool
 GfxInfoBase::InitFeatureObject(JSContext* aCx,
                                JS::Handle<JSObject*> aContainer,
                                const char* aName,
                                int32_t aFeature,
                                Maybe<mozilla::gfx::FeatureStatus> aFeatureStatus,
--- a/widget/nsIGfxInfo.idl
+++ b/widget/nsIGfxInfo.idl
@@ -113,16 +113,18 @@ interface nsIGfxInfo : nsISupports
   /* Whether Canvas acceleration is supported, starting in 45 */
   const long FEATURE_CANVAS2D_ACCELERATION = 16;
   /* Whether hardware VP8 decoding is supported, starting in 48. */
   const long FEATURE_VP8_HW_DECODE = 17;
   /* Whether hardware VP9 decoding is supported, starting in 48. */
   const long FEATURE_VP9_HW_DECODE = 18;
   /* Whether NV_dx_interop2 is supported, starting in 50. */
   const long FEATURE_DX_INTEROP2 = 19;
+  /* Whether the GPU process is supported, starting in 52. */
+  const long FEATURE_GPU_PROCESS = 20;
 
   /*
    * A set of return values from GetFeatureStatus
    */
 
   /* The driver is safe to the best of our knowledge */
   const long FEATURE_STATUS_OK = 1;
   /* We don't know the status of the feature yet. The analysis probably hasn't finished yet. */