Propagate D3D9 device resets to remote layers. (bug 1245765 part 2, r=mattwoodrow)
authorDavid Anderson <danderson@mozilla.com>
Mon, 29 Feb 2016 01:53:12 -0500
changeset 322391 6fcea9ec83505069544ad8671b468dff7bd87aea
parent 322390 0c434a1ba1f596fc5df52f0ed7391a97a29fecfa
child 322392 fe3b4dabf0b045c245c23bd5de660a360ff8918a
push id5913
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 16:57:49 +0000
treeherdermozilla-beta@dcaf0a6fa115 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1245765
milestone47.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
Propagate D3D9 device resets to remote layers. (bug 1245765 part 2, r=mattwoodrow)
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
gfx/layers/Compositor.h
gfx/layers/d3d9/CompositorD3D9.cpp
gfx/layers/d3d9/CompositorD3D9.h
gfx/layers/ipc/CompositorChild.cpp
gfx/layers/ipc/CompositorChild.h
gfx/layers/ipc/CompositorParent.cpp
gfx/layers/ipc/CompositorParent.h
gfx/layers/ipc/PCompositor.ipdl
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -104,16 +104,17 @@
 #include "nsPresShell.h"
 #include "nsIAppsService.h"
 #include "nsNetUtil.h"
 #include "nsIPermissionManager.h"
 #include "nsIURILoader.h"
 #include "nsIScriptError.h"
 #include "mozilla/EventForwards.h"
 #include "nsDeviceContext.h"
+#include "FrameLayerBuilder.h"
 
 #define BROWSER_ELEMENT_CHILD_SCRIPT \
     NS_LITERAL_STRING("chrome://global/content/BrowserElementChild.js")
 
 #define TABC_LOG(...)
 // #define TABC_LOG(...) printf_stderr("TABC: " __VA_ARGS__)
 
 using namespace mozilla;
@@ -2864,16 +2865,28 @@ TabChild::ClearCachedResources()
   MOZ_ASSERT(mPuppetWidget->GetLayerManager()->GetBackendType() ==
                LayersBackend::LAYERS_CLIENT);
 
   ClientLayerManager *manager =
     static_cast<ClientLayerManager*>(mPuppetWidget->GetLayerManager());
   manager->ClearCachedResources();
 }
 
+void
+TabChild::InvalidateLayers()
+{
+  MOZ_ASSERT(mPuppetWidget);
+  MOZ_ASSERT(mPuppetWidget->GetLayerManager());
+  MOZ_ASSERT(mPuppetWidget->GetLayerManager()->GetBackendType() ==
+               LayersBackend::LAYERS_CLIENT);
+
+  RefPtr<LayerManager> lm = mPuppetWidget->GetLayerManager();
+  FrameLayerBuilder::InvalidateAllLayers(lm);
+}
+
 NS_IMETHODIMP
 TabChild::OnShowTooltip(int32_t aXCoords, int32_t aYCoords, const char16_t *aTipText)
 {
     nsString str(aTipText);
     SendShowTooltip(aXCoords, aYCoords, str);
     return NS_OK;
 }
 
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -540,16 +540,17 @@ public:
   void DidComposite(uint64_t aTransactionId,
                     const TimeStamp& aCompositeStart,
                     const TimeStamp& aCompositeEnd);
 
   void DidRequestComposite(const TimeStamp& aCompositeReqStart,
                            const TimeStamp& aCompositeReqEnd);
 
   void ClearCachedResources();
+  void InvalidateLayers();
 
   static inline TabChild* GetFrom(nsIDOMWindow* aWindow)
   {
     nsCOMPtr<nsIWebNavigation> webNav = do_GetInterface(aWindow);
     nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(webNav);
     return GetFrom(docShell);
   }
 
--- a/gfx/layers/Compositor.h
+++ b/gfx/layers/Compositor.h
@@ -120,17 +120,17 @@ namespace layers {
 struct Effect;
 struct EffectChain;
 class Image;
 class ImageHostOverlay;
 class Layer;
 class TextureSource;
 class DataTextureSource;
 class CompositingRenderTarget;
-class PCompositorParent;
+class CompositorParent;
 class LayerManagerComposite;
 
 enum SurfaceInitMode
 {
   INIT_MODE_NONE,
   INIT_MODE_CLEAR
 };
 
@@ -179,17 +179,17 @@ enum SurfaceInitMode
 class Compositor
 {
 protected:
   virtual ~Compositor() {}
 
 public:
   NS_INLINE_DECL_REFCOUNTING(Compositor)
 
-  explicit Compositor(PCompositorParent* aParent = nullptr)
+  explicit Compositor(CompositorParent* aParent = nullptr)
     : mCompositorID(0)
     , mDiagnosticTypes(DiagnosticTypes::NO_DIAGNOSTIC)
     , mParent(aParent)
     , mScreenRotation(ROTATION_0)
   {
   }
 
   virtual already_AddRefed<DataTextureSource> CreateDataTextureSource(TextureFlags aFlags = TextureFlags::NO_FLAGS) = 0;
@@ -548,17 +548,17 @@ protected:
    * When nonnull, during rendering, some compositable indicated that it will
    * change its rendering at this time. In order not to miss it, we composite
    * on every vsync until this time occurs (this is the latest such time).
    */
   TimeStamp mCompositeUntilTime;
 
   uint32_t mCompositorID;
   DiagnosticTypes mDiagnosticTypes;
-  PCompositorParent* mParent;
+  CompositorParent* mParent;
 
   /**
    * We keep track of the total number of pixels filled as we composite the
    * current frame. This value is an approximation and is not accurate,
    * especially in the presence of transforms.
    */
   size_t mPixelsPerFrame;
   size_t mPixelsFilled;
--- a/gfx/layers/d3d9/CompositorD3D9.cpp
+++ b/gfx/layers/d3d9/CompositorD3D9.cpp
@@ -12,23 +12,24 @@
 #include "mozilla/layers/Effects.h"
 #include "nsWindowsHelpers.h"
 #include "Nv3DVUtils.h"
 #include "gfxFailure.h"
 #include "mozilla/layers/PCompositorParent.h"
 #include "mozilla/layers/LayerManagerComposite.h"
 #include "gfxPrefs.h"
 #include "gfxCrashReporterUtils.h"
+#include "mozilla/layers/CompositorParent.h"
 
 namespace mozilla {
 namespace layers {
 
 using namespace mozilla::gfx;
 
-CompositorD3D9::CompositorD3D9(PCompositorParent* aParent, nsIWidget *aWidget)
+CompositorD3D9::CompositorD3D9(CompositorParent* aParent, nsIWidget *aWidget)
   : Compositor(aParent)
   , mWidget(aWidget)
   , mDeviceResetCount(0)
   , mFailedResetAttempts(0)
 {
 }
 
 CompositorD3D9::~CompositorD3D9()
@@ -571,17 +572,17 @@ CompositorD3D9::SetMask(const EffectChai
                                      ShaderConstantRect(bounds.x,
                                                         bounds.y,
                                                         bounds.width,
                                                         bounds.height),
                                      1);
 }
 
 /**
- * In the next few methods we call |mParent->SendInvalidateAll()| - that has
+ * In the next few methods we call |mParent->InvalidateRemoteLayers()| - that has
  * a few uses - if our device or swap chain is not ready, it causes us to try
  * to render again, that means we keep trying to get a good device and swap
  * chain and don't block the main thread (which we would if we kept trying in
  * a busy loop because this is likely to happen in a sync transaction).
  * If we had to recreate our device, then we have new textures and we
  * need to reupload everything (not just what is currently invalid) from the
  * client side. That means we need to invalidate everything on the client.
  * If we just reset and didn't need to recreate, then we don't need to reupload
@@ -604,41 +605,41 @@ CompositorD3D9::EnsureSwapChain()
       CreateSwapChain((HWND)mWidget->GetNativeData(NS_NATIVE_WINDOW));
     // We could not create a swap chain, return false
     if (!mSwapChain) {
       // Check the state of the device too
       DeviceManagerState state = mDeviceManager->VerifyReadyForRendering();
       if (state == DeviceMustRecreate) {
         mDeviceManager = nullptr;
       }
-      mParent->SendInvalidateAll();
+      mParent->InvalidateRemoteLayers();
       return false;
     }
   }
 
   // We have a swap chain, lets initialise it
   DeviceManagerState state = mSwapChain->PrepareForRendering();
   if (state == DeviceOK) {
     mFailedResetAttempts = 0;
     return true;
   }
   // Swap chain could not be initialised, handle the failure
   if (state == DeviceMustRecreate) {
     mDeviceManager = nullptr;
     mSwapChain = nullptr;
   }
-  mParent->SendInvalidateAll();
+  mParent->InvalidateRemoteLayers();
   return false;
 }
 
 void
 CompositorD3D9::CheckResetCount()
 {
   if (mDeviceResetCount != mDeviceManager->GetDeviceResetCount()) {
-    mParent->SendInvalidateAll();
+    mParent->InvalidateRemoteLayers();
   }
   mDeviceResetCount = mDeviceManager->GetDeviceResetCount();
 }
 
 bool
 CompositorD3D9::Ready()
 {
   if (mDeviceManager) {
@@ -653,17 +654,17 @@ CompositorD3D9::Ready()
 
   NS_ASSERTION(!mCurrentRT && !mDefaultRT,
                "Shouldn't have any render targets around, they must be released before our device");
   mSwapChain = nullptr;
 
   mDeviceManager = gfxWindowsPlatform::GetPlatform()->GetD3D9DeviceManager();
   if (!mDeviceManager) {
     FailedToResetDevice();
-    mParent->SendInvalidateAll();
+    mParent->InvalidateRemoteLayers();
     return false;
   }
   if (EnsureSwapChain()) {
     CheckResetCount();
     return true;
   }
   return false;
 }
--- a/gfx/layers/d3d9/CompositorD3D9.h
+++ b/gfx/layers/d3d9/CompositorD3D9.h
@@ -16,17 +16,17 @@
 class nsWidget;
 
 namespace mozilla {
 namespace layers {
 
 class CompositorD3D9 : public Compositor
 {
 public:
-  CompositorD3D9(PCompositorParent* aParent, nsIWidget *aWidget);
+  CompositorD3D9(CompositorParent* aParent, nsIWidget *aWidget);
   ~CompositorD3D9();
 
   virtual bool Initialize() override;
   virtual void Destroy() override {}
 
   virtual TextureFactoryIdentifier
     GetTextureFactoryIdentifier() override;
 
--- a/gfx/layers/ipc/CompositorChild.cpp
+++ b/gfx/layers/ipc/CompositorChild.cpp
@@ -192,20 +192,25 @@ CompositorChild::DeallocPLayerTransactio
       iter.Remove();
     }
   }
   static_cast<LayerTransactionChild*>(actor)->ReleaseIPDLReference();
   return true;
 }
 
 bool
-CompositorChild::RecvInvalidateAll()
+CompositorChild::RecvInvalidateLayers(const uint64_t& aLayersId)
 {
   if (mLayerManager) {
+    MOZ_ASSERT(aLayersId == 0);
     FrameLayerBuilder::InvalidateAllLayers(mLayerManager);
+  } else if (aLayersId != 0) {
+    if (dom::TabChild* child = dom::TabChild::GetFrom(aLayersId)) {
+      child->InvalidateLayers();
+    }
   }
   return true;
 }
 
 #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
 static void CalculatePluginClip(const LayoutDeviceIntRect& aBounds,
                                 const nsTArray<LayoutDeviceIntRect>& aPluginClipRects,
                                 const LayoutDeviceIntPoint& aContentOffset,
--- a/gfx/layers/ipc/CompositorChild.h
+++ b/gfx/layers/ipc/CompositorChild.h
@@ -74,17 +74,17 @@ public:
   RecvClearCachedResources(const uint64_t& id) override;
 
   virtual bool
   RecvDidComposite(const uint64_t& aId, const uint64_t& aTransactionId,
                    const TimeStamp& aCompositeStart,
                    const TimeStamp& aCompositeEnd) override;
 
   virtual bool
-  RecvInvalidateAll() override;
+  RecvInvalidateLayers(const uint64_t& aLayersId) override;
 
   virtual bool
   RecvOverfill(const uint32_t &aOverfill) override;
 
   virtual bool
   RecvUpdatePluginConfigurations(const LayoutDeviceIntPoint& aContentOffset,
                                  const LayoutDeviceIntRegion& aVisibleRegion,
                                  nsTArray<PluginWindowData>&& aPlugins) override;
--- a/gfx/layers/ipc/CompositorParent.cpp
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -2024,16 +2024,32 @@ CompositorParent::DidComposite(TimeStamp
   ForEachIndirectLayerTree([&] (LayerTreeState* lts, const uint64_t& aLayersId) -> void {
     if (lts->mCrossProcessParent) {
       auto cpcp = static_cast<CrossProcessCompositorParent*>(lts->mCrossProcessParent);
       cpcp->DidComposite(aLayersId, aCompositeStart, aCompositeEnd);
     }
   });
 }
 
+void
+CompositorParent::InvalidateRemoteLayers()
+{
+  MOZ_ASSERT(CompositorLoop() == MessageLoop::current());
+
+  Unused << PCompositorParent::SendInvalidateLayers(0);
+
+  MonitorAutoLock lock(*sIndirectLayerTreesLock);
+  ForEachIndirectLayerTree([] (LayerTreeState* lts, const uint64_t& aLayersId) -> void {
+    if (lts->mCrossProcessParent) {
+      auto cpcp = static_cast<CrossProcessCompositorParent*>(lts->mCrossProcessParent);
+      Unused << cpcp->SendInvalidateLayers(aLayersId);
+    }
+  });
+}
+
 static void
 OpenCompositor(CrossProcessCompositorParent* aCompositor,
                Transport* aTransport, ProcessId aOtherPid,
                MessageLoop* aIOLoop)
 {
   DebugOnly<bool> ok = aCompositor->Open(aTransport, aOtherPid, aIOLoop);
   MOZ_ASSERT(ok);
 }
--- a/gfx/layers/ipc/CompositorParent.h
+++ b/gfx/layers/ipc/CompositorParent.h
@@ -314,16 +314,25 @@ public:
 
   /**
    * Returns the unique layer tree identifier that corresponds to the root
    * tree of this compositor.
    */
   uint64_t RootLayerTreeId();
 
   /**
+   * Notify local and remote layer trees connected to this compositor that
+   * the compositor's local device is being reset. All layers must be
+   * invalidated to clear any cached TextureSources.
+   *
+   * This must be called on the compositor thread.
+   */
+  void InvalidateRemoteLayers();
+
+  /**
    * Returns a pointer to the compositor corresponding to the given ID.
    */
   static CompositorParent* GetCompositor(uint64_t id);
 
   /**
    * Returns the compositor thread's message loop.
    *
    * This message loop is used by CompositorParent, ImageBridgeParent,
--- a/gfx/layers/ipc/PCompositor.ipdl
+++ b/gfx/layers/ipc/PCompositor.ipdl
@@ -36,18 +36,20 @@ namespace layers {
  * purpose is to manage the PLayerTransaction sub protocol.
  */
 sync protocol PCompositor
 {
   // A Compositor manages a single Layer Manager (PLayerTransaction)
   manages PLayerTransaction;
 
 child:
-  // The child should invalidate everything so that the whole window is redrawn.
-  async InvalidateAll();
+  // The child should invalidate retained layers. This is used for local
+  // compositor device resets, such as in CompositorD3D9, and ensures that
+  // TextureSources are recreated.
+  async InvalidateLayers(uint64_t layersId);
 
   // The compositor completed a layers transaction. id is the layers id
   // of the child layer tree that was composited (or 0 when notifying
   // the root layer tree).
   // transactionId is the id of the transaction before this composite, or 0
   // if there was no transaction since the last composite.
   async DidComposite(uint64_t id, uint64_t transactionId,
                      TimeStamp compositeStart, TimeStamp compositeEnd);