Bug 1366446 - Ensure layers TextureClient always lives as long as the SourceSurface using it. r=jrmuizel
authorLee Salzman <lsalzman@mozilla.com>
Sun, 28 May 2017 13:30:32 -0400
changeset 409587 61bea8a3b2dbe040462ea430d17e09427827d62f
parent 409586 7b3e7c43611ba7c586eacfd00af7dce905f97b92
child 409588 a8af366e880cca530d77716226342ff3bf82363b
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1366446
milestone55.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 1366446 - Ensure layers TextureClient always lives as long as the SourceSurface using it. r=jrmuizel MozReview-Commit-ID: HU3TBQQgotE
gfx/layers/ipc/SharedRGBImage.cpp
--- a/gfx/layers/ipc/SharedRGBImage.cpp
+++ b/gfx/layers/ipc/SharedRGBImage.cpp
@@ -97,16 +97,24 @@ SharedRGBImage::GetSize()
 }
 
 TextureClient*
 SharedRGBImage::GetTextureClient(KnowsCompositor* aForwarder)
 {
   return mTextureClient.get();
 }
 
+static void
+ReleaseTextureClient(void* aData)
+{
+  RELEASE_MANUALLY(static_cast<TextureClient*>(aData));
+}
+
+static gfx::UserDataKey sTextureClientKey;
+
 already_AddRefed<gfx::SourceSurface>
 SharedRGBImage::GetAsSourceSurface()
 {
   NS_ASSERTION(NS_IsMainThread(), "Must be main thread");
 
   if (mSourceSurface) {
     RefPtr<gfx::SourceSurface> surface(mSourceSurface);
     return surface.forget();
@@ -122,16 +130,28 @@ SharedRGBImage::GetAsSourceSurface()
       mTextureClient->GetInternalData()->AsBufferTextureData();
     RefPtr<gfx::DrawTarget> drawTarget = decoded_buffer->BorrowDrawTarget();
 
     if (!drawTarget) {
       return nullptr;
     }
 
     surface = drawTarget->Snapshot();
+    if (!surface) {
+      return nullptr;
+    }
+
+    // The surface may outlive the owning TextureClient. So, we need to ensure
+    // that the surface keeps the TextureClient alive via a reference held in
+    // user data. The TextureClient's DrawTarget only has a weak reference to the
+    // surface, so we won't create any cycles by just referencing the TextureClient.
+    if (!surface->GetUserData(&sTextureClientKey)) {
+      surface->AddUserData(&sTextureClientKey, mTextureClient, ReleaseTextureClient);
+      ADDREF_MANUALLY(mTextureClient);
+    }
   }
 
   mSourceSurface = surface;
   return surface.forget();
 }
 
 } // namespace layers
 } // namespace mozilla