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 if (value) { |
| 23 m_paintChunksRasterInvalidationTrackingMap = |
| 24 wrapUnique(new RasterInvalidationTrackingMap<const PaintChunk>); |
| 25 } else { |
| 26 m_paintChunksRasterInvalidationTrackingMap = nullptr; |
| 27 } |
| 28 } |
| 29 |
21 const PaintArtifact& PaintController::paintArtifact() const { | 30 const PaintArtifact& PaintController::paintArtifact() const { |
22 DCHECK(m_newDisplayItemList.isEmpty()); | 31 DCHECK(m_newDisplayItemList.isEmpty()); |
23 DCHECK(m_newPaintChunks.isInInitialState()); | 32 DCHECK(m_newPaintChunks.isInInitialState()); |
24 return m_currentPaintArtifact; | 33 return m_currentPaintArtifact; |
25 } | 34 } |
26 | 35 |
27 bool PaintController::useCachedDrawingIfPossible( | 36 bool PaintController::useCachedDrawingIfPossible( |
28 const DisplayItemClient& client, | 37 const DisplayItemClient& client, |
29 DisplayItem::Type type) { | 38 DisplayItem::Type type) { |
30 DCHECK(DisplayItem::isDrawingType(type)); | 39 DCHECK(DisplayItem::isDrawingType(type)); |
(...skipping 551 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
582 m_currentPaintArtifact.getDisplayItemList().appendVisualRect( | 591 m_currentPaintArtifact.getDisplayItemList().appendVisualRect( |
583 visualRectForDisplayItem(displayItem, offsetFromLayoutObject)); | 592 visualRectForDisplayItem(displayItem, offsetFromLayoutObject)); |
584 } | 593 } |
585 | 594 |
586 void PaintController::generateChunkRasterInvalidationRects( | 595 void PaintController::generateChunkRasterInvalidationRects( |
587 PaintChunk& newChunk) { | 596 PaintChunk& newChunk) { |
588 DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); | 597 DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); |
589 if (newChunk.beginIndex >= m_currentCachedSubsequenceBeginIndexInNewList) | 598 if (newChunk.beginIndex >= m_currentCachedSubsequenceBeginIndexInNewList) |
590 return; | 599 return; |
591 | 600 |
| 601 static FloatRect infiniteFloatRect(LayoutRect::infiniteIntRect()); |
592 if (!newChunk.id) { | 602 if (!newChunk.id) { |
593 newChunk.rasterInvalidationRects.append( | 603 addRasterInvalidationInfo(nullptr, newChunk, infiniteFloatRect); |
594 FloatRect(LayoutRect::infiniteIntRect())); | |
595 return; | 604 return; |
596 } | 605 } |
597 | 606 |
598 // Try to match old chunk sequentially first. | 607 // Try to match old chunk sequentially first. |
599 const auto& oldChunks = m_currentPaintArtifact.paintChunks(); | 608 const auto& oldChunks = m_currentPaintArtifact.paintChunks(); |
600 while (m_nextChunkToMatch < oldChunks.size()) { | 609 while (m_nextChunkToMatch < oldChunks.size()) { |
601 const PaintChunk& oldChunk = oldChunks[m_nextChunkToMatch]; | 610 const PaintChunk& oldChunk = oldChunks[m_nextChunkToMatch]; |
602 if (newChunk.matches(oldChunk)) { | 611 if (newChunk.matches(oldChunk)) { |
603 generateChunkRasterInvalidationRectsComparingOldChunk(newChunk, oldChunk); | 612 generateChunkRasterInvalidationRectsComparingOldChunk(newChunk, oldChunk); |
604 ++m_nextChunkToMatch; | 613 ++m_nextChunkToMatch; |
(...skipping 20 matching lines...) Expand all Loading... |
625 for (size_t i : it->value) { | 634 for (size_t i : it->value) { |
626 if (newChunk.matches(oldChunks[i])) { | 635 if (newChunk.matches(oldChunks[i])) { |
627 generateChunkRasterInvalidationRectsComparingOldChunk(newChunk, | 636 generateChunkRasterInvalidationRectsComparingOldChunk(newChunk, |
628 oldChunks[i]); | 637 oldChunks[i]); |
629 return; | 638 return; |
630 } | 639 } |
631 } | 640 } |
632 } | 641 } |
633 | 642 |
634 // We reach here because the chunk is new. | 643 // We reach here because the chunk is new. |
635 newChunk.rasterInvalidationRects.append( | 644 addRasterInvalidationInfo(nullptr, newChunk, infiniteFloatRect); |
636 FloatRect(LayoutRect::infiniteIntRect())); | 645 } |
| 646 |
| 647 void PaintController::addRasterInvalidationInfo(const DisplayItemClient* client, |
| 648 PaintChunk& chunk, |
| 649 const FloatRect& rect) { |
| 650 chunk.rasterInvalidationRects.append(rect); |
| 651 if (!m_paintChunksRasterInvalidationTrackingMap) |
| 652 return; |
| 653 RasterInvalidationInfo info; |
| 654 info.rect = enclosingIntRect(rect); |
| 655 info.client = client; |
| 656 if (client) { |
| 657 info.clientDebugName = client->debugName(); |
| 658 info.reason = client->getPaintInvalidationReason(); |
| 659 } |
| 660 RasterInvalidationTracking& tracking = |
| 661 m_paintChunksRasterInvalidationTrackingMap->add(&chunk); |
| 662 tracking.trackedRasterInvalidations.append(info); |
637 } | 663 } |
638 | 664 |
639 void PaintController::generateChunkRasterInvalidationRectsComparingOldChunk( | 665 void PaintController::generateChunkRasterInvalidationRectsComparingOldChunk( |
640 PaintChunk& newChunk, | 666 PaintChunk& newChunk, |
641 const PaintChunk& oldChunk) { | 667 const PaintChunk& oldChunk) { |
642 DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); | 668 DCHECK(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); |
643 | 669 |
644 // TODO(wangxianzhu): Handle PaintInvalidationIncremental. | 670 // TODO(wangxianzhu): Handle PaintInvalidationIncremental. |
645 // TODO(wangxianzhu): Optimize paint offset change. | 671 // TODO(wangxianzhu): Optimize paint offset change. |
646 | 672 |
647 HashSet<const DisplayItemClient*> invalidatedClientsInOldChunk; | 673 HashSet<const DisplayItemClient*> invalidatedClientsInOldChunk; |
648 size_t highestMovedToIndex = 0; | 674 size_t highestMovedToIndex = 0; |
649 for (size_t oldIndex = oldChunk.beginIndex; oldIndex < oldChunk.endIndex; | 675 for (size_t oldIndex = oldChunk.beginIndex; oldIndex < oldChunk.endIndex; |
650 ++oldIndex) { | 676 ++oldIndex) { |
651 const DisplayItem& oldItem = | 677 const DisplayItem& oldItem = |
652 m_currentPaintArtifact.getDisplayItemList()[oldIndex]; | 678 m_currentPaintArtifact.getDisplayItemList()[oldIndex]; |
653 const DisplayItemClient* clientToInvalidate = nullptr; | 679 const DisplayItemClient* clientToInvalidate = nullptr; |
| 680 bool isPotentiallyInvalidClient = false; |
654 if (!oldItem.hasValidClient()) { | 681 if (!oldItem.hasValidClient()) { |
655 size_t movedToIndex = m_itemsMovedIntoNewList[oldIndex]; | 682 size_t movedToIndex = m_itemsMovedIntoNewList[oldIndex]; |
656 if (m_newDisplayItemList[movedToIndex].drawsContent()) { | 683 if (m_newDisplayItemList[movedToIndex].drawsContent()) { |
657 if (movedToIndex < newChunk.beginIndex || | 684 if (movedToIndex < newChunk.beginIndex || |
658 movedToIndex >= newChunk.endIndex) { | 685 movedToIndex >= newChunk.endIndex) { |
659 // The item has been moved into another chunk, so need to invalidate i
t in the old chunk. | 686 // The item has been moved into another chunk, so need to invalidate i
t in the old chunk. |
660 clientToInvalidate = &m_newDisplayItemList[movedToIndex].client(); | 687 clientToInvalidate = &m_newDisplayItemList[movedToIndex].client(); |
661 // And invalidate in the new chunk into which the item was moved. | 688 // And invalidate in the new chunk into which the item was moved. |
662 PaintChunk& movedToChunk = | 689 PaintChunk& movedToChunk = |
663 m_newPaintChunks.findChunkByDisplayItemIndex(movedToIndex); | 690 m_newPaintChunks.findChunkByDisplayItemIndex(movedToIndex); |
664 movedToChunk.rasterInvalidationRects.append( | 691 addRasterInvalidationInfo( |
665 clientToInvalidate->visualRect()); | 692 clientToInvalidate, movedToChunk, |
| 693 FloatRect(clientToInvalidate->visualRect())); |
666 } else if (movedToIndex < highestMovedToIndex) { | 694 } else if (movedToIndex < highestMovedToIndex) { |
667 // The item has been moved behind other cached items, so need to inval
idate the area | 695 // The item has been moved behind other cached items, so need to inval
idate the area |
668 // that is probably exposed by the item moved earlier. | 696 // that is probably exposed by the item moved earlier. |
669 clientToInvalidate = &m_newDisplayItemList[movedToIndex].client(); | 697 clientToInvalidate = &m_newDisplayItemList[movedToIndex].client(); |
670 } else { | 698 } else { |
671 highestMovedToIndex = movedToIndex; | 699 highestMovedToIndex = movedToIndex; |
672 } | 700 } |
673 } | 701 } |
674 } else if (oldItem.drawsContent()) { | 702 } else if (oldItem.drawsContent()) { |
| 703 isPotentiallyInvalidClient = true; |
675 clientToInvalidate = &oldItem.client(); | 704 clientToInvalidate = &oldItem.client(); |
676 } | 705 } |
677 if (clientToInvalidate && | 706 if (clientToInvalidate && |
678 invalidatedClientsInOldChunk.add(clientToInvalidate).isNewEntry) { | 707 invalidatedClientsInOldChunk.add(clientToInvalidate).isNewEntry) { |
679 newChunk.rasterInvalidationRects.append( | 708 addRasterInvalidationInfo( |
680 m_currentPaintArtifact.getDisplayItemList().visualRect(oldIndex)); | 709 isPotentiallyInvalidClient ? nullptr : clientToInvalidate, newChunk, |
| 710 FloatRect(m_currentPaintArtifact.getDisplayItemList().visualRect( |
| 711 oldIndex))); |
681 } | 712 } |
682 } | 713 } |
683 | 714 |
684 HashSet<const DisplayItemClient*> invalidatedClientsInNewChunk; | 715 HashSet<const DisplayItemClient*> invalidatedClientsInNewChunk; |
685 for (size_t newIndex = newChunk.beginIndex; newIndex < newChunk.endIndex; | 716 for (size_t newIndex = newChunk.beginIndex; newIndex < newChunk.endIndex; |
686 ++newIndex) { | 717 ++newIndex) { |
687 const DisplayItem& newItem = m_newDisplayItemList[newIndex]; | 718 const DisplayItem& newItem = m_newDisplayItemList[newIndex]; |
688 if (newItem.drawsContent() && !clientCacheIsValid(newItem.client()) && | 719 if (newItem.drawsContent() && !clientCacheIsValid(newItem.client()) && |
689 invalidatedClientsInNewChunk.add(&newItem.client()).isNewEntry) | 720 invalidatedClientsInNewChunk.add(&newItem.client()).isNewEntry) { |
690 newChunk.rasterInvalidationRects.append(newItem.client().visualRect()); | 721 addRasterInvalidationInfo(&newItem.client(), newChunk, |
| 722 FloatRect(newItem.client().visualRect())); |
| 723 } |
691 } | 724 } |
692 } | 725 } |
693 | 726 |
694 void PaintController::showUnderInvalidationError( | 727 void PaintController::showUnderInvalidationError( |
695 const char* reason, | 728 const char* reason, |
696 const DisplayItem& newItem, | 729 const DisplayItem& newItem, |
697 const DisplayItem* oldItem) const { | 730 const DisplayItem* oldItem) const { |
698 LOG(ERROR) << m_underInvalidationMessagePrefix << " " << reason; | 731 LOG(ERROR) << m_underInvalidationMessagePrefix << " " << reason; |
699 #ifndef NDEBUG | 732 #ifndef NDEBUG |
700 LOG(ERROR) << "New display item: " << newItem.asDebugString(); | 733 LOG(ERROR) << "New display item: " << newItem.asDebugString(); |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
836 m_currentPaintArtifact.getDisplayItemList(), showPictures) | 869 m_currentPaintArtifact.getDisplayItemList(), showPictures) |
837 .utf8() | 870 .utf8() |
838 .data()); | 871 .data()); |
839 WTFLogAlways("new display item list: [%s]\n", | 872 WTFLogAlways("new display item list: [%s]\n", |
840 displayItemListAsDebugString(m_newDisplayItemList, showPictures) | 873 displayItemListAsDebugString(m_newDisplayItemList, showPictures) |
841 .utf8() | 874 .utf8() |
842 .data()); | 875 .data()); |
843 } | 876 } |
844 | 877 |
845 } // namespace blink | 878 } // namespace blink |
OLD | NEW |