diff options
Diffstat (limited to 'gfx/layers/wr/WebRenderBridgeParent.h')
-rw-r--r-- | gfx/layers/wr/WebRenderBridgeParent.h | 540 |
1 files changed, 540 insertions, 0 deletions
diff --git a/gfx/layers/wr/WebRenderBridgeParent.h b/gfx/layers/wr/WebRenderBridgeParent.h new file mode 100644 index 0000000000..602e2a74f4 --- /dev/null +++ b/gfx/layers/wr/WebRenderBridgeParent.h @@ -0,0 +1,540 @@ +/* -*- 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_layers_WebRenderBridgeParent_h +#define mozilla_layers_WebRenderBridgeParent_h + +#include <unordered_map> +#include <unordered_set> + +#include "CompositableHost.h" // for CompositableHost, ImageCompositeNotificationInfo +#include "GLContextProvider.h" +#include "mozilla/DataMutex.h" +#include "mozilla/layers/CompositableTransactionParent.h" +#include "mozilla/layers/CompositorVsyncSchedulerOwner.h" +#include "mozilla/layers/PWebRenderBridgeParent.h" +#include "mozilla/HashTable.h" +#include "mozilla/Maybe.h" +#include "mozilla/Result.h" +#include "mozilla/UniquePtr.h" +#include "mozilla/webrender/WebRenderTypes.h" +#include "mozilla/webrender/WebRenderAPI.h" +#include "nsTArrayForwardDeclare.h" +#include "WindowRenderer.h" + +namespace mozilla { + +namespace gl { +class GLContext; +} + +namespace widget { +class CompositorWidget; +} + +namespace wr { +class WebRenderAPI; +class WebRenderPipelineInfo; +} // namespace wr + +namespace layers { + +class AsyncImagePipelineManager; +class Compositor; +class CompositorBridgeParentBase; +class CompositorVsyncScheduler; +class OMTASampler; +class UiCompositorControllerParent; +class WebRenderBridgeParentRef; +class WebRenderImageHost; +struct WrAnimations; + +struct CompositorAnimationIdsForEpoch { + CompositorAnimationIdsForEpoch(const wr::Epoch& aEpoch, + nsTArray<uint64_t>&& aIds) + : mEpoch(aEpoch), mIds(std::move(aIds)) {} + + wr::Epoch mEpoch; + nsTArray<uint64_t> mIds; +}; + +class WebRenderBridgeParent final : public PWebRenderBridgeParent, + public CompositorVsyncSchedulerOwner, + public CompositableParentManager, + public FrameRecorder { + public: + WebRenderBridgeParent(CompositorBridgeParentBase* aCompositorBridge, + const wr::PipelineId& aPipelineId, + widget::CompositorWidget* aWidget, + CompositorVsyncScheduler* aScheduler, + RefPtr<wr::WebRenderAPI>&& aApi, + RefPtr<AsyncImagePipelineManager>&& aImageMgr, + TimeDuration aVsyncRate); + + static WebRenderBridgeParent* CreateDestroyed( + const wr::PipelineId& aPipelineId, nsCString&& aError); + + wr::PipelineId PipelineId() { return mPipelineId; } + already_AddRefed<wr::WebRenderAPI> GetWebRenderAPI() { + return do_AddRef(mApi); + } + AsyncImagePipelineManager* AsyncImageManager() { return mAsyncImageManager; } + CompositorVsyncScheduler* CompositorScheduler() { + return mCompositorScheduler.get(); + } + CompositorBridgeParentBase* GetCompositorBridge() { + return mCompositorBridge; + } + + void UpdateQualitySettings(); + void UpdateDebugFlags(); + void UpdateParameters(); + void UpdateBoolParameters(); + void UpdateProfilerUI(); + + mozilla::ipc::IPCResult RecvEnsureConnected( + TextureFactoryIdentifier* aTextureFactoryIdentifier, + MaybeIdNamespace* aMaybeIdNamespace, nsCString* aError) override; + + mozilla::ipc::IPCResult RecvNewCompositable( + const CompositableHandle& aHandle, const TextureInfo& aInfo) override; + mozilla::ipc::IPCResult RecvReleaseCompositable( + const CompositableHandle& aHandle) override; + + mozilla::ipc::IPCResult RecvShutdown() override; + mozilla::ipc::IPCResult RecvShutdownSync() override; + mozilla::ipc::IPCResult RecvDeleteCompositorAnimations( + nsTArray<uint64_t>&& aIds) override; + mozilla::ipc::IPCResult RecvUpdateResources( + const wr::IdNamespace& aIdNamespace, + nsTArray<OpUpdateResource>&& aUpdates, + nsTArray<RefCountedShmem>&& aSmallShmems, + nsTArray<ipc::Shmem>&& aLargeShmems) override; + mozilla::ipc::IPCResult RecvSetDisplayList( + DisplayListData&& aDisplayList, nsTArray<OpDestroy>&& aToDestroy, + const uint64_t& aFwdTransactionId, const TransactionId& aTransactionId, + const bool& aContainsSVGGroup, const VsyncId& aVsyncId, + const TimeStamp& aVsyncStartTime, const TimeStamp& aRefreshStartTime, + const TimeStamp& aTxnStartTime, const nsACString& aTxnURL, + const TimeStamp& aFwdTime, + nsTArray<CompositionPayload>&& aPayloads) override; + mozilla::ipc::IPCResult RecvEmptyTransaction( + const FocusTarget& aFocusTarget, + Maybe<TransactionData>&& aTransactionData, + nsTArray<OpDestroy>&& aToDestroy, const uint64_t& aFwdTransactionId, + const TransactionId& aTransactionId, const VsyncId& aVsyncId, + const TimeStamp& aVsyncStartTime, const TimeStamp& aRefreshStartTime, + const TimeStamp& aTxnStartTime, const nsACString& aTxnURL, + const TimeStamp& aFwdTime, + nsTArray<CompositionPayload>&& aPayloads) override; + mozilla::ipc::IPCResult RecvSetFocusTarget( + const FocusTarget& aFocusTarget) override; + mozilla::ipc::IPCResult RecvParentCommands( + nsTArray<WebRenderParentCommand>&& commands) override; + mozilla::ipc::IPCResult RecvGetSnapshot(PTextureParent* aTexture, + bool* aNeedsYFlip) override; + + mozilla::ipc::IPCResult RecvSetLayersObserverEpoch( + const LayersObserverEpoch& aChildEpoch) override; + + mozilla::ipc::IPCResult RecvClearCachedResources() override; + mozilla::ipc::IPCResult RecvClearAnimationResources() override; + mozilla::ipc::IPCResult RecvInvalidateRenderedFrame() override; + mozilla::ipc::IPCResult RecvScheduleComposite( + const wr::RenderReasons& aReasons) override; + mozilla::ipc::IPCResult RecvCapture() override; + mozilla::ipc::IPCResult RecvStartCaptureSequence( + const nsACString& path, const uint32_t& aFlags) override; + mozilla::ipc::IPCResult RecvStopCaptureSequence() override; + mozilla::ipc::IPCResult RecvSyncWithCompositor() override; + + mozilla::ipc::IPCResult RecvSetConfirmedTargetAPZC( + const uint64_t& aBlockId, + nsTArray<ScrollableLayerGuid>&& aTargets) override; + + mozilla::ipc::IPCResult RecvSetTestSampleTime( + const TimeStamp& aTime) override; + mozilla::ipc::IPCResult RecvLeaveTestMode() override; + mozilla::ipc::IPCResult RecvGetAnimationValue( + const uint64_t& aCompositorAnimationsId, OMTAValue* aValue) override; + mozilla::ipc::IPCResult RecvSetAsyncScrollOffset( + const ScrollableLayerGuid::ViewID& aScrollId, const float& aX, + const float& aY) override; + mozilla::ipc::IPCResult RecvSetAsyncZoom( + const ScrollableLayerGuid::ViewID& aScrollId, + const float& aZoom) override; + mozilla::ipc::IPCResult RecvFlushApzRepaints() override; + mozilla::ipc::IPCResult RecvGetAPZTestData(APZTestData* data) override; + mozilla::ipc::IPCResult RecvGetFrameUniformity( + FrameUniformityData* aOutData) override; + + void ActorDestroy(ActorDestroyReason aWhy) override; + + mozilla::ipc::IPCResult RecvSetDefaultClearColor( + const uint32_t& aColor) override; + void SetClearColor(const gfx::DeviceColor& aColor); + + void Pause(); + bool Resume(); + + void Destroy(); + + // CompositorVsyncSchedulerOwner + bool IsPendingComposite() override { return false; } + void FinishPendingComposite() override {} + void CompositeToTarget(VsyncId aId, wr::RenderReasons aReasons, + gfx::DrawTarget* aTarget, + const gfx::IntRect* aRect = nullptr) override; + TimeDuration GetVsyncInterval() const override; + + // CompositableParentManager + bool IsSameProcess() const override; + base::ProcessId GetChildProcessId() override; + void NotifyNotUsed(PTextureParent* aTexture, + uint64_t aTransactionId) override; + void SendAsyncMessage( + const nsTArray<AsyncParentMessageData>& aMessage) override; + void SendPendingAsyncMessages() override; + void SetAboutToSendAsyncMessages() override; + + void HoldPendingTransactionId( + const wr::Epoch& aWrEpoch, TransactionId aTransactionId, + bool aContainsSVGGroup, const VsyncId& aVsyncId, + const TimeStamp& aVsyncStartTime, const TimeStamp& aRefreshStartTime, + const TimeStamp& aTxnStartTime, const nsACString& aTxnURL, + const TimeStamp& aFwdTime, const bool aIsFirstPaint, + nsTArray<CompositionPayload>&& aPayloads, + const bool aUseForTelemetry = true); + TransactionId LastPendingTransactionId(); + void FlushTransactionIdsForEpoch( + const wr::Epoch& aEpoch, const VsyncId& aCompositeStartId, + const TimeStamp& aCompositeStartTime, const TimeStamp& aRenderStartTime, + const TimeStamp& aEndTime, UiCompositorControllerParent* aUiController, + wr::RendererStats* aStats, nsTArray<FrameStats>& aOutputStats, + nsTArray<TransactionId>& aOutputTransactions); + void NotifySceneBuiltForEpoch(const wr::Epoch& aEpoch, + const TimeStamp& aEndTime); + + void RetrySkippedComposite(); + + TextureFactoryIdentifier GetTextureFactoryIdentifier(); + + void ExtractImageCompositeNotifications( + nsTArray<ImageCompositeNotificationInfo>* aNotifications); + + wr::Epoch GetCurrentEpoch() const { return mWrEpoch; } + wr::IdNamespace GetIdNamespace() { return mIdNamespace; } + + bool MatchesNamespace(const wr::ImageKey& aImageKey) const { + return aImageKey.mNamespace == mIdNamespace; + } + + bool MatchesNamespace(const wr::BlobImageKey& aBlobKey) const { + return MatchesNamespace(wr::AsImageKey(aBlobKey)); + } + + bool MatchesNamespace(const wr::FontKey& aFontKey) const { + return aFontKey.mNamespace == mIdNamespace; + } + + bool MatchesNamespace(const wr::FontInstanceKey& aFontKey) const { + return aFontKey.mNamespace == mIdNamespace; + } + + void FlushRendering(wr::RenderReasons aReasons, bool aWaitForPresent = true); + + /** + * Schedule generating WebRender frame definitely at next composite timing. + * + * WebRenderBridgeParent uses composite timing to check if there is an update + * to AsyncImagePipelines. If there is no update, WebRenderBridgeParent skips + * to generate frame. If we need to generate new frame at next composite + * timing, call this method. + * + * Call CompositorVsyncScheduler::ScheduleComposition() directly, if we just + * want to trigger AsyncImagePipelines update checks. + */ + void ScheduleGenerateFrame(wr::RenderReasons aReason); + + /** + * Invalidate rendered frame. + * + * WebRender could skip frame rendering if there is no update. + * This function is used to force invalidating even when there is no update. + */ + void InvalidateRenderedFrame(wr::RenderReasons aReasons); + + /** + * Schedule forced frame rendering at next composite timing. + * + * WebRender could skip frame rendering if there is no update. + * This function is used to force rendering even when there is no update. + */ + void ScheduleForcedGenerateFrame(wr::RenderReasons aReasons); + + void NotifyDidSceneBuild(RefPtr<const wr::WebRenderPipelineInfo> aInfo); + + wr::Epoch UpdateWebRender( + CompositorVsyncScheduler* aScheduler, RefPtr<wr::WebRenderAPI>&& aApi, + AsyncImagePipelineManager* aImageMgr, + const TextureFactoryIdentifier& aTextureFactoryIdentifier); + + void RemoveEpochDataPriorTo(const wr::Epoch& aRenderedEpoch); + + bool IsRootWebRenderBridgeParent() const; + LayersId GetLayersId() const; + + void BeginRecording(const TimeStamp& aRecordingStart); + + /** + * Write the frames collected since the call to BeginRecording to disk. + * + * If there is not currently a recorder, this is a no-op. + */ + RefPtr<wr::WebRenderAPI::WriteCollectedFramesPromise> WriteCollectedFrames(); + +#if defined(MOZ_WIDGET_ANDROID) + /** + * Request a screengrab for android + */ + void RequestScreenPixels(UiCompositorControllerParent* aController); + void MaybeCaptureScreenPixels(); +#endif + /** + * Return the frames collected since the call to BeginRecording encoded + * as data URIs. + * + * If there is not currently a recorder, this is a no-op and the promise will + * be rejected. + */ + RefPtr<wr::WebRenderAPI::GetCollectedFramesPromise> GetCollectedFrames(); + + void DisableNativeCompositor(); + void AddPendingScrollPayload(CompositionPayload& aPayload, + const VsyncId& aCompositeStartId); + + nsTArray<CompositionPayload> TakePendingScrollPayload( + const VsyncId& aCompositeStartId); + + RefPtr<WebRenderBridgeParentRef> GetWebRenderBridgeParentRef(); + + private: + class ScheduleSharedSurfaceRelease; + + WebRenderBridgeParent(const wr::PipelineId& aPipelineId, nsCString&& aError); + virtual ~WebRenderBridgeParent(); + + bool ProcessEmptyTransactionUpdates(TransactionData& aData, + bool* aScheduleComposite); + + bool ProcessDisplayListData(DisplayListData& aDisplayList, wr::Epoch aWrEpoch, + const TimeStamp& aTxnStartTime, + bool aValidTransaction, + bool aObserveLayersUpdate); + + bool SetDisplayList(const LayoutDeviceRect& aRect, ipc::ByteBuf&& aDLItems, + ipc::ByteBuf&& aDLCache, ipc::ByteBuf&& aSpatialTreeDL, + const wr::BuiltDisplayListDescriptor& aDLDesc, + const nsTArray<OpUpdateResource>& aResourceUpdates, + const nsTArray<RefCountedShmem>& aSmallShmems, + const nsTArray<ipc::Shmem>& aLargeShmems, + const TimeStamp& aTxnStartTime, + wr::TransactionBuilder& aTxn, wr::Epoch aWrEpoch, + bool aObserveLayersUpdate); + + void UpdateAPZFocusState(const FocusTarget& aFocus); + void UpdateAPZScrollData(const wr::Epoch& aEpoch, + WebRenderScrollData&& aData); + void UpdateAPZScrollOffsets(ScrollUpdatesMap&& aUpdates, + uint32_t aPaintSequenceNumber); + + bool UpdateResources(const nsTArray<OpUpdateResource>& aResourceUpdates, + const nsTArray<RefCountedShmem>& aSmallShmems, + const nsTArray<ipc::Shmem>& aLargeShmems, + wr::TransactionBuilder& aUpdates); + bool AddSharedExternalImage(wr::ExternalImageId aExtId, wr::ImageKey aKey, + wr::TransactionBuilder& aResources); + bool UpdateSharedExternalImage( + wr::ExternalImageId aExtId, wr::ImageKey aKey, + const ImageIntRect& aDirtyRect, wr::TransactionBuilder& aResources, + UniquePtr<ScheduleSharedSurfaceRelease>& aScheduleRelease); + void ObserveSharedSurfaceRelease( + const nsTArray<wr::ExternalImageKeyPair>& aPairs, + const bool& aFromCheckpoint); + + bool PushExternalImageForTexture(wr::ExternalImageId aExtId, + wr::ImageKey aKey, TextureHost* aTexture, + bool aIsUpdate, + wr::TransactionBuilder& aResources); + + void AddPipelineIdForCompositable(const wr::PipelineId& aPipelineIds, + const CompositableHandle& aHandle, + const CompositableHandleOwner& aOwner, + wr::TransactionBuilder& aTxn, + wr::TransactionBuilder& aTxnForImageBridge); + void RemovePipelineIdForCompositable(const wr::PipelineId& aPipelineId, + wr::TransactionBuilder& aTxn); + + void DeleteImage(const wr::ImageKey& aKey, wr::TransactionBuilder& aUpdates); + void ReleaseTextureOfImage(const wr::ImageKey& aKey); + + bool ProcessWebRenderParentCommands( + const nsTArray<WebRenderParentCommand>& aCommands, + wr::TransactionBuilder& aTxn); + + void ClearResources(); + void ClearAnimationResources(); + bool ShouldParentObserveEpoch(); + mozilla::ipc::IPCResult HandleShutdown(); + + void ResetPreviousSampleTime(); + + void SetOMTASampleTime(); + RefPtr<OMTASampler> GetOMTASampler() const; + + CompositorBridgeParent* GetRootCompositorBridgeParent() const; + + RefPtr<WebRenderBridgeParent> GetRootWebRenderBridgeParent() const; + + // Tell APZ what the subsequent sampling's timestamp should be. + void SetAPZSampleTime(); + + wr::Epoch GetNextWrEpoch(); + // This function is expected to be used when GetNextWrEpoch() is called, + // but TransactionBuilder does not have resource updates nor display list. + // In this case, ScheduleGenerateFrame is not triggered via SceneBuilder. + // Then we want to rollback WrEpoch. See Bug 1490117. + void RollbackWrEpoch(); + + void FlushSceneBuilds(); + void FlushFrameGeneration(wr::RenderReasons aReasons); + void FlushFramePresentation(); + + void MaybeGenerateFrame(VsyncId aId, bool aForceGenerateFrame, + wr::RenderReasons aReasons); + + VsyncId GetVsyncIdForEpoch(const wr::Epoch& aEpoch) { + for (auto& id : mPendingTransactionIds) { + if (id.mEpoch.mHandle == aEpoch.mHandle) { + return id.mVsyncId; + } + } + return VsyncId(); + } + + private: + struct PendingTransactionId { + PendingTransactionId(const wr::Epoch& aEpoch, TransactionId aId, + bool aContainsSVGGroup, const VsyncId& aVsyncId, + const TimeStamp& aVsyncStartTime, + const TimeStamp& aRefreshStartTime, + const TimeStamp& aTxnStartTime, + const nsACString& aTxnURL, const TimeStamp& aFwdTime, + const bool aIsFirstPaint, const bool aUseForTelemetry, + nsTArray<CompositionPayload>&& aPayloads) + : mEpoch(aEpoch), + mId(aId), + mVsyncId(aVsyncId), + mVsyncStartTime(aVsyncStartTime), + mRefreshStartTime(aRefreshStartTime), + mTxnStartTime(aTxnStartTime), + mTxnURL(aTxnURL), + mFwdTime(aFwdTime), + mSkippedComposites(0), + mContainsSVGGroup(aContainsSVGGroup), + mIsFirstPaint(aIsFirstPaint), + mUseForTelemetry(aUseForTelemetry), + mPayloads(std::move(aPayloads)) {} + wr::Epoch mEpoch; + TransactionId mId; + VsyncId mVsyncId; + TimeStamp mVsyncStartTime; + TimeStamp mRefreshStartTime; + TimeStamp mTxnStartTime; + nsCString mTxnURL; + TimeStamp mFwdTime; + TimeStamp mSceneBuiltTime; + uint32_t mSkippedComposites; + bool mContainsSVGGroup; + bool mIsFirstPaint; + bool mUseForTelemetry; + nsTArray<CompositionPayload> mPayloads; + }; + + CompositorBridgeParentBase* MOZ_NON_OWNING_REF mCompositorBridge; + wr::PipelineId mPipelineId; + RefPtr<widget::CompositorWidget> mWidget; + RefPtr<wr::WebRenderAPI> mApi; + RefPtr<AsyncImagePipelineManager> mAsyncImageManager; + RefPtr<CompositorVsyncScheduler> mCompositorScheduler; + // mActiveAnimations is used to avoid leaking animations when + // WebRenderBridgeParent is destroyed abnormally and Tab move between + // different windows. + std::unordered_map<uint64_t, wr::Epoch> mActiveAnimations; + std::unordered_map<uint64_t, RefPtr<WebRenderImageHost>> mAsyncCompositables; + std::unordered_map<uint64_t, CompositableTextureHostRef> mTextureHosts; + std::unordered_map<uint64_t, wr::ExternalImageId> mSharedSurfaceIds; + + TimeDuration mVsyncRate; + TimeStamp mPreviousFrameTimeStamp; + // These fields keep track of the latest layer observer epoch values in the + // child and the parent. mChildLayersObserverEpoch is the latest epoch value + // received from the child. mParentLayersObserverEpoch is the latest epoch + // value that we have told BrowserParent about (via ObserveLayerUpdate). + LayersObserverEpoch mChildLayersObserverEpoch; + LayersObserverEpoch mParentLayersObserverEpoch; + + std::deque<PendingTransactionId> mPendingTransactionIds; + std::queue<CompositorAnimationIdsForEpoch> mCompositorAnimationsToDelete; + wr::Epoch mWrEpoch; + wr::IdNamespace mIdNamespace; + CompositionOpportunityId mCompositionOpportunityId; + nsCString mInitError; + + TimeStamp mMostRecentComposite; + + RefPtr<WebRenderBridgeParentRef> mWebRenderBridgeRef; + +#if defined(MOZ_WIDGET_ANDROID) + UiCompositorControllerParent* mScreenPixelsTarget; +#endif + uint32_t mBoolParameterBits; + uint16_t mBlobTileSize; + wr::RenderReasons mSkippedCompositeReasons; + bool mDestroyed; + bool mReceivedDisplayList; + bool mIsFirstPaint; + bool mSkippedComposite; + bool mDisablingNativeCompositor; + // These payloads are being used for SCROLL_PRESENT_LATENCY telemetry + DataMutex<nsClassHashtable<nsUint64HashKey, nsTArray<CompositionPayload>>> + mPendingScrollPayloads; +}; + +// Use this class, since WebRenderBridgeParent could not supports +// ThreadSafeWeakPtr. +// This class provides a ref of WebRenderBridgeParent when +// the WebRenderBridgeParent is not destroyed. Then it works similar to +// weak pointer. +class WebRenderBridgeParentRef final { + public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebRenderBridgeParentRef) + + explicit WebRenderBridgeParentRef(WebRenderBridgeParent* aWebRenderBridge); + + RefPtr<WebRenderBridgeParent> WrBridge(); + void Clear(); + + protected: + ~WebRenderBridgeParentRef(); + + RefPtr<WebRenderBridgeParent> mWebRenderBridge; +}; + +} // namespace layers +} // namespace mozilla + +#endif // mozilla_layers_WebRenderBridgeParent_h |