OLD | NEW |
| (Empty) |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #ifndef DisplayItemList_h | |
6 #define DisplayItemList_h | |
7 | |
8 #include "platform/PlatformExport.h" | |
9 #include "platform/RuntimeEnabledFeatures.h" | |
10 #include "platform/geometry/IntRect.h" | |
11 #include "platform/geometry/LayoutPoint.h" | |
12 #include "platform/graphics/ContiguousContainer.h" | |
13 #include "platform/graphics/PaintInvalidationReason.h" | |
14 #include "platform/graphics/paint/DisplayItem.h" | |
15 #include "platform/graphics/paint/DisplayItems.h" | |
16 #include "platform/graphics/paint/PaintArtifact.h" | |
17 #include "platform/graphics/paint/PaintChunk.h" | |
18 #include "platform/graphics/paint/PaintChunker.h" | |
19 #include "platform/graphics/paint/Transform3DDisplayItem.h" | |
20 #include "wtf/Alignment.h" | |
21 #include "wtf/HashMap.h" | |
22 #include "wtf/PassOwnPtr.h" | |
23 #include "wtf/Utility.h" | |
24 #include "wtf/Vector.h" | |
25 | |
26 namespace blink { | |
27 | |
28 class GraphicsLayer; | |
29 class GraphicsContext; | |
30 | |
31 static const size_t kInitialDisplayItemsCapacity = 64; | |
32 | |
33 // Responsible for processing display items as they are produced, and producing | |
34 // a final paint artifact when complete. This class includes logic for caching, | |
35 // cache invalidation, and merging. | |
36 class PLATFORM_EXPORT DisplayItemList { | |
37 WTF_MAKE_NONCOPYABLE(DisplayItemList); | |
38 WTF_MAKE_FAST_ALLOCATED(DisplayItemList); | |
39 public: | |
40 static PassOwnPtr<DisplayItemList> create() | |
41 { | |
42 return adoptPtr(new DisplayItemList()); | |
43 } | |
44 | |
45 // These methods are called during paint invalidation (or paint if SlimmingP
aintSynchronizedPainting is on). | |
46 void invalidate(const DisplayItemClientWrapper&, PaintInvalidationReason, co
nst IntRect& previousPaintInvalidationRect, const IntRect& newPaintInvalidationR
ect); | |
47 void invalidateUntracked(DisplayItemClient); | |
48 void invalidateAll(); | |
49 | |
50 // Record when paint offsets change during paint. | |
51 void invalidatePaintOffset(const DisplayItemClientWrapper&); | |
52 #if ENABLE(ASSERT) | |
53 bool paintOffsetWasInvalidated(DisplayItemClient) const; | |
54 #endif | |
55 | |
56 // These methods are called during painting. | |
57 | |
58 // Provide a new set of paint chunk properties to apply to recorded display | |
59 // items, for Slimming Paint v2. | |
60 // TODO(pdr): This should be moved to PaintArtifact. | |
61 void updateCurrentPaintChunkProperties(const PaintChunkProperties&); | |
62 | |
63 template <typename DisplayItemClass, typename... Args> | |
64 void createAndAppend(Args&&... args) | |
65 { | |
66 static_assert(WTF::IsSubclass<DisplayItemClass, DisplayItem>::value, | |
67 "Can only createAndAppend subclasses of DisplayItem."); | |
68 static_assert(sizeof(DisplayItemClass) <= kMaximumDisplayItemSize, | |
69 "DisplayItem subclass is larger than kMaximumDisplayItemSize."); | |
70 | |
71 if (displayItemConstructionIsDisabled()) | |
72 return; | |
73 DisplayItemClass& displayItem = m_newDisplayItems.allocateAndConstruct<D
isplayItemClass>(WTF::forward<Args>(args)...); | |
74 processNewItem(displayItem); | |
75 } | |
76 | |
77 // Creates and appends an ending display item to pair with a preceding | |
78 // beginning item iff the display item actually draws content. For no-op | |
79 // items, rather than creating an ending item, the begin item will | |
80 // instead be removed, thereby maintaining brevity of the list. If display | |
81 // item construction is disabled, no list mutations will be performed. | |
82 template <typename DisplayItemClass, typename... Args> | |
83 void endItem(Args&&... args) | |
84 { | |
85 if (displayItemConstructionIsDisabled()) | |
86 return; | |
87 if (lastDisplayItemIsNoopBegin()) | |
88 removeLastDisplayItem(); | |
89 else | |
90 createAndAppend<DisplayItemClass>(WTF::forward<Args>(args)...); | |
91 } | |
92 | |
93 // Scopes must be used to avoid duplicated display item ids when we paint so
me object | |
94 // multiple times and generate multiple display items with the same type. | |
95 // We don't cache display items added in scopes. | |
96 void beginScope(); | |
97 void endScope(); | |
98 | |
99 // True if the last display item is a begin that doesn't draw content. | |
100 bool lastDisplayItemIsNoopBegin() const; | |
101 void removeLastDisplayItem(); | |
102 | |
103 void beginSkippingCache() { ++m_skippingCacheCount; } | |
104 void endSkippingCache() { ASSERT(m_skippingCacheCount > 0); --m_skippingCach
eCount; } | |
105 bool skippingCache() const { return m_skippingCacheCount; } | |
106 | |
107 // Must be called when a painting is finished. If passed, invalidations are
recorded on the given | |
108 // GraphicsLayer. | |
109 void commitNewDisplayItems(GraphicsLayer* = 0); | |
110 | |
111 // Returns the approximate memory usage, excluding memory likely to be | |
112 // shared with the embedder after copying to WebDisplayItemList. | |
113 // Should only be called right after commitNewDisplayItems. | |
114 size_t approximateUnsharedMemoryUsage() const; | |
115 | |
116 // Get the artifact generated after the last commit. | |
117 const PaintArtifact& paintArtifact() const; | |
118 const DisplayItems& displayItems() const { return paintArtifact().displayIte
ms(); } | |
119 const Vector<PaintChunk>& paintChunks() const { return paintArtifact().paint
Chunks(); } | |
120 | |
121 bool clientCacheIsValid(DisplayItemClient) const; | |
122 | |
123 bool displayItemConstructionIsDisabled() const { return m_constructionDisabl
ed; } | |
124 void setDisplayItemConstructionIsDisabled(const bool disable) { m_constructi
onDisabled = disable; } | |
125 | |
126 bool textPainted() const { return m_textPainted; } | |
127 void setTextPainted() { m_textPainted = true; } | |
128 | |
129 // Returns displayItems added using createAndAppend() since beginning or the
last | |
130 // commitNewDisplayItems(). Use with care. | |
131 DisplayItems& newDisplayItems() { return m_newDisplayItems; } | |
132 | |
133 #ifndef NDEBUG | |
134 void showDebugData() const; | |
135 #endif | |
136 | |
137 void startTrackingPaintInvalidationObjects() | |
138 { | |
139 ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); | |
140 m_trackedPaintInvalidationObjects = adoptPtr(new Vector<String>()); | |
141 } | |
142 void stopTrackingPaintInvalidationObjects() | |
143 { | |
144 ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); | |
145 m_trackedPaintInvalidationObjects = nullptr; | |
146 } | |
147 Vector<String> trackedPaintInvalidationObjects() | |
148 { | |
149 ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); | |
150 return m_trackedPaintInvalidationObjects ? *m_trackedPaintInvalidationOb
jects : Vector<String>(); | |
151 } | |
152 | |
153 bool clientHasCheckedPaintInvalidation(DisplayItemClient client) const | |
154 { | |
155 ASSERT(RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled(
)); | |
156 return m_clientsCheckedPaintInvalidation.contains(client); | |
157 } | |
158 void setClientHasCheckedPaintInvalidation(DisplayItemClient client) | |
159 { | |
160 ASSERT(RuntimeEnabledFeatures::slimmingPaintSynchronizedPaintingEnabled(
)); | |
161 m_clientsCheckedPaintInvalidation.add(client); | |
162 } | |
163 | |
164 protected: | |
165 DisplayItemList() | |
166 : m_newDisplayItems(kInitialDisplayItemsCapacity * kMaximumDisplayItemSi
ze) | |
167 , m_validlyCachedClientsDirty(false) | |
168 , m_constructionDisabled(false) | |
169 , m_textPainted(false) | |
170 , m_skippingCacheCount(0) | |
171 , m_numCachedItems(0) | |
172 , m_nextScope(1) { } | |
173 | |
174 private: | |
175 // Set new item state (scopes, cache skipping, etc) for a new item. | |
176 void processNewItem(DisplayItem&); | |
177 | |
178 void updateValidlyCachedClientsIfNeeded() const; | |
179 | |
180 void invalidateClient(const DisplayItemClientWrapper&); | |
181 | |
182 #ifndef NDEBUG | |
183 WTF::String displayItemsAsDebugString(const DisplayItems&) const; | |
184 #endif | |
185 | |
186 // Indices into PaintList of all DrawingDisplayItems and BeginSubsequenceDis
playItems of each client. | |
187 // Temporarily used during merge to find out-of-order display items. | |
188 using DisplayItemIndicesByClientMap = HashMap<DisplayItemClient, Vector<size
_t>>; | |
189 | |
190 static size_t findMatchingItemFromIndex(const DisplayItem::Id&, const Displa
yItemIndicesByClientMap&, const DisplayItems&); | |
191 static void addItemToIndexIfNeeded(const DisplayItem&, size_t index, Display
ItemIndicesByClientMap&); | |
192 | |
193 struct OutOfOrderIndexContext; | |
194 DisplayItems::iterator findOutOfOrderCachedItem(const DisplayItem::Id&, OutO
fOrderIndexContext&); | |
195 DisplayItems::iterator findOutOfOrderCachedItemForward(const DisplayItem::Id
&, OutOfOrderIndexContext&); | |
196 void copyCachedSubsequence(DisplayItems::iterator& currentIt, DisplayItems&
updatedList); | |
197 | |
198 #if ENABLE(ASSERT) | |
199 // The following two methods are for checking under-invalidations | |
200 // (when RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabl
ed). | |
201 void checkUnderInvalidation(DisplayItems::iterator& newIt, DisplayItems::ite
rator& currentIt); | |
202 void checkCachedDisplayItemIsUnchanged(const char* messagePrefix, const Disp
layItem& newItem, const DisplayItem& oldItem); | |
203 void checkNoRemainingCachedDisplayItems(); | |
204 #endif | |
205 | |
206 // The last complete paint artifact. | |
207 // In SPv2, this includes paint chunks as well as display items. | |
208 PaintArtifact m_currentPaintArtifact; | |
209 | |
210 // Data being used to build the next paint artifact. | |
211 DisplayItems m_newDisplayItems; | |
212 PaintChunker m_newPaintChunks; | |
213 | |
214 // Contains all clients having valid cached paintings if updated. | |
215 // It's lazily updated in updateValidlyCachedClientsIfNeeded(). | |
216 // TODO(wangxianzhu): In the future we can replace this with client-side rep
aint flags | |
217 // to avoid the cost of building and querying the hash table. | |
218 mutable HashSet<DisplayItemClient> m_validlyCachedClients; | |
219 mutable bool m_validlyCachedClientsDirty; | |
220 | |
221 // Used during painting. Contains clients that have checked paint invalidati
on and | |
222 // are known to be valid. | |
223 // TODO(wangxianzhu): Use client side flag to avoid const of hash table. | |
224 HashSet<DisplayItemClient> m_clientsCheckedPaintInvalidation; | |
225 | |
226 #if ENABLE(ASSERT) | |
227 // Set of clients which had paint offset changes since the last commit. This
is used for | |
228 // ensuring paint offsets are only updated once and are the same in all phas
es. | |
229 HashSet<DisplayItemClient> m_clientsWithPaintOffsetInvalidations; | |
230 #endif | |
231 | |
232 // Allow display item construction to be disabled to isolate the costs of co
nstruction | |
233 // in performance metrics. | |
234 bool m_constructionDisabled; | |
235 | |
236 // Indicates this DisplayItemList has ever had text. It is never reset to fa
lse. | |
237 bool m_textPainted; | |
238 | |
239 int m_skippingCacheCount; | |
240 | |
241 int m_numCachedItems; | |
242 | |
243 unsigned m_nextScope; | |
244 Vector<unsigned> m_scopeStack; | |
245 | |
246 struct Invalidation { | |
247 IntRect rect; | |
248 PaintInvalidationReason invalidationReason; | |
249 }; | |
250 | |
251 Vector<Invalidation> m_invalidations; | |
252 | |
253 #if ENABLE(ASSERT) | |
254 // This is used to check duplicated ids during add(). We could also check du
ring | |
255 // updatePaintList(), but checking during add() helps developer easily find
where | |
256 // the duplicated ids are from. | |
257 DisplayItemIndicesByClientMap m_newDisplayItemIndicesByClient; | |
258 #endif | |
259 | |
260 OwnPtr<Vector<String>> m_trackedPaintInvalidationObjects; | |
261 }; | |
262 | |
263 } // namespace blink | |
264 | |
265 #endif // DisplayItemList_h | |
OLD | NEW |