Block compositable updates from stale layers. (bug 1256517 part 4, r=mattwoodrow,nical)
☠☠ backed out by 8127138e3146 ☠ ☠
authorDavid Anderson <danderson@mozilla.com>
Wed, 23 Mar 2016 10:32:34 -0700
changeset 290077 27a8a01abf66e8794d52ef84ef7ad84db2ca2f2d
parent 290076 9d33171eb4e91554b3d7f07da5dd737fc2c86c53
child 290078 f112e7dad6f73d3d2c0e72288670c8d91e4036aa
push id74087
push userdanderson@mozilla.com
push dateWed, 23 Mar 2016 17:34:05 +0000
treeherdermozilla-inbound@27a8a01abf66 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow, nical
bugs1256517
milestone48.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
Block compositable updates from stale layers. (bug 1256517 part 4, r=mattwoodrow,nical)
gfx/layers/Compositor.cpp
gfx/layers/Compositor.h
gfx/layers/basic/BasicCompositor.cpp
gfx/layers/basic/BasicCompositor.h
gfx/layers/basic/X11BasicCompositor.h
gfx/layers/d3d11/CompositorD3D11.cpp
gfx/layers/d3d11/CompositorD3D11.h
gfx/layers/ipc/CompositableTransactionParent.cpp
gfx/layers/ipc/CompositorBridgeParent.cpp
gfx/layers/ipc/LayerTransactionParent.cpp
gfx/layers/opengl/CompositorOGL.cpp
gfx/layers/opengl/CompositorOGL.h
gfx/tests/gtest/TestCompositor.cpp
--- a/gfx/layers/Compositor.cpp
+++ b/gfx/layers/Compositor.cpp
@@ -393,16 +393,28 @@ Compositor::ComputeBackdropCopyRect(cons
   gfx::Matrix4x4 transform;
   transform.PostScale(rtSize.width, rtSize.height, 1.0);
   transform.PostTranslate(-result.x, -result.y, 0.0);
   transform.PostScale(1 / float(result.width), 1 / float(result.height), 1.0);
   *aOutTransform = transform;
   return result;
 }
 
+void
+Compositor::SetInvalid()
+{
+  mParent = nullptr;
+}
+
+bool
+Compositor::IsValid() const
+{
+  return !mParent;
+}
+
 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
 void
 Compositor::SetDispAcquireFence(Layer* aLayer, nsIWidget* aWidget)
 {
   // OpenGL does not provide ReleaseFence for rendering.
   // Instead use DispAcquireFence as layer buffer's ReleaseFence
   // to prevent flickering and tearing.
   // DispAcquireFence is DisplaySurface's AcquireFence.
--- a/gfx/layers/Compositor.h
+++ b/gfx/layers/Compositor.h
@@ -512,16 +512,21 @@ public:
         mCompositeUntilTime < aTimeStamp) {
       mCompositeUntilTime = aTimeStamp;
     }
   }
   TimeStamp GetCompositeUntilTime() const {
     return mCompositeUntilTime;
   }
 
+  // A stale Compositor has no CompositorBridgeParent; it will not process
+  // frames and should not be used.
+  void SetInvalid();
+  bool IsValid() const;
+
 protected:
   void DrawDiagnosticsInternal(DiagnosticFlags aFlags,
                                const gfx::Rect& aVisibleRect,
                                const gfx::Rect& aClipRect,
                                const gfx::Matrix4x4& transform,
                                uint32_t aFlashCounter);
 
   bool ShouldDrawDiagnostics(DiagnosticFlags);
--- a/gfx/layers/basic/BasicCompositor.cpp
+++ b/gfx/layers/basic/BasicCompositor.cpp
@@ -73,18 +73,19 @@ public:
     SetUpdateSerial(0);
   }
 
 public:
   RefPtr<gfx::DataSourceSurface> mSurface;
   bool mWrappingExistingData;
 };
 
-BasicCompositor::BasicCompositor(nsIWidget *aWidget)
-  : mWidget(aWidget)
+BasicCompositor::BasicCompositor(CompositorBridgeParent* aParent, nsIWidget *aWidget)
+  : Compositor(aParent)
+  , mWidget(aWidget)
   , mDidExternalComposition(false)
 {
   MOZ_COUNT_CTOR(BasicCompositor);
 
   mMaxTextureSize =
     Factory::GetMaxSurfaceSize(gfxPlatform::GetPlatform()->GetContentBackendFor(LayersBackend::LAYERS_BASIC));
 }
 
--- a/gfx/layers/basic/BasicCompositor.h
+++ b/gfx/layers/basic/BasicCompositor.h
@@ -37,17 +37,17 @@ public:
 
   RefPtr<gfx::DrawTarget> mDrawTarget;
   gfx::IntSize mSize;
 };
 
 class BasicCompositor : public Compositor
 {
 public:
-  explicit BasicCompositor(nsIWidget *aWidget);
+  explicit BasicCompositor(CompositorBridgeParent* aParent, nsIWidget *aWidget);
 
 protected:
   virtual ~BasicCompositor();
 
 public:
   virtual bool Initialize() override;
 
   virtual void Destroy() override;
--- a/gfx/layers/basic/X11BasicCompositor.h
+++ b/gfx/layers/basic/X11BasicCompositor.h
@@ -41,18 +41,19 @@ public:
 private:
   // We are going to buffer layer content on this xlib draw target
   RefPtr<mozilla::gfx::DrawTarget> mBufferDrawTarget;
 };
 
 class X11BasicCompositor : public BasicCompositor
 {
 public:
-
-  explicit X11BasicCompositor(nsIWidget *aWidget) : BasicCompositor(aWidget) {}
+  explicit X11BasicCompositor(CompositorBridgeParent* aParent, nsIWidget *aWidget)
+    : BasicCompositor(aParent, aWidget)
+  {}
 
   virtual already_AddRefed<DataTextureSource>
   CreateDataTextureSource(TextureFlags aFlags = TextureFlags::NO_FLAGS) override;
 
   virtual already_AddRefed<DataTextureSource>
   CreateDataTextureSourceAround(gfx::DataSourceSurface* aSurface) override { return nullptr; }
 
   virtual void EndFrame() override;
--- a/gfx/layers/d3d11/CompositorD3D11.cpp
+++ b/gfx/layers/d3d11/CompositorD3D11.cpp
@@ -153,18 +153,19 @@ private:
     return true;
   }
 
   // Only used during initialization.
   RefPtr<ID3D11Device> mDevice;
   bool mInitOkay;
 };
 
-CompositorD3D11::CompositorD3D11(nsIWidget* aWidget)
-  : mAttachments(nullptr)
+CompositorD3D11::CompositorD3D11(CompositorBridgeParent* aParent, nsIWidget* aWidget)
+  : Compositor(aParent)
+  , mAttachments(nullptr)
   , mWidget(aWidget)
   , mHwnd(nullptr)
   , mDisableSequenceForNextFrame(false)
   , mVerifyBuffersFailed(false)
 {
 }
 
 CompositorD3D11::~CompositorD3D11()
--- a/gfx/layers/d3d11/CompositorD3D11.h
+++ b/gfx/layers/d3d11/CompositorD3D11.h
@@ -37,17 +37,17 @@ struct PixelShaderConstants
   int blendConfig[4];
 };
 
 struct DeviceAttachmentsD3D11;
 
 class CompositorD3D11 : public Compositor
 {
 public:
-  CompositorD3D11(nsIWidget* aWidget);
+  CompositorD3D11(CompositorBridgeParent* aParent, nsIWidget* aWidget);
   ~CompositorD3D11();
 
   virtual bool Initialize() override;
   virtual void Destroy() override {}
 
   virtual TextureFactoryIdentifier
     GetTextureFactoryIdentifier() override;
 
--- a/gfx/layers/ipc/CompositableTransactionParent.cpp
+++ b/gfx/layers/ipc/CompositableTransactionParent.cpp
@@ -69,17 +69,22 @@ static bool ValidatePictureRect(const mo
       !aPictureRect.IsEmpty();
 }
 #endif
 
 bool
 CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation& aEdit,
                                                      EditReplyVector& replyv)
 {
+  // Ignore all operations on compositables created on stale compositors. We
+  // return true because the child is unable to handle errors.
   CompositableHost* compositable = CompositableHost::FromIPDLActor(aEdit.compositableParent());
+  if (compositable->GetCompositor() && compositable->GetCompositor()->IsValid()) {
+    return true;
+  }
 
   switch (aEdit.detail().type()) {
     case CompositableOperationDetail::TOpPaintTextureRegion: {
       MOZ_LAYERS_LOG(("[ParentSide] Paint PaintedLayer"));
 
       const OpPaintTextureRegion& op = aEdit.detail().get_OpPaintTextureRegion();
       Layer* layer = compositable->GetLayer();
       if (!layer || layer->GetType() != Layer::TYPE_PAINTED) {
@@ -116,16 +121,17 @@ CompositableParentManager::ReceiveCompos
       bool success = tiledHost->UseTiledLayerBuffer(this, tileDesc);
       if (!success) {
         return false;
       }
       break;
     }
     case CompositableOperationDetail::TOpRemoveTexture: {
       const OpRemoveTexture& op = aEdit.detail().get_OpRemoveTexture();
+
       RefPtr<TextureHost> tex = TextureHost::AsTextureHost(op.textureParent());
 
       MOZ_ASSERT(tex.get());
       compositable->RemoveTextureHost(tex);
       // send FenceHandle if present.
       SendFenceHandleIfPresent(op.textureParent());
       break;
     }
@@ -178,17 +184,19 @@ CompositableParentManager::ReceiveCompos
         MaybeFence maybeFence = timedTexture.fence();
         if (maybeFence.type() == MaybeFence::TFenceHandle) {
           FenceHandle fence = maybeFence.get_FenceHandle();
           if (fence.IsValid()) {
             t->mTexture->SetAcquireFenceHandle(fence);
           }
         }
       }
-      compositable->UseTextureHost(textures);
+      if (textures.Length() > 0) {
+        compositable->UseTextureHost(textures);
+      }
 
       if (UsesImageBridge() && compositable->GetLayer()) {
         ScheduleComposition(compositable);
       }
       break;
     }
     case CompositableOperationDetail::TOpUseComponentAlphaTextures: {
       const OpUseComponentAlphaTextures& op = aEdit.detail().get_OpUseComponentAlphaTextures();
--- a/gfx/layers/ipc/CompositorBridgeParent.cpp
+++ b/gfx/layers/ipc/CompositorBridgeParent.cpp
@@ -1613,32 +1613,33 @@ CompositorBridgeParent::InitializeLayerM
 }
 
 RefPtr<Compositor>
 CompositorBridgeParent::NewCompositor(const nsTArray<LayersBackend>& aBackendHints)
 {
   for (size_t i = 0; i < aBackendHints.Length(); ++i) {
     RefPtr<Compositor> compositor;
     if (aBackendHints[i] == LayersBackend::LAYERS_OPENGL) {
-      compositor = new CompositorOGL(mWidget,
+      compositor = new CompositorOGL(this,
+                                     mWidget,
                                      mEGLSurfaceSize.width,
                                      mEGLSurfaceSize.height,
                                      mUseExternalSurfaceSize);
     } else if (aBackendHints[i] == LayersBackend::LAYERS_BASIC) {
 #ifdef MOZ_WIDGET_GTK
       if (gfxPlatformGtk::GetPlatform()->UseXRender()) {
-        compositor = new X11BasicCompositor(mWidget);
+        compositor = new X11BasicCompositor(this, mWidget);
       } else
 #endif
       {
-        compositor = new BasicCompositor(mWidget);
+        compositor = new BasicCompositor(this, mWidget);
       }
 #ifdef XP_WIN
     } else if (aBackendHints[i] == LayersBackend::LAYERS_D3D11) {
-      compositor = new CompositorD3D11(mWidget);
+      compositor = new CompositorD3D11(this, mWidget);
     } else if (aBackendHints[i] == LayersBackend::LAYERS_D3D9) {
       compositor = new CompositorD3D9(this, mWidget);
 #endif
     }
 
     if (compositor && compositor->Initialize()) {
       compositor->SetCompositorID(mCompositorID);
       return compositor;
@@ -2207,16 +2208,19 @@ CompositorBridgeParent::ResetCompositorI
   // Don't bother changing from basic->basic.
   if (mCompositor &&
       mCompositor->GetBackendType() == LayersBackend::LAYERS_BASIC &&
       compositor->GetBackendType() == LayersBackend::LAYERS_BASIC)
   {
     return Nothing();
   }
 
+  if (mCompositor) {
+    mCompositor->SetInvalid();
+  }
   mCompositor = compositor;
   mLayerManager->ChangeCompositor(compositor);
 
   return Some(compositor->GetTextureFactoryIdentifier());
 }
 
 static void
 OpenCompositor(CrossProcessCompositorBridgeParent* aCompositor,
--- a/gfx/layers/ipc/LayerTransactionParent.cpp
+++ b/gfx/layers/ipc/LayerTransactionParent.cpp
@@ -582,29 +582,39 @@ LayerTransactionParent::RecvUpdate(Infal
                                 replyv)) {
         return false;
       }
       break;
     }
     case Edit::TOpAttachCompositable: {
       const OpAttachCompositable& op = edit.get_OpAttachCompositable();
       CompositableHost* host = CompositableHost::FromIPDLActor(op.compositableParent());
+      if (mPendingCompositorUpdates) {
+        // Do not attach compositables from old layer trees. Return true since
+        // content cannot handle errors.
+        return true;
+      }
       if (!Attach(cast(op.layerParent()), host, false)) {
         return false;
       }
       host->SetCompositorID(mLayerManager->GetCompositor()->GetCompositorID());
       break;
     }
     case Edit::TOpAttachAsyncCompositable: {
       const OpAttachAsyncCompositable& op = edit.get_OpAttachAsyncCompositable();
       PCompositableParent* compositableParent = CompositableMap::Get(op.containerID());
       if (!compositableParent) {
         NS_ERROR("CompositableParent not found in the map");
         return false;
       }
+      if (mPendingCompositorUpdates) {
+        // Do not attach compositables from old layer trees. Return true since
+        // content cannot handle errors.
+        return true;
+      }
       CompositableHost* host = CompositableHost::FromIPDLActor(compositableParent);
       if (!Attach(cast(op.layerParent()), host, true)) {
         return false;
       }
       host->SetCompositorID(mLayerManager->GetCompositor()->GetCompositorID());
       break;
     }
     default:
--- a/gfx/layers/opengl/CompositorOGL.cpp
+++ b/gfx/layers/opengl/CompositorOGL.cpp
@@ -78,19 +78,21 @@ CompositorOGL::BindBackdrop(ShaderProgra
 
   mGLContext->fActiveTexture(aTexUnit);
   mGLContext->fBindTexture(LOCAL_GL_TEXTURE_2D, aBackdrop);
   mGLContext->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MIN_FILTER, LOCAL_GL_LINEAR);
   mGLContext->fTexParameteri(LOCAL_GL_TEXTURE_2D, LOCAL_GL_TEXTURE_MAG_FILTER, LOCAL_GL_LINEAR);
   aProgram->SetBackdropTextureUnit(aTexUnit - LOCAL_GL_TEXTURE0);
 }
 
-CompositorOGL::CompositorOGL(nsIWidget *aWidget, int aSurfaceWidth,
+CompositorOGL::CompositorOGL(CompositorBridgeParent* aParent,
+                             nsIWidget *aWidget, int aSurfaceWidth,
                              int aSurfaceHeight, bool aUseExternalSurfaceSize)
-  : mWidget(aWidget)
+  : Compositor(aParent)
+  , mWidget(aWidget)
   , mWidgetSize(-1, -1)
   , mSurfaceSize(aSurfaceWidth, aSurfaceHeight)
   , mHasBGRA(0)
   , mUseExternalSurfaceSize(aUseExternalSurfaceSize)
   , mFrameInProgress(false)
   , mDestroyed(false)
   , mViewportSize(0, 0)
   , mCurrentProgram(nullptr)
--- a/gfx/layers/opengl/CompositorOGL.h
+++ b/gfx/layers/opengl/CompositorOGL.h
@@ -188,17 +188,18 @@ class CompositorOGL final : public Compo
 {
   typedef mozilla::gl::GLContext GLContext;
 
   friend class GLManagerCompositor;
   friend class CompositingRenderTargetOGL;
 
   std::map<ShaderConfigOGL, ShaderProgramOGL*> mPrograms;
 public:
-  explicit CompositorOGL(nsIWidget *aWidget, int aSurfaceWidth = -1, int aSurfaceHeight = -1,
+  explicit CompositorOGL(CompositorBridgeParent* aParent,
+                         nsIWidget *aWidget, int aSurfaceWidth = -1, int aSurfaceHeight = -1,
                          bool aUseExternalSurfaceSize = false);
 
 protected:
   virtual ~CompositorOGL();
 
 public:
   virtual already_AddRefed<DataTextureSource>
   CreateDataTextureSource(TextureFlags aFlags = TextureFlags::NO_FLAGS) override;
--- a/gfx/tests/gtest/TestCompositor.cpp
+++ b/gfx/tests/gtest/TestCompositor.cpp
@@ -107,23 +107,24 @@ struct LayerManagerData {
 
 static already_AddRefed<Compositor> CreateTestCompositor(LayersBackend backend, MockWidget* widget)
 {
   gfxPrefs::GetSingleton();
 
   RefPtr<Compositor> compositor;
 
   if (backend == LayersBackend::LAYERS_OPENGL) {
-    compositor = new CompositorOGL(widget,
+    compositor = new CompositorOGL(nullptr,
+                                   widget,
                                    gCompWidth,
                                    gCompHeight,
                                    true);
     compositor->SetDestinationSurfaceSize(IntSize(gCompWidth, gCompHeight));
   } else if (backend == LayersBackend::LAYERS_BASIC) {
-    compositor = new BasicCompositor(widget);
+    compositor = new BasicCompositor(nullptr, widget);
 #ifdef XP_WIN
   } else if (backend == LayersBackend::LAYERS_D3D11) {
     //compositor = new CompositorD3D11();
     MOZ_CRASH(); // No support yet
   } else if (backend == LayersBackend::LAYERS_D3D9) {
     //compositor = new CompositorD3D9(this, mWidget);
     MOZ_CRASH(); // No support yet
 #endif