| 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 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 66 ASSERT(!m_constructionDisabled); | 66 ASSERT(!m_constructionDisabled); |
| 67 ASSERT(!skippingCache() || !displayItem->isCached()); | 67 ASSERT(!skippingCache() || !displayItem->isCached()); |
| 68 | 68 |
| 69 if (displayItem->isCached()) | 69 if (displayItem->isCached()) |
| 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.size() >= 2 && displayItem->isEnd()) { | 74 if (m_newDisplayItems.size() >= 2 && displayItem->isEnd()) { |
| 75 const auto& beginDisplayItem = m_newDisplayItems[m_newDisplayItems.size(
) - 2]; | 75 const auto& beginDisplayItem = m_newDisplayItems[m_newDisplayItems.size(
) - 2]; |
| 76 if (beginDisplayItem.isBegin() && !beginDisplayItem.drawsContent()) | 76 if (beginDisplayItem.isBegin() && beginDisplayItem.type() != DisplayItem
::BeginSubsequence && !beginDisplayItem.drawsContent()) |
| 77 ASSERT(!displayItem->isEndAndPairedWith(beginDisplayItem.type())); | 77 ASSERT(!displayItem->isEndAndPairedWith(beginDisplayItem.type())); |
| 78 } | 78 } |
| 79 #endif | 79 #endif |
| 80 | 80 |
| 81 if (!m_scopeStack.isEmpty()) | 81 if (!m_scopeStack.isEmpty()) |
| 82 displayItem->setScope(m_scopeStack.last()); | 82 displayItem->setScope(m_scopeStack.last()); |
| 83 | 83 |
| 84 #if ENABLE(ASSERT) | 84 #if ENABLE(ASSERT) |
| 85 size_t index = findMatchingItemFromIndex(displayItem->nonCachedId(), m_newDi
splayItemIndicesByClient, m_newDisplayItems); | 85 size_t index = findMatchingItemFromIndex(displayItem->nonCachedId(), m_newDi
splayItemIndicesByClient, m_newDisplayItems); |
| 86 if (index != kNotFound) { | 86 if (index != kNotFound) { |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 171 OutOfOrderIndexContext(DisplayItems::iterator begin) : nextItemToIndex(begin
) { } | 171 OutOfOrderIndexContext(DisplayItems::iterator begin) : nextItemToIndex(begin
) { } |
| 172 | 172 |
| 173 DisplayItems::iterator nextItemToIndex; | 173 DisplayItems::iterator nextItemToIndex; |
| 174 DisplayItemIndicesByClientMap displayItemIndicesByClient; | 174 DisplayItemIndicesByClientMap displayItemIndicesByClient; |
| 175 }; | 175 }; |
| 176 | 176 |
| 177 DisplayItems::iterator DisplayItemList::findOutOfOrderCachedItem(DisplayItems::i
terator currentIt, const DisplayItem::Id& id, OutOfOrderIndexContext& context) | 177 DisplayItems::iterator DisplayItemList::findOutOfOrderCachedItem(DisplayItems::i
terator currentIt, const DisplayItem::Id& id, OutOfOrderIndexContext& context) |
| 178 { | 178 { |
| 179 ASSERT(clientCacheIsValid(id.client)); | 179 ASSERT(clientCacheIsValid(id.client)); |
| 180 | 180 |
| 181 // Skip indexing of copied items. | |
| 182 if (currentIt - context.nextItemToIndex > 0) | |
| 183 context.nextItemToIndex = currentIt; | |
| 184 | |
| 185 size_t foundIndex = findMatchingItemFromIndex(id, context.displayItemIndices
ByClient, m_currentDisplayItems); | 181 size_t foundIndex = findMatchingItemFromIndex(id, context.displayItemIndices
ByClient, m_currentDisplayItems); |
| 186 if (foundIndex != kNotFound) | 182 if (foundIndex != kNotFound) |
| 187 return m_currentDisplayItems.begin() + foundIndex; | 183 return m_currentDisplayItems.begin() + foundIndex; |
| 188 | 184 |
| 189 return findOutOfOrderCachedItemForward(id, context); | 185 return findOutOfOrderCachedItemForward(currentIt, id, context); |
| 190 } | 186 } |
| 191 | 187 |
| 192 // Find forward for the item and index all skipped indexable items. | 188 // Find forward for the item and index all skipped indexable items. |
| 193 DisplayItems::iterator DisplayItemList::findOutOfOrderCachedItemForward(const Di
splayItem::Id& id, OutOfOrderIndexContext& context) | 189 DisplayItems::iterator DisplayItemList::findOutOfOrderCachedItemForward(DisplayI
tems::iterator currentIt, const DisplayItem::Id& id, OutOfOrderIndexContext& con
text) |
| 194 { | 190 { |
| 191 // Items before currentIt should have been copied. Skip indexing of them. |
| 192 if (currentIt - context.nextItemToIndex > 0) |
| 193 context.nextItemToIndex = currentIt; |
| 194 |
| 195 DisplayItems::iterator currentEnd = m_currentDisplayItems.end(); | 195 DisplayItems::iterator currentEnd = m_currentDisplayItems.end(); |
| 196 for (; context.nextItemToIndex != currentEnd; ++context.nextItemToIndex) { | 196 for (; context.nextItemToIndex != currentEnd; ++context.nextItemToIndex) { |
| 197 const DisplayItem& item = *context.nextItemToIndex; | 197 const DisplayItem& item = *context.nextItemToIndex; |
| 198 ASSERT(item.isValid()); | 198 ASSERT(item.isValid()); |
| 199 if (item.isCacheable() && clientCacheIsValid(item.client())) { | 199 if (item.isCacheable() && clientCacheIsValid(item.client())) { |
| 200 if (id.matches(item)) | 200 if (id.matches(item)) |
| 201 return context.nextItemToIndex++; | 201 return context.nextItemToIndex++; |
| 202 | 202 |
| 203 addItemToIndexIfNeeded(item, context.nextItemToIndex - m_currentDisp
layItems.begin(), context.displayItemIndicesByClient); | 203 addItemToIndexIfNeeded(item, context.nextItemToIndex - m_currentDisp
layItems.begin(), context.displayItemIndicesByClient); |
| 204 } | 204 } |
| 205 } | 205 } |
| 206 return currentEnd; | 206 return currentEnd; |
| 207 } | 207 } |
| 208 | 208 |
| 209 void DisplayItemList::copyCachedSubtree(DisplayItems::iterator& currentIt, Displ
ayItems& updatedList) | 209 void DisplayItemList::copyCachedSubsequence(DisplayItems::iterator& currentIt, D
isplayItems& updatedList) |
| 210 { | 210 { |
| 211 ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); | 211 ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); |
| 212 ASSERT(currentIt->isBeginSubtree()); | 212 ASSERT(currentIt->type() == DisplayItem::BeginSubsequence); |
| 213 ASSERT(!currentIt->scope()); | 213 ASSERT(!currentIt->scope()); |
| 214 DisplayItem::Id endSubtreeId(currentIt->client(), DisplayItem::beginSubtreeT
ypeToEndSubtreeType(currentIt->type()), 0); | 214 DisplayItem::Id endSubsequenceId(currentIt->client(), DisplayItem::EndSubseq
uence, 0); |
| 215 do { | 215 do { |
| 216 // We should always find the EndSubtree display item. | 216 // We should always find the EndSubsequence display item. |
| 217 ASSERT(currentIt != m_currentDisplayItems.end()); | 217 ASSERT(currentIt != m_currentDisplayItems.end()); |
| 218 updatedList.appendByMoving(*currentIt, currentIt->derivedSize()); | 218 updatedList.appendByMoving(*currentIt, currentIt->derivedSize()); |
| 219 ++currentIt; | 219 ++currentIt; |
| 220 } while (!endSubtreeId.matches(updatedList.last())); | 220 } while (!endSubsequenceId.matches(updatedList.last())); |
| 221 } | 221 } |
| 222 | 222 |
| 223 // Update the existing display items by removing invalidated entries, updating | 223 // Update the existing display items by removing invalidated entries, updating |
| 224 // repainted ones, and appending new items. | 224 // repainted ones, and appending new items. |
| 225 // - For CachedDisplayItem, copy the corresponding cached DrawingDisplayItem; | 225 // - For CachedDisplayItem, copy the corresponding cached DrawingDisplayItem; |
| 226 // - For SubtreeCachedDisplayItem, copy the cached display items between the | 226 // - For SubsequenceCachedDisplayItem, copy the cached display items between the |
| 227 // corresponding BeginSubtreeDisplayItem and EndSubtreeDisplayItem (incl.); | 227 // corresponding BeginSubsequenceDisplayItem and EndSubsequenceDisplayItem (in
cl.); |
| 228 // - Otherwise, copy the new display item. | 228 // - Otherwise, copy the new display item. |
| 229 // | 229 // |
| 230 // The algorithm is O(|m_currentDisplayItems| + |m_newDisplayItems|). | 230 // The algorithm is O(|m_currentDisplayItems| + |m_newDisplayItems|). |
| 231 // Coefficients are related to the ratio of out-of-order [Subtree]CachedDisplayI
tems | 231 // Coefficients are related to the ratio of out-of-order [Subsequence]CachedDisp
layItems |
| 232 // and the average number of (Drawing|BeginSubtree)DisplayItems per client. | 232 // and the average number of (Drawing|BeginSubsequence)DisplayItems per client. |
| 233 // | 233 // |
| 234 // TODO(pdr): Implement the DisplayListDiff algorithm for SlimmingPaintV2. | 234 // TODO(pdr): Implement the DisplayListDiff algorithm for SlimmingPaintV2. |
| 235 void DisplayItemList::commitNewDisplayItems(DisplayListDiff*) | 235 void DisplayItemList::commitNewDisplayItems(DisplayListDiff*) |
| 236 { | 236 { |
| 237 TRACE_EVENT2("blink,benchmark", "DisplayItemList::commitNewDisplayItems", "c
urrent_display_list_size", (int)m_currentDisplayItems.size(), | 237 TRACE_EVENT2("blink,benchmark", "DisplayItemList::commitNewDisplayItems", "c
urrent_display_list_size", (int)m_currentDisplayItems.size(), |
| 238 "num_non_cached_new_items", (int)m_newDisplayItems.size() - m_numCachedI
tems); | 238 "num_non_cached_new_items", (int)m_newDisplayItems.size() - m_numCachedI
tems); |
| 239 | 239 |
| 240 // These data structures are used during painting only. | 240 // These data structures are used during painting only. |
| 241 ASSERT(m_scopeStack.isEmpty()); | 241 ASSERT(m_scopeStack.isEmpty()); |
| 242 m_scopeStack.clear(); | 242 m_scopeStack.clear(); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 288 const DisplayItem::Id newDisplayItemId = newDisplayItem.nonCachedId(); | 288 const DisplayItem::Id newDisplayItemId = newDisplayItem.nonCachedId(); |
| 289 bool newDisplayItemHasCachedType = newDisplayItem.type() != newDisplayIt
emId.type; | 289 bool newDisplayItemHasCachedType = newDisplayItem.type() != newDisplayIt
emId.type; |
| 290 | 290 |
| 291 bool isSynchronized = currentIt != currentEnd && newDisplayItemId.matche
s(*currentIt); | 291 bool isSynchronized = currentIt != currentEnd && newDisplayItemId.matche
s(*currentIt); |
| 292 | 292 |
| 293 if (newDisplayItemHasCachedType) { | 293 if (newDisplayItemHasCachedType) { |
| 294 ASSERT(!RuntimeEnabledFeatures::slimmingPaintUnderInvalidationChecki
ngEnabled()); | 294 ASSERT(!RuntimeEnabledFeatures::slimmingPaintUnderInvalidationChecki
ngEnabled()); |
| 295 ASSERT(newDisplayItem.isCached()); | 295 ASSERT(newDisplayItem.isCached()); |
| 296 ASSERT(clientCacheIsValid(newDisplayItem.client())); | 296 ASSERT(clientCacheIsValid(newDisplayItem.client())); |
| 297 if (!isSynchronized) { | 297 if (!isSynchronized) { |
| 298 DisplayItems::iterator foundIt = findOutOfOrderCachedItem(curren
tIt, newDisplayItemId, outOfOrderIndexContext); | 298 currentIt = findOutOfOrderCachedItem(currentIt, newDisplayItemId
, outOfOrderIndexContext); |
| 299 | 299 |
| 300 if (foundIt == currentEnd) { | 300 if (currentIt == currentEnd) { |
| 301 #ifndef NDEBUG | 301 #ifndef NDEBUG |
| 302 showDebugData(); | 302 showDebugData(); |
| 303 WTFLogAlways("%s not found in m_currentDisplayItems\n", newD
isplayItem.asDebugString().utf8().data()); | 303 WTFLogAlways("%s not found in m_currentDisplayItems\n", newD
isplayItem.asDebugString().utf8().data()); |
| 304 #endif | 304 #endif |
| 305 ASSERT_NOT_REACHED(); | 305 ASSERT_NOT_REACHED(); |
| 306 | 306 // We did not find the cached display item. This should be i
mpossible, but may occur if there is a bug |
| 307 // If foundIt == currentEnd, it means that we did not find t
he cached display item. This should be impossible, but may occur | 307 // in the system, such as under-invalidation, incorrect cach
e checking or duplicate display ids. |
| 308 // if there is a bug in the system, such as under-invalidati
on, incorrect cache checking or duplicate display ids. In this case, | 308 // In this case, attempt to recover rather than crashing or
bailing on display of the rest of the display list. |
| 309 // attempt to recover rather than crashing or bailing on dis
play of the rest of the display list. | |
| 310 continue; | 309 continue; |
| 311 } | 310 } |
| 312 | |
| 313 ASSERT(foundIt != currentIt); // because we are in 'if (!isSynch
ronized)' | |
| 314 currentIt = foundIt; | |
| 315 } | 311 } |
| 316 | 312 |
| 317 if (newDisplayItem.isCachedDrawing()) { | 313 if (newDisplayItem.isCachedDrawing()) { |
| 318 updatedList.appendByMoving(*currentIt, currentIt->derivedSize())
; | 314 updatedList.appendByMoving(*currentIt, currentIt->derivedSize())
; |
| 319 ++currentIt; | 315 ++currentIt; |
| 320 } else { | 316 } else { |
| 321 ASSERT(newDisplayItem.isCachedSubtree()); | 317 ASSERT(newDisplayItem.type() == DisplayItem::CachedSubsequence); |
| 322 copyCachedSubtree(currentIt, updatedList); | 318 copyCachedSubsequence(currentIt, updatedList); |
| 323 ASSERT(updatedList.last().isEndSubtree()); | 319 ASSERT(updatedList.last().type() == DisplayItem::EndSubsequence)
; |
| 324 } | 320 } |
| 325 } else { | 321 } else { |
| 326 #if ENABLE(ASSERT) | 322 #if ENABLE(ASSERT) |
| 327 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEn
abled()) | 323 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEn
abled()) |
| 328 checkCachedDisplayItemIsUnchanged(newDisplayItem, outOfOrderInde
xContext.displayItemIndicesByClient); | 324 checkCachedDisplayItemIsUnchanged(newDisplayItem, outOfOrderInde
xContext.displayItemIndicesByClient); |
| 329 else | 325 else |
| 330 ASSERT(!newDisplayItem.isDrawing() || newDisplayItem.skippedCach
e() || !clientCacheIsValid(newDisplayItem.client())); | 326 ASSERT(!newDisplayItem.isDrawing() || newDisplayItem.skippedCach
e() || !clientCacheIsValid(newDisplayItem.client())); |
| 331 #endif // ENABLE(ASSERT) | 327 #endif // ENABLE(ASSERT) |
| 332 updatedList.appendByMoving(*newIt, newIt->derivedSize()); | 328 updatedList.appendByMoving(*newIt, newIt->derivedSize()); |
| 333 | 329 |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 545 | 541 |
| 546 void DisplayItemList::replay(GraphicsContext& context) | 542 void DisplayItemList::replay(GraphicsContext& context) |
| 547 { | 543 { |
| 548 TRACE_EVENT0("blink,benchmark", "DisplayItemList::replay"); | 544 TRACE_EVENT0("blink,benchmark", "DisplayItemList::replay"); |
| 549 ASSERT(m_newDisplayItems.isEmpty()); | 545 ASSERT(m_newDisplayItems.isEmpty()); |
| 550 for (DisplayItem& displayItem : m_currentDisplayItems) | 546 for (DisplayItem& displayItem : m_currentDisplayItems) |
| 551 displayItem.replay(context); | 547 displayItem.replay(context); |
| 552 } | 548 } |
| 553 | 549 |
| 554 } // namespace blink | 550 } // namespace blink |
| OLD | NEW |