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 "platform/graphics/paint/PaintController.h" | 5 #include "platform/graphics/paint/PaintController.h" |
| 6 | 6 |
| 7 #include "platform/TraceEvent.h" | 7 #include "platform/TraceEvent.h" |
| 8 #include "platform/graphics/GraphicsLayer.h" | 8 #include "platform/graphics/GraphicsLayer.h" |
| 9 #include "platform/graphics/paint/DrawingDisplayItem.h" | 9 #include "platform/graphics/paint/DrawingDisplayItem.h" |
| 10 #include "third_party/skia/include/core/SkPictureAnalyzer.h" | 10 #include "third_party/skia/include/core/SkPictureAnalyzer.h" |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 44 | 44 |
| 45 size_t cachedItem = findCachedItem(DisplayItem::Id(client, type)); | 45 size_t cachedItem = findCachedItem(DisplayItem::Id(client, type)); |
| 46 if (cachedItem == kNotFound) { | 46 if (cachedItem == kNotFound) { |
| 47 NOTREACHED(); | 47 NOTREACHED(); |
| 48 return false; | 48 return false; |
| 49 } | 49 } |
| 50 | 50 |
| 51 ++m_numCachedNewItems; | 51 ++m_numCachedNewItems; |
| 52 ensureNewDisplayItemListInitialCapacity(); | 52 ensureNewDisplayItemListInitialCapacity(); |
| 53 if (!DCHECK_IS_ON() || !RuntimeEnabledFeatures::slimmingPaintUnderInvalidati onCheckingEnabled()) | 53 if (!DCHECK_IS_ON() || !RuntimeEnabledFeatures::slimmingPaintUnderInvalidati onCheckingEnabled()) |
| 54 processNewItem(m_newDisplayItemList.appendByMoving(m_currentPaintArtifac t.getDisplayItemList()[cachedItem])); | 54 processNewItem(m_newDisplayItemList.appendByMoving(m_currentPaintArtifac t.getDisplayItemList()[cachedItem]), FromCachedItem); |
| 55 | 55 |
| 56 m_nextItemToMatch = cachedItem + 1; | 56 m_nextItemToMatch = cachedItem + 1; |
| 57 // Items before m_nextItemToMatch have been copied so we don't need to index them. | 57 // Items before m_nextItemToMatch have been copied so we don't need to index them. |
| 58 if (m_nextItemToMatch > m_nextItemToIndex) | 58 if (m_nextItemToMatch > m_nextItemToIndex) |
| 59 m_nextItemToIndex = m_nextItemToMatch; | 59 m_nextItemToIndex = m_nextItemToMatch; |
| 60 | 60 |
| 61 #if DCHECK_IS_ON() | 61 #if DCHECK_IS_ON() |
| 62 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) { | 62 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) { |
| 63 if (!isCheckingUnderInvalidation()) { | 63 if (!isCheckingUnderInvalidation()) { |
| 64 m_underInvalidationCheckingBegin = cachedItem; | 64 m_underInvalidationCheckingBegin = cachedItem; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 126 return lastDisplayItem.isBegin() && !lastDisplayItem.drawsContent(); | 126 return lastDisplayItem.isBegin() && !lastDisplayItem.drawsContent(); |
| 127 } | 127 } |
| 128 | 128 |
| 129 void PaintController::removeLastDisplayItem() | 129 void PaintController::removeLastDisplayItem() |
| 130 { | 130 { |
| 131 if (m_newDisplayItemList.isEmpty()) | 131 if (m_newDisplayItemList.isEmpty()) |
| 132 return; | 132 return; |
| 133 | 133 |
| 134 #if DCHECK_IS_ON() | 134 #if DCHECK_IS_ON() |
| 135 // Also remove the index pointing to the removed display item. | 135 // Also remove the index pointing to the removed display item. |
| 136 DisplayItemIndicesByClientMap::iterator it = m_newDisplayItemIndicesByClient .find(&m_newDisplayItemList.last().client()); | 136 IndicesByClientMap::iterator it = m_newDisplayItemIndicesByClient.find(&m_ne wDisplayItemList.last().client()); |
| 137 if (it != m_newDisplayItemIndicesByClient.end()) { | 137 if (it != m_newDisplayItemIndicesByClient.end()) { |
| 138 Vector<size_t>& indices = it->value; | 138 Vector<size_t>& indices = it->value; |
| 139 if (!indices.isEmpty() && indices.last() == (m_newDisplayItemList.size() - 1)) | 139 if (!indices.isEmpty() && indices.last() == (m_newDisplayItemList.size() - 1)) |
| 140 indices.removeLast(); | 140 indices.removeLast(); |
| 141 } | 141 } |
| 142 | 142 |
| 143 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled() && isCheckingUnderInvalidation()) { | 143 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled() && isCheckingUnderInvalidation()) { |
| 144 if (m_skippedProbableUnderInvalidationCount) { | 144 if (m_skippedProbableUnderInvalidationCount) { |
| 145 --m_skippedProbableUnderInvalidationCount; | 145 --m_skippedProbableUnderInvalidationCount; |
| 146 } else { | 146 } else { |
| 147 DCHECK(m_underInvalidationCheckingBegin); | 147 DCHECK(m_underInvalidationCheckingBegin); |
| 148 --m_underInvalidationCheckingBegin; | 148 --m_underInvalidationCheckingBegin; |
| 149 } | 149 } |
| 150 } | 150 } |
| 151 #endif | 151 #endif |
| 152 m_newDisplayItemList.removeLast(); | 152 m_newDisplayItemList.removeLast(); |
| 153 | 153 |
| 154 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) | 154 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
| 155 m_newPaintChunks.decrementDisplayItemIndex(); | 155 m_newPaintChunks.decrementDisplayItemIndex(); |
| 156 } | 156 } |
| 157 | 157 |
| 158 const DisplayItem* PaintController::lastDisplayItem(unsigned offset) | 158 const DisplayItem* PaintController::lastDisplayItem(unsigned offset) |
| 159 { | 159 { |
| 160 if (offset < m_newDisplayItemList.size()) | 160 if (offset < m_newDisplayItemList.size()) |
| 161 return &m_newDisplayItemList[m_newDisplayItemList.size() - offset - 1]; | 161 return &m_newDisplayItemList[m_newDisplayItemList.size() - offset - 1]; |
| 162 return nullptr; | 162 return nullptr; |
| 163 } | 163 } |
| 164 | 164 |
| 165 void PaintController::processNewItem(DisplayItem& displayItem) | 165 void PaintController::processNewItem(DisplayItem& displayItem, NewItemSource new ItemSource) |
| 166 { | 166 { |
| 167 DCHECK(!m_constructionDisabled); | 167 DCHECK(!m_constructionDisabled); |
| 168 | 168 |
| 169 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS | 169 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS |
| 170 if (!isSkippingCache()) { | 170 if (!isSkippingCache()) { |
| 171 if (displayItem.isCacheable()) { | 171 if (displayItem.isCacheable()) { |
| 172 // Mark the client shouldKeepAlive under this PaintController. | 172 // Mark the client shouldKeepAlive under this PaintController. |
| 173 // The status will end after the new display items are committed. | 173 // The status will end after the new display items are committed. |
| 174 displayItem.client().beginShouldKeepAlive(this); | 174 displayItem.client().beginShouldKeepAlive(this); |
| 175 | 175 |
| 176 if (!m_currentSubsequenceClients.isEmpty()) { | 176 if (!m_currentSubsequenceClients.isEmpty()) { |
| 177 // Mark the client shouldKeepAlive under the current subsequence . | 177 // Mark the client shouldKeepAlive under the current subsequence . |
| 178 // The status will end when the subsequence owner is invalidated or deleted. | 178 // The status will end when the subsequence owner is invalidated or deleted. |
| 179 displayItem.client().beginShouldKeepAlive(m_currentSubsequenceCl ients.last()); | 179 displayItem.client().beginShouldKeepAlive(m_currentSubsequenceCl ients.last()); |
| 180 } | 180 } |
| 181 } | 181 } |
| 182 | 182 |
| 183 if (displayItem.getType() == DisplayItem::Subsequence) { | 183 if (displayItem.getType() == DisplayItem::Subsequence) { |
| 184 m_currentSubsequenceClients.append(&displayItem.client()); | 184 m_currentSubsequenceClients.append(&displayItem.client()); |
| 185 } else if (displayItem.getType() == DisplayItem::EndSubsequence) { | 185 } else if (displayItem.getType() == DisplayItem::EndSubsequence) { |
| 186 CHECK(m_currentSubsequenceClients.last() == &displayItem.client()); | 186 CHECK(m_currentSubsequenceClients.last() == &displayItem.client()); |
| 187 m_currentSubsequenceClients.removeLast(); | 187 m_currentSubsequenceClients.removeLast(); |
| 188 } | 188 } |
| 189 } | 189 } |
| 190 #endif | 190 #endif |
| 191 | 191 |
| 192 if (isSkippingCache()) | 192 if (isSkippingCache()) { |
| 193 DCHECK(newItemSource == NewPainting); | |
| 193 displayItem.setSkippedCache(); | 194 displayItem.setSkippedCache(); |
| 195 } | |
| 196 | |
| 197 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { | |
| 198 if (newItemSource != FromCachedSubsequence) | |
| 199 m_currentChunkIsFromCachedSubsequence = false; | |
| 200 | |
| 201 size_t lastChunkIndex = m_newPaintChunks.lastChunkIndex(); | |
| 202 if (m_newPaintChunks.incrementDisplayItemIndex(displayItem)) { | |
| 203 DCHECK(lastChunkIndex != m_newPaintChunks.lastChunkIndex()); | |
| 204 if (lastChunkIndex != kNotFound) | |
| 205 generateChunkRerasterizationRects(m_newPaintChunks.paintChunkAt( lastChunkIndex)); | |
| 206 m_currentChunkIsFromCachedSubsequence = true; | |
| 207 } | |
| 208 } | |
| 194 | 209 |
| 195 #if DCHECK_IS_ON() | 210 #if DCHECK_IS_ON() |
| 196 // Verify noop begin/end pairs have been removed. | 211 // Verify noop begin/end pairs have been removed. |
| 197 if (m_newDisplayItemList.size() >= 2 && displayItem.isEnd()) { | 212 if (m_newDisplayItemList.size() >= 2 && displayItem.isEnd()) { |
| 198 const auto& beginDisplayItem = m_newDisplayItemList[m_newDisplayItemList .size() - 2]; | 213 const auto& beginDisplayItem = m_newDisplayItemList[m_newDisplayItemList .size() - 2]; |
| 199 if (beginDisplayItem.isBegin() && beginDisplayItem.getType() != DisplayI tem::Subsequence && !beginDisplayItem.drawsContent()) | 214 if (beginDisplayItem.isBegin() && beginDisplayItem.getType() != DisplayI tem::Subsequence && !beginDisplayItem.drawsContent()) |
| 200 DCHECK(!displayItem.isEndAndPairedWith(beginDisplayItem.getType())); | 215 DCHECK(!displayItem.isEndAndPairedWith(beginDisplayItem.getType())); |
| 201 } | 216 } |
| 202 | 217 |
| 203 size_t index = findMatchingItemFromIndex(displayItem.getId(), m_newDisplayIt emIndicesByClient, m_newDisplayItemList); | 218 size_t index = findMatchingItemFromIndex(displayItem.getId(), m_newDisplayIt emIndicesByClient, m_newDisplayItemList); |
| 204 if (index != kNotFound) { | 219 if (index != kNotFound) { |
| 205 #ifndef NDEBUG | 220 #ifndef NDEBUG |
| 206 showDebugData(); | 221 showDebugData(); |
| 207 WTFLogAlways("DisplayItem %s has duplicated id with previous %s (index=% d)\n", | 222 WTFLogAlways("DisplayItem %s has duplicated id with previous %s (index=% d)\n", |
| 208 displayItem.asDebugString().utf8().data(), m_newDisplayItemList[inde x].asDebugString().utf8().data(), static_cast<int>(index)); | 223 displayItem.asDebugString().utf8().data(), m_newDisplayItemList[inde x].asDebugString().utf8().data(), static_cast<int>(index)); |
| 209 #endif | 224 #endif |
| 210 NOTREACHED(); | 225 NOTREACHED(); |
| 211 } | 226 } |
| 212 addItemToIndexIfNeeded(displayItem, m_newDisplayItemList.size() - 1, m_newDi splayItemIndicesByClient); | 227 addItemToIndexIfNeeded(displayItem, m_newDisplayItemList.size() - 1, m_newDi splayItemIndicesByClient); |
| 213 | 228 |
| 214 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) | 229 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) |
| 215 checkUnderInvalidation(); | 230 checkUnderInvalidation(); |
| 216 #endif // DCHECK_IS_ON() | 231 #endif // DCHECK_IS_ON() |
| 217 | |
| 218 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) | |
| 219 m_newPaintChunks.incrementDisplayItemIndex(displayItem); | |
| 220 } | 232 } |
| 221 | 233 |
| 222 void PaintController::updateCurrentPaintChunkProperties(const PaintChunk::Id* id , const PaintChunkProperties& newProperties) | 234 void PaintController::updateCurrentPaintChunkProperties(const PaintChunk::Id* id , const PaintChunkProperties& newProperties) |
| 223 { | 235 { |
| 224 m_newPaintChunks.updateCurrentPaintChunkProperties(id, newProperties); | 236 m_newPaintChunks.updateCurrentPaintChunkProperties(id, newProperties); |
| 225 } | 237 } |
| 226 | 238 |
| 227 const PaintChunkProperties& PaintController::currentPaintChunkProperties() const | 239 const PaintChunkProperties& PaintController::currentPaintChunkProperties() const |
| 228 { | 240 { |
| 229 return m_newPaintChunks.currentPaintChunkProperties(); | 241 return m_newPaintChunks.currentPaintChunkProperties(); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 240 bool PaintController::clientCacheIsValid(const DisplayItemClient& client) const | 252 bool PaintController::clientCacheIsValid(const DisplayItemClient& client) const |
| 241 { | 253 { |
| 242 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS | 254 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS |
| 243 CHECK(client.isAlive()); | 255 CHECK(client.isAlive()); |
| 244 #endif | 256 #endif |
| 245 if (isSkippingCache()) | 257 if (isSkippingCache()) |
| 246 return false; | 258 return false; |
| 247 return client.displayItemsAreCached(m_currentCacheGeneration); | 259 return client.displayItemsAreCached(m_currentCacheGeneration); |
| 248 } | 260 } |
| 249 | 261 |
| 250 size_t PaintController::findMatchingItemFromIndex(const DisplayItem::Id& id, con st DisplayItemIndicesByClientMap& displayItemIndicesByClient, const DisplayItemL ist& list) | 262 size_t PaintController::findMatchingItemFromIndex(const DisplayItem::Id& id, con st IndicesByClientMap& displayItemIndicesByClient, const DisplayItemList& list) |
| 251 { | 263 { |
| 252 DisplayItemIndicesByClientMap::const_iterator it = displayItemIndicesByClien t.find(&id.client); | 264 IndicesByClientMap::const_iterator it = displayItemIndicesByClient.find(&id. client); |
| 253 if (it == displayItemIndicesByClient.end()) | 265 if (it == displayItemIndicesByClient.end()) |
| 254 return kNotFound; | 266 return kNotFound; |
| 255 | 267 |
| 256 const Vector<size_t>& indices = it->value; | 268 const Vector<size_t>& indices = it->value; |
| 257 for (size_t index : indices) { | 269 for (size_t index : indices) { |
| 258 const DisplayItem& existingItem = list[index]; | 270 const DisplayItem& existingItem = list[index]; |
| 259 DCHECK(!existingItem.hasValidClient() || existingItem.client() == id.cli ent); | 271 DCHECK(!existingItem.hasValidClient() || existingItem.client() == id.cli ent); |
| 260 if (id == existingItem.getId()) | 272 if (id == existingItem.getId()) |
| 261 return index; | 273 return index; |
| 262 } | 274 } |
| 263 | 275 |
| 264 return kNotFound; | 276 return kNotFound; |
| 265 } | 277 } |
| 266 | 278 |
| 267 void PaintController::addItemToIndexIfNeeded(const DisplayItem& displayItem, siz e_t index, DisplayItemIndicesByClientMap& displayItemIndicesByClient) | 279 void PaintController::addItemToIndexIfNeeded(const DisplayItem& displayItem, siz e_t index, IndicesByClientMap& displayItemIndicesByClient) |
| 268 { | 280 { |
| 269 if (!displayItem.isCacheable()) | 281 if (!displayItem.isCacheable()) |
| 270 return; | 282 return; |
| 271 | 283 |
| 272 DisplayItemIndicesByClientMap::iterator it = displayItemIndicesByClient.find (&displayItem.client()); | 284 IndicesByClientMap::iterator it = displayItemIndicesByClient.find(&displayIt em.client()); |
| 273 Vector<size_t>& indices = it == displayItemIndicesByClient.end() ? | 285 Vector<size_t>& indices = it == displayItemIndicesByClient.end() ? |
| 274 displayItemIndicesByClient.add(&displayItem.client(), Vector<size_t>()). storedValue->value : it->value; | 286 displayItemIndicesByClient.add(&displayItem.client(), Vector<size_t>()). storedValue->value : it->value; |
| 275 indices.append(index); | 287 indices.append(index); |
| 276 } | 288 } |
| 277 | 289 |
| 278 size_t PaintController::findCachedItem(const DisplayItem::Id& id) | 290 size_t PaintController::findCachedItem(const DisplayItem::Id& id) |
| 279 { | 291 { |
| 280 DCHECK(clientCacheIsValid(id.client)); | 292 DCHECK(clientCacheIsValid(id.client)); |
| 281 | 293 |
| 282 // Try to find the item sequentially first. This is fast if the current list and the new list are in | 294 // Try to find the item sequentially first. This is fast if the current list and the new list are in |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 370 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS | 382 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS |
| 371 CHECK(cachedItem->client().isAlive()); | 383 CHECK(cachedItem->client().isAlive()); |
| 372 #endif | 384 #endif |
| 373 ++m_numCachedNewItems; | 385 ++m_numCachedNewItems; |
| 374 bool metEndSubsequence = cachedItem->getId() == endSubsequenceId; | 386 bool metEndSubsequence = cachedItem->getId() == endSubsequenceId; |
| 375 if (!DCHECK_IS_ON() || !RuntimeEnabledFeatures::slimmingPaintUnderInvali dationCheckingEnabled()) { | 387 if (!DCHECK_IS_ON() || !RuntimeEnabledFeatures::slimmingPaintUnderInvali dationCheckingEnabled()) { |
| 376 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && cachedItemIn dex == cachedChunk->endIndex) { | 388 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && cachedItemIn dex == cachedChunk->endIndex) { |
| 377 ++cachedChunk; | 389 ++cachedChunk; |
| 378 updateCurrentPaintChunkProperties(cachedChunk->id ? &*cachedChun k->id : nullptr, cachedChunk->properties); | 390 updateCurrentPaintChunkProperties(cachedChunk->id ? &*cachedChun k->id : nullptr, cachedChunk->properties); |
| 379 } | 391 } |
| 380 processNewItem(m_newDisplayItemList.appendByMoving(*cachedItem)); | 392 processNewItem(m_newDisplayItemList.appendByMoving(*cachedItem), Fro mCachedSubsequence); |
| 381 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) | 393 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
| 382 DCHECK((!m_newPaintChunks.lastChunk().id && !cachedChunk->id) || m_newPaintChunks.lastChunk().matches(*cachedChunk)); | 394 DCHECK((!m_newPaintChunks.lastChunk().id && !cachedChunk->id) || m_newPaintChunks.lastChunk().matches(*cachedChunk)); |
| 383 } | 395 } |
| 384 | 396 |
| 385 ++cachedItemIndex; | 397 ++cachedItemIndex; |
| 386 if (metEndSubsequence) | 398 if (metEndSubsequence) |
| 387 break; | 399 break; |
| 388 | 400 |
| 389 // We should always be able to find the EndSubsequence display item. | 401 // We should always be able to find the EndSubsequence display item. |
| 390 DCHECK(cachedItemIndex < m_currentPaintArtifact.getDisplayItemList().siz e()); | 402 DCHECK(cachedItemIndex < m_currentPaintArtifact.getDisplayItemList().siz e()); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 403 { | 415 { |
| 404 LayoutRect visualRect = displayItem.client().visualRect(); | 416 LayoutRect visualRect = displayItem.client().visualRect(); |
| 405 visualRect.move(-offsetFromLayoutObject); | 417 visualRect.move(-offsetFromLayoutObject); |
| 406 return enclosingIntRect(visualRect); | 418 return enclosingIntRect(visualRect); |
| 407 } | 419 } |
| 408 | 420 |
| 409 void PaintController::resetCurrentListIndices() | 421 void PaintController::resetCurrentListIndices() |
| 410 { | 422 { |
| 411 m_nextItemToMatch = 0; | 423 m_nextItemToMatch = 0; |
| 412 m_nextItemToIndex = 0; | 424 m_nextItemToIndex = 0; |
| 425 m_nextChunkToMatch = 0; | |
| 413 #if DCHECK_IS_ON() | 426 #if DCHECK_IS_ON() |
| 414 m_underInvalidationCheckingBegin = 0; | 427 m_underInvalidationCheckingBegin = 0; |
| 415 m_underInvalidationCheckingEnd = 0; | 428 m_underInvalidationCheckingEnd = 0; |
| 416 m_skippedProbableUnderInvalidationCount = 0; | 429 m_skippedProbableUnderInvalidationCount = 0; |
| 417 #endif | 430 #endif |
| 418 } | 431 } |
| 419 | 432 |
| 420 void PaintController::commitNewDisplayItems(const LayoutSize& offsetFromLayoutOb ject) | 433 void PaintController::commitNewDisplayItems(const LayoutSize& offsetFromLayoutOb ject) |
| 421 { | 434 { |
| 422 TRACE_EVENT2("blink,benchmark", "PaintController::commitNewDisplayItems", | 435 TRACE_EVENT2("blink,benchmark", "PaintController::commitNewDisplayItems", |
| 423 "current_display_list_size", (int)m_currentPaintArtifact.getDisplayItemL ist().size(), | 436 "current_display_list_size", (int)m_currentPaintArtifact.getDisplayItemL ist().size(), |
| 424 "num_non_cached_new_items", (int)m_newDisplayItemList.size() - m_numCach edNewItems); | 437 "num_non_cached_new_items", (int)m_newDisplayItemList.size() - m_numCach edNewItems); |
| 425 m_numCachedNewItems = 0; | 438 m_numCachedNewItems = 0; |
| 426 | 439 |
| 427 // These data structures are used during painting only. | 440 // These data structures are used during painting only. |
| 428 DCHECK(!isSkippingCache()); | 441 DCHECK(!isSkippingCache()); |
| 429 #if DCHECK_IS_ON() | 442 #if DCHECK_IS_ON() |
| 430 m_newDisplayItemIndicesByClient.clear(); | 443 m_newDisplayItemIndicesByClient.clear(); |
| 431 #endif | 444 #endif |
| 432 | 445 |
| 446 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && !m_newDisplayItemLis t.isEmpty()) | |
| 447 generateChunkRerasterizationRects(m_newPaintChunks.lastChunk()); | |
| 448 | |
| 433 SkPictureGpuAnalyzer gpuAnalyzer; | 449 SkPictureGpuAnalyzer gpuAnalyzer; |
| 434 | 450 |
| 435 m_currentCacheGeneration = DisplayItemClient::CacheGenerationOrInvalidationR eason::next(); | 451 m_currentCacheGeneration = DisplayItemClient::CacheGenerationOrInvalidationR eason::next(); |
| 436 Vector<const DisplayItemClient*> skippedCacheClients; | 452 Vector<const DisplayItemClient*> skippedCacheClients; |
| 437 for (const auto& item : m_newDisplayItemList) { | 453 for (const auto& item : m_newDisplayItemList) { |
| 438 // No reason to continue the analysis once we have a veto. | 454 // No reason to continue the analysis once we have a veto. |
| 439 if (gpuAnalyzer.suitableForGpuRasterization()) | 455 if (gpuAnalyzer.suitableForGpuRasterization()) |
| 440 item.analyzeForGpuRasterization(gpuAnalyzer); | 456 item.analyzeForGpuRasterization(gpuAnalyzer); |
| 441 | 457 |
| 442 // TODO(wkorman): Only compute and append visual rect for drawings. | 458 // TODO(wkorman): Only compute and append visual rect for drawings. |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 453 } | 469 } |
| 454 | 470 |
| 455 for (auto* client : skippedCacheClients) | 471 for (auto* client : skippedCacheClients) |
| 456 client->setDisplayItemsUncached(); | 472 client->setDisplayItemsUncached(); |
| 457 | 473 |
| 458 // The new list will not be appended to again so we can release unused memor y. | 474 // The new list will not be appended to again so we can release unused memor y. |
| 459 m_newDisplayItemList.shrinkToFit(); | 475 m_newDisplayItemList.shrinkToFit(); |
| 460 m_currentPaintArtifact = PaintArtifact(std::move(m_newDisplayItemList), m_ne wPaintChunks.releasePaintChunks(), gpuAnalyzer.suitableForGpuRasterization()); | 476 m_currentPaintArtifact = PaintArtifact(std::move(m_newDisplayItemList), m_ne wPaintChunks.releasePaintChunks(), gpuAnalyzer.suitableForGpuRasterization()); |
| 461 resetCurrentListIndices(); | 477 resetCurrentListIndices(); |
| 462 m_outOfOrderItemIndices.clear(); | 478 m_outOfOrderItemIndices.clear(); |
| 479 m_outOfOrderChunkIndices.clear(); | |
| 463 | 480 |
| 464 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { | 481 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
| 465 for (const auto& chunk : m_currentPaintArtifact.paintChunks()) { | 482 for (const auto& chunk : m_currentPaintArtifact.paintChunks()) { |
| 466 if (chunk.id && chunk.id->client.isJustCreated()) | 483 if (chunk.id && chunk.id->client.isJustCreated()) |
| 467 chunk.id->client.clearIsJustCreated(); | 484 chunk.id->client.clearIsJustCreated(); |
| 468 } | 485 } |
| 469 } | 486 } |
| 470 | 487 |
| 471 // We'll allocate the initial buffer when we start the next paint. | 488 // We'll allocate the initial buffer when we start the next paint. |
| 472 m_newDisplayItemList = DisplayItemList(0); | 489 m_newDisplayItemList = DisplayItemList(0); |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 510 | 527 |
| 511 void PaintController::appendDebugDrawingAfterCommit(const DisplayItemClient& dis playItemClient, PassRefPtr<SkPicture> picture, const LayoutSize& offsetFromLayou tObject) | 528 void PaintController::appendDebugDrawingAfterCommit(const DisplayItemClient& dis playItemClient, PassRefPtr<SkPicture> picture, const LayoutSize& offsetFromLayou tObject) |
| 512 { | 529 { |
| 513 DCHECK(m_newDisplayItemList.isEmpty()); | 530 DCHECK(m_newDisplayItemList.isEmpty()); |
| 514 DrawingDisplayItem& displayItem = m_currentPaintArtifact.getDisplayItemList( ).allocateAndConstruct<DrawingDisplayItem>(displayItemClient, DisplayItem::Debug Drawing, picture); | 531 DrawingDisplayItem& displayItem = m_currentPaintArtifact.getDisplayItemList( ).allocateAndConstruct<DrawingDisplayItem>(displayItemClient, DisplayItem::Debug Drawing, picture); |
| 515 displayItem.setSkippedCache(); | 532 displayItem.setSkippedCache(); |
| 516 // TODO(wkorman): Only compute and append visual rect for drawings. | 533 // TODO(wkorman): Only compute and append visual rect for drawings. |
| 517 m_currentPaintArtifact.getDisplayItemList().appendVisualRect(visualRectForDi splayItem(displayItem, offsetFromLayoutObject)); | 534 m_currentPaintArtifact.getDisplayItemList().appendVisualRect(visualRectForDi splayItem(displayItem, offsetFromLayoutObject)); |
| 518 } | 535 } |
| 519 | 536 |
| 537 void PaintController::generateChunkRerasterizationRects(PaintChunk& newChunk) | |
| 538 { | |
| 539 DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); | |
| 540 if (m_currentChunkIsFromCachedSubsequence) | |
| 541 return; | |
| 542 | |
| 543 if (!newChunk.id) { | |
|
chrishtr
2016/08/26 18:10:51
Why would there be no id?
Xianzhu
2016/08/26 18:39:23
Please see https://cs.chromium.org/chromium/src/th
| |
| 544 newChunk.rasterInvalidationRects.append(FloatRect(LayoutRect::infiniteIn tRect())); | |
| 545 return; | |
| 546 } | |
| 547 | |
| 548 // Try to match old chunk sequentially first. | |
| 549 const auto& oldChunks = m_currentPaintArtifact.paintChunks(); | |
| 550 while (m_nextChunkToMatch < oldChunks.size()) { | |
| 551 const PaintChunk& oldChunk = oldChunks[m_nextChunkToMatch]; | |
| 552 if (newChunk.matches(oldChunk)) { | |
| 553 generateChunkRerasterizationRectsComparingOldChunk(newChunk, oldChun k); | |
| 554 ++m_nextChunkToMatch; | |
| 555 return; | |
| 556 } | |
| 557 | |
| 558 // Add skipped old chunks into the index. | |
| 559 if (oldChunk.id) { | |
| 560 auto it = m_outOfOrderChunkIndices.find(&oldChunk.id->client); | |
| 561 Vector<size_t>& indices = it == m_outOfOrderChunkIndices.end() ? | |
| 562 m_outOfOrderChunkIndices.add(&oldChunk.id->client, Vector<size_t >()).storedValue->value : it->value; | |
| 563 indices.append(m_nextChunkToMatch); | |
| 564 } | |
| 565 ++m_nextChunkToMatch; | |
| 566 } | |
| 567 | |
| 568 // Sequential matching reaches the end. Find from the out-of-order index. | |
| 569 auto it = m_outOfOrderChunkIndices.find(&newChunk.id->client); | |
| 570 if (it != m_outOfOrderChunkIndices.end()) { | |
| 571 for (size_t i : it->value) { | |
| 572 if (newChunk.matches(oldChunks[i])) { | |
| 573 generateChunkRerasterizationRectsComparingOldChunk(newChunk, old Chunks[i]); | |
| 574 return; | |
| 575 } | |
| 576 } | |
| 577 } | |
| 578 | |
| 579 // We reach here because the chunk is new. | |
| 580 newChunk.rasterInvalidationRects.append(FloatRect(LayoutRect::infiniteIntRec t())); | |
| 581 } | |
| 582 | |
| 583 void PaintController::generateChunkRerasterizationRectsComparingOldChunk(PaintCh unk& newChunk, const PaintChunk& oldChunk) | |
| 584 { | |
| 585 DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); | |
| 586 | |
| 587 // TODO(wangxianzhu): Support raster invalidation for recordered display ite ms without invalidating | |
|
chrishtr
2016/08/26 18:10:51
Do you mean "reordered"? What is an example where
Xianzhu
2016/08/26 18:39:23
Yes :) An example is z-index change: actually we d
| |
| 588 // display item clients. Currently we invalidate display item clients ensuri ng raster invalidation. | |
| 589 | |
| 590 // Maps from each client to the index of the first drawing-content display i tem of the client. | |
| 591 HashMap<const DisplayItemClient*, size_t> oldChunkClients; | |
| 592 for (size_t i = oldChunk.beginIndex; i < oldChunk.endIndex; ++i) { | |
| 593 const DisplayItem& oldItem = m_currentPaintArtifact.getDisplayItemList() [i]; | |
| 594 if (oldItem.hasValidClient() && oldItem.drawsContent()) | |
| 595 oldChunkClients.add(&oldItem.client(), i); | |
| 596 } | |
| 597 | |
| 598 HashSet<const DisplayItemClient*> newChunkClients; | |
| 599 for (size_t i = newChunk.beginIndex; i < newChunk.endIndex; ++i) { | |
| 600 const DisplayItem& newItem = m_newDisplayItemList[i]; | |
| 601 if (newItem.drawsContent()) { | |
| 602 if (!newItem.client().isJustCreated() && newItem.client().getPaintIn validationReason() == PaintInvalidationNone) | |
|
chrishtr
2016/08/26 18:10:51
This is to check for cached items?
Xianzhu
2016/08/26 18:39:23
Yes. Changed to clientCacheIsValid(newItem.client(
| |
| 603 oldChunkClients.remove(&newItem.client()); | |
| 604 else | |
| 605 newChunkClients.add(&newItem.client()); | |
| 606 } | |
| 607 } | |
| 608 | |
| 609 // TODO(wangxianzhu): Handle PaintInvalidationIncremental and optimize paint offset change. | |
| 610 for (const DisplayItemClient* client : newChunkClients) | |
| 611 newChunk.rasterInvalidationRects.append(client->visualRect()); | |
| 612 for (const auto& oldChunkClientInfo : oldChunkClients) | |
| 613 newChunk.rasterInvalidationRects.append(m_currentPaintArtifact.getDispla yItemList().visualRect(oldChunkClientInfo.value)); | |
| 614 } | |
| 615 | |
| 520 #if DCHECK_IS_ON() | 616 #if DCHECK_IS_ON() |
| 521 | 617 |
| 522 void PaintController::showUnderInvalidationError(const char* reason, const Displ ayItem& newItem, const DisplayItem* oldItem) const | 618 void PaintController::showUnderInvalidationError(const char* reason, const Displ ayItem& newItem, const DisplayItem* oldItem) const |
| 523 { | 619 { |
| 524 LOG(ERROR) << m_underInvalidationMessagePrefix << " " << reason; | 620 LOG(ERROR) << m_underInvalidationMessagePrefix << " " << reason; |
| 525 #ifndef NDEBUG | 621 #ifndef NDEBUG |
| 526 LOG(ERROR) << "New display item: " << newItem.asDebugString(); | 622 LOG(ERROR) << "New display item: " << newItem.asDebugString(); |
| 527 LOG(ERROR) << "Old display item: " << (oldItem ? oldItem->asDebugString() : "None"); | 623 LOG(ERROR) << "Old display item: " << (oldItem ? oldItem->asDebugString() : "None"); |
| 528 #else | 624 #else |
| 529 LOG(ERROR) << "Run debug build to get more details."; | 625 LOG(ERROR) << "Run debug build to get more details."; |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 611 return stringBuilder.toString(); | 707 return stringBuilder.toString(); |
| 612 } | 708 } |
| 613 | 709 |
| 614 void PaintController::showDebugData() const | 710 void PaintController::showDebugData() const |
| 615 { | 711 { |
| 616 WTFLogAlways("current display item list: [%s]\n", displayItemListAsDebugStri ng(m_currentPaintArtifact.getDisplayItemList()).utf8().data()); | 712 WTFLogAlways("current display item list: [%s]\n", displayItemListAsDebugStri ng(m_currentPaintArtifact.getDisplayItemList()).utf8().data()); |
| 617 WTFLogAlways("new display item list: [%s]\n", displayItemListAsDebugString(m _newDisplayItemList).utf8().data()); | 713 WTFLogAlways("new display item list: [%s]\n", displayItemListAsDebugString(m _newDisplayItemList).utf8().data()); |
| 618 } | 714 } |
| 619 | 715 |
| 620 } // namespace blink | 716 } // namespace blink |
| OLD | NEW |