Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / third_party / WebKit / Source / platform / graphics / paint / DisplayItemList.h
blob237c0343f117040809bad534e38e006be8a8d053
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.
5 #ifndef DisplayItemList_h
6 #define DisplayItemList_h
8 #include "platform/PlatformExport.h"
9 #include "platform/RuntimeEnabledFeatures.h"
10 #include "platform/geometry/LayoutPoint.h"
11 #include "platform/graphics/ContiguousContainer.h"
12 #include "platform/graphics/paint/DisplayItem.h"
13 #include "platform/graphics/paint/Transform3DDisplayItem.h"
14 #include "wtf/Alignment.h"
15 #include "wtf/HashMap.h"
16 #include "wtf/PassOwnPtr.h"
17 #include "wtf/Utility.h"
18 #include "wtf/Vector.h"
20 namespace blink {
22 class GraphicsContext;
24 // kDisplayItemAlignment must be a multiple of alignof(derived display item) for
25 // each derived display item; the ideal value is the least common multiple.
26 // Currently the limiting factor is TransformtionMatrix (in
27 // BeginTransform3DDisplayItem), which requests 16-byte alignment.
28 static const size_t kDisplayItemAlignment = WTF_ALIGN_OF(BeginTransform3DDisplayItem);
29 static const size_t kInitialDisplayItemsCapacity = 64;
30 static const size_t kMaximumDisplayItemSize = sizeof(BeginTransform3DDisplayItem);
32 // Map from SimpleLayer.startPoint to the DrawingDisplayItems within its range
33 // which were invalidated on this frame and do not change SimpleLayers.
34 using DisplayListDiff = HashMap<DisplayItemClient, DisplayItem*>;
36 class DisplayItems : public ContiguousContainer<DisplayItem, kDisplayItemAlignment> {
37 public:
38 DisplayItems(size_t initialSizeBytes)
39 : ContiguousContainer(kMaximumDisplayItemSize, initialSizeBytes) {}
41 DisplayItem& appendByMoving(DisplayItem& item)
43 #ifndef NDEBUG
44 WTF::String originalDebugString = item.asDebugString();
45 #endif
46 ASSERT(item.isValid());
47 DisplayItem& result = ContiguousContainer::appendByMoving(item, item.derivedSize());
48 // ContiguousContainer::appendByMoving() called in-place constructor on item, which invalidated it.
49 ASSERT(!item.isValid());
50 #ifndef NDEBUG
51 // Save original debug string in the old item to help debugging.
52 item.setClientDebugString(originalDebugString);
53 #endif
54 return result;
58 class PLATFORM_EXPORT DisplayItemList {
59 WTF_MAKE_NONCOPYABLE(DisplayItemList);
60 WTF_MAKE_FAST_ALLOCATED(DisplayItemList);
61 public:
62 static PassOwnPtr<DisplayItemList> create()
64 return adoptPtr(new DisplayItemList());
67 // These methods are called during paint invalidation.
68 void invalidate(const DisplayItemClientWrapper&);
69 void invalidateUntracked(DisplayItemClient);
70 void invalidateAll();
72 // Record when paint offsets change during paint.
73 void invalidatePaintOffset(const DisplayItemClientWrapper&);
74 #if ENABLE(ASSERT)
75 bool paintOffsetWasInvalidated(DisplayItemClient) const;
76 #endif
78 // Record a new paint offset.
79 // TODO(pdr): Remove these once the paint offset cache is on LayoutObject.
80 void recordPaintOffset(DisplayItemClient, const LayoutPoint&);
81 bool paintOffsetIsUnchanged(DisplayItemClient, const LayoutPoint&) const;
83 // These methods are called during painting.
84 template <typename DisplayItemClass, typename... Args>
85 DisplayItemClass& createAndAppend(Args&&... args)
87 static_assert(WTF::IsSubclass<DisplayItemClass, DisplayItem>::value,
88 "Can only createAndAppend subclasses of DisplayItem.");
89 static_assert(sizeof(DisplayItemClass) <= kMaximumDisplayItemSize,
90 "DisplayItem subclass is larger than kMaximumDisplayItemSize.");
92 DisplayItemClass& displayItem = m_newDisplayItems.allocateAndConstruct<DisplayItemClass>(WTF::forward<Args>(args)...);
93 processNewItem(displayItem);
94 return displayItem;
97 // Scopes must be used to avoid duplicated display item ids when we paint some object
98 // multiple times and generate multiple display items with the same type.
99 // We don't cache display items added in scopes.
100 void beginScope();
101 void endScope();
103 // True if the last display item is a begin that doesn't draw content.
104 bool lastDisplayItemIsNoopBegin() const;
105 void removeLastDisplayItem();
107 void beginSkippingCache() { ++m_skippingCacheCount; }
108 void endSkippingCache() { ASSERT(m_skippingCacheCount > 0); --m_skippingCacheCount; }
109 bool skippingCache() const { return m_skippingCacheCount; }
111 // Must be called when a painting is finished. If passed, a DisplayListDiff
112 // is initialized and created.
113 void commitNewDisplayItems(DisplayListDiff* = 0);
115 // Returns the approximate memory usage, excluding memory likely to be
116 // shared with the embedder after copying to WebDisplayItemList.
117 // Should only be called right after commitNewDisplayItems.
118 size_t approximateUnsharedMemoryUsage() const;
120 // Get the paint list generated after the last painting.
121 const DisplayItems& displayItems() const;
123 bool clientCacheIsValid(DisplayItemClient) const;
125 // Commits the new display items and plays back the updated display items into the given context.
126 void commitNewDisplayItemsAndReplay(GraphicsContext& context)
128 commitNewDisplayItems();
129 replay(context);
132 void appendToWebDisplayItemList(WebDisplayItemList*);
133 void commitNewDisplayItemsAndAppendToWebDisplayItemList(WebDisplayItemList*);
135 bool displayItemConstructionIsDisabled() const { return m_constructionDisabled; }
136 void setDisplayItemConstructionIsDisabled(const bool disable) { m_constructionDisabled = disable; }
138 // Returns displayItems added using createAndAppend() since beginning or the last
139 // commitNewDisplayItems(). Use with care.
140 DisplayItems& newDisplayItems() { return m_newDisplayItems; }
142 #ifndef NDEBUG
143 void showDebugData() const;
144 #endif
146 void startTrackingPaintInvalidationObjects()
148 ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled());
149 m_trackedPaintInvalidationObjects = adoptPtr(new Vector<String>());
151 void stopTrackingPaintInvalidationObjects()
153 ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled());
154 m_trackedPaintInvalidationObjects = nullptr;
156 Vector<String> trackedPaintInvalidationObjects()
158 ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled());
159 return m_trackedPaintInvalidationObjects ? *m_trackedPaintInvalidationObjects : Vector<String>();
162 protected:
163 DisplayItemList()
164 : m_currentDisplayItems(0)
165 , m_newDisplayItems(kInitialDisplayItemsCapacity * kMaximumDisplayItemSize)
166 , m_validlyCachedClientsDirty(false)
167 , m_constructionDisabled(false)
168 , m_skippingCacheCount(0)
169 , m_numCachedItems(0)
170 , m_nextScope(1) { }
172 private:
173 // Set new item state (scopes, cache skipping, etc) for a new item.
174 void processNewItem(DisplayItem&);
176 void updateValidlyCachedClientsIfNeeded() const;
178 // Update the recorded paint offsets to remove any items that no longer have
179 // corresponding cached display items.
180 // TODO(pdr): Remove this once the paint offset cache is on LayoutObject.
181 void removeUnneededPaintOffsetEntries();
183 #ifndef NDEBUG
184 WTF::String displayItemsAsDebugString(const DisplayItems&) const;
185 #endif
187 // Indices into PaintList of all DrawingDisplayItems and BeginSubsequenceDisplayItems of each client.
188 // Temporarily used during merge to find out-of-order display items.
189 using DisplayItemIndicesByClientMap = HashMap<DisplayItemClient, Vector<size_t>>;
191 static size_t findMatchingItemFromIndex(const DisplayItem::Id&, const DisplayItemIndicesByClientMap&, const DisplayItems&);
192 static void addItemToIndexIfNeeded(const DisplayItem&, size_t index, DisplayItemIndicesByClientMap&);
194 struct OutOfOrderIndexContext;
195 DisplayItems::iterator findOutOfOrderCachedItem(const DisplayItem::Id&, OutOfOrderIndexContext&);
196 DisplayItems::iterator findOutOfOrderCachedItemForward(const DisplayItem::Id&, OutOfOrderIndexContext&);
197 void copyCachedSubsequence(DisplayItems::iterator& currentIt, DisplayItems& updatedList);
199 #if ENABLE(ASSERT)
200 // The following two methods are for checking under-invalidations
201 // (when RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled).
202 void checkUnderInvalidation(DisplayItems::iterator& newIt, DisplayItems::iterator& currentIt);
203 void checkCachedDisplayItemIsUnchanged(const char* messagePrefix, const DisplayItem& newItem, const DisplayItem& oldItem);
204 void checkNoRemainingCachedDisplayItems();
205 #endif
207 void replay(GraphicsContext&);
209 DisplayItems m_currentDisplayItems;
210 DisplayItems m_newDisplayItems;
212 // Contains all clients having valid cached paintings if updated.
213 // It's lazily updated in updateValidlyCachedClientsIfNeeded().
214 // FIXME: In the future we can replace this with client-side repaint flags
215 // to avoid the cost of building and querying the hash table.
216 mutable HashSet<DisplayItemClient> m_validlyCachedClients;
217 mutable bool m_validlyCachedClientsDirty;
219 #if ENABLE(ASSERT)
220 // Set of clients which had paint offset changes since the last commit. This is used for
221 // ensuring paint offsets are only updated once and are the same in all phases.
222 HashSet<DisplayItemClient> m_clientsWithPaintOffsetInvalidations;
223 #endif
225 // Allow display item construction to be disabled to isolate the costs of construction
226 // in performance metrics.
227 bool m_constructionDisabled;
229 int m_skippingCacheCount;
231 int m_numCachedItems;
233 unsigned m_nextScope;
234 Vector<unsigned> m_scopeStack;
236 // Cache of LayoutObject paint offsets.
237 // TODO(pdr): This should be on LayoutObject itself and is only on the display
238 // item list temporarily until paint invalidation for v2 frees up space on
239 // LayoutObject.
240 using PreviousPaintOffsets = HashMap<DisplayItemClient, LayoutPoint>;
241 PreviousPaintOffsets m_previousPaintOffsets;
243 #if ENABLE(ASSERT)
244 // This is used to check duplicated ids during add(). We could also check during
245 // updatePaintList(), but checking during add() helps developer easily find where
246 // the duplicated ids are from.
247 DisplayItemIndicesByClientMap m_newDisplayItemIndicesByClient;
248 #endif
250 OwnPtr<Vector<String>> m_trackedPaintInvalidationObjects;
253 } // namespace blink
255 #endif // DisplayItemList_h