Bug 1637437 - Recompute backdrop-filter only when WebRender changes r=jrmuizel
authorErik Nordin <nordzilla@mozilla.com>
Wed, 27 May 2020 19:53:05 +0000
changeset 532604 090e5dcb0308dfe72c01ff264332c1a25bfb1fdf
parent 532603 004abcb3322e94e257226a058ec78e0d02c0d582
child 532605 4626bc2c944d531971159e127b663e8232427a24
push id117264
push userrmaries@mozilla.com
push dateWed, 27 May 2020 20:49:37 +0000
treeherderautoland@090e5dcb0308 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1637437
milestone78.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 1637437 - Recompute backdrop-filter only when WebRender changes r=jrmuizel - Add a gfxVarReceiver for nsCSSProps. - Recompute backdrop-filter state when notifying receivers for WebRender. - Remove NS_NewRunableFunction calls when we know we're on main thread. - Add assertion that recompute enabled state is called from main thread. Differential Revision: https://phabricator.services.mozilla.com/D74975
gfx/thebes/gfxPlatform.cpp
layout/style/nsCSSProps.cpp
layout/style/nsCSSProps.h
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -802,22 +802,16 @@ static void FrameRatePrefChanged(const c
                         ? gfxPlatform::GetSoftwareVsyncRate()
                         : -1;
   if (newRate != gLastUsedFrameRate) {
     gLastUsedFrameRate = newRate;
     gfxPlatform::ReInitFrameRate();
   }
 }
 
-static void RecomputeBackdropFilterEnabledState() {
-  NS_DispatchToMainThread(NS_NewRunnableFunction("RecomputeEnabledState", [] {
-    nsCSSProps::RecomputeEnabledState("layout.css.backdrop-filter.enabled");
-  }));
-}
-
 void gfxPlatform::Init() {
   MOZ_RELEASE_ASSERT(!XRE_IsGPUProcess(), "GFX: Not allowed in GPU process.");
   MOZ_RELEASE_ASSERT(!XRE_IsRDDProcess(), "GFX: Not allowed in RDD process.");
   MOZ_RELEASE_ASSERT(NS_IsMainThread(), "GFX: Not in main thread.");
 
   if (gEverInitialized) {
     MOZ_CRASH("Already started???");
   }
@@ -1079,18 +1073,16 @@ void gfxPlatform::Init() {
   if (XRE_IsParentProcess()) {
     ReportTelemetry();
   }
 
   nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
   if (obs) {
     obs->NotifyObservers(nullptr, "gfx-features-ready", nullptr);
   }
-
-  RecomputeBackdropFilterEnabledState();
 }
 
 void gfxPlatform::ReportTelemetry() {
   MOZ_RELEASE_ASSERT(XRE_IsParentProcess(),
                      "GFX: Only allowed to be called from parent process.");
 
   nsCOMPtr<nsIGfxInfo> gfxInfo = services::GetGfxInfo();
   nsTArray<uint32_t> displayWidths;
@@ -2688,30 +2680,38 @@ bool gfxPlatform::WebRenderEnvvarDisable
   const char* env = PR_GetEnv("MOZ_WEBRENDER");
   return (env && *env == '0');
 }
 
 void gfxPlatform::InitWebRenderConfig() {
   bool prefEnabled = WebRenderPrefEnabled();
   bool envvarEnabled = WebRenderEnvvarEnabled();
 
+  // This would ideally be in the nsCSSProps code
+  // but nsCSSProps is initialized before gfxPlatform
+  // so it has to be done here.
+  gfxVars::AddReceiver(&nsCSSProps::GfxVarReceiver());
+
   // WR? WR+   => means WR was enabled via gfx.webrender.all.qualified on
   //              qualified hardware
   // WR! WR+   => means WR was enabled via gfx.webrender.{all,enabled} or
   //              envvar, possibly on unqualified hardware
   // In all cases WR- means WR was not enabled, for one of many possible
   // reasons. Prior to bug 1523788 landing the gfx.webrender.{all,enabled}
   // prefs only worked on Nightly so keep that in mind when looking at older
   // crash reports.
   ScopedGfxFeatureReporter reporter("WR", prefEnabled || envvarEnabled);
   if (!XRE_IsParentProcess()) {
     // The parent process runs through all the real decision-making code
     // later in this function. For other processes we still want to report
     // the state of the feature for crash reports.
     if (gfxVars::UseWebRender()) {
+      // gfxVars doesn't notify receivers when initialized on content processes
+      // we need to explicitly recompute backdrop-filter's enabled state here.
+      nsCSSProps::RecomputeEnabledState("layout.css.backdrop-filter.enabled");
       reporter.SetSuccessful();
     }
     return;
   }
 
   // Update the gfxConfig feature states.
   gfxConfigManager manager;
   manager.Init();
@@ -3283,18 +3283,16 @@ void gfxPlatform::NotifyCompositorCreate
 /* static */
 void gfxPlatform::NotifyGPUProcessDisabled() {
   if (gfxConfig::IsEnabled(Feature::WEBRENDER)) {
     gfxConfig::GetFeature(Feature::WEBRENDER)
         .ForceDisable(
             FeatureStatus::Unavailable, "GPU Process is disabled",
             NS_LITERAL_CSTRING("FEATURE_FAILURE_GPU_PROCESS_DISABLED"));
     gfxVars::SetUseWebRender(false);
-
-    RecomputeBackdropFilterEnabledState();
   }
   gfxVars::SetRemoteCanvasEnabled(false);
 }
 
 void gfxPlatform::FetchAndImportContentDeviceData() {
   MOZ_ASSERT(XRE_IsContentProcess());
 
   if (gContentDeviceInitData) {
--- a/layout/style/nsCSSProps.cpp
+++ b/layout/style/nsCSSProps.cpp
@@ -17,17 +17,18 @@
 #include "gfxPlatform.h"
 #include "nsLayoutUtils.h"
 #include "nsIWidget.h"
 #include "nsStyleConsts.h"  // For system widget appearance types
 
 #include "mozilla/dom/Animation.h"
 #include "mozilla/dom/AnimationEffectBinding.h"  // for PlaybackDirection
 #include "mozilla/gfx/gfxVars.h"                 // for UseWebRender
-#include "mozilla/LookAndFeel.h"                 // for system colors
+#include "mozilla/gfx/gfxVarReceiver.h"
+#include "mozilla/LookAndFeel.h"  // for system colors
 
 #include "nsString.h"
 #include "nsStaticNameTable.h"
 
 #include "mozilla/Preferences.h"
 #include "mozilla/StaticPrefs_layout.h"
 
 using namespace mozilla;
@@ -60,25 +61,26 @@ static nsStaticCaseInsensitiveNameTable*
     MOZ_ASSERT(-1 == temp.FindChar('_'),
                "underscore char in case insensitive name table");
   }
 #endif
   return table;
 }
 
 void nsCSSProps::RecomputeEnabledState(const char* aPref, void*) {
+  MOZ_RELEASE_ASSERT(NS_IsMainThread());
   DebugOnly<bool> foundPref = false;
   for (const PropertyPref* pref = kPropertyPrefTable;
        pref->mPropID != eCSSProperty_UNKNOWN; pref++) {
     if (!aPref || !strcmp(aPref, pref->mPref)) {
       foundPref = true;
       gPropertyEnabled[pref->mPropID] = Preferences::GetBool(pref->mPref);
       if (pref->mPropID == eCSSProperty_backdrop_filter) {
         gPropertyEnabled[pref->mPropID] &=
-            gfxPlatform::Initialized() && gfx::gfxVars::UseWebRender();
+            gfx::gfxVars::GetUseWebRenderOrDefault();
       }
     }
   }
   MOZ_ASSERT(foundPref);
 }
 
 void nsCSSProps::AddRefTable(void) {
   if (0 == gPropertyTableRefCount++) {
@@ -209,9 +211,45 @@ bool nsCSSProps::gPropertyEnabled[eCSSPr
 #include "mozilla/ServoCSSPropList.h"
 #undef CSS_PROP_ALIAS
 #undef CSS_PROP_SHORTHAND
 #undef CSS_PROP_LONGHAND
 
 #undef IS_ENABLED_BY_DEFAULT
 };
 
+/**
+ * A singleton class to register as a receiver for gfxVars.
+ * Updates the state of backdrop-filter's pref if the gfx
+ * WebRender var changes state.
+ */
+class nsCSSPropsGfxVarReceiver final : public gfx::gfxVarReceiver {
+  constexpr nsCSSPropsGfxVarReceiver() = default;
+
+  // WebRender's last known enabled state.
+  static bool sLastKnownUseWebRender;
+  static nsCSSPropsGfxVarReceiver sInstance;
+
+ public:
+  static gfx::gfxVarReceiver& GetInstance() { return sInstance; }
+
+  void OnVarChanged(const gfx::GfxVarUpdate&) override {
+    bool enabled = gfxVars::UseWebRender();
+    if (sLastKnownUseWebRender != enabled) {
+      sLastKnownUseWebRender = enabled;
+      nsCSSProps::RecomputeEnabledState("layout.css.backdrop-filter.enabled");
+    }
+  }
+};
+
+/* static */
+nsCSSPropsGfxVarReceiver nsCSSPropsGfxVarReceiver::sInstance =
+    nsCSSPropsGfxVarReceiver();
+
+/* static */
+bool nsCSSPropsGfxVarReceiver::sLastKnownUseWebRender = false;
+
+/* static */
+gfx::gfxVarReceiver& nsCSSProps::GfxVarReceiver() {
+  return nsCSSPropsGfxVarReceiver::GetInstance();
+}
+
 #include "nsCSSPropsGenerated.inc"
--- a/layout/style/nsCSSProps.h
+++ b/layout/style/nsCSSProps.h
@@ -19,16 +19,17 @@
 #include "nsString.h"
 #include "nsCSSPropertyID.h"
 #include "nsStyleStructFwd.h"
 #include "mozilla/UseCounter.h"
 #include "mozilla/CSSEnabledState.h"
 #include "mozilla/CSSPropFlags.h"
 #include "mozilla/EnumTypeTraits.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/gfx/gfxVarReceiver.h"
 #include "nsXULAppAPI.h"
 
 // Length of the "--" prefix on custom names (such as custom property names,
 // and, in the future, custom media query names).
 #define CSS_CUSTOM_NAME_PREFIX_LENGTH 2
 
 namespace mozilla {
 class ComputedStyle;
@@ -133,16 +134,21 @@ class nsCSSProps {
   /**
    * Recoumputes the enabled state of a pref. If aPrefName is nullptr,
    * recomputes the state of all prefs in gPropertyEnabled.
    * aClosure is the pref callback closure data, which is not used.
    */
   static void RecomputeEnabledState(const char* aPrefName,
                                     void* aClosure = nullptr);
 
+  /**
+   * Retrieve a singleton receiver to register with gfxVars
+   */
+  static mozilla::gfx::gfxVarReceiver& GfxVarReceiver();
+
   static const nsCSSPropertyID* SubpropertyEntryFor(nsCSSPropertyID aProperty) {
     MOZ_ASSERT(eCSSProperty_COUNT_no_shorthands <= aProperty &&
                    aProperty < eCSSProperty_COUNT,
                "out of range");
     return nsCSSProps::kSubpropertyTable[aProperty -
                                          eCSSProperty_COUNT_no_shorthands];
   }