diff --git a/gfx/layers/Compositor.h b/gfx/layers/Compositor.h index c53a663cff85..2de953a0650b 100644 --- a/gfx/layers/Compositor.h +++ b/gfx/layers/Compositor.h @@ -39,6 +39,8 @@ * * # Main interfaces and abstractions * + * - Layer, ShadowableLayer and LayerComposite + * (see Layers.h and ipc/ShadowLayers.h) * - CompositableClient and CompositableHost * (client/CompositableClient.h composite/CompositableHost.h) * - TextureClient and TextureHost @@ -69,6 +71,7 @@ * are also platform-independent. Examples of compositable classes are: * - ImageClient * - CanvasClient + * - ContentHost * - etc. * Texture classes (TextureClient and TextureHost) are thin abstractions over * platform-dependent texture memory. They are maniplulated by compositables diff --git a/gfx/layers/client/CompositableClient.h b/gfx/layers/client/CompositableClient.h index 5ca8ae067d26..90b4235f8e0d 100644 --- a/gfx/layers/client/CompositableClient.h +++ b/gfx/layers/client/CompositableClient.h @@ -53,6 +53,11 @@ class ContentClientRemoteBuffer; * Connect() creates the underlying IPDL actor (see CompositableChild) and the * corresponding CompositableHost on the other side. * + * To do in-transaction texture transfer (the default), call + * ShadowLayerForwarder::Attach(CompositableClient*, ShadowableLayer*). This + * will let the LayerComposite on the compositor side know which + * CompositableHost to use for compositing. + * * To do async texture transfer (like async-video), the CompositableClient * should be created with a different CompositableForwarder (like * ImageBridgeChild) and attachment is done with diff --git a/gfx/layers/composite/CompositableHost.cpp b/gfx/layers/composite/CompositableHost.cpp index 5c0d092ae4a0..018b5b349db8 100644 --- a/gfx/layers/composite/CompositableHost.cpp +++ b/gfx/layers/composite/CompositableHost.cpp @@ -29,17 +29,41 @@ namespace layers { class Compositor; CompositableHost::CompositableHost(const TextureInfo& aTextureInfo) - : mTextureInfo(aTextureInfo), mCompositorBridgeID(0) { + : mTextureInfo(aTextureInfo), + mCompositorBridgeID(0), + mLayer(nullptr), + mAttached(false), + mKeepAttached(false) { MOZ_COUNT_CTOR(CompositableHost); } CompositableHost::~CompositableHost() { MOZ_COUNT_DTOR(CompositableHost); } void CompositableHost::UseTextureHost(const nsTArray& aTextures) { + if (mTextureSourceProvider) { + for (auto& texture : aTextures) { + texture.mTexture->SetTextureSourceProvider(mTextureSourceProvider); + } + } +} + +void CompositableHost::UseComponentAlphaTextures(TextureHost* aTextureOnBlack, + TextureHost* aTextureOnWhite) { + MOZ_ASSERT(aTextureOnBlack && aTextureOnWhite); + if (mTextureSourceProvider) { + aTextureOnBlack->SetTextureSourceProvider(mTextureSourceProvider); + aTextureOnWhite->SetTextureSourceProvider(mTextureSourceProvider); + } } void CompositableHost::RemoveTextureHost(TextureHost* aTexture) {} +void CompositableHost::SetTextureSourceProvider( + TextureSourceProvider* aProvider) { + MOZ_ASSERT(aProvider); + mTextureSourceProvider = aProvider; +} + /* static */ already_AddRefed CompositableHost::Create( const TextureInfo& aTextureInfo) { @@ -66,5 +90,9 @@ void CompositableHost::DumpTextureHost(std::stringstream& aStream, aStream << gfxUtils::GetAsDataURI(dSurf).get(); } +TextureSourceProvider* CompositableHost::GetTextureSourceProvider() const { + return mTextureSourceProvider; +} + } // namespace layers } // namespace mozilla diff --git a/gfx/layers/composite/CompositableHost.h b/gfx/layers/composite/CompositableHost.h index e2bcad7df594..e696a2f484fb 100644 --- a/gfx/layers/composite/CompositableHost.h +++ b/gfx/layers/composite/CompositableHost.h @@ -7,29 +7,48 @@ #ifndef MOZILLA_GFX_BUFFERHOST_H #define MOZILLA_GFX_BUFFERHOST_H -#include // for uint64_t -#include // for FILE -#include "gfxRect.h" // for gfxRect -#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc -#include "mozilla/Attributes.h" // for override -#include "mozilla/RefPtr.h" // for RefPtr, RefCounted, etc -//#include "mozilla/gfx/MatrixFwd.h" // for Matrix4x4 -#include "mozilla/gfx/Polygon.h" // for Polygon -#include "mozilla/gfx/Rect.h" // for Rect +#include // for uint64_t +#include // for FILE +#include "gfxRect.h" // for gfxRect +#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc +#include "mozilla/Attributes.h" // for override +#include "mozilla/RefPtr.h" // for RefPtr, RefCounted, etc +#include "mozilla/gfx/MatrixFwd.h" // for Matrix4x4 +#include "mozilla/gfx/Point.h" // for Point +#include "mozilla/gfx/Polygon.h" // for Polygon +#include "mozilla/gfx/Rect.h" // for Rect +#include "mozilla/gfx/Types.h" // for SamplingFilter #include "mozilla/ipc/ProtocolUtils.h" +#include "mozilla/layers/Compositor.h" // for Compositor #include "mozilla/layers/CompositorTypes.h" // for TextureInfo, etc -//#include "mozilla/layers/LayersTypes.h" // for LayerRenderState, etc +#include "mozilla/layers/Effects.h" // for Texture Effect +#include "mozilla/layers/LayersTypes.h" // for LayerRenderState, etc #include "mozilla/layers/LayersMessages.h" #include "mozilla/layers/TextureHost.h" // for TextureHost +#include "mozilla/mozalloc.h" // for operator delete #include "nsCOMPtr.h" // for already_AddRefed +#include "nsRegion.h" // for nsIntRegion #include "nscore.h" // for nsACString #include "Units.h" // for CSSToScreenScale namespace mozilla { +namespace gfx { +class DataSourceSurface; +} // namespace gfx namespace layers { +class Layer; +class LayerComposite; +class ImageHost; +class Compositor; +class ThebesBufferData; +class TiledContentHost; +class CompositableParentManager; class WebRenderImageHost; +class ContentHost; +class ContentHostTexture; +struct EffectChain; struct ImageCompositeNotificationInfo { base::ProcessId mImageBridgeProcessId; @@ -71,13 +90,100 @@ class CompositableHost { static already_AddRefed Create( const TextureInfo& aTextureInfo); + virtual CompositableType GetType() = 0; + + // If base class overrides, it should still call the parent implementation + virtual void SetTextureSourceProvider(TextureSourceProvider* aProvider); + + // composite the contents of this buffer host to the compositor's surface + virtual void Composite(Compositor* aCompositor, LayerComposite* aLayer, + EffectChain& aEffectChain, float aOpacity, + const gfx::Matrix4x4& aTransform, + const gfx::SamplingFilter aSamplingFilter, + const gfx::IntRect& aClipRect, + const nsIntRegion* aVisibleRegion = nullptr, + const Maybe& aGeometry = Nothing()) = 0; + + /** + * Update the content host. + * aUpdated is the region which should be updated. + */ + virtual bool UpdateThebes(const ThebesBufferData& aData, + const nsIntRegion& aUpdated, + const nsIntRegion& aOldValidRegionBack) { + NS_ERROR("should be implemented or not used"); + return false; + } + + /** + * Returns the front buffer. + * *aPictureRect (if non-null, and the returned TextureHost is non-null) + * is set to the picture rect. + */ + virtual TextureHost* GetAsTextureHost(gfx::IntRect* aPictureRect = nullptr) { + return nullptr; + } + + virtual gfx::IntSize GetImageSize() { + MOZ_ASSERT(false, "Should have been overridden"); + return gfx::IntSize(); + } + + const TextureInfo& GetTextureInfo() const { return mTextureInfo; } + + TextureSourceProvider* GetTextureSourceProvider() const; + + Layer* GetLayer() const { return mLayer; } + void SetLayer(Layer* aLayer) { mLayer = aLayer; } + + virtual ContentHost* AsContentHost() { return nullptr; } + virtual ContentHostTexture* AsContentHostTexture() { return nullptr; } + virtual ImageHost* AsImageHost() { return nullptr; } + virtual TiledContentHost* AsTiledContentHost() { return nullptr; } virtual WebRenderImageHost* AsWebRenderImageHost() { return nullptr; } + typedef uint32_t AttachFlags; + static const AttachFlags NO_FLAGS = 0; + static const AttachFlags ALLOW_REATTACH = 1; + static const AttachFlags KEEP_ATTACHED = 2; + static const AttachFlags FORCE_DETACH = 2; + + virtual void Attach(Layer* aLayer, TextureSourceProvider* aProvider, + AttachFlags aFlags = NO_FLAGS) { + MOZ_ASSERT(aProvider); + NS_ASSERTION(aFlags & ALLOW_REATTACH || !mAttached, + "Re-attaching compositables must be explicitly authorised"); + SetTextureSourceProvider(aProvider); + SetLayer(aLayer); + mAttached = true; + mKeepAttached = aFlags & KEEP_ATTACHED; + } + // 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. + // Only force detach if the IPDL tree is being shutdown. + virtual void Detach(Layer* aLayer = nullptr, AttachFlags aFlags = NO_FLAGS) { + if (!mKeepAttached || aLayer == mLayer || aFlags & FORCE_DETACH) { + SetLayer(nullptr); + mAttached = false; + mKeepAttached = false; + } + } + bool IsAttached() { return mAttached; } + virtual void Dump(std::stringstream& aStream, const char* aPrefix = "", bool aDumpHtml = false) {} static void DumpTextureHost(std::stringstream& aStream, TextureHost* aTexture); + virtual already_AddRefed GetAsSurface() { + return nullptr; + } + struct TimedTexture { CompositableTextureHostRef mTexture; TimeStamp mTimeStamp; @@ -86,6 +192,8 @@ class CompositableHost { int32_t mProducerID; }; virtual void UseTextureHost(const nsTArray& aTextures); + virtual void UseComponentAlphaTextures(TextureHost* aTextureOnBlack, + TextureHost* aTextureOnWhite); virtual void RemoveTextureHost(TextureHost* aTexture); uint64_t GetCompositorBridgeID() const { return mCompositorBridgeID; } @@ -95,11 +203,22 @@ class CompositableHost { void SetCompositorBridgeID(uint64_t aID) { mCompositorBridgeID = aID; } + virtual bool Lock() { return false; } + + virtual void Unlock() {} + + virtual already_AddRefed GenEffect( + const gfx::SamplingFilter aSamplingFilter) { + return nullptr; + } + /// Called when shutting down the layer tree. /// This is a good place to clear all potential gpu resources before the /// widget is is destroyed. virtual void CleanupResources() {} + virtual void BindTextureSource() {} + virtual uint32_t GetDroppedFrames() { return 0; } protected: @@ -107,6 +226,29 @@ class CompositableHost { TextureInfo mTextureInfo; AsyncCompositableRef mAsyncRef; uint64_t mCompositorBridgeID; + RefPtr mTextureSourceProvider; + Layer* mLayer; + bool mAttached; + bool mKeepAttached; +}; + +class AutoLockCompositableHost final { + public: + explicit AutoLockCompositableHost(CompositableHost* aHost) : mHost(aHost) { + mSucceeded = (mHost && mHost->Lock()); + } + + ~AutoLockCompositableHost() { + if (mSucceeded && mHost) { + mHost->Unlock(); + } + } + + bool Failed() const { return !mSucceeded; } + + private: + RefPtr mHost; + bool mSucceeded; }; } // namespace layers diff --git a/gfx/layers/composite/TextureHost.h b/gfx/layers/composite/TextureHost.h index 5999a6598b5a..0299f8e7e1bb 100644 --- a/gfx/layers/composite/TextureHost.h +++ b/gfx/layers/composite/TextureHost.h @@ -21,7 +21,6 @@ #include "mozilla/layers/CompositorTypes.h" // for TextureFlags, etc #include "mozilla/layers/LayersTypes.h" // for LayerRenderState, etc #include "mozilla/layers/LayersSurfaces.h" -#include "mozilla/layers/TextureSourceProvider.h" #include "mozilla/mozalloc.h" // for operator delete #include "mozilla/Range.h" #include "mozilla/UniquePtr.h" // for UniquePtr @@ -70,6 +69,7 @@ class TextureReadLock; class TextureSourceOGL; class TextureSourceD3D11; class TextureSourceBasic; +class TextureSourceProvider; class DataTextureSource; class PTextureParent; class TextureParent; diff --git a/gfx/layers/ipc/CompositableTransactionParent.cpp b/gfx/layers/ipc/CompositableTransactionParent.cpp index e723161cf5d1..c16e11281171 100644 --- a/gfx/layers/ipc/CompositableTransactionParent.cpp +++ b/gfx/layers/ipc/CompositableTransactionParent.cpp @@ -7,6 +7,8 @@ #include "CompositableTransactionParent.h" #include "CompositableHost.h" // for CompositableParent, etc #include "CompositorBridgeParent.h" // for CompositorBridgeParent +#include "GLContext.h" // for GLContext +#include "Layers.h" // for Layer #include "mozilla/Assertions.h" // for MOZ_ASSERT, etc #include "mozilla/RefPtr.h" // for RefPtr #include "mozilla/layers/CompositorTypes.h" @@ -14,6 +16,7 @@ #include "mozilla/layers/LayersSurfaces.h" // for SurfaceDescriptor #include "mozilla/layers/LayersTypes.h" // for MOZ_LAYERS_LOG #include "mozilla/layers/TextureHost.h" // for TextureHost +#include "mozilla/layers/TextureHostOGL.h" // for TextureHostOGL #include "mozilla/mozalloc.h" // for operator delete #include "mozilla/Unused.h" #include "nsDebug.h" // for NS_WARNING, NS_ASSERTION @@ -26,6 +29,33 @@ namespace mozilla { namespace layers { +class Compositor; + +// This function can in some cases fail and return false without it being a bug. +// This can theoretically happen if the ImageBridge sends frames before +// we created the layer tree. Since we can't enforce that the layer +// tree is already created before ImageBridge operates, there isn't much +// we can do about it, but in practice it is very rare. +// Typically when a tab with a video is dragged from a window to another, +// there can be a short time when the video is still sending frames +// asynchonously while the layer tree is not reconstructed. It's not a +// big deal. +// Note that Layers transactions do not need to call this because they always +// schedule the composition, in LayerManagerComposite::EndTransaction. +static bool ScheduleComposition(CompositableHost* aCompositable) { + uint64_t id = aCompositable->GetCompositorBridgeID(); + if (!id) { + return false; + } + CompositorBridgeParent* cp = + CompositorBridgeParent::GetCompositorBridgeParent(id); + if (!cp) { + return false; + } + cp->ScheduleComposition(wr::RenderReasons::ASYNC_IMAGE); + return true; +} + bool CompositableParentManager::ReceiveCompositableUpdate( const CompositableOperation& aEdit) { // Ignore all operations on compositables created on stale compositors. We @@ -41,6 +71,13 @@ bool CompositableParentManager::ReceiveCompositableUpdate( bool CompositableParentManager::ReceiveCompositableUpdate( const CompositableOperationDetail& aDetail, NotNull aCompositable) { + if (TextureSourceProvider* provider = + aCompositable->GetTextureSourceProvider()) { + if (!provider->IsValid()) { + return false; + } + } + switch (aDetail.type()) { case CompositableOperationDetail::TOpRemoveTexture: { const OpRemoveTexture& op = aDetail.get_OpRemoveTexture(); @@ -81,6 +118,10 @@ bool CompositableParentManager::ReceiveCompositableUpdate( } } } + + if (UsesImageBridge() && aCompositable->GetLayer()) { + ScheduleComposition(aCompositable); + } break; } case CompositableOperationDetail::TOpDeliverAcquireFence: { @@ -155,7 +196,10 @@ void CompositableParentManager::ReleaseCompositable( return; } + RefPtr host = iter->second; mCompositables.erase(iter); + + host->Detach(nullptr, CompositableHost::FORCE_DETACH); } } // namespace layers diff --git a/gfx/layers/wr/WebRenderImageHost.cpp b/gfx/layers/wr/WebRenderImageHost.cpp index 11774f843a3a..e531a9a8c29f 100644 --- a/gfx/layers/wr/WebRenderImageHost.cpp +++ b/gfx/layers/wr/WebRenderImageHost.cpp @@ -10,7 +10,9 @@ #include "mozilla/ScopeExit.h" #include "mozilla/layers/AsyncImagePipelineManager.h" +#include "mozilla/layers/Compositor.h" // for Compositor #include "mozilla/layers/CompositorVsyncScheduler.h" // for CompositorVsyncScheduler +#include "mozilla/layers/Effects.h" // for TexturedEffect, Effect, etc #include "mozilla/layers/WebRenderBridgeParent.h" #include "mozilla/layers/WebRenderTextureHost.h" #include "nsAString.h" @@ -96,6 +98,11 @@ void WebRenderImageHost::UseTextureHost( } } +void WebRenderImageHost::UseComponentAlphaTextures( + TextureHost* aTextureOnBlack, TextureHost* aTextureOnWhite) { + MOZ_ASSERT_UNREACHABLE("unexpected to be called"); +} + void WebRenderImageHost::CleanupResources() { ClearImages(); SetCurrentTextureHost(nullptr); @@ -134,6 +141,11 @@ void WebRenderImageHost::AppendImageCompositeNotification( } } +TextureHost* WebRenderImageHost::GetAsTextureHost(IntRect* aPictureRect) { + MOZ_ASSERT_UNREACHABLE("unexpected to be called"); + return nullptr; +} + TextureHost* WebRenderImageHost::GetAsTextureHostForComposite( AsyncImagePipelineManager* aAsyncImageManager) { mCurrentAsyncImageManager = aAsyncImageManager; @@ -170,6 +182,27 @@ void WebRenderImageHost::SetCurrentTextureHost(TextureHost* aTexture) { mCurrentTextureHost = aTexture; } +void WebRenderImageHost::Attach(Layer* aLayer, TextureSourceProvider* aProvider, + AttachFlags aFlags) {} + +void WebRenderImageHost::Composite( + Compositor* aCompositor, LayerComposite* aLayer, EffectChain& aEffectChain, + float aOpacity, const gfx::Matrix4x4& aTransform, + const gfx::SamplingFilter aSamplingFilter, const gfx::IntRect& aClipRect, + const nsIntRegion* aVisibleRegion, const Maybe& aGeometry) { + MOZ_ASSERT_UNREACHABLE("unexpected to be called"); +} + +void WebRenderImageHost::SetTextureSourceProvider( + TextureSourceProvider* aProvider) { + if (mTextureSourceProvider != aProvider) { + for (const auto& img : Images()) { + img.mTextureHost->SetTextureSourceProvider(aProvider); + } + } + CompositableHost::SetTextureSourceProvider(aProvider); +} + void WebRenderImageHost::Dump(std::stringstream& aStream, const char* aPrefix, bool aDumpHtml) { for (const auto& img : Images()) { @@ -180,6 +213,28 @@ void WebRenderImageHost::Dump(std::stringstream& aStream, const char* aPrefix, } } +already_AddRefed WebRenderImageHost::GetAsSurface() { + MOZ_ASSERT_UNREACHABLE("unexpected to be called"); + return nullptr; +} + +bool WebRenderImageHost::Lock() { + MOZ_ASSERT_UNREACHABLE("unexpected to be called"); + return false; +} + +void WebRenderImageHost::Unlock() { + MOZ_ASSERT_UNREACHABLE("unexpected to be called"); +} + +IntSize WebRenderImageHost::GetImageSize() { + const TimedImage* img = ChooseImage(); + if (img) { + return IntSize(img->mPictureRect.Width(), img->mPictureRect.Height()); + } + return IntSize(); +} + void WebRenderImageHost::SetWrBridge(const wr::PipelineId& aPipelineId, WebRenderBridgeParent* aWrBridge) { MOZ_ASSERT(aWrBridge); diff --git a/gfx/layers/wr/WebRenderImageHost.h b/gfx/layers/wr/WebRenderImageHost.h index 6c42ccc563e7..1b663308b77f 100644 --- a/gfx/layers/wr/WebRenderImageHost.h +++ b/gfx/layers/wr/WebRenderImageHost.h @@ -28,12 +28,39 @@ class WebRenderImageHost : public CompositableHost, public ImageComposite { explicit WebRenderImageHost(const TextureInfo& aTextureInfo); virtual ~WebRenderImageHost(); + CompositableType GetType() override { return mTextureInfo.mCompositableType; } + + void Composite(Compositor* aCompositor, LayerComposite* aLayer, + EffectChain& aEffectChain, float aOpacity, + const gfx::Matrix4x4& aTransform, + const gfx::SamplingFilter aSamplingFilter, + const gfx::IntRect& aClipRect, + const nsIntRegion* aVisibleRegion = nullptr, + const Maybe& aGeometry = Nothing()) override; + void UseTextureHost(const nsTArray& aTextures) override; + void UseComponentAlphaTextures(TextureHost* aTextureOnBlack, + TextureHost* aTextureOnWhite) override; void RemoveTextureHost(TextureHost* aTexture) override; + TextureHost* GetAsTextureHost(gfx::IntRect* aPictureRect = nullptr) override; + + void Attach(Layer* aLayer, TextureSourceProvider* aProvider, + AttachFlags aFlags = NO_FLAGS) override; + + void SetTextureSourceProvider(TextureSourceProvider* aProvider) override; + + gfx::IntSize GetImageSize() override; + void Dump(std::stringstream& aStream, const char* aPrefix = "", bool aDumpHtml = false) override; + already_AddRefed GetAsSurface() override; + + bool Lock() override; + + void Unlock() override; + void CleanupResources() override; uint32_t GetDroppedFrames() override { return GetDroppedFramesAndReset(); } diff --git a/gfx/webrender_bindings/RenderThread.cpp b/gfx/webrender_bindings/RenderThread.cpp index 29dec5e7c97f..03f665525c30 100644 --- a/gfx/webrender_bindings/RenderThread.cpp +++ b/gfx/webrender_bindings/RenderThread.cpp @@ -22,7 +22,6 @@ #include "mozilla/layers/CompositorManagerParent.h" #include "mozilla/layers/WebRenderBridgeParent.h" #include "mozilla/layers/SharedSurfacesParent.h" -#include "mozilla/layers/SurfacePool.h" #include "mozilla/StaticPtr.h" #include "mozilla/Telemetry.h" #include "mozilla/webrender/RendererOGL.h"