Bug 774388 - Patch 4: Flatten the way that we track whether we are using OMTC, and move Layers IPC shutdown code back to gfxPlatform (but still triggered by ShutdownXPCOM) - r=nical,sotaro
☠☠ backed out by fc02eb625f9e ☠ ☠
authorBenoit Jacob <bjacob@mozilla.com>
Fri, 06 Jun 2014 09:51:24 -0400
changeset 207512 7a0d8feb1575bb4883211ef09a8f029a205523e1
parent 207511 3d77c8ef5b69e951fe0c0bb69a4059353e10618d
child 207513 6f2e001c5f3923c740bf2e3d8ca8750739c88758
push id494
push userraliiev@mozilla.com
push dateMon, 25 Aug 2014 18:42:16 +0000
treeherdermozilla-release@a3cc3e46b571 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical, sotaro
bugs774388
milestone32.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 774388 - Patch 4: Flatten the way that we track whether we are using OMTC, and move Layers IPC shutdown code back to gfxPlatform (but still triggered by ShutdownXPCOM) - r=nical,sotaro
dom/ipc/ContentParent.cpp
dom/ipc/TabParent.cpp
gfx/thebes/gfxPlatform.cpp
gfx/thebes/gfxPlatform.h
gfx/thebes/gfxPlatformGtk.cpp
gfx/thebes/gfxPlatformGtk.h
gfx/thebes/gfxPlatformMac.cpp
gfx/thebes/gfxPlatformMac.h
gfx/thebes/gfxQtPlatform.cpp
gfx/thebes/gfxQtPlatform.h
gfx/thebes/gfxWindowsPlatform.cpp
layout/build/nsLayoutModule.cpp
layout/ipc/RenderFrameParent.cpp
widget/windows/winrt/MetroWidget.cpp
widget/xpwidgets/nsBaseWidget.cpp
xpcom/build/nsXPComInit.cpp
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -1705,18 +1705,17 @@ ContentParent::InitInternal(ProcessPrior
         // NB: internally, this will send an IPC message to the child
         // process to get it to create the CompositorChild.  This
         // message goes through the regular IPC queue for this
         // channel, so delivery will happen-before any other messages
         // we send.  The CompositorChild must be created before any
         // PBrowsers are created, because they rely on the Compositor
         // already being around.  (Creation is async, so can't happen
         // on demand.)
-        bool useOffMainThreadCompositing = !!CompositorParent::CompositorLoop();
-        if (useOffMainThreadCompositing) {
+        if (gfxPlatform::UsesOffMainThreadCompositing()) {
             DebugOnly<bool> opened = PCompositor::Open(this);
             MOZ_ASSERT(opened);
 
             if (gfxPrefs::AsyncVideoOOPEnabled()) {
                 opened = PImageBridge::Open(this);
                 MOZ_ASSERT(opened);
             }
         }
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -1883,19 +1883,19 @@ TabParent::GetWidget() const
 
   nsCOMPtr<nsIWidget> widget = frame->GetNearestWidget();
   return widget.forget();
 }
 
 bool
 TabParent::UseAsyncPanZoom()
 {
-  bool usingOffMainThreadCompositing = !!CompositorParent::CompositorLoop();
-  return (usingOffMainThreadCompositing && gfxPrefs::AsyncPanZoomEnabled() &&
-          GetScrollingBehavior() == ASYNC_PAN_ZOOM);
+  return gfxPlatform::UsesOffMainThreadCompositing() &&
+         gfxPrefs::AsyncPanZoomEnabled() &&
+         GetScrollingBehavior() == ASYNC_PAN_ZOOM;
 }
 
 nsEventStatus
 TabParent::MaybeForwardEventToRenderFrame(WidgetInputEvent& aEvent,
                                           ScrollableLayerGuid* aOutTargetGuid)
 {
   if (RenderFrameParent* rfp = GetRenderFrame()) {
     return rfp->NotifyInputEvent(aEvent, aOutTargetGuid);
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -272,16 +272,19 @@ gfxPlatform::gfxPlatform()
     mLayersPreferMemoryOverShmem = XRE_GetProcessType() == GeckoProcessType_Default;
 
     mSkiaGlue = nullptr;
 
     uint32_t canvasMask = BackendTypeBit(BackendType::CAIRO) | BackendTypeBit(BackendType::SKIA);
     uint32_t contentMask = BackendTypeBit(BackendType::CAIRO);
     InitBackendPrefs(canvasMask, BackendType::CAIRO,
                      contentMask, BackendType::CAIRO);
+
+    mUsesOffMainThreadCompositing = ComputeUsesOffMainThreadCompositing();
+    mAlreadyShutDownLayersIPC = false;
 }
 
 gfxPlatform*
 gfxPlatform::GetPlatform()
 {
     if (!gPlatform) {
         Init();
     }
@@ -359,27 +362,22 @@ gfxPlatform::Init()
 #else
     #error "No gfxPlatform implementation available"
 #endif
 
 #ifdef DEBUG
     mozilla::gl::GLContext::StaticInit();
 #endif
 
-    bool useOffMainThreadCompositing = OffMainThreadCompositionRequired() ||
-                                       GetPrefLayersOffMainThreadCompositionEnabled();
-
-    if (!OffMainThreadCompositionRequired()) {
-      useOffMainThreadCompositing &= GetPlatform()->SupportsOffMainThreadCompositing();
-    }
-
-    if (useOffMainThreadCompositing && (XRE_GetProcessType() == GeckoProcessType_Default)) {
-        CompositorParent::StartUp();
+    if (UsesOffMainThreadCompositing() &&
+        XRE_GetProcessType() == GeckoProcessType_Default)
+    {
+        mozilla::layers::CompositorParent::StartUp();
         if (gfxPrefs::AsyncVideoEnabled()) {
-            ImageBridgeChild::StartUp();
+            mozilla::layers::ImageBridgeChild::StartUp();
         }
 #ifdef MOZ_WIDGET_GONK
         SharedBufferManagerChild::StartUp();
 #endif
     }
 
     nsresult rv;
 
@@ -439,16 +437,19 @@ gfxPlatform::Init()
     }
 
     RegisterStrongMemoryReporter(new GfxMemoryImageReporter());
 }
 
 void
 gfxPlatform::Shutdown()
 {
+    MOZ_ASSERT(gPlatform, "gfxPlatform already down!");
+    MOZ_ASSERT(gPlatform->mAlreadyShutDownLayersIPC, "ShutdownLayersIPC should have been called before this point!");
+
     // These may be called before the corresponding subsystems have actually
     // started up. That's OK, they can handle it.
     gfxFontCache::Shutdown();
     gfxFontGroup::Shutdown();
     gfxGradientCache::Shutdown();
     gfxGraphiteShaper::Shutdown();
 #if defined(XP_MACOSX) || defined(XP_WIN) // temporary, until this is implemented on others
     gfxPlatformFontList::Shutdown();
@@ -501,16 +502,35 @@ gfxPlatform::Shutdown()
 
     gfxPrefs::DestroySingleton();
     gfxFont::DestroySingletons();
 
     delete gPlatform;
     gPlatform = nullptr;
 }
 
+/* static */ void
+gfxPlatform::ShutdownLayersIPC()
+{
+    MOZ_ASSERT(!gPlatform->mAlreadyShutDownLayersIPC);
+    if (UsesOffMainThreadCompositing() &&
+        XRE_GetProcessType() == GeckoProcessType_Default)
+    {
+        // This must happen after the shutdown of media and widgets, which
+        // are triggered by the NS_XPCOM_SHUTDOWN_OBSERVER_ID notification.
+        layers::ImageBridgeChild::ShutDown();
+#ifdef MOZ_WIDGET_GONK
+        layers::SharedBufferManagerChild::ShutDown();
+#endif
+
+        layers::CompositorParent::ShutDown();
+    }
+    gPlatform->mAlreadyShutDownLayersIPC = true;
+}
+
 gfxPlatform::~gfxPlatform()
 {
     mScreenReferenceSurface = nullptr;
     mScreenReferenceDrawTarget = nullptr;
 
     // The cairo folks think we should only clean up in debug builds,
     // but we're generally in the habit of trying to shut down as
     // cleanly as possible even in production code, so call this
@@ -527,17 +547,16 @@ gfxPlatform::~gfxPlatform()
 #if MOZ_TREE_CAIRO
     cairo_debug_reset_static_data();
 #endif
 #endif
 }
 
 bool
 gfxPlatform::PreferMemoryOverShmem() const {
-  MOZ_ASSERT(!CompositorParent::IsInCompositorThread());
   return mLayersPreferMemoryOverShmem;
 }
 
 already_AddRefed<gfxASurface>
 gfxPlatform::OptimizeImage(gfxImageSurface *aSurface,
                            gfxImageFormat format)
 {
     IntSize surfaceSize = aSurface->GetSize().ToIntSize();
@@ -1537,19 +1556,17 @@ gfxPlatform::GetBackendPref(const char* 
 
     aBackendBitmask = allowedBackends;
     return result;
 }
 
 bool
 gfxPlatform::OffMainThreadCompositingEnabled()
 {
-  return XRE_GetProcessType() == GeckoProcessType_Default ?
-    CompositorParent::CompositorLoop() != nullptr :
-    CompositorChild::ChildProcessHasCompositor();
+  return UsesOffMainThreadCompositing();
 }
 
 eCMSMode
 gfxPlatform::GetCMSMode()
 {
     if (gCMSInitialized == false) {
         gCMSInitialized = true;
 
@@ -2004,37 +2021,16 @@ InitLayersAccelerationPrefs()
     }
 #endif
 
     sLayersAccelerationPrefsInitialized = true;
   }
 }
 
 bool
-gfxPlatform::GetPrefLayersOffMainThreadCompositionEnabled()
-{
-  InitLayersAccelerationPrefs();
-  return gfxPrefs::LayersOffMainThreadCompositionEnabled() ||
-         gfxPrefs::LayersOffMainThreadCompositionForceEnabled() ||
-         gfxPrefs::LayersOffMainThreadCompositionTestingEnabled();
-}
-
-bool gfxPlatform::OffMainThreadCompositionRequired()
-{
-  InitLayersAccelerationPrefs();
-#if defined(MOZ_WIDGET_GTK) && defined(NIGHTLY_BUILD)
-  // Linux users who chose OpenGL are being grandfathered in to OMTC
-  return sPrefBrowserTabsRemoteAutostart ||
-         gfxPrefs::LayersAccelerationForceEnabled();
-#else
-  return sPrefBrowserTabsRemoteAutostart;
-#endif
-}
-
-bool
 gfxPlatform::CanUseDirect3D9()
 {
   // this function is called from the compositor thread, so it is not
   // safe to init the prefs etc. from here.
   MOZ_ASSERT(sLayersAccelerationPrefsInitialized);
   return sLayersSupportsD3D9;
 }
 
@@ -2070,8 +2066,30 @@ gfxPlatform::GetScaledFontForFontWithCai
     if (aTarget->GetType() == BackendType::CAIRO || aTarget->GetType() == BackendType::SKIA) {
         nativeFont.mType = NativeFontType::CAIRO_FONT_FACE;
         nativeFont.mFont = aFont->GetCairoScaledFont();
         return Factory::CreateScaledFontForNativeFont(nativeFont, aFont->GetAdjustedSize());
     }
 
     return nullptr;
 }
+
+bool
+gfxPlatform::ComputeUsesOffMainThreadCompositing()
+{
+  InitLayersAccelerationPrefs();
+  bool result =
+    sPrefBrowserTabsRemoteAutostart ||
+    gfxPrefs::LayersOffMainThreadCompositionEnabled() ||
+    gfxPrefs::LayersOffMainThreadCompositionForceEnabled() ||
+    gfxPrefs::LayersOffMainThreadCompositionTestingEnabled();
+#if defined(MOZ_WIDGET_GTK) && defined(NIGHTLY_BUILD)
+  // Linux users who chose OpenGL are being grandfathered in to OMTC
+  result |=
+    gfxPrefs::LayersAccelerationForceEnabled() ||
+    PR_GetEnv("MOZ_USE_OMTC") ||
+    PR_GetEnv("MOZ_OMTC_ENABLED"); // yeah, these two env vars do the same thing.
+                                   // I'm told that one of them is enabled on some test slaves config.
+                                   // so be slightly careful if you think you can
+                                   // remove one of them.
+#endif
+  return result;
+}
\ No newline at end of file
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -165,16 +165,18 @@ public:
 
 
     /**
      * Shut down Thebes.
      * Init() arranges for this to be called at an appropriate time.
      */
     static void Shutdown();
 
+    static void ShutdownLayersIPC();
+
     /**
      * Create an offscreen surface of the given dimensions
      * and image format.
      */
     virtual already_AddRefed<gfxASurface>
       CreateOffscreenSurface(const IntSize& size,
                              gfxContentType contentType) = 0;
 
@@ -428,26 +430,19 @@ public:
                                         int32_t /*aRunScript*/,
                                         nsTArray<const char*>& /*aFontList*/)
     {
         // platform-specific override, by default do nothing
     }
 
     static bool OffMainThreadCompositingEnabled();
 
-    /** Use gfxPlatform::GetPref* methods instead of direct calls to Preferences
-     * to get the values for layers preferences.  These will only be evaluated
-     * only once, and remain the same until restart.
-     */
-    static bool GetPrefLayersOffMainThreadCompositionEnabled();
     static bool CanUseDirect3D9();
     static bool CanUseDirect3D11();
 
-    static bool OffMainThreadCompositionRequired();
-
     /**
      * Is it possible to use buffer rotation.  Note that these
      * check the preference, but also allow for the override to
      * disable it using DisableBufferRotation.
      */
     static bool BufferRotationEnabled();
     static void DisableBufferRotation();
 
@@ -544,16 +539,20 @@ public:
      */
     bool PreferMemoryOverShmem() const;
 
     mozilla::gl::SkiaGLGlue* GetSkiaGLGlue();
     void PurgeSkiaCache();
 
     virtual bool IsInGonkEmulator() const { return false; }
 
+    static bool UsesOffMainThreadCompositing() {
+      return GetPlatform()->mUsesOffMainThreadCompositing;
+    }
+
 protected:
     gfxPlatform();
     virtual ~gfxPlatform();
 
     void AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], uint32_t &aLen, 
                             eFontPrefLang aCharLang, eFontPrefLang aPageLang);
 
     /**
@@ -613,31 +612,38 @@ protected:
     int8_t  mFallbackUsesCmaps;
 
     // max character limit for words in word cache
     int32_t mWordCacheCharLimit;
 
     // max number of entries in word cache
     int32_t mWordCacheMaxEntries;
 
+    // Whether we use OMTC/OMPC (as opposed to main-thread compositing)
+    bool mUsesOffMainThreadCompositing;
+
+    // Whether ShutdownLayersIPC has alrady been called. Used to enforce that
+    // it is called before Shutdown.
+    bool mAlreadyShutDownLayersIPC;
+
 private:
     /**
      * Start up Thebes.
      */
     static void Init();
 
     static void CreateCMSOutputProfile();
 
     static void GetCMSOutputProfileData(void *&mem, size_t &size);
 
     friend void RecordingPrefChanged(const char *aPrefName, void *aClosure);
 
     virtual void GetPlatformCMSOutputProfile(void *&mem, size_t &size);
 
-    virtual bool SupportsOffMainThreadCompositing() { return true; }
+    bool ComputeUsesOffMainThreadCompositing();
 
     nsRefPtr<gfxASurface> mScreenReferenceSurface;
     mozilla::RefPtr<mozilla::gfx::DrawTarget> mScreenReferenceDrawTarget;
     nsTArray<uint32_t> mCJKPrefLangs;
     nsCOMPtr<nsIObserver> mSRGBOverrideObserver;
     nsCOMPtr<nsIObserver> mFontPrefsObserver;
     nsCOMPtr<nsIObserver> mMemoryPressureObserver;
 
--- a/gfx/thebes/gfxPlatformGtk.cpp
+++ b/gfx/thebes/gfxPlatformGtk.cpp
@@ -247,28 +247,16 @@ gfxPlatformGtk::GetScreenDepth() const
             sDepth = 24;
         }
 
     }
 
     return sDepth;
 }
 
-bool
-gfxPlatformGtk::SupportsOffMainThreadCompositing()
-{
-  // Nightly builds have OMTC support by default for Electrolysis testing.
-#if defined(MOZ_X11) && !defined(NIGHTLY_BUILD)
-  return (PR_GetEnv("MOZ_USE_OMTC") != nullptr) ||
-         (PR_GetEnv("MOZ_OMTC_ENABLED") != nullptr);
-#else
-  return true;
-#endif
-}
-
 void
 gfxPlatformGtk::GetPlatformCMSOutputProfile(void *&mem, size_t &size)
 {
     mem = nullptr;
     size = 0;
 
 #ifdef MOZ_X11
     const char EDID1_ATOM_NAME[] = "XFree86_DDC_EDID1_RAWDATA";
--- a/gfx/thebes/gfxPlatformGtk.h
+++ b/gfx/thebes/gfxPlatformGtk.h
@@ -93,15 +93,14 @@ public:
     virtual int GetScreenDepth() const;
 
 protected:
     static gfxFontconfigUtils *sFontconfigUtils;
 
 private:
     virtual void GetPlatformCMSOutputProfile(void *&mem, size_t &size);
 
-    virtual bool SupportsOffMainThreadCompositing();
 #ifdef MOZ_X11
     static bool sUseXRender;
 #endif
 };
 
 #endif /* GFX_PLATFORM_GTK_H */
--- a/gfx/thebes/gfxPlatformMac.cpp
+++ b/gfx/thebes/gfxPlatformMac.cpp
@@ -430,22 +430,16 @@ gfxPlatformMac::GetThebesSurfaceForDrawT
 
 bool
 gfxPlatformMac::UseAcceleratedCanvas()
 {
   // Lion or later is required
   return nsCocoaFeatures::OnLionOrLater() && Preferences::GetBool("gfx.canvas.azure.accelerated", false);
 }
 
-bool
-gfxPlatformMac::SupportsOffMainThreadCompositing()
-{
-  return true;
-}
-
 void
 gfxPlatformMac::GetPlatformCMSOutputProfile(void* &mem, size_t &size)
 {
     mem = nullptr;
     size = 0;
 
     CGColorSpaceRef cspace = ::CGDisplayCopyColorSpace(::CGMainDisplayID());
     if (!cspace) {
--- a/gfx/thebes/gfxPlatformMac.h
+++ b/gfx/thebes/gfxPlatformMac.h
@@ -67,17 +67,15 @@ public:
     // lower threshold on font anti-aliasing
     uint32_t GetAntiAliasingThreshold() { return mFontAntiAliasingThreshold; }
 
     virtual already_AddRefed<gfxASurface>
     GetThebesSurfaceForDrawTarget(mozilla::gfx::DrawTarget *aTarget);
 private:
     virtual void GetPlatformCMSOutputProfile(void* &mem, size_t &size);
 
-    virtual bool SupportsOffMainThreadCompositing();
-
     // read in the pref value for the lower threshold on font anti-aliasing
     static uint32_t ReadAntiAliasingThreshold();
 
     uint32_t mFontAntiAliasingThreshold;
 };
 
 #endif /* GFX_PLATFORM_MAC_H */
--- a/gfx/thebes/gfxQtPlatform.cpp
+++ b/gfx/thebes/gfxQtPlatform.cpp
@@ -156,27 +156,16 @@ gfxQtPlatform::MakePlatformFont(const gf
                                  const uint8_t *aFontData, uint32_t aLength)
 {
     // passing ownership of the font data to the new font entry
     return gfxPangoFontGroup::NewFontEntry(*aProxyEntry,
                                            aFontData, aLength);
 }
 
 bool
-gfxQtPlatform::SupportsOffMainThreadCompositing()
-{
-#if defined(MOZ_X11) && !defined(NIGHTLY_BUILD)
-  return (PR_GetEnv("MOZ_USE_OMTC") != nullptr) ||
-         (PR_GetEnv("MOZ_OMTC_ENABLED") != nullptr);
-#else
-  return true;
-#endif
-}
-
-bool
 gfxQtPlatform::IsFontFormatSupported(nsIURI *aFontURI, uint32_t aFormatFlags)
 {
     // check for strange format flags
     NS_ASSERTION(!(aFormatFlags & gfxUserFontSet::FLAG_FORMAT_NOT_USED),
                  "strange font format hint set");
 
     // accept supported formats
     // Pango doesn't apply features from AAT TrueType extensions.
--- a/gfx/thebes/gfxQtPlatform.h
+++ b/gfx/thebes/gfxQtPlatform.h
@@ -78,18 +78,16 @@ public:
     virtual gfxImageFormat GetOffscreenFormat() MOZ_OVERRIDE;
 #ifdef MOZ_X11
     static Display* GetXDisplay(QWindow* aWindow = 0);
     static Screen* GetXScreen(QWindow* aWindow = 0);
 #endif
 
     virtual int GetScreenDepth() const MOZ_OVERRIDE;
 
-    virtual bool SupportsOffMainThreadCompositing() MOZ_OVERRIDE;
-
 protected:
     static gfxFontconfigUtils *sFontconfigUtils;
 
 private:
     virtual void GetPlatformCMSOutputProfile(void *&mem, size_t &size) MOZ_OVERRIDE;
 
     // TODO: unify this with mPrefFonts (NB: holds families, not fonts) in gfxPlatformFontList
     nsDataHashtable<nsCStringHashKey, nsTArray<nsRefPtr<gfxFontEntry> > > mPrefFonts;
--- a/gfx/thebes/gfxWindowsPlatform.cpp
+++ b/gfx/thebes/gfxWindowsPlatform.cpp
@@ -1375,18 +1375,18 @@ gfxWindowsPlatform::GetD3D9Device()
 }
 
 DeviceManagerD3D9*
 gfxWindowsPlatform::GetD3D9DeviceManager()
 {
   // We should only create the d3d9 device on the compositor thread
   // or we don't have a compositor thread.
   if (!mDeviceManager &&
-      (CompositorParent::IsInCompositorThread() ||
-       !CompositorParent::CompositorLoop())) {
+      (!gfxPlatform::UsesOffMainThreadCompositing() ||
+       CompositorParent::IsInCompositorThread())) {
     mDeviceManager = new DeviceManagerD3D9();
     if (!mDeviceManager->Init()) {
       NS_WARNING("Could not initialise device manager");
       mDeviceManager = nullptr;
     }
   }
 
   return mDeviceManager;
--- a/layout/build/nsLayoutModule.cpp
+++ b/layout/build/nsLayoutModule.cpp
@@ -66,17 +66,16 @@
 
 // view stuff
 #include "nsContentCreatorFunctions.h"
 
 // DOM includes
 #include "nsDOMBlobBuilder.h"
 #include "nsDOMFileReader.h"
 
-#include "gfxPlatform.h"
 #include "nsFormData.h"
 #include "nsHostObjectProtocolHandler.h"
 #include "nsHostObjectURI.h"
 #include "nsGlobalWindowCommands.h"
 #include "nsIControllerCommandTable.h"
 #include "nsJSProtocolHandler.h"
 #include "nsScriptNameSpaceManager.h"
 #include "nsIControllerContext.h"
--- a/layout/ipc/RenderFrameParent.cpp
+++ b/layout/ipc/RenderFrameParent.cpp
@@ -732,17 +732,17 @@ RenderFrameParent::RenderFrameParent(nsF
 
   if (lm && lm->GetRoot() && lm->GetRoot()->AsContainerLayer()) {
     ViewID rootScrollId = lm->GetRoot()->AsContainerLayer()->GetFrameMetrics().GetScrollId();
     if (rootScrollId != FrameMetrics::NULL_SCROLL_ID) {
       mContentViews[rootScrollId] = new nsContentView(aFrameLoader, rootScrollId, true);
     }
   }
 
-  if (CompositorParent::CompositorLoop()) {
+  if (gfxPlatform::UsesOffMainThreadCompositing()) {
     // Our remote frame will push layers updates to the compositor,
     // and we'll keep an indirect reference to that tree.
     *aId = mLayersId = CompositorParent::AllocateLayerTreeId();
     if (lm && lm->GetBackendType() == LayersBackend::LAYERS_CLIENT) {
       ClientLayerManager *clientManager = static_cast<ClientLayerManager*>(lm.get());
       clientManager->GetRemoteRenderer()->SendNotifyChildCreated(mLayersId);
     }
     if (aScrollingBehavior == ASYNC_PAN_ZOOM) {
--- a/widget/windows/winrt/MetroWidget.cpp
+++ b/widget/windows/winrt/MetroWidget.cpp
@@ -993,27 +993,29 @@ MetroWidget::RemoveSubclass()
 bool
 MetroWidget::ShouldUseOffMainThreadCompositing()
 {
   // Either we're not initialized yet, or this is the toolkit widget
   if (!mView) {
     return false;
   }
   // toolkit or test widgets can't use omtc, they don't have ICoreWindow.
-  return (CompositorParent::CompositorLoop() && mWindowType == eWindowType_toplevel);
+  return gfxPlatform::UsesOffMainThreadCompositing() &&
+         mWindowType == eWindowType_toplevel;
 }
 
 bool
 MetroWidget::ShouldUseMainThreadD3D10Manager()
 {
   // Either we're not initialized yet, or this is the toolkit widget
   if (!mView) {
     return false;
   }
-  return (!CompositorParent::CompositorLoop() && mWindowType == eWindowType_toplevel);
+  return !gfxPlatform::UsesOffMainThreadCompositing() &&
+         mWindowType == eWindowType_toplevel;
 }
 
 bool
 MetroWidget::ShouldUseBasicManager()
 {
   // toolkit or test widgets fall back on empty shadow layers
   return (mWindowType != eWindowType_toplevel);
 }
--- a/widget/xpwidgets/nsBaseWidget.cpp
+++ b/widget/xpwidgets/nsBaseWidget.cpp
@@ -883,16 +883,19 @@ CheckForBasicBackends(nsTArray<LayersBac
       aHints[i] = LayersBackend::LAYERS_NONE;
     }
   }
 #endif
 }
 
 void nsBaseWidget::CreateCompositor(int aWidth, int aHeight)
 {
+  MOZ_ASSERT(gfxPlatform::UsesOffMainThreadCompositing(),
+             "This function assumes OMTC");
+
   // Recreating this is tricky, as we may still have an old and we need
   // to make sure it's properly destroyed by calling DestroyCompositor!
 
   // If we've already received a shutdown notification, don't try
   // create a new compositor.
   if (!mShutdownObserver) {
     return;
   }
@@ -941,17 +944,17 @@ void nsBaseWidget::CreateCompositor(int 
   NS_WARNING("Failed to create an OMT compositor.");
   DestroyCompositor();
   // Compositor child had the only reference to LayerManager and will have
   // deallocated it when being freed.
 }
 
 bool nsBaseWidget::ShouldUseOffMainThreadCompositing()
 {
-  return CompositorParent::CompositorLoop();
+  return gfxPlatform::UsesOffMainThreadCompositing();
 }
 
 LayerManager* nsBaseWidget::GetLayerManager(PLayerTransactionChild* aShadowManager,
                                             LayersBackend aBackendHint,
                                             LayerManagerPersistence aPersistence,
                                             bool* aAllowRetaining)
 {
   if (!mLayerManager) {
--- a/xpcom/build/nsXPComInit.cpp
+++ b/xpcom/build/nsXPComInit.cpp
@@ -144,16 +144,18 @@ extern nsresult nsStringInputStreamConst
 #ifdef MOZ_WEBM
 #include "nestegg/nestegg.h"
 #endif
 
 #include "GeckoProfiler.h"
 
 #include "jsapi.h"
 
+#include "gfxPlatform.h"
+
 using namespace mozilla;
 using base::AtExitManager;
 using mozilla::ipc::BrowserProcessSubThread;
 #ifdef MOZ_VISUAL_EVENT_TRACER
 using mozilla::eventtracer::VisualEventTracer;
 #endif
 
 namespace {
@@ -792,31 +794,26 @@ ShutdownXPCOM(nsIServiceManager* servMgr
             if (NS_SUCCEEDED(rv))
             {
                 (void) observerService->
                     NotifyObservers(mgr, NS_XPCOM_SHUTDOWN_OBSERVER_ID,
                                     nullptr);
             }
         }
 
-        // This must happen after the shutdown of media and widgets, which
-        // are triggered by the NS_XPCOM_SHUTDOWN_OBSERVER_ID notification.
-        layers::ImageBridgeChild::ShutDown();
-#ifdef MOZ_WIDGET_GONK
-        layers::SharedBufferManagerChild::ShutDown();
-#endif
-
         NS_ProcessPendingEvents(thread);
         mozilla::scache::StartupCache::DeleteSingleton();
         if (observerService)
             (void) observerService->
                 NotifyObservers(nullptr, NS_XPCOM_SHUTDOWN_THREADS_OBSERVER_ID,
                                 nullptr);
 
-        layers::CompositorParent::ShutDown();
+        // This must happen after the shutdown of media and widgets, which
+        // are triggered by the NS_XPCOM_SHUTDOWN_OBSERVER_ID notification.
+        gfxPlatform::ShutdownLayersIPC();
 
         gXPCOMThreadsShutDown = true;
         NS_ProcessPendingEvents(thread);
 
         // Shutdown the timer thread and all timers that might still be alive before
         // shutting down the component manager
         nsTimerImpl::Shutdown();