Simplify subtree (now subsequence) caching

We no longer need paint-phase-based subtree display items because we'll
use paint layers as units of subtrees. This greatly simplifies subtree
caching.

Renamed subtree to subsequence.

BUG=410087

Review URL: https://codereview.chromium.org/1313223002

git-svn-id: svn://svn.chromium.org/blink/trunk@201282 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent d7eed001
...@@ -23,28 +23,12 @@ ...@@ -23,28 +23,12 @@
#include "core/paint/ScrollRecorder.h" #include "core/paint/ScrollRecorder.h"
#include "core/paint/ScrollableAreaPainter.h" #include "core/paint/ScrollableAreaPainter.h"
#include "platform/graphics/paint/ClipRecorder.h" #include "platform/graphics/paint/ClipRecorder.h"
#include "platform/graphics/paint/SubtreeRecorder.h"
#include "wtf/Optional.h" #include "wtf/Optional.h"
namespace blink { namespace blink {
// We need to balance the benefit of subtree optimization and the cost of subtree display items.
// Only output subtree information if the block has multiple children or multiple line boxes.
static bool needsSubtreeRecorder(const LayoutBlock& layoutBlock)
{
return (layoutBlock.firstChild() && layoutBlock.firstChild()->nextSibling())
|| (layoutBlock.isLayoutBlockFlow() && toLayoutBlockFlow(layoutBlock).firstLineBox() && toLayoutBlockFlow(layoutBlock).firstLineBox()->nextLineBox());
}
void BlockPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset) void BlockPainter::paint(const PaintInfo& paintInfo, const LayoutPoint& paintOffset)
{ {
Optional<SubtreeRecorder> subtreeRecorder;
if (needsSubtreeRecorder(m_layoutBlock)) {
subtreeRecorder.emplace(*paintInfo.context, m_layoutBlock, paintInfo.phase);
if (subtreeRecorder->canUseCache())
return;
}
PaintInfo localPaintInfo(paintInfo); PaintInfo localPaintInfo(paintInfo);
LayoutPoint adjustedPaintOffset = paintOffset + m_layoutBlock.location(); LayoutPoint adjustedPaintOffset = paintOffset + m_layoutBlock.location();
......
...@@ -247,12 +247,10 @@ TEST_F(DisplayItemListPaintTestForSlimmingPaintV2, InlineRelayout) ...@@ -247,12 +247,10 @@ TEST_F(DisplayItemListPaintTestForSlimmingPaintV2, InlineRelayout)
InlineTextBox& newFirstTextBox = *newText.firstTextBox(); InlineTextBox& newFirstTextBox = *newText.firstTextBox();
InlineTextBox& secondTextBox = *newText.firstTextBox()->nextTextBox(); InlineTextBox& secondTextBox = *newText.firstTextBox()->nextTextBox();
EXPECT_DISPLAY_LIST_WITH_RED_FILL_IN_DEBUG(rootDisplayItemList().displayItems(), 5, EXPECT_DISPLAY_LIST_WITH_RED_FILL_IN_DEBUG(rootDisplayItemList().displayItems(), 3,
TestDisplayItem(layoutView, DisplayItem::BoxDecorationBackground), TestDisplayItem(layoutView, DisplayItem::BoxDecorationBackground),
TestDisplayItem(divBlock, DisplayItem::paintPhaseToBeginSubtreeType(PaintPhaseForeground)),
TestDisplayItem(newFirstTextBox, DisplayItem::paintPhaseToDrawingType(PaintPhaseForeground)), TestDisplayItem(newFirstTextBox, DisplayItem::paintPhaseToDrawingType(PaintPhaseForeground)),
TestDisplayItem(secondTextBox, DisplayItem::paintPhaseToDrawingType(PaintPhaseForeground)), TestDisplayItem(secondTextBox, DisplayItem::paintPhaseToDrawingType(PaintPhaseForeground)));
TestDisplayItem(divBlock, DisplayItem::paintPhaseToEndSubtreeType(PaintPhaseForeground)));
} }
} // namespace blink } // namespace blink
...@@ -680,9 +680,9 @@ ...@@ -680,9 +680,9 @@
'graphics/paint/ScrollDisplayItem.cpp', 'graphics/paint/ScrollDisplayItem.cpp',
'graphics/paint/ScrollDisplayItem.h', 'graphics/paint/ScrollDisplayItem.h',
'graphics/paint/SkPictureBuilder.h', 'graphics/paint/SkPictureBuilder.h',
'graphics/paint/SubtreeDisplayItem.h', 'graphics/paint/SubsequenceDisplayItem.h',
'graphics/paint/SubtreeRecorder.cpp', 'graphics/paint/SubsequenceRecorder.cpp',
'graphics/paint/SubtreeRecorder.h', 'graphics/paint/SubsequenceRecorder.h',
'graphics/paint/Transform3DDisplayItem.cpp', 'graphics/paint/Transform3DDisplayItem.cpp',
'graphics/paint/Transform3DDisplayItem.h', 'graphics/paint/Transform3DDisplayItem.h',
'graphics/paint/TransformDisplayItem.cpp', 'graphics/paint/TransformDisplayItem.cpp',
......
...@@ -180,13 +180,6 @@ WTF::String DisplayItem::typeAsDebugString(Type type) ...@@ -180,13 +180,6 @@ WTF::String DisplayItem::typeAsDebugString(Type type)
if (isEndTransform3DType(type)) if (isEndTransform3DType(type))
return "End" + transform3DTypeAsDebugString(endTransform3DTypeToTransform3DType(type)); return "End" + transform3DTypeAsDebugString(endTransform3DTypeToTransform3DType(type));
PAINT_PHASE_BASED_DEBUG_STRINGS(CachedSubtree);
PAINT_PHASE_BASED_DEBUG_STRINGS(BeginSubtree);
PAINT_PHASE_BASED_DEBUG_STRINGS(EndSubtree);
if (type == UninitializedType)
return "UninitializedType";
switch (type) { switch (type) {
DEBUG_STRING_CASE(BeginFilter); DEBUG_STRING_CASE(BeginFilter);
DEBUG_STRING_CASE(EndFilter); DEBUG_STRING_CASE(EndFilter);
...@@ -200,6 +193,10 @@ WTF::String DisplayItem::typeAsDebugString(Type type) ...@@ -200,6 +193,10 @@ WTF::String DisplayItem::typeAsDebugString(Type type)
DEBUG_STRING_CASE(EndFixedPosition); DEBUG_STRING_CASE(EndFixedPosition);
DEBUG_STRING_CASE(BeginFixedPositionContainer); DEBUG_STRING_CASE(BeginFixedPositionContainer);
DEBUG_STRING_CASE(EndFixedPositionContainer); DEBUG_STRING_CASE(EndFixedPositionContainer);
DEBUG_STRING_CASE(BeginSubsequence);
DEBUG_STRING_CASE(EndSubsequence);
DEBUG_STRING_CASE(CachedSubsequence);
DEBUG_STRING_CASE(UninitializedType);
DEFAULT_CASE; DEFAULT_CASE;
} }
} }
......
...@@ -164,20 +164,9 @@ public: ...@@ -164,20 +164,9 @@ public:
BeginFixedPositionContainer, BeginFixedPositionContainer,
EndFixedPositionContainer, EndFixedPositionContainer,
CachedSubtreeFirst, BeginSubsequence,
CachedSubtreePaintPhaseFirst = CachedSubtreeFirst, EndSubsequence,
CachedSubtreePaintPhaseLast = CachedSubtreePaintPhaseFirst + PaintPhaseMax, CachedSubsequence,
CachedSubtreeLast = CachedSubtreePaintPhaseLast,
BeginSubtreeFirst,
BeginSubtreePaintPhaseFirst = BeginSubtreeFirst,
BeginSubtreePaintPhaseLast = BeginSubtreePaintPhaseFirst + PaintPhaseMax,
BeginSubtreeLast = BeginSubtreePaintPhaseLast,
EndSubtreeFirst,
EndSubtreePaintPhaseFirst = EndSubtreeFirst,
EndSubtreePaintPhaseLast = EndSubtreePaintPhaseFirst + PaintPhaseMax,
EndSubtreeLast = EndSubtreePaintPhaseLast,
UninitializedType, UninitializedType,
TypeLast = UninitializedType TypeLast = UninitializedType
...@@ -238,8 +227,8 @@ public: ...@@ -238,8 +227,8 @@ public:
{ {
if (isCachedDrawingType(type)) if (isCachedDrawingType(type))
return cachedDrawingTypeToDrawingType(type); return cachedDrawingTypeToDrawingType(type);
if (isCachedSubtreeType(type)) if (type == CachedSubsequence)
return cachedSubtreeTypeToBeginSubtreeType(type); return BeginSubsequence;
return type; return type;
} }
...@@ -319,19 +308,9 @@ public: ...@@ -319,19 +308,9 @@ public:
DEFINE_PAIRED_CATEGORY_METHODS(Transform3D, transform3D); DEFINE_PAIRED_CATEGORY_METHODS(Transform3D, transform3D);
DEFINE_CATEGORY_METHODS(CachedSubtree) static bool isCachedType(Type type) { return isCachedDrawingType(type) || type == CachedSubsequence; }
DEFINE_PAINT_PHASE_CONVERSION_METHOD(CachedSubtree)
DEFINE_CATEGORY_METHODS(BeginSubtree)
DEFINE_PAINT_PHASE_CONVERSION_METHOD(BeginSubtree)
DEFINE_CATEGORY_METHODS(EndSubtree)
DEFINE_PAINT_PHASE_CONVERSION_METHOD(EndSubtree)
DEFINE_CONVERSION_METHODS(CachedSubtree, cachedSubtree, BeginSubtree, beginSubtree)
DEFINE_CONVERSION_METHODS(CachedSubtree, cachedSubtree, EndSubtree, endSubtree)
DEFINE_CONVERSION_METHODS(BeginSubtree, beginSubtree, EndSubtree, endSubtree)
static bool isCachedType(Type type) { return isCachedDrawingType(type) || isCachedSubtreeType(type); }
bool isCached() const { return isCachedType(m_type); } bool isCached() const { return isCachedType(m_type); }
static bool isCacheableType(Type type) { return isDrawingType(type) || isBeginSubtreeType(type); } static bool isCacheableType(Type type) { return isDrawingType(type) || type == BeginSubsequence; }
bool isCacheable() const { return !skippedCache() && isCacheableType(m_type); } bool isCacheable() const { return !skippedCache() && isCacheableType(m_type); }
virtual bool isBegin() const { return false; } virtual bool isBegin() const { return false; }
......
...@@ -73,7 +73,7 @@ void DisplayItemList::processNewItem(DisplayItem* displayItem) ...@@ -73,7 +73,7 @@ void DisplayItemList::processNewItem(DisplayItem* displayItem)
// Verify noop begin/end pairs have been removed. // Verify noop begin/end pairs have been removed.
if (m_newDisplayItems.size() >= 2 && displayItem->isEnd()) { if (m_newDisplayItems.size() >= 2 && displayItem->isEnd()) {
const auto& beginDisplayItem = m_newDisplayItems[m_newDisplayItems.size() - 2]; const auto& beginDisplayItem = m_newDisplayItems[m_newDisplayItems.size() - 2];
if (beginDisplayItem.isBegin() && !beginDisplayItem.drawsContent()) if (beginDisplayItem.isBegin() && beginDisplayItem.type() != DisplayItem::BeginSubsequence && !beginDisplayItem.drawsContent())
ASSERT(!displayItem->isEndAndPairedWith(beginDisplayItem.type())); ASSERT(!displayItem->isEndAndPairedWith(beginDisplayItem.type()));
} }
#endif #endif
...@@ -178,20 +178,20 @@ DisplayItems::iterator DisplayItemList::findOutOfOrderCachedItem(DisplayItems::i ...@@ -178,20 +178,20 @@ DisplayItems::iterator DisplayItemList::findOutOfOrderCachedItem(DisplayItems::i
{ {
ASSERT(clientCacheIsValid(id.client)); ASSERT(clientCacheIsValid(id.client));
// Skip indexing of copied items.
if (currentIt - context.nextItemToIndex > 0)
context.nextItemToIndex = currentIt;
size_t foundIndex = findMatchingItemFromIndex(id, context.displayItemIndicesByClient, m_currentDisplayItems); size_t foundIndex = findMatchingItemFromIndex(id, context.displayItemIndicesByClient, m_currentDisplayItems);
if (foundIndex != kNotFound) if (foundIndex != kNotFound)
return m_currentDisplayItems.begin() + foundIndex; return m_currentDisplayItems.begin() + foundIndex;
return findOutOfOrderCachedItemForward(id, context); return findOutOfOrderCachedItemForward(currentIt, id, context);
} }
// Find forward for the item and index all skipped indexable items. // Find forward for the item and index all skipped indexable items.
DisplayItems::iterator DisplayItemList::findOutOfOrderCachedItemForward(const DisplayItem::Id& id, OutOfOrderIndexContext& context) DisplayItems::iterator DisplayItemList::findOutOfOrderCachedItemForward(DisplayItems::iterator currentIt, const DisplayItem::Id& id, OutOfOrderIndexContext& context)
{ {
// Items before currentIt should have been copied. Skip indexing of them.
if (currentIt - context.nextItemToIndex > 0)
context.nextItemToIndex = currentIt;
DisplayItems::iterator currentEnd = m_currentDisplayItems.end(); DisplayItems::iterator currentEnd = m_currentDisplayItems.end();
for (; context.nextItemToIndex != currentEnd; ++context.nextItemToIndex) { for (; context.nextItemToIndex != currentEnd; ++context.nextItemToIndex) {
const DisplayItem& item = *context.nextItemToIndex; const DisplayItem& item = *context.nextItemToIndex;
...@@ -206,30 +206,30 @@ DisplayItems::iterator DisplayItemList::findOutOfOrderCachedItemForward(const Di ...@@ -206,30 +206,30 @@ DisplayItems::iterator DisplayItemList::findOutOfOrderCachedItemForward(const Di
return currentEnd; return currentEnd;
} }
void DisplayItemList::copyCachedSubtree(DisplayItems::iterator& currentIt, DisplayItems& updatedList) void DisplayItemList::copyCachedSubsequence(DisplayItems::iterator& currentIt, DisplayItems& updatedList)
{ {
ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled()); ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled());
ASSERT(currentIt->isBeginSubtree()); ASSERT(currentIt->type() == DisplayItem::BeginSubsequence);
ASSERT(!currentIt->scope()); ASSERT(!currentIt->scope());
DisplayItem::Id endSubtreeId(currentIt->client(), DisplayItem::beginSubtreeTypeToEndSubtreeType(currentIt->type()), 0); DisplayItem::Id endSubsequenceId(currentIt->client(), DisplayItem::EndSubsequence, 0);
do { do {
// We should always find the EndSubtree display item. // We should always find the EndSubsequence display item.
ASSERT(currentIt != m_currentDisplayItems.end()); ASSERT(currentIt != m_currentDisplayItems.end());
updatedList.appendByMoving(*currentIt, currentIt->derivedSize()); updatedList.appendByMoving(*currentIt, currentIt->derivedSize());
++currentIt; ++currentIt;
} while (!endSubtreeId.matches(updatedList.last())); } while (!endSubsequenceId.matches(updatedList.last()));
} }
// Update the existing display items by removing invalidated entries, updating // Update the existing display items by removing invalidated entries, updating
// repainted ones, and appending new items. // repainted ones, and appending new items.
// - For CachedDisplayItem, copy the corresponding cached DrawingDisplayItem; // - For CachedDisplayItem, copy the corresponding cached DrawingDisplayItem;
// - For SubtreeCachedDisplayItem, copy the cached display items between the // - For SubsequenceCachedDisplayItem, copy the cached display items between the
// corresponding BeginSubtreeDisplayItem and EndSubtreeDisplayItem (incl.); // corresponding BeginSubsequenceDisplayItem and EndSubsequenceDisplayItem (incl.);
// - Otherwise, copy the new display item. // - Otherwise, copy the new display item.
// //
// The algorithm is O(|m_currentDisplayItems| + |m_newDisplayItems|). // The algorithm is O(|m_currentDisplayItems| + |m_newDisplayItems|).
// Coefficients are related to the ratio of out-of-order [Subtree]CachedDisplayItems // Coefficients are related to the ratio of out-of-order [Subsequence]CachedDisplayItems
// and the average number of (Drawing|BeginSubtree)DisplayItems per client. // and the average number of (Drawing|BeginSubsequence)DisplayItems per client.
// //
// TODO(pdr): Implement the DisplayListDiff algorithm for SlimmingPaintV2. // TODO(pdr): Implement the DisplayListDiff algorithm for SlimmingPaintV2.
void DisplayItemList::commitNewDisplayItems(DisplayListDiff*) void DisplayItemList::commitNewDisplayItems(DisplayListDiff*)
...@@ -295,32 +295,28 @@ void DisplayItemList::commitNewDisplayItems(DisplayListDiff*) ...@@ -295,32 +295,28 @@ void DisplayItemList::commitNewDisplayItems(DisplayListDiff*)
ASSERT(newDisplayItem.isCached()); ASSERT(newDisplayItem.isCached());
ASSERT(clientCacheIsValid(newDisplayItem.client())); ASSERT(clientCacheIsValid(newDisplayItem.client()));
if (!isSynchronized) { if (!isSynchronized) {
DisplayItems::iterator foundIt = findOutOfOrderCachedItem(currentIt, newDisplayItemId, outOfOrderIndexContext); currentIt = findOutOfOrderCachedItem(currentIt, newDisplayItemId, outOfOrderIndexContext);
if (foundIt == currentEnd) { if (currentIt == currentEnd) {
#ifndef NDEBUG #ifndef NDEBUG
showDebugData(); showDebugData();
WTFLogAlways("%s not found in m_currentDisplayItems\n", newDisplayItem.asDebugString().utf8().data()); WTFLogAlways("%s not found in m_currentDisplayItems\n", newDisplayItem.asDebugString().utf8().data());
#endif #endif
ASSERT_NOT_REACHED(); ASSERT_NOT_REACHED();
// We did not find the cached display item. This should be impossible, but may occur if there is a bug
// If foundIt == currentEnd, it means that we did not find the cached display item. This should be impossible, but may occur // in the system, such as under-invalidation, incorrect cache checking or duplicate display ids.
// if there is a bug in the system, such as under-invalidation, incorrect cache checking or duplicate display ids. In this case, // In this case, attempt to recover rather than crashing or bailing on display of the rest of the display list.
// attempt to recover rather than crashing or bailing on display of the rest of the display list.
continue; continue;
} }
ASSERT(foundIt != currentIt); // because we are in 'if (!isSynchronized)'
currentIt = foundIt;
} }
if (newDisplayItem.isCachedDrawing()) { if (newDisplayItem.isCachedDrawing()) {
updatedList.appendByMoving(*currentIt, currentIt->derivedSize()); updatedList.appendByMoving(*currentIt, currentIt->derivedSize());
++currentIt; ++currentIt;
} else { } else {
ASSERT(newDisplayItem.isCachedSubtree()); ASSERT(newDisplayItem.type() == DisplayItem::CachedSubsequence);
copyCachedSubtree(currentIt, updatedList); copyCachedSubsequence(currentIt, updatedList);
ASSERT(updatedList.last().isEndSubtree()); ASSERT(updatedList.last().type() == DisplayItem::EndSubsequence);
} }
} else { } else {
#if ENABLE(ASSERT) #if ENABLE(ASSERT)
......
...@@ -135,7 +135,7 @@ private: ...@@ -135,7 +135,7 @@ private:
WTF::String displayItemsAsDebugString(const DisplayItems&) const; WTF::String displayItemsAsDebugString(const DisplayItems&) const;
#endif #endif
// Indices into PaintList of all DrawingDisplayItems and BeginSubtreeDisplayItems of each client. // Indices into PaintList of all DrawingDisplayItems and BeginSubsequenceDisplayItems of each client.
// Temporarily used during merge to find out-of-order display items. // Temporarily used during merge to find out-of-order display items.
using DisplayItemIndicesByClientMap = HashMap<DisplayItemClient, Vector<size_t>>; using DisplayItemIndicesByClientMap = HashMap<DisplayItemClient, Vector<size_t>>;
...@@ -144,8 +144,8 @@ private: ...@@ -144,8 +144,8 @@ private:
struct OutOfOrderIndexContext; struct OutOfOrderIndexContext;
DisplayItems::iterator findOutOfOrderCachedItem(DisplayItems::iterator currentIt, const DisplayItem::Id&, OutOfOrderIndexContext&); DisplayItems::iterator findOutOfOrderCachedItem(DisplayItems::iterator currentIt, const DisplayItem::Id&, OutOfOrderIndexContext&);
DisplayItems::iterator findOutOfOrderCachedItemForward(const DisplayItem::Id&, OutOfOrderIndexContext&); DisplayItems::iterator findOutOfOrderCachedItemForward(DisplayItems::iterator currentIt, const DisplayItem::Id&, OutOfOrderIndexContext&);
void copyCachedSubtree(DisplayItems::iterator& currentIt, DisplayItems& updatedList); void copyCachedSubsequence(DisplayItems::iterator& currentIt, DisplayItems& updatedList);
#if ENABLE(ASSERT) #if ENABLE(ASSERT)
// The following two methods are for checking under-invalidations // The following two methods are for checking under-invalidations
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef SubtreeDisplayItem_h #ifndef SubsequenceDisplayItem_h
#define SubtreeDisplayItem_h #define SubsequenceDisplayItem_h
#include "platform/geometry/FloatRect.h" #include "platform/geometry/FloatRect.h"
#include "platform/graphics/paint/DisplayItem.h" #include "platform/graphics/paint/DisplayItem.h"
...@@ -11,28 +11,24 @@ ...@@ -11,28 +11,24 @@
namespace blink { namespace blink {
class BeginSubtreeDisplayItem final : public PairedBeginDisplayItem { class BeginSubsequenceDisplayItem final : public PairedBeginDisplayItem {
public: public:
BeginSubtreeDisplayItem(const DisplayItemClientWrapper& client, Type type) BeginSubsequenceDisplayItem(const DisplayItemClientWrapper& client)
: PairedBeginDisplayItem(client, type, sizeof(*this)) : PairedBeginDisplayItem(client, BeginSubsequence, sizeof(*this))
{ { }
ASSERT(isBeginSubtreeType(type));
}
}; };
class EndSubtreeDisplayItem final : public PairedEndDisplayItem { class EndSubsequenceDisplayItem final : public PairedEndDisplayItem {
public: public:
EndSubtreeDisplayItem(const DisplayItemClientWrapper& client, Type type) EndSubsequenceDisplayItem(const DisplayItemClientWrapper& client)
: PairedEndDisplayItem(client, type, sizeof(*this)) : PairedEndDisplayItem(client, EndSubsequence, sizeof(*this))
{ { }
ASSERT(isEndSubtreeType(type));
}
#if ENABLE(ASSERT) #if ENABLE(ASSERT)
bool isEndAndPairedWith(DisplayItem::Type otherType) const final { return DisplayItem::isBeginSubtreeType(otherType); } bool isEndAndPairedWith(DisplayItem::Type otherType) const final { return otherType == BeginSubsequence; }
#endif #endif
}; };
} // namespace blink } // namespace blink
#endif // SubtreeDisplayItem_h #endif // SubsequenceDisplayItem_h
...@@ -3,56 +3,52 @@ ...@@ -3,56 +3,52 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "config.h" #include "config.h"
#include "platform/graphics/paint/SubtreeRecorder.h" #include "platform/graphics/paint/SubsequenceRecorder.h"
#include "platform/RuntimeEnabledFeatures.h" #include "platform/RuntimeEnabledFeatures.h"
#include "platform/graphics/GraphicsContext.h" #include "platform/graphics/GraphicsContext.h"
#include "platform/graphics/paint/CachedDisplayItem.h" #include "platform/graphics/paint/CachedDisplayItem.h"
#include "platform/graphics/paint/DisplayItemList.h" #include "platform/graphics/paint/DisplayItemList.h"
#include "platform/graphics/paint/SubtreeDisplayItem.h" #include "platform/graphics/paint/SubsequenceDisplayItem.h"
namespace blink { namespace blink {
SubtreeRecorder::SubtreeRecorder(GraphicsContext& context, const DisplayItemClientWrapper& client, int paintPhase) bool SubsequenceRecorder::useCachedSubsequenceIfPossible(GraphicsContext& context, const DisplayItemClientWrapper& client)
: m_displayItemList(context.displayItemList())
, m_client(client)
, m_paintPhase(paintPhase)
, m_canUseCache(false)
#if ENABLE(ASSERT)
, m_checkedCanUseCache(false)
#endif
{ {
if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled()) if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled())
return; return false;
ASSERT(m_displayItemList); ASSERT(context.displayItemList());
if (context.displayItemList()->displayItemConstructionIsDisabled() || RuntimeEnabledFeatures::slimmingPaintUnderInvalidationCheckingEnabled())
return false;
// TODO(wangxianzhu): Implement subtree caching. if (!context.displayItemList()->clientCacheIsValid(client.displayItemClient()))
return false;
if (!m_canUseCache) context.displayItemList()->createAndAppend<CachedDisplayItem>(client, DisplayItem::CachedSubsequence);
m_displayItemList->createAndAppend<BeginSubtreeDisplayItem>(m_client, DisplayItem::paintPhaseToBeginSubtreeType(paintPhase)); return true;
} }
SubtreeRecorder::~SubtreeRecorder() SubsequenceRecorder::SubsequenceRecorder(GraphicsContext& context, const DisplayItemClientWrapper& client)
: m_displayItemList(context.displayItemList())
, m_client(client)
{ {
if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled()) if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled())
return; return;
ASSERT(m_checkedCanUseCache); ASSERT(m_displayItemList);
if (m_canUseCache) m_displayItemList->createAndAppend<BeginSubsequenceDisplayItem>(m_client);
m_displayItemList->createAndAppend<CachedDisplayItem>(m_client, DisplayItem::paintPhaseToCachedSubtreeType(m_paintPhase));
else if (m_displayItemList->lastDisplayItemIsNoopBegin())
m_displayItemList->removeLastDisplayItem();
else
m_displayItemList->createAndAppend<EndSubtreeDisplayItem>(m_client, DisplayItem::paintPhaseToEndSubtreeType(m_paintPhase));
} }
bool SubtreeRecorder::canUseCache() const SubsequenceRecorder::~SubsequenceRecorder()
{ {
#if ENABLE(ASSERT) if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled())
m_checkedCanUseCache = true; return;
#endif
return m_canUseCache; // Don't remove no-op BeginSubsequence/EndSubsequence pairs because we need to
// match them later with CachedSubsequences.
m_displayItemList->createAndAppend<EndSubsequenceDisplayItem>(m_client);
} }
} // namespace blink } // namespace blink
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef SubtreeRecorder_h #ifndef SubsequenceRecorder_h
#define SubtreeRecorder_h #define SubsequenceRecorder_h
#include "platform/graphics/paint/DisplayItemClient.h" #include "platform/graphics/paint/DisplayItemClient.h"
...@@ -12,26 +12,26 @@ namespace blink { ...@@ -12,26 +12,26 @@ namespace blink {
class DisplayItemList; class DisplayItemList;
class GraphicsContext; class GraphicsContext;
// Records subtree information during painting. The recorder's life span covers // SubsequenceRecorder records BeginSubsequenceDisplayItem and EndSubsequenceDisplayItem
// all painting operations executed during the root of the subtree's paint method // sentinels at either end of a continguous sequence of DisplayItems, and supports
// for the paint phase. // caching via a CachedDisplayItem with the CachedSubsequence DisplayItem type.
class PLATFORM_EXPORT SubtreeRecorder { //
// Also note that useCachedSubsequenceIfPossible is not sufficient to determine whether a
// CachedSubsequence can be used. In particular, the client is responsible for checking that
// none of the DisplayItemClients that contribute to the subsequence have been invalidated.
//
class PLATFORM_EXPORT SubsequenceRecorder {
public: public:
SubtreeRecorder(GraphicsContext&, const DisplayItemClientWrapper&, int paintPhase); static bool useCachedSubsequenceIfPossible(GraphicsContext&, const DisplayItemClientWrapper&);
~SubtreeRecorder();
bool canUseCache() const; SubsequenceRecorder(GraphicsContext&, const DisplayItemClientWrapper&);
~SubsequenceRecorder();
private: private:
DisplayItemList* m_displayItemList; DisplayItemList* m_displayItemList;
DisplayItemClientWrapper m_client; DisplayItemClientWrapper m_client;
const int m_paintPhase;
bool m_canUseCache;
#if ENABLE(ASSERT)
mutable bool m_checkedCanUseCache;
#endif
}; };
} // namespace blink } // namespace blink
#endif // SubtreeRecorder_h #endif // SubsequenceRecorder_h
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment