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" |
| 11 #include "wtf/AutoReset.h" | |
| 11 #include "wtf/text/StringBuilder.h" | 12 #include "wtf/text/StringBuilder.h" |
| 12 | 13 |
| 13 #ifndef NDEBUG | 14 #ifndef NDEBUG |
| 14 #include "platform/graphics/LoggingCanvas.h" | 15 #include "platform/graphics/LoggingCanvas.h" |
| 15 #include <stdio.h> | 16 #include <stdio.h> |
| 16 #endif | 17 #endif |
| 17 | 18 |
| 18 namespace blink { | 19 namespace blink { |
| 19 | 20 |
| 20 const PaintArtifact& PaintController::paintArtifact() const | 21 const PaintArtifact& PaintController::paintArtifact() const |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 188 } | 189 } |
| 189 } | 190 } |
| 190 #endif | 191 #endif |
| 191 | 192 |
| 192 if (isSkippingCache()) { | 193 if (isSkippingCache()) { |
| 193 DCHECK(newItemSource == NewPainting); | 194 DCHECK(newItemSource == NewPainting); |
| 194 displayItem.setSkippedCache(); | 195 displayItem.setSkippedCache(); |
| 195 } | 196 } |
| 196 | 197 |
| 197 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { | 198 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
| 198 if (newItemSource != FromCachedSubsequence) | |
| 199 m_currentChunkIsFromCachedSubsequence = false; | |
| 200 | |
| 201 size_t lastChunkIndex = m_newPaintChunks.lastChunkIndex(); | 199 size_t lastChunkIndex = m_newPaintChunks.lastChunkIndex(); |
| 202 if (m_newPaintChunks.incrementDisplayItemIndex(displayItem)) { | 200 if (m_newPaintChunks.incrementDisplayItemIndex(displayItem)) { |
| 203 DCHECK(lastChunkIndex != m_newPaintChunks.lastChunkIndex()); | 201 DCHECK(lastChunkIndex != m_newPaintChunks.lastChunkIndex()); |
| 204 if (lastChunkIndex != kNotFound) | 202 if (lastChunkIndex != kNotFound) |
| 205 generateChunkRasterInvalidationRects(m_newPaintChunks.paintChunk At(lastChunkIndex)); | 203 generateChunkRasterInvalidationRects(m_newPaintChunks.paintChunk At(lastChunkIndex)); |
| 206 m_currentChunkIsFromCachedSubsequence = true; | |
| 207 } | 204 } |
| 208 } | 205 } |
| 209 | 206 |
| 210 #if DCHECK_IS_ON() | 207 #if DCHECK_IS_ON() |
| 211 // Verify noop begin/end pairs have been removed. | 208 // Verify noop begin/end pairs have been removed. |
| 212 if (m_newDisplayItemList.size() >= 2 && displayItem.isEnd()) { | 209 if (m_newDisplayItemList.size() >= 2 && displayItem.isEnd()) { |
| 213 const auto& beginDisplayItem = m_newDisplayItemList[m_newDisplayItemList .size() - 2]; | 210 const auto& beginDisplayItem = m_newDisplayItemList[m_newDisplayItemList .size() - 2]; |
| 214 if (beginDisplayItem.isBegin() && beginDisplayItem.getType() != DisplayI tem::kSubsequence && !beginDisplayItem.drawsContent()) | 211 if (beginDisplayItem.isBegin() && beginDisplayItem.getType() != DisplayI tem::kSubsequence && !beginDisplayItem.drawsContent()) |
| 215 DCHECK(!displayItem.isEndAndPairedWith(beginDisplayItem.getType())); | 212 DCHECK(!displayItem.isEndAndPairedWith(beginDisplayItem.getType())); |
| 216 } | 213 } |
| 217 | 214 |
| 218 size_t index = findMatchingItemFromIndex(displayItem.getId(), m_newDisplayIt emIndicesByClient, m_newDisplayItemList); | 215 size_t index = findMatchingItemFromIndex(displayItem.getId(), m_newDisplayIt emIndicesByClient, m_newDisplayItemList); |
| 219 if (index != kNotFound) { | 216 if (index != kNotFound) { |
| 220 #ifndef NDEBUG | 217 #ifndef NDEBUG |
| 221 showDebugData(); | 218 showDebugData(); |
| 222 WTFLogAlways("DisplayItem %s has duplicated id with previous %s (index=% d)\n", | 219 WTFLogAlways("DisplayItem %s has duplicated id with previous %s (index=% zu)\n", |
| 223 displayItem.asDebugString().utf8().data(), m_newDisplayItemList[inde x].asDebugString().utf8().data(), static_cast<int>(index)); | 220 displayItem.asDebugString().utf8().data(), m_newDisplayItemList[inde x].asDebugString().utf8().data(), index); |
| 224 #endif | 221 #endif |
| 225 NOTREACHED(); | 222 NOTREACHED(); |
| 226 } | 223 } |
| 227 addItemToIndexIfNeeded(displayItem, m_newDisplayItemList.size() - 1, m_newDi splayItemIndicesByClient); | 224 addItemToIndexIfNeeded(displayItem, m_newDisplayItemList.size() - 1, m_newDi splayItemIndicesByClient); |
| 228 | 225 |
| 229 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) | 226 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) |
| 230 checkUnderInvalidation(); | 227 checkUnderInvalidation(); |
| 231 #endif // DCHECK_IS_ON() | 228 #endif // DCHECK_IS_ON() |
| 232 } | 229 } |
| 233 | 230 |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 261 | 258 |
| 262 size_t PaintController::findMatchingItemFromIndex(const DisplayItem::Id& id, con st IndicesByClientMap& displayItemIndicesByClient, const DisplayItemList& list) | 259 size_t PaintController::findMatchingItemFromIndex(const DisplayItem::Id& id, con st IndicesByClientMap& displayItemIndicesByClient, const DisplayItemList& list) |
| 263 { | 260 { |
| 264 IndicesByClientMap::const_iterator it = displayItemIndicesByClient.find(&id. client); | 261 IndicesByClientMap::const_iterator it = displayItemIndicesByClient.find(&id. client); |
| 265 if (it == displayItemIndicesByClient.end()) | 262 if (it == displayItemIndicesByClient.end()) |
| 266 return kNotFound; | 263 return kNotFound; |
| 267 | 264 |
| 268 const Vector<size_t>& indices = it->value; | 265 const Vector<size_t>& indices = it->value; |
| 269 for (size_t index : indices) { | 266 for (size_t index : indices) { |
| 270 const DisplayItem& existingItem = list[index]; | 267 const DisplayItem& existingItem = list[index]; |
| 271 DCHECK(!existingItem.hasValidClient() || existingItem.client() == id.cli ent); | 268 if (existingItem.hasBeenMoved()) |
| 269 continue; | |
| 270 DCHECK(existingItem.client() == id.client); | |
| 272 if (id == existingItem.getId()) | 271 if (id == existingItem.getId()) |
| 273 return index; | 272 return index; |
| 274 } | 273 } |
| 275 | 274 |
| 276 return kNotFound; | 275 return kNotFound; |
| 277 } | 276 } |
| 278 | 277 |
| 279 void PaintController::addItemToIndexIfNeeded(const DisplayItem& displayItem, siz e_t index, IndicesByClientMap& displayItemIndicesByClient) | 278 void PaintController::addItemToIndexIfNeeded(const DisplayItem& displayItem, siz e_t index, IndicesByClientMap& displayItemIndicesByClient) |
| 280 { | 279 { |
| 281 if (!displayItem.isCacheable()) | 280 if (!displayItem.isCacheable()) |
| 282 return; | 281 return; |
| 283 | 282 |
| 284 IndicesByClientMap::iterator it = displayItemIndicesByClient.find(&displayIt em.client()); | 283 IndicesByClientMap::iterator it = displayItemIndicesByClient.find(&displayIt em.client()); |
| 285 Vector<size_t>& indices = it == displayItemIndicesByClient.end() ? | 284 Vector<size_t>& indices = it == displayItemIndicesByClient.end() ? |
| 286 displayItemIndicesByClient.add(&displayItem.client(), Vector<size_t>()). storedValue->value : it->value; | 285 displayItemIndicesByClient.add(&displayItem.client(), Vector<size_t>()). storedValue->value : it->value; |
| 287 indices.append(index); | 286 indices.append(index); |
| 288 } | 287 } |
| 289 | 288 |
| 290 size_t PaintController::findCachedItem(const DisplayItem::Id& id) | 289 size_t PaintController::findCachedItem(const DisplayItem::Id& id) |
| 291 { | 290 { |
| 292 DCHECK(clientCacheIsValid(id.client)); | 291 DCHECK(clientCacheIsValid(id.client)); |
| 293 | 292 |
| 294 // Try to find the item sequentially first. This is fast if the current list and the new list are in | 293 // Try to find the item sequentially first. This is fast if the current list and the new list are in |
| 295 // the same order around the new item. If found, we don't need to update and lookup the index. | 294 // the same order around the new item. If found, we don't need to update and lookup the index. |
| 296 for (size_t i = m_nextItemToMatch; i < m_currentPaintArtifact.getDisplayItem List().size(); ++i) { | 295 for (size_t i = m_nextItemToMatch; i < m_currentPaintArtifact.getDisplayItem List().size(); ++i) { |
| 297 // We encounter an item that has already been copied which indicates we can't do sequential matching. | 296 // We encounter an item that has already been copied which indicates we can't do sequential matching. |
| 298 const DisplayItem& item = m_currentPaintArtifact.getDisplayItemList()[i] ; | 297 const DisplayItem& item = m_currentPaintArtifact.getDisplayItemList()[i] ; |
| 299 if (!item.hasValidClient()) | 298 if (item.hasBeenMoved()) |
| 300 break; | 299 break; |
| 301 if (id == item.getId()) { | 300 if (id == item.getId()) { |
| 302 #if DCHECK_IS_ON() | 301 #if DCHECK_IS_ON() |
| 303 ++m_numSequentialMatches; | 302 ++m_numSequentialMatches; |
| 304 #endif | 303 #endif |
| 305 return i; | 304 return i; |
| 306 } | 305 } |
| 307 // We encounter a different cacheable item which also indicates we can't do sequential matching. | 306 // We encounter a different cacheable item which also indicates we can't do sequential matching. |
| 308 if (item.isCacheable()) | 307 if (item.isCacheable()) |
| 309 break; | 308 break; |
| 310 } | 309 } |
| 311 | 310 |
| 312 size_t foundIndex = findMatchingItemFromIndex(id, m_outOfOrderItemIndices, m _currentPaintArtifact.getDisplayItemList()); | 311 size_t foundIndex = findMatchingItemFromIndex(id, m_outOfOrderItemIndices, m _currentPaintArtifact.getDisplayItemList()); |
| 313 if (foundIndex != kNotFound) { | 312 if (foundIndex != kNotFound) { |
| 314 #if DCHECK_IS_ON() | 313 #if DCHECK_IS_ON() |
| 315 ++m_numOutOfOrderMatches; | 314 ++m_numOutOfOrderMatches; |
| 316 #endif | 315 #endif |
| 317 return foundIndex; | 316 return foundIndex; |
| 318 } | 317 } |
| 319 | 318 |
| 320 return findOutOfOrderCachedItemForward(id); | 319 return findOutOfOrderCachedItemForward(id); |
| 321 } | 320 } |
| 322 | 321 |
| 323 // Find forward for the item and index all skipped indexable items. | 322 // Find forward for the item and index all skipped indexable items. |
| 324 size_t PaintController::findOutOfOrderCachedItemForward(const DisplayItem::Id& i d) | 323 size_t PaintController::findOutOfOrderCachedItemForward(const DisplayItem::Id& i d) |
| 325 { | 324 { |
| 326 for (size_t i = m_nextItemToIndex; i < m_currentPaintArtifact.getDisplayItem List().size(); ++i) { | 325 for (size_t i = m_nextItemToIndex; i < m_currentPaintArtifact.getDisplayItem List().size(); ++i) { |
| 327 const DisplayItem& item = m_currentPaintArtifact.getDisplayItemList()[i] ; | 326 const DisplayItem& item = m_currentPaintArtifact.getDisplayItemList()[i] ; |
| 328 DCHECK(item.hasValidClient()); | 327 DCHECK(!item.hasBeenMoved()); |
| 329 if (id == item.getId()) { | 328 if (id == item.getId()) { |
| 330 #if DCHECK_IS_ON() | 329 #if DCHECK_IS_ON() |
| 331 ++m_numSequentialMatches; | 330 ++m_numSequentialMatches; |
| 332 #endif | 331 #endif |
| 333 return i; | 332 return i; |
| 334 } | 333 } |
| 335 if (item.isCacheable()) { | 334 if (item.isCacheable()) { |
| 336 #if DCHECK_IS_ON() | 335 #if DCHECK_IS_ON() |
| 337 ++m_numIndexedItems; | 336 ++m_numIndexedItems; |
| 338 #endif | 337 #endif |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 350 // In this case, the caller should fall back to repaint the display item. | 349 // In this case, the caller should fall back to repaint the display item. |
| 351 return kNotFound; | 350 return kNotFound; |
| 352 } | 351 } |
| 353 | 352 |
| 354 // Copies a cached subsequence from current list to the new list. On return, | 353 // Copies a cached subsequence from current list to the new list. On return, |
| 355 // |cachedItemIndex| points to the item after the EndSubsequence item of the sub sequence. | 354 // |cachedItemIndex| points to the item after the EndSubsequence item of the sub sequence. |
| 356 // When paintUnderInvaldiationCheckingEnabled() we'll not actually copy the subs equence, | 355 // When paintUnderInvaldiationCheckingEnabled() we'll not actually copy the subs equence, |
| 357 // but mark the begin and end of the subsequence for under-invalidation checking . | 356 // but mark the begin and end of the subsequence for under-invalidation checking . |
| 358 void PaintController::copyCachedSubsequence(size_t& cachedItemIndex) | 357 void PaintController::copyCachedSubsequence(size_t& cachedItemIndex) |
| 359 { | 358 { |
| 359 AutoReset<size_t> subsequenceBeginIndex(&m_currentCachedSubsequenceBeginInde xInNewList, m_newDisplayItemList.size()); | |
|
chrishtr
2016/09/06 22:14:12
What does changing to m_currentCachedSubsequenceBe
Xianzhu
2016/09/06 22:42:38
This replaces the original m_currentChunkIsFromCac
| |
| 360 DisplayItem* cachedItem = &m_currentPaintArtifact.getDisplayItemList()[cache dItemIndex]; | 360 DisplayItem* cachedItem = &m_currentPaintArtifact.getDisplayItemList()[cache dItemIndex]; |
| 361 #if DCHECK_IS_ON() | 361 #if DCHECK_IS_ON() |
| 362 DCHECK(cachedItem->getType() == DisplayItem::kSubsequence); | 362 DCHECK(cachedItem->getType() == DisplayItem::kSubsequence); |
| 363 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) { | 363 if (RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled()) { |
| 364 DCHECK(!isCheckingUnderInvalidation()); | 364 DCHECK(!isCheckingUnderInvalidation()); |
| 365 m_underInvalidationCheckingBegin = cachedItemIndex; | 365 m_underInvalidationCheckingBegin = cachedItemIndex; |
| 366 m_underInvalidationMessagePrefix = "(In cached subsequence of " + cached Item->client().debugName() + ")"; | 366 m_underInvalidationMessagePrefix = "(In cached subsequence of " + cached Item->client().debugName() + ")"; |
| 367 } | 367 } |
| 368 #endif | 368 #endif |
| 369 | 369 |
| 370 DisplayItem::Id endSubsequenceId(cachedItem->client(), DisplayItem::kEndSubs equence); | 370 DisplayItem::Id endSubsequenceId(cachedItem->client(), DisplayItem::kEndSubs equence); |
| 371 Vector<PaintChunk>::const_iterator cachedChunk; | 371 Vector<PaintChunk>::const_iterator cachedChunk; |
| 372 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { | 372 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) { |
| 373 cachedChunk = m_currentPaintArtifact.findChunkByDisplayItemIndex(cachedI temIndex); | 373 cachedChunk = m_currentPaintArtifact.findChunkByDisplayItemIndex(cachedI temIndex); |
| 374 DCHECK(cachedChunk != m_currentPaintArtifact.paintChunks().end()); | |
| 374 updateCurrentPaintChunkProperties(cachedChunk->id ? &*cachedChunk->id : nullptr, cachedChunk->properties); | 375 updateCurrentPaintChunkProperties(cachedChunk->id ? &*cachedChunk->id : nullptr, cachedChunk->properties); |
| 375 } else { | 376 } else { |
| 376 // This is to avoid compilation error about uninitialized variable on Wi ndows. | 377 // This is to avoid compilation error about uninitialized variable on Wi ndows. |
| 377 cachedChunk = m_currentPaintArtifact.paintChunks().begin(); | 378 cachedChunk = m_currentPaintArtifact.paintChunks().begin(); |
| 378 } | 379 } |
| 379 | 380 |
| 380 while (true) { | 381 while (true) { |
| 381 DCHECK(cachedItem->hasValidClient()); | 382 DCHECK(!cachedItem->hasBeenMoved()); |
| 382 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS | 383 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS |
| 383 CHECK(cachedItem->client().isAlive()); | 384 CHECK(cachedItem->client().isAlive()); |
| 384 #endif | 385 #endif |
| 385 ++m_numCachedNewItems; | 386 ++m_numCachedNewItems; |
| 386 bool metEndSubsequence = cachedItem->getId() == endSubsequenceId; | 387 bool metEndSubsequence = cachedItem->getId() == endSubsequenceId; |
| 387 if (!DCHECK_IS_ON() || !RuntimeEnabledFeatures::slimmingPaintUnderInvali dationCheckingEnabled()) { | 388 if (!DCHECK_IS_ON() || !RuntimeEnabledFeatures::slimmingPaintUnderInvali dationCheckingEnabled()) { |
| 388 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && cachedItemIn dex == cachedChunk->endIndex) { | 389 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled() && cachedItemIn dex == cachedChunk->endIndex) { |
| 389 ++cachedChunk; | 390 ++cachedChunk; |
| 391 DCHECK(cachedChunk != m_currentPaintArtifact.paintChunks().end() ); | |
| 390 updateCurrentPaintChunkProperties(cachedChunk->id ? &*cachedChun k->id : nullptr, cachedChunk->properties); | 392 updateCurrentPaintChunkProperties(cachedChunk->id ? &*cachedChun k->id : nullptr, cachedChunk->properties); |
| 391 } | 393 } |
| 392 processNewItem(m_newDisplayItemList.appendByMoving(*cachedItem), Fro mCachedSubsequence); | 394 processNewItem(m_newDisplayItemList.appendByMoving(*cachedItem), Fro mCachedSubsequence); |
| 393 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) | 395 if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) |
| 394 DCHECK((!m_newPaintChunks.lastChunk().id && !cachedChunk->id) || m_newPaintChunks.lastChunk().matches(*cachedChunk)); | 396 DCHECK((!m_newPaintChunks.lastChunk().id && !cachedChunk->id) || m_newPaintChunks.lastChunk().matches(*cachedChunk)); |
| 395 } | 397 } |
| 396 | 398 |
| 397 ++cachedItemIndex; | 399 ++cachedItemIndex; |
| 398 if (metEndSubsequence) | 400 if (metEndSubsequence) |
| 399 break; | 401 break; |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 530 DCHECK(m_newDisplayItemList.isEmpty()); | 532 DCHECK(m_newDisplayItemList.isEmpty()); |
| 531 DrawingDisplayItem& displayItem = m_currentPaintArtifact.getDisplayItemList( ).allocateAndConstruct<DrawingDisplayItem>(displayItemClient, DisplayItem::kDebu gDrawing, picture); | 533 DrawingDisplayItem& displayItem = m_currentPaintArtifact.getDisplayItemList( ).allocateAndConstruct<DrawingDisplayItem>(displayItemClient, DisplayItem::kDebu gDrawing, picture); |
| 532 displayItem.setSkippedCache(); | 534 displayItem.setSkippedCache(); |
| 533 // TODO(wkorman): Only compute and append visual rect for drawings. | 535 // TODO(wkorman): Only compute and append visual rect for drawings. |
| 534 m_currentPaintArtifact.getDisplayItemList().appendVisualRect(visualRectForDi splayItem(displayItem, offsetFromLayoutObject)); | 536 m_currentPaintArtifact.getDisplayItemList().appendVisualRect(visualRectForDi splayItem(displayItem, offsetFromLayoutObject)); |
| 535 } | 537 } |
| 536 | 538 |
| 537 void PaintController::generateChunkRasterInvalidationRects(PaintChunk& newChunk) | 539 void PaintController::generateChunkRasterInvalidationRects(PaintChunk& newChunk) |
| 538 { | 540 { |
| 539 DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); | 541 DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); |
| 540 if (m_currentChunkIsFromCachedSubsequence) | 542 if (newChunk.beginIndex >= m_currentCachedSubsequenceBeginIndexInNewList) |
| 541 return; | 543 return; |
| 542 | 544 |
| 543 if (!newChunk.id) { | 545 if (!newChunk.id) { |
| 544 newChunk.rasterInvalidationRects.append(FloatRect(LayoutRect::infiniteIn tRect())); | 546 newChunk.rasterInvalidationRects.append(FloatRect(LayoutRect::infiniteIn tRect())); |
| 545 return; | 547 return; |
| 546 } | 548 } |
| 547 | 549 |
| 548 // Try to match old chunk sequentially first. | 550 // Try to match old chunk sequentially first. |
| 549 const auto& oldChunks = m_currentPaintArtifact.paintChunks(); | 551 const auto& oldChunks = m_currentPaintArtifact.paintChunks(); |
| 550 while (m_nextChunkToMatch < oldChunks.size()) { | 552 while (m_nextChunkToMatch < oldChunks.size()) { |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 577 } | 579 } |
| 578 | 580 |
| 579 // We reach here because the chunk is new. | 581 // We reach here because the chunk is new. |
| 580 newChunk.rasterInvalidationRects.append(FloatRect(LayoutRect::infiniteIntRec t())); | 582 newChunk.rasterInvalidationRects.append(FloatRect(LayoutRect::infiniteIntRec t())); |
| 581 } | 583 } |
| 582 | 584 |
| 583 void PaintController::generateChunkRasterInvalidationRectsComparingOldChunk(Pain tChunk& newChunk, const PaintChunk& oldChunk) | 585 void PaintController::generateChunkRasterInvalidationRectsComparingOldChunk(Pain tChunk& newChunk, const PaintChunk& oldChunk) |
| 584 { | 586 { |
| 585 DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); | 587 DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); |
| 586 | 588 |
| 587 // TODO(wangxianzhu): Support raster invalidation for reordered display item s without invalidating | |
| 588 // display item clients. Currently we invalidate display item clients ensuri ng raster invalidation. | |
| 589 // TODO(wangxianzhu): Handle PaintInvalidationIncremental. | 589 // TODO(wangxianzhu): Handle PaintInvalidationIncremental. |
| 590 // TODO(wangxianzhu): Optimize paint offset change. | 590 // TODO(wangxianzhu): Optimize paint offset change. |
| 591 | 591 |
| 592 // Maps from each client to the index of the first drawing-content display i tem of the client. | 592 HashSet<const DisplayItemClient*> invalidatedClientsInOldChunk; |
| 593 HashMap<const DisplayItemClient*, size_t> oldChunkClients; | 593 size_t highestMovedToIndex = 0; |
| 594 for (size_t i = oldChunk.beginIndex; i < oldChunk.endIndex; ++i) { | 594 for (size_t oldIndex = oldChunk.beginIndex; oldIndex < oldChunk.endIndex; ++ oldIndex) { |
| 595 const DisplayItem& oldItem = m_currentPaintArtifact.getDisplayItemList() [i]; | 595 const DisplayItem& oldItem = m_currentPaintArtifact.getDisplayItemList() [oldIndex]; |
| 596 // oldItem.hasValidClient() indicates that the item has not been copied as a cached item into | 596 const DisplayItemClient* clientToInvalidate = nullptr; |
| 597 // m_newDislayItemList, so the item either disappeared or changed, and n eeds raster invalidation. | 597 if (oldItem.hasBeenMoved()) { |
| 598 if (oldItem.hasValidClient() && oldItem.drawsContent() && oldChunkClient s.add(&oldItem.client(), i).isNewEntry) | 598 size_t movedToIndex = oldItem.movedToIndex(); |
| 599 newChunk.rasterInvalidationRects.append(m_currentPaintArtifact.getDi splayItemList().visualRect(i)); | 599 if (m_newDisplayItemList[movedToIndex].drawsContent()) { |
| 600 if (movedToIndex < newChunk.beginIndex || movedToIndex >= newChu nk.endIndex) { | |
| 601 // The item has been moved into another chunk, so need to in validate it in the old chunk. | |
| 602 clientToInvalidate = &m_newDisplayItemList[movedToIndex].cli ent(); | |
| 603 // And invalidate in the new chunk into which the item was m oved. | |
| 604 PaintChunk& movedToChunk = m_newPaintChunks.findChunkByDispl ayItemIndex(movedToIndex); | |
| 605 movedToChunk.rasterInvalidationRects.append(clientToInvalida te->visualRect()); | |
| 606 } else if (movedToIndex < highestMovedToIndex) { | |
| 607 // The item has been moved behind other cached items, so nee d to invalidate the area | |
| 608 // that is probably exposed by the item. | |
|
chrishtr
2016/09/06 22:14:12
"exposed by the item moving earlier"
Xianzhu
2016/09/06 22:42:38
Done.
| |
| 609 clientToInvalidate = &m_newDisplayItemList[movedToIndex].cli ent(); | |
| 610 } else { | |
| 611 highestMovedToIndex = movedToIndex; | |
| 612 } | |
| 613 } | |
| 614 } else if (oldItem.drawsContent()) { | |
| 615 clientToInvalidate = &oldItem.client(); | |
| 616 } | |
| 617 if (clientToInvalidate && invalidatedClientsInOldChunk.add(clientToInval idate).isNewEntry) { | |
| 618 newChunk.rasterInvalidationRects.append(m_currentPaintArtifact.getDi splayItemList().visualRect(oldIndex)); | |
| 619 } | |
| 600 } | 620 } |
| 601 | 621 |
| 602 HashSet<const DisplayItemClient*> newChunkClients; | 622 HashSet<const DisplayItemClient*> invalidatedClientsInNewChunk; |
| 603 for (size_t i = newChunk.beginIndex; i < newChunk.endIndex; ++i) { | 623 for (size_t newIndex = newChunk.beginIndex; newIndex < newChunk.endIndex; ++ newIndex) { |
| 604 const DisplayItem& newItem = m_newDisplayItemList[i]; | 624 const DisplayItem& newItem = m_newDisplayItemList[newIndex]; |
| 605 if (newItem.drawsContent()) { | 625 if (newItem.drawsContent() && !clientCacheIsValid(newItem.client()) && i nvalidatedClientsInNewChunk.add(&newItem.client()).isNewEntry) |
| 606 if (!clientCacheIsValid(newItem.client())) { | 626 newChunk.rasterInvalidationRects.append(newItem.client().visualRect( )); |
| 607 if (newChunkClients.add(&newItem.client()).isNewEntry) | |
| 608 newChunk.rasterInvalidationRects.append(newItem.client().vis ualRect()); | |
| 609 } else { | |
| 610 // The cached item was moved from the old chunk which should not contain any item of the client now. | |
| 611 DCHECK(!oldChunkClients.contains(&newItem.client())); | |
| 612 } | |
| 613 } | |
| 614 } | 627 } |
| 615 } | 628 } |
| 616 | 629 |
| 617 #if DCHECK_IS_ON() | 630 #if DCHECK_IS_ON() |
| 618 | 631 |
| 619 void PaintController::showUnderInvalidationError(const char* reason, const Displ ayItem& newItem, const DisplayItem* oldItem) const | 632 void PaintController::showUnderInvalidationError(const char* reason, const Displ ayItem& newItem, const DisplayItem* oldItem) const |
| 620 { | 633 { |
| 621 LOG(ERROR) << m_underInvalidationMessagePrefix << " " << reason; | 634 LOG(ERROR) << m_underInvalidationMessagePrefix << " " << reason; |
| 622 #ifndef NDEBUG | 635 #ifndef NDEBUG |
| 623 LOG(ERROR) << "New display item: " << newItem.asDebugString(); | 636 LOG(ERROR) << "New display item: " << newItem.asDebugString(); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 686 #endif // DCHECK_IS_ON() | 699 #endif // DCHECK_IS_ON() |
| 687 | 700 |
| 688 String PaintController::displayItemListAsDebugString(const DisplayItemList& list ) const | 701 String PaintController::displayItemListAsDebugString(const DisplayItemList& list ) const |
| 689 { | 702 { |
| 690 StringBuilder stringBuilder; | 703 StringBuilder stringBuilder; |
| 691 size_t i = 0; | 704 size_t i = 0; |
| 692 for (auto it = list.begin(); it != list.end(); ++it, ++i) { | 705 for (auto it = list.begin(); it != list.end(); ++it, ++i) { |
| 693 const DisplayItem& displayItem = *it; | 706 const DisplayItem& displayItem = *it; |
| 694 if (i) | 707 if (i) |
| 695 stringBuilder.append(",\n"); | 708 stringBuilder.append(",\n"); |
| 696 stringBuilder.append(String::format("{index: %d, ", (int)i)); | 709 stringBuilder.append(String::format("{index: %zu, ", i)); |
| 697 #ifndef NDEBUG | 710 #ifndef NDEBUG |
| 698 displayItem.dumpPropertiesAsDebugString(stringBuilder); | 711 displayItem.dumpPropertiesAsDebugString(stringBuilder); |
| 699 #else | 712 #else |
| 700 stringBuilder.append(String::format("clientDebugName: %s", displayItem.c lient().debugName().ascii().data())); | 713 stringBuilder.append(String::format("clientDebugName: %s", displayItem.c lient().debugName().ascii().data())); |
| 701 #endif | 714 #endif |
| 702 if (displayItem.hasValidClient()) { | 715 if (!displayItem.hasBeenMoved()) { |
| 703 do { | 716 do { |
| 704 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS | 717 #if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS |
| 705 if (!displayItem.client().isAlive()) { | 718 if (!displayItem.client().isAlive()) { |
| 706 stringBuilder.append(", clientIsAlive: false"); | 719 stringBuilder.append(", clientIsAlive: false"); |
| 707 break; | 720 break; |
| 708 } | 721 } |
| 709 #endif | 722 #endif |
| 710 stringBuilder.append(", cacheIsValid: "); | 723 stringBuilder.append(", cacheIsValid: "); |
| 711 stringBuilder.append(clientCacheIsValid(displayItem.client()) ? "true" : "false"); | 724 stringBuilder.append(clientCacheIsValid(displayItem.client()) ? "true" : "false"); |
| 712 } while (false); | 725 } while (false); |
| 713 } | 726 } |
| 714 if (list.hasVisualRect(i)) { | 727 if (list.hasVisualRect(i)) { |
| 715 IntRect visualRect = list.visualRect(i); | 728 IntRect visualRect = list.visualRect(i); |
| 716 stringBuilder.append(String::format(", visualRect: [%d,%d %dx%d]", | 729 stringBuilder.append(String::format(", visualRect: [%d,%d %dx%d]", |
| 717 visualRect.x(), visualRect.y(), | 730 visualRect.x(), visualRect.y(), |
| 718 visualRect.width(), visualRect.height())); | 731 visualRect.width(), visualRect.height())); |
| 719 } | 732 } |
| 720 stringBuilder.append('}'); | 733 stringBuilder.append('}'); |
| 721 } | 734 } |
| 722 return stringBuilder.toString(); | 735 return stringBuilder.toString(); |
| 723 } | 736 } |
| 724 | 737 |
| 725 void PaintController::showDebugData() const | 738 void PaintController::showDebugData() const |
| 726 { | 739 { |
| 727 WTFLogAlways("current display item list: [%s]\n", displayItemListAsDebugStri ng(m_currentPaintArtifact.getDisplayItemList()).utf8().data()); | 740 WTFLogAlways("current display item list: [%s]\n", displayItemListAsDebugStri ng(m_currentPaintArtifact.getDisplayItemList()).utf8().data()); |
| 728 WTFLogAlways("new display item list: [%s]\n", displayItemListAsDebugString(m _newDisplayItemList).utf8().data()); | 741 WTFLogAlways("new display item list: [%s]\n", displayItemListAsDebugString(m _newDisplayItemList).utf8().data()); |
| 729 } | 742 } |
| 730 | 743 |
| 731 } // namespace blink | 744 } // namespace blink |
| OLD | NEW |