Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(15)

Side by Side Diff: Source/platform/graphics/paint/DisplayItemList.cpp

Issue 1193433004: Blink-side contiguous allocation of display items. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Add ListContainer::AllocateAndConstructWithArguments and a TODO in DisplayItemList::findMatchingIte… Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "config.h" 5 #include "config.h"
6 #include "platform/graphics/paint/DisplayItemList.h" 6 #include "platform/graphics/paint/DisplayItemList.h"
7 7
8 #include "platform/NotImplemented.h" 8 #include "platform/NotImplemented.h"
9 #include "platform/RuntimeEnabledFeatures.h" 9 #include "platform/RuntimeEnabledFeatures.h"
10 #include "platform/TraceEvent.h" 10 #include "platform/TraceEvent.h"
(...skipping 10 matching lines...) Expand all
21 #include "platform/graphics/LoggingCanvas.h" 21 #include "platform/graphics/LoggingCanvas.h"
22 #include "wtf/text/StringBuilder.h" 22 #include "wtf/text/StringBuilder.h"
23 #include <stdio.h> 23 #include <stdio.h>
24 #endif 24 #endif
25 25
26 namespace blink { 26 namespace blink {
27 27
28 const DisplayItems& DisplayItemList::displayItems() const 28 const DisplayItems& DisplayItemList::displayItems() const
29 { 29 {
30 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled()); 30 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled());
31 ASSERT(m_newDisplayItems.isEmpty()); 31 ASSERT(m_newDisplayItems.empty());
32 return m_currentDisplayItems; 32 return m_currentDisplayItems;
33 } 33 }
34 34
35 bool DisplayItemList::lastDisplayItemIsNoopBegin() const 35 bool DisplayItemList::lastDisplayItemIsNoopBegin() const
36 { 36 {
37 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled()); 37 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled());
38 if (m_newDisplayItems.isEmpty()) 38 if (m_newDisplayItems.empty())
39 return false; 39 return false;
40 40
41 const auto& lastDisplayItem = m_newDisplayItems.last(); 41 const auto& lastDisplayItem = *m_newDisplayItems.back();
42 return lastDisplayItem.isBegin() && !lastDisplayItem.drawsContent(); 42 return lastDisplayItem.isBegin() && !lastDisplayItem.drawsContent();
43 } 43 }
44 44
45 void DisplayItemList::removeLastDisplayItem() 45 void DisplayItemList::removeLastDisplayItem()
46 { 46 {
47 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled()); 47 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled());
48 if (m_newDisplayItems.isEmpty()) 48 if (m_newDisplayItems.empty())
49 return; 49 return;
50 50
51 #if ENABLE(ASSERT) 51 #if ENABLE(ASSERT)
52 // Also remove the index pointing to the removed display item. 52 // Also remove the index pointing to the removed display item.
53 DisplayItemIndicesByClientMap::iterator it = m_newDisplayItemIndicesByClient .find(m_newDisplayItems.last().client()); 53 DisplayItemIndicesByClientMap::iterator it = m_newDisplayItemIndicesByClient .find(m_newDisplayItems.back()->client());
54 if (it != m_newDisplayItemIndicesByClient.end()) { 54 if (it != m_newDisplayItemIndicesByClient.end()) {
55 Vector<size_t>& indices = it->value; 55 Vector<size_t>& indices = it->value;
56 if (!indices.isEmpty() && indices.last() == (m_newDisplayItems.size() - 1)) 56 if (!indices.isEmpty() && indices.last() == (m_newDisplayItems.size() - 1))
57 indices.removeLast(); 57 indices.removeLast();
58 } 58 }
59 #endif 59 #endif
60 m_newDisplayItems.removeLast(); 60 m_newDisplayItems.removeLast();
61 } 61 }
62 62
63 void DisplayItemList::add(WTF::PassOwnPtr<DisplayItem> displayItem) 63 void DisplayItemList::processNewItem(DisplayItem* displayItem)
64 { 64 {
65 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled()); 65 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled());
66 ASSERT(!m_constructionDisabled); 66 ASSERT(!m_constructionDisabled);
67 ASSERT(!skippingCache() || !displayItem->isCached()); 67 ASSERT(!skippingCache() || !displayItem->isCached());
68 68
69 if (DisplayItem::isCachedType(displayItem->type())) 69 if (DisplayItem::isCachedType(displayItem->type()))
70 ++m_numCachedItems; 70 ++m_numCachedItems;
71 71
72 #if ENABLE(ASSERT) 72 #if ENABLE(ASSERT)
73 // Verify noop begin/end pairs have been removed. 73 // Verify noop begin/end pairs have been removed.
74 if (!m_newDisplayItems.isEmpty() && m_newDisplayItems.last().isBegin() && !m _newDisplayItems.last().drawsContent()) 74 if (m_newDisplayItems.size() >= 2 && displayItem->isEnd()) {
75 ASSERT(!displayItem->isEndAndPairedWith(m_newDisplayItems.last().type()) ); 75 const auto& beginDisplayItem = *m_newDisplayItems.elementAt(m_newDisplay Items.size() - 2);
76 if (beginDisplayItem.isBegin() && !beginDisplayItem.drawsContent())
77 ASSERT(!displayItem->isEndAndPairedWith(beginDisplayItem.type()));
78 }
76 #endif 79 #endif
77 80
78 if (!m_scopeStack.isEmpty()) 81 if (!m_scopeStack.isEmpty())
79 displayItem->setScope(m_scopeStack.last().id, m_scopeStack.last().client ); 82 displayItem->setScope(m_scopeStack.last().id, m_scopeStack.last().client );
80 83
81 #if ENABLE(ASSERT) 84 #if ENABLE(ASSERT)
82 size_t index = findMatchingItemFromIndex(displayItem->id(), displayItem->typ e(), m_newDisplayItemIndicesByClient, m_newDisplayItems); 85 size_t index = findMatchingItemFromIndex(displayItem->id(), displayItem->typ e(), m_newDisplayItemIndicesByClient, m_newDisplayItems);
83 if (index != kNotFound) { 86 if (index != kNotFound) {
84 #ifndef NDEBUG 87 #ifndef NDEBUG
85 showDebugData(); 88 showDebugData();
86 WTFLogAlways("DisplayItem %s has duplicated id with previous %s (index=% d)\n", 89 WTFLogAlways("DisplayItem %s has duplicated id with previous %s (index=% d)\n",
87 displayItem->asDebugString().utf8().data(), m_newDisplayItems[index] .asDebugString().utf8().data(), static_cast<int>(index)); 90 displayItem->asDebugString().utf8().data(), m_newDisplayItems.elemen tAt(index)->asDebugString().utf8().data(), static_cast<int>(index));
88 #endif 91 #endif
89 ASSERT_NOT_REACHED(); 92 ASSERT_NOT_REACHED();
90 } 93 }
91 addItemToIndex(displayItem->client(), displayItem->type(), m_newDisplayItems .size(), m_newDisplayItemIndicesByClient); 94 addItemToIndex(displayItem->client(), displayItem->type(), m_newDisplayItems .size() - 1, m_newDisplayItemIndicesByClient);
92 #endif // ENABLE(ASSERT) 95 #endif // ENABLE(ASSERT)
93 96
94 ASSERT(!displayItem->skippedCache()); // Only DisplayItemList can set the fl ag. 97 ASSERT(!displayItem->skippedCache()); // Only DisplayItemList can set the fl ag.
95 if (skippingCache()) 98 if (skippingCache())
96 displayItem->setSkippedCache(); 99 displayItem->setSkippedCache();
97
98 m_newDisplayItems.append(displayItem);
99 } 100 }
100 101
101 void DisplayItemList::beginScope(DisplayItemClient client) 102 void DisplayItemList::beginScope(DisplayItemClient client)
102 { 103 {
103 ClientScopeIdMap::iterator it = m_clientScopeIdMap.find(client); 104 ClientScopeIdMap::iterator it = m_clientScopeIdMap.find(client);
104 int scopeId; 105 int scopeId;
105 if (it == m_clientScopeIdMap.end()) { 106 if (it == m_clientScopeIdMap.end()) {
106 m_clientScopeIdMap.add(client, 0); 107 m_clientScopeIdMap.add(client, 0);
107 scopeId = 0; 108 scopeId = 0;
108 } else { 109 } else {
109 scopeId = ++it->value; 110 scopeId = ++it->value;
110 } 111 }
111 m_scopeStack.append(Scope(client, scopeId)); 112 m_scopeStack.append(Scope(client, scopeId));
112 beginSkippingCache(); 113 beginSkippingCache();
113 } 114 }
114 115
115 void DisplayItemList::endScope(DisplayItemClient client) 116 void DisplayItemList::endScope(DisplayItemClient client)
116 { 117 {
117 m_scopeStack.removeLast(); 118 m_scopeStack.removeLast();
118 endSkippingCache(); 119 endSkippingCache();
119 } 120 }
120 121
121 void DisplayItemList::invalidate(DisplayItemClient client) 122 void DisplayItemList::invalidate(DisplayItemClient client)
122 { 123 {
123 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled()); 124 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled());
124 // Can only be called during layout/paintInvalidation, not during painting. 125 // Can only be called during layout/paintInvalidation, not during painting.
125 ASSERT(m_newDisplayItems.isEmpty()); 126 ASSERT(m_newDisplayItems.empty());
126 updateValidlyCachedClientsIfNeeded(); 127 updateValidlyCachedClientsIfNeeded();
127 m_validlyCachedClients.remove(client); 128 m_validlyCachedClients.remove(client);
128 } 129 }
129 130
130 void DisplayItemList::invalidateAll() 131 void DisplayItemList::invalidateAll()
131 { 132 {
132 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled()); 133 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled());
133 // Can only be called during layout/paintInvalidation, not during painting. 134 // Can only be called during layout/paintInvalidation, not during painting.
134 ASSERT(m_newDisplayItems.isEmpty()); 135 ASSERT(m_newDisplayItems.empty());
135 m_currentDisplayItems.clear(); 136 m_currentDisplayItems.clear();
136 m_validlyCachedClients.clear(); 137 m_validlyCachedClients.clear();
137 m_validlyCachedClientsDirty = false; 138 m_validlyCachedClientsDirty = false;
138 } 139 }
139 140
140 bool DisplayItemList::clientCacheIsValid(DisplayItemClient client) const 141 bool DisplayItemList::clientCacheIsValid(DisplayItemClient client) const
141 { 142 {
142 if (skippingCache()) 143 if (skippingCache())
143 return false; 144 return false;
144 updateValidlyCachedClientsIfNeeded(); 145 updateValidlyCachedClientsIfNeeded();
145 return m_validlyCachedClients.contains(client); 146 return m_validlyCachedClients.contains(client);
146 } 147 }
147 148
148 size_t DisplayItemList::findMatchingItemFromIndex(const DisplayItem::Id& id, Dis playItem::Type matchingType, const DisplayItemIndicesByClientMap& displayItemInd icesByClient, const DisplayItems& list) 149 size_t DisplayItemList::findMatchingItemFromIndex(const DisplayItem::Id& id, Dis playItem::Type matchingType, const DisplayItemIndicesByClientMap& displayItemInd icesByClient, const DisplayItems& list)
149 { 150 {
150 DisplayItemIndicesByClientMap::const_iterator it = displayItemIndicesByClien t.find(id.client); 151 DisplayItemIndicesByClientMap::const_iterator it = displayItemIndicesByClien t.find(id.client);
151 if (it == displayItemIndicesByClient.end()) 152 if (it == displayItemIndicesByClient.end())
152 return kNotFound; 153 return kNotFound;
153 154
154 const Vector<size_t>& indices = it->value; 155 const Vector<size_t>& indices = it->value;
155 for (size_t index : indices) { 156 for (size_t index : indices) {
156 DisplayItems::ItemHandle existingItem = list[index]; 157 // TODO(pdr): elementAt is not cheap so this should be refactored (See c rbug.com/505965).
157 ASSERT(existingItem.isGone() || existingItem.client() == id.client); 158 const DisplayItem& existingItem = *list.elementAt(index);
158 if (!existingItem.isGone() && existingItem.id().equalToExceptForType(id, matchingType)) 159 ASSERT(existingItem.ignoreFromDisplayList() || existingItem.client() == id.client);
160 if (!existingItem.ignoreFromDisplayList() && existingItem.id().equalToEx ceptForType(id, matchingType))
159 return index; 161 return index;
160 } 162 }
161 163
162 return kNotFound; 164 return kNotFound;
163 } 165 }
164 166
165 void DisplayItemList::addItemToIndex(DisplayItemClient client, DisplayItem::Type type, size_t index, DisplayItemIndicesByClientMap& displayItemIndicesByClient) 167 void DisplayItemList::addItemToIndex(DisplayItemClient client, DisplayItem::Type type, size_t index, DisplayItemIndicesByClientMap& displayItemIndicesByClient)
166 { 168 {
167 // Only need to index DrawingDisplayItems and FIXME: BeginSubtreeDisplayItem s. 169 // Only need to index DrawingDisplayItems and FIXME: BeginSubtreeDisplayItem s.
168 if (!DisplayItem::isDrawingType(type)) 170 if (!DisplayItem::isDrawingType(type))
(...skipping 15 matching lines...) Expand all
184 return m_currentDisplayItems.iteratorAt(foundIndex); 186 return m_currentDisplayItems.iteratorAt(foundIndex);
185 187
186 return findOutOfOrderCachedItemForward(currentIt, id, matchingType, displayI temIndicesByClient); 188 return findOutOfOrderCachedItemForward(currentIt, id, matchingType, displayI temIndicesByClient);
187 } 189 }
188 190
189 // Find forward for the item and index all skipped indexable items. 191 // Find forward for the item and index all skipped indexable items.
190 DisplayItems::Iterator DisplayItemList::findOutOfOrderCachedItemForward(DisplayI tems::Iterator currentIt, const DisplayItem::Id& id, DisplayItem::Type matchingT ype, DisplayItemIndicesByClientMap& displayItemIndicesByClient) 192 DisplayItems::Iterator DisplayItemList::findOutOfOrderCachedItemForward(DisplayI tems::Iterator currentIt, const DisplayItem::Id& id, DisplayItem::Type matchingT ype, DisplayItemIndicesByClientMap& displayItemIndicesByClient)
191 { 193 {
192 DisplayItems::Iterator currentEnd = m_currentDisplayItems.end(); 194 DisplayItems::Iterator currentEnd = m_currentDisplayItems.end();
193 for (; currentIt != currentEnd; ++currentIt) { 195 for (; currentIt != currentEnd; ++currentIt) {
194 DisplayItems::ItemHandle item = *currentIt; 196 const DisplayItem& item = **currentIt;
195 if (!item.isGone() 197 if (!item.ignoreFromDisplayList()
196 && DisplayItem::isDrawingType(item.type()) 198 && DisplayItem::isDrawingType(item.type())
197 && m_validlyCachedClients.contains(item.client())) { 199 && m_validlyCachedClients.contains(item.client())) {
198 if (item.id().equalToExceptForType(id, matchingType)) 200 if (item.id().equalToExceptForType(id, matchingType))
199 return currentIt; 201 return currentIt;
200 202
201 size_t currentDisplayItemsIndex = m_currentDisplayItems.indexForIter ator(currentIt); 203 addItemToIndex(item.client(), item.type(), currentIt.index(), displa yItemIndicesByClient);
202 addItemToIndex(item.client(), item.type(), currentDisplayItemsIndex, displayItemIndicesByClient);
203 } 204 }
204 } 205 }
205 return currentEnd; 206 return currentEnd;
206 } 207 }
207 208
208 // Update the existing display items by removing invalidated entries, updating 209 // Update the existing display items by removing invalidated entries, updating
209 // repainted ones, and appending new items. 210 // repainted ones, and appending new items.
210 // - For CachedDisplayItem, copy the corresponding cached DrawingDisplayItem; 211 // - For CachedDisplayItem, copy the corresponding cached DrawingDisplayItem;
211 // - FIXME: Re-enable SubtreeCachedDisplayItem: 212 // - FIXME: Re-enable SubtreeCachedDisplayItem:
212 // For SubtreeCachedDisplayItem, copy the cached display items between the 213 // For SubtreeCachedDisplayItem, copy the cached display items between the
(...skipping 10 matching lines...) Expand all
223 224
224 // These data structures are used during painting only. 225 // These data structures are used during painting only.
225 m_clientScopeIdMap.clear(); 226 m_clientScopeIdMap.clear();
226 ASSERT(m_scopeStack.isEmpty()); 227 ASSERT(m_scopeStack.isEmpty());
227 m_scopeStack.clear(); 228 m_scopeStack.clear();
228 ASSERT(!skippingCache()); 229 ASSERT(!skippingCache());
229 #if ENABLE(ASSERT) 230 #if ENABLE(ASSERT)
230 m_newDisplayItemIndicesByClient.clear(); 231 m_newDisplayItemIndicesByClient.clear();
231 #endif 232 #endif
232 233
233 if (m_currentDisplayItems.isEmpty()) { 234 if (m_currentDisplayItems.empty()) {
234 #if ENABLE(ASSERT) 235 #if ENABLE(ASSERT)
235 for (auto& item : m_newDisplayItems) { 236 for (const auto& item : m_newDisplayItems) {
236 ASSERT(!DisplayItem::isCachedType(item.type()) 237 ASSERT(!DisplayItem::isCachedType(item->type())
237 && !DisplayItem::isSubtreeCachedType(item.type())); 238 && !DisplayItem::isSubtreeCachedType(item->type()));
238 } 239 }
239 #endif 240 #endif
240 m_currentDisplayItems.swap(m_newDisplayItems); 241 m_currentDisplayItems.swap(m_newDisplayItems);
241 m_validlyCachedClientsDirty = true; 242 m_validlyCachedClientsDirty = true;
242 m_numCachedItems = 0; 243 m_numCachedItems = 0;
243 return; 244 return;
244 } 245 }
245 246
246 updateValidlyCachedClientsIfNeeded(); 247 updateValidlyCachedClientsIfNeeded();
247 248
248 // Stores indices to valid DrawingDisplayItems in m_currentDisplayItems that have not been matched 249 // Stores indices to valid DrawingDisplayItems in m_currentDisplayItems that have not been matched
249 // by CachedDisplayItems during synchronized matching. The indexed items wil l be matched 250 // by CachedDisplayItems during synchronized matching. The indexed items wil l be matched
250 // by later out-of-order CachedDisplayItems in m_newDisplayItems. This ensur es that when 251 // by later out-of-order CachedDisplayItems in m_newDisplayItems. This ensur es that when
251 // out-of-order CachedDisplayItems occur, we only traverse at most once over m_currentDisplayItems 252 // out-of-order CachedDisplayItems occur, we only traverse at most once over m_currentDisplayItems
252 // looking for potential matches. Thus we can ensure that the algorithm runs in linear time. 253 // looking for potential matches. Thus we can ensure that the algorithm runs in linear time.
253 DisplayItemIndicesByClientMap displayItemIndicesByClient; 254 DisplayItemIndicesByClientMap displayItemIndicesByClient;
254 255
255 #if ENABLE(ASSERT) 256 #if ENABLE(ASSERT)
256 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) { 257 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) {
257 // Under-invalidation checking requires a full index of m_currentDisplay Items. 258 // Under-invalidation checking requires a full index of m_currentDisplay Items.
258 size_t i = 0; 259 size_t i = 0;
259 for (const auto& item : m_currentDisplayItems) { 260 for (const auto& item : m_currentDisplayItems) {
260 addItemToIndex(item.client(), item.type(), i, displayItemIndicesByCl ient); 261 addItemToIndex(item->client(), item->type(), i, displayItemIndicesBy Client);
261 ++i; 262 ++i;
262 } 263 }
263 } 264 }
264 #endif // ENABLE(ASSERT) 265 #endif // ENABLE(ASSERT)
265 266
266 DisplayItems updatedList; 267 DisplayItems updatedList(kMaximumDisplayItemSize, std::max(m_currentDisplayI tems.size(), m_newDisplayItems.size()));
267 DisplayItems::Iterator currentIt = m_currentDisplayItems.begin(); 268 DisplayItems::Iterator currentIt = m_currentDisplayItems.begin();
268 DisplayItems::Iterator currentEnd = m_currentDisplayItems.end(); 269 DisplayItems::Iterator currentEnd = m_currentDisplayItems.end();
269 for (DisplayItems::Iterator newIt = m_newDisplayItems.begin(); newIt != m_ne wDisplayItems.end(); ++newIt) { 270 for (DisplayItems::Iterator newIt = m_newDisplayItems.begin(); newIt != m_ne wDisplayItems.end(); ++newIt) {
270 DisplayItems::ItemHandle newDisplayItem = *newIt; 271 const DisplayItem& newDisplayItem = **newIt;
271 DisplayItem::Type matchingType = newDisplayItem.type(); 272 DisplayItem::Type matchingType = newDisplayItem.type();
272 if (DisplayItem::isCachedType(newDisplayItem.type())) 273 if (DisplayItem::isCachedType(newDisplayItem.type()))
273 matchingType = DisplayItem::cachedTypeToDrawingType(matchingType); 274 matchingType = DisplayItem::cachedTypeToDrawingType(matchingType);
274 bool isSynchronized = currentIt != currentEnd 275 bool isSynchronized = currentIt != currentEnd
275 && !currentIt->isGone() 276 && !currentIt->ignoreFromDisplayList()
276 && currentIt->id().equalToExceptForType(newDisplayItem.id(), matchin gType); 277 && currentIt->id().equalToExceptForType(newDisplayItem.id(), matchin gType);
277 278
278 if (DisplayItem::isCachedType(newDisplayItem.type())) { 279 if (DisplayItem::isCachedType(newDisplayItem.type())) {
279 ASSERT(!RuntimeEnabledFeatures::slimmingPaintUnderInvalidationChecki ngEnabled()); 280 ASSERT(!RuntimeEnabledFeatures::slimmingPaintUnderInvalidationChecki ngEnabled());
280 ASSERT(clientCacheIsValid(newDisplayItem.client())); 281 ASSERT(clientCacheIsValid(newDisplayItem.client()));
281 if (isSynchronized) { 282 if (isSynchronized) {
282 updatedList.appendByMoving(currentIt); 283 updatedList.appendByMoving(*currentIt);
283 } else { 284 } else {
284 DisplayItems::Iterator foundIt = findOutOfOrderCachedItem(curren tIt, newDisplayItem.id(), matchingType, displayItemIndicesByClient); 285 DisplayItems::Iterator foundIt = findOutOfOrderCachedItem(curren tIt, newDisplayItem.id(), matchingType, displayItemIndicesByClient);
285 isSynchronized = (foundIt == currentIt); 286 isSynchronized = (foundIt == currentIt);
286 287
287 #ifndef NDEBUG 288 #ifndef NDEBUG
288 if (foundIt == currentEnd) { 289 if (foundIt == currentEnd) {
289 showDebugData(); 290 showDebugData();
290 WTFLogAlways("CachedDisplayItem %s not found in m_currentDis playItems\n", 291 WTFLogAlways("CachedDisplayItem %s not found in m_currentDis playItems\n",
291 newDisplayItem.asDebugString().utf8().data()); 292 newDisplayItem.asDebugString().utf8().data());
292 ASSERT_NOT_REACHED(); 293 ASSERT_NOT_REACHED();
293 } 294 }
294 #endif 295 #endif
295 // If foundIt == currentEnd, it means that we did not find the c ached display item. This should be impossible, but may occur 296 // If foundIt == currentEnd, it means that we did not find the c ached display item. This should be impossible, but may occur
296 // if there is a bug in the system, such as under-invalidation, incorrect cache checking or duplicate display ids. In this case, 297 // if there is a bug in the system, such as under-invalidation, incorrect cache checking or duplicate display ids. In this case,
297 // attempt to recover rather than crashing or bailing on display of the rest of the display list. 298 // attempt to recover rather than crashing or bailing on display of the rest of the display list.
298 if (foundIt == currentEnd) 299 if (foundIt == currentEnd)
299 continue; 300 continue;
300 301
301 currentIt = foundIt; 302 currentIt = foundIt;
302 303
303 updatedList.appendByMoving(foundIt); 304 updatedList.appendByMoving(*foundIt);
304 } 305 }
305 } else { 306 } else {
306 #if ENABLE(ASSERT) 307 #if ENABLE(ASSERT)
307 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEn abled()) 308 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEn abled())
308 checkCachedDisplayItemIsUnchanged(newDisplayItem, displayItemInd icesByClient); 309 checkCachedDisplayItemIsUnchanged(newDisplayItem, displayItemInd icesByClient);
309 else 310 else
310 ASSERT(!DisplayItem::isDrawingType(newDisplayItem.type()) || new DisplayItem.skippedCache() || !clientCacheIsValid(newDisplayItem.client())); 311 ASSERT(!DisplayItem::isDrawingType(newDisplayItem.type()) || new DisplayItem.skippedCache() || !clientCacheIsValid(newDisplayItem.client()));
311 #endif // ENABLE(ASSERT) 312 #endif // ENABLE(ASSERT)
312 updatedList.appendByMoving(newIt); 313 updatedList.appendByMoving(*newIt);
313 } 314 }
314 315
315 if (isSynchronized) 316 if (isSynchronized)
316 ++currentIt; 317 ++currentIt;
317 } 318 }
318 319
319 #if ENABLE(ASSERT) 320 #if ENABLE(ASSERT)
320 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) 321 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled())
321 checkNoRemainingCachedDisplayItems(); 322 checkNoRemainingCachedDisplayItems();
322 #endif // ENABLE(ASSERT) 323 #endif // ENABLE(ASSERT)
323 324
324 m_newDisplayItems.clear(); 325 m_newDisplayItems.clear();
325 m_validlyCachedClientsDirty = true; 326 m_validlyCachedClientsDirty = true;
326 m_currentDisplayItems.clear();
327 m_currentDisplayItems.swap(updatedList); 327 m_currentDisplayItems.swap(updatedList);
328 m_numCachedItems = 0; 328 m_numCachedItems = 0;
329 } 329 }
330 330
331 void DisplayItemList::updateValidlyCachedClientsIfNeeded() const 331 void DisplayItemList::updateValidlyCachedClientsIfNeeded() const
332 { 332 {
333 if (!m_validlyCachedClientsDirty) 333 if (!m_validlyCachedClientsDirty)
334 return; 334 return;
335 335
336 m_validlyCachedClients.clear(); 336 m_validlyCachedClients.clear();
337 m_validlyCachedClientsDirty = false; 337 m_validlyCachedClientsDirty = false;
338 338
339 DisplayItemClient lastClient = nullptr; 339 DisplayItemClient lastClient = nullptr;
340 for (const auto& displayItem : m_currentDisplayItems) { 340 for (const auto& displayItem : m_currentDisplayItems) {
341 if (displayItem.client() == lastClient) 341 if (displayItem->client() == lastClient)
342 continue; 342 continue;
343 lastClient = displayItem.client(); 343 lastClient = displayItem->client();
344 if (!displayItem.skippedCache()) 344 if (!displayItem->skippedCache())
345 m_validlyCachedClients.add(lastClient); 345 m_validlyCachedClients.add(lastClient);
346 } 346 }
347 } 347 }
348 348
349 void DisplayItemList::commitNewDisplayItemsAndAppendToWebDisplayItemList(WebDisp layItemList* list) 349 void DisplayItemList::commitNewDisplayItemsAndAppendToWebDisplayItemList(WebDisp layItemList* list)
350 { 350 {
351 commitNewDisplayItems(); 351 commitNewDisplayItems();
352 for (auto& item : m_currentDisplayItems) 352 for (const auto& item : m_currentDisplayItems)
353 item.appendToWebDisplayItemList(list); 353 item->appendToWebDisplayItemList(list);
354 } 354 }
355 355
356 #if ENABLE(ASSERT) 356 #if ENABLE(ASSERT)
357 357
358 static void showUnderInvalidationError(const char* reason, const DisplayItems::I temHandle& displayItem) 358 static void showUnderInvalidationError(const char* reason, const DisplayItem& di splayItem)
359 { 359 {
360 #ifndef NDEBUG 360 #ifndef NDEBUG
361 WTFLogAlways("%s: %s\nSee http://crbug.com/450725.", reason, displayItem.asD ebugString().utf8().data()); 361 WTFLogAlways("%s: %s\nSee http://crbug.com/450725.", reason, displayItem.asD ebugString().utf8().data());
362 #else 362 #else
363 WTFLogAlways("%s. Run debug build to get more details\nSee http://crbug.com/ 450725.", reason); 363 WTFLogAlways("%s. Run debug build to get more details\nSee http://crbug.com/ 450725.", reason);
364 #endif // NDEBUG 364 #endif // NDEBUG
365 } 365 }
366 366
367 static bool bitmapIsAllZero(const SkBitmap& bitmap) 367 static bool bitmapIsAllZero(const SkBitmap& bitmap)
368 { 368 {
369 bitmap.lockPixels(); 369 bitmap.lockPixels();
370 bool result = true; 370 bool result = true;
371 for (int x = 0; result && x < bitmap.width(); ++x) { 371 for (int x = 0; result && x < bitmap.width(); ++x) {
372 for (int y = 0; result && y < bitmap.height(); ++y) { 372 for (int y = 0; result && y < bitmap.height(); ++y) {
373 if (SkColorSetA(bitmap.getColor(x, y), 0) != SK_ColorTRANSPARENT) 373 if (SkColorSetA(bitmap.getColor(x, y), 0) != SK_ColorTRANSPARENT)
374 result = false; 374 result = false;
375 } 375 }
376 } 376 }
377 bitmap.unlockPixels(); 377 bitmap.unlockPixels();
378 return result; 378 return result;
379 } 379 }
380 380
381 void DisplayItemList::checkCachedDisplayItemIsUnchanged(const DisplayItems::Item Handle& displayItem, DisplayItemIndicesByClientMap& displayItemIndicesByClient) 381 void DisplayItemList::checkCachedDisplayItemIsUnchanged(const DisplayItem& displ ayItem, DisplayItemIndicesByClientMap& displayItemIndicesByClient)
382 { 382 {
383 ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled ()); 383 ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled ());
384 384
385 if (!DisplayItem::isDrawingType(displayItem.type()) || displayItem.skippedCa che() || !clientCacheIsValid(displayItem.client())) 385 if (!DisplayItem::isDrawingType(displayItem.type()) || displayItem.skippedCa che() || !clientCacheIsValid(displayItem.client()))
386 return; 386 return;
387 387
388 // If checking under-invalidation, we always generate new display item even if the client is not invalidated. 388 // If checking under-invalidation, we always generate new display item even if the client is not invalidated.
389 // Checks if the new picture is the same as the cached old picture. If the n ew picture is different but 389 // Checks if the new picture is the same as the cached old picture. If the n ew picture is different but
390 // the client is not invalidated, issue error about under-invalidation. 390 // the client is not invalidated, issue error about under-invalidation.
391 size_t index = findMatchingItemFromIndex(displayItem.id(), displayItem.type( ), displayItemIndicesByClient, m_currentDisplayItems); 391 size_t index = findMatchingItemFromIndex(displayItem.id(), displayItem.type( ), displayItemIndicesByClient, m_currentDisplayItems);
392 if (index == kNotFound) { 392 if (index == kNotFound) {
393 showUnderInvalidationError("ERROR: under-invalidation: no cached display item", displayItem); 393 showUnderInvalidationError("ERROR: under-invalidation: no cached display item", displayItem);
394 ASSERT_NOT_REACHED(); 394 ASSERT_NOT_REACHED();
395 return; 395 return;
396 } 396 }
397 397
398 DisplayItems::Iterator foundItem = m_currentDisplayItems.iteratorAt(index); 398 DisplayItems::Iterator foundItem = m_currentDisplayItems.iteratorAt(index);
399 RefPtr<const SkPicture> newPicture = displayItem.picture(); 399 RefPtr<const SkPicture> newPicture = static_cast<const DrawingDisplayItem&>( displayItem).picture();
400 RefPtr<const SkPicture> oldPicture = foundItem->picture(); 400 RefPtr<const SkPicture> oldPicture = static_cast<const DrawingDisplayItem*>( *foundItem)->picture();
401 // Remove the display item from cache so that we can check if there are any remaining cached display items after merging. 401 // Mark the display item as ignored so that we can check if there are any re maining cached display items after merging.
402 m_currentDisplayItems.setGone(foundItem); 402 foundItem->setIgnoredFromDisplayList();
403 403
404 if (!newPicture && !oldPicture) 404 if (!newPicture && !oldPicture)
405 return; 405 return;
406 if (newPicture && oldPicture) { 406 if (newPicture && oldPicture) {
407 switch (displayItem.underInvalidationCheckingMode()) { 407 switch (static_cast<const DrawingDisplayItem&>(displayItem).underInvalid ationCheckingMode()) {
408 case DrawingDisplayItem::CheckPicture: 408 case DrawingDisplayItem::CheckPicture:
409 if (newPicture->approximateOpCount() == oldPicture->approximateOpCou nt()) { 409 if (newPicture->approximateOpCount() == oldPicture->approximateOpCou nt()) {
410 SkDynamicMemoryWStream newPictureSerialized; 410 SkDynamicMemoryWStream newPictureSerialized;
411 newPicture->serialize(&newPictureSerialized); 411 newPicture->serialize(&newPictureSerialized);
412 SkDynamicMemoryWStream oldPictureSerialized; 412 SkDynamicMemoryWStream oldPictureSerialized;
413 oldPicture->serialize(&oldPictureSerialized); 413 oldPicture->serialize(&oldPictureSerialized);
414 414
415 if (newPictureSerialized.bytesWritten() == oldPictureSerialized. bytesWritten()) { 415 if (newPictureSerialized.bytesWritten() == oldPictureSerialized. bytesWritten()) {
416 RefPtr<SkData> oldData = adoptRef(oldPictureSerialized.copyT oData()); 416 RefPtr<SkData> oldData = adoptRef(oldPictureSerialized.copyT oData());
417 RefPtr<SkData> newData = adoptRef(newPictureSerialized.copyT oData()); 417 RefPtr<SkData> newData = adoptRef(newPictureSerialized.copyT oData());
(...skipping 30 matching lines...) Expand all
448 #endif // NDEBUG 448 #endif // NDEBUG
449 449
450 ASSERT_NOT_REACHED(); 450 ASSERT_NOT_REACHED();
451 } 451 }
452 452
453 void DisplayItemList::checkNoRemainingCachedDisplayItems() 453 void DisplayItemList::checkNoRemainingCachedDisplayItems()
454 { 454 {
455 ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled ()); 455 ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled ());
456 456
457 for (const auto& displayItem : m_currentDisplayItems) { 457 for (const auto& displayItem : m_currentDisplayItems) {
458 if (displayItem.isGone() || !DisplayItem::isDrawingType(displayItem.type ()) || !clientCacheIsValid(displayItem.client())) 458 if (displayItem->ignoreFromDisplayList() || !DisplayItem::isDrawingType( displayItem->type()) || !clientCacheIsValid(displayItem->client()))
459 continue; 459 continue;
460 showUnderInvalidationError("May be under-invalidation: no new display it em", displayItem); 460 showUnderInvalidationError("May be under-invalidation: no new display it em", *displayItem);
461 } 461 }
462 } 462 }
463 463
464 #endif // ENABLE(ASSERT) 464 #endif // ENABLE(ASSERT)
465 465
466 #ifndef NDEBUG 466 #ifndef NDEBUG
467 467
468 WTF::String DisplayItemList::displayItemsAsDebugString(const DisplayItems& list) const 468 WTF::String DisplayItemList::displayItemsAsDebugString(const DisplayItems& list) const
469 { 469 {
470 StringBuilder stringBuilder; 470 StringBuilder stringBuilder;
471 size_t i = 0; 471 size_t i = 0;
472 for (auto it = list.begin(); it != list.end(); ++it, ++i) { 472 for (auto it = list.begin(); it != list.end(); ++it, ++i) {
473 DisplayItems::ItemHandle displayItem = list[i]; 473 const DisplayItem& displayItem = *list.elementAt(i);
474 if (i) 474 if (i)
475 stringBuilder.append(",\n"); 475 stringBuilder.append(",\n");
476 if (displayItem.isGone()) { 476 if (displayItem.ignoreFromDisplayList()) {
477 stringBuilder.append("null"); 477 stringBuilder.append("null");
478 continue; 478 continue;
479 } 479 }
480 stringBuilder.append(String::format("{index: %d, ", (int)i)); 480 stringBuilder.append(String::format("{index: %d, ", (int)i));
481 displayItem.dumpPropertiesAsDebugString(stringBuilder); 481 displayItem.dumpPropertiesAsDebugString(stringBuilder);
482 stringBuilder.append(", cacheIsValid: "); 482 stringBuilder.append(", cacheIsValid: ");
483 stringBuilder.append(clientCacheIsValid(displayItem.client()) ? "true" : "false"); 483 stringBuilder.append(clientCacheIsValid(displayItem.client()) ? "true" : "false");
484 stringBuilder.append('}'); 484 stringBuilder.append('}');
485 } 485 }
486 return stringBuilder.toString(); 486 return stringBuilder.toString();
487 } 487 }
488 488
489 void DisplayItemList::showDebugData() const 489 void DisplayItemList::showDebugData() const
490 { 490 {
491 WTFLogAlways("current display items: [%s]\n", displayItemsAsDebugString(m_cu rrentDisplayItems).utf8().data()); 491 WTFLogAlways("current display items: [%s]\n", displayItemsAsDebugString(m_cu rrentDisplayItems).utf8().data());
492 WTFLogAlways("new display items: [%s]\n", displayItemsAsDebugString(m_newDis playItems).utf8().data()); 492 WTFLogAlways("new display items: [%s]\n", displayItemsAsDebugString(m_newDis playItems).utf8().data());
493 } 493 }
494 494
495 #endif // ifndef NDEBUG 495 #endif // ifndef NDEBUG
496 496
497 void DisplayItemList::replay(GraphicsContext& context) const 497 void DisplayItemList::replay(GraphicsContext& context)
498 { 498 {
499 TRACE_EVENT0("blink,benchmark", "DisplayItemList::replay"); 499 TRACE_EVENT0("blink,benchmark", "DisplayItemList::replay");
500 ASSERT(m_newDisplayItems.isEmpty()); 500 ASSERT(m_newDisplayItems.empty());
501 for (auto& displayItem : m_currentDisplayItems) 501 for (auto displayItem : m_currentDisplayItems)
502 displayItem.replay(context); 502 displayItem->replay(context);
503 } 503 }
504 504
505 } // namespace blink 505 } // namespace blink
OLDNEW
« no previous file with comments | « Source/platform/graphics/paint/DisplayItemList.h ('k') | Source/platform/graphics/paint/DisplayItemListTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698