Bug 1331676 - Avoid doing sync IPC to the parent process for getting gfx feature status; r=dvander
authorEhsan Akhgari <ehsan@mozilla.com>
Mon, 16 Jan 2017 23:05:46 -0500
changeset 374946 2f86db66e8e44f993004c4f4853d0f51a94a381b
parent 374945 8acb67f2e136fd063ab8c2c5b8574b1656da187e
child 374947 5cf462d962ce50af3d801318c58648925457bef9
push id6996
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 20:48:21 +0000
treeherdermozilla-beta@d89512dab048 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdvander
bugs1331676
milestone53.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 1331676 - Avoid doing sync IPC to the parent process for getting gfx feature status; r=dvander
dom/ipc/ContentChild.cpp
dom/ipc/ContentParent.cpp
dom/ipc/ContentParent.h
dom/ipc/PContent.ipdl
widget/GfxInfoBase.cpp
widget/GfxInfoBase.h
widget/nsIGfxInfo.idl
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -191,16 +191,17 @@
 #include "nsDeviceStorage.h"
 #include "DomainPolicy.h"
 #include "mozilla/dom/ipc/StructuredCloneData.h"
 #include "mozilla/dom/time/DateCacheCleaner.h"
 #include "mozilla/net/NeckoMessageUtils.h"
 #include "mozilla/widget/PuppetBidiKeyboard.h"
 #include "mozilla/RemoteSpellCheckEngineChild.h"
 #include "GMPServiceChild.h"
+#include "GfxInfoBase.h"
 #include "gfxPlatform.h"
 #include "nscore.h" // for NS_FREE_PERMANENT_DATA
 #include "VRManagerChild.h"
 
 using namespace mozilla;
 using namespace mozilla::docshell;
 using namespace mozilla::dom::devicestorage;
 using namespace mozilla::dom::ipc;
@@ -606,16 +607,20 @@ ContentChild::Init(MessageLoop* aIOLoop,
 #ifdef NS_PRINTING
   // Force the creation of the nsPrintingProxy so that it's IPC counterpart,
   // PrintingParent, is always available for printing initiated from the parent.
   RefPtr<nsPrintingProxy> printingProxy = nsPrintingProxy::GetInstance();
 #endif
 
   SetProcessName(NS_LITERAL_STRING("Web Content"), true);
 
+  nsTArray<mozilla::dom::GfxInfoFeatureStatus> featureStatus;
+  SendGetGfxInfoFeatureStatus(&featureStatus);
+  GfxInfoBase::SetFeatureStatus(featureStatus);
+
   return true;
 }
 
 void
 ContentChild::SetProcessName(const nsAString& aName, bool aDontOverride)
 {
   if (!mCanOverrideProcessName) {
     return;
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -3758,28 +3758,31 @@ ContentParent::RecvRecordingDeviceEvents
                          aRecordingStatus.get());
   } else {
     NS_WARNING("Could not get the Observer service for ContentParent::RecvRecordingDeviceEvents.");
   }
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
-ContentParent::RecvGetGraphicsFeatureStatus(const int32_t& aFeature,
-                                            int32_t* aStatus,
-                                            nsCString* aFailureId,
-                                            bool* aSuccess)
+ContentParent::RecvGetGfxInfoFeatureStatus(nsTArray<mozilla::dom::GfxInfoFeatureStatus>* aFS)
 {
   nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
   if (!gfxInfo) {
-    *aSuccess = false;
     return IPC_OK();
   }
 
-  *aSuccess = NS_SUCCEEDED(gfxInfo->GetFeatureStatus(aFeature, *aFailureId, aStatus));
+  for (int32_t i = 1; i <= nsIGfxInfo::FEATURE_MAX_VALUE; ++i) {
+    int32_t status = 0;
+    nsAutoCString failureId;
+    gfxInfo->GetFeatureStatus(i, failureId, &status);
+    mozilla::dom::GfxInfoFeatureStatus fs(i, status, failureId);
+    aFS->AppendElement(Move(fs));
+  }
+
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult
 ContentParent::RecvAddIdleObserver(const uint64_t& aObserver,
                                    const uint32_t& aIdleTimeInS)
 {
   nsresult rv;
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -429,16 +429,18 @@ public:
 
   virtual PRemoteSpellcheckEngineParent* AllocPRemoteSpellcheckEngineParent() override;
 
   virtual mozilla::ipc::IPCResult RecvRecordingDeviceEvents(const nsString& aRecordingStatus,
                                                             const nsString& aPageURL,
                                                             const bool& aIsAudio,
                                                             const bool& aIsVideo) override;
 
+  virtual mozilla::ipc::IPCResult RecvGetGfxInfoFeatureStatus(nsTArray<mozilla::dom::GfxInfoFeatureStatus>* aFS) override;
+
   bool CycleCollectWithLogs(bool aDumpAllTraces,
                             nsICycleCollectorLogSink* aSink,
                             nsIDumpGCAndCCLogsCallback* aCallback);
 
   virtual PBlobParent*
   SendPBlobConstructor(PBlobParent* aActor,
                        const BlobConstructorParams& aParams) override;
 
@@ -987,21 +989,16 @@ private:
   virtual void ProcessingError(Result aCode, const char* aMsgName) override;
 
   virtual mozilla::ipc::IPCResult RecvAllocateLayerTreeId(const ContentParentId& aCpId,
                                                           const TabId& aTabId,
                                                           uint64_t* aId) override;
 
   virtual mozilla::ipc::IPCResult RecvDeallocateLayerTreeId(const uint64_t& aId) override;
 
-  virtual mozilla::ipc::IPCResult RecvGetGraphicsFeatureStatus(const int32_t& aFeature,
-                                                               int32_t* aStatus,
-                                                               nsCString* aFailureId,
-                                                               bool* aSuccess) override;
-
   virtual mozilla::ipc::IPCResult RecvGraphicsError(const nsCString& aError) override;
 
   virtual mozilla::ipc::IPCResult
   RecvBeginDriverCrashGuard(const uint32_t& aGuardType,
                             bool* aOutCrashed) override;
 
   virtual mozilla::ipc::IPCResult RecvEndDriverCrashGuard(const uint32_t& aGuardType) override;
 
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -340,16 +340,23 @@ struct GMPAPITags
 
 struct GMPCapabilityData
 {
     nsCString name;
     nsCString version;
     GMPAPITags[] capabilities;
 };
 
+struct GfxInfoFeatureStatus
+{
+    int32_t feature;
+    int32_t status;
+    nsCString failureId;
+};
+
 /**
  * The PContent protocol is a top-level protocol between the UI process
  * and a content process. There is exactly one PContentParent/PContentChild pair
  * for each content process.
  */
 nested(upto inside_cpow) sync protocol PContent
 {
     parent spawns PPluginModule;
@@ -929,18 +936,17 @@ parent:
      * @param isAudio recording start with microphone
      * @param isVideo recording start with camera
      */
     async RecordingDeviceEvents(nsString recordingStatus,
                                 nsString pageURL,
                                 bool isAudio,
                                 bool isVideo);
 
-    sync GetGraphicsFeatureStatus(int32_t aFeature) returns (int32_t aStatus, nsCString aFailureCode,
-                                                             bool aSuccess);
+    sync GetGfxInfoFeatureStatus() returns (GfxInfoFeatureStatus[] features);
 
     // Graphics errors
     async GraphicsError(nsCString aError);
 
     // Driver crash guards. aGuardType must be a member of CrashGuardType.
     sync BeginDriverCrashGuard(uint32_t aGuardType) returns (bool crashDetected);
     sync EndDriverCrashGuard(uint32_t aGuardType);
 
--- a/widget/GfxInfoBase.cpp
+++ b/widget/GfxInfoBase.cpp
@@ -42,16 +42,17 @@
 #include "nsExceptionHandler.h"
 #endif
 
 using namespace mozilla::widget;
 using namespace mozilla;
 using mozilla::MutexAutoLock;
 
 nsTArray<GfxDriverInfo>* GfxInfoBase::mDriverInfo;
+nsTArray<dom::GfxInfoFeatureStatus>* GfxInfoBase::mFeatureStatus;
 bool GfxInfoBase::mDriverInfoObserverInitialized;
 bool GfxInfoBase::mShutdownOccurred;
 
 // Observes for shutdown so that the child GfxDriverInfo list is freed.
 class ShutdownObserver : public nsIObserver
 {
   virtual ~ShutdownObserver() {}
 
@@ -63,16 +64,19 @@ public:
   NS_IMETHOD Observe(nsISupports *subject, const char *aTopic,
                      const char16_t *aData) override
   {
     MOZ_ASSERT(strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0);
 
     delete GfxInfoBase::mDriverInfo;
     GfxInfoBase::mDriverInfo = nullptr;
 
+    delete GfxInfoBase::mFeatureStatus;
+    GfxInfoBase::mFeatureStatus = nullptr;
+
     for (uint32_t i = 0; i < DeviceFamilyMax; i++)
       delete GfxDriverInfo::mDeviceFamilies[i];
 
     for (uint32_t i = 0; i < DeviceVendorMax; i++)
       delete GfxDriverInfo::mDeviceVendors[i];
 
     GfxInfoBase::mShutdownOccurred = true;
 
@@ -594,23 +598,28 @@ GfxInfoBase::GetFeatureStatus(int32_t aF
     return NS_OK;
   }
 
   if (GetPrefValueForFeature(aFeature, *aStatus, aFailureId)) {
     return NS_OK;
   }
 
   if (XRE_IsContentProcess()) {
-      // Delegate to the parent process.
-      mozilla::dom::ContentChild* cc = mozilla::dom::ContentChild::GetSingleton();
-      bool success;
-      nsCString remoteFailureId;
-      cc->SendGetGraphicsFeatureStatus(aFeature, aStatus, &remoteFailureId, &success);
-      aFailureId = remoteFailureId;
-      return success ? NS_OK : NS_ERROR_FAILURE;
+    // Use the cached data received from the parent process.
+    MOZ_ASSERT(mFeatureStatus);
+    bool success = false;
+    for (const auto& fs : *mFeatureStatus) {
+      if (fs.feature() == aFeature) {
+        aFailureId = fs.failureId();
+        *aStatus = fs.status();
+        success = true;
+        break;
+      }
+    }
+    return success ? NS_OK : NS_ERROR_FAILURE;
   }
 
   nsString version;
   nsTArray<GfxDriverInfo> driverInfo;
   nsresult rv = GetFeatureStatusImpl(aFeature, aStatus, version, driverInfo, aFailureId);
   return rv;
 }
 
@@ -842,16 +851,23 @@ GfxInfoBase::FindBlocklistedDeviceInList
                                       (info[i].mDriverVersion & 0x000000000000ffff));
     }
   }
 #endif
 
   return status;
 }
 
+void
+GfxInfoBase::SetFeatureStatus(const nsTArray<dom::GfxInfoFeatureStatus>& aFS)
+{
+  MOZ_ASSERT(!mFeatureStatus);
+  mFeatureStatus = new nsTArray<dom::GfxInfoFeatureStatus>(aFS);
+}
+
 nsresult
 GfxInfoBase::GetFeatureStatusImpl(int32_t aFeature,
                                   int32_t* aStatus,
                                   nsAString& aSuggestedVersion,
                                   const nsTArray<GfxDriverInfo>& aDriverInfo,
                                   nsACString& aFailureId,
                                   OperatingSystem* aOS /* = nullptr */)
 {
--- a/widget/GfxInfoBase.h
+++ b/widget/GfxInfoBase.h
@@ -11,16 +11,17 @@
 #include "GfxDriverInfo.h"
 #include "GfxInfoCollector.h"
 #include "gfxFeature.h"
 #include "gfxTelemetry.h"
 #include "js/Value.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/Maybe.h"
 #include "mozilla/Mutex.h"
+#include "mozilla/dom/PContentParent.h"
 #include "nsCOMPtr.h"
 #include "nsIGfxInfo.h"
 #include "nsIGfxInfoDebug.h"
 #include "nsIObserver.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsWeakReference.h"
 
@@ -72,32 +73,36 @@ public:
   
   // only useful on X11
   NS_IMETHOD_(void) GetData() override { }
 
   static void AddCollector(GfxInfoCollectorBase* collector);
   static void RemoveCollector(GfxInfoCollectorBase* collector);
 
   static nsTArray<GfxDriverInfo>* mDriverInfo;
+  static nsTArray<mozilla::dom::GfxInfoFeatureStatus>* mFeatureStatus;
   static bool mDriverInfoObserverInitialized;
   static bool mShutdownOccurred;
 
   virtual nsString Model() { return EmptyString(); }
   virtual nsString Hardware() { return EmptyString(); }
   virtual nsString Product() { return EmptyString(); }
   virtual nsString Manufacturer() { return EmptyString(); }
   virtual uint32_t OperatingSystemVersion() { return 0; }
 
   // Convenience to get the application version
   static const nsCString& GetApplicationVersion();
 
   virtual nsresult FindMonitors(JSContext* cx, JS::HandleObject array) {
     return NS_ERROR_NOT_IMPLEMENTED;
   }
 
+  static void SetFeatureStatus(
+      const nsTArray<mozilla::dom::GfxInfoFeatureStatus>& aFS);
+
 protected:
 
   virtual ~GfxInfoBase();
 
   virtual nsresult GetFeatureStatusImpl(int32_t aFeature, int32_t* aStatus,
                                         nsAString& aSuggestedDriverVersion,
                                         const nsTArray<GfxDriverInfo>& aDriverInfo,
                                         nsACString& aFailureId,
--- a/widget/nsIGfxInfo.idl
+++ b/widget/nsIGfxInfo.idl
@@ -116,16 +116,18 @@ interface nsIGfxInfo : nsISupports
   /* 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;
+  /* the maximum feature value. */
+  const long FEATURE_MAX_VALUE = FEATURE_GPU_PROCESS;
 
   /*
    * 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. */