diff options
Diffstat (limited to 'gfx/layers/wr/AsyncImagePipelineManager.h')
-rw-r--r-- | gfx/layers/wr/AsyncImagePipelineManager.h | 278 |
1 files changed, 278 insertions, 0 deletions
diff --git a/gfx/layers/wr/AsyncImagePipelineManager.h b/gfx/layers/wr/AsyncImagePipelineManager.h new file mode 100644 index 0000000000..0a9efe3869 --- /dev/null +++ b/gfx/layers/wr/AsyncImagePipelineManager.h @@ -0,0 +1,278 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef MOZILLA_GFX_WEBRENDERCOMPOSITABLE_HOLDER_H +#define MOZILLA_GFX_WEBRENDERCOMPOSITABLE_HOLDER_H + +#include <vector> + +#include "CompositableHost.h" +#include "mozilla/gfx/Point.h" +#include "mozilla/ipc/FileDescriptor.h" +#include "mozilla/layers/TextureHost.h" +#include "mozilla/Maybe.h" +#include "mozilla/webrender/WebRenderAPI.h" +#include "mozilla/webrender/WebRenderTypes.h" +#include "nsClassHashtable.h" + +namespace mozilla { + +namespace wr { +class DisplayListBuilder; +class WebRenderAPI; +class WebRenderPipelineInfo; +} // namespace wr + +namespace layers { + +class CompositableHost; +class CompositorVsyncScheduler; +class WebRenderImageHost; +class WebRenderTextureHost; + +class AsyncImagePipelineManager final { + public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AsyncImagePipelineManager) + + explicit AsyncImagePipelineManager(RefPtr<wr::WebRenderAPI>&& aApi, + bool aUseCompositorWnd); + + protected: + ~AsyncImagePipelineManager(); + + public: + void Destroy(); + + bool UseCompositorWnd() const { return mUseCompositorWnd; } + + void AddPipeline(const wr::PipelineId& aPipelineId, + WebRenderBridgeParent* aWrBridge); + void RemovePipeline(const wr::PipelineId& aPipelineId, + const wr::Epoch& aEpoch); + WebRenderBridgeParent* GetWrBridge(const wr::PipelineId& aPipelineId); + + void HoldExternalImage(const wr::PipelineId& aPipelineId, + const wr::Epoch& aEpoch, TextureHost* aTexture); + void HoldExternalImage(const wr::PipelineId& aPipelineId, + const wr::Epoch& aEpoch, + const wr::ExternalImageId& aImageId); + + // This is called from the Renderer thread to notify this class about the + // pipelines in the most recently completed update. + // @param aInfo PipelineInfo for the update + // @param aLatestFrameId RenderedFrameId if a frame has been submitted for + // rendering, invalid if not + // @param aLastCompletedFrameId RenderedFrameId for the last completed frame + void NotifyPipelinesUpdated(RefPtr<const wr::WebRenderPipelineInfo> aInfo, + wr::RenderedFrameId aLatestFrameId, + wr::RenderedFrameId aLastCompletedFrameId, + ipc::FileDescriptor&& aFenceFd); + + // This is run on the compositor thread to process mRenderSubmittedUpdates. We + // make this public because we need to invoke it from other places. + void ProcessPipelineUpdates(); + + TimeStamp GetCompositionTime() const { return mCompositionTime; } + CompositionOpportunityId GetCompositionOpportunityId() const { + return mCompositionOpportunityId; + } + + void SetCompositionInfo(TimeStamp aTimeStamp, + CompositionOpportunityId aCompositionOpportunityId) { + mCompositionTime = aTimeStamp; + mCompositionOpportunityId = aCompositionOpportunityId; + if (!mCompositionTime.IsNull() && !mCompositeUntilTime.IsNull() && + mCompositionTime >= mCompositeUntilTime) { + mCompositeUntilTime = TimeStamp(); + } + } + void CompositeUntil(TimeStamp aTimeStamp) { + if (mCompositeUntilTime.IsNull() || mCompositeUntilTime < aTimeStamp) { + mCompositeUntilTime = aTimeStamp; + } + } + TimeStamp GetCompositeUntilTime() const { return mCompositeUntilTime; } + + void AddAsyncImagePipeline(const wr::PipelineId& aPipelineId, + WebRenderImageHost* aImageHost); + void RemoveAsyncImagePipeline(const wr::PipelineId& aPipelineId, + wr::TransactionBuilder& aTxn); + + void UpdateAsyncImagePipeline(const wr::PipelineId& aPipelineId, + const LayoutDeviceRect& aScBounds, + VideoInfo::Rotation aRotation, + const wr::ImageRendering& aFilter, + const wr::MixBlendMode& aMixBlendMode); + void ApplyAsyncImagesOfImageBridge(wr::TransactionBuilder& aSceneBuilderTxn, + wr::TransactionBuilder& aFastTxn); + void ApplyAsyncImageForPipeline(const wr::PipelineId& aPipelineId, + wr::TransactionBuilder& aTxn, + wr::TransactionBuilder& aTxnForImageBridge); + + void SetEmptyDisplayList(const wr::PipelineId& aPipelineId, + wr::TransactionBuilder& aTxn, + wr::TransactionBuilder& aTxnForImageBridge); + + void AppendImageCompositeNotification( + const ImageCompositeNotificationInfo& aNotification) { + mImageCompositeNotifications.AppendElement(aNotification); + } + + void FlushImageNotifications( + nsTArray<ImageCompositeNotificationInfo>* aNotifications) { + aNotifications->AppendElements(std::move(mImageCompositeNotifications)); + } + + void SetWillGenerateFrame(); + bool GetAndResetWillGenerateFrame(); + + static wr::ExternalImageId GetNextExternalImageId(); + + private: + void ProcessPipelineRendered(const wr::PipelineId& aPipelineId, + const wr::Epoch& aEpoch, + wr::RenderedFrameId aRenderedFrameId); + void ProcessPipelineRemoved(const wr::RemovedPipeline& aRemovedPipeline, + wr::RenderedFrameId aRenderedFrameId); + + wr::Epoch GetNextImageEpoch(); + uint32_t GetNextResourceId() { return ++mResourceId; } + wr::IdNamespace GetNamespace() { return mIdNamespace; } + wr::ImageKey GenerateImageKey() { + wr::ImageKey key; + key.mNamespace = GetNamespace(); + key.mHandle = GetNextResourceId(); + return key; + } + + struct ForwardingTextureHost { + ForwardingTextureHost(const wr::Epoch& aEpoch, TextureHost* aTexture) + : mEpoch(aEpoch), mTexture(aTexture) {} + wr::Epoch mEpoch; + CompositableTextureHostRef mTexture; + }; + + struct ForwardingExternalImage { + ForwardingExternalImage(const wr::Epoch& aEpoch, + const wr::ExternalImageId& aImageId) + : mEpoch(aEpoch), mImageId(aImageId) {} + ~ForwardingExternalImage(); + wr::Epoch mEpoch; + wr::ExternalImageId mImageId; + }; + + struct PipelineTexturesHolder { + // Holds forwarding WebRenderTextureHosts. + std::vector<ForwardingTextureHost> mTextureHostsUntilRenderSubmitted; + // TextureHosts that must be held until rendering has completed. UniquePtr + // is used to make the entries movable, ideally ForwardingTextureHost would + // be fully movable. + std::vector<UniquePtr<ForwardingTextureHost>> + mTextureHostsUntilRenderCompleted; + std::vector<UniquePtr<ForwardingExternalImage>> mExternalImages; + Maybe<wr::Epoch> mDestroyedEpoch; + WebRenderBridgeParent* MOZ_NON_OWNING_REF mWrBridge = nullptr; + }; + + struct AsyncImagePipeline { + AsyncImagePipeline(wr::PipelineId aPipelineId, + layers::WebRenderBackend aBackend); + void Update(const LayoutDeviceRect& aScBounds, + VideoInfo::Rotation aRotation, + const wr::ImageRendering& aFilter, + const wr::MixBlendMode& aMixBlendMode) { + mIsChanged |= !mScBounds.IsEqualEdges(aScBounds) || + mRotation != aRotation || mFilter != aFilter || + mMixBlendMode != aMixBlendMode; + mScBounds = aScBounds; + mRotation = aRotation; + mFilter = aFilter; + mMixBlendMode = aMixBlendMode; + } + + bool mInitialised; + bool mIsChanged; + bool mUseExternalImage; + LayoutDeviceRect mScBounds; + VideoInfo::Rotation mRotation; + wr::ImageRendering mFilter; + wr::MixBlendMode mMixBlendMode; + RefPtr<WebRenderImageHost> mImageHost; + CompositableTextureHostRef mCurrentTexture; + nsTArray<wr::ImageKey> mKeys; + wr::DisplayListBuilder mDLBuilder; + }; + + void ApplyAsyncImageForPipeline(const wr::Epoch& aEpoch, + const wr::PipelineId& aPipelineId, + AsyncImagePipeline* aPipeline, + wr::TransactionBuilder& aSceneBuilderTxn, + wr::TransactionBuilder& aMaybeFastTxn); + Maybe<TextureHost::ResourceUpdateOp> UpdateImageKeys( + const wr::Epoch& aEpoch, const wr::PipelineId& aPipelineId, + AsyncImagePipeline* aPipeline, nsTArray<wr::ImageKey>& aKeys, + wr::TransactionBuilder& aSceneBuilderTxn, + wr::TransactionBuilder& aMaybeFastTxn); + Maybe<TextureHost::ResourceUpdateOp> UpdateWithoutExternalImage( + TextureHost* aTexture, wr::ImageKey aKey, TextureHost::ResourceUpdateOp, + wr::TransactionBuilder& aTxn); + + void CheckForTextureHostsNotUsedByGPU(); + + RefPtr<wr::WebRenderAPI> mApi; + bool mUseCompositorWnd; + + const wr::IdNamespace mIdNamespace; + const bool mUseTripleBuffering; + uint32_t mResourceId; + + nsClassHashtable<nsUint64HashKey, PipelineTexturesHolder> + mPipelineTexturesHolders; + nsClassHashtable<nsUint64HashKey, AsyncImagePipeline> mAsyncImagePipelines; + wr::Epoch mAsyncImageEpoch; + bool mWillGenerateFrame; + bool mDestroyed; + +#ifdef XP_WIN + bool mUseWebRenderDCompVideoOverlayWin; +#endif + + // Render time for the current composition. + TimeStamp mCompositionTime; + + // CompositionOpportunityId of the current composition. + CompositionOpportunityId mCompositionOpportunityId; + + // When nonnull, during rendering, some compositable indicated that it will + // change its rendering at this time. In order not to miss it, we composite + // on every vsync until this time occurs (this is the latest such time). + TimeStamp mCompositeUntilTime; + + nsTArray<ImageCompositeNotificationInfo> mImageCompositeNotifications; + + struct WebRenderPipelineInfoHolder { + WebRenderPipelineInfoHolder(RefPtr<const wr::WebRenderPipelineInfo>&& aInfo, + ipc::FileDescriptor&& aFenceFd); + ~WebRenderPipelineInfoHolder(); + RefPtr<const wr::WebRenderPipelineInfo> mInfo; + ipc::FileDescriptor mFenceFd; + }; + + std::vector<std::pair<wr::RenderedFrameId, WebRenderPipelineInfoHolder>> + mRenderSubmittedUpdates; + Mutex mRenderSubmittedUpdatesLock MOZ_UNANNOTATED; + + Atomic<uint64_t> mLastCompletedFrameId; + std::vector<std::pair<wr::RenderedFrameId, + std::vector<UniquePtr<ForwardingTextureHost>>>> + mTexturesInUseByGPU; + ipc::FileDescriptor mReleaseFenceFd; +}; + +} // namespace layers +} // namespace mozilla + +#endif /* MOZILLA_GFX_WEBRENDERCOMPOSITABLE_HOLDER_H */ |