Bug 1143575. Extend IPDL OpUseTexture to support multiple timestamped images. r=nical draft
authorRobert O'Callahan <robert@ocallahan.org>
Mon, 04 May 2015 22:59:02 +1200
changeset 275581 9567e347be3224a85e9d41ce04f871130c44419a
parent 275580 213c17643d7cd3422a1bf7e68bbe748c2dcadbd2
child 275582 4cfbe37b685332a5203e0562b671d083facf8aa7
push id3189
push userrocallahan@mozilla.com
push dateFri, 03 Jul 2015 11:12:01 +0000
reviewersnical
bugs1143575
milestone42.0a1
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
@@ -111,20 +111,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();
   }
 }