Index: Source/platform/graphics/paint/DisplayItemListTest.cpp |
diff --git a/Source/platform/graphics/paint/DisplayItemListTest.cpp b/Source/platform/graphics/paint/DisplayItemListTest.cpp |
index 59e7642e15a0df630c18a0e3f31dec68c67c752b..b4d9437e617a7834cb2568729ae9fd5d70dbbcab 100644 |
--- a/Source/platform/graphics/paint/DisplayItemListTest.cpp |
+++ b/Source/platform/graphics/paint/DisplayItemListTest.cpp |
@@ -12,11 +12,40 @@ |
#include "platform/graphics/paint/ClipRecorder.h" |
#include "platform/graphics/paint/DrawingDisplayItem.h" |
#include "platform/graphics/paint/DrawingRecorder.h" |
-#include "platform/graphics/paint/SubtreeRecorder.h" |
+#include "platform/graphics/paint/SubtreeDisplayItem.h" |
#include <gtest/gtest.h> |
namespace blink { |
+class SimpleSubtreeRecorder { |
+public: |
+ static bool useCachedSubtreeIfPossible(DisplayItemList& displayItemList, const DisplayItemClientWrapper& client, int paintPhase) |
+ { |
+ if (displayItemList.subtreeCacheIsValid(client.displayItemClient(), DisplayItem::paintPhaseToBeginSubtreeType(paintPhase))) { |
+ displayItemList.createAndAppend<CachedDisplayItem>(client, DisplayItem::paintPhaseToCachedSubtreeType(paintPhase)); |
+ return true; |
+ } |
+ return false; |
+ } |
+ |
+ SimpleSubtreeRecorder(DisplayItemList& displayItemList, const DisplayItemClientWrapper& client, int paintPhase) |
+ : m_displayItemList(displayItemList) |
+ , m_client(client) |
+ , m_paintPhase(paintPhase) |
+ { |
+ displayItemList.createAndAppend<BeginSubtreeDisplayItem>(client, DisplayItem::paintPhaseToBeginSubtreeType(paintPhase)); |
+ } |
+ ~SimpleSubtreeRecorder() |
+ { |
+ m_displayItemList.createAndAppend<EndSubtreeDisplayItem>(m_client, DisplayItem::paintPhaseToEndSubtreeType(m_paintPhase)); |
+ } |
+ |
+private: |
+ DisplayItemList& m_displayItemList; |
+ const DisplayItemClientWrapper m_client; |
+ const int m_paintPhase; |
+}; |
+ |
class DisplayItemListTest : public ::testing::Test { |
public: |
DisplayItemListTest() |
@@ -462,26 +491,22 @@ TEST_F(DisplayItemListTest, CachedSubtreeSwapOrder) |
const int foregroundPaintPhase = foregroundDrawingType - DisplayItem::DrawingPaintPhaseFirst; |
{ |
- SubtreeRecorder r(context, container1, backgroundPaintPhase); |
- EXPECT_FALSE(r.canUseCache()); |
+ SimpleSubtreeRecorder r(displayItemList(), container1, backgroundPaintPhase); |
drawRect(context, container1, backgroundDrawingType, FloatRect(100, 100, 100, 100)); |
drawRect(context, content1, backgroundDrawingType, FloatRect(100, 100, 50, 200)); |
} |
{ |
- SubtreeRecorder r(context, container1, foregroundPaintPhase); |
- EXPECT_FALSE(r.canUseCache()); |
+ SimpleSubtreeRecorder r(displayItemList(), container1, foregroundPaintPhase); |
drawRect(context, content1, foregroundDrawingType, FloatRect(100, 100, 50, 200)); |
drawRect(context, container1, foregroundDrawingType, FloatRect(100, 100, 100, 100)); |
} |
{ |
- SubtreeRecorder r(context, container2, backgroundPaintPhase); |
- EXPECT_FALSE(r.canUseCache()); |
+ SimpleSubtreeRecorder r(displayItemList(), container2, backgroundPaintPhase); |
drawRect(context, container2, backgroundDrawingType, FloatRect(100, 200, 100, 100)); |
drawRect(context, content2, backgroundDrawingType, FloatRect(100, 200, 50, 200)); |
} |
{ |
- SubtreeRecorder r(context, container2, foregroundPaintPhase); |
- EXPECT_FALSE(r.canUseCache()); |
+ SimpleSubtreeRecorder r(displayItemList(), container2, foregroundPaintPhase); |
drawRect(context, content2, foregroundDrawingType, FloatRect(100, 200, 50, 200)); |
drawRect(context, container2, foregroundDrawingType, FloatRect(100, 200, 100, 100)); |
} |
@@ -509,17 +534,17 @@ TEST_F(DisplayItemListTest, CachedSubtreeSwapOrder) |
TestDisplayItem(container2, DisplayItem::paintPhaseToEndSubtreeType(foregroundPaintPhase))); |
// Simulate the situation when container1 e.g. gets a z-index that is now greater than container2. |
- displayItemList().createAndAppend<CachedDisplayItem>(container2, DisplayItem::paintPhaseToCachedSubtreeType(backgroundPaintPhase)); |
+ EXPECT_TRUE(SimpleSubtreeRecorder::useCachedSubtreeIfPossible(displayItemList(), container2, backgroundPaintPhase)); |
EXPECT_EQ((size_t)1, newPaintListBeforeUpdate().size()); |
EXPECT_TRUE(newPaintListBeforeUpdate().last().isCachedSubtree()); |
- displayItemList().createAndAppend<CachedDisplayItem>(container2, DisplayItem::paintPhaseToCachedSubtreeType(foregroundPaintPhase)); |
+ EXPECT_TRUE(SimpleSubtreeRecorder::useCachedSubtreeIfPossible(displayItemList(), container2, foregroundPaintPhase)); |
EXPECT_EQ((size_t)2, newPaintListBeforeUpdate().size()); |
EXPECT_TRUE(newPaintListBeforeUpdate().last().isCachedSubtree()); |
- displayItemList().createAndAppend<CachedDisplayItem>(container1, DisplayItem::paintPhaseToCachedSubtreeType(backgroundPaintPhase)); |
+ EXPECT_TRUE(SimpleSubtreeRecorder::useCachedSubtreeIfPossible(displayItemList(), container1, backgroundPaintPhase)); |
EXPECT_EQ((size_t)3, newPaintListBeforeUpdate().size()); |
EXPECT_TRUE(newPaintListBeforeUpdate().last().isCachedSubtree()); |
- displayItemList().createAndAppend<CachedDisplayItem>(container1, DisplayItem::paintPhaseToCachedSubtreeType(foregroundPaintPhase)); |
+ EXPECT_TRUE(SimpleSubtreeRecorder::useCachedSubtreeIfPossible(displayItemList(), container1, foregroundPaintPhase)); |
EXPECT_EQ((size_t)4, newPaintListBeforeUpdate().size()); |
EXPECT_TRUE(newPaintListBeforeUpdate().last().isCachedSubtree()); |
displayItemList().commitNewDisplayItems(); |
@@ -546,6 +571,108 @@ TEST_F(DisplayItemListTest, CachedSubtreeSwapOrder) |
TestDisplayItem(container1, DisplayItem::paintPhaseToEndSubtreeType(foregroundDrawingType))); |
} |
+TEST_F(DisplayItemListTest, CachedNestedSubtreeUpdate) |
+{ |
+ TestDisplayItemClient container1("container1"); |
+ TestDisplayItemClient content1("content1"); |
+ TestDisplayItemClient container2("container2"); |
+ TestDisplayItemClient content2("content2"); |
+ GraphicsContext context(&displayItemList()); |
+ const int backgroundPaintPhase = backgroundDrawingType - DisplayItem::DrawingPaintPhaseFirst; |
+ const int foregroundPaintPhase = foregroundDrawingType - DisplayItem::DrawingPaintPhaseFirst; |
+ |
+ { |
+ SimpleSubtreeRecorder r(displayItemList(), container1, backgroundPaintPhase); |
+ drawRect(context, container1, backgroundDrawingType, FloatRect(100, 100, 100, 100)); |
+ { |
+ SimpleSubtreeRecorder r(displayItemList(), content1, backgroundPaintPhase); |
+ drawRect(context, content1, backgroundDrawingType, FloatRect(100, 100, 50, 200)); |
+ } |
+ } |
+ { |
+ SimpleSubtreeRecorder r(displayItemList(), container1, foregroundPaintPhase); |
+ { |
+ SimpleSubtreeRecorder r(displayItemList(), content1, foregroundPaintPhase); |
+ drawRect(context, content1, foregroundDrawingType, FloatRect(100, 100, 50, 200)); |
+ } |
+ drawRect(context, container1, foregroundDrawingType, FloatRect(100, 100, 100, 100)); |
+ } |
+ { |
+ SimpleSubtreeRecorder r(displayItemList(), container2, backgroundPaintPhase); |
+ drawRect(context, container2, backgroundDrawingType, FloatRect(100, 200, 100, 100)); |
+ { |
+ SimpleSubtreeRecorder r(displayItemList(), content2, backgroundPaintPhase); |
+ drawRect(context, content2, backgroundDrawingType, FloatRect(100, 200, 50, 200)); |
+ } |
+ } |
+ displayItemList().commitNewDisplayItems(); |
+ |
+ EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 18, |
+ TestDisplayItem(container1, DisplayItem::paintPhaseToBeginSubtreeType(backgroundPaintPhase)), |
+ TestDisplayItem(container1, backgroundDrawingType), |
+ TestDisplayItem(content1, DisplayItem::paintPhaseToBeginSubtreeType(backgroundPaintPhase)), |
+ TestDisplayItem(content1, backgroundDrawingType), |
+ TestDisplayItem(content1, DisplayItem::paintPhaseToEndSubtreeType(backgroundPaintPhase)), |
+ TestDisplayItem(container1, DisplayItem::paintPhaseToEndSubtreeType(backgroundPaintPhase)), |
+ |
+ TestDisplayItem(container1, DisplayItem::paintPhaseToBeginSubtreeType(foregroundPaintPhase)), |
+ TestDisplayItem(content1, DisplayItem::paintPhaseToBeginSubtreeType(foregroundPaintPhase)), |
+ TestDisplayItem(content1, foregroundDrawingType), |
+ TestDisplayItem(content1, DisplayItem::paintPhaseToEndSubtreeType(foregroundPaintPhase)), |
+ TestDisplayItem(container1, foregroundDrawingType), |
+ TestDisplayItem(container1, DisplayItem::paintPhaseToEndSubtreeType(foregroundPaintPhase)), |
+ |
+ TestDisplayItem(container2, DisplayItem::paintPhaseToBeginSubtreeType(backgroundPaintPhase)), |
+ TestDisplayItem(container2, backgroundDrawingType), |
+ TestDisplayItem(content2, DisplayItem::paintPhaseToBeginSubtreeType(backgroundPaintPhase)), |
+ TestDisplayItem(content2, backgroundDrawingType), |
+ TestDisplayItem(content2, DisplayItem::paintPhaseToEndSubtreeType(backgroundPaintPhase)), |
+ TestDisplayItem(container2, DisplayItem::paintPhaseToEndSubtreeType(backgroundPaintPhase))); |
+ |
+ // Container2 itself now becomes empty (but still has the 'content2' child), and chooses not to output subtree info. |
+ displayItemList().invalidate(container2.displayItemClient()); |
+ displayItemList().invalidate(content2.displayItemClient()); |
+ EXPECT_FALSE(SimpleSubtreeRecorder::useCachedSubtreeIfPossible(displayItemList(), container2, backgroundPaintPhase)); |
+ EXPECT_FALSE(SimpleSubtreeRecorder::useCachedSubtreeIfPossible(displayItemList(), content2, backgroundPaintPhase)); |
+ // Content2 now outputs foreground. |
+ EXPECT_FALSE(SimpleSubtreeRecorder::useCachedSubtreeIfPossible(displayItemList(), content2, foregroundPaintPhase)); |
+ { |
+ SimpleSubtreeRecorder r(displayItemList(), content2, foregroundPaintPhase); |
+ drawRect(context, content2, foregroundDrawingType, FloatRect(100, 200, 50, 200)); |
+ } |
+ EXPECT_EQ((size_t)3, newPaintListBeforeUpdate().size()); |
+ |
+ // Container1 subtree now uses cached background, but not cached foreground. |
+ // The merge algorithm allows changing subtree without invalidating the displayItemClient. |
+ EXPECT_TRUE(SimpleSubtreeRecorder::useCachedSubtreeIfPossible(displayItemList(), container1, backgroundPaintPhase)); |
+ EXPECT_EQ((size_t)4, newPaintListBeforeUpdate().size()); |
+ EXPECT_TRUE(newPaintListBeforeUpdate().last().isCachedSubtree()); |
+ |
+ displayItemList().commitNewDisplayItems(); |
+ |
+ EXPECT_DISPLAY_LIST(displayItemList().displayItems(), 9, |
+ TestDisplayItem(content2, DisplayItem::paintPhaseToBeginSubtreeType(foregroundPaintPhase)), |
+ TestDisplayItem(content2, foregroundDrawingType), |
+ TestDisplayItem(content2, DisplayItem::paintPhaseToEndSubtreeType(foregroundPaintPhase)), |
+ |
+ TestDisplayItem(container1, DisplayItem::paintPhaseToBeginSubtreeType(backgroundPaintPhase)), |
+ TestDisplayItem(container1, backgroundDrawingType), |
+ TestDisplayItem(content1, DisplayItem::paintPhaseToBeginSubtreeType(backgroundPaintPhase)), |
+ TestDisplayItem(content1, backgroundDrawingType), |
+ TestDisplayItem(content1, DisplayItem::paintPhaseToEndSubtreeType(backgroundPaintPhase)), |
+ TestDisplayItem(container1, DisplayItem::paintPhaseToEndSubtreeType(backgroundPaintPhase))); |
+ |
+ EXPECT_TRUE(displayItemList().subtreeCacheIsValid(container1.displayItemClient(), DisplayItem::paintPhaseToBeginSubtreeType(backgroundPaintPhase))); |
+ EXPECT_TRUE(displayItemList().subtreeCacheIsValid(content1.displayItemClient(), DisplayItem::paintPhaseToBeginSubtreeType(backgroundPaintPhase))); |
+ EXPECT_FALSE(displayItemList().subtreeCacheIsValid(container1.displayItemClient(), DisplayItem::paintPhaseToBeginSubtreeType(foregroundPaintPhase))); |
+ EXPECT_FALSE(displayItemList().subtreeCacheIsValid(content1.displayItemClient(), DisplayItem::paintPhaseToBeginSubtreeType(foregroundPaintPhase))); |
+ |
+ EXPECT_FALSE(displayItemList().subtreeCacheIsValid(container2.displayItemClient(), DisplayItem::paintPhaseToBeginSubtreeType(backgroundPaintPhase))); |
+ EXPECT_FALSE(displayItemList().subtreeCacheIsValid(content2.displayItemClient(), DisplayItem::paintPhaseToBeginSubtreeType(backgroundPaintPhase))); |
+ EXPECT_FALSE(displayItemList().subtreeCacheIsValid(container2.displayItemClient(), DisplayItem::paintPhaseToBeginSubtreeType(foregroundPaintPhase))); |
+ EXPECT_TRUE(displayItemList().subtreeCacheIsValid(content2.displayItemClient(), DisplayItem::paintPhaseToBeginSubtreeType(foregroundPaintPhase))); |
+} |
+ |
TEST_F(DisplayItemListTest, Scope) |
{ |
TestDisplayItemClient multicol("multicol"); |