Commit 080b866a authored by wangxianzhu's avatar wangxianzhu Committed by Commit bot

Fix issues of display item client cache flags

- Clear just created flag if the client is used in any display item
  or chunk. Don't set a chunk client to validly cached status because
  it doesn't have any validly cached display item (otherwise it should
  have been marked validly cached in the m_newADisplayItemList loop.

- Invalidate the client if it has any display items skipped cache.

Review-Url: https://codereview.chromium.org/2185933003
Cr-Commit-Position: refs/heads/master@{#408251}
parent cfa709c1
......@@ -8,6 +8,7 @@
#include "core/layout/line/InlineTextBox.h"
#include "core/page/FocusController.h"
#include "core/paint/LayoutObjectDrawingRecorder.h"
#include "core/paint/ObjectPaintProperties.h"
#include "core/paint/PaintLayerPainter.h"
#include "platform/graphics/GraphicsContext.h"
#include "platform/graphics/paint/DrawingDisplayItem.h"
......@@ -63,4 +64,36 @@ TEST_P(PaintControllerPaintTestForSlimmingPaintV1AndV2, InlineRelayout)
TestDisplayItem(secondTextBox, foregroundType));
}
TEST_F(PaintControllerPaintTestForSlimmingPaintV2, ChunkIdClientCacheFlag)
{
setBodyInnerHTML(
"<div id='div' style='width: 200px; height: 200px; opacity: 0.5'>"
" <div style='width: 100px; height: 100px; background-color: blue'></div>"
"</div>");
PaintLayer& htmlLayer = *toLayoutBoxModelObject(document().documentElement()->layoutObject())->layer();
LayoutBlock& div = *toLayoutBlock(getLayoutObjectByElementId("div"));
LayoutObject& subDiv = *div.firstChild();
EXPECT_DISPLAY_LIST(rootPaintController().getDisplayItemList(), 6,
TestDisplayItem(layoutView(), documentBackgroundType),
TestDisplayItem(htmlLayer, DisplayItem::Subsequence),
TestDisplayItem(div, DisplayItem::BeginCompositing),
TestDisplayItem(subDiv, backgroundType),
TestDisplayItem(div, DisplayItem::EndCompositing),
TestDisplayItem(htmlLayer, DisplayItem::EndSubsequence));
const EffectPaintPropertyNode* effectNode = div.objectPaintProperties()->effect();
EXPECT_EQ(0.5f, effectNode->opacity());
const PaintChunk& chunk = rootPaintController().paintChunks()[1];
EXPECT_EQ(*div.layer(), chunk.id->client);
EXPECT_EQ(effectNode, chunk.properties.effect.get());
EXPECT_FALSE(div.layer()->isJustCreated());
// Client used by only paint chunks and non-cachaeable display items but not by any
// cacheable display items won't be marked as validly cached.
EXPECT_FALSE(rootPaintController().clientCacheIsValid(*div.layer()));
EXPECT_FALSE(rootPaintController().clientCacheIsValid(div));
EXPECT_TRUE(rootPaintController().clientCacheIsValid(subDiv));
}
} // namespace blink
......@@ -65,6 +65,7 @@ public:
// A client is considered "just created" if its display items have never been committed.
bool isJustCreated() const { return m_cacheGenerationOrInvalidationReason.isJustCreated(); }
void clearIsJustCreated() const { m_cacheGenerationOrInvalidationReason.clearIsJustCreated(); }
private:
friend class FakeDisplayItemClient;
......@@ -115,6 +116,7 @@ private:
}
bool isJustCreated() const { return m_value == kJustCreated; }
void clearIsJustCreated() { m_value = static_cast<ValueType>(PaintInvalidationFull); }
private:
typedef uint32_t ValueType;
......
......@@ -420,6 +420,7 @@ void PaintController::commitNewDisplayItems(const LayoutSize& offsetFromLayoutOb
SkPictureGpuAnalyzer gpuAnalyzer;
m_currentCacheGeneration = DisplayItemClient::CacheGenerationOrInvalidationReason::next();
Vector<const DisplayItemClient*> skippedCacheClients;
for (const auto& item : m_newDisplayItemList) {
// No reason to continue the analysis once we have a veto.
if (gpuAnalyzer.suitableForGpuRasterization())
......@@ -427,19 +428,30 @@ void PaintController::commitNewDisplayItems(const LayoutSize& offsetFromLayoutOb
m_newDisplayItemList.appendVisualRect(visualRectForDisplayItem(item, offsetFromLayoutObject));
if (item.isCacheable())
if (item.isCacheable()) {
item.client().setDisplayItemsCached(m_currentCacheGeneration);
} else {
if (item.client().isJustCreated())
item.client().clearIsJustCreated();
if (item.skippedCache())
skippedCacheClients.append(&item.client());
}
}
for (auto* client : skippedCacheClients)
client->setDisplayItemsUncached();
// The new list will not be appended to again so we can release unused memory.
m_newDisplayItemList.shrinkToFit();
m_currentPaintArtifact = PaintArtifact(std::move(m_newDisplayItemList), m_newPaintChunks.releasePaintChunks(), gpuAnalyzer.suitableForGpuRasterization());
resetCurrentListIndices();
m_outOfOrderItemIndices.clear();
for (const auto& chunk : m_currentPaintArtifact.paintChunks()) {
if (chunk.id)
chunk.id->client.setDisplayItemsCached(m_currentCacheGeneration);
if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
for (const auto& chunk : m_currentPaintArtifact.paintChunks()) {
if (chunk.id && chunk.id->client.isJustCreated())
chunk.id->client.clearIsJustCreated();
}
}
// We'll allocate the initial buffer when we start the next paint.
......
......@@ -828,6 +828,61 @@ TEST_F(PaintControllerTest, SkipCache)
getPaintController().commitNewDisplayItems();
}
TEST_F(PaintControllerTest, PartialSkipCache)
{
FakeDisplayItemClient content("content");
GraphicsContext context(getPaintController());
FloatRect rect1(100, 100, 50, 50);
FloatRect rect2(150, 100, 50, 50);
FloatRect rect3(200, 100, 50, 50);
drawRect(context, content, backgroundDrawingType, rect1);
getPaintController().beginSkippingCache();
drawRect(context, content, foregroundDrawingType, rect2);
getPaintController().endSkippingCache();
drawRect(context, content, foregroundDrawingType, rect3);
getPaintController().commitNewDisplayItems();
EXPECT_DISPLAY_LIST(getPaintController().getDisplayItemList(), 3,
TestDisplayItem(content, backgroundDrawingType),
TestDisplayItem(content, foregroundDrawingType),
TestDisplayItem(content, foregroundDrawingType));
RefPtr<const SkPicture> picture0 = static_cast<const DrawingDisplayItem&>(getPaintController().getDisplayItemList()[0]).picture();
RefPtr<const SkPicture> picture1 = static_cast<const DrawingDisplayItem&>(getPaintController().getDisplayItemList()[1]).picture();
RefPtr<const SkPicture> picture2 = static_cast<const DrawingDisplayItem&>(getPaintController().getDisplayItemList()[2]).picture();
EXPECT_NE(picture1, picture2);
// Content's cache is invalid because it has display items skipped cache.
EXPECT_FALSE(getPaintController().clientCacheIsValid(content));
EXPECT_EQ(PaintInvalidationFull, content.getPaintInvalidationReason());
// Draw again with nothing invalidated.
drawRect(context, content, backgroundDrawingType, rect1);
getPaintController().beginSkippingCache();
drawRect(context, content, foregroundDrawingType, rect2);
getPaintController().endSkippingCache();
drawRect(context, content, foregroundDrawingType, rect3);
EXPECT_EQ(0, numCachedNewItems());
#if DCHECK_IS_ON()
EXPECT_EQ(0, numSequentialMatches());
EXPECT_EQ(0, numOutOfOrderMatches());
EXPECT_EQ(0, numIndexedItems());
#endif
getPaintController().commitNewDisplayItems();
EXPECT_DISPLAY_LIST(getPaintController().getDisplayItemList(), 3,
TestDisplayItem(content, backgroundDrawingType),
TestDisplayItem(content, foregroundDrawingType),
TestDisplayItem(content, foregroundDrawingType));
EXPECT_NE(picture0, static_cast<const DrawingDisplayItem&>(getPaintController().getDisplayItemList()[0]).picture());
EXPECT_NE(picture1, static_cast<const DrawingDisplayItem&>(getPaintController().getDisplayItemList()[1]).picture());
EXPECT_NE(picture2, static_cast<const DrawingDisplayItem&>(getPaintController().getDisplayItemList()[2]).picture());
}
TEST_F(PaintControllerTest, OptimizeNoopPairs)
{
FakeDisplayItemClient first("first");
......
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