/* -*- 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_WEBRENDERAPI_H #define MOZILLA_LAYERS_WEBRENDERAPI_H #include #include #include #include #include #include "mozilla/AlreadyAddRefed.h" #include "mozilla/gfx/CompositorHitTestInfo.h" #include "mozilla/layers/AsyncImagePipelineOp.h" #include "mozilla/layers/IpcResourceUpdateQueue.h" #include "mozilla/layers/RemoteTextureMap.h" #include "mozilla/layers/ScrollableLayerGuid.h" #include "mozilla/layers/SyncObject.h" #include "mozilla/layers/CompositionRecorder.h" #include "mozilla/MozPromise.h" #include "mozilla/Range.h" #include "mozilla/TimeStamp.h" #include "mozilla/UniquePtr.h" #include "mozilla/VsyncDispatcher.h" #include "mozilla/webrender/webrender_ffi.h" #include "mozilla/webrender/WebRenderTypes.h" #include "nsString.h" #include "GLTypes.h" #include "Units.h" class gfxContext; #undef None namespace mozilla { class nsDisplayItem; class nsPaintedDisplayItem; class nsDisplayTransform; class nsDisplayListBuilder; struct DisplayItemClipChain; struct ActiveScrolledRoot; namespace widget { class CompositorWidget; } namespace layers { class CompositorBridgeParent; class DisplayItemCache; class WebRenderBridgeParent; class RenderRootStateManager; class StackingContextHelper; struct DisplayListData; } // namespace layers namespace layout { class TextDrawTarget; } namespace wr { class DisplayListBuilder; class RendererOGL; class RendererEvent; class WebRenderAPI; // This isn't part of WR's API, but we define it here to simplify layout's // logic and data plumbing. struct Line { wr::LayoutRect bounds; float wavyLineThickness; wr::LineOrientation orientation; wr::ColorF color; wr::LineStyle style; }; /// A handler that can be bundled into a transaction and notified at specific /// points in the rendering pipeline, such as after scene building or after /// frame building. /// /// If for any reason the handler is dropped before reaching the requested /// point, it is notified with the value Checkpoint::TransactionDropped. /// So it is safe to assume that the handler will be notified "at some point". class NotificationHandler { public: virtual void Notify(wr::Checkpoint aCheckpoint) = 0; virtual ~NotificationHandler() = default; }; struct WrHitResult { layers::LayersId mLayersId; layers::ScrollableLayerGuid::ViewID mScrollId; gfx::CompositorHitTestInfo mHitInfo; SideBits mSideBits; Maybe mAnimationId; }; class TransactionBuilder final { public: explicit TransactionBuilder(WebRenderAPI* aApi, bool aUseSceneBuilderThread = true); TransactionBuilder(WebRenderAPI* aApi, Transaction* aTxn, bool aUseSceneBuilderThread, bool aOwnsData); ~TransactionBuilder(); void SetLowPriority(bool aIsLowPriority); void UpdateEpoch(PipelineId aPipelineId, Epoch aEpoch); void SetRootPipeline(PipelineId aPipelineId); void RemovePipeline(PipelineId aPipelineId); void SetDisplayList(Epoch aEpoch, wr::WrPipelineId pipeline_id, wr::BuiltDisplayListDescriptor dl_descriptor, wr::Vec& dl_items_data, wr::Vec& dl_cache_data, wr::Vec& dl_spatial_tree); void ClearDisplayList(Epoch aEpoch, wr::WrPipelineId aPipeline); void GenerateFrame(const VsyncId& aVsyncId, wr::RenderReasons aReasons); void InvalidateRenderedFrame(wr::RenderReasons aReasons); void SetDocumentView(const LayoutDeviceIntRect& aDocRect); bool IsEmpty() const; bool IsResourceUpdatesEmpty() const; bool IsRenderedFrameInvalidated() const; void AddImage(wr::ImageKey aKey, const ImageDescriptor& aDescriptor, wr::Vec& aBytes); void AddBlobImage(wr::BlobImageKey aKey, const ImageDescriptor& aDescriptor, uint16_t aTileSize, wr::Vec& aBytes, const wr::DeviceIntRect& aVisibleRect); void AddExternalImageBuffer(ImageKey key, const ImageDescriptor& aDescriptor, ExternalImageId aHandle); void AddExternalImage(ImageKey key, const ImageDescriptor& aDescriptor, ExternalImageId aExtID, wr::ExternalImageType aImageType, uint8_t aChannelIndex = 0); void UpdateImageBuffer(wr::ImageKey aKey, const ImageDescriptor& aDescriptor, wr::Vec& aBytes); void UpdateBlobImage(wr::BlobImageKey aKey, const ImageDescriptor& aDescriptor, wr::Vec& aBytes, const wr::DeviceIntRect& aVisibleRect, const wr::LayoutIntRect& aDirtyRect); void UpdateExternalImage(ImageKey aKey, const ImageDescriptor& aDescriptor, ExternalImageId aExtID, wr::ExternalImageType aImageType, uint8_t aChannelIndex = 0); void UpdateExternalImageWithDirtyRect(ImageKey aKey, const ImageDescriptor& aDescriptor, ExternalImageId aExtID, wr::ExternalImageType aImageType, const wr::DeviceIntRect& aDirtyRect, uint8_t aChannelIndex = 0); void SetBlobImageVisibleArea(BlobImageKey aKey, const wr::DeviceIntRect& aArea); void DeleteImage(wr::ImageKey aKey); void DeleteBlobImage(wr::BlobImageKey aKey); void AddRawFont(wr::FontKey aKey, wr::Vec& aBytes, uint32_t aIndex); void AddFontDescriptor(wr::FontKey aKey, wr::Vec& aBytes, uint32_t aIndex); void DeleteFont(wr::FontKey aKey); void AddFontInstance(wr::FontInstanceKey aKey, wr::FontKey aFontKey, float aGlyphSize, const wr::FontInstanceOptions* aOptions, const wr::FontInstancePlatformOptions* aPlatformOptions, wr::Vec& aVariations); void DeleteFontInstance(wr::FontInstanceKey aKey); void UpdateQualitySettings(bool aForceSubpixelAAWherePossible); void Notify(wr::Checkpoint aWhen, UniquePtr aHandler); void Clear(); Transaction* Take(); bool UseSceneBuilderThread() const { return mUseSceneBuilderThread; } layers::WebRenderBackend GetBackendType() { return mApiBackend; } Transaction* Raw() { return mTxn; } protected: Transaction* mTxn; bool mUseSceneBuilderThread; layers::WebRenderBackend mApiBackend; bool mOwnsData; }; class TransactionWrapper final { public: explicit TransactionWrapper(Transaction* aTxn); void AppendDynamicProperties( const nsTArray& aOpacityArray, const nsTArray& aTransformArray, const nsTArray& aColorArray); void AppendTransformProperties( const nsTArray& aTransformArray); void UpdateScrollPosition( const wr::ExternalScrollId& aScrollId, const nsTArray& aSampledOffsets); void UpdateIsTransformAsyncZooming(uint64_t aAnimationId, bool aIsZooming); void AddMinimapData(const wr::ExternalScrollId& aScrollId, const MinimapData& aMinimapData); private: Transaction* mTxn; }; class WebRenderAPI final { NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebRenderAPI); public: /// This can be called on the compositor thread only. static already_AddRefed Create( layers::CompositorBridgeParent* aBridge, RefPtr&& aWidget, const wr::WrWindowId& aWindowId, LayoutDeviceIntSize aSize, layers::WindowKind aWindowKind, nsACString& aError); already_AddRefed Clone(); void DestroyRenderer(); wr::WindowId GetId() const { return mId; } /// Do a non-blocking hit-testing query on a shared version of the hit /// testing information. std::vector HitTest(const wr::WorldPoint& aPoint); void SendTransaction(TransactionBuilder& aTxn); void SetFrameStartTime(const TimeStamp& aTime); void RunOnRenderThread(UniquePtr aEvent); void Readback(const TimeStamp& aStartTime, gfx::IntSize aSize, const gfx::SurfaceFormat& aFormat, const Range& aBuffer, bool* aNeedsYFlip); void ClearAllCaches(); void EnableNativeCompositor(bool aEnable); void SetBatchingLookback(uint32_t aCount); void SetBool(wr::BoolParameter, bool value); void SetInt(wr::IntParameter, int32_t value); void SetClearColor(const gfx::DeviceColor& aColor); void SetProfilerUI(const nsACString& aUIString); void Pause(); bool Resume(); void WakeSceneBuilder(); void FlushSceneBuilder(); void NotifyMemoryPressure(); void AccumulateMemoryReport(wr::MemoryReport*); wr::WrIdNamespace GetNamespace(); layers::WebRenderBackend GetBackendType() { return mBackend; } layers::WebRenderCompositor GetCompositorType() { return mCompositor; } uint32_t GetMaxTextureSize() const { return mMaxTextureSize; } bool GetUseANGLE() const { return mUseANGLE; } bool GetUseDComp() const { return mUseDComp; } bool GetUseTripleBuffering() const { return mUseTripleBuffering; } bool SupportsExternalBufferTextures() const { return mSupportsExternalBufferTextures; } layers::SyncHandle GetSyncHandle() const { return mSyncHandle; } void Capture(); void StartCaptureSequence(const nsACString& aPath, uint32_t aFlags); void StopCaptureSequence(); void BeginRecording(const TimeStamp& aRecordingStart, wr::PipelineId aRootPipelineId); typedef MozPromise EndRecordingPromise; RefPtr EndRecording(); layers::RemoteTextureInfoList* GetPendingRemoteTextureInfoList(); layers::AsyncImagePipelineOps* GetPendingAsyncImagePipelineOps( TransactionBuilder& aTxn); void FlushPendingWrTransactionEventsWithoutWait(); void FlushPendingWrTransactionEventsWithWait(); wr::WebRenderAPI* GetRootAPI(); protected: WebRenderAPI(wr::DocumentHandle* aHandle, wr::WindowId aId, layers::WebRenderBackend aBackend, layers::WebRenderCompositor aCompositor, uint32_t aMaxTextureSize, bool aUseANGLE, bool aUseDComp, bool aUseTripleBuffering, bool aSupportsExternalBufferTextures, layers::SyncHandle aSyncHandle, wr::WebRenderAPI* aRootApi = nullptr, wr::WebRenderAPI* aRootDocumentApi = nullptr); ~WebRenderAPI(); // Should be used only for shutdown handling void WaitFlushed(); void UpdateDebugFlags(uint32_t aFlags); bool CheckIsRemoteTextureReady(layers::RemoteTextureInfoList* aList, const TimeStamp& aTimeStamp); void WaitRemoteTextureReady(layers::RemoteTextureInfoList* aList); enum class RemoteTextureWaitType : uint8_t { AsyncWait = 0, FlushWithWait = 1, FlushWithoutWait = 2 }; void HandleWrTransactionEvents(RemoteTextureWaitType aType); class WrTransactionEvent { public: enum class Tag { Transaction, PendingRemoteTextures, PendingAsyncImagePipelineOps, }; const Tag mTag; const TimeStamp mTimeStamp; private: WrTransactionEvent(const Tag aTag, UniquePtr&& aTransaction) : mTag(aTag), mTimeStamp(TimeStamp::Now()), mTransaction(std::move(aTransaction)) { MOZ_ASSERT(mTag == Tag::Transaction); } WrTransactionEvent( const Tag aTag, UniquePtr&& aPendingRemoteTextures) : mTag(aTag), mTimeStamp(TimeStamp::Now()), mPendingRemoteTextures(std::move(aPendingRemoteTextures)) { MOZ_ASSERT(mTag == Tag::PendingRemoteTextures); } WrTransactionEvent(const Tag aTag, UniquePtr&& aPendingAsyncImagePipelineOps, UniquePtr&& aTransaction) : mTag(aTag), mTimeStamp(TimeStamp::Now()), mPendingAsyncImagePipelineOps( std::move(aPendingAsyncImagePipelineOps)), mTransaction(std::move(aTransaction)) { MOZ_ASSERT(mTag == Tag::PendingAsyncImagePipelineOps); } UniquePtr mPendingRemoteTextures; UniquePtr mPendingAsyncImagePipelineOps; UniquePtr mTransaction; public: static WrTransactionEvent Transaction(WebRenderAPI* aApi, wr::Transaction* aTxn, bool aUseSceneBuilderThread) { auto transaction = MakeUnique( aApi, aTxn, aUseSceneBuilderThread, /* aOwnsData */ true); return WrTransactionEvent(Tag::Transaction, std::move(transaction)); } static WrTransactionEvent PendingRemoteTextures( UniquePtr&& aPendingRemoteTextures) { return WrTransactionEvent(Tag::PendingRemoteTextures, std::move(aPendingRemoteTextures)); } static WrTransactionEvent PendingAsyncImagePipelineOps( UniquePtr&& aPendingAsyncImagePipelineOps, WebRenderAPI* aApi, wr::Transaction* aTxn, bool aUseSceneBuilderThread) { auto transaction = MakeUnique( aApi, aTxn, aUseSceneBuilderThread, /* aOwnsData */ false); return WrTransactionEvent(Tag::PendingAsyncImagePipelineOps, std::move(aPendingAsyncImagePipelineOps), std::move(transaction)); } wr::Transaction* RawTransaction() { if (mTag == Tag::Transaction) { return mTransaction->Raw(); } MOZ_ASSERT_UNREACHABLE("unexpected to be called"); return nullptr; } TransactionBuilder* GetTransactionBuilder() { if (mTag == Tag::PendingAsyncImagePipelineOps) { return mTransaction.get(); } MOZ_CRASH("Should not be called"); return nullptr; } bool UseSceneBuilderThread() { if (mTag == Tag::Transaction) { return mTransaction->UseSceneBuilderThread(); } MOZ_ASSERT_UNREACHABLE("unexpected to be called"); return true; } layers::RemoteTextureInfoList* RemoteTextureInfoList() { if (mTag == Tag::PendingRemoteTextures) { MOZ_ASSERT(mPendingRemoteTextures); return mPendingRemoteTextures.get(); } MOZ_ASSERT_UNREACHABLE("unexpected to be called"); return nullptr; } layers::AsyncImagePipelineOps* AsyncImagePipelineOps() { if (mTag == Tag::PendingAsyncImagePipelineOps) { MOZ_ASSERT(mPendingAsyncImagePipelineOps); return mPendingAsyncImagePipelineOps.get(); } MOZ_ASSERT_UNREACHABLE("unexpected to be called"); return nullptr; } }; wr::DocumentHandle* mDocHandle; wr::WindowId mId; layers::WebRenderBackend mBackend; layers::WebRenderCompositor mCompositor; int32_t mMaxTextureSize; bool mUseANGLE; bool mUseDComp; bool mUseTripleBuffering; bool mSupportsExternalBufferTextures; bool mCaptureSequence; layers::SyncHandle mSyncHandle; bool mRendererDestroyed; UniquePtr mPendingRemoteTextureInfoList; UniquePtr mPendingAsyncImagePipelineOps; std::queue mPendingWrTransactionEvents; // We maintain alive the root api to know when to shut the render backend // down, and the root api for the document to know when to delete the // document. mRootApi is null for the api object that owns the channel (and is // responsible for shutting it down), and mRootDocumentApi is null for the api // object owning (and responsible for destroying) a given document. All api // objects in the same window use the same channel, and some api objects write // to the same document (but there is only one owner for each channel and for // each document). const RefPtr mRootApi; const RefPtr mRootDocumentApi; friend class DisplayListBuilder; friend class layers::WebRenderBridgeParent; }; // This is a RAII class that automatically sends the transaction on // destruction. This is useful for code that has multiple exit points and we // want to ensure that the stuff accumulated in the transaction gets sent // regardless of which exit we take. Note that if the caller explicitly calls // mApi->SendTransaction() that's fine too because that empties out the // TransactionBuilder and leaves it as a valid empty transaction, so calling // SendTransaction on it again ends up being a no-op. class MOZ_RAII AutoTransactionSender { public: AutoTransactionSender(WebRenderAPI* aApi, TransactionBuilder* aTxn) : mApi(aApi), mTxn(aTxn) { MOZ_RELEASE_ASSERT(mApi); MOZ_RELEASE_ASSERT(aTxn); } ~AutoTransactionSender() { mApi->SendTransaction(*mTxn); } private: WebRenderAPI* mApi; TransactionBuilder* mTxn; }; /** * A set of optional parameters for stacking context creation. */ struct MOZ_STACK_CLASS StackingContextParams : public WrStackingContextParams { StackingContextParams() : WrStackingContextParams{ WrStackingContextClip::None(), nullptr, nullptr, nullptr, wr::TransformStyle::Flat, wr::WrReferenceFrameKind::Transform, false, false, false, nullptr, /* prim_flags = */ wr::PrimitiveFlags::IS_BACKFACE_VISIBLE, wr::MixBlendMode::Normal, wr::StackingContextFlags{0}} {} void SetPreserve3D(bool aPreserve) { transform_style = aPreserve ? wr::TransformStyle::Preserve3D : wr::TransformStyle::Flat; } // Fill this in only if this is for the root StackingContextHelper. nsIFrame* mRootReferenceFrame = nullptr; nsTArray mFilters; nsTArray mFilterDatas; wr::LayoutRect mBounds = wr::ToLayoutRect(LayoutDeviceRect()); const gfx::Matrix4x4* mBoundTransform = nullptr; const wr::WrTransformInfo* mTransformPtr = nullptr; nsDisplayTransform* mDeferredTransformItem = nullptr; // Whether the stacking context is possibly animated. This alters how // coordinates are transformed/snapped to invalidate less when transforms // change frequently. bool mAnimated = false; // Whether items should be rasterized in a local space that is (mostly) // invariant to transforms, i.e. disabling subpixel AA and screen space pixel // snapping on text runs that would only make sense in screen space. bool mRasterizeLocally = false; }; /// This is a simple C++ wrapper around WrState defined in the rust bindings. /// We may want to turn this into a direct wrapper on top of /// WebRenderFrameBuilder instead, so the interface may change a bit. class DisplayListBuilder final { public: explicit DisplayListBuilder(wr::PipelineId aId, layers::WebRenderBackend aBackend); DisplayListBuilder(DisplayListBuilder&&) = default; ~DisplayListBuilder(); void Save(); void Restore(); void ClearSave(); usize Dump(usize aIndent, const Maybe& aStart, const Maybe& aEnd); void DumpSerializedDisplayList(); void Begin(layers::DisplayItemCache* aCache = nullptr); void End(wr::BuiltDisplayList& aOutDisplayList); void End(layers::DisplayListData& aOutTransaction); Maybe PushStackingContext( const StackingContextParams& aParams, const wr::LayoutRect& aBounds, const wr::RasterSpace& aRasterSpace); void PopStackingContext(bool aIsReferenceFrame); wr::WrClipChainId DefineClipChain(const nsTArray& aClips, bool aParentWithCurrentChain = false); wr::WrClipId DefineImageMaskClip(const wr::ImageMask& aMask, const nsTArray&, wr::FillRule); wr::WrClipId DefineRoundedRectClip(Maybe aSpace, const wr::ComplexClipRegion& aComplex); wr::WrClipId DefineRectClip(Maybe aSpace, wr::LayoutRect aClipRect); wr::WrSpatialId DefineStickyFrame( const wr::LayoutRect& aContentRect, const float* aTopMargin, const float* aRightMargin, const float* aBottomMargin, const float* aLeftMargin, const StickyOffsetBounds& aVerticalBounds, const StickyOffsetBounds& aHorizontalBounds, const wr::LayoutVector2D& aAppliedOffset, wr::SpatialTreeItemKey aKey); Maybe GetScrollIdForDefinedScrollLayer( layers::ScrollableLayerGuid::ViewID aViewId) const; wr::WrSpatialId DefineScrollLayer( const layers::ScrollableLayerGuid::ViewID& aViewId, const Maybe& aParent, const wr::LayoutRect& aContentRect, const wr::LayoutRect& aClipRect, const wr::LayoutVector2D& aScrollOffset, wr::APZScrollGeneration aScrollOffsetGeneration, wr::HasScrollLinkedEffect aHasScrollLinkedEffect, wr::SpatialTreeItemKey aKey); void PushRect(const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, bool aIsBackfaceVisible, bool aForceAntiAliasing, bool aIsCheckerboard, const wr::ColorF& aColor); void PushRectWithAnimation(const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, bool aIsBackfaceVisible, const wr::ColorF& aColor, const WrAnimationProperty* aAnimation); void PushRoundedRect(const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, bool aIsBackfaceVisible, const wr::ColorF& aColor); void PushHitTest(const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, bool aIsBackfaceVisible, const layers::ScrollableLayerGuid::ViewID& aScrollId, const gfx::CompositorHitTestInfo& aHitInfo, SideBits aSideBits); void PushClearRect(const wr::LayoutRect& aBounds); void PushBackdropFilter(const wr::LayoutRect& aBounds, const wr::ComplexClipRegion& aRegion, const nsTArray& aFilters, const nsTArray& aFilterDatas, bool aIsBackfaceVisible); void PushLinearGradient(const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, bool aIsBackfaceVisible, const wr::LayoutPoint& aStartPoint, const wr::LayoutPoint& aEndPoint, const nsTArray& aStops, wr::ExtendMode aExtendMode, const wr::LayoutSize aTileSize, const wr::LayoutSize aTileSpacing); void PushRadialGradient(const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, bool aIsBackfaceVisible, const wr::LayoutPoint& aCenter, const wr::LayoutSize& aRadius, const nsTArray& aStops, wr::ExtendMode aExtendMode, const wr::LayoutSize aTileSize, const wr::LayoutSize aTileSpacing); void PushConicGradient(const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, bool aIsBackfaceVisible, const wr::LayoutPoint& aCenter, const float aAngle, const nsTArray& aStops, wr::ExtendMode aExtendMode, const wr::LayoutSize aTileSize, const wr::LayoutSize aTileSpacing); void PushImage(const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, bool aIsBackfaceVisible, bool aForceAntiAliasing, wr::ImageRendering aFilter, wr::ImageKey aImage, bool aPremultipliedAlpha = true, const wr::ColorF& aColor = wr::ColorF{1.0f, 1.0f, 1.0f, 1.0f}, bool aPreferCompositorSurface = false, bool aSupportsExternalCompositing = false); void PushRepeatingImage( const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, bool aIsBackfaceVisible, const wr::LayoutSize& aStretchSize, const wr::LayoutSize& aTileSpacing, wr::ImageRendering aFilter, wr::ImageKey aImage, bool aPremultipliedAlpha = true, const wr::ColorF& aColor = wr::ColorF{1.0f, 1.0f, 1.0f, 1.0f}); void PushYCbCrPlanarImage( const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, bool aIsBackfaceVisible, wr::ImageKey aImageChannel0, wr::ImageKey aImageChannel1, wr::ImageKey aImageChannel2, wr::WrColorDepth aColorDepth, wr::WrYuvColorSpace aColorSpace, wr::WrColorRange aColorRange, wr::ImageRendering aFilter, bool aPreferCompositorSurface = false, bool aSupportsExternalCompositing = false); void PushNV12Image(const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, bool aIsBackfaceVisible, wr::ImageKey aImageChannel0, wr::ImageKey aImageChannel1, wr::WrColorDepth aColorDepth, wr::WrYuvColorSpace aColorSpace, wr::WrColorRange aColorRange, wr::ImageRendering aFilter, bool aPreferCompositorSurface = false, bool aSupportsExternalCompositing = false); void PushP010Image(const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, bool aIsBackfaceVisible, wr::ImageKey aImageChannel0, wr::ImageKey aImageChannel1, wr::WrColorDepth aColorDepth, wr::WrYuvColorSpace aColorSpace, wr::WrColorRange aColorRange, wr::ImageRendering aFilter, bool aPreferCompositorSurface = false, bool aSupportsExternalCompositing = false); void PushYCbCrInterleavedImage( const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, bool aIsBackfaceVisible, wr::ImageKey aImageChannel0, wr::WrColorDepth aColorDepth, wr::WrYuvColorSpace aColorSpace, wr::WrColorRange aColorRange, wr::ImageRendering aFilter, bool aPreferCompositorSurface = false, bool aSupportsExternalCompositing = false); void PushIFrame(const LayoutDeviceRect& aDevPxBounds, bool aIsBackfaceVisible, wr::PipelineId aPipeline, bool aIgnoreMissingPipeline); // XXX WrBorderSides are passed with Range. // It is just to bypass compiler bug. See Bug 1357734. void PushBorder(const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, bool aIsBackfaceVisible, const wr::LayoutSideOffsets& aWidths, const Range& aSides, const wr::BorderRadius& aRadius, wr::AntialiasBorder = wr::AntialiasBorder::Yes); void PushBorderImage(const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, bool aIsBackfaceVisible, const wr::WrBorderImage& aParams); void PushBorderGradient(const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, bool aIsBackfaceVisible, const wr::LayoutSideOffsets& aWidths, const int32_t aWidth, const int32_t aHeight, bool aFill, const wr::DeviceIntSideOffsets& aSlice, const wr::LayoutPoint& aStartPoint, const wr::LayoutPoint& aEndPoint, const nsTArray& aStops, wr::ExtendMode aExtendMode); void PushBorderRadialGradient( const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, bool aIsBackfaceVisible, const wr::LayoutSideOffsets& aWidths, bool aFill, const wr::LayoutPoint& aCenter, const wr::LayoutSize& aRadius, const nsTArray& aStops, wr::ExtendMode aExtendMode); void PushBorderConicGradient( const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, bool aIsBackfaceVisible, const wr::LayoutSideOffsets& aWidths, bool aFill, const wr::LayoutPoint& aCenter, const float aAngle, const nsTArray& aStops, wr::ExtendMode aExtendMode); void PushText(const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, bool aIsBackfaceVisible, const wr::ColorF& aColor, wr::FontInstanceKey aFontKey, Range aGlyphBuffer, const wr::GlyphOptions* aGlyphOptions = nullptr); void PushLine(const wr::LayoutRect& aClip, bool aIsBackfaceVisible, const wr::Line& aLine); void PushShadow(const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, bool aIsBackfaceVisible, const wr::Shadow& aShadow, bool aShouldInflate); void PopAllShadows(); void PushBoxShadow(const wr::LayoutRect& aRect, const wr::LayoutRect& aClip, bool aIsBackfaceVisible, const wr::LayoutRect& aBoxBounds, const wr::LayoutVector2D& aOffset, const wr::ColorF& aColor, const float& aBlurRadius, const float& aSpreadRadius, const wr::BorderRadius& aBorderRadius, const wr::BoxShadowClipMode& aClipMode); /** * Notifies the DisplayListBuilder that it can group together WR display items * that are pushed until |CancelGroup()| or |FinishGroup()| call. */ void StartGroup(nsPaintedDisplayItem* aItem); /** * Cancels grouping of the display items and discards all the display items * pushed between the |StartGroup()| and |CancelGroup()| calls. */ void CancelGroup(const bool aDiscard = false); /** * Finishes the display item group. The group is stored in WebRender backend, * and can be reused with |ReuseItem()|, if the Gecko display item is reused. */ void FinishGroup(); /** * Try to reuse the previously created WebRender display items for the given * Gecko display item |aItem|. * Returns true if the items were reused, otherwise returns false. */ bool ReuseItem(nsPaintedDisplayItem* aItem); uint64_t CurrentClipChainId() const { return mCurrentSpaceAndClipChain.clip_chain; } const wr::WrSpaceAndClipChain& CurrentSpaceAndClipChain() const { return mCurrentSpaceAndClipChain; } const wr::PipelineId& CurrentPipelineId() const { return mPipelineId; } layers::WebRenderBackend GetBackendType() const { return mBackend; } // Checks to see if the innermost enclosing fixed pos item has the same // ASR. If so, it returns the scroll target for that fixed-pos item. // Otherwise, it returns Nothing(). Maybe GetContainingFixedPosScrollTarget( const ActiveScrolledRoot* aAsr); Maybe GetContainingFixedPosSideBits(const ActiveScrolledRoot* aAsr); gfxContext* GetTextContext(wr::IpcResourceUpdateQueue& aResources, const layers::StackingContextHelper& aSc, layers::RenderRootStateManager* aManager, nsDisplayItem* aItem, nsRect& aBounds, const gfx::Point& aDeviceOffset); // Try to avoid using this when possible. wr::WrState* Raw() { return mWrState; } void SetClipChainLeaf(const Maybe& aClipRect) { mClipChainLeaf = aClipRect; } // Used for opacity flattening. When we flatten away an opacity item, // we push the opacity value onto the builder. // Descendant items should pull the inherited opacity during // their CreateWebRenderCommands implementation. This can only happen if all // descendant items reported supporting this functionality, via // nsDisplayItem::CanApplyOpacity. float GetInheritedOpacity() { return mInheritedOpacity; } void SetInheritedOpacity(float aOpacity) { mInheritedOpacity = aOpacity; } const DisplayItemClipChain* GetInheritedClipChain() { return mInheritedClipChain; } void PushInheritedClipChain(nsDisplayListBuilder* aBuilder, const DisplayItemClipChain* aClipChain); void SetInheritedClipChain(const DisplayItemClipChain* aClipChain) { mInheritedClipChain = aClipChain; } layers::DisplayItemCache* GetDisplayItemCache() { return mDisplayItemCache; } // A chain of RAII objects, each holding a (ASR, ViewID, SideBits) tuple of // data. The topmost object is pointed to by the mActiveFixedPosTracker // pointer in the wr::DisplayListBuilder. class MOZ_RAII FixedPosScrollTargetTracker final { public: FixedPosScrollTargetTracker(DisplayListBuilder& aBuilder, const ActiveScrolledRoot* aAsr, layers::ScrollableLayerGuid::ViewID aScrollId, SideBits aSideBits); ~FixedPosScrollTargetTracker(); Maybe GetScrollTargetForASR( const ActiveScrolledRoot* aAsr); Maybe GetSideBitsForASR(const ActiveScrolledRoot* aAsr); private: FixedPosScrollTargetTracker* mParentTracker; DisplayListBuilder& mBuilder; const ActiveScrolledRoot* mAsr; layers::ScrollableLayerGuid::ViewID mScrollId; SideBits mSideBits; }; protected: wr::LayoutRect MergeClipLeaf(const wr::LayoutRect& aClip) { if (mClipChainLeaf) { return wr::IntersectLayoutRect(*mClipChainLeaf, aClip); } return aClip; } // See the implementation of PushShadow for details on these methods. void SuspendClipLeafMerging(); void ResumeClipLeafMerging(); wr::WrState* mWrState; // Track each scroll id that we encountered. We use this structure to // ensure that we don't define a particular scroll layer multiple times, // as that results in undefined behaviour in WR. std::unordered_map mScrollIds; wr::WrSpaceAndClipChain mCurrentSpaceAndClipChain; // Contains the current leaf of the clip chain to be merged with the // display item's clip rect when pushing an item. May be set to Nothing() if // there is no clip rect to merge with. Maybe mClipChainLeaf; // Versions of the above that are on hold while SuspendClipLeafMerging is on // (see the implementation of PushShadow for details). Maybe mSuspendedSpaceAndClipChain; Maybe mSuspendedClipChainLeaf; RefPtr mCachedTextDT; mozilla::UniquePtr mCachedContext; FixedPosScrollTargetTracker* mActiveFixedPosTracker; wr::PipelineId mPipelineId; layers::WebRenderBackend mBackend; layers::DisplayItemCache* mDisplayItemCache; Maybe mCurrentCacheSlot; float mInheritedOpacity = 1.0f; const DisplayItemClipChain* mInheritedClipChain = nullptr; friend class WebRenderAPI; friend class SpaceAndClipChainHelper; }; // This is a RAII class that overrides the current Wr's SpatialId and // ClipChainId. class MOZ_RAII SpaceAndClipChainHelper final { public: SpaceAndClipChainHelper(DisplayListBuilder& aBuilder, wr::WrSpaceAndClipChain aSpaceAndClipChain) : mBuilder(aBuilder), mOldSpaceAndClipChain(aBuilder.mCurrentSpaceAndClipChain) { aBuilder.mCurrentSpaceAndClipChain = aSpaceAndClipChain; } SpaceAndClipChainHelper(DisplayListBuilder& aBuilder, wr::WrSpatialId aSpatialId) : mBuilder(aBuilder), mOldSpaceAndClipChain(aBuilder.mCurrentSpaceAndClipChain) { aBuilder.mCurrentSpaceAndClipChain.space = aSpatialId; } SpaceAndClipChainHelper(DisplayListBuilder& aBuilder, wr::WrClipChainId aClipChainId) : mBuilder(aBuilder), mOldSpaceAndClipChain(aBuilder.mCurrentSpaceAndClipChain) { aBuilder.mCurrentSpaceAndClipChain.clip_chain = aClipChainId.id; } ~SpaceAndClipChainHelper() { mBuilder.mCurrentSpaceAndClipChain = mOldSpaceAndClipChain; } private: SpaceAndClipChainHelper(const SpaceAndClipChainHelper&) = delete; DisplayListBuilder& mBuilder; wr::WrSpaceAndClipChain mOldSpaceAndClipChain; }; Maybe SurfaceFormatToImageFormat(gfx::SurfaceFormat aFormat); } // namespace wr } // namespace mozilla #endif