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 GFX_WEBRENDERCOMMANDBUILDER_H
8 #define GFX_WEBRENDERCOMMANDBUILDER_H
9 
10 #include "mozilla/webrender/WebRenderAPI.h"
11 #include "mozilla/layers/ClipManager.h"
12 #include "mozilla/layers/HitTestInfoManager.h"
13 #include "mozilla/layers/WebRenderMessages.h"
14 #include "mozilla/layers/WebRenderScrollData.h"
15 #include "mozilla/layers/WebRenderUserData.h"
16 #include "mozilla/SVGIntegrationUtils.h"  // for WrFiltersHolder
17 #include "nsDisplayList.h"
18 #include "nsIFrame.h"
19 #include "nsTHashSet.h"
20 #include "DisplayItemCache.h"
21 #include "ImgDrawResult.h"
22 
23 namespace mozilla {
24 
25 namespace image {
26 class WebRenderImageProvider;
27 }
28 
29 namespace layers {
30 
31 class ImageClient;
32 class ImageContainer;
33 class WebRenderBridgeChild;
34 class WebRenderCanvasData;
35 class WebRenderCanvasRendererAsync;
36 class WebRenderImageData;
37 class WebRenderFallbackData;
38 class WebRenderParentCommand;
39 class WebRenderUserData;
40 
41 class WebRenderCommandBuilder final {
42   typedef nsTHashSet<RefPtr<WebRenderUserData>> WebRenderUserDataRefTable;
43   typedef nsTHashSet<RefPtr<WebRenderCanvasData>> CanvasDataSet;
44 
45  public:
46   explicit WebRenderCommandBuilder(WebRenderLayerManager* aManager);
47 
48   void Destroy();
49 
50   void EmptyTransaction();
51 
52   bool NeedsEmptyTransaction();
53 
54   void BuildWebRenderCommands(wr::DisplayListBuilder& aBuilder,
55                               wr::IpcResourceUpdateQueue& aResourceUpdates,
56                               nsDisplayList* aDisplayList,
57                               nsDisplayListBuilder* aDisplayListBuilder,
58                               WebRenderScrollData& aScrollData,
59                               WrFiltersHolder&& aFilters);
60 
61   void PushOverrideForASR(const ActiveScrolledRoot* aASR,
62                           const wr::WrSpatialId& aSpatialId);
63   void PopOverrideForASR(const ActiveScrolledRoot* aASR);
64 
65   Maybe<wr::ImageKey> CreateImageKey(
66       nsDisplayItem* aItem, ImageContainer* aContainer,
67       mozilla::wr::DisplayListBuilder& aBuilder,
68       mozilla::wr::IpcResourceUpdateQueue& aResources,
69       mozilla::wr::ImageRendering aRendering, const StackingContextHelper& aSc,
70       gfx::IntSize& aSize, const Maybe<LayoutDeviceRect>& aAsyncImageBounds);
71 
72   Maybe<wr::ImageKey> CreateImageProviderKey(
73       nsDisplayItem* aItem, image::WebRenderImageProvider* aProvider,
74       image::ImgDrawResult aDrawResult,
75       mozilla::wr::IpcResourceUpdateQueue& aResources);
76 
GetWebRenderUserDataTable()77   WebRenderUserDataRefTable* GetWebRenderUserDataTable() {
78     return &mWebRenderUserDatas;
79   }
80 
81   bool PushImage(nsDisplayItem* aItem, ImageContainer* aContainer,
82                  mozilla::wr::DisplayListBuilder& aBuilder,
83                  mozilla::wr::IpcResourceUpdateQueue& aResources,
84                  const StackingContextHelper& aSc,
85                  const LayoutDeviceRect& aRect, const LayoutDeviceRect& aClip);
86 
87   bool PushImageProvider(nsDisplayItem* aItem,
88                          image::WebRenderImageProvider* aProvider,
89                          image::ImgDrawResult aDrawResult,
90                          mozilla::wr::DisplayListBuilder& aBuilder,
91                          mozilla::wr::IpcResourceUpdateQueue& aResources,
92                          const LayoutDeviceRect& aRect,
93                          const LayoutDeviceRect& aClip);
94 
95   void PushInProcessImage(nsDisplayItem* aItem,
96                           const CompositableHandle& aHandle,
97                           mozilla::wr::DisplayListBuilder& aBuilder,
98                           mozilla::wr::IpcResourceUpdateQueue& aResources,
99                           const StackingContextHelper& aSc,
100                           const LayoutDeviceRect& aAsyncImageBounds);
101 
102   Maybe<wr::ImageMask> BuildWrMaskImage(
103       nsDisplayMasksAndClipPaths* aMaskItem, wr::DisplayListBuilder& aBuilder,
104       wr::IpcResourceUpdateQueue& aResources, const StackingContextHelper& aSc,
105       nsDisplayListBuilder* aDisplayListBuilder,
106       const LayoutDeviceRect& aBounds);
107 
108   bool PushItemAsImage(nsDisplayItem* aItem, wr::DisplayListBuilder& aBuilder,
109                        wr::IpcResourceUpdateQueue& aResources,
110                        const StackingContextHelper& aSc,
111                        nsDisplayListBuilder* aDisplayListBuilder);
112 
113   void CreateWebRenderCommandsFromDisplayList(
114       nsDisplayList* aDisplayList, nsDisplayItem* aWrappingItem,
115       nsDisplayListBuilder* aDisplayListBuilder,
116       const StackingContextHelper& aSc, wr::DisplayListBuilder& aBuilder,
117       wr::IpcResourceUpdateQueue& aResources, bool aNewClipList = true);
118 
119   // aWrappingItem has to be non-null.
120   void DoGroupingForDisplayList(nsDisplayList* aDisplayList,
121                                 nsDisplayItem* aWrappingItem,
122                                 nsDisplayListBuilder* aDisplayListBuilder,
123                                 const StackingContextHelper& aSc,
124                                 wr::DisplayListBuilder& aBuilder,
125                                 wr::IpcResourceUpdateQueue& aResources);
126 
127   already_AddRefed<WebRenderFallbackData> GenerateFallbackData(
128       nsDisplayItem* aItem, wr::DisplayListBuilder& aBuilder,
129       wr::IpcResourceUpdateQueue& aResources, const StackingContextHelper& aSc,
130       nsDisplayListBuilder* aDisplayListBuilder, LayoutDeviceRect& aImageRect);
131 
132   void RemoveUnusedAndResetWebRenderUserData();
133   void ClearCachedResources();
134 
135   bool ShouldDumpDisplayList(nsDisplayListBuilder* aBuilder);
GetBuilderDumpIndex()136   wr::usize GetBuilderDumpIndex() const { return mBuilderDumpIndex; }
137 
GetContainsSVGGroup()138   bool GetContainsSVGGroup() { return mContainsSVGGroup; }
139 
140   // Those are data that we kept between transactions. We used to cache some
141   // data in the layer. But in layers free mode, we don't have layer which
142   // means we need some other place to cached the data between transaction.
143   // We store the data in frame's property.
144   template <class T>
145   already_AddRefed<T> CreateOrRecycleWebRenderUserData(
146       nsDisplayItem* aItem, bool* aOutIsRecycled = nullptr) {
147     MOZ_ASSERT(aItem);
148     nsIFrame* frame = aItem->Frame();
149     if (aOutIsRecycled) {
150       *aOutIsRecycled = true;
151     }
152 
153     WebRenderUserDataTable* userDataTable =
154         frame->GetProperty(WebRenderUserDataProperty::Key());
155 
156     if (!userDataTable) {
157       userDataTable = new WebRenderUserDataTable();
158       frame->AddProperty(WebRenderUserDataProperty::Key(), userDataTable);
159     }
160 
161     RefPtr<WebRenderUserData>& data = userDataTable->LookupOrInsertWith(
162         WebRenderUserDataKey(aItem->GetPerFrameKey(), T::Type()), [&] {
163           auto data = MakeRefPtr<T>(GetRenderRootStateManager(), aItem);
164           mWebRenderUserDatas.Insert(data);
165           if (aOutIsRecycled) {
166             *aOutIsRecycled = false;
167           }
168           return data;
169         });
170 
171     MOZ_ASSERT(data);
172     MOZ_ASSERT(data->GetType() == T::Type());
173 
174     // Mark the data as being used. We will remove unused user data in the end
175     // of EndTransaction.
176     data->SetUsed(true);
177 
178     switch (T::Type()) {
179       case WebRenderUserData::UserDataType::eCanvas:
180         mLastCanvasDatas.Insert(data->AsCanvasData());
181         break;
182       default:
183         break;
184     }
185 
186     RefPtr<T> res = static_cast<T*>(data.get());
187     return res.forget();
188   }
189 
190   WebRenderLayerManager* mManager;
191 
192  private:
193   RenderRootStateManager* GetRenderRootStateManager();
194   void CreateWebRenderCommands(nsDisplayItem* aItem,
195                                mozilla::wr::DisplayListBuilder& aBuilder,
196                                mozilla::wr::IpcResourceUpdateQueue& aResources,
197                                const StackingContextHelper& aSc,
198                                nsDisplayListBuilder* aDisplayListBuilder);
199 
200   bool ComputeInvalidationForDisplayItem(nsDisplayListBuilder* aBuilder,
201                                          const nsPoint& aShift,
202                                          nsDisplayItem* aItem);
203   bool ComputeInvalidationForDisplayList(nsDisplayListBuilder* aBuilder,
204                                          const nsPoint& aShift,
205                                          nsDisplayList* aList);
206 
207   ClipManager mClipManager;
208   HitTestInfoManager mHitTestInfoManager;
209 
210   // We use this as a temporary data structure while building the mScrollData
211   // inside a layers-free transaction.
212   std::vector<WebRenderLayerScrollData> mLayerScrollData;
213   // We use this as a temporary data structure to track the current display
214   // item's ASR as we recurse in CreateWebRenderCommandsFromDisplayList. We
215   // need this so that WebRenderLayerScrollData items that deeper in the
216   // tree don't duplicate scroll metadata that their ancestors already have.
217   std::vector<const ActiveScrolledRoot*> mAsrStack;
218   const ActiveScrolledRoot* mLastAsr;
219 
220   WebRenderUserDataRefTable mWebRenderUserDatas;
221 
222   // Store of WebRenderCanvasData objects for use in empty transactions
223   CanvasDataSet mLastCanvasDatas;
224 
225   wr::usize mBuilderDumpIndex;
226   wr::usize mDumpIndent;
227 
228  public:
229   // Whether consecutive inactive display items should be grouped into one
230   // blob image.
231   bool mDoGrouping;
232 
233   // True if the most recently build display list contained an svg that
234   // we did grouping for.
235   bool mContainsSVGGroup;
236 };
237 
238 }  // namespace layers
239 }  // namespace mozilla
240 
241 #endif /* GFX_WEBRENDERCOMMANDBUILDER_H */
242