0

Revert of PaintChunk::id (patchset id:180001 of https://codereview.chromium.org/2116693002/ )

Reason for revert:
Test failures on WebKit Win x64 Builder (dbg) since https://build.chromium.org/p/chromium.webkit/builders/WebKit%20Win%20x64%20Builder%20%28dbg%29/builds/89039.

failures:
PaintChunkerTest.BuildChunksFromNestedTransforms
PaintChunkerTest.ChangingPropertiesWithoutItems
PaintChunkerTest.SingleNonEmptyRange
PaintChunkerTest.CreatesSeparateChunksWhenRequested
PaintChunkerTest.ChunkIds
PaintChunkerTest.SamePropertiesTwiceCombineIntoOneChunk
PaintChunkerTest.ChunkIdsSkippingCache
PaintChunkerTest.BuildMultipleChunksWithSinglePropertyChanging
PaintChunkerTest.CanRewindDisplayItemIndex
PaintChunkerTest.BuildMultipleChunksWithDifferentPropertyChanges

Original issue's description:
> PaintChunk::id
>
> The id will be used in rasterization paint invalidation to match old
> and new paint chunks. It can be also used in incremental layerization.
>
> BUG=510908
>
> Committed: https://crrev.com/5426e435a6a1c6761b7d9565f769fcde10e7b99c
> Cr-Commit-Position: refs/heads/master@{#406461}

TBR=chrishtr@chromium.org,pdr@chromium.org,wangxianzhu@chromium.org
# Skipping CQ checks because original CL landed less than 1 days ago.
NOPRESUBMIT=true
NOTREECHECKS=true
NOTRY=true
BUG=510908

Review-Url: https://codereview.chromium.org/2161253003
Cr-Commit-Position: refs/heads/master@{#406479}
This commit is contained in:
hayato
2016-07-19 21:20:40 -07:00
committed by Commit bot
parent d149b80d54
commit 3a9f8efd42
20 changed files with 131 additions and 403 deletions

@ -106,7 +106,6 @@
#include "platform/graphics/GraphicsLayerDebugInfo.h"
#include "platform/graphics/paint/CullRect.h"
#include "platform/graphics/paint/PaintController.h"
#include "platform/graphics/paint/ScopedPaintChunkProperties.h"
#include "platform/scheduler/CancellableTaskFactory.h"
#include "platform/scroll/ScrollAnimatorBase.h"
#include "platform/scroll/ScrollbarTheme.h"
@ -2643,15 +2642,16 @@ void FrameView::synchronizedPaintRecursively(GraphicsLayer* graphicsLayer)
// Usually this is not needed because the PaintLayer will setup the chunk properties
// altogether. However in debug builds the GraphicsLayer could paint debug background before
// we ever reach the PaintLayer.
Optional<ScopedPaintChunkProperties> scopedPaintChunkProperties;
if (RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {
PaintChunkProperties properties;
properties.transform = m_rootTransform;
properties.clip = m_rootClip;
properties.effect = m_rootEffect;
scopedPaintChunkProperties.emplace(graphicsLayer->getPaintController(), *layoutView(), DisplayItem::DebugRedFill, properties);
graphicsLayer->getPaintController().updateCurrentPaintChunkProperties(properties);
}
graphicsLayer->paint(nullptr);
if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
graphicsLayer->getPaintController().updateCurrentPaintChunkProperties(PaintChunkProperties());
}
if (!RuntimeEnabledFeatures::slimmingPaintV2Enabled()) {

@ -161,7 +161,7 @@ void BlockPainter::paintObject(const PaintInfo& paintInfo, const LayoutPoint& pa
if (auto* scrollTranslation = objectProperties ? objectProperties->scrollTranslation() : nullptr) {
PaintChunkProperties properties(paintInfo.context.getPaintController().currentPaintChunkProperties());
properties.transform = scrollTranslation;
m_scopedScrollProperty.emplace(paintInfo.context.getPaintController(), m_layoutBlock, DisplayItem::paintPhaseToDrawingType(paintPhase), properties);
m_scopedScrollProperty.emplace(paintInfo.context.getPaintController(), properties);
scrolledPaintInfo.emplace(paintInfo);
scrolledPaintInfo->updateCullRect(scrollTranslation->matrix().toAffineTransform());
}

@ -30,7 +30,7 @@ BoxClipper::BoxClipper(const LayoutBox& box, const PaintInfo& paintInfo, const L
if (objectProperties && objectProperties->overflowClip()) {
PaintChunkProperties properties(paintInfo.context.getPaintController().currentPaintChunkProperties());
properties.clip = objectProperties->overflowClip();
m_scopedClipProperty.emplace(paintInfo.context.getPaintController(), box, paintInfo.displayItemTypeForClipping(), properties);
m_scopedClipProperty.emplace(paintInfo.context.getPaintController(), properties);
}
return;
}

@ -54,7 +54,7 @@ void FramePainter::paint(GraphicsContext& context, const GlobalPaintFlags global
properties.transform = transform;
if (clip)
properties.clip = clip;
scopedPaintChunkProperties.emplace(context.getPaintController(), *frameView().layoutView(), properties);
scopedPaintChunkProperties.emplace(context.getPaintController(), properties);
}
}
@ -78,7 +78,7 @@ void FramePainter::paint(GraphicsContext& context, const GlobalPaintFlags global
if (TransformPaintPropertyNode* transform = m_frameView->preTranslation()) {
PaintChunkProperties properties(context.getPaintController().currentPaintChunkProperties());
properties.transform = transform;
scopedPaintChunkProperties.emplace(context.getPaintController(), *frameView().layoutView(), properties);
scopedPaintChunkProperties.emplace(context.getPaintController(), properties);
}
}

@ -378,7 +378,7 @@ PaintLayerPainter::PaintResult PaintLayerPainter::paintLayerContents(GraphicsCon
properties.clip = localBorderBoxProperties.propertyTreeState.clip;
properties.effect = localBorderBoxProperties.propertyTreeState.effect;
properties.backfaceHidden = m_paintLayer.layoutObject()->hasHiddenBackface();
scopedPaintChunkProperties.emplace(context.getPaintController(), m_paintLayer, properties);
scopedPaintChunkProperties.emplace(context.getPaintController(), properties);
}
bool shouldPaintBackground = isPaintingCompositedBackground && shouldPaintContent && !selectionOnly;

@ -65,7 +65,7 @@ public:
auto& paintController = context.getPaintController();
PaintChunkProperties properties(paintController.currentPaintChunkProperties());
properties.transform = objectProperties->svgLocalToBorderBoxTransform();
m_transformPropertyScope.emplace(paintController, object, properties);
m_transformPropertyScope.emplace(paintController, properties);
}
} else {
DCHECK(object.isSVG());
@ -77,7 +77,7 @@ public:
auto& paintController = context.getPaintController();
PaintChunkProperties properties(paintController.currentPaintChunkProperties());
properties.transform = objectProperties->transform();
m_transformPropertyScope.emplace(paintController, object, properties);
m_transformPropertyScope.emplace(paintController, properties);
}
}
}

@ -133,7 +133,7 @@ void ScrollableAreaPainter::paintOverflowControls(GraphicsContext& context, cons
if (objectProperties && objectProperties->scrollbarPaintOffset()) {
PaintChunkProperties properties(context.getPaintController().currentPaintChunkProperties());
properties.transform = objectProperties->scrollbarPaintOffset();
scopedTransformProperty.emplace(context.getPaintController(), getScrollableArea().box(), DisplayItem::ScrollOverflowControls, properties);
scopedTransformProperty.emplace(context.getPaintController(), properties);
}
}
if (getScrollableArea().horizontalScrollbar() && !getScrollableArea().layerForHorizontalScrollbar()) {

@ -1216,7 +1216,6 @@
'graphics/paint/DisplayItemTest.cpp',
'graphics/paint/GeometryMapperTest.cpp',
'graphics/paint/PaintArtifactToSkCanvasTest.cpp',
'graphics/paint/PaintChunkTest.cpp',
'graphics/paint/PaintChunkerTest.cpp',
'graphics/paint/PaintControllerTest.cpp',
'graphics/paint/PropertyTreeStateTest.cpp',

@ -215,7 +215,7 @@ public:
// Ids are for matching new DisplayItems with existing DisplayItems.
struct Id {
DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
STACK_ALLOCATED();
Id(const DisplayItemClient& client, const Type type)
: client(client)
, type(type) { }

@ -63,11 +63,7 @@ public:
PaintInvalidationReason getPaintInvalidationReason() const { return m_cacheGenerationOrInvalidationReason.getPaintInvalidationReason(); }
// A client is considered "just created" if its display items have never been committed.
bool isJustCreated() const { return m_cacheGenerationOrInvalidationReason.isJustCreated(); }
private:
friend class FakeDisplayItemClient;
friend class PaintController;
// Holds a unique cache generation id of DisplayItemClients and PaintControllers,
@ -85,16 +81,12 @@ private:
// only. The client will be treated as invalid on other paint controllers regardless if
// it's validly cached by these paint controllers. The situation is very rare (about 0.07%
// clients were painted on multiple paint controllers) so the performance penalty is trivial.
class PLATFORM_EXPORT CacheGenerationOrInvalidationReason {
class CacheGenerationOrInvalidationReason {
DISALLOW_NEW();
public:
CacheGenerationOrInvalidationReason() : m_value(kJustCreated) { }
CacheGenerationOrInvalidationReason() { invalidate(); }
void invalidate(PaintInvalidationReason reason = PaintInvalidationFull)
{
if (m_value != kJustCreated)
m_value = static_cast<ValueType>(reason);
}
void invalidate(PaintInvalidationReason reason = PaintInvalidationFull) { m_value = static_cast<ValueType>(reason); }
static CacheGenerationOrInvalidationReason next()
{
@ -111,17 +103,14 @@ private:
PaintInvalidationReason getPaintInvalidationReason() const
{
return m_value < kJustCreated ? static_cast<PaintInvalidationReason>(m_value) : PaintInvalidationNone;
return m_value < kFirstValidGeneration ? static_cast<PaintInvalidationReason>(m_value) : PaintInvalidationNone;
}
bool isJustCreated() const { return m_value == kJustCreated; }
private:
typedef uint32_t ValueType;
explicit CacheGenerationOrInvalidationReason(ValueType value) : m_value(value) { }
static const ValueType kJustCreated = static_cast<ValueType>(PaintInvalidationReasonMax) + 1;
static const ValueType kFirstValidGeneration = static_cast<ValueType>(PaintInvalidationReasonMax) + 2;
static const ValueType kFirstValidGeneration = static_cast<ValueType>(PaintInvalidationReasonMax) + 1;
static ValueType s_nextGeneration;
ValueType m_value;
};

@ -6,10 +6,8 @@
#define PaintChunk_h
#include "platform/geometry/FloatRect.h"
#include "platform/graphics/paint/DisplayItem.h"
#include "platform/graphics/paint/PaintChunkProperties.h"
#include "wtf/Allocator.h"
#include "wtf/Optional.h"
#include <iosfwd>
namespace blink {
@ -23,12 +21,8 @@ namespace blink {
struct PaintChunk {
DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
PaintChunk() : beginIndex(0), endIndex(0), knownToBeOpaque(false) { }
PaintChunk(unsigned begin, unsigned end, const DisplayItem::Id* chunkId, const PaintChunkProperties& props)
: beginIndex(begin), endIndex(end), properties(props), knownToBeOpaque(false)
{
if (chunkId)
id.emplace(*chunkId);
}
PaintChunk(unsigned begin, unsigned end, const PaintChunkProperties& props)
: beginIndex(begin), endIndex(end), properties(props), knownToBeOpaque(false) { }
unsigned size() const
{
@ -36,24 +30,6 @@ struct PaintChunk {
return endIndex - beginIndex;
}
// Check if a new PaintChunk (this) created in the latest paint matches an old
// PaintChunk created in the previous paint.
bool matches(const PaintChunk& old) const
{
// A PaintChunk without an id doesn't match any other PaintChunks.
if (!id || !old.id)
return false;
if (*id != *old.id)
return false;
#if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS
CHECK(id->client.isAlive());
#endif
// A chunk whose client is just created should not match any cached chunk,
// even if it's id equals the old chunk's id (which may happen if this chunk's
// client is just created at the same address of the old chunk's deleted client).
return !id->client.isJustCreated();
}
// Index of the first drawing in this chunk.
unsigned beginIndex;
@ -61,15 +37,6 @@ struct PaintChunk {
// |endIndex - beginIndex| drawings in the chunk.
unsigned endIndex;
// Identifier of this chunk. If it has a value, it should be unique.
// It's used to match a new chunk to a cached old chunk to track changes of chunk
// contents, so the id should be stable across document cycles.
// If the contents of the chunk can't be cached (e.g. it's created when PaintController
// is skipping cache, normally because display items can't be uniquely identified),
// id is nullopt so that the chunk won't match any other chunk.
using Id = DisplayItem::Id;
Optional<Id> id;
// The paint properties which apply to this chunk.
PaintChunkProperties properties;
@ -84,7 +51,6 @@ inline bool operator==(const PaintChunk& a, const PaintChunk& b)
{
return a.beginIndex == b.beginIndex
&& a.endIndex == b.endIndex
&& a.id == b.id
&& a.properties == b.properties
&& a.bounds == b.bounds
&& a.knownToBeOpaque == b.knownToBeOpaque;

@ -1,86 +0,0 @@
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "platform/graphics/paint/PaintChunk.h"
#include "platform/RuntimeEnabledFeatures.h"
#include "platform/testing/FakeDisplayItemClient.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "wtf/Optional.h"
namespace blink {
TEST(PaintChunkTest, matchesSame)
{
PaintChunkProperties properties;
FakeDisplayItemClient client;
client.updateCacheGeneration();
DisplayItem::Id id(client, DisplayItem::DrawingFirst);
EXPECT_TRUE(PaintChunk(0, 1, &id, properties).matches(PaintChunk(0, 1, &id, properties)));
}
TEST(PaintChunkTest, matchesEqual)
{
PaintChunkProperties properties;
FakeDisplayItemClient client;
client.updateCacheGeneration();
DisplayItem::Id id(client, DisplayItem::DrawingFirst);
DisplayItem::Id idEqual = id;
EXPECT_TRUE(PaintChunk(0, 1, &id, properties).matches(PaintChunk(0, 1, &idEqual, properties)));
EXPECT_TRUE(PaintChunk(0, 1, &idEqual, properties).matches(PaintChunk(0, 1, &id, properties)));
}
TEST(PaintChunkTest, IdNotMatches)
{
PaintChunkProperties properties;
FakeDisplayItemClient client1;
client1.updateCacheGeneration();
DisplayItem::Id id1a(client1, DisplayItem::DrawingFirst);
DisplayItem::Id id1b(client1, DisplayItem::Subsequence);
EXPECT_FALSE(PaintChunk(0, 1, &id1a, properties).matches(PaintChunk(0, 1, &id1b, properties)));
EXPECT_FALSE(PaintChunk(0, 1, &id1b, properties).matches(PaintChunk(0, 1, &id1a, properties)));
FakeDisplayItemClient client2;
client2.updateCacheGeneration();
DisplayItem::Id id2(client2, DisplayItem::DrawingFirst);
EXPECT_FALSE(PaintChunk(0, 1, &id1a, properties).matches(PaintChunk(0, 1, &id2, properties)));
EXPECT_FALSE(PaintChunk(0, 1, &id2, properties).matches(PaintChunk(0, 1, &id1a, properties)));
}
TEST(PaintChunkTest, IdNotMatchesNull)
{
PaintChunkProperties properties;
FakeDisplayItemClient client;
client.updateCacheGeneration();
DisplayItem::Id id(client, DisplayItem::DrawingFirst);
EXPECT_FALSE(PaintChunk(0, 1, nullptr, properties).matches(PaintChunk(0, 1, &id, properties)));
EXPECT_FALSE(PaintChunk(0, 1, &id, properties).matches(PaintChunk(0, 1, nullptr, properties)));
EXPECT_FALSE(PaintChunk(0, 1, nullptr, properties).matches(PaintChunk(0, 1, nullptr, properties)));
}
TEST(PaintChunkTest, IdNotMatchesJustCreated)
{
PaintChunkProperties properties;
Optional<FakeDisplayItemClient> client;
client.emplace();
EXPECT_TRUE(client->isJustCreated());
// Invalidation won't change the "just created" status.
client->setDisplayItemsUncached();
EXPECT_TRUE(client->isJustCreated());
DisplayItem::Id id(*client, DisplayItem::DrawingFirst);
// A chunk of a newly created client doesn't match any chunk because it's never cached.
EXPECT_FALSE(PaintChunk(0, 1, &id, properties).matches(PaintChunk(0, 1, &id, properties)));
client->updateCacheGeneration();
EXPECT_TRUE(PaintChunk(0, 1, &id, properties).matches(PaintChunk(0, 1, &id, properties)));
// Delete the current object and create a new object at the same address.
client = WTF::nullopt;
client.emplace();
EXPECT_TRUE(client->isJustCreated());
EXPECT_FALSE(PaintChunk(0, 1, &id, properties).matches(PaintChunk(0, 1, &id, properties)));
}
} // namespace blink

@ -16,41 +16,19 @@ PaintChunker::~PaintChunker()
{
}
void PaintChunker::updateCurrentPaintChunkProperties(const PaintChunk::Id* chunkId, const PaintChunkProperties& properties)
void PaintChunker::updateCurrentPaintChunkProperties(const PaintChunkProperties& properties)
{
ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled());
m_currentChunkId = WTF::nullopt;
if (chunkId)
m_currentChunkId.emplace(*chunkId);
m_currentProperties = properties;
}
void PaintChunker::incrementDisplayItemIndex(const DisplayItem& item)
void PaintChunker::incrementDisplayItemIndex(ItemBehavior behavior)
{
ASSERT(RuntimeEnabledFeatures::slimmingPaintV2Enabled());
ItemBehavior behavior;
Optional<PaintChunk::Id> newChunkId;
if (DisplayItem::isForeignLayerType(item.getType())) {
behavior = RequiresSeparateChunk;
// Use null chunkId if we are skipping cache, so that the chunk will not
// match any old chunk and will be treated as brand new.
if (!item.skippedCache())
newChunkId.emplace(item.getId());
// Clear m_currentChunkId so that any display items after the foreign layer
// without a new chunk id will be treated as having no id to avoid the chunk
// from using the same id as the chunk before the foreign layer chunk.
m_currentChunkId = WTF::nullopt;
} else {
behavior = DefaultBehavior;
if (!item.skippedCache() && m_currentChunkId)
newChunkId.emplace(*m_currentChunkId);
}
if (m_chunks.isEmpty()) {
PaintChunk newChunk(0, 1, newChunkId ? &*newChunkId : nullptr, m_currentProperties);
PaintChunk newChunk(0, 1, m_currentProperties);
m_chunks.append(newChunk);
m_chunkBehavior.append(behavior);
return;
@ -65,7 +43,7 @@ void PaintChunker::incrementDisplayItemIndex(const DisplayItem& item)
return;
}
PaintChunk newChunk(lastChunk.endIndex, lastChunk.endIndex + 1, newChunkId ? &*newChunkId : nullptr, m_currentProperties);
PaintChunk newChunk(lastChunk.endIndex, lastChunk.endIndex + 1, m_currentProperties);
m_chunks.append(newChunk);
m_chunkBehavior.append(behavior);
}
@ -88,7 +66,6 @@ void PaintChunker::clear()
{
m_chunks.clear();
m_chunkBehavior.clear();
m_currentChunkId = WTF::nullopt;
m_currentProperties = PaintChunkProperties();
}
@ -97,7 +74,6 @@ Vector<PaintChunk> PaintChunker::releasePaintChunks()
Vector<PaintChunk> chunks;
chunks.swap(m_chunks);
m_chunkBehavior.clear();
m_currentChunkId = WTF::nullopt;
m_currentProperties = PaintChunkProperties();
return chunks;
}

@ -6,7 +6,6 @@
#define PaintChunker_h
#include "platform/PlatformExport.h"
#include "platform/graphics/paint/DisplayItem.h"
#include "platform/graphics/paint/PaintChunk.h"
#include "platform/graphics/paint/PaintChunkProperties.h"
#include "wtf/Allocator.h"
@ -22,15 +21,23 @@ class PLATFORM_EXPORT PaintChunker final {
DISALLOW_NEW();
WTF_MAKE_NONCOPYABLE(PaintChunker);
public:
enum ItemBehavior {
// Can be combined with adjacent items when building chunks.
DefaultBehavior = 0,
// Item requires its own paint chunk.
RequiresSeparateChunk,
};
PaintChunker();
~PaintChunker();
bool isInInitialState() const { return m_chunks.isEmpty() && m_currentProperties == PaintChunkProperties(); }
const PaintChunkProperties& currentPaintChunkProperties() const { return m_currentProperties; }
void updateCurrentPaintChunkProperties(const PaintChunk::Id*, const PaintChunkProperties&);
void updateCurrentPaintChunkProperties(const PaintChunkProperties&);
void incrementDisplayItemIndex(const DisplayItem&);
void incrementDisplayItemIndex(ItemBehavior);
void decrementDisplayItemIndex();
void clear();
@ -40,17 +47,8 @@ public:
Vector<PaintChunk> releasePaintChunks();
private:
enum ItemBehavior {
// Can be combined with adjacent items when building chunks.
DefaultBehavior = 0,
// Item requires its own paint chunk.
RequiresSeparateChunk,
};
Vector<PaintChunk> m_chunks;
Vector<ItemBehavior> m_chunkBehavior;
Optional<PaintChunk::Id> m_currentChunkId;
PaintChunkProperties m_currentProperties;
};

@ -31,26 +31,6 @@ private:
RuntimeEnabledFeatures::Backup m_featuresBackup;
};
class TestDisplayItem : public DisplayItem, public DisplayItemClient {
public:
TestDisplayItem(DisplayItem::Type type) : DisplayItem(*this, type, sizeof(*this)) { }
void replay(GraphicsContext&) const final { NOTREACHED(); }
void appendToWebDisplayItemList(const IntRect&, WebDisplayItemList*) const final { NOTREACHED(); }
String debugName() const final { return "Test"; }
LayoutRect visualRect() const final { return LayoutRect(); }
};
class NormalTestDisplayItem : public TestDisplayItem {
public:
NormalTestDisplayItem() : TestDisplayItem(DisplayItem::DrawingFirst) { }
};
class TestDisplayItemRequiringSeparateChunk : public TestDisplayItem {
public:
TestDisplayItemRequiringSeparateChunk() : TestDisplayItem(DisplayItem::ForeignLayerPlugin) { }
};
TEST_F(PaintChunkerTest, Empty)
{
Vector<PaintChunk> chunks = PaintChunker().releasePaintChunks();
@ -60,108 +40,108 @@ TEST_F(PaintChunkerTest, Empty)
TEST_F(PaintChunkerTest, SingleNonEmptyRange)
{
PaintChunker chunker;
chunker.updateCurrentPaintChunkProperties(nullptr, rootPaintChunkProperties());
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.updateCurrentPaintChunkProperties(rootPaintChunkProperties());
chunker.incrementDisplayItemIndex(PaintChunker::DefaultBehavior);
chunker.incrementDisplayItemIndex(PaintChunker::DefaultBehavior);
Vector<PaintChunk> chunks = chunker.releasePaintChunks();
EXPECT_THAT(chunks, ElementsAre(
PaintChunk(0, 2, nullptr, rootPaintChunkProperties())));
PaintChunk(0, 2, rootPaintChunkProperties())));
}
TEST_F(PaintChunkerTest, SamePropertiesTwiceCombineIntoOneChunk)
{
PaintChunker chunker;
chunker.updateCurrentPaintChunkProperties(nullptr, rootPaintChunkProperties());
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.updateCurrentPaintChunkProperties(nullptr, rootPaintChunkProperties());
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.updateCurrentPaintChunkProperties(rootPaintChunkProperties());
chunker.incrementDisplayItemIndex(PaintChunker::DefaultBehavior);
chunker.incrementDisplayItemIndex(PaintChunker::DefaultBehavior);
chunker.updateCurrentPaintChunkProperties(rootPaintChunkProperties());
chunker.incrementDisplayItemIndex(PaintChunker::DefaultBehavior);
Vector<PaintChunk> chunks = chunker.releasePaintChunks();
EXPECT_THAT(chunks, ElementsAre(
PaintChunk(0, 3, nullptr, rootPaintChunkProperties())));
PaintChunk(0, 3, rootPaintChunkProperties())));
}
TEST_F(PaintChunkerTest, CanRewindDisplayItemIndex)
{
PaintChunker chunker;
chunker.updateCurrentPaintChunkProperties(nullptr, rootPaintChunkProperties());
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.updateCurrentPaintChunkProperties(rootPaintChunkProperties());
chunker.incrementDisplayItemIndex(PaintChunker::DefaultBehavior);
chunker.incrementDisplayItemIndex(PaintChunker::DefaultBehavior);
chunker.decrementDisplayItemIndex();
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.incrementDisplayItemIndex(PaintChunker::DefaultBehavior);
Vector<PaintChunk> chunks = chunker.releasePaintChunks();
EXPECT_THAT(chunks, ElementsAre(
PaintChunk(0, 2, nullptr, rootPaintChunkProperties())));
PaintChunk(0, 2, rootPaintChunkProperties())));
}
TEST_F(PaintChunkerTest, BuildMultipleChunksWithSinglePropertyChanging)
{
PaintChunker chunker;
chunker.updateCurrentPaintChunkProperties(nullptr, rootPaintChunkProperties());
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.updateCurrentPaintChunkProperties(rootPaintChunkProperties());
chunker.incrementDisplayItemIndex(PaintChunker::DefaultBehavior);
chunker.incrementDisplayItemIndex(PaintChunker::DefaultBehavior);
PaintChunkProperties simpleTransform;
simpleTransform.transform = TransformPaintPropertyNode::create(TransformationMatrix(0, 1, 2, 3, 4, 5), FloatPoint3D(9, 8, 7));
chunker.updateCurrentPaintChunkProperties(nullptr, simpleTransform);
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.updateCurrentPaintChunkProperties(simpleTransform);
chunker.incrementDisplayItemIndex(PaintChunker::DefaultBehavior);
PaintChunkProperties anotherTransform;
anotherTransform.transform = TransformPaintPropertyNode::create(TransformationMatrix(0, 1, 2, 3, 4, 5), FloatPoint3D(9, 8, 7));
chunker.updateCurrentPaintChunkProperties(nullptr, anotherTransform);
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.updateCurrentPaintChunkProperties(anotherTransform);
chunker.incrementDisplayItemIndex(PaintChunker::DefaultBehavior);
Vector<PaintChunk> chunks = chunker.releasePaintChunks();
EXPECT_THAT(chunks, ElementsAre(
PaintChunk(0, 2, nullptr, rootPaintChunkProperties()),
PaintChunk(2, 3, nullptr, simpleTransform),
PaintChunk(3, 4, nullptr, anotherTransform)));
PaintChunk(0, 2, rootPaintChunkProperties()),
PaintChunk(2, 3, simpleTransform),
PaintChunk(3, 4, anotherTransform)));
}
TEST_F(PaintChunkerTest, BuildMultipleChunksWithDifferentPropertyChanges)
{
PaintChunker chunker;
chunker.updateCurrentPaintChunkProperties(nullptr, rootPaintChunkProperties());
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.updateCurrentPaintChunkProperties(rootPaintChunkProperties());
chunker.incrementDisplayItemIndex(PaintChunker::DefaultBehavior);
PaintChunkProperties simpleTransform;
simpleTransform.transform = TransformPaintPropertyNode::create(TransformationMatrix(0, 0, 0, 0, 0, 0), FloatPoint3D(9, 8, 7));
chunker.updateCurrentPaintChunkProperties(nullptr, simpleTransform);
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.updateCurrentPaintChunkProperties(simpleTransform);
chunker.incrementDisplayItemIndex(PaintChunker::DefaultBehavior);
chunker.incrementDisplayItemIndex(PaintChunker::DefaultBehavior);
PaintChunkProperties simpleTransformAndEffect;
simpleTransformAndEffect.transform = simpleTransform.transform;
simpleTransformAndEffect.effect = EffectPaintPropertyNode::create(0.5f);
chunker.updateCurrentPaintChunkProperties(nullptr, simpleTransformAndEffect);
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.updateCurrentPaintChunkProperties(simpleTransformAndEffect);
chunker.incrementDisplayItemIndex(PaintChunker::DefaultBehavior);
chunker.incrementDisplayItemIndex(PaintChunker::DefaultBehavior);
PaintChunkProperties simpleTransformAndEffectWithUpdatedTransform;
simpleTransformAndEffectWithUpdatedTransform.transform = TransformPaintPropertyNode::create(TransformationMatrix(1, 1, 0, 0, 0, 0), FloatPoint3D(9, 8, 7));
simpleTransformAndEffectWithUpdatedTransform.effect = EffectPaintPropertyNode::create(simpleTransformAndEffect.effect->opacity());
chunker.updateCurrentPaintChunkProperties(nullptr, simpleTransformAndEffectWithUpdatedTransform);
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.updateCurrentPaintChunkProperties(simpleTransformAndEffectWithUpdatedTransform);
chunker.incrementDisplayItemIndex(PaintChunker::DefaultBehavior);
chunker.incrementDisplayItemIndex(PaintChunker::DefaultBehavior);
// Test that going back to a previous chunk property still creates a new chunk.
chunker.updateCurrentPaintChunkProperties(nullptr, simpleTransformAndEffect);
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.updateCurrentPaintChunkProperties(simpleTransformAndEffect);
chunker.incrementDisplayItemIndex(PaintChunker::DefaultBehavior);
chunker.incrementDisplayItemIndex(PaintChunker::DefaultBehavior);
Vector<PaintChunk> chunks = chunker.releasePaintChunks();
EXPECT_THAT(chunks, ElementsAre(
PaintChunk(0, 1, nullptr, rootPaintChunkProperties()),
PaintChunk(1, 3, nullptr, simpleTransform),
PaintChunk(3, 5, nullptr, simpleTransformAndEffect),
PaintChunk(5, 7, nullptr, simpleTransformAndEffectWithUpdatedTransform),
PaintChunk(7, 9, nullptr, simpleTransformAndEffect)));
PaintChunk(0, 1, rootPaintChunkProperties()),
PaintChunk(1, 3, simpleTransform),
PaintChunk(3, 5, simpleTransformAndEffect),
PaintChunk(5, 7, simpleTransformAndEffectWithUpdatedTransform),
PaintChunk(7, 9, simpleTransformAndEffect)));
}
TEST_F(PaintChunkerTest, BuildChunksFromNestedTransforms)
@ -170,47 +150,47 @@ TEST_F(PaintChunkerTest, BuildChunksFromNestedTransforms)
// sequence of transforms and display items:
// <root xform>, <paint>, <a xform>, <paint>, <paint>, </a xform>, <paint>, </root xform>
PaintChunker chunker;
chunker.updateCurrentPaintChunkProperties(nullptr, rootPaintChunkProperties());
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.updateCurrentPaintChunkProperties(rootPaintChunkProperties());
chunker.incrementDisplayItemIndex(PaintChunker::DefaultBehavior);
PaintChunkProperties simpleTransform;
simpleTransform.transform = TransformPaintPropertyNode::create(TransformationMatrix(0, 1, 2, 3, 4, 5), FloatPoint3D(9, 8, 7));
chunker.updateCurrentPaintChunkProperties(nullptr, simpleTransform);
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.updateCurrentPaintChunkProperties(simpleTransform);
chunker.incrementDisplayItemIndex(PaintChunker::DefaultBehavior);
chunker.incrementDisplayItemIndex(PaintChunker::DefaultBehavior);
chunker.updateCurrentPaintChunkProperties(nullptr, rootPaintChunkProperties());
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.updateCurrentPaintChunkProperties(rootPaintChunkProperties());
chunker.incrementDisplayItemIndex(PaintChunker::DefaultBehavior);
Vector<PaintChunk> chunks = chunker.releasePaintChunks();
EXPECT_THAT(chunks, ElementsAre(
PaintChunk(0, 1, nullptr, rootPaintChunkProperties()),
PaintChunk(1, 3, nullptr, simpleTransform),
PaintChunk(3, 4, nullptr, rootPaintChunkProperties())));
PaintChunk(0, 1, rootPaintChunkProperties()),
PaintChunk(1, 3, simpleTransform),
PaintChunk(3, 4, rootPaintChunkProperties())));
}
TEST_F(PaintChunkerTest, ChangingPropertiesWithoutItems)
{
// Test that properties can change without display items being generated.
PaintChunker chunker;
chunker.updateCurrentPaintChunkProperties(nullptr, rootPaintChunkProperties());
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.updateCurrentPaintChunkProperties(rootPaintChunkProperties());
chunker.incrementDisplayItemIndex(PaintChunker::DefaultBehavior);
PaintChunkProperties firstTransform;
firstTransform.transform = TransformPaintPropertyNode::create(TransformationMatrix(0, 1, 2, 3, 4, 5), FloatPoint3D(9, 8, 7));
chunker.updateCurrentPaintChunkProperties(nullptr, firstTransform);
chunker.updateCurrentPaintChunkProperties(firstTransform);
PaintChunkProperties secondTransform;
secondTransform.transform = TransformPaintPropertyNode::create(TransformationMatrix(9, 8, 7, 6, 5, 4), FloatPoint3D(3, 2, 1));
chunker.updateCurrentPaintChunkProperties(nullptr, secondTransform);
chunker.updateCurrentPaintChunkProperties(secondTransform);
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.incrementDisplayItemIndex(PaintChunker::DefaultBehavior);
Vector<PaintChunk> chunks = chunker.releasePaintChunks();
EXPECT_THAT(chunks, ElementsAre(
PaintChunk(0, 1, nullptr, rootPaintChunkProperties()),
PaintChunk(1, 2, nullptr, secondTransform)));
PaintChunk(0, 1, rootPaintChunkProperties()),
PaintChunk(1, 2, secondTransform)));
}
TEST_F(PaintChunkerTest, CreatesSeparateChunksWhenRequested)
@ -218,99 +198,29 @@ TEST_F(PaintChunkerTest, CreatesSeparateChunksWhenRequested)
// Tests that the chunker creates a separate chunks for display items which
// require it.
PaintChunker chunker;
TestDisplayItemRequiringSeparateChunk i1, i2, i3, i4, i5, i6;
chunker.updateCurrentPaintChunkProperties(nullptr, rootPaintChunkProperties());
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.incrementDisplayItemIndex(i1);
chunker.incrementDisplayItemIndex(i2);
chunker.incrementDisplayItemIndex(i3);
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.incrementDisplayItemIndex(i4);
chunker.incrementDisplayItemIndex(i5);
chunker.updateCurrentPaintChunkProperties(rootPaintChunkProperties());
chunker.incrementDisplayItemIndex(PaintChunker::DefaultBehavior);
chunker.incrementDisplayItemIndex(PaintChunker::RequiresSeparateChunk);
chunker.incrementDisplayItemIndex(PaintChunker::RequiresSeparateChunk);
chunker.incrementDisplayItemIndex(PaintChunker::RequiresSeparateChunk);
chunker.incrementDisplayItemIndex(PaintChunker::DefaultBehavior);
chunker.incrementDisplayItemIndex(PaintChunker::DefaultBehavior);
chunker.incrementDisplayItemIndex(PaintChunker::RequiresSeparateChunk);
chunker.incrementDisplayItemIndex(PaintChunker::RequiresSeparateChunk);
chunker.decrementDisplayItemIndex();
chunker.decrementDisplayItemIndex();
chunker.decrementDisplayItemIndex();
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.incrementDisplayItemIndex(i6);
DisplayItem::Id id1 = i1.getId();
DisplayItem::Id id2 = i2.getId();
DisplayItem::Id id3 = i3.getId();
DisplayItem::Id id6 = i6.getId();
Vector<PaintChunk> chunks = chunker.releasePaintChunks();
EXPECT_THAT(chunks, ElementsAre(
PaintChunk(0, 1, nullptr, rootPaintChunkProperties()),
PaintChunk(1, 2, &id1, rootPaintChunkProperties()),
PaintChunk(2, 3, &id2, rootPaintChunkProperties()),
PaintChunk(3, 4, &id3, rootPaintChunkProperties()),
PaintChunk(4, 6, nullptr, rootPaintChunkProperties()),
PaintChunk(6, 7, &id6, rootPaintChunkProperties())));
}
TEST_F(PaintChunkerTest, ChunkIds)
{
PaintChunker chunker;
TestDisplayItem i1(DisplayItem::DrawingFirst);
DisplayItem::Id id1 = i1.getId();
TestDisplayItemRequiringSeparateChunk i2;
DisplayItem::Id id2 = i2.getId();
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
PaintChunkProperties simpleTransform;
simpleTransform.transform = TransformPaintPropertyNode::create(TransformationMatrix(0, 1, 2, 3, 4, 5), FloatPoint3D(9, 8, 7));
chunker.updateCurrentPaintChunkProperties(&id1, simpleTransform);
chunker.incrementDisplayItemIndex(i1);
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.incrementDisplayItemIndex(i2);
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.updateCurrentPaintChunkProperties(nullptr, rootPaintChunkProperties());
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.incrementDisplayItemIndex(PaintChunker::DefaultBehavior);
chunker.incrementDisplayItemIndex(PaintChunker::RequiresSeparateChunk);
Vector<PaintChunk> chunks = chunker.releasePaintChunks();
EXPECT_THAT(chunks, ElementsAre(
PaintChunk(0, 2, nullptr, rootPaintChunkProperties()),
PaintChunk(2, 4, &id1, simpleTransform),
PaintChunk(4, 5, &id2, simpleTransform),
PaintChunk(5, 6, nullptr, simpleTransform),
PaintChunk(6, 7, nullptr, rootPaintChunkProperties())));
}
TEST_F(PaintChunkerTest, ChunkIdsSkippingCache)
{
PaintChunker chunker;
TestDisplayItem i1(DisplayItem::DrawingFirst);
i1.setSkippedCache();
DisplayItem::Id id1 = i1.getId();
TestDisplayItemRequiringSeparateChunk i2;
i2.setSkippedCache();
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
PaintChunkProperties simpleTransform;
simpleTransform.transform = TransformPaintPropertyNode::create(TransformationMatrix(0, 1, 2, 3, 4, 5), FloatPoint3D(9, 8, 7));
chunker.updateCurrentPaintChunkProperties(&id1, simpleTransform);
chunker.incrementDisplayItemIndex(i1);
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.incrementDisplayItemIndex(i2);
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
chunker.updateCurrentPaintChunkProperties(nullptr, rootPaintChunkProperties());
chunker.incrementDisplayItemIndex(NormalTestDisplayItem());
Vector<PaintChunk> chunks = chunker.releasePaintChunks();
EXPECT_THAT(chunks, ElementsAre(
PaintChunk(0, 2, nullptr, rootPaintChunkProperties()),
PaintChunk(2, 4, nullptr, simpleTransform),
PaintChunk(4, 5, nullptr, simpleTransform),
PaintChunk(5, 6, nullptr, simpleTransform),
PaintChunk(6, 7, nullptr, rootPaintChunkProperties())));
PaintChunk(0, 1, rootPaintChunkProperties()),
PaintChunk(1, 2, rootPaintChunkProperties()),
PaintChunk(2, 3, rootPaintChunkProperties()),
PaintChunk(3, 4, rootPaintChunkProperties()),
PaintChunk(4, 6, rootPaintChunkProperties()),
PaintChunk(6, 7, rootPaintChunkProperties())));
}
} // namespace

@ -17,6 +17,13 @@
namespace blink {
static PaintChunker::ItemBehavior behaviorOfItemType(DisplayItem::Type type)
{
if (DisplayItem::isForeignLayerType(type))
return PaintChunker::RequiresSeparateChunk;
return PaintChunker::DefaultBehavior;
}
const PaintArtifact& PaintController::paintArtifact() const
{
DCHECK(m_newDisplayItemList.isEmpty());
@ -158,7 +165,7 @@ void PaintController::processNewItem(DisplayItem& displayItem)
DCHECK(!m_constructionDisabled);
#if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS
if (!isSkippingCache()) {
if (!skippingCache()) {
if (displayItem.isCacheable()) {
// Mark the client shouldKeepAlive under this PaintController.
// The status will end after the new display items are committed.
@ -189,7 +196,7 @@ void PaintController::processNewItem(DisplayItem& displayItem)
}
#endif
if (isSkippingCache())
if (skippingCache())
displayItem.setSkippedCache();
#if DCHECK_IS_ON()
@ -209,12 +216,12 @@ void PaintController::processNewItem(DisplayItem& displayItem)
#endif // DCHECK_IS_ON()
if (RuntimeEnabledFeatures::slimmingPaintV2Enabled())
m_newPaintChunks.incrementDisplayItemIndex(displayItem);
m_newPaintChunks.incrementDisplayItemIndex(behaviorOfItemType(displayItem.getType()));
}
void PaintController::updateCurrentPaintChunkProperties(const PaintChunk::Id* id, const PaintChunkProperties& newProperties)
void PaintController::updateCurrentPaintChunkProperties(const PaintChunkProperties& newProperties)
{
m_newPaintChunks.updateCurrentPaintChunkProperties(id, newProperties);
m_newPaintChunks.updateCurrentPaintChunkProperties(newProperties);
}
const PaintChunkProperties& PaintController::currentPaintChunkProperties() const
@ -235,7 +242,7 @@ bool PaintController::clientCacheIsValid(const DisplayItemClient& client) const
#if CHECK_DISPLAY_ITEM_CLIENT_ALIVENESS
CHECK(client.isAlive());
#endif
if (isSkippingCache())
if (skippingCache())
return false;
return client.displayItemsAreCached(m_currentCacheGeneration);
}
@ -403,7 +410,7 @@ void PaintController::commitNewDisplayItems(const LayoutSize& offsetFromLayoutOb
m_numCachedNewItems = 0;
// These data structures are used during painting only.
DCHECK(!isSkippingCache());
DCHECK(!skippingCache());
#if DCHECK_IS_ON()
m_newDisplayItemIndicesByClient.clear();
#endif

@ -60,7 +60,7 @@ public:
// Provide a new set of paint chunk properties to apply to recorded display
// items, for Slimming Paint v2.
void updateCurrentPaintChunkProperties(const PaintChunk::Id*, const PaintChunkProperties&);
void updateCurrentPaintChunkProperties(const PaintChunkProperties&);
// Retrieve the current paint properties.
const PaintChunkProperties& currentPaintChunkProperties() const;
@ -111,7 +111,7 @@ public:
void beginSkippingCache() { ++m_skippingCacheCount; }
void endSkippingCache() { DCHECK(m_skippingCacheCount > 0); --m_skippingCacheCount; }
bool isSkippingCache() const { return m_skippingCacheCount; }
bool skippingCache() const { return m_skippingCacheCount; }
// Must be called when a painting is finished.
// offsetFromLayoutObject is the offset between the space of the GraphicsLayer which owns this

@ -5,8 +5,6 @@
#ifndef ScopedPaintChunkProperties_h
#define ScopedPaintChunkProperties_h
#include "platform/graphics/paint/DisplayItem.h"
#include "platform/graphics/paint/PaintChunk.h"
#include "platform/graphics/paint/PaintChunkProperties.h"
#include "platform/graphics/paint/PaintController.h"
#include "wtf/Allocator.h"
@ -18,27 +16,16 @@ class ScopedPaintChunkProperties {
DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
WTF_MAKE_NONCOPYABLE(ScopedPaintChunkProperties);
public:
ScopedPaintChunkProperties(PaintController& paintController, const DisplayItemClient& client, DisplayItem::Type type, const PaintChunkProperties& properties)
ScopedPaintChunkProperties(PaintController& paintController, const PaintChunkProperties& properties)
: m_paintController(paintController)
, m_previousProperties(paintController.currentPaintChunkProperties())
{
PaintChunk::Id id(client, type);
m_paintController.updateCurrentPaintChunkProperties(&id, properties);
m_paintController.updateCurrentPaintChunkProperties(properties);
}
// Omits the type parameter, in case that the client creates only one PaintChunkProperties node during each painting.
ScopedPaintChunkProperties(PaintController& paintController, const DisplayItemClient& client, const PaintChunkProperties& properties)
: ScopedPaintChunkProperties(paintController, client, DisplayItem::UninitializedType, properties)
{ }
~ScopedPaintChunkProperties()
{
// We should not return to the previous id, because that may cause a new chunk to use
// the same id as that of the previous chunk before this ScopedPaintChunkProperties.
// The painter should create another scope of paint properties with new id, or the
// new chunk will have no id and will not match any old chunk and will be treated as
// fully invalidated for rasterization.
m_paintController.updateCurrentPaintChunkProperties(nullptr, m_previousProperties);
m_paintController.updateCurrentPaintChunkProperties(m_previousProperties);
}
private:

@ -20,12 +20,6 @@ public:
String debugName() const final { return m_name; }
LayoutRect visualRect() const override { return m_visualRect; }
// This simulates a paint without needing a PaintController.
void updateCacheGeneration()
{
setDisplayItemsCached(CacheGenerationOrInvalidationReason::next());
}
private:
String m_name;
LayoutRect m_visualRect;

@ -45,19 +45,7 @@ void PrintTo(const PaintChunk& chunk, std::ostream* os)
{
*os << "PaintChunk(begin=" << chunk.beginIndex
<< ", end=" << chunk.endIndex
<< ", id=";
if (!chunk.id) {
*os << "null";
} else {
*os << "(" << &chunk.id->client << ", ";
#ifndef NDEBUG
*os << DisplayItem::typeAsDebugString(chunk.id->type);
#else
*os << static_cast<int>(chunk.id->type);
#endif
*os << ")";
}
*os << ", props=";
<< ", props=";
PrintTo(chunk.properties, os);
*os << ", bounds=";
PrintTo(chunk.bounds, os);