Bug 1143575. Extend IPDL OpUseTexture to support multiple timestamped images. r=nical
authorRobert O'Callahan <robert@ocallahan.org>
Mon, 04 May 2015 22:59:02 +1200
changeset 283341 44927f617616c4141d71d20e9792668e7e3d365f
parent 283340 e587e6bd4d6f0d8e7afda65baa43f2386c4a0a29
child 283342 03a8e48f413499fa38a8a59d0affeabcf80f2107
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersnical
bugs1143575
milestone42.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 1143575. Extend IPDL OpUseTexture to support multiple timestamped images. r=nical
gfx/layers/composite/CompositableHost.cpp
gfx/layers/composite/CompositableHost.h
gfx/layers/composite/ContentHost.cpp
gfx/layers/composite/ContentHost.h
gfx/layers/composite/ImageHost.cpp
gfx/layers/composite/ImageHost.h
gfx/layers/ipc/CompositableTransactionParent.cpp
gfx/layers/ipc/ImageBridgeChild.cpp
gfx/layers/ipc/LayersMessages.ipdlh
gfx/layers/ipc/ShadowLayers.cpp
--- a/gfx/layers/composite/CompositableHost.cpp
+++ b/gfx/layers/composite/CompositableHost.cpp
@@ -102,24 +102,22 @@ CompositableHost::DestroyIPDLActor(PComp
 CompositableHost*
 CompositableHost::FromIPDLActor(PCompositableParent* aActor)
 {
   MOZ_ASSERT(aActor);
   return static_cast<CompositableParent*>(aActor)->mHost;
 }
 
 void
-CompositableHost::UseTextureHost(TextureHost* aTexture,
-                                 const IntRect& aPictureRect)
+CompositableHost::UseTextureHost(const nsTArray<TimedTexture>& aTextures)
 {
-  if (!aTexture) {
-    return;
-  }
   if (GetCompositor()) {
-    aTexture->SetCompositor(GetCompositor());
+    for (auto& texture : aTextures) {
+      texture.mTexture->SetCompositor(GetCompositor());
+    }
   }
 }
 
 void
 CompositableHost::UseComponentAlphaTextures(TextureHost* aTextureOnBlack,
                                             TextureHost* aTextureOnWhite)
 {
   MOZ_ASSERT(aTextureOnBlack && aTextureOnWhite);
--- a/gfx/layers/composite/CompositableHost.h
+++ b/gfx/layers/composite/CompositableHost.h
@@ -145,23 +145,16 @@ public:
   {
     MOZ_ASSERT(aCompositor, "Compositor is required");
     NS_ASSERTION(aFlags & ALLOW_REATTACH || !mAttached,
                  "Re-attaching compositables must be explicitly authorised");
     SetCompositor(aCompositor);
     SetLayer(aLayer);
     mAttached = true;
     mKeepAttached = aFlags & KEEP_ATTACHED;
-
-    // If we already have a textureHost before, use that in this moment.
-    gfx::IntRect pictureRect;
-    RefPtr<TextureHost> frontBuffer = GetAsTextureHost(&pictureRect);
-    if (frontBuffer) {
-      UseTextureHost(frontBuffer, pictureRect);
-    }
   }
   // Detach this compositable host from its layer.
   // If we are used for async video, then it is not safe to blindly detach since
   // we might be re-attached to a different layer. aLayer is the layer which the
   // caller expects us to be attached to, we will only detach if we are in fact
   // attached to that layer. If we are part of a normal layer, then we will be
   // detached in any case. if aLayer is null, then we will only detach if we are
   // not async.
@@ -182,18 +175,22 @@ public:
                     const char* aPrefix="",
                     bool aDumpHtml=false) { }
   static void DumpTextureHost(std::stringstream& aStream, TextureHost* aTexture);
 
   virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() { return nullptr; }
 
   virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) = 0;
 
-  virtual void UseTextureHost(TextureHost* aTexture,
-                              const gfx::IntRect& aPictureRect);
+  struct TimedTexture {
+    RefPtr<TextureHost> mTexture;
+    TimeStamp mTimeStamp;
+    gfx::IntRect mPictureRect;
+  };
+  virtual void UseTextureHost(const nsTArray<TimedTexture>& aTextures);
   virtual void UseComponentAlphaTextures(TextureHost* aTextureOnBlack,
                                          TextureHost* aTextureOnWhite);
   virtual void UseOverlaySource(OverlaySource aOverlay,
                                 const gfx::IntRect& aPictureRect) { }
 
   virtual void RemoveTextureHost(TextureHost* aTexture);
 
   // Called every time this is composited
--- a/gfx/layers/composite/ContentHost.cpp
+++ b/gfx/layers/composite/ContentHost.cpp
@@ -213,24 +213,25 @@ ContentHostTexture::Composite(EffectChai
   if (iterOnWhite) {
     diagnostics |= DiagnosticFlags::COMPONENT_ALPHA;
   }
   GetCompositor()->DrawDiagnostics(diagnostics, nsIntRegion(mBufferRect), aClipRect,
                                    aTransform, mFlashCounter);
 }
 
 void
-ContentHostTexture::UseTextureHost(TextureHost* aTexture,
-                                   const nsIntRect& aPictureRect)
+ContentHostTexture::UseTextureHost(const nsTArray<TimedTexture>& aTextures)
 {
-  ContentHostBase::UseTextureHost(aTexture, aPictureRect);
-  MOZ_ASSERT(aPictureRect.IsEqualInterior(
-      nsIntRect(nsIntPoint(0, 0), nsIntSize(aTexture->GetSize()))),
+  ContentHostBase::UseTextureHost(aTextures);
+  MOZ_ASSERT(aTextures.Length() == 1);
+  const TimedTexture& t = aTextures[0];
+  MOZ_ASSERT(t.mPictureRect.IsEqualInterior(
+      nsIntRect(nsIntPoint(0, 0), nsIntSize(t.mTexture->GetSize()))),
       "Only default picture rect supported");
-  mTextureHost = aTexture;
+  mTextureHost = t.mTexture;
   mTextureHostOnWhite = nullptr;
   mTextureSourceOnWhite = nullptr;
   if (mTextureHost) {
     mTextureHost->PrepareTextureSource(mTextureSource);
   }
 }
 
 void
--- a/gfx/layers/composite/ContentHost.h
+++ b/gfx/layers/composite/ContentHost.h
@@ -126,18 +126,17 @@ public:
   virtual already_AddRefed<gfx::DataSourceSurface> GetAsSurface() override;
 
   virtual void Dump(std::stringstream& aStream,
                     const char* aPrefix="",
                     bool aDumpHtml=false) override;
 
   virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) override;
 
-  virtual void UseTextureHost(TextureHost* aTexture,
-                              const nsIntRect& aPictureRect) override;
+  virtual void UseTextureHost(const nsTArray<TimedTexture>& aTextures) override;
   virtual void UseComponentAlphaTextures(TextureHost* aTextureOnBlack,
                                          TextureHost* aTextureOnWhite) override;
 
   virtual bool Lock() override {
     MOZ_ASSERT(!mLocked);
     if (!mTextureHost) {
       return false;
     }
--- a/gfx/layers/composite/ImageHost.cpp
+++ b/gfx/layers/composite/ImageHost.cpp
@@ -31,26 +31,27 @@ ImageHost::ImageHost(const TextureInfo& 
   : CompositableHost(aTextureInfo)
   , mLocked(false)
 {}
 
 ImageHost::~ImageHost()
 {}
 
 void
-ImageHost::UseTextureHost(TextureHost* aTexture,
-                          const nsIntRect& aPictureRect)
+ImageHost::UseTextureHost(const nsTArray<TimedTexture>& aTextures)
 {
-  CompositableHost::UseTextureHost(aTexture, aPictureRect);
-  mFrontBuffer = aTexture;
+  CompositableHost::UseTextureHost(aTextures);
+  MOZ_ASSERT(aTextures.Length() >= 1);
+  const TimedTexture& t = aTextures[0];
+  mFrontBuffer = t.mTexture;
   if (mFrontBuffer) {
     mFrontBuffer->Updated();
     mFrontBuffer->PrepareTextureSource(mTextureSource);
   }
-  mPictureRect = aPictureRect;
+  mPictureRect = t.mPictureRect;
 }
 
 void
 ImageHost::RemoveTextureHost(TextureHost* aTexture)
 {
   CompositableHost::RemoveTextureHost(aTexture);
   if (aTexture && mFrontBuffer == aTexture) {
     mFrontBuffer->UnbindTextureSource();
@@ -63,16 +64,30 @@ TextureHost*
 ImageHost::GetAsTextureHost(IntRect* aPictureRect)
 {
   if (aPictureRect) {
     *aPictureRect = mPictureRect;
   }
   return mFrontBuffer;
 }
 
+void ImageHost::Attach(Layer* aLayer,
+                       Compositor* aCompositor,
+                       AttachFlags aFlags)
+{
+  CompositableHost::Attach(aLayer, aCompositor, aFlags);
+  if (mFrontBuffer) {
+    if (GetCompositor()) {
+      mFrontBuffer->SetCompositor(GetCompositor());
+    }
+    mFrontBuffer->Updated();
+    mFrontBuffer->PrepareTextureSource(mTextureSource);
+  }
+}
+
 void
 ImageHost::Composite(EffectChain& aEffectChain,
                      float aOpacity,
                      const gfx::Matrix4x4& aTransform,
                      const gfx::Filter& aFilter,
                      const gfx::Rect& aClipRect,
                      const nsIntRegion* aVisibleRegion)
 {
--- a/gfx/layers/composite/ImageHost.h
+++ b/gfx/layers/composite/ImageHost.h
@@ -46,23 +46,26 @@ public:
 
   virtual void Composite(EffectChain& aEffectChain,
                          float aOpacity,
                          const gfx::Matrix4x4& aTransform,
                          const gfx::Filter& aFilter,
                          const gfx::Rect& aClipRect,
                          const nsIntRegion* aVisibleRegion = nullptr) override;
 
-  virtual void UseTextureHost(TextureHost* aTexture,
-                              const nsIntRect& aPictureRect) override;
+  virtual void UseTextureHost(const nsTArray<TimedTexture>& aTextures) override;
 
   virtual void RemoveTextureHost(TextureHost* aTexture) override;
 
   virtual TextureHost* GetAsTextureHost(gfx::IntRect* aPictureRect = nullptr) override;
 
+  virtual void Attach(Layer* aLayer,
+                      Compositor* aCompositor,
+                      AttachFlags aFlags = NO_FLAGS) override;
+
   virtual void SetCompositor(Compositor* aCompositor) override;
 
   gfx::IntSize GetImageSize() const override;
 
   virtual LayerRenderState GetRenderState() override;
 
   virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) override;
 
--- a/gfx/layers/ipc/CompositableTransactionParent.cpp
+++ b/gfx/layers/ipc/CompositableTransactionParent.cpp
@@ -166,31 +166,36 @@ CompositableParentManager::ReceiveCompos
         ReplyRemoveTexture(OpReplyRemoveTexture(op.holderId(),
                                                 op.transactionId()));
       }
       break;
     }
     case CompositableOperation::TOpUseTexture: {
       const OpUseTexture& op = aEdit.get_OpUseTexture();
       CompositableHost* compositable = AsCompositable(op);
-      RefPtr<TextureHost> tex = TextureHost::AsTextureHost(op.textureParent());
 
-      MOZ_ASSERT(tex.get());
-      if (!ValidatePictureRect(tex->GetSize(), op.picture())) {
-        return false;
-      }
-      compositable->UseTextureHost(tex, op.picture());
+      nsAutoTArray<CompositableHost::TimedTexture,4> textures;
+      for (auto& timedTexture : op.textures()) {
+        CompositableHost::TimedTexture* t = textures.AppendElement();
+        t->mTexture =
+            TextureHost::AsTextureHost(timedTexture.textureParent());
+        MOZ_ASSERT(t->mTexture);
+        t->mTimeStamp = timedTexture.timeStamp();
+        t->mPictureRect = timedTexture.picture();
+        MOZ_ASSERT(ValidatePictureRect(t->mTexture->GetSize(), t->mPictureRect));
 
-      MaybeFence maybeFence = op.fence();
-      if (maybeFence.type() == MaybeFence::TFenceHandle) {
-        FenceHandle fence = maybeFence.get_FenceHandle();
-        if (fence.IsValid() && tex) {
-          tex->SetAcquireFenceHandle(fence);
+        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 (IsAsync() && compositable->GetLayer()) {
         ScheduleComposition(op);
         // Async layer updates don't trigger invalidation, manually tell the layer
         // that its content have changed.
         compositable->GetLayer()->SetInvalidRectToVisibleRegion();
       }
       break;
--- a/gfx/layers/ipc/ImageBridgeChild.cpp
+++ b/gfx/layers/ipc/ImageBridgeChild.cpp
@@ -114,20 +114,22 @@ ImageBridgeChild::UseTexture(Compositabl
   MOZ_ASSERT(aCompositable);
   MOZ_ASSERT(aTexture);
   MOZ_ASSERT(aCompositable->GetIPDLActor());
   MOZ_ASSERT(aTexture->GetIPDLActor());
 
   FenceHandle fence = aTexture->GetAcquireFenceHandle();
   IntRect pictureRect = aPictureRect ? *aPictureRect :
       IntRect(IntPoint(0, 0), IntSize(aTexture->GetSize()));
+  nsAutoTArray<TimedTexture,1> textures;
+  textures.AppendElement(TimedTexture(nullptr, aTexture->GetIPDLActor(),
+                                      fence.IsValid() ? MaybeFence(fence) : MaybeFence(null_t()),
+                                      TimeStamp(), pictureRect));
   mTxn->AddNoSwapEdit(OpUseTexture(nullptr, aCompositable->GetIPDLActor(),
-                                   nullptr, aTexture->GetIPDLActor(),
-                                   fence.IsValid() ? MaybeFence(fence) : MaybeFence(null_t()),
-                                   pictureRect));
+                                   textures));
 }
 
 void
 ImageBridgeChild::UseComponentAlphaTextures(CompositableClient* aCompositable,
                                             TextureClient* aTextureOnBlack,
                                             TextureClient* aTextureOnWhite)
 {
   MOZ_ASSERT(aCompositable);
--- a/gfx/layers/ipc/LayersMessages.ipdlh
+++ b/gfx/layers/ipc/LayersMessages.ipdlh
@@ -378,25 +378,36 @@ struct OpReplyRemoveTexture {
   uint64_t transactionId;
 };
 
 union MaybeFence {
   FenceHandle;
   null_t;
 };
 
+struct TimedTexture {
+  PTexture texture;
+  MaybeFence fence;
+  TimeStamp timeStamp;
+  IntRect picture;
+};
+
 /**
- * Tells the compositor-side which texture to use (for example, as front buffer
- * if there is several textures for double buffering)
+ * Tells the compositor-side which textures to use (for example, as front buffer
+ * if there are several textures for double buffering).
+ * This provides a list of textures with timestamps, ordered by timestamp.
+ * The newest texture whose timestamp is <= the current time is rendered
+ * (where null is considered less than every other timestamp). If there is no
+ * such texture, the first texture is rendered.
+ * The first timestamp value can be null, but the others must not be.
+ * The list must not be empty.
  */
 struct OpUseTexture {
   PCompositable compositable;
-  PTexture texture;
-  MaybeFence fence;
-  IntRect picture;
+  TimedTexture[] textures;
 };
 
 struct OpUseComponentAlphaTextures {
   PCompositable compositable;
   PTexture textureOnBlack;
   PTexture textureOnWhite;
 };
 
--- a/gfx/layers/ipc/ShadowLayers.cpp
+++ b/gfx/layers/ipc/ShadowLayers.cpp
@@ -357,20 +357,22 @@ ShadowLayerForwarder::UseTexture(Composi
   MOZ_ASSERT(aCompositable);
   MOZ_ASSERT(aTexture);
   MOZ_ASSERT(aCompositable->GetIPDLActor());
   MOZ_ASSERT(aTexture->GetIPDLActor());
 
   FenceHandle fence = aTexture->GetAcquireFenceHandle();
   IntRect pictureRect = aPictureRect ? *aPictureRect :
       IntRect(nsIntPoint(0, 0), IntSize(aTexture->GetSize()));
+  nsAutoTArray<TimedTexture,1> textures;
+  textures.AppendElement(TimedTexture(nullptr, aTexture->GetIPDLActor(),
+                                      fence.IsValid() ? MaybeFence(fence) : MaybeFence(null_t()),
+                                      TimeStamp(), pictureRect));
   mTxn->AddEdit(OpUseTexture(nullptr, aCompositable->GetIPDLActor(),
-                             nullptr, aTexture->GetIPDLActor(),
-                             fence.IsValid() ? MaybeFence(fence) : MaybeFence(null_t()),
-                             pictureRect));
+                             textures));
   if (aTexture->GetFlags() & TextureFlags::IMMEDIATE_UPLOAD
       && aTexture->HasInternalBuffer()) {
     // We use IMMEDIATE_UPLOAD when we want to be sure that the upload cannot
     // race with updates on the main thread. In this case we want the transaction
     // to be synchronous.
     mTxn->MarkSyncTransaction();
   }
 }