fune/gfx/webrender_bindings/WebRenderAPI.h
Brad Werth 26751bb55f Bug 1745492 Part 3: Expand WR YUV formats to include P010 as a MSB packing. r=lsalzman
P010 is trivially the same as NV12, but the 10-bit colors are packed into
the most significant bits instead of the least significant bits. This changes
the yuv shader to use the correct packing for P010. It treats P010 as its
own yuv format, which requires a lot of scaffolding.

Differential Revision: https://phabricator.services.mozilla.com/D140422
2022-03-05 17:31:19 +00:00

829 lines
32 KiB
C++

/* -*- 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 <stdint.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/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;
};
class TransactionBuilder final {
public:
explicit TransactionBuilder(WebRenderAPI* aApi,
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_items_data,
wr::Vec<uint8_t>& dl_cache_data,
wr::Vec<uint8_t>& 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<uint8_t>& aBytes);
void AddBlobImage(wr::BlobImageKey aKey, const ImageDescriptor& aDescriptor,
uint16_t aTileSize, 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; }
layers::WebRenderBackend GetBackendType() { return mApiBackend; }
Transaction* Raw() { return mTxn; }
protected:
bool mUseSceneBuilderThread;
layers::WebRenderBackend mApiBackend;
Transaction* mTxn;
};
class TransactionWrapper final {
public:
explicit TransactionWrapper(Transaction* aTxn);
void AppendDynamicProperties(
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 nsTArray<wr::SampledScrollOffset>& aSampledOffsets);
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();
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<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 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 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 StartCaptureSequence(const nsCString& aPath, uint32_t aFlags);
void StopCaptureSequence();
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;
bool mRendererDestroyed;
// 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) {
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<wr::FilterOp> mFilters;
nsTArray<wr::WrFilterData> 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<usize>& aStart,
const Maybe<usize>& aEnd);
void DumpSerializedDisplayList();
void Begin(layers::DisplayItemCache* aCache = nullptr);
void End(wr::BuiltDisplayList& aOutDisplayList);
void End(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 DefineImageMaskClip(const wr::ImageMask& aMask,
const nsTArray<wr::LayoutPoint>&,
wr::FillRule);
wr::WrClipId DefineRoundedRectClip(Maybe<wr::WrSpatialId> aSpace,
const wr::ComplexClipRegion& aComplex);
wr::WrClipId DefineRectClip(Maybe<wr::WrSpatialId> 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<wr::WrSpatialId> GetScrollIdForDefinedScrollLayer(
layers::ScrollableLayerGuid::ViewID aViewId) const;
wr::WrSpatialId DefineScrollLayer(
const layers::ScrollableLayerGuid::ViewID& aViewId,
const Maybe<wr::WrSpatialId>& 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,
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 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, 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 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; }
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<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;
}
// 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<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::WrSpatialId>
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;
layers::WebRenderBackend mBackend;
nsTArray<wr::PipelineId> mRemotePipelineIds;
layers::DisplayItemCache* mDisplayItemCache;
Maybe<uint16_t> 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<wr::ImageFormat> SurfaceFormatToImageFormat(gfx::SurfaceFormat aFormat);
} // namespace wr
} // namespace mozilla
#endif