1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef MOZILLA_LAYERS_WEBRENDERAPI_H
8 #define MOZILLA_LAYERS_WEBRENDERAPI_H
9 
10 #include <vector>
11 #include <unordered_map>
12 #include <unordered_set>
13 
14 #include "mozilla/AlreadyAddRefed.h"
15 #include "mozilla/gfx/CompositorHitTestInfo.h"
16 #include "mozilla/layers/IpcResourceUpdateQueue.h"
17 #include "mozilla/layers/ScrollableLayerGuid.h"
18 #include "mozilla/layers/SyncObject.h"
19 #include "mozilla/layers/WebRenderCompositionRecorder.h"
20 #include "mozilla/Range.h"
21 #include "mozilla/TimeStamp.h"
22 #include "mozilla/webrender/webrender_ffi.h"
23 #include "mozilla/webrender/WebRenderTypes.h"
24 #include "GLTypes.h"
25 #include "Units.h"
26 
27 class nsDisplayItem;
28 class nsPaintedDisplayItem;
29 class nsDisplayTransform;
30 
31 #undef None
32 
33 namespace mozilla {
34 
35 struct ActiveScrolledRoot;
36 
37 namespace widget {
38 class CompositorWidget;
39 }
40 
41 namespace layers {
42 class CompositorBridgeParent;
43 class DisplayItemCache;
44 class WebRenderBridgeParent;
45 class RenderRootStateManager;
46 struct DisplayListData;
47 }  // namespace layers
48 
49 namespace layout {
50 class TextDrawTarget;
51 }
52 
53 namespace wr {
54 
55 class DisplayListBuilder;
56 class RendererOGL;
57 class RendererEvent;
58 
59 // This isn't part of WR's API, but we define it here to simplify layout's
60 // logic and data plumbing.
61 struct Line {
62   wr::LayoutRect bounds;
63   float wavyLineThickness;
64   wr::LineOrientation orientation;
65   wr::ColorF color;
66   wr::LineStyle style;
67 };
68 
69 /// A handler that can be bundled into a transaction and notified at specific
70 /// points in the rendering pipeline, such as after scene building or after
71 /// frame building.
72 ///
73 /// If for any reason the handler is dropped before reaching the requested
74 /// point, it is notified with the value Checkpoint::TransactionDropped.
75 /// So it is safe to assume that the handler will be notified "at some point".
76 class NotificationHandler {
77  public:
78   virtual void Notify(wr::Checkpoint aCheckpoint) = 0;
79   virtual ~NotificationHandler() = default;
80 };
81 
82 struct WrHitResult {
83   layers::LayersId mLayersId;
84   layers::ScrollableLayerGuid::ViewID mScrollId;
85   gfx::CompositorHitTestInfo mHitInfo;
86   SideBits mSideBits;
87 };
88 
89 class TransactionBuilder final {
90  public:
91   explicit TransactionBuilder(bool aUseSceneBuilderThread = true);
92 
93   ~TransactionBuilder();
94 
95   void SetLowPriority(bool aIsLowPriority);
96 
97   void UpdateEpoch(PipelineId aPipelineId, Epoch aEpoch);
98 
99   void SetRootPipeline(PipelineId aPipelineId);
100 
101   void RemovePipeline(PipelineId aPipelineId);
102 
103   void SetDisplayList(const gfx::DeviceColor& aBgColor, Epoch aEpoch,
104                       const wr::LayoutSize& aViewportSize,
105                       wr::WrPipelineId pipeline_id,
106                       const wr::LayoutSize& content_size,
107                       wr::BuiltDisplayListDescriptor dl_descriptor,
108                       wr::Vec<uint8_t>& dl_data);
109 
110   void ClearDisplayList(Epoch aEpoch, wr::WrPipelineId aPipeline);
111 
112   void GenerateFrame();
113 
114   void InvalidateRenderedFrame();
115 
116   void UpdateDynamicProperties(
117       const nsTArray<wr::WrOpacityProperty>& aOpacityArray,
118       const nsTArray<wr::WrTransformProperty>& aTransformArray,
119       const nsTArray<wr::WrColorProperty>& aColorArray);
120 
121   void SetDocumentView(const LayoutDeviceIntRect& aDocRect);
122 
123   void UpdateScrollPosition(
124       const wr::WrPipelineId& aPipelineId,
125       const layers::ScrollableLayerGuid::ViewID& aScrollId,
126       const wr::LayoutPoint& aScrollPosition);
127 
128   bool IsEmpty() const;
129 
130   bool IsResourceUpdatesEmpty() const;
131 
132   bool IsRenderedFrameInvalidated() const;
133 
134   void AddImage(wr::ImageKey aKey, const ImageDescriptor& aDescriptor,
135                 wr::Vec<uint8_t>& aBytes);
136 
137   void AddBlobImage(wr::BlobImageKey aKey, const ImageDescriptor& aDescriptor,
138                     wr::Vec<uint8_t>& aBytes,
139                     const wr::DeviceIntRect& aVisibleRect);
140 
141   void AddExternalImageBuffer(ImageKey key, const ImageDescriptor& aDescriptor,
142                               ExternalImageId aHandle);
143 
144   void AddExternalImage(ImageKey key, const ImageDescriptor& aDescriptor,
145                         ExternalImageId aExtID,
146                         wr::ExternalImageType aImageType,
147                         uint8_t aChannelIndex = 0);
148 
149   void UpdateImageBuffer(wr::ImageKey aKey, const ImageDescriptor& aDescriptor,
150                          wr::Vec<uint8_t>& aBytes);
151 
152   void UpdateBlobImage(wr::BlobImageKey aKey,
153                        const ImageDescriptor& aDescriptor,
154                        wr::Vec<uint8_t>& aBytes,
155                        const wr::DeviceIntRect& aVisibleRect,
156                        const wr::LayoutIntRect& aDirtyRect);
157 
158   void UpdateExternalImage(ImageKey aKey, const ImageDescriptor& aDescriptor,
159                            ExternalImageId aExtID,
160                            wr::ExternalImageType aImageType,
161                            uint8_t aChannelIndex = 0);
162 
163   void UpdateExternalImageWithDirtyRect(ImageKey aKey,
164                                         const ImageDescriptor& aDescriptor,
165                                         ExternalImageId aExtID,
166                                         wr::ExternalImageType aImageType,
167                                         const wr::DeviceIntRect& aDirtyRect,
168                                         uint8_t aChannelIndex = 0);
169 
170   void SetBlobImageVisibleArea(BlobImageKey aKey,
171                                const wr::DeviceIntRect& aArea);
172 
173   void DeleteImage(wr::ImageKey aKey);
174 
175   void DeleteBlobImage(wr::BlobImageKey aKey);
176 
177   void AddRawFont(wr::FontKey aKey, wr::Vec<uint8_t>& aBytes, uint32_t aIndex);
178 
179   void AddFontDescriptor(wr::FontKey aKey, wr::Vec<uint8_t>& aBytes,
180                          uint32_t aIndex);
181 
182   void DeleteFont(wr::FontKey aKey);
183 
184   void AddFontInstance(wr::FontInstanceKey aKey, wr::FontKey aFontKey,
185                        float aGlyphSize,
186                        const wr::FontInstanceOptions* aOptions,
187                        const wr::FontInstancePlatformOptions* aPlatformOptions,
188                        wr::Vec<uint8_t>& aVariations);
189 
190   void DeleteFontInstance(wr::FontInstanceKey aKey);
191 
192   void UpdateQualitySettings(bool aForceSubpixelAAWherePossible);
193 
194   void Notify(wr::Checkpoint aWhen, UniquePtr<NotificationHandler> aHandler);
195 
196   void Clear();
197 
UseSceneBuilderThread()198   bool UseSceneBuilderThread() const { return mUseSceneBuilderThread; }
Raw()199   Transaction* Raw() { return mTxn; }
200 
201  protected:
202   bool mUseSceneBuilderThread;
203   Transaction* mTxn;
204 };
205 
206 class TransactionWrapper final {
207  public:
208   explicit TransactionWrapper(Transaction* aTxn);
209 
210   void AppendTransformProperties(
211       const nsTArray<wr::WrTransformProperty>& aTransformArray);
212   void UpdateScrollPosition(
213       const wr::WrPipelineId& aPipelineId,
214       const layers::ScrollableLayerGuid::ViewID& aScrollId,
215       const wr::LayoutPoint& aScrollPosition);
216   void UpdatePinchZoom(float aZoom);
217   void UpdateIsTransformAsyncZooming(uint64_t aAnimationId, bool aIsZooming);
218 
219  private:
220   Transaction* mTxn;
221 };
222 
223 class WebRenderAPI final {
224   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WebRenderAPI);
225 
226  public:
227   /// This can be called on the compositor thread only.
228   static already_AddRefed<WebRenderAPI> Create(
229       layers::CompositorBridgeParent* aBridge,
230       RefPtr<widget::CompositorWidget>&& aWidget,
231       const wr::WrWindowId& aWindowId, LayoutDeviceIntSize aSize);
232 
233   already_AddRefed<WebRenderAPI> Clone();
234 
GetId()235   wr::WindowId GetId() const { return mId; }
236 
237   /// Do a non-blocking hit-testing query on a shared version of the hit
238   /// testing information.
239   std::vector<WrHitResult> HitTest(const wr::WorldPoint& aPoint);
240 
241   void SendTransaction(TransactionBuilder& aTxn);
242 
243   void SetFrameStartTime(const TimeStamp& aTime);
244 
245   void RunOnRenderThread(UniquePtr<RendererEvent> aEvent);
246 
247   void Readback(const TimeStamp& aStartTime, gfx::IntSize aSize,
248                 const gfx::SurfaceFormat& aFormat,
249                 const Range<uint8_t>& aBuffer);
250 
251   void ClearAllCaches();
252   void EnableNativeCompositor(bool aEnable);
253   void EnableMultithreading(bool aEnable);
254   void SetBatchingLookback(uint32_t aCount);
255 
256   void Pause();
257   bool Resume();
258 
259   void WakeSceneBuilder();
260   void FlushSceneBuilder();
261 
262   void NotifyMemoryPressure();
263   void AccumulateMemoryReport(wr::MemoryReport*);
264 
265   wr::WrIdNamespace GetNamespace();
GetMaxTextureSize()266   uint32_t GetMaxTextureSize() const { return mMaxTextureSize; }
GetUseANGLE()267   bool GetUseANGLE() const { return mUseANGLE; }
GetUseDComp()268   bool GetUseDComp() const { return mUseDComp; }
GetUseTripleBuffering()269   bool GetUseTripleBuffering() const { return mUseTripleBuffering; }
GetSyncHandle()270   layers::SyncHandle GetSyncHandle() const { return mSyncHandle; }
271 
272   void Capture();
273 
274   void ToggleCaptureSequence();
275 
276   void SetCompositionRecorder(
277       UniquePtr<layers::WebRenderCompositionRecorder> aRecorder);
278 
279   typedef MozPromise<bool, nsresult, true> WriteCollectedFramesPromise;
280   typedef MozPromise<layers::CollectedFrames, nsresult, true>
281       GetCollectedFramesPromise;
282 
283   /**
284    * Write the frames collected by the |WebRenderCompositionRecorder| to disk.
285    *
286    * If there is not currently a recorder, this is a no-op.
287    */
288   RefPtr<WriteCollectedFramesPromise> WriteCollectedFrames();
289 
290   /**
291    * Return the frames collected by the |WebRenderCompositionRecorder| encoded
292    * as data URIs.
293    *
294    * If there is not currently a recorder, this is a no-op and the promise will
295    * be rejected.
296    */
297   RefPtr<GetCollectedFramesPromise> GetCollectedFrames();
298 
299  protected:
300   WebRenderAPI(wr::DocumentHandle* aHandle, wr::WindowId aId,
301                uint32_t aMaxTextureSize, bool aUseANGLE, bool aUseDComp,
302                bool aUseTripleBuffering, layers::SyncHandle aSyncHandle);
303 
304   ~WebRenderAPI();
305   // Should be used only for shutdown handling
306   void WaitFlushed();
307 
308   void UpdateDebugFlags(uint32_t aFlags);
309 
310   wr::DocumentHandle* mDocHandle;
311   wr::WindowId mId;
312   int32_t mMaxTextureSize;
313   bool mUseANGLE;
314   bool mUseDComp;
315   bool mUseTripleBuffering;
316   bool mCaptureSequence;
317   layers::SyncHandle mSyncHandle;
318 
319   // We maintain alive the root api to know when to shut the render backend
320   // down, and the root api for the document to know when to delete the
321   // document. mRootApi is null for the api object that owns the channel (and is
322   // responsible for shutting it down), and mRootDocumentApi is null for the api
323   // object owning (and responsible for destroying) a given document. All api
324   // objects in the same window use the same channel, and some api objects write
325   // to the same document (but there is only one owner for each channel and for
326   // each document).
327   RefPtr<wr::WebRenderAPI> mRootApi;
328   RefPtr<wr::WebRenderAPI> mRootDocumentApi;
329 
330   friend class DisplayListBuilder;
331   friend class layers::WebRenderBridgeParent;
332 };
333 
334 // This is a RAII class that automatically sends the transaction on
335 // destruction. This is useful for code that has multiple exit points and we
336 // want to ensure that the stuff accumulated in the transaction gets sent
337 // regardless of which exit we take. Note that if the caller explicitly calls
338 // mApi->SendTransaction() that's fine too because that empties out the
339 // TransactionBuilder and leaves it as a valid empty transaction, so calling
340 // SendTransaction on it again ends up being a no-op.
341 class MOZ_RAII AutoTransactionSender {
342  public:
AutoTransactionSender(WebRenderAPI * aApi,TransactionBuilder * aTxn)343   AutoTransactionSender(WebRenderAPI* aApi, TransactionBuilder* aTxn)
344       : mApi(aApi), mTxn(aTxn) {}
345 
~AutoTransactionSender()346   ~AutoTransactionSender() { mApi->SendTransaction(*mTxn); }
347 
348  private:
349   WebRenderAPI* mApi;
350   TransactionBuilder* mTxn;
351 };
352 
353 /**
354  * A set of optional parameters for stacking context creation.
355  */
356 struct MOZ_STACK_CLASS StackingContextParams : public WrStackingContextParams {
StackingContextParamsStackingContextParams357   StackingContextParams()
358       : WrStackingContextParams{
359             WrStackingContextClip::None(),
360             nullptr,
361             nullptr,
362             wr::TransformStyle::Flat,
363             wr::WrReferenceFrameKind::Transform,
364             nullptr,
365             /* prim_flags = */ wr::PrimitiveFlags::IS_BACKFACE_VISIBLE,
366             wr::MixBlendMode::Normal,
367             wr::StackingContextFlags{0}} {}
368 
SetPreserve3DStackingContextParams369   void SetPreserve3D(bool aPreserve) {
370     transform_style =
371         aPreserve ? wr::TransformStyle::Preserve3D : wr::TransformStyle::Flat;
372   }
373 
374   nsTArray<wr::FilterOp> mFilters;
375   nsTArray<wr::WrFilterData> mFilterDatas;
376   wr::LayoutRect mBounds = wr::ToLayoutRect(LayoutDeviceRect());
377   const gfx::Matrix4x4* mBoundTransform = nullptr;
378   const gfx::Matrix4x4* mTransformPtr = nullptr;
379   Maybe<nsDisplayTransform*> mDeferredTransformItem;
380   // Whether the stacking context is possibly animated. This alters how
381   // coordinates are transformed/snapped to invalidate less when transforms
382   // change frequently.
383   bool mAnimated = false;
384   // Whether items should be rasterized in a local space that is (mostly)
385   // invariant to transforms, i.e. disabling subpixel AA and screen space pixel
386   // snapping on text runs that would only make sense in screen space.
387   bool mRasterizeLocally = false;
388 };
389 
390 /// This is a simple C++ wrapper around WrState defined in the rust bindings.
391 /// We may want to turn this into a direct wrapper on top of
392 /// WebRenderFrameBuilder instead, so the interface may change a bit.
393 class DisplayListBuilder final {
394  public:
395   DisplayListBuilder(wr::PipelineId aId, const wr::LayoutSize& aContentSize,
396                      size_t aCapacity = 0,
397                      layers::DisplayItemCache* aCache = nullptr);
398   DisplayListBuilder(DisplayListBuilder&&) = default;
399 
400   ~DisplayListBuilder();
401 
402   void Save();
403   void Restore();
404   void ClearSave();
405 
406   usize Dump(usize aIndent, const Maybe<usize>& aStart,
407              const Maybe<usize>& aEnd);
408   void DumpSerializedDisplayList();
409 
410   void Finalize(wr::LayoutSize& aOutContentSizes,
411                 wr::BuiltDisplayList& aOutDisplayList);
412   void Finalize(layers::DisplayListData& aOutTransaction);
413 
414   Maybe<wr::WrSpatialId> PushStackingContext(
415       const StackingContextParams& aParams, const wr::LayoutRect& aBounds,
416       const wr::RasterSpace& aRasterSpace);
417   void PopStackingContext(bool aIsReferenceFrame);
418 
419   wr::WrClipChainId DefineClipChain(const nsTArray<wr::WrClipId>& aClips,
420                                     bool aParentWithCurrentChain = false);
421 
422   wr::WrClipId DefineClip(
423       const Maybe<wr::WrSpaceAndClip>& aParent, const wr::LayoutRect& aClipRect,
424       const nsTArray<wr::ComplexClipRegion>* aComplex = nullptr);
425 
426   wr::WrClipId DefineImageMaskClip(const wr::ImageMask& aMask);
427   wr::WrClipId DefineRoundedRectClip(const wr::ComplexClipRegion& aComplex);
428   wr::WrClipId DefineRectClip(wr::LayoutRect aClipRect);
429 
430   wr::WrSpatialId DefineStickyFrame(const wr::LayoutRect& aContentRect,
431                                     const float* aTopMargin,
432                                     const float* aRightMargin,
433                                     const float* aBottomMargin,
434                                     const float* aLeftMargin,
435                                     const StickyOffsetBounds& aVerticalBounds,
436                                     const StickyOffsetBounds& aHorizontalBounds,
437                                     const wr::LayoutVector2D& aAppliedOffset);
438 
439   Maybe<wr::WrSpaceAndClip> GetScrollIdForDefinedScrollLayer(
440       layers::ScrollableLayerGuid::ViewID aViewId) const;
441   wr::WrSpaceAndClip DefineScrollLayer(
442       const layers::ScrollableLayerGuid::ViewID& aViewId,
443       const Maybe<wr::WrSpaceAndClip>& aParent,
444       const wr::LayoutRect& aContentRect, const wr::LayoutRect& aClipRect,
445       const wr::LayoutPoint& aScrollOffset);
446 
447   void PushRect(const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
448                 bool aIsBackfaceVisible, const wr::ColorF& aColor);
449   void PushRectWithAnimation(const wr::LayoutRect& aBounds,
450                              const wr::LayoutRect& aClip,
451                              bool aIsBackfaceVisible, const wr::ColorF& aColor,
452                              const WrAnimationProperty* aAnimation);
453   void PushRoundedRect(const wr::LayoutRect& aBounds,
454                        const wr::LayoutRect& aClip, bool aIsBackfaceVisible,
455                        const wr::ColorF& aColor);
456   void PushHitTest(const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
457                    bool aIsBackfaceVisible);
458   void PushClearRect(const wr::LayoutRect& aBounds);
459   void PushClearRectWithComplexRegion(const wr::LayoutRect& aBounds,
460                                       const wr::ComplexClipRegion& aRegion);
461 
462   void PushBackdropFilter(const wr::LayoutRect& aBounds,
463                           const wr::ComplexClipRegion& aRegion,
464                           const nsTArray<wr::FilterOp>& aFilters,
465                           const nsTArray<wr::WrFilterData>& aFilterDatas,
466                           bool aIsBackfaceVisible);
467 
468   void PushLinearGradient(const wr::LayoutRect& aBounds,
469                           const wr::LayoutRect& aClip, bool aIsBackfaceVisible,
470                           const wr::LayoutPoint& aStartPoint,
471                           const wr::LayoutPoint& aEndPoint,
472                           const nsTArray<wr::GradientStop>& aStops,
473                           wr::ExtendMode aExtendMode,
474                           const wr::LayoutSize aTileSize,
475                           const wr::LayoutSize aTileSpacing);
476 
477   void PushRadialGradient(const wr::LayoutRect& aBounds,
478                           const wr::LayoutRect& aClip, bool aIsBackfaceVisible,
479                           const wr::LayoutPoint& aCenter,
480                           const wr::LayoutSize& aRadius,
481                           const nsTArray<wr::GradientStop>& aStops,
482                           wr::ExtendMode aExtendMode,
483                           const wr::LayoutSize aTileSize,
484                           const wr::LayoutSize aTileSpacing);
485 
486   void PushConicGradient(const wr::LayoutRect& aBounds,
487                          const wr::LayoutRect& aClip, bool aIsBackfaceVisible,
488                          const wr::LayoutPoint& aCenter, const float aAngle,
489                          const nsTArray<wr::GradientStop>& aStops,
490                          wr::ExtendMode aExtendMode,
491                          const wr::LayoutSize aTileSize,
492                          const wr::LayoutSize aTileSpacing);
493 
494   void PushImage(const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
495                  bool aIsBackfaceVisible, wr::ImageRendering aFilter,
496                  wr::ImageKey aImage, bool aPremultipliedAlpha = true,
497                  const wr::ColorF& aColor = wr::ColorF{1.0f, 1.0f, 1.0f, 1.0f},
498                  bool aPreferCompositorSurface = false);
499 
500   void PushRepeatingImage(
501       const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
502       bool aIsBackfaceVisible, const wr::LayoutSize& aStretchSize,
503       const wr::LayoutSize& aTileSpacing, wr::ImageRendering aFilter,
504       wr::ImageKey aImage, bool aPremultipliedAlpha = true,
505       const wr::ColorF& aColor = wr::ColorF{1.0f, 1.0f, 1.0f, 1.0f});
506 
507   void PushYCbCrPlanarImage(
508       const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
509       bool aIsBackfaceVisible, wr::ImageKey aImageChannel0,
510       wr::ImageKey aImageChannel1, wr::ImageKey aImageChannel2,
511       wr::WrColorDepth aColorDepth, wr::WrYuvColorSpace aColorSpace,
512       wr::WrColorRange aColorRange, wr::ImageRendering aFilter,
513       bool aPreferCompositorSurface = false);
514 
515   void PushNV12Image(const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
516                      bool aIsBackfaceVisible, wr::ImageKey aImageChannel0,
517                      wr::ImageKey aImageChannel1, wr::WrColorDepth aColorDepth,
518                      wr::WrYuvColorSpace aColorSpace,
519                      wr::WrColorRange aColorRange, wr::ImageRendering aFilter,
520                      bool aPreferCompositorSurface = false);
521 
522   void PushYCbCrInterleavedImage(
523       const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
524       bool aIsBackfaceVisible, wr::ImageKey aImageChannel0,
525       wr::WrColorDepth aColorDepth, wr::WrYuvColorSpace aColorSpace,
526       wr::WrColorRange aColorRange, wr::ImageRendering aFilter,
527       bool aPreferCompositorSurface = false);
528 
529   void PushIFrame(const wr::LayoutRect& aBounds, bool aIsBackfaceVisible,
530                   wr::PipelineId aPipeline, bool aIgnoreMissingPipeline);
531 
532   // XXX WrBorderSides are passed with Range.
533   // It is just to bypass compiler bug. See Bug 1357734.
534   void PushBorder(const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
535                   bool aIsBackfaceVisible, const wr::LayoutSideOffsets& aWidths,
536                   const Range<const wr::BorderSide>& aSides,
537                   const wr::BorderRadius& aRadius,
538                   wr::AntialiasBorder = wr::AntialiasBorder::Yes);
539 
540   void PushBorderImage(const wr::LayoutRect& aBounds,
541                        const wr::LayoutRect& aClip, bool aIsBackfaceVisible,
542                        const wr::WrBorderImage& aParams);
543 
544   void PushBorderGradient(const wr::LayoutRect& aBounds,
545                           const wr::LayoutRect& aClip, bool aIsBackfaceVisible,
546                           const wr::LayoutSideOffsets& aWidths,
547                           const int32_t aWidth, const int32_t aHeight,
548                           bool aFill, const wr::DeviceIntSideOffsets& aSlice,
549                           const wr::LayoutPoint& aStartPoint,
550                           const wr::LayoutPoint& aEndPoint,
551                           const nsTArray<wr::GradientStop>& aStops,
552                           wr::ExtendMode aExtendMode,
553                           const wr::LayoutSideOffsets& aOutset);
554 
555   void PushBorderRadialGradient(
556       const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
557       bool aIsBackfaceVisible, const wr::LayoutSideOffsets& aWidths, bool aFill,
558       const wr::LayoutPoint& aCenter, const wr::LayoutSize& aRadius,
559       const nsTArray<wr::GradientStop>& aStops, wr::ExtendMode aExtendMode,
560       const wr::LayoutSideOffsets& aOutset);
561 
562   void PushBorderConicGradient(
563       const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
564       bool aIsBackfaceVisible, const wr::LayoutSideOffsets& aWidths, bool aFill,
565       const wr::LayoutPoint& aCenter, const float aAngle,
566       const nsTArray<wr::GradientStop>& aStops, wr::ExtendMode aExtendMode,
567       const wr::LayoutSideOffsets& aOutset);
568 
569   void PushText(const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
570                 bool aIsBackfaceVisible, const wr::ColorF& aColor,
571                 wr::FontInstanceKey aFontKey,
572                 Range<const wr::GlyphInstance> aGlyphBuffer,
573                 const wr::GlyphOptions* aGlyphOptions = nullptr);
574 
575   void PushLine(const wr::LayoutRect& aClip, bool aIsBackfaceVisible,
576                 const wr::Line& aLine);
577 
578   void PushShadow(const wr::LayoutRect& aBounds, const wr::LayoutRect& aClip,
579                   bool aIsBackfaceVisible, const wr::Shadow& aShadow,
580                   bool aShouldInflate);
581 
582   void PopAllShadows();
583 
584   void PushBoxShadow(const wr::LayoutRect& aRect, const wr::LayoutRect& aClip,
585                      bool aIsBackfaceVisible, const wr::LayoutRect& aBoxBounds,
586                      const wr::LayoutVector2D& aOffset,
587                      const wr::ColorF& aColor, const float& aBlurRadius,
588                      const float& aSpreadRadius,
589                      const wr::BorderRadius& aBorderRadius,
590                      const wr::BoxShadowClipMode& aClipMode);
591 
592   /**
593    * Notifies the DisplayListBuilder that it can group together WR display items
594    * that are pushed until |CancelGroup()| or |FinishGroup()| call.
595    */
596   void StartGroup(nsPaintedDisplayItem* aItem);
597 
598   /**
599    * Cancels grouping of the display items and discards all the display items
600    * pushed between the |StartGroup()| and |CancelGroup()| calls.
601    */
602   void CancelGroup(const bool aDiscard = false);
603 
604   /**
605    * Finishes the display item group. The group is stored in WebRender backend,
606    * and can be reused with |ReuseItem()|, if the Gecko display item is reused.
607    */
608   void FinishGroup();
609 
610   /**
611    * Try to reuse the previously created WebRender display items for the given
612    * Gecko display item |aItem|.
613    * Returns true if the items were reused, otherwise returns false.
614    */
615   bool ReuseItem(nsPaintedDisplayItem* aItem);
616 
CurrentClipChainId()617   uint64_t CurrentClipChainId() const {
618     return mCurrentSpaceAndClipChain.clip_chain;
619   }
620 
CurrentSpaceAndClipChain()621   const wr::WrSpaceAndClipChain& CurrentSpaceAndClipChain() const {
622     return mCurrentSpaceAndClipChain;
623   }
624 
CurrentPipelineId()625   const wr::PipelineId& CurrentPipelineId() const { return mPipelineId; }
626 
627   // Checks to see if the innermost enclosing fixed pos item has the same
628   // ASR. If so, it returns the scroll target for that fixed-pos item.
629   // Otherwise, it returns Nothing().
630   Maybe<layers::ScrollableLayerGuid::ViewID> GetContainingFixedPosScrollTarget(
631       const ActiveScrolledRoot* aAsr);
632 
633   Maybe<SideBits> GetContainingFixedPosSideBits(const ActiveScrolledRoot* aAsr);
634 
635   // Set the hit-test info to be used for all display items until the next call
636   // to SetHitTestInfo or ClearHitTestInfo.
637   void SetHitTestInfo(const layers::ScrollableLayerGuid::ViewID& aScrollId,
638                       gfx::CompositorHitTestInfo aHitInfo, SideBits aSideBits);
639   // Clears the hit-test info so that subsequent display items will not have it.
640   void ClearHitTestInfo();
641 
642   already_AddRefed<gfxContext> GetTextContext(
643       wr::IpcResourceUpdateQueue& aResources,
644       const layers::StackingContextHelper& aSc,
645       layers::RenderRootStateManager* aManager, nsDisplayItem* aItem,
646       nsRect& aBounds, const gfx::Point& aDeviceOffset);
647 
648   // Try to avoid using this when possible.
Raw()649   wr::WrState* Raw() { return mWrState; }
650 
SetClipChainLeaf(const Maybe<wr::LayoutRect> & aClipRect)651   void SetClipChainLeaf(const Maybe<wr::LayoutRect>& aClipRect) {
652     mClipChainLeaf = aClipRect;
653   }
654 
655   // A chain of RAII objects, each holding a (ASR, ViewID, SideBits) tuple of
656   // data. The topmost object is pointed to by the mActiveFixedPosTracker
657   // pointer in the wr::DisplayListBuilder.
658   class MOZ_RAII FixedPosScrollTargetTracker final {
659    public:
660     FixedPosScrollTargetTracker(DisplayListBuilder& aBuilder,
661                                 const ActiveScrolledRoot* aAsr,
662                                 layers::ScrollableLayerGuid::ViewID aScrollId,
663                                 SideBits aSideBits);
664     ~FixedPosScrollTargetTracker();
665     Maybe<layers::ScrollableLayerGuid::ViewID> GetScrollTargetForASR(
666         const ActiveScrolledRoot* aAsr);
667     Maybe<SideBits> GetSideBitsForASR(const ActiveScrolledRoot* aAsr);
668 
669    private:
670     FixedPosScrollTargetTracker* mParentTracker;
671     DisplayListBuilder& mBuilder;
672     const ActiveScrolledRoot* mAsr;
673     layers::ScrollableLayerGuid::ViewID mScrollId;
674     SideBits mSideBits;
675   };
676 
677  protected:
MergeClipLeaf(const wr::LayoutRect & aClip)678   wr::LayoutRect MergeClipLeaf(const wr::LayoutRect& aClip) {
679     if (mClipChainLeaf) {
680       return wr::IntersectLayoutRect(*mClipChainLeaf, aClip);
681     }
682     return aClip;
683   }
684 
685   // See the implementation of PushShadow for details on these methods.
686   void SuspendClipLeafMerging();
687   void ResumeClipLeafMerging();
688 
689   wr::WrState* mWrState;
690 
691   // Track each scroll id that we encountered. We use this structure to
692   // ensure that we don't define a particular scroll layer multiple times,
693   // as that results in undefined behaviour in WR.
694   std::unordered_map<layers::ScrollableLayerGuid::ViewID, wr::WrSpaceAndClip>
695       mScrollIds;
696 
697   wr::WrSpaceAndClipChain mCurrentSpaceAndClipChain;
698 
699   // Contains the current leaf of the clip chain to be merged with the
700   // display item's clip rect when pushing an item. May be set to Nothing() if
701   // there is no clip rect to merge with.
702   Maybe<wr::LayoutRect> mClipChainLeaf;
703 
704   // Versions of the above that are on hold while SuspendClipLeafMerging is on
705   // (see the implementation of PushShadow for details).
706   Maybe<wr::WrSpaceAndClipChain> mSuspendedSpaceAndClipChain;
707   Maybe<wr::LayoutRect> mSuspendedClipChainLeaf;
708 
709   RefPtr<layout::TextDrawTarget> mCachedTextDT;
710   RefPtr<gfxContext> mCachedContext;
711 
712   FixedPosScrollTargetTracker* mActiveFixedPosTracker;
713 
714   wr::PipelineId mPipelineId;
715   wr::LayoutSize mContentSize;
716 
717   nsTArray<wr::PipelineId> mRemotePipelineIds;
718 
719   layers::DisplayItemCache* mDisplayItemCache;
720   Maybe<uint16_t> mCurrentCacheSlot;
721 
722   friend class WebRenderAPI;
723   friend class SpaceAndClipChainHelper;
724 };
725 
726 // This is a RAII class that overrides the current Wr's SpatialId and
727 // ClipChainId.
728 class MOZ_RAII SpaceAndClipChainHelper final {
729  public:
SpaceAndClipChainHelper(DisplayListBuilder & aBuilder,wr::WrSpaceAndClipChain aSpaceAndClipChain MOZ_GUARD_OBJECT_NOTIFIER_PARAM)730   SpaceAndClipChainHelper(DisplayListBuilder& aBuilder,
731                           wr::WrSpaceAndClipChain aSpaceAndClipChain
732                               MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
733       : mBuilder(aBuilder),
734         mOldSpaceAndClipChain(aBuilder.mCurrentSpaceAndClipChain) {
735     aBuilder.mCurrentSpaceAndClipChain = aSpaceAndClipChain;
736     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
737   }
SpaceAndClipChainHelper(DisplayListBuilder & aBuilder,wr::WrSpatialId aSpatialId MOZ_GUARD_OBJECT_NOTIFIER_PARAM)738   SpaceAndClipChainHelper(DisplayListBuilder& aBuilder,
739                           wr::WrSpatialId aSpatialId
740                               MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
741       : mBuilder(aBuilder),
742         mOldSpaceAndClipChain(aBuilder.mCurrentSpaceAndClipChain) {
743     aBuilder.mCurrentSpaceAndClipChain.space = aSpatialId;
744     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
745   }
SpaceAndClipChainHelper(DisplayListBuilder & aBuilder,wr::WrClipChainId aClipChainId MOZ_GUARD_OBJECT_NOTIFIER_PARAM)746   SpaceAndClipChainHelper(DisplayListBuilder& aBuilder,
747                           wr::WrClipChainId aClipChainId
748                               MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
749       : mBuilder(aBuilder),
750         mOldSpaceAndClipChain(aBuilder.mCurrentSpaceAndClipChain) {
751     aBuilder.mCurrentSpaceAndClipChain.clip_chain = aClipChainId.id;
752     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
753   }
754 
~SpaceAndClipChainHelper()755   ~SpaceAndClipChainHelper() {
756     mBuilder.mCurrentSpaceAndClipChain = mOldSpaceAndClipChain;
757   }
758 
759  private:
760   SpaceAndClipChainHelper(const SpaceAndClipChainHelper&) = delete;
761 
762   DisplayListBuilder& mBuilder;
763   wr::WrSpaceAndClipChain mOldSpaceAndClipChain;
764   MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
765 };
766 
767 Maybe<wr::ImageFormat> SurfaceFormatToImageFormat(gfx::SurfaceFormat aFormat);
768 
769 }  // namespace wr
770 }  // namespace mozilla
771 
772 #endif
773