| 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 18 matching lines...) Expand all Loading... |
| 29 { | 29 { |
| 30 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled()); | 30 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled()); |
| 31 ASSERT(m_newDisplayItems.isEmpty()); | 31 ASSERT(m_newDisplayItems.isEmpty()); |
| 32 return m_currentDisplayItems; | 32 return m_currentDisplayItems; |
| 33 } | 33 } |
| 34 | 34 |
| 35 void DisplayItemList::add(WTF::PassOwnPtr<DisplayItem> displayItem) | 35 void DisplayItemList::add(WTF::PassOwnPtr<DisplayItem> displayItem) |
| 36 { | 36 { |
| 37 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled()); | 37 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled()); |
| 38 ASSERT(!m_constructionDisabled); | 38 ASSERT(!m_constructionDisabled); |
| 39 ASSERT(!skippingCache() || !displayItem->isCached()); |
| 39 | 40 |
| 40 if (displayItem->isEnd()) { | 41 if (displayItem->isEnd()) { |
| 41 ASSERT(!m_newDisplayItems.isEmpty()); | 42 ASSERT(!m_newDisplayItems.isEmpty()); |
| 42 if (m_newDisplayItems.last()->isBegin() && !m_newDisplayItems.last()->dr
awsContent()) { | 43 if (m_newDisplayItems.last()->isBegin() && !m_newDisplayItems.last()->dr
awsContent()) { |
| 43 ASSERT(displayItem->isEndAndPairedWith(*m_newDisplayItems.last())); | 44 ASSERT(displayItem->isEndAndPairedWith(*m_newDisplayItems.last())); |
| 44 // Remove the beginning display item of this empty pair. | 45 // Remove the beginning display item of this empty pair. |
| 45 m_newDisplayItems.removeLast(); | 46 m_newDisplayItems.removeLast(); |
| 46 #if ENABLE(ASSERT) | 47 #if ENABLE(ASSERT) |
| 47 // Also remove the index pointing to the removed display item. | 48 // Also remove the index pointing to the removed display item. |
| 48 DisplayItemIndicesByClientMap::iterator it = m_newDisplayItemIndices
ByClient.find(displayItem->client()); | 49 DisplayItemIndicesByClientMap::iterator it = m_newDisplayItemIndices
ByClient.find(displayItem->client()); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 63 size_t index = findMatchingItemFromIndex(*displayItem, displayItem->type(),
m_newDisplayItemIndicesByClient, m_newDisplayItems); | 64 size_t index = findMatchingItemFromIndex(*displayItem, displayItem->type(),
m_newDisplayItemIndicesByClient, m_newDisplayItems); |
| 64 if (index != kNotFound) { | 65 if (index != kNotFound) { |
| 65 #ifndef NDEBUG | 66 #ifndef NDEBUG |
| 66 showDebugData(); | 67 showDebugData(); |
| 67 WTFLogAlways("DisplayItem %s has duplicated id with previous %s (index=%
d)\n", | 68 WTFLogAlways("DisplayItem %s has duplicated id with previous %s (index=%
d)\n", |
| 68 displayItem->asDebugString().utf8().data(), m_newDisplayItems[index]
->asDebugString().utf8().data(), static_cast<int>(index)); | 69 displayItem->asDebugString().utf8().data(), m_newDisplayItems[index]
->asDebugString().utf8().data(), static_cast<int>(index)); |
| 69 #endif | 70 #endif |
| 70 ASSERT_NOT_REACHED(); | 71 ASSERT_NOT_REACHED(); |
| 71 } | 72 } |
| 72 addItemToIndex(*displayItem, m_newDisplayItems.size(), m_newDisplayItemIndic
esByClient); | 73 addItemToIndex(*displayItem, m_newDisplayItems.size(), m_newDisplayItemIndic
esByClient); |
| 73 #endif | 74 #endif // ENABLE(ASSERT) |
| 75 |
| 76 ASSERT(!displayItem->skippedCache()); // Only DisplayItemList can set the fl
ag. |
| 77 if (skippingCache()) |
| 78 displayItem->setSkippedCache(); |
| 74 | 79 |
| 75 m_newDisplayItems.append(displayItem); | 80 m_newDisplayItems.append(displayItem); |
| 76 } | 81 } |
| 77 | 82 |
| 78 void DisplayItemList::beginScope(DisplayItemClient client) | 83 void DisplayItemList::beginScope(DisplayItemClient client) |
| 79 { | 84 { |
| 80 ClientScopeIdMap::iterator it = m_clientScopeIdMap.find(client); | 85 ClientScopeIdMap::iterator it = m_clientScopeIdMap.find(client); |
| 81 int scopeId; | 86 int scopeId; |
| 82 if (it == m_clientScopeIdMap.end()) { | 87 if (it == m_clientScopeIdMap.end()) { |
| 83 m_clientScopeIdMap.add(client, 0); | 88 m_clientScopeIdMap.add(client, 0); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 107 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled()); | 112 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled()); |
| 108 // Can only be called during layout/paintInvalidation, not during painting. | 113 // Can only be called during layout/paintInvalidation, not during painting. |
| 109 ASSERT(m_newDisplayItems.isEmpty()); | 114 ASSERT(m_newDisplayItems.isEmpty()); |
| 110 m_currentDisplayItems.clear(); | 115 m_currentDisplayItems.clear(); |
| 111 m_validlyCachedClients.clear(); | 116 m_validlyCachedClients.clear(); |
| 112 m_validlyCachedClientsDirty = false; | 117 m_validlyCachedClientsDirty = false; |
| 113 } | 118 } |
| 114 | 119 |
| 115 bool DisplayItemList::clientCacheIsValid(DisplayItemClient client) const | 120 bool DisplayItemList::clientCacheIsValid(DisplayItemClient client) const |
| 116 { | 121 { |
| 122 if (skippingCache()) |
| 123 return false; |
| 117 updateValidlyCachedClientsIfNeeded(); | 124 updateValidlyCachedClientsIfNeeded(); |
| 118 return m_validlyCachedClients.contains(client); | 125 return m_validlyCachedClients.contains(client); |
| 119 } | 126 } |
| 120 | 127 |
| 121 size_t DisplayItemList::findMatchingItemFromIndex(const DisplayItem& displayItem
, DisplayItem::Type matchingType, const DisplayItemIndicesByClientMap& displayIt
emIndicesByClient, const DisplayItems& list) | 128 size_t DisplayItemList::findMatchingItemFromIndex(const DisplayItem& displayItem
, DisplayItem::Type matchingType, const DisplayItemIndicesByClientMap& displayIt
emIndicesByClient, const DisplayItems& list) |
| 122 { | 129 { |
| 123 DisplayItemIndicesByClientMap::const_iterator it = displayItemIndicesByClien
t.find(displayItem.client()); | 130 DisplayItemIndicesByClientMap::const_iterator it = displayItemIndicesByClien
t.find(displayItem.client()); |
| 124 if (it == displayItemIndicesByClient.end()) | 131 if (it == displayItemIndicesByClient.end()) |
| 125 return kNotFound; | 132 return kNotFound; |
| 126 | 133 |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 187 // Coefficients are related to the ratio of out-of-order [Subtree]CachedDisplayI
tems | 194 // Coefficients are related to the ratio of out-of-order [Subtree]CachedDisplayI
tems |
| 188 // and the average number of (Drawing|BeginSubtree)DisplayItems per client. | 195 // and the average number of (Drawing|BeginSubtree)DisplayItems per client. |
| 189 void DisplayItemList::commitNewDisplayItems() | 196 void DisplayItemList::commitNewDisplayItems() |
| 190 { | 197 { |
| 191 TRACE_EVENT0("blink,benchmark", "DisplayItemList::commitNewDisplayItems"); | 198 TRACE_EVENT0("blink,benchmark", "DisplayItemList::commitNewDisplayItems"); |
| 192 | 199 |
| 193 // These data structures are used during painting only. | 200 // These data structures are used during painting only. |
| 194 m_clientScopeIdMap.clear(); | 201 m_clientScopeIdMap.clear(); |
| 195 ASSERT(m_scopeStack.isEmpty()); | 202 ASSERT(m_scopeStack.isEmpty()); |
| 196 m_scopeStack.clear(); | 203 m_scopeStack.clear(); |
| 204 ASSERT(!skippingCache()); |
| 197 #if ENABLE(ASSERT) | 205 #if ENABLE(ASSERT) |
| 198 m_newDisplayItemIndicesByClient.clear(); | 206 m_newDisplayItemIndicesByClient.clear(); |
| 199 #endif | 207 #endif |
| 200 | 208 |
| 201 if (m_currentDisplayItems.isEmpty()) { | 209 if (m_currentDisplayItems.isEmpty()) { |
| 202 #if ENABLE(ASSERT) | 210 #if ENABLE(ASSERT) |
| 203 for (auto& item : m_newDisplayItems) | 211 for (auto& item : m_newDisplayItems) |
| 204 ASSERT(!item->isCached() && !item->isSubtreeCached()); | 212 ASSERT(!item->isCached() && !item->isSubtreeCached()); |
| 205 #endif | 213 #endif |
| 206 m_currentDisplayItems.swap(m_newDisplayItems); | 214 m_currentDisplayItems.swap(m_newDisplayItems); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 246 isSynchronized = (foundIndex == currentDisplayItemsIndex); | 254 isSynchronized = (foundIndex == currentDisplayItemsIndex); |
| 247 updatedList.append(m_currentDisplayItems[foundIndex].release
()); | 255 updatedList.append(m_currentDisplayItems[foundIndex].release
()); |
| 248 } | 256 } |
| 249 // else: do nothing because previously the client generated a em
pty picture which is not stored in the cache. | 257 // else: do nothing because previously the client generated a em
pty picture which is not stored in the cache. |
| 250 } | 258 } |
| 251 } else { | 259 } else { |
| 252 #if ENABLE(ASSERT) | 260 #if ENABLE(ASSERT) |
| 253 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEn
abled()) | 261 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEn
abled()) |
| 254 checkCachedDisplayItemIsUnchanged(*newDisplayItem, displayItemIn
dicesByClient); | 262 checkCachedDisplayItemIsUnchanged(*newDisplayItem, displayItemIn
dicesByClient); |
| 255 else | 263 else |
| 256 ASSERT(!newDisplayItem->isDrawing() || !clientCacheIsValid(newDi
splayItem->client())); | 264 ASSERT(!newDisplayItem->isDrawing() || newDisplayItem->skippedCa
che() || !clientCacheIsValid(newDisplayItem->client())); |
| 257 #endif // ENABLE(ASSERT) | 265 #endif // ENABLE(ASSERT) |
| 258 updatedList.append(newDisplayItem.release()); | 266 updatedList.append(newDisplayItem.release()); |
| 259 } | 267 } |
| 260 | 268 |
| 261 if (isSynchronized) | 269 if (isSynchronized) |
| 262 ++currentDisplayItemsIndex; | 270 ++currentDisplayItemsIndex; |
| 263 } | 271 } |
| 264 | 272 |
| 265 #if ENABLE(ASSERT) | 273 #if ENABLE(ASSERT) |
| 266 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) | 274 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) |
| (...skipping 12 matching lines...) Expand all Loading... |
| 279 return; | 287 return; |
| 280 | 288 |
| 281 m_validlyCachedClients.clear(); | 289 m_validlyCachedClients.clear(); |
| 282 m_validlyCachedClientsDirty = false; | 290 m_validlyCachedClientsDirty = false; |
| 283 | 291 |
| 284 DisplayItemClient lastClient = nullptr; | 292 DisplayItemClient lastClient = nullptr; |
| 285 for (const auto& displayItem : m_currentDisplayItems) { | 293 for (const auto& displayItem : m_currentDisplayItems) { |
| 286 if (displayItem->client() == lastClient) | 294 if (displayItem->client() == lastClient) |
| 287 continue; | 295 continue; |
| 288 lastClient = displayItem->client(); | 296 lastClient = displayItem->client(); |
| 289 m_validlyCachedClients.add(lastClient); | 297 if (!displayItem->skippedCache()) |
| 298 m_validlyCachedClients.add(lastClient); |
| 290 } | 299 } |
| 291 } | 300 } |
| 292 | 301 |
| 293 #if ENABLE(ASSERT) | 302 #if ENABLE(ASSERT) |
| 294 | 303 |
| 295 static void showUnderInvalidationError(const char* reason, const DisplayItem& di
splayItem) | 304 static void showUnderInvalidationError(const char* reason, const DisplayItem& di
splayItem) |
| 296 { | 305 { |
| 297 #ifndef NDEBUG | 306 #ifndef NDEBUG |
| 298 WTFLogAlways("%s: %s\nSee http://crbug.com/450725.", reason, displayItem.asD
ebugString().utf8().data()); | 307 WTFLogAlways("%s: %s\nSee http://crbug.com/450725.", reason, displayItem.asD
ebugString().utf8().data()); |
| 299 #else | 308 #else |
| (...skipping 15 matching lines...) Expand all Loading... |
| 315 return result; | 324 return result; |
| 316 } | 325 } |
| 317 | 326 |
| 318 void DisplayItemList::checkCachedDisplayItemIsUnchanged(const DisplayItem& displ
ayItem, DisplayItemIndicesByClientMap& displayItemIndicesByClient) | 327 void DisplayItemList::checkCachedDisplayItemIsUnchanged(const DisplayItem& displ
ayItem, DisplayItemIndicesByClientMap& displayItemIndicesByClient) |
| 319 { | 328 { |
| 320 ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled
()); | 329 ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled
()); |
| 321 | 330 |
| 322 if (!displayItem.isDrawing() || !clientCacheIsValid(displayItem.client())) | 331 if (!displayItem.isDrawing() || !clientCacheIsValid(displayItem.client())) |
| 323 return; | 332 return; |
| 324 | 333 |
| 325 DrawingDisplayItem::UnderInvalidationCheckingMode mode = static_cast<const D
rawingDisplayItem&>(displayItem).underInvalidationCheckingMode(); | 334 const DrawingDisplayItem& drawingDisplayItem = static_cast<const DrawingDisp
layItem&>(displayItem); |
| 335 if (drawingDisplayItem.skippedCache()) |
| 336 return; |
| 337 |
| 338 DrawingDisplayItem::UnderInvalidationCheckingMode mode = drawingDisplayItem.
underInvalidationCheckingMode(); |
| 326 if (mode == DrawingDisplayItem::DontCheck) | 339 if (mode == DrawingDisplayItem::DontCheck) |
| 327 return; | 340 return; |
| 328 | 341 |
| 329 // If checking under-invalidation, we always generate new display item even
if the client is not invalidated. | 342 // If checking under-invalidation, we always generate new display item even
if the client is not invalidated. |
| 330 // Checks if the new picture is the same as the cached old picture. If the n
ew picture is different but | 343 // Checks if the new picture is the same as the cached old picture. If the n
ew picture is different but |
| 331 // the client is not invalidated, issue error about under-invalidation. | 344 // the client is not invalidated, issue error about under-invalidation. |
| 332 size_t index = findMatchingItemFromIndex(displayItem, displayItem.type(), di
splayItemIndicesByClient, m_currentDisplayItems); | 345 size_t index = findMatchingItemFromIndex(displayItem, displayItem.type(), di
splayItemIndicesByClient, m_currentDisplayItems); |
| 333 if (index == kNotFound) { | 346 if (index == kNotFound) { |
| 334 showUnderInvalidationError("ERROR: under-invalidation: no cached display
item", displayItem); | 347 showUnderInvalidationError("ERROR: under-invalidation: no cached display
item", displayItem); |
| 335 ASSERT_NOT_REACHED(); | 348 ASSERT_NOT_REACHED(); |
| 336 return; | 349 return; |
| 337 } | 350 } |
| 338 | 351 |
| 339 RefPtr<const SkPicture> newPicture = static_cast<const DrawingDisplayItem&>(
displayItem).picture(); | 352 RefPtr<const SkPicture> newPicture = drawingDisplayItem.picture(); |
| 340 RefPtr<const SkPicture> oldPicture = static_cast<const DrawingDisplayItem&>(
*m_currentDisplayItems[index]).picture(); | 353 RefPtr<const SkPicture> oldPicture = static_cast<const DrawingDisplayItem&>(
*m_currentDisplayItems[index]).picture(); |
| 341 // Remove the display item from cache so that we can check if there are any
remaining cached display items after merging. | 354 // Remove the display item from cache so that we can check if there are any
remaining cached display items after merging. |
| 342 m_currentDisplayItems[index] = nullptr; | 355 m_currentDisplayItems[index] = nullptr; |
| 343 | 356 |
| 344 if (!newPicture && !oldPicture) | 357 if (!newPicture && !oldPicture) |
| 345 return; | 358 return; |
| 346 if (newPicture && oldPicture) { | 359 if (newPicture && oldPicture) { |
| 347 switch (mode) { | 360 switch (mode) { |
| 348 case DrawingDisplayItem::CheckPicture: | 361 case DrawingDisplayItem::CheckPicture: |
| 349 if (newPicture->approximateOpCount() == oldPicture->approximateOpCou
nt()) { | 362 if (newPicture->approximateOpCount() == oldPicture->approximateOpCou
nt()) { |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 435 | 448 |
| 436 void DisplayItemList::replay(GraphicsContext& context) const | 449 void DisplayItemList::replay(GraphicsContext& context) const |
| 437 { | 450 { |
| 438 TRACE_EVENT0("blink,benchmark", "DisplayItemList::replay"); | 451 TRACE_EVENT0("blink,benchmark", "DisplayItemList::replay"); |
| 439 ASSERT(m_newDisplayItems.isEmpty()); | 452 ASSERT(m_newDisplayItems.isEmpty()); |
| 440 for (auto& displayItem : m_currentDisplayItems) | 453 for (auto& displayItem : m_currentDisplayItems) |
| 441 displayItem->replay(context); | 454 displayItem->replay(context); |
| 442 } | 455 } |
| 443 | 456 |
| 444 } // namespace blink | 457 } // namespace blink |
| OLD | NEW |