Chromium Code Reviews| 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 | |
|
chrishtr
2015/06/02 20:58:37
ASSERT(!displayItem.skippedCache()); // random co
Xianzhu
2015/06/02 21:10:32
Added the assert. It's reasonable to allow only Di
| |
| 76 if (skippingCache()) | |
| 77 displayItem->setSkippedCache(); | |
| 74 | 78 |
| 75 m_newDisplayItems.append(displayItem); | 79 m_newDisplayItems.append(displayItem); |
| 76 } | 80 } |
| 77 | 81 |
| 78 void DisplayItemList::beginScope(DisplayItemClient client) | 82 void DisplayItemList::beginScope(DisplayItemClient client) |
| 79 { | 83 { |
| 80 ClientScopeIdMap::iterator it = m_clientScopeIdMap.find(client); | 84 ClientScopeIdMap::iterator it = m_clientScopeIdMap.find(client); |
| 81 int scopeId; | 85 int scopeId; |
| 82 if (it == m_clientScopeIdMap.end()) { | 86 if (it == m_clientScopeIdMap.end()) { |
| 83 m_clientScopeIdMap.add(client, 0); | 87 m_clientScopeIdMap.add(client, 0); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 107 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled()); | 111 ASSERT(RuntimeEnabledFeatures::slimmingPaintEnabled()); |
| 108 // Can only be called during layout/paintInvalidation, not during painting. | 112 // Can only be called during layout/paintInvalidation, not during painting. |
| 109 ASSERT(m_newDisplayItems.isEmpty()); | 113 ASSERT(m_newDisplayItems.isEmpty()); |
| 110 m_currentDisplayItems.clear(); | 114 m_currentDisplayItems.clear(); |
| 111 m_validlyCachedClients.clear(); | 115 m_validlyCachedClients.clear(); |
| 112 m_validlyCachedClientsDirty = false; | 116 m_validlyCachedClientsDirty = false; |
| 113 } | 117 } |
| 114 | 118 |
| 115 bool DisplayItemList::clientCacheIsValid(DisplayItemClient client) const | 119 bool DisplayItemList::clientCacheIsValid(DisplayItemClient client) const |
| 116 { | 120 { |
| 121 if (skippingCache()) | |
| 122 return false; | |
| 117 updateValidlyCachedClientsIfNeeded(); | 123 updateValidlyCachedClientsIfNeeded(); |
| 118 return m_validlyCachedClients.contains(client); | 124 return m_validlyCachedClients.contains(client); |
| 119 } | 125 } |
| 120 | 126 |
| 121 size_t DisplayItemList::findMatchingItemFromIndex(const DisplayItem& displayItem , DisplayItem::Type matchingType, const DisplayItemIndicesByClientMap& displayIt emIndicesByClient, const DisplayItems& list) | 127 size_t DisplayItemList::findMatchingItemFromIndex(const DisplayItem& displayItem , DisplayItem::Type matchingType, const DisplayItemIndicesByClientMap& displayIt emIndicesByClient, const DisplayItems& list) |
| 122 { | 128 { |
| 123 DisplayItemIndicesByClientMap::const_iterator it = displayItemIndicesByClien t.find(displayItem.client()); | 129 DisplayItemIndicesByClientMap::const_iterator it = displayItemIndicesByClien t.find(displayItem.client()); |
| 124 if (it == displayItemIndicesByClient.end()) | 130 if (it == displayItemIndicesByClient.end()) |
| 125 return kNotFound; | 131 return kNotFound; |
| 126 | 132 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 188 // and the average number of (Drawing|BeginSubtree)DisplayItems per client. | 194 // and the average number of (Drawing|BeginSubtree)DisplayItems per client. |
| 189 void DisplayItemList::commitNewDisplayItems() | 195 void DisplayItemList::commitNewDisplayItems() |
| 190 { | 196 { |
| 191 showDebugData(); | 197 showDebugData(); |
| 192 TRACE_EVENT0("blink,benchmark", "DisplayItemList::commitNewDisplayItems"); | 198 TRACE_EVENT0("blink,benchmark", "DisplayItemList::commitNewDisplayItems"); |
| 193 | 199 |
| 194 // These data structures are used during painting only. | 200 // These data structures are used during painting only. |
| 195 m_clientScopeIdMap.clear(); | 201 m_clientScopeIdMap.clear(); |
| 196 ASSERT(m_scopeStack.isEmpty()); | 202 ASSERT(m_scopeStack.isEmpty()); |
| 197 m_scopeStack.clear(); | 203 m_scopeStack.clear(); |
| 204 ASSERT(!skippingCache()); | |
| 198 #if ENABLE(ASSERT) | 205 #if ENABLE(ASSERT) |
| 199 m_newDisplayItemIndicesByClient.clear(); | 206 m_newDisplayItemIndicesByClient.clear(); |
| 200 #endif | 207 #endif |
| 201 | 208 |
| 202 if (m_currentDisplayItems.isEmpty()) { | 209 if (m_currentDisplayItems.isEmpty()) { |
| 203 #if ENABLE(ASSERT) | 210 #if ENABLE(ASSERT) |
| 204 for (auto& item : m_newDisplayItems) | 211 for (auto& item : m_newDisplayItems) |
| 205 ASSERT(!item->isCached() && !item->isSubtreeCached()); | 212 ASSERT(!item->isCached() && !item->isSubtreeCached()); |
| 206 #endif | 213 #endif |
| 207 m_currentDisplayItems.swap(m_newDisplayItems); | 214 m_currentDisplayItems.swap(m_newDisplayItems); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 247 isSynchronized = (foundIndex == currentDisplayItemsIndex); | 254 isSynchronized = (foundIndex == currentDisplayItemsIndex); |
| 248 updatedList.append(m_currentDisplayItems[foundIndex].release ()); | 255 updatedList.append(m_currentDisplayItems[foundIndex].release ()); |
| 249 } | 256 } |
| 250 // 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. |
| 251 } | 258 } |
| 252 } else { | 259 } else { |
| 253 #if ENABLE(ASSERT) | 260 #if ENABLE(ASSERT) |
| 254 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEn abled()) | 261 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEn abled()) |
| 255 checkCachedDisplayItemIsUnchanged(*newDisplayItem, displayItemIn dicesByClient); | 262 checkCachedDisplayItemIsUnchanged(*newDisplayItem, displayItemIn dicesByClient); |
| 256 else | 263 else |
| 257 ASSERT(!newDisplayItem->isDrawing() || !clientCacheIsValid(newDi splayItem->client())); | 264 ASSERT(!newDisplayItem->isDrawing() || newDisplayItem->skippedCa che() || !clientCacheIsValid(newDisplayItem->client())); |
| 258 #endif // ENABLE(ASSERT) | 265 #endif // ENABLE(ASSERT) |
| 259 updatedList.append(newDisplayItem.release()); | 266 updatedList.append(newDisplayItem.release()); |
| 260 } | 267 } |
| 261 | 268 |
| 262 if (isSynchronized) | 269 if (isSynchronized) |
| 263 ++currentDisplayItemsIndex; | 270 ++currentDisplayItemsIndex; |
| 264 } | 271 } |
| 265 | 272 |
| 266 #if ENABLE(ASSERT) | 273 #if ENABLE(ASSERT) |
| 267 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) | 274 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 280 return; | 287 return; |
| 281 | 288 |
| 282 m_validlyCachedClients.clear(); | 289 m_validlyCachedClients.clear(); |
| 283 m_validlyCachedClientsDirty = false; | 290 m_validlyCachedClientsDirty = false; |
| 284 | 291 |
| 285 DisplayItemClient lastClient = nullptr; | 292 DisplayItemClient lastClient = nullptr; |
| 286 for (const auto& displayItem : m_currentDisplayItems) { | 293 for (const auto& displayItem : m_currentDisplayItems) { |
| 287 if (displayItem->client() == lastClient) | 294 if (displayItem->client() == lastClient) |
| 288 continue; | 295 continue; |
| 289 lastClient = displayItem->client(); | 296 lastClient = displayItem->client(); |
| 290 m_validlyCachedClients.add(lastClient); | 297 if (!displayItem->skippedCache()) |
| 298 m_validlyCachedClients.add(lastClient); | |
| 291 } | 299 } |
| 292 } | 300 } |
| 293 | 301 |
| 294 #if ENABLE(ASSERT) | 302 #if ENABLE(ASSERT) |
| 295 | 303 |
| 296 static void showUnderInvalidationError(const char* reason, const DisplayItem& di splayItem) | 304 static void showUnderInvalidationError(const char* reason, const DisplayItem& di splayItem) |
| 297 { | 305 { |
| 298 #ifndef NDEBUG | 306 #ifndef NDEBUG |
| 299 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()); |
| 300 #else | 308 #else |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 316 return result; | 324 return result; |
| 317 } | 325 } |
| 318 | 326 |
| 319 void DisplayItemList::checkCachedDisplayItemIsUnchanged(const DisplayItem& displ ayItem, DisplayItemIndicesByClientMap& displayItemIndicesByClient) | 327 void DisplayItemList::checkCachedDisplayItemIsUnchanged(const DisplayItem& displ ayItem, DisplayItemIndicesByClientMap& displayItemIndicesByClient) |
| 320 { | 328 { |
| 321 ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled ()); | 329 ASSERT(RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled ()); |
| 322 | 330 |
| 323 if (!displayItem.isDrawing() || !clientCacheIsValid(displayItem.client())) | 331 if (!displayItem.isDrawing() || !clientCacheIsValid(displayItem.client())) |
| 324 return; | 332 return; |
| 325 | 333 |
| 326 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(); | |
| 327 if (mode == DrawingDisplayItem::DontCheck) | 339 if (mode == DrawingDisplayItem::DontCheck) |
| 328 return; | 340 return; |
| 329 | 341 |
| 330 // 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. |
| 331 // 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 |
| 332 // the client is not invalidated, issue error about under-invalidation. | 344 // the client is not invalidated, issue error about under-invalidation. |
| 333 size_t index = findMatchingItemFromIndex(displayItem, displayItem.type(), di splayItemIndicesByClient, m_currentDisplayItems); | 345 size_t index = findMatchingItemFromIndex(displayItem, displayItem.type(), di splayItemIndicesByClient, m_currentDisplayItems); |
| 334 if (index == kNotFound) { | 346 if (index == kNotFound) { |
| 335 showUnderInvalidationError("ERROR: under-invalidation: no cached display item", displayItem); | 347 showUnderInvalidationError("ERROR: under-invalidation: no cached display item", displayItem); |
| 336 ASSERT_NOT_REACHED(); | 348 ASSERT_NOT_REACHED(); |
| 337 return; | 349 return; |
| 338 } | 350 } |
| 339 | 351 |
| 340 RefPtr<const SkPicture> newPicture = static_cast<const DrawingDisplayItem&>( displayItem).picture(); | 352 RefPtr<const SkPicture> newPicture = drawingDisplayItem.picture(); |
| 341 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(); |
| 342 // 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. |
| 343 m_currentDisplayItems[index] = nullptr; | 355 m_currentDisplayItems[index] = nullptr; |
| 344 | 356 |
| 345 if (!newPicture && !oldPicture) | 357 if (!newPicture && !oldPicture) |
| 346 return; | 358 return; |
| 347 if (newPicture && oldPicture) { | 359 if (newPicture && oldPicture) { |
| 348 switch (mode) { | 360 switch (mode) { |
| 349 case DrawingDisplayItem::CheckPicture: | 361 case DrawingDisplayItem::CheckPicture: |
| 350 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... | |
| 436 | 448 |
| 437 void DisplayItemList::replay(GraphicsContext& context) const | 449 void DisplayItemList::replay(GraphicsContext& context) const |
| 438 { | 450 { |
| 439 TRACE_EVENT0("blink,benchmark", "DisplayItemList::replay"); | 451 TRACE_EVENT0("blink,benchmark", "DisplayItemList::replay"); |
| 440 ASSERT(m_newDisplayItems.isEmpty()); | 452 ASSERT(m_newDisplayItems.isEmpty()); |
| 441 for (auto& displayItem : m_currentDisplayItems) | 453 for (auto& displayItem : m_currentDisplayItems) |
| 442 displayItem->replay(context); | 454 displayItem->replay(context); |
| 443 } | 455 } |
| 444 | 456 |
| 445 } // namespace blink | 457 } // namespace blink |
| OLD | NEW |