/* -*- 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 #include #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/LayerManager.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" 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&& aIds) : mEpoch(aEpoch), mIds(std::move(aIds)) {} wr::Epoch mEpoch; nsTArray mIds; }; class WebRenderBridgeParent final : public PWebRenderBridgeParent, public CompositorVsyncSchedulerOwner, public CompositableParentManager, public layers::FrameRecorder { public: WebRenderBridgeParent(CompositorBridgeParentBase* aCompositorBridge, const wr::PipelineId& aPipelineId, widget::CompositorWidget* aWidget, CompositorVsyncScheduler* aScheduler, RefPtr&& aApi, RefPtr&& aImageMgr, TimeDuration aVsyncRate); static WebRenderBridgeParent* CreateDestroyed( const wr::PipelineId& aPipelineId, nsCString&& aError); wr::PipelineId PipelineId() { return mPipelineId; } already_AddRefed GetWebRenderAPI() { return do_AddRef(mApi); } AsyncImagePipelineManager* AsyncImageManager() { return mAsyncImageManager; } CompositorVsyncScheduler* CompositorScheduler() { return mCompositorScheduler.get(); } CompositorBridgeParentBase* GetCompositorBridge() { return mCompositorBridge; } void UpdateQualitySettings(); void UpdateDebugFlags(); void UpdateMultithreading(); void UpdateBatchingParameters(); 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&& aIds) override; mozilla::ipc::IPCResult RecvUpdateResources( const wr::IdNamespace& aIdNamespace, nsTArray&& aUpdates, nsTArray&& aSmallShmems, nsTArray&& aLargeShmems) override; mozilla::ipc::IPCResult RecvSetDisplayList( DisplayListData&& aDisplayList, nsTArray&& aToDestroy, const uint64_t& aFwdTransactionId, const TransactionId& aTransactionId, const bool& aContainsSVGGroup, const VsyncId& aVsyncId, const TimeStamp& aVsyncStartTime, const TimeStamp& aRefreshStartTime, const TimeStamp& aTxnStartTime, const nsCString& aTxnURL, const TimeStamp& aFwdTime, nsTArray&& aPayloads) override; mozilla::ipc::IPCResult RecvEmptyTransaction( const FocusTarget& aFocusTarget, Maybe&& aTransactionData, nsTArray&& aToDestroy, const uint64_t& aFwdTransactionId, const TransactionId& aTransactionId, const VsyncId& aVsyncId, const TimeStamp& aVsyncStartTime, const TimeStamp& aRefreshStartTime, const TimeStamp& aTxnStartTime, const nsCString& aTxnURL, const TimeStamp& aFwdTime, nsTArray&& aPayloads) override; mozilla::ipc::IPCResult RecvSetFocusTarget( const FocusTarget& aFocusTarget) override; mozilla::ipc::IPCResult RecvParentCommands( nsTArray&& 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 RecvInvalidateRenderedFrame() override; mozilla::ipc::IPCResult RecvScheduleComposite() override; mozilla::ipc::IPCResult RecvCapture() override; mozilla::ipc::IPCResult RecvToggleCaptureSequence() override; mozilla::ipc::IPCResult RecvSyncWithCompositor() override; mozilla::ipc::IPCResult RecvSetConfirmedTargetAPZC( const uint64_t& aBlockId, nsTArray&& 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; 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, 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& 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 nsCString& aTxnURL, const TimeStamp& aFwdTime, const bool aIsFirstPaint, nsTArray&& aPayloads, const bool aUseForTelemetry = true); TransactionId LastPendingTransactionId(); TransactionId FlushTransactionIdsForEpoch( const wr::Epoch& aEpoch, const VsyncId& aCompositeStartId, const TimeStamp& aCompositeStartTime, const TimeStamp& aRenderStartTime, const TimeStamp& aEndTime, UiCompositorControllerParent* aUiController, wr::RendererStats* aStats = nullptr, nsTArray* aOutputStats = nullptr); void NotifySceneBuiltForEpoch(const wr::Epoch& aEpoch, const TimeStamp& aEndTime); void CompositeIfNeeded(); TextureFactoryIdentifier GetTextureFactoryIdentifier(); void ExtractImageCompositeNotifications( nsTArray* 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(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(); /** * 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(); /** * 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(); void NotifyDidSceneBuild(RefPtr aInfo); wr::Epoch UpdateWebRender( CompositorVsyncScheduler* aScheduler, RefPtr&& 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 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 GetCollectedFrames(); void DisableNativeCompositor(); void AddPendingScrollPayload(CompositionPayload& aPayload, const VsyncId& aCompositeStartId); nsTArray TakePendingScrollPayload( const VsyncId& aCompositeStartId); RefPtr 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&& aDL, const wr::BuiltDisplayListDescriptor& aDLDesc, const nsTArray& aResourceUpdates, const nsTArray& aSmallShmems, const nsTArray& 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& aResourceUpdates, const nsTArray& aSmallShmems, const nsTArray& aLargeShmems, wr::TransactionBuilder& aUpdates); bool AddPrivateExternalImage(wr::ExternalImageId aExtId, wr::ImageKey aKey, wr::ImageDescriptor aDesc, wr::TransactionBuilder& aResources); bool UpdatePrivateExternalImage(wr::ExternalImageId aExtId, wr::ImageKey aKey, const wr::ImageDescriptor& aDesc, const ImageIntRect& aDirtyRect, wr::TransactionBuilder& aResources); 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& aScheduleRelease); void ObserveSharedSurfaceRelease( const nsTArray& aPairs); 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 bool& aAsync, 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& aCommands, wr::TransactionBuilder& aTxn); void ClearResources(); void ClearAnimationResources(); bool ShouldParentObserveEpoch(); mozilla::ipc::IPCResult HandleShutdown(); void ResetPreviousSampleTime(); void SetOMTASampleTime(); RefPtr GetOMTASampler() const; CompositorBridgeParent* GetRootCompositorBridgeParent() const; RefPtr 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(); void FlushFramePresentation(); void MaybeGenerateFrame(VsyncId aId, bool aForceGenerateFrame); 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 nsCString& aTxnURL, const TimeStamp& aFwdTime, const bool aIsFirstPaint, const bool aUseForTelemetry, nsTArray&& 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 mPayloads; }; CompositorBridgeParentBase* MOZ_NON_OWNING_REF mCompositorBridge; wr::PipelineId mPipelineId; RefPtr mWidget; RefPtr mApi; RefPtr mAsyncImageManager; RefPtr mCompositorScheduler; // mActiveAnimations is used to avoid leaking animations when // WebRenderBridgeParent is destroyed abnormally and Tab move between // different windows. std::unordered_map mActiveAnimations; std::unordered_map> mAsyncCompositables; std::unordered_map mTextureHosts; std::unordered_map 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 mPendingTransactionIds; std::queue mCompositorAnimationsToDelete; wr::Epoch mWrEpoch; wr::IdNamespace mIdNamespace; CompositionOpportunityId mCompositionOpportunityId; nsCString mInitError; TimeStamp mMostRecentComposite; RefPtr mWebRenderBridgeRef; #if defined(MOZ_WIDGET_ANDROID) UiCompositorControllerParent* mScreenPixelsTarget; #endif bool mPaused; bool mDestroyed; bool mReceivedDisplayList; bool mIsFirstPaint; bool mSkippedComposite; bool mDisablingNativeCompositor; // These payloads are being used for SCROLL_PRESENT_LATENCY telemetry DataMutex>> 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 WrBridge(); void Clear(); protected: ~WebRenderBridgeParentRef(); RefPtr mWebRenderBridge; }; } // namespace layers } // namespace mozilla #endif // mozilla_layers_WebRenderBridgeParent_h