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/AutoReset.h" |
12 #include "wtf/text/StringBuilder.h" | 12 #include "wtf/text/StringBuilder.h" |
13 | 13 |
14 #ifndef NDEBUG | 14 #ifndef NDEBUG |
15 #include "platform/graphics/LoggingCanvas.h" | 15 #include "platform/graphics/LoggingCanvas.h" |
16 #include <stdio.h> | 16 #include <stdio.h> |
17 #endif | 17 #endif |
18 | 18 |
19 namespace blink { | 19 namespace blink { |
20 | 20 |
| 21 void PaintController::setTracksRasterInvalidations(bool value) |
| 22 { |
| 23 if (value) |
| 24 m_paintChunksRasterInvalidationTrackingMap = wrapUnique(new RasterInvali
dationTrackingMap<const PaintChunk>); |
| 25 else |
| 26 m_paintChunksRasterInvalidationTrackingMap = nullptr; |
| 27 } |
| 28 |
| 29 |
21 const PaintArtifact& PaintController::paintArtifact() const | 30 const PaintArtifact& PaintController::paintArtifact() const |
22 { | 31 { |
23 DCHECK(m_newDisplayItemList.isEmpty()); | 32 DCHECK(m_newDisplayItemList.isEmpty()); |
24 DCHECK(m_newPaintChunks.isInInitialState()); | 33 DCHECK(m_newPaintChunks.isInInitialState()); |
25 return m_currentPaintArtifact; | 34 return m_currentPaintArtifact; |
26 } | 35 } |
27 | 36 |
28 bool PaintController::useCachedDrawingIfPossible(const DisplayItemClient& client
, DisplayItem::Type type) | 37 bool PaintController::useCachedDrawingIfPossible(const DisplayItemClient& client
, DisplayItem::Type type) |
29 { | 38 { |
30 DCHECK(DisplayItem::isDrawingType(type)); | 39 DCHECK(DisplayItem::isDrawingType(type)); |
(...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
531 // TODO(wkorman): Only compute and append visual rect for drawings. | 540 // TODO(wkorman): Only compute and append visual rect for drawings. |
532 m_currentPaintArtifact.getDisplayItemList().appendVisualRect(visualRectForDi
splayItem(displayItem, offsetFromLayoutObject)); | 541 m_currentPaintArtifact.getDisplayItemList().appendVisualRect(visualRectForDi
splayItem(displayItem, offsetFromLayoutObject)); |
533 } | 542 } |
534 | 543 |
535 void PaintController::generateChunkRasterInvalidationRects(PaintChunk& newChunk) | 544 void PaintController::generateChunkRasterInvalidationRects(PaintChunk& newChunk) |
536 { | 545 { |
537 DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); | 546 DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); |
538 if (newChunk.beginIndex >= m_currentCachedSubsequenceBeginIndexInNewList) | 547 if (newChunk.beginIndex >= m_currentCachedSubsequenceBeginIndexInNewList) |
539 return; | 548 return; |
540 | 549 |
| 550 static FloatRect infiniteFloatRect(LayoutRect::infiniteIntRect()); |
541 if (!newChunk.id) { | 551 if (!newChunk.id) { |
542 newChunk.rasterInvalidationRects.append(FloatRect(LayoutRect::infiniteIn
tRect())); | 552 addRasterInvalidationInfo(nullptr, newChunk, infiniteFloatRect); |
543 return; | 553 return; |
544 } | 554 } |
545 | 555 |
546 // Try to match old chunk sequentially first. | 556 // Try to match old chunk sequentially first. |
547 const auto& oldChunks = m_currentPaintArtifact.paintChunks(); | 557 const auto& oldChunks = m_currentPaintArtifact.paintChunks(); |
548 while (m_nextChunkToMatch < oldChunks.size()) { | 558 while (m_nextChunkToMatch < oldChunks.size()) { |
549 const PaintChunk& oldChunk = oldChunks[m_nextChunkToMatch]; | 559 const PaintChunk& oldChunk = oldChunks[m_nextChunkToMatch]; |
550 if (newChunk.matches(oldChunk)) { | 560 if (newChunk.matches(oldChunk)) { |
551 generateChunkRasterInvalidationRectsComparingOldChunk(newChunk, oldC
hunk); | 561 generateChunkRasterInvalidationRectsComparingOldChunk(newChunk, oldC
hunk); |
552 ++m_nextChunkToMatch; | 562 ++m_nextChunkToMatch; |
(...skipping 15 matching lines...) Expand all Loading... |
568 if (it != m_outOfOrderChunkIndices.end()) { | 578 if (it != m_outOfOrderChunkIndices.end()) { |
569 for (size_t i : it->value) { | 579 for (size_t i : it->value) { |
570 if (newChunk.matches(oldChunks[i])) { | 580 if (newChunk.matches(oldChunks[i])) { |
571 generateChunkRasterInvalidationRectsComparingOldChunk(newChunk,
oldChunks[i]); | 581 generateChunkRasterInvalidationRectsComparingOldChunk(newChunk,
oldChunks[i]); |
572 return; | 582 return; |
573 } | 583 } |
574 } | 584 } |
575 } | 585 } |
576 | 586 |
577 // We reach here because the chunk is new. | 587 // We reach here because the chunk is new. |
578 newChunk.rasterInvalidationRects.append(FloatRect(LayoutRect::infiniteIntRec
t())); | 588 addRasterInvalidationInfo(nullptr, newChunk, infiniteFloatRect); |
| 589 } |
| 590 |
| 591 void PaintController::addRasterInvalidationInfo(const DisplayItemClient* client,
PaintChunk& chunk, const FloatRect& rect) |
| 592 { |
| 593 chunk.rasterInvalidationRects.append(rect); |
| 594 if (!m_paintChunksRasterInvalidationTrackingMap) |
| 595 return; |
| 596 |
| 597 RasterInvalidationInfo info; |
| 598 info.rect = enclosingIntRect(rect); |
| 599 info.client = client; |
| 600 if (client) { |
| 601 info.clientDebugName = client->debugName(); |
| 602 info.reason = client->getPaintInvalidationReason(); |
| 603 } |
| 604 |
| 605 RasterInvalidationTracking& tracking = m_paintChunksRasterInvalidationTracki
ngMap->add(&chunk); |
| 606 tracking.trackedRasterInvalidations.append(info); |
579 } | 607 } |
580 | 608 |
581 void PaintController::generateChunkRasterInvalidationRectsComparingOldChunk(Pain
tChunk& newChunk, const PaintChunk& oldChunk) | 609 void PaintController::generateChunkRasterInvalidationRectsComparingOldChunk(Pain
tChunk& newChunk, const PaintChunk& oldChunk) |
582 { | 610 { |
583 DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); | 611 DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); |
584 | 612 |
585 // TODO(wangxianzhu): Handle PaintInvalidationIncremental. | 613 // TODO(wangxianzhu): Handle PaintInvalidationIncremental. |
586 // TODO(wangxianzhu): Optimize paint offset change. | 614 // TODO(wangxianzhu): Optimize paint offset change. |
587 | 615 |
588 HashSet<const DisplayItemClient*> invalidatedClientsInOldChunk; | 616 HashSet<const DisplayItemClient*> invalidatedClientsInOldChunk; |
589 size_t highestMovedToIndex = 0; | 617 size_t highestMovedToIndex = 0; |
590 for (size_t oldIndex = oldChunk.beginIndex; oldIndex < oldChunk.endIndex; ++
oldIndex) { | 618 for (size_t oldIndex = oldChunk.beginIndex; oldIndex < oldChunk.endIndex; ++
oldIndex) { |
591 const DisplayItem& oldItem = m_currentPaintArtifact.getDisplayItemList()
[oldIndex]; | 619 const DisplayItem& oldItem = m_currentPaintArtifact.getDisplayItemList()
[oldIndex]; |
592 const DisplayItemClient* clientToInvalidate = nullptr; | 620 const DisplayItemClient* clientToInvalidate = nullptr; |
593 if (!oldItem.hasValidClient()) { | 621 if (!oldItem.hasValidClient()) { |
594 size_t movedToIndex = m_itemsMovedIntoNewList[oldIndex]; | 622 size_t movedToIndex = m_itemsMovedIntoNewList[oldIndex]; |
595 if (m_newDisplayItemList[movedToIndex].drawsContent()) { | 623 if (m_newDisplayItemList[movedToIndex].drawsContent()) { |
596 if (movedToIndex < newChunk.beginIndex || movedToIndex >= newChu
nk.endIndex) { | 624 if (movedToIndex < newChunk.beginIndex || movedToIndex >= newChu
nk.endIndex) { |
597 // The item has been moved into another chunk, so need to in
validate it in the old chunk. | 625 // The item has been moved into another chunk, so need to in
validate it in the old chunk. |
598 clientToInvalidate = &m_newDisplayItemList[movedToIndex].cli
ent(); | 626 clientToInvalidate = &m_newDisplayItemList[movedToIndex].cli
ent(); |
599 // And invalidate in the new chunk into which the item was m
oved. | 627 // And invalidate in the new chunk into which the item was m
oved. |
600 PaintChunk& movedToChunk = m_newPaintChunks.findChunkByDispl
ayItemIndex(movedToIndex); | 628 PaintChunk& movedToChunk = m_newPaintChunks.findChunkByDispl
ayItemIndex(movedToIndex); |
601 movedToChunk.rasterInvalidationRects.append(clientToInvalida
te->visualRect()); | 629 |
| 630 addRasterInvalidationInfo(clientToInvalidate, movedToChunk,
FloatRect(clientToInvalidate->visualRect())); |
602 } else if (movedToIndex < highestMovedToIndex) { | 631 } else if (movedToIndex < highestMovedToIndex) { |
603 // The item has been moved behind other cached items, so nee
d to invalidate the area | 632 // The item has been moved behind other cached items, so nee
d to invalidate the area |
604 // that is probably exposed by the item moved earlier. | 633 // that is probably exposed by the item moved earlier. |
605 clientToInvalidate = &m_newDisplayItemList[movedToIndex].cli
ent(); | 634 clientToInvalidate = &m_newDisplayItemList[movedToIndex].cli
ent(); |
606 } else { | 635 } else { |
607 highestMovedToIndex = movedToIndex; | 636 highestMovedToIndex = movedToIndex; |
608 } | 637 } |
609 } | 638 } |
610 } else if (oldItem.drawsContent()) { | 639 } else if (oldItem.drawsContent()) { |
611 clientToInvalidate = &oldItem.client(); | 640 clientToInvalidate = &oldItem.client(); |
612 } | 641 } |
613 if (clientToInvalidate && invalidatedClientsInOldChunk.add(clientToInval
idate).isNewEntry) { | 642 if (clientToInvalidate && invalidatedClientsInOldChunk.add(clientToInval
idate).isNewEntry) { |
614 newChunk.rasterInvalidationRects.append(m_currentPaintArtifact.getDi
splayItemList().visualRect(oldIndex)); | 643 addRasterInvalidationInfo(clientToInvalidate, newChunk, FloatRect(m_
currentPaintArtifact.getDisplayItemList().visualRect(oldIndex))); |
| 644 |
615 } | 645 } |
616 } | 646 } |
617 | 647 |
618 HashSet<const DisplayItemClient*> invalidatedClientsInNewChunk; | 648 HashSet<const DisplayItemClient*> invalidatedClientsInNewChunk; |
619 for (size_t newIndex = newChunk.beginIndex; newIndex < newChunk.endIndex; ++
newIndex) { | 649 for (size_t newIndex = newChunk.beginIndex; newIndex < newChunk.endIndex; ++
newIndex) { |
620 const DisplayItem& newItem = m_newDisplayItemList[newIndex]; | 650 const DisplayItem& newItem = m_newDisplayItemList[newIndex]; |
621 if (newItem.drawsContent() && !clientCacheIsValid(newItem.client()) && i
nvalidatedClientsInNewChunk.add(&newItem.client()).isNewEntry) | 651 if (newItem.drawsContent() && !clientCacheIsValid(newItem.client()) && i
nvalidatedClientsInNewChunk.add(&newItem.client()).isNewEntry) { |
622 newChunk.rasterInvalidationRects.append(newItem.client().visualRect(
)); | 652 addRasterInvalidationInfo(&newItem.client(), newChunk, FloatRect(new
Item.client().visualRect())); |
| 653 } |
623 } | 654 } |
624 } | 655 } |
625 | 656 |
626 void PaintController::showUnderInvalidationError(const char* reason, const Displ
ayItem& newItem, const DisplayItem* oldItem) const | 657 void PaintController::showUnderInvalidationError(const char* reason, const Displ
ayItem& newItem, const DisplayItem* oldItem) const |
627 { | 658 { |
628 LOG(ERROR) << m_underInvalidationMessagePrefix << " " << reason; | 659 LOG(ERROR) << m_underInvalidationMessagePrefix << " " << reason; |
629 #ifndef NDEBUG | 660 #ifndef NDEBUG |
630 LOG(ERROR) << "New display item: " << newItem.asDebugString(); | 661 LOG(ERROR) << "New display item: " << newItem.asDebugString(); |
631 LOG(ERROR) << "Old display item: " << (oldItem ? oldItem->asDebugString() :
"None"); | 662 LOG(ERROR) << "Old display item: " << (oldItem ? oldItem->asDebugString() :
"None"); |
632 #else | 663 #else |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
739 return stringBuilder.toString(); | 770 return stringBuilder.toString(); |
740 } | 771 } |
741 | 772 |
742 void PaintController::showDebugDataInternal(bool showPictures) const | 773 void PaintController::showDebugDataInternal(bool showPictures) const |
743 { | 774 { |
744 WTFLogAlways("current display item list: [%s]\n", displayItemListAsDebugStri
ng(m_currentPaintArtifact.getDisplayItemList(), showPictures).utf8().data()); | 775 WTFLogAlways("current display item list: [%s]\n", displayItemListAsDebugStri
ng(m_currentPaintArtifact.getDisplayItemList(), showPictures).utf8().data()); |
745 WTFLogAlways("new display item list: [%s]\n", displayItemListAsDebugString(m
_newDisplayItemList, showPictures).utf8().data()); | 776 WTFLogAlways("new display item list: [%s]\n", displayItemListAsDebugString(m
_newDisplayItemList, showPictures).utf8().data()); |
746 } | 777 } |
747 | 778 |
748 } // namespace blink | 779 } // namespace blink |
OLD | NEW |