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

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: Remove ListContainer::operatorAt[] 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 const DisplayItem& existingItem = *list.elementAt(index);
danakj 2015/06/30 18:49:01 This is using elementAt() in non-assert code AFAIC
jbroman 2015/06/30 18:59:17 I'd suggest attempting this in a followup CL. I el
pdr. 2015/06/30 22:16:06 I added a TODO here and filed crbug.com/505965.
157 ASSERT(existingItem.isGone() || existingItem.client() == id.client); 158 ASSERT(existingItem.ignoreFromDisplayList() || existingItem.client() == id.client);
158 if (!existingItem.isGone() && existingItem.id().equalToExceptForType(id, matchingType)) 159 if (!existingItem.ignoreFromDisplayList() && existingItem.id().equalToEx ceptForType(id, matchingType))
159 return index; 160 return index;
160 } 161 }
161 162
162 return kNotFound; 163 return kNotFound;
163 } 164 }
164 165
165 void DisplayItemList::addItemToIndex(DisplayItemClient client, DisplayItem::Type type, size_t index, DisplayItemIndicesByClientMap& displayItemIndicesByClient) 166 void DisplayItemList::addItemToIndex(DisplayItemClient client, DisplayItem::Type type, size_t index, DisplayItemIndicesByClientMap& displayItemIndicesByClient)
166 { 167 {
167 // Only need to index DrawingDisplayItems and FIXME: BeginSubtreeDisplayItem s. 168 // Only need to index DrawingDisplayItems and FIXME: BeginSubtreeDisplayItem s.
168 if (!DisplayItem::isDrawingType(type)) 169 if (!DisplayItem::isDrawingType(type))
(...skipping 15 matching lines...) Expand all
184 return m_currentDisplayItems.iteratorAt(foundIndex); 185 return m_currentDisplayItems.iteratorAt(foundIndex);
185 186
186 return findOutOfOrderCachedItemForward(currentIt, id, matchingType, displayI temIndicesByClient); 187 return findOutOfOrderCachedItemForward(currentIt, id, matchingType, displayI temIndicesByClient);
187 } 188 }
188 189
189 // Find forward for the item and index all skipped indexable items. 190 // 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) 191 DisplayItems::Iterator DisplayItemList::findOutOfOrderCachedItemForward(DisplayI tems::Iterator currentIt, const DisplayItem::Id& id, DisplayItem::Type matchingT ype, DisplayItemIndicesByClientMap& displayItemIndicesByClient)
191 { 192 {
192 DisplayItems::Iterator currentEnd = m_currentDisplayItems.end(); 193 DisplayItems::Iterator currentEnd = m_currentDisplayItems.end();
193 for (; currentIt != currentEnd; ++currentIt) { 194 for (; currentIt != currentEnd; ++currentIt) {
194 DisplayItems::ItemHandle item = *currentIt; 195 const DisplayItem& item = **currentIt;
195 if (!item.isGone() 196 if (!item.ignoreFromDisplayList()
196 && DisplayItem::isDrawingType(item.type()) 197 && DisplayItem::isDrawingType(item.type())
197 && m_validlyCachedClients.contains(item.client())) { 198 && m_validlyCachedClients.contains(item.client())) {
198 if (item.id().equalToExceptForType(id, matchingType)) 199 if (item.id().equalToExceptForType(id, matchingType))
199 return currentIt; 200 return currentIt;
200 201
201 size_t currentDisplayItemsIndex = m_currentDisplayItems.indexForIter ator(currentIt); 202 addItemToIndex(item.client(), item.type(), currentIt.index(), displa yItemIndicesByClient);
202 addItemToIndex(item.client(), item.type(), currentDisplayItemsIndex, displayItemIndicesByClient);
203 } 203 }
204 } 204 }
205 return currentEnd; 205 return currentEnd;
206 } 206 }
207 207
208 // Update the existing display items by removing invalidated entries, updating 208 // Update the existing display items by removing invalidated entries, updating
209 // repainted ones, and appending new items. 209 // repainted ones, and appending new items.
210 // - For CachedDisplayItem, copy the corresponding cached DrawingDisplayItem; 210 // - For CachedDisplayItem, copy the corresponding cached DrawingDisplayItem;
211 // - FIXME: Re-enable SubtreeCachedDisplayItem: 211 // - FIXME: Re-enable SubtreeCachedDisplayItem:
212 // For SubtreeCachedDisplayItem, copy the cached display items between the 212 // For SubtreeCachedDisplayItem, copy the cached display items between the
(...skipping 10 matching lines...) Expand all
223 223
224 // These data structures are used during painting only. 224 // These data structures are used during painting only.
225 m_clientScopeIdMap.clear(); 225 m_clientScopeIdMap.clear();
226 ASSERT(m_scopeStack.isEmpty()); 226 ASSERT(m_scopeStack.isEmpty());
227 m_scopeStack.clear(); 227 m_scopeStack.clear();
228 ASSERT(!skippingCache()); 228 ASSERT(!skippingCache());
229 #if ENABLE(ASSERT) 229 #if ENABLE(ASSERT)
230 m_newDisplayItemIndicesByClient.clear(); 230 m_newDisplayItemIndicesByClient.clear();
231 #endif 231 #endif
232 232
233 if (m_currentDisplayItems.isEmpty()) { 233 if (m_currentDisplayItems.empty()) {
234 #if ENABLE(ASSERT) 234 #if ENABLE(ASSERT)
235 for (auto& item : m_newDisplayItems) { 235 for (const auto& item : m_newDisplayItems) {
236 ASSERT(!DisplayItem::isCachedType(item.type()) 236 ASSERT(!DisplayItem::isCachedType(item->type())
237 && !DisplayItem::isSubtreeCachedType(item.type())); 237 && !DisplayItem::isSubtreeCachedType(item->type()));
238 } 238 }
239 #endif 239 #endif
240 m_currentDisplayItems.swap(m_newDisplayItems); 240 m_currentDisplayItems.swap(m_newDisplayItems);
241 m_validlyCachedClientsDirty = true; 241 m_validlyCachedClientsDirty = true;
242 m_numCachedItems = 0; 242 m_numCachedItems = 0;
243 return; 243 return;
244 } 244 }
245 245
246 updateValidlyCachedClientsIfNeeded(); 246 updateValidlyCachedClientsIfNeeded();
247 247
248 // Stores indices to valid DrawingDisplayItems in m_currentDisplayItems that have not been matched 248 // 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 249 // 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 250 // 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 251 // 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. 252 // looking for potential matches. Thus we can ensure that the algorithm runs in linear time.
253 DisplayItemIndicesByClientMap displayItemIndicesByClient; 253 DisplayItemIndicesByClientMap displayItemIndicesByClient;
254 254
255 #if ENABLE(ASSERT) 255 #if ENABLE(ASSERT)
256 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) { 256 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) {
257 // Under-invalidation checking requires a full index of m_currentDisplay Items. 257 // Under-invalidation checking requires a full index of m_currentDisplay Items.
258 size_t i = 0; 258 size_t i = 0;
259 for (const auto& item : m_currentDisplayItems) { 259 for (const auto& item : m_currentDisplayItems) {
260 addItemToIndex(item.client(), item.type(), i, displayItemIndicesByCl ient); 260 addItemToIndex(item->client(), item->type(), i, displayItemIndicesBy Client);
261 ++i; 261 ++i;
262 } 262 }
263 } 263 }
264 #endif // ENABLE(ASSERT) 264 #endif // ENABLE(ASSERT)
265 265
266 DisplayItems updatedList; 266 DisplayItems updatedList(kMaximumDisplayItemSize, std::max(m_currentDisplayI tems.size(), m_newDisplayItems.size()));
267 DisplayItems::Iterator currentIt = m_currentDisplayItems.begin(); 267 DisplayItems::Iterator currentIt = m_currentDisplayItems.begin();
268 DisplayItems::Iterator currentEnd = m_currentDisplayItems.end(); 268 DisplayItems::Iterator currentEnd = m_currentDisplayItems.end();
269 for (DisplayItems::Iterator newIt = m_newDisplayItems.begin(); newIt != m_ne wDisplayItems.end(); ++newIt) { 269 for (DisplayItems::Iterator newIt = m_newDisplayItems.begin(); newIt != m_ne wDisplayItems.end(); ++newIt) {
270 DisplayItems::ItemHandle newDisplayItem = *newIt; 270 const DisplayItem& newDisplayItem = **newIt;
271 DisplayItem::Type matchingType = newDisplayItem.type(); 271 DisplayItem::Type matchingType = newDisplayItem.type();
272 if (DisplayItem::isCachedType(newDisplayItem.type())) 272 if (DisplayItem::isCachedType(newDisplayItem.type()))
273 matchingType = DisplayItem::cachedTypeToDrawingType(matchingType); 273 matchingType = DisplayItem::cachedTypeToDrawingType(matchingType);
274 bool isSynchronized = currentIt != currentEnd 274 bool isSynchronized = currentIt != currentEnd
275 && !currentIt->isGone() 275 && !currentIt->ignoreFromDisplayList()
276 && currentIt->id().equalToExceptForType(newDisplayItem.id(), matchin gType); 276 && currentIt->id().equalToExceptForType(newDisplayItem.id(), matchin gType);
277 277
278 if (DisplayItem::isCachedType(newDisplayItem.type())) { 278 if (DisplayItem::isCachedType(newDisplayItem.type())) {
279 ASSERT(!RuntimeEnabledFeatures::slimmingPaintUnderInvalidationChecki ngEnabled()); 279 ASSERT(!RuntimeEnabledFeatures::slimmingPaintUnderInvalidationChecki ngEnabled());
280 ASSERT(clientCacheIsValid(newDisplayItem.client())); 280 ASSERT(clientCacheIsValid(newDisplayItem.client()));
281 if (isSynchronized) { 281 if (isSynchronized) {
282 updatedList.appendByMoving(currentIt); 282 updatedList.appendByMoving(*currentIt);
283 } else { 283 } else {
284 DisplayItems::Iterator foundIt = findOutOfOrderCachedItem(curren tIt, newDisplayItem.id(), matchingType, displayItemIndicesByClient); 284 DisplayItems::Iterator foundIt = findOutOfOrderCachedItem(curren tIt, newDisplayItem.id(), matchingType, displayItemIndicesByClient);
285 isSynchronized = (foundIt == currentIt); 285 isSynchronized = (foundIt == currentIt);
286 286
287 #ifndef NDEBUG 287 #ifndef NDEBUG
288 if (foundIt == currentEnd) { 288 if (foundIt == currentEnd) {
289 showDebugData(); 289 showDebugData();
290 WTFLogAlways("CachedDisplayItem %s not found in m_currentDis playItems\n", 290 WTFLogAlways("CachedDisplayItem %s not found in m_currentDis playItems\n",
291 newDisplayItem.asDebugString().utf8().data()); 291 newDisplayItem.asDebugString().utf8().data());
292 ASSERT_NOT_REACHED(); 292 ASSERT_NOT_REACHED();
293 } 293 }
294 #endif 294 #endif
295 // If foundIt == currentEnd, it means that we did not find the c ached display item. This should be impossible, but may occur 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 there is a bug in the system, such as under-invalidation, incorrect cache checking or duplicate display ids. In this case, 296 // 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. 297 // attempt to recover rather than crashing or bailing on display of the rest of the display list.
298 if (foundIt == currentEnd) 298 if (foundIt == currentEnd)
299 continue; 299 continue;
300 300
301 currentIt = foundIt; 301 currentIt = foundIt;
302 302
303 updatedList.appendByMoving(foundIt); 303 updatedList.appendByMoving(*foundIt);
304 } 304 }
305 } else { 305 } else {
306 #if ENABLE(ASSERT) 306 #if ENABLE(ASSERT)
307 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEn abled()) 307 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEn abled())
308 checkCachedDisplayItemIsUnchanged(newDisplayItem, displayItemInd icesByClient); 308 checkCachedDisplayItemIsUnchanged(newDisplayItem, displayItemInd icesByClient);
309 else 309 else
310 ASSERT(!DisplayItem::isDrawingType(newDisplayItem.type()) || new DisplayItem.skippedCache() || !clientCacheIsValid(newDisplayItem.client())); 310 ASSERT(!DisplayItem::isDrawingType(newDisplayItem.type()) || new DisplayItem.skippedCache() || !clientCacheIsValid(newDisplayItem.client()));
311 #endif // ENABLE(ASSERT) 311 #endif // ENABLE(ASSERT)
312 updatedList.appendByMoving(newIt); 312 updatedList.appendByMoving(*newIt);
313 } 313 }
314 314
315 if (isSynchronized) 315 if (isSynchronized)
316 ++currentIt; 316 ++currentIt;
317 } 317 }
318 318
319 #if ENABLE(ASSERT) 319 #if ENABLE(ASSERT)
320 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) 320 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled())
321 checkNoRemainingCachedDisplayItems(); 321 checkNoRemainingCachedDisplayItems();
322 #endif // ENABLE(ASSERT) 322 #endif // ENABLE(ASSERT)
323 323
324 m_newDisplayItems.clear(); 324 m_newDisplayItems.clear();
325 m_validlyCachedClientsDirty = true; 325 m_validlyCachedClientsDirty = true;
326 m_currentDisplayItems.clear();
327 m_currentDisplayItems.swap(updatedList); 326 m_currentDisplayItems.swap(updatedList);
328 m_numCachedItems = 0; 327 m_numCachedItems = 0;
329 } 328 }
330 329
331 void DisplayItemList::updateValidlyCachedClientsIfNeeded() const 330 void DisplayItemList::updateValidlyCachedClientsIfNeeded() const
332 { 331 {
333 if (!m_validlyCachedClientsDirty) 332 if (!m_validlyCachedClientsDirty)
334 return; 333 return;
335 334
336 m_validlyCachedClients.clear(); 335 m_validlyCachedClients.clear();
337 m_validlyCachedClientsDirty = false; 336 m_validlyCachedClientsDirty = false;
338 337
339 DisplayItemClient lastClient = nullptr; 338 DisplayItemClient lastClient = nullptr;
340 for (const auto& displayItem : m_currentDisplayItems) { 339 for (const auto& displayItem : m_currentDisplayItems) {
341 if (displayItem.client() == lastClient) 340 if (displayItem->client() == lastClient)
342 continue; 341 continue;
343 lastClient = displayItem.client(); 342 lastClient = displayItem->client();
344 if (!displayItem.skippedCache()) 343 if (!displayItem->skippedCache())
345 m_validlyCachedClients.add(lastClient); 344 m_validlyCachedClients.add(lastClient);
346 } 345 }
347 } 346 }
348 347
349 void DisplayItemList::commitNewDisplayItemsAndAppendToWebDisplayItemList(WebDisp layItemList* list) 348 void DisplayItemList::commitNewDisplayItemsAndAppendToWebDisplayItemList(WebDisp layItemList* list)
350 { 349 {
351 commitNewDisplayItems(); 350 commitNewDisplayItems();
352 for (auto& item : m_currentDisplayItems) 351 for (const auto& item : m_currentDisplayItems)
353 item.appendToWebDisplayItemList(list); 352 item->appendToWebDisplayItemList(list);
354 } 353 }
355 354
356 #if ENABLE(ASSERT) 355 #if ENABLE(ASSERT)
357 356
358 static void showUnderInvalidationError(const char* reason, const DisplayItems::I temHandle& displayItem) 357 static void showUnderInvalidationError(const char* reason, const DisplayItem& di splayItem)
359 { 358 {
360 #ifndef NDEBUG 359 #ifndef NDEBUG
361 WTFLogAlways("%s: %s\nSee http://crbug.com/450725.", reason, displayItem.asD ebugString().utf8().data()); 360 WTFLogAlways("%s: %s\nSee http://crbug.com/450725.", reason, displayItem.asD ebugString().utf8().data());
362 #else 361 #else
363 WTFLogAlways("%s. Run debug build to get more details\nSee http://crbug.com/ 450725.", reason); 362 WTFLogAlways("%s. Run debug build to get more details\nSee http://crbug.com/ 450725.", reason);
364 #endif // NDEBUG 363 #endif // NDEBUG
365 } 364 }
366 365
367 static bool bitmapIsAllZero(const SkBitmap& bitmap) 366 static bool bitmapIsAllZero(const SkBitmap& bitmap)
368 { 367 {
369 bitmap.lockPixels(); 368 bitmap.lockPixels();
370 bool result = true; 369 bool result = true;
371 for (int x = 0; result && x < bitmap.width(); ++x) { 370 for (int x = 0; result && x < bitmap.width(); ++x) {
372 for (int y = 0; result && y < bitmap.height(); ++y) { 371 for (int y = 0; result && y < bitmap.height(); ++y) {
373 if (SkColorSetA(bitmap.getColor(x, y), 0) != SK_ColorTRANSPARENT) 372 if (SkColorSetA(bitmap.getColor(x, y), 0) != SK_ColorTRANSPARENT)
374 result = false; 373 result = false;
375 } 374 }
376 } 375 }
377 bitmap.unlockPixels(); 376 bitmap.unlockPixels();
378 return result; 377 return result;
379 } 378 }
380 379
381 void DisplayItemList::checkCachedDisplayItemIsUnchanged(const DisplayItems::Item Handle& displayItem, DisplayItemIndicesByClientMap& displayItemIndicesByClient) 380 void DisplayItemList::checkCachedDisplayItemIsUnchanged(const DisplayItem& displ ayItem, DisplayItemIndicesByClientMap& displayItemIndicesByClient)
382 { 381 {
383 ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled ()); 382 ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled ());
384 383
385 if (!DisplayItem::isDrawingType(displayItem.type()) || displayItem.skippedCa che() || !clientCacheIsValid(displayItem.client())) 384 if (!DisplayItem::isDrawingType(displayItem.type()) || displayItem.skippedCa che() || !clientCacheIsValid(displayItem.client()))
386 return; 385 return;
387 386
388 // If checking under-invalidation, we always generate new display item even if the client is not invalidated. 387 // 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 388 // 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. 389 // the client is not invalidated, issue error about under-invalidation.
391 size_t index = findMatchingItemFromIndex(displayItem.id(), displayItem.type( ), displayItemIndicesByClient, m_currentDisplayItems); 390 size_t index = findMatchingItemFromIndex(displayItem.id(), displayItem.type( ), displayItemIndicesByClient, m_currentDisplayItems);
392 if (index == kNotFound) { 391 if (index == kNotFound) {
393 showUnderInvalidationError("ERROR: under-invalidation: no cached display item", displayItem); 392 showUnderInvalidationError("ERROR: under-invalidation: no cached display item", displayItem);
394 ASSERT_NOT_REACHED(); 393 ASSERT_NOT_REACHED();
395 return; 394 return;
396 } 395 }
397 396
398 DisplayItems::Iterator foundItem = m_currentDisplayItems.iteratorAt(index); 397 DisplayItems::Iterator foundItem = m_currentDisplayItems.iteratorAt(index);
399 RefPtr<const SkPicture> newPicture = displayItem.picture(); 398 RefPtr<const SkPicture> newPicture = static_cast<const DrawingDisplayItem&>( displayItem).picture();
400 RefPtr<const SkPicture> oldPicture = foundItem->picture(); 399 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. 400 // 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); 401 foundItem->setIgnoredFromDisplayList();
403 402
404 if (!newPicture && !oldPicture) 403 if (!newPicture && !oldPicture)
405 return; 404 return;
406 if (newPicture && oldPicture) { 405 if (newPicture && oldPicture) {
407 switch (displayItem.underInvalidationCheckingMode()) { 406 switch (static_cast<const DrawingDisplayItem&>(displayItem).underInvalid ationCheckingMode()) {
408 case DrawingDisplayItem::CheckPicture: 407 case DrawingDisplayItem::CheckPicture:
409 if (newPicture->approximateOpCount() == oldPicture->approximateOpCou nt()) { 408 if (newPicture->approximateOpCount() == oldPicture->approximateOpCou nt()) {
410 SkDynamicMemoryWStream newPictureSerialized; 409 SkDynamicMemoryWStream newPictureSerialized;
411 newPicture->serialize(&newPictureSerialized); 410 newPicture->serialize(&newPictureSerialized);
412 SkDynamicMemoryWStream oldPictureSerialized; 411 SkDynamicMemoryWStream oldPictureSerialized;
413 oldPicture->serialize(&oldPictureSerialized); 412 oldPicture->serialize(&oldPictureSerialized);
414 413
415 if (newPictureSerialized.bytesWritten() == oldPictureSerialized. bytesWritten()) { 414 if (newPictureSerialized.bytesWritten() == oldPictureSerialized. bytesWritten()) {
416 RefPtr<SkData> oldData = adoptRef(oldPictureSerialized.copyT oData()); 415 RefPtr<SkData> oldData = adoptRef(oldPictureSerialized.copyT oData());
417 RefPtr<SkData> newData = adoptRef(newPictureSerialized.copyT oData()); 416 RefPtr<SkData> newData = adoptRef(newPictureSerialized.copyT oData());
(...skipping 30 matching lines...) Expand all
448 #endif // NDEBUG 447 #endif // NDEBUG
449 448
450 ASSERT_NOT_REACHED(); 449 ASSERT_NOT_REACHED();
451 } 450 }
452 451
453 void DisplayItemList::checkNoRemainingCachedDisplayItems() 452 void DisplayItemList::checkNoRemainingCachedDisplayItems()
454 { 453 {
455 ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled ()); 454 ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled ());
456 455
457 for (const auto& displayItem : m_currentDisplayItems) { 456 for (const auto& displayItem : m_currentDisplayItems) {
458 if (displayItem.isGone() || !DisplayItem::isDrawingType(displayItem.type ()) || !clientCacheIsValid(displayItem.client())) 457 if (displayItem->ignoreFromDisplayList() || !DisplayItem::isDrawingType( displayItem->type()) || !clientCacheIsValid(displayItem->client()))
459 continue; 458 continue;
460 showUnderInvalidationError("May be under-invalidation: no new display it em", displayItem); 459 showUnderInvalidationError("May be under-invalidation: no new display it em", *displayItem);
461 } 460 }
462 } 461 }
463 462
464 #endif // ENABLE(ASSERT) 463 #endif // ENABLE(ASSERT)
465 464
466 #ifndef NDEBUG 465 #ifndef NDEBUG
467 466
468 WTF::String DisplayItemList::displayItemsAsDebugString(const DisplayItems& list) const 467 WTF::String DisplayItemList::displayItemsAsDebugString(const DisplayItems& list) const
469 { 468 {
470 StringBuilder stringBuilder; 469 StringBuilder stringBuilder;
471 size_t i = 0; 470 size_t i = 0;
472 for (auto it = list.begin(); it != list.end(); ++it, ++i) { 471 for (auto it = list.begin(); it != list.end(); ++it, ++i) {
473 DisplayItems::ItemHandle displayItem = list[i]; 472 const DisplayItem& displayItem = *list.elementAt(i);
474 if (i) 473 if (i)
475 stringBuilder.append(",\n"); 474 stringBuilder.append(",\n");
476 if (displayItem.isGone()) { 475 if (displayItem.ignoreFromDisplayList()) {
477 stringBuilder.append("null"); 476 stringBuilder.append("null");
478 continue; 477 continue;
479 } 478 }
480 stringBuilder.append(String::format("{index: %d, ", (int)i)); 479 stringBuilder.append(String::format("{index: %d, ", (int)i));
481 displayItem.dumpPropertiesAsDebugString(stringBuilder); 480 displayItem.dumpPropertiesAsDebugString(stringBuilder);
482 stringBuilder.append(", cacheIsValid: "); 481 stringBuilder.append(", cacheIsValid: ");
483 stringBuilder.append(clientCacheIsValid(displayItem.client()) ? "true" : "false"); 482 stringBuilder.append(clientCacheIsValid(displayItem.client()) ? "true" : "false");
484 stringBuilder.append('}'); 483 stringBuilder.append('}');
485 } 484 }
486 return stringBuilder.toString(); 485 return stringBuilder.toString();
487 } 486 }
488 487
489 void DisplayItemList::showDebugData() const 488 void DisplayItemList::showDebugData() const
490 { 489 {
491 WTFLogAlways("current display items: [%s]\n", displayItemsAsDebugString(m_cu rrentDisplayItems).utf8().data()); 490 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()); 491 WTFLogAlways("new display items: [%s]\n", displayItemsAsDebugString(m_newDis playItems).utf8().data());
493 } 492 }
494 493
495 #endif // ifndef NDEBUG 494 #endif // ifndef NDEBUG
496 495
497 void DisplayItemList::replay(GraphicsContext& context) const 496 void DisplayItemList::replay(GraphicsContext& context)
498 { 497 {
499 TRACE_EVENT0("blink,benchmark", "DisplayItemList::replay"); 498 TRACE_EVENT0("blink,benchmark", "DisplayItemList::replay");
500 ASSERT(m_newDisplayItems.isEmpty()); 499 ASSERT(m_newDisplayItems.empty());
501 for (auto& displayItem : m_currentDisplayItems) 500 for (auto displayItem : m_currentDisplayItems)
502 displayItem.replay(context); 501 displayItem->replay(context);
503 } 502 }
504 503
505 } // namespace blink 504 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698