diff --git a/gfx/layers/composite/CompositableHost.cpp b/gfx/layers/composite/CompositableHost.cpp index b134f7115df8..5006c71bb350 100644 --- a/gfx/layers/composite/CompositableHost.cpp +++ b/gfx/layers/composite/CompositableHost.cpp @@ -107,14 +107,12 @@ CompositableHost::FromIPDLActor(PCompositableParent* aActor) } void -CompositableHost::UseTextureHost(TextureHost* aTexture, - const IntRect& aPictureRect) +CompositableHost::UseTextureHost(const nsTArray& aTextures) { - if (!aTexture) { - return; - } if (GetCompositor()) { - aTexture->SetCompositor(GetCompositor()); + for (auto& texture : aTextures) { + texture.mTexture->SetCompositor(GetCompositor()); + } } } diff --git a/gfx/layers/composite/CompositableHost.h b/gfx/layers/composite/CompositableHost.h index 180a69e6b2b8..a40595b8f69f 100644 --- a/gfx/layers/composite/CompositableHost.h +++ b/gfx/layers/composite/CompositableHost.h @@ -150,13 +150,6 @@ public: SetLayer(aLayer); mAttached = true; mKeepAttached = aFlags & KEEP_ATTACHED; - - // If we already have a textureHost before, use that in this moment. - gfx::IntRect pictureRect; - RefPtr 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 @@ -187,8 +180,12 @@ public: virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) = 0; - virtual void UseTextureHost(TextureHost* aTexture, - const gfx::IntRect& aPictureRect); + struct TimedTexture { + RefPtr mTexture; + TimeStamp mTimeStamp; + gfx::IntRect mPictureRect; + }; + virtual void UseTextureHost(const nsTArray& aTextures); virtual void UseComponentAlphaTextures(TextureHost* aTextureOnBlack, TextureHost* aTextureOnWhite); virtual void UseOverlaySource(OverlaySource aOverlay, diff --git a/gfx/layers/composite/ContentHost.cpp b/gfx/layers/composite/ContentHost.cpp index 3247601fc5cc..1bfca7b83468 100644 --- a/gfx/layers/composite/ContentHost.cpp +++ b/gfx/layers/composite/ContentHost.cpp @@ -218,14 +218,15 @@ ContentHostTexture::Composite(EffectChain& aEffectChain, } void -ContentHostTexture::UseTextureHost(TextureHost* aTexture, - const nsIntRect& aPictureRect) +ContentHostTexture::UseTextureHost(const nsTArray& 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) { diff --git a/gfx/layers/composite/ContentHost.h b/gfx/layers/composite/ContentHost.h index f788fc75150b..7b93610f562d 100644 --- a/gfx/layers/composite/ContentHost.h +++ b/gfx/layers/composite/ContentHost.h @@ -131,8 +131,7 @@ public: virtual void PrintInfo(std::stringstream& aStream, const char* aPrefix) override; - virtual void UseTextureHost(TextureHost* aTexture, - const nsIntRect& aPictureRect) override; + virtual void UseTextureHost(const nsTArray& aTextures) override; virtual void UseComponentAlphaTextures(TextureHost* aTextureOnBlack, TextureHost* aTextureOnWhite) override; diff --git a/gfx/layers/composite/ImageHost.cpp b/gfx/layers/composite/ImageHost.cpp index dcb99114b4b5..9b9f8caa12fd 100644 --- a/gfx/layers/composite/ImageHost.cpp +++ b/gfx/layers/composite/ImageHost.cpp @@ -36,16 +36,17 @@ ImageHost::~ImageHost() {} void -ImageHost::UseTextureHost(TextureHost* aTexture, - const nsIntRect& aPictureRect) +ImageHost::UseTextureHost(const nsTArray& 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 @@ -68,6 +69,20 @@ ImageHost::GetAsTextureHost(IntRect* aPictureRect) 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, diff --git a/gfx/layers/composite/ImageHost.h b/gfx/layers/composite/ImageHost.h index 2d9df242c808..c505118146b7 100644 --- a/gfx/layers/composite/ImageHost.h +++ b/gfx/layers/composite/ImageHost.h @@ -51,13 +51,16 @@ public: const gfx::Rect& aClipRect, const nsIntRegion* aVisibleRegion = nullptr) override; - virtual void UseTextureHost(TextureHost* aTexture, - const nsIntRect& aPictureRect) override; + virtual void UseTextureHost(const nsTArray& 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; diff --git a/gfx/layers/ipc/CompositableTransactionParent.cpp b/gfx/layers/ipc/CompositableTransactionParent.cpp index 74f482669410..ffcd6a78cd60 100644 --- a/gfx/layers/ipc/CompositableTransactionParent.cpp +++ b/gfx/layers/ipc/CompositableTransactionParent.cpp @@ -171,21 +171,26 @@ CompositableParentManager::ReceiveCompositableUpdate(const CompositableOperation case CompositableOperation::TOpUseTexture: { const OpUseTexture& op = aEdit.get_OpUseTexture(); CompositableHost* compositable = AsCompositable(op); - RefPtr tex = TextureHost::AsTextureHost(op.textureParent()); - MOZ_ASSERT(tex.get()); - if (!ValidatePictureRect(tex->GetSize(), op.picture())) { - return false; - } - compositable->UseTextureHost(tex, op.picture()); + nsAutoTArray 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); diff --git a/gfx/layers/ipc/ImageBridgeChild.cpp b/gfx/layers/ipc/ImageBridgeChild.cpp index 3936317b4bde..a4619b1a5286 100644 --- a/gfx/layers/ipc/ImageBridgeChild.cpp +++ b/gfx/layers/ipc/ImageBridgeChild.cpp @@ -119,10 +119,12 @@ ImageBridgeChild::UseTexture(CompositableClient* aCompositable, FenceHandle fence = aTexture->GetAcquireFenceHandle(); IntRect pictureRect = aPictureRect ? *aPictureRect : IntRect(IntPoint(0, 0), IntSize(aTexture->GetSize())); + nsAutoTArray 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 diff --git a/gfx/layers/ipc/LayersMessages.ipdlh b/gfx/layers/ipc/LayersMessages.ipdlh index 5b8b20960331..bc6f032261d6 100644 --- a/gfx/layers/ipc/LayersMessages.ipdlh +++ b/gfx/layers/ipc/LayersMessages.ipdlh @@ -383,15 +383,26 @@ union MaybeFence { 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 { diff --git a/gfx/layers/ipc/ShadowLayers.cpp b/gfx/layers/ipc/ShadowLayers.cpp index 113a6bd0efe3..f4774e17bd20 100644 --- a/gfx/layers/ipc/ShadowLayers.cpp +++ b/gfx/layers/ipc/ShadowLayers.cpp @@ -362,10 +362,12 @@ ShadowLayerForwarder::UseTexture(CompositableClient* aCompositable, FenceHandle fence = aTexture->GetAcquireFenceHandle(); IntRect pictureRect = aPictureRect ? *aPictureRect : IntRect(nsIntPoint(0, 0), IntSize(aTexture->GetSize())); + nsAutoTArray 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