diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-28 14:29:10 +0000 |
commit | 2aa4a82499d4becd2284cdb482213d541b8804dd (patch) | |
tree | b80bf8bf13c3766139fbacc530efd0dd9d54394c /gfx/webrender_bindings/WebRenderAPI.h | |
parent | Initial commit. (diff) | |
download | firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.tar.xz firefox-2aa4a82499d4becd2284cdb482213d541b8804dd.zip |
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'gfx/webrender_bindings/WebRenderAPI.h')
-rw-r--r-- | gfx/webrender_bindings/WebRenderAPI.h | 784 |
1 files changed, 784 insertions, 0 deletions
diff --git a/gfx/webrender_bindings/WebRenderAPI.h b/gfx/webrender_bindings/WebRenderAPI.h new file mode 100644 index 0000000000..9ab65b0784 --- /dev/null +++ b/gfx/webrender_bindings/WebRenderAPI.h @@ -0,0 +1,784 @@ +/* -*- 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 <vector> +#include <unordered_map> +#include <unordered_set> + +#include "mozilla/AlreadyAddRefed.h" +#include "mozilla/gfx/CompositorHitTestInfo.h" +#include "mozilla/layers/IpcResourceUpdateQueue.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/webrender/webrender_ffi.h" +#include "mozilla/webrender/WebRenderTypes.h" +#include "GLTypes.h" +#include "Units.h" + +class gfxContext; +class nsDisplayItem; +class nsPaintedDisplayItem; +class nsDisplayTransform; + +#undef None + +namespace mozilla { + +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; + +// 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; +}; + +class TransactionBuilder final { + public: + explicit TransactionBuilder(bool aUseSceneBuilderThread = true); + + ~TransactionBuilder(); + + void SetLowPriority(bool aIsLowPriority); + + void UpdateEpoch(PipelineId aPipelineId, Epoch aEpoch); + + void SetRootPipeline(PipelineId aPipelineId); + + void RemovePipeline(PipelineId aPipelineId); + + void SetDisplayList(const gfx::DeviceColor& aBgColor, Epoch aEpoch, + const wr::LayoutSize& aViewportSize, + wr::WrPipelineId pipeline_id, + wr::BuiltDisplayListDescriptor dl_descriptor, + wr::Vec<uint8_t>& dl_data); + + void ClearDisplayList(Epoch aEpoch, wr::WrPipelineId aPipeline); + + void GenerateFrame(const VsyncId& aVsyncId); + + void InvalidateRenderedFrame(); + + void UpdateDynamicProperties( + const nsTArray<wr::WrOpacityProperty>& aOpacityArray, + const nsTArray<wr::WrTransformProperty>& aTransformArray, + const nsTArray<wr::WrColorProperty>& aColorArray); + + void SetDocumentView(const LayoutDeviceIntRect& aDocRect); + + void UpdateScrollPosition( + const wr::WrPipelineId& aPipelineId, + const layers::ScrollableLayerGuid::ViewID& aScrollId, + const wr::LayoutPoint& aScrollPosition); + + bool IsEmpty() const; + + bool IsResourceUpdatesEmpty() const; + + bool IsRenderedFrameInvalidated() const; + + void AddImage(wr::ImageKey aKey, const ImageDescriptor& aDescriptor, + wr::Vec<uint8_t>& aBytes); + + void AddBlobImage(wr::BlobImageKey aKey, const ImageDescriptor& aDescriptor, + wr::Vec<uint8_t>& 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<uint8_t>& aBytes); + + void UpdateBlobImage(wr::BlobImageKey aKey, + const ImageDescriptor& aDescriptor, + wr::Vec<uint8_t>& 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<uint8_t>& aBytes, uint32_t aIndex); + + void AddFontDescriptor(wr::FontKey aKey, wr::Vec<uint8_t>& 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<uint8_t>& aVariations); + + void DeleteFontInstance(wr::FontInstanceKey aKey); + + void UpdateQualitySettings(bool aForceSubpixelAAWherePossible); + + void Notify(wr::Checkpoint aWhen, UniquePtr<NotificationHandler> aHandler); + + void Clear(); + + bool UseSceneBuilderThread() const { return mUseSceneBuilderThread; } + Transaction* Raw() { return mTxn; } + + protected: + bool mUseSceneBuilderThread; + Transaction* mTxn; +}; + +class TransactionWrapper final { + public: + explicit TransactionWrapper(Transaction* aTxn); + + void UpdateDynamicProperties( + const nsTArray<wr::WrOpacityProperty>& aOpacityArray, + const nsTArray<wr::WrTransformProperty>& aTransformArray, + const nsTArray<wr::WrColorProperty>& aColorArray); + void AppendTransformProperties( + const nsTArray<wr::WrTransformProperty>& aTransformArray); + void UpdateScrollPosition( + const wr::WrPipelineId& aPipelineId, + const layers::ScrollableLayerGuid::ViewID& aScrollId, + const wr::LayoutPoint& aScrollPosition); + void UpdatePinchZoom(float aZoom); + void UpdateIsTransformAsyncZooming(uint64_t aAnimationId, bool aIsZooming); + + 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<WebRenderAPI> Create( + layers::CompositorBridgeParent* aBridge, + RefPtr<widget::CompositorWidget>&& aWidget, + const wr::WrWindowId& aWindowId, LayoutDeviceIntSize aSize, + layers::WindowKind aWindowKind, nsACString& aError); + + already_AddRefed<WebRenderAPI> Clone(); + + wr::WindowId GetId() const { return mId; } + + /// Do a non-blocking hit-testing query on a shared version of the hit + /// testing information. + std::vector<WrHitResult> HitTest(const wr::WorldPoint& aPoint); + + void SendTransaction(TransactionBuilder& aTxn); + + void SetFrameStartTime(const TimeStamp& aTime); + + void RunOnRenderThread(UniquePtr<RendererEvent> aEvent); + + void Readback(const TimeStamp& aStartTime, gfx::IntSize aSize, + const gfx::SurfaceFormat& aFormat, + const Range<uint8_t>& aBuffer, bool* aNeedsYFlip); + + void ClearAllCaches(); + void EnableNativeCompositor(bool aEnable); + void EnableMultithreading(bool aEnable); + void SetBatchingLookback(uint32_t aCount); + + void SetClearColor(const gfx::DeviceColor& aColor); + void SetProfilerUI(const nsCString& 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 ToggleCaptureSequence(); + + void BeginRecording(const TimeStamp& aRecordingStart, + wr::PipelineId aRootPipelineId); + + typedef MozPromise<bool, nsresult, true> WriteCollectedFramesPromise; + typedef MozPromise<layers::CollectedFrames, nsresult, true> + GetCollectedFramesPromise; + + /** + * Write the frames collected since the call to BeginRecording() to disk. + * + * If there is not currently a recorder, this is a no-op. + */ + RefPtr<WriteCollectedFramesPromise> WriteCollectedFrames(); + + /** + * 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<GetCollectedFramesPromise> GetCollectedFrames(); + + 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); + + ~WebRenderAPI(); + // Should be used only for shutdown handling + void WaitFlushed(); + + void UpdateDebugFlags(uint32_t aFlags); + + 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; + + // 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). + RefPtr<wr::WebRenderAPI> mRootApi; + RefPtr<wr::WebRenderAPI> 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) {} + + ~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, + 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; + } + + nsTArray<wr::FilterOp> mFilters; + nsTArray<wr::WrFilterData> mFilterDatas; + wr::LayoutRect mBounds = wr::ToLayoutRect(LayoutDeviceRect()); + const gfx::Matrix4x4* mBoundTransform = nullptr; + const gfx::Matrix4x4* mTransformPtr = nullptr; + Maybe<nsDisplayTransform*> mDeferredTransformItem; + // 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, size_t aCapacity = 0, + layers::DisplayItemCache* aCache = nullptr); + DisplayListBuilder(DisplayListBuilder&&) = default; + + ~DisplayListBuilder(); + + void Save(); + void Restore(); + void ClearSave(); + + usize Dump(usize aIndent, const Maybe<usize>& aStart, + const Maybe<usize>& aEnd); + void DumpSerializedDisplayList(); + + void Finalize(wr::BuiltDisplayList& aOutDisplayList); + void Finalize(layers::DisplayListData& aOutTransaction); + + Maybe<wr::WrSpatialId> PushStackingContext( + const StackingContextParams& aParams, const wr::LayoutRect& aBounds, + const wr::RasterSpace& aRasterSpace); + void PopStackingContext(bool aIsReferenceFrame); + + wr::WrClipChainId DefineClipChain(const nsTArray<wr::WrClipId>& aClips, + bool aParentWithCurrentChain = false); + + wr::WrClipId DefineClip( + const Maybe<wr::WrSpaceAndClip>& aParent, const wr::LayoutRect& aClipRect, + const nsTArray<wr::ComplexClipRegion>* aComplex = nullptr); + + wr::WrClipId DefineImageMaskClip(const wr::ImageMask& aMask); + wr::WrClipId DefineRoundedRectClip(const wr::ComplexClipRegion& aComplex); + wr::WrClipId DefineRectClip(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); + + Maybe<wr::WrSpaceAndClip> GetScrollIdForDefinedScrollLayer( + layers::ScrollableLayerGuid::ViewID aViewId) const; + wr::WrSpaceAndClip DefineScrollLayer( + const layers::ScrollableLayerGuid::ViewID& aViewId, + const Maybe<wr::WrSpaceAndClip>& aParent, + const wr::LayoutRect& aContentRect, const wr::LayoutRect& aClipRect, + const wr::LayoutPoint& aScrollOffset); + + void PushRect(const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, + bool aIsBackfaceVisible, 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, + gfx::CompositorHitTestInfo aHitInfo, SideBits aSideBits); + void PushClearRect(const wr::LayoutRect& aBounds); + void PushClearRectWithComplexRegion(const wr::LayoutRect& aBounds, + const wr::ComplexClipRegion& aRegion); + + void PushBackdropFilter(const wr::LayoutRect& aBounds, + const wr::ComplexClipRegion& aRegion, + const nsTArray<wr::FilterOp>& aFilters, + const nsTArray<wr::WrFilterData>& 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<wr::GradientStop>& 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<wr::GradientStop>& 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<wr::GradientStop>& aStops, + wr::ExtendMode aExtendMode, + const wr::LayoutSize aTileSize, + const wr::LayoutSize aTileSpacing); + + void PushImage(const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, + bool aIsBackfaceVisible, 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 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 wr::LayoutRect& aBounds, 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<const wr::BorderSide>& 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<wr::GradientStop>& aStops, + wr::ExtendMode aExtendMode, + const wr::LayoutSideOffsets& aOutset); + + 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<wr::GradientStop>& aStops, wr::ExtendMode aExtendMode, + const wr::LayoutSideOffsets& aOutset); + + 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<wr::GradientStop>& aStops, wr::ExtendMode aExtendMode, + const wr::LayoutSideOffsets& aOutset); + + void PushText(const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip, + bool aIsBackfaceVisible, const wr::ColorF& aColor, + wr::FontInstanceKey aFontKey, + Range<const wr::GlyphInstance> 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; } + + // 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<layers::ScrollableLayerGuid::ViewID> GetContainingFixedPosScrollTarget( + const ActiveScrolledRoot* aAsr); + + Maybe<SideBits> GetContainingFixedPosSideBits(const ActiveScrolledRoot* aAsr); + + already_AddRefed<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<wr::LayoutRect>& aClipRect) { + mClipChainLeaf = aClipRect; + } + + // 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<layers::ScrollableLayerGuid::ViewID> GetScrollTargetForASR( + const ActiveScrolledRoot* aAsr); + Maybe<SideBits> 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<layers::ScrollableLayerGuid::ViewID, wr::WrSpaceAndClip> + 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<wr::LayoutRect> mClipChainLeaf; + + // Versions of the above that are on hold while SuspendClipLeafMerging is on + // (see the implementation of PushShadow for details). + Maybe<wr::WrSpaceAndClipChain> mSuspendedSpaceAndClipChain; + Maybe<wr::LayoutRect> mSuspendedClipChainLeaf; + + RefPtr<layout::TextDrawTarget> mCachedTextDT; + RefPtr<gfxContext> mCachedContext; + + FixedPosScrollTargetTracker* mActiveFixedPosTracker; + + wr::PipelineId mPipelineId; + wr::LayoutSize mContentSize; + + nsTArray<wr::PipelineId> mRemotePipelineIds; + + layers::DisplayItemCache* mDisplayItemCache; + Maybe<uint16_t> mCurrentCacheSlot; + + 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<wr::ImageFormat> SurfaceFormatToImageFormat(gfx::SurfaceFormat aFormat); + +} // namespace wr +} // namespace mozilla + +#endif |