Bug 1119019 - Avoid destroying a SharedSurface before its TextureClient/Host pair. r=sotaro, a=abillings
authorNicolas Silva <nsilva@mozilla.com>
Fri, 23 Jan 2015 15:35:16 +0100
changeset 243046 6601b8da1750
parent 243045 b17339648b55
child 243047 4417d345698a
push id4373
push userryanvm@gmail.com
push date2015-01-26 18:43 +0000
treeherdermozilla-beta@bc7489448a98 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssotaro, abillings
bugs1119019
milestone36.0
Bug 1119019 - Avoid destroying a SharedSurface before its TextureClient/Host pair. r=sotaro, a=abillings
gfx/layers/client/CanvasClient.cpp
gfx/layers/client/CanvasClient.h
gfx/layers/client/TextureClient.cpp
gfx/layers/client/TextureClient.h
--- a/gfx/layers/client/CanvasClient.cpp
+++ b/gfx/layers/client/CanvasClient.cpp
@@ -396,10 +396,25 @@ CanvasClientSharedSurface::Update(gfx::I
 
   // Use the new TexClient.
   mFrontTex = newTex;
 
   forwarder->UpdatedTexture(this, mFrontTex, nullptr);
   forwarder->UseTexture(this, mFrontTex);
 }
 
+void
+CanvasClientSharedSurface::ClearSurfaces()
+{
+  if (mFrontTex && (mFront || mPrevFront)) {
+    // Force a synchronous destruction so that the TextureHost does not
+    // outlive the SharedSurface. This won't be needed once TextureClient/Host
+    // and SharedSurface are merged.
+    mFrontTex->ForceRemove(true /* sync */);
+    mFrontTex = nullptr;
+  }
+  // It is important to destroy the SharedSurface *after* the TextureClient.
+  mFront = nullptr;
+  mPrevFront = nullptr;
+}
+
 }
 }
--- a/gfx/layers/client/CanvasClient.h
+++ b/gfx/layers/client/CanvasClient.h
@@ -114,34 +114,39 @@ private:
 class CanvasClientSharedSurface : public CanvasClient
 {
 private:
   RefPtr<gl::ShSurfHandle> mFront;
   RefPtr<gl::ShSurfHandle> mPrevFront;
 
   RefPtr<TextureClient> mFrontTex;
 
+  void ClearSurfaces();
+
 public:
   CanvasClientSharedSurface(CompositableForwarder* aLayerForwarder,
                             TextureFlags aFlags);
 
+  ~CanvasClientSharedSurface()
+  {
+    ClearSurfaces();
+  }
+
   virtual TextureInfo GetTextureInfo() const MOZ_OVERRIDE {
     return TextureInfo(CompositableType::IMAGE);
   }
 
   virtual void Clear() MOZ_OVERRIDE {
-    mFront = nullptr;
-    mPrevFront = nullptr;
-    mFrontTex = nullptr;
+    ClearSurfaces();
   }
 
   virtual void Update(gfx::IntSize aSize,
                       ClientCanvasLayer* aLayer) MOZ_OVERRIDE;
 
   virtual void OnDetach() MOZ_OVERRIDE {
-    CanvasClientSharedSurface::Clear();
+    ClearSurfaces();
   }
 };
 
 }
 }
 
 #endif
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -489,20 +489,20 @@ TextureClient::~TextureClient()
 void
 TextureClient::KeepUntilFullDeallocation(KeepAlive* aKeep)
 {
   MOZ_ASSERT(mActor);
   MOZ_ASSERT(!mActor->mKeep);
   mActor->mKeep = aKeep;
 }
 
-void TextureClient::ForceRemove()
+void TextureClient::ForceRemove(bool sync)
 {
   if (mValid && mActor) {
-    if (GetFlags() & TextureFlags::DEALLOCATE_CLIENT) {
+    if (sync || GetFlags() & TextureFlags::DEALLOCATE_CLIENT) {
       if (mActor->IPCOpen()) {
         mActor->SendClearTextureHostSync();
         mActor->SendRemoveTexture();
       }
     } else {
       if (mActor->IPCOpen()) {
         mActor->SendRemoveTexture();
       }
--- a/gfx/layers/client/TextureClient.h
+++ b/gfx/layers/client/TextureClient.h
@@ -379,18 +379,20 @@ public:
   PTextureChild* GetIPDLActor();
 
   /**
    * Triggers the destruction of the shared data and the corresponding TextureHost.
    *
    * If the texture flags contain TextureFlags::DEALLOCATE_CLIENT, the destruction
    * will be synchronously coordinated with the compositor side, otherwise it
    * will be done asynchronously.
+   * If sync is true, the destruction will be synchronous regardless of the
+   * texture's flags (bad for performance, use with care).
    */
-  void ForceRemove();
+  void ForceRemove(bool sync = false);
 
   virtual void SetReleaseFenceHandle(FenceHandle aReleaseFenceHandle)
   {
     mReleaseFenceHandle.Merge(aReleaseFenceHandle);
   }
 
   const FenceHandle& GetReleaseFenceHandle() const
   {