OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |