Commit 139880d7 authored by Xianzhu Wang's avatar Xianzhu Wang Committed by Commit Bot

Let PaintController build PaintArtifact

This prepares for unified PaintController for pre-CompositeAfterPaint
and CompositeAfterPaint. Unified PaintController needs to create
PaintChunkSubset for the painting of a pre-composited layer
(GraphicsLayer) which needs to hold a reference to the PaintArtifact.

Bug: 1132717
Change-Id: I9ec46fdda2eb6ad1d755f2d9f20a0d081db26973
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2447121
Commit-Queue: Xianzhu Wang <wangxianzhu@chromium.org>
Reviewed-by: default avatarPhilip Rogers <pdr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#814501}
parent d8ed49a5
...@@ -179,10 +179,13 @@ class TestChunks { ...@@ -179,10 +179,13 @@ class TestChunks {
const EffectPaintPropertyNodeOrAlias& e, const EffectPaintPropertyNodeOrAlias& e,
const IntRect& bounds = IntRect(0, 0, 100, 100), const IntRect& bounds = IntRect(0, 0, 100, 100),
const base::Optional<IntRect>& drawable_bounds = base::nullopt) { const base::Optional<IntRect>& drawable_bounds = base::nullopt) {
auto& items = paint_artifact_->GetDisplayItemList();
auto i = items.size(); auto i = items.size();
items.AllocateAndConstruct<DrawingDisplayItem>( items.AllocateAndConstruct<DrawingDisplayItem>(
DefaultId().client, DefaultId().type, DefaultId().client, DefaultId().type,
drawable_bounds ? *drawable_bounds : bounds, std::move(record)); drawable_bounds ? *drawable_bounds : bounds, std::move(record));
auto& chunks = paint_artifact_->PaintChunks();
chunks.emplace_back(i, i + 1, DefaultId(), chunks.emplace_back(i, i + 1, DefaultId(),
PropertyTreeStateOrAlias(t, c, e)); PropertyTreeStateOrAlias(t, c, e));
chunks.back().bounds = bounds; chunks.back().bounds = bounds;
...@@ -193,19 +196,19 @@ class TestChunks { ...@@ -193,19 +196,19 @@ class TestChunks {
const ClipPaintPropertyNode& c, const ClipPaintPropertyNode& c,
const EffectPaintPropertyNode& e, const EffectPaintPropertyNode& e,
const IntRect& bounds = IntRect(0, 0, 100, 100)) { const IntRect& bounds = IntRect(0, 0, 100, 100)) {
auto i = items.size(); auto& chunks = paint_artifact_->PaintChunks();
auto i = paint_artifact_->GetDisplayItemList().size();
chunks.emplace_back(i, i, DefaultId(), PropertyTreeState(t, c, e)); chunks.emplace_back(i, i, DefaultId(), PropertyTreeState(t, c, e));
chunks.back().bounds = bounds; chunks.back().bounds = bounds;
} }
PaintChunkSubset Build() { PaintChunkSubset Build() {
return PaintChunkSubset(base::MakeRefCounted<PaintArtifact>( return PaintChunkSubset(std::move(paint_artifact_));
std::move(items), std::move(chunks)));
} }
private: private:
Vector<PaintChunk> chunks; scoped_refptr<PaintArtifact> paint_artifact_ =
DisplayItemList items; base::MakeRefCounted<PaintArtifact>();
}; };
TEST_P(PaintChunksToCcLayerTest, EffectGroupingSimple) { TEST_P(PaintChunksToCcLayerTest, EffectGroupingSimple) {
......
...@@ -12,12 +12,6 @@ ...@@ -12,12 +12,6 @@
namespace blink { namespace blink {
#if DCHECK_IS_ON()
static bool g_list_modification_check_disabled = false;
DisableListModificationCheck::DisableListModificationCheck()
: disabler_(&g_list_modification_check_disabled, true) {}
#endif
DrawingRecorder::DrawingRecorder(GraphicsContext& context, DrawingRecorder::DrawingRecorder(GraphicsContext& context,
const DisplayItemClient& display_item_client, const DisplayItemClient& display_item_client,
DisplayItem::Type display_item_type, DisplayItem::Type display_item_type,
...@@ -44,11 +38,6 @@ DrawingRecorder::DrawingRecorder(GraphicsContext& context, ...@@ -44,11 +38,6 @@ DrawingRecorder::DrawingRecorder(GraphicsContext& context,
context.SetDOMNodeId(dom_node_id); context.SetDOMNodeId(dom_node_id);
} }
} }
#if DCHECK_IS_ON()
initial_display_item_list_size_ =
context_.GetPaintController().NewDisplayItemList().size();
#endif
} }
DrawingRecorder::~DrawingRecorder() { DrawingRecorder::~DrawingRecorder() {
...@@ -57,13 +46,6 @@ DrawingRecorder::~DrawingRecorder() { ...@@ -57,13 +46,6 @@ DrawingRecorder::~DrawingRecorder() {
context_.SetInDrawingRecorder(false); context_.SetInDrawingRecorder(false);
#if DCHECK_IS_ON()
if (!g_list_modification_check_disabled) {
DCHECK(initial_display_item_list_size_ ==
context_.GetPaintController().NewDisplayItemList().size());
}
#endif
context_.GetPaintController().CreateAndAppend<DrawingDisplayItem>( context_.GetPaintController().CreateAndAppend<DrawingDisplayItem>(
client_, type_, visual_rect_, context_.EndRecording()); client_, type_, visual_rect_, context_.EndRecording());
} }
......
...@@ -84,11 +84,6 @@ class PLATFORM_EXPORT DrawingRecorder { ...@@ -84,11 +84,6 @@ class PLATFORM_EXPORT DrawingRecorder {
IntRect visual_rect_; IntRect visual_rect_;
base::Optional<DOMNodeId> dom_node_id_to_restore_; base::Optional<DOMNodeId> dom_node_id_to_restore_;
#if DCHECK_IS_ON()
// Ensures the list size does not change during the recorder's scope.
wtf_size_t initial_display_item_list_size_;
#endif
DISALLOW_COPY_AND_ASSIGN(DrawingRecorder); DISALLOW_COPY_AND_ASSIGN(DrawingRecorder);
}; };
......
...@@ -14,13 +14,6 @@ ...@@ -14,13 +14,6 @@
namespace blink { namespace blink {
PaintArtifact::PaintArtifact(DisplayItemList display_items,
Vector<PaintChunk> chunks)
: display_item_list_(std::move(display_items)), chunks_(std::move(chunks)) {
}
PaintArtifact::~PaintArtifact() = default;
size_t PaintArtifact::ApproximateUnsharedMemoryUsage() const { size_t PaintArtifact::ApproximateUnsharedMemoryUsage() const {
size_t total_size = sizeof(*this) + display_item_list_.MemoryUsageInBytes() + size_t total_size = sizeof(*this) + display_item_list_.MemoryUsageInBytes() +
chunks_.capacity() * sizeof(chunks_[0]); chunks_.capacity() * sizeof(chunks_[0]);
......
...@@ -34,9 +34,9 @@ class PLATFORM_EXPORT PaintArtifact final : public RefCounted<PaintArtifact> { ...@@ -34,9 +34,9 @@ class PLATFORM_EXPORT PaintArtifact final : public RefCounted<PaintArtifact> {
USING_FAST_MALLOC(PaintArtifact); USING_FAST_MALLOC(PaintArtifact);
public: public:
PaintArtifact() = default; explicit PaintArtifact(
PaintArtifact(DisplayItemList, Vector<PaintChunk>); wtf_size_t initial_display_item_list_capacity_in_bytes = 0)
~PaintArtifact(); : display_item_list_(initial_display_item_list_capacity_in_bytes) {}
PaintArtifact(const PaintArtifact& other) = delete; PaintArtifact(const PaintArtifact& other) = delete;
PaintArtifact& operator=(const PaintArtifact& other) = delete; PaintArtifact& operator=(const PaintArtifact& other) = delete;
......
...@@ -8,11 +8,18 @@ ...@@ -8,11 +8,18 @@
namespace blink { namespace blink {
PaintChunker::PaintChunker() void PaintChunker::ResetChunks(Vector<PaintChunk>* chunks) {
: current_properties_(PropertyTreeState::Uninitialized()), if (chunks_) {
force_new_chunk_(true) {} FinalizeLastChunkProperties();
SetWillForceNewChunk(true);
PaintChunker::~PaintChunker() = default; current_properties_ = PropertyTreeState::Uninitialized();
}
chunks_ = chunks;
#if DCHECK_IS_ON()
DCHECK(!chunks || chunks->IsEmpty());
DCHECK(IsInInitialState());
#endif
}
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
bool PaintChunker::IsInInitialState() const { bool PaintChunker::IsInInitialState() const {
...@@ -20,7 +27,8 @@ bool PaintChunker::IsInInitialState() const { ...@@ -20,7 +27,8 @@ bool PaintChunker::IsInInitialState() const {
return false; return false;
DCHECK_EQ(candidate_background_color_.Rgb(), Color::kTransparent); DCHECK_EQ(candidate_background_color_.Rgb(), Color::kTransparent);
DCHECK_EQ(candidate_background_area_, 0u); DCHECK_EQ(candidate_background_area_, 0u);
DCHECK(chunks_.IsEmpty()); DCHECK(will_force_new_chunk_);
DCHECK(!chunks_ || chunks_->IsEmpty());
return true; return true;
} }
#endif #endif
...@@ -41,14 +49,16 @@ void PaintChunker::UpdateCurrentPaintChunkProperties( ...@@ -41,14 +49,16 @@ void PaintChunker::UpdateCurrentPaintChunkProperties(
} }
void PaintChunker::AppendByMoving(PaintChunk&& chunk) { void PaintChunker::AppendByMoving(PaintChunk&& chunk) {
DCHECK(chunks_);
FinalizeLastChunkProperties(); FinalizeLastChunkProperties();
wtf_size_t next_chunk_begin_index = wtf_size_t next_chunk_begin_index =
chunks_.IsEmpty() ? 0 : LastChunk().end_index; chunks_->IsEmpty() ? 0 : chunks_->back().end_index;
chunks_.emplace_back(next_chunk_begin_index, std::move(chunk)); chunks_->emplace_back(next_chunk_begin_index, std::move(chunk));
} }
PaintChunk& PaintChunker::EnsureCurrentChunk(const PaintChunk::Id& id) { bool PaintChunker::EnsureCurrentChunk(const PaintChunk::Id& id) {
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
DCHECK(chunks_);
// If this DCHECKs are hit we are missing a call to update the properties. // If this DCHECKs are hit we are missing a call to update the properties.
// See: ScopedPaintChunkProperties. // See: ScopedPaintChunkProperties.
DCHECK(!IsInInitialState()); DCHECK(!IsInInitialState());
...@@ -56,28 +66,31 @@ PaintChunk& PaintChunker::EnsureCurrentChunk(const PaintChunk::Id& id) { ...@@ -56,28 +66,31 @@ PaintChunk& PaintChunker::EnsureCurrentChunk(const PaintChunk::Id& id) {
DCHECK(current_properties_.IsInitialized()); DCHECK(current_properties_.IsInitialized());
#endif #endif
if (WillForceNewChunk() || current_properties_ != LastChunk().properties) { if (WillForceNewChunk() ||
current_properties_ != chunks_->back().properties) {
if (!next_chunk_id_) if (!next_chunk_id_)
next_chunk_id_.emplace(id); next_chunk_id_.emplace(id);
FinalizeLastChunkProperties(); FinalizeLastChunkProperties();
wtf_size_t begin = chunks_.IsEmpty() ? 0 : LastChunk().end_index; wtf_size_t begin = chunks_->IsEmpty() ? 0 : chunks_->back().end_index;
chunks_.emplace_back(begin, begin, *next_chunk_id_, current_properties_); chunks_->emplace_back(begin, begin, *next_chunk_id_, current_properties_);
next_chunk_id_ = base::nullopt; next_chunk_id_ = base::nullopt;
force_new_chunk_ = false; will_force_new_chunk_ = false;
return true;
} }
return LastChunk(); return false;
} }
bool PaintChunker::IncrementDisplayItemIndex(const DisplayItem& item) { bool PaintChunker::IncrementDisplayItemIndex(const DisplayItem& item) {
DCHECK(chunks_);
bool item_forces_new_chunk = item.IsForeignLayer() || bool item_forces_new_chunk = item.IsForeignLayer() ||
item.IsGraphicsLayerWrapper() || item.IsGraphicsLayerWrapper() ||
item.IsScrollbar(); item.IsScrollbar();
if (item_forces_new_chunk) if (item_forces_new_chunk)
SetForceNewChunk(true); SetWillForceNewChunk(true);
auto previous_size = size(); bool created_new_chunk = EnsureCurrentChunk(item.GetId());
auto& chunk = EnsureCurrentChunk(item.GetId()); auto& chunk = chunks_->back();
bool created_new_chunk = size() > previous_size;
chunk.bounds.Unite(item.VisualRect()); chunk.bounds.Unite(item.VisualRect());
if (item.DrawsContent()) if (item.DrawsContent())
...@@ -105,16 +118,16 @@ bool PaintChunker::IncrementDisplayItemIndex(const DisplayItem& item) { ...@@ -105,16 +118,16 @@ bool PaintChunker::IncrementDisplayItemIndex(const DisplayItem& item) {
// When forcing a new chunk, we still need to force new chunk for the next // When forcing a new chunk, we still need to force new chunk for the next
// display item. Otherwise reset force_new_chunk_ to false. // display item. Otherwise reset force_new_chunk_ to false.
DCHECK(!force_new_chunk_); DCHECK(!will_force_new_chunk_);
if (item_forces_new_chunk) { if (item_forces_new_chunk) {
DCHECK(created_new_chunk); DCHECK(created_new_chunk);
SetForceNewChunk(true); SetWillForceNewChunk(true);
} }
return created_new_chunk; return created_new_chunk;
} }
void PaintChunker::AddHitTestDataToCurrentChunk(const PaintChunk::Id& id, bool PaintChunker::AddHitTestDataToCurrentChunk(const PaintChunk::Id& id,
const IntRect& rect, const IntRect& rect,
TouchAction touch_action) { TouchAction touch_action) {
// In CompositeAfterPaint, we ensure a paint chunk for correct composited // In CompositeAfterPaint, we ensure a paint chunk for correct composited
...@@ -124,14 +137,16 @@ void PaintChunker::AddHitTestDataToCurrentChunk(const PaintChunk::Id& id, ...@@ -124,14 +137,16 @@ void PaintChunker::AddHitTestDataToCurrentChunk(const PaintChunk::Id& id,
if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled() && if (!RuntimeEnabledFeatures::CompositeAfterPaintEnabled() &&
touch_action == TouchAction::kAuto && touch_action == TouchAction::kAuto &&
&current_properties_.Effect() == &EffectPaintPropertyNode::Root()) &current_properties_.Effect() == &EffectPaintPropertyNode::Root())
return; return false;
auto& chunk = EnsureCurrentChunk(id); bool created_new_chunk = EnsureCurrentChunk(id);
auto& chunk = chunks_->back();
chunk.bounds.Unite(rect); chunk.bounds.Unite(rect);
if (touch_action != TouchAction::kAuto) { if (touch_action != TouchAction::kAuto) {
chunk.EnsureHitTestData().touch_action_rects.push_back( chunk.EnsureHitTestData().touch_action_rects.push_back(
TouchActionRect{rect, touch_action}); TouchActionRect{rect, touch_action});
} }
return created_new_chunk;
} }
void PaintChunker::CreateScrollHitTestChunk( void PaintChunker::CreateScrollHitTestChunk(
...@@ -154,50 +169,47 @@ void PaintChunker::CreateScrollHitTestChunk( ...@@ -154,50 +169,47 @@ void PaintChunker::CreateScrollHitTestChunk(
} }
#endif #endif
SetForceNewChunk(true); SetWillForceNewChunk(true);
auto& chunk = EnsureCurrentChunk(id); bool created_new_chunk = EnsureCurrentChunk(id);
DCHECK(created_new_chunk);
auto& chunk = chunks_->back();
chunk.bounds.Unite(rect); chunk.bounds.Unite(rect);
auto& hit_test_data = chunk.EnsureHitTestData(); auto& hit_test_data = chunk.EnsureHitTestData();
hit_test_data.scroll_translation = scroll_translation; hit_test_data.scroll_translation = scroll_translation;
hit_test_data.scroll_hit_test_rect = rect; hit_test_data.scroll_hit_test_rect = rect;
SetForceNewChunk(true); SetWillForceNewChunk(true);
} }
void PaintChunker::ProcessBackgroundColorCandidate(const PaintChunk::Id& id, bool PaintChunker::ProcessBackgroundColorCandidate(const PaintChunk::Id& id,
Color color, Color color,
uint64_t area) { uint64_t area) {
EnsureCurrentChunk(id); bool created_new_chunk = EnsureCurrentChunk(id);
if (color != Color::kTransparent && if (color != Color::kTransparent &&
(candidate_background_color_ == Color::kTransparent || (candidate_background_color_ == Color::kTransparent ||
(area >= candidate_background_area_))) { (area >= candidate_background_area_))) {
candidate_background_color_ = color; candidate_background_color_ = color;
candidate_background_area_ = area; candidate_background_area_ = area;
} }
return created_new_chunk;
} }
void PaintChunker::FinalizeLastChunkProperties() { void PaintChunker::FinalizeLastChunkProperties() {
if (chunks_.IsEmpty() || LastChunk().is_moved_from_cached_subsequence) DCHECK(chunks_);
if (chunks_->IsEmpty() || chunks_->back().is_moved_from_cached_subsequence)
return; return;
LastChunk().known_to_be_opaque = auto& chunk = chunks_->back();
last_chunk_known_to_be_opaque_region_.Contains(LastChunk().bounds); chunk.known_to_be_opaque =
last_chunk_known_to_be_opaque_region_.Contains(chunk.bounds);
last_chunk_known_to_be_opaque_region_ = Region(); last_chunk_known_to_be_opaque_region_ = Region();
if (candidate_background_color_ != Color::kTransparent) { if (candidate_background_color_ != Color::kTransparent) {
LastChunk().background_color = candidate_background_color_; chunk.background_color = candidate_background_color_;
LastChunk().background_color_area = candidate_background_area_; chunk.background_color_area = candidate_background_area_;
} }
candidate_background_color_ = Color::kTransparent; candidate_background_color_ = Color::kTransparent;
candidate_background_area_ = 0u; candidate_background_area_ = 0u;
} }
Vector<PaintChunk> PaintChunker::ReleasePaintChunks() {
FinalizeLastChunkProperties();
next_chunk_id_ = base::nullopt;
current_properties_ = PropertyTreeState::Uninitialized();
chunks_.ShrinkToFit();
force_new_chunk_ = true;
return std::move(chunks_);
}
} // namespace blink } // namespace blink
...@@ -25,8 +25,11 @@ class PLATFORM_EXPORT PaintChunker final { ...@@ -25,8 +25,11 @@ class PLATFORM_EXPORT PaintChunker final {
DISALLOW_NEW(); DISALLOW_NEW();
public: public:
PaintChunker(); explicit PaintChunker(Vector<PaintChunk>& chunks) { ResetChunks(&chunks); }
~PaintChunker();
// Finishes current chunks if any, and makes it ready to create chunks into
// the given vector if not null.
void ResetChunks(Vector<PaintChunk>*);
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
bool IsInInitialState() const; bool IsInInitialState() const;
...@@ -43,28 +46,20 @@ class PLATFORM_EXPORT PaintChunker final { ...@@ -43,28 +46,20 @@ class PLATFORM_EXPORT PaintChunker final {
// display item and then automatically resets the status. Some special display // display item and then automatically resets the status. Some special display
// item (e.g. ForeignLayerDisplayItem) also automatically sets the status on // item (e.g. ForeignLayerDisplayItem) also automatically sets the status on
// before and after the item to force a dedicated paint chunk. // before and after the item to force a dedicated paint chunk.
void SetForceNewChunk(bool force) { void SetWillForceNewChunk(bool force) {
force_new_chunk_ = force; will_force_new_chunk_ = force;
next_chunk_id_ = base::nullopt; next_chunk_id_ = base::nullopt;
} }
bool WillForceNewChunk() const { bool WillForceNewChunk() const { return will_force_new_chunk_; }
return force_new_chunk_ || chunks_.IsEmpty();
}
void AppendByMoving(PaintChunk&&); void AppendByMoving(PaintChunk&&);
// Returns true if a new chunk is created. // Returns true if a new chunk is created.
bool IncrementDisplayItemIndex(const DisplayItem&); bool IncrementDisplayItemIndex(const DisplayItem&);
const Vector<PaintChunk>& PaintChunks() const { return chunks_; }
wtf_size_t size() const { return chunks_.size(); }
PaintChunk& LastChunk() { return chunks_.back(); }
const PaintChunk& LastChunk() const { return chunks_.back(); }
// The id will be used when we need to create a new current chunk. // The id will be used when we need to create a new current chunk.
// Otherwise it's ignored. // Otherwise it's ignored. Returns true if a new chunk is added.
void AddHitTestDataToCurrentChunk(const PaintChunk::Id&, bool AddHitTestDataToCurrentChunk(const PaintChunk::Id&,
const IntRect&, const IntRect&,
TouchAction); TouchAction);
void CreateScrollHitTestChunk( void CreateScrollHitTestChunk(
...@@ -72,20 +67,21 @@ class PLATFORM_EXPORT PaintChunker final { ...@@ -72,20 +67,21 @@ class PLATFORM_EXPORT PaintChunker final {
const TransformPaintPropertyNode* scroll_translation, const TransformPaintPropertyNode* scroll_translation,
const IntRect&); const IntRect&);
void ProcessBackgroundColorCandidate(const PaintChunk::Id& id, // Returns true if a new chunk is created.
bool ProcessBackgroundColorCandidate(const PaintChunk::Id& id,
Color color, Color color,
uint64_t area); uint64_t area);
void EnsureChunk() { EnsureCurrentChunk(*next_chunk_id_); }
// Releases the generated paint chunk list and raster invalidations and // Returns true if a new chunk is created.
// resets the state of this object. bool EnsureChunk() { return EnsureCurrentChunk(*next_chunk_id_); }
Vector<PaintChunk> ReleasePaintChunks();
private: private:
PaintChunk& EnsureCurrentChunk(const PaintChunk::Id&); // Returns true if a new chunk is created.
bool EnsureCurrentChunk(const PaintChunk::Id&);
void FinalizeLastChunkProperties(); void FinalizeLastChunkProperties();
Vector<PaintChunk> chunks_; Vector<PaintChunk>* chunks_ = nullptr;
// The id specified by UpdateCurrentPaintChunkProperties(). If it is not // The id specified by UpdateCurrentPaintChunkProperties(). If it is not
// nullopt, we will use it as the id of the next new chunk. Otherwise we will // nullopt, we will use it as the id of the next new chunk. Otherwise we will
...@@ -95,14 +91,15 @@ class PLATFORM_EXPORT PaintChunker final { ...@@ -95,14 +91,15 @@ class PLATFORM_EXPORT PaintChunker final {
// forced to create a new chunk). // forced to create a new chunk).
base::Optional<PaintChunk::Id> next_chunk_id_; base::Optional<PaintChunk::Id> next_chunk_id_;
PropertyTreeStateOrAlias current_properties_; PropertyTreeStateOrAlias current_properties_ =
PropertyTreeState::Uninitialized();
Region last_chunk_known_to_be_opaque_region_; Region last_chunk_known_to_be_opaque_region_;
// True when an item forces a new chunk (e.g., foreign display items), and for // True when an item forces a new chunk (e.g., foreign display items), and for
// the item following a forced chunk. PaintController also forces new chunks // the item following a forced chunk. PaintController also forces new chunks
// before and after subsequences by calling ForceNewChunk(). // before and after subsequences by calling ForceNewChunk().
bool force_new_chunk_; bool will_force_new_chunk_ = true;
Color candidate_background_color_ = Color::kTransparent; Color candidate_background_color_ = Color::kTransparent;
uint64_t candidate_background_area_ = 0; uint64_t candidate_background_area_ = 0;
......
...@@ -93,46 +93,31 @@ class PLATFORM_EXPORT PaintController { ...@@ -93,46 +93,31 @@ class PLATFORM_EXPORT PaintController {
void UpdateCurrentPaintChunkProperties(const PaintChunk::Id*, void UpdateCurrentPaintChunkProperties(const PaintChunk::Id*,
const PropertyTreeStateOrAlias&); const PropertyTreeStateOrAlias&);
const PropertyTreeStateOrAlias& CurrentPaintChunkProperties() const { const PropertyTreeStateOrAlias& CurrentPaintChunkProperties() const {
return new_paint_chunks_.CurrentPaintChunkProperties(); return paint_chunker_.CurrentPaintChunkProperties();
} }
// See PaintChunker for documentation of the following methods. // See PaintChunker for documentation of the following methods.
wtf_size_t NumNewChunks() const { return new_paint_chunks_.size(); } void SetWillForceNewChunk(bool force) {
void SetForceNewChunk(bool force) { paint_chunker_.SetWillForceNewChunk(force);
new_paint_chunks_.SetForceNewChunk(force);
}
bool WillForceNewChunk() const {
return new_paint_chunks_.WillForceNewChunk();
}
const IntRect& LastChunkBounds() const {
return new_paint_chunks_.LastChunk().bounds;
} }
bool WillForceNewChunk() const { return paint_chunker_.WillForceNewChunk(); }
void EnsureChunk() { new_paint_chunks_.EnsureChunk(); } void EnsureChunk();
void RecordHitTestData(const DisplayItemClient& client,
const IntRect& rect, void RecordHitTestData(const DisplayItemClient&, const IntRect&, TouchAction);
TouchAction touch_action) {
if (rect.IsEmpty())
return;
PaintChunk::Id id(client, DisplayItem::kHitTest, current_fragment_);
CheckDuplicatePaintChunkId(id);
new_paint_chunks_.AddHitTestDataToCurrentChunk(id, rect, touch_action);
}
void RecordScrollHitTestData( void RecordScrollHitTestData(
const DisplayItemClient& client, const DisplayItemClient&,
DisplayItem::Type type, DisplayItem::Type,
const TransformPaintPropertyNode* scroll_translation, const TransformPaintPropertyNode* scroll_translation,
const IntRect& rect) { const IntRect&);
PaintChunk::Id id(client, type, current_fragment_); void SetPossibleBackgroundColor(const DisplayItemClient&,
CheckDuplicatePaintChunkId(id); Color,
new_paint_chunks_.CreateScrollHitTestChunk(id, scroll_translation, rect); uint64_t area);
}
void SetPossibleBackgroundColor(const DisplayItemClient& client, wtf_size_t NumNewChunks() const {
Color color, return new_paint_artifact_->PaintChunks().size();
uint64_t area) { }
PaintChunk::Id id = {client, DisplayItem::kBoxDecorationBackground, const IntRect& LastChunkBounds() const {
current_fragment_}; return new_paint_artifact_->PaintChunks().back().bounds;
new_paint_chunks_.ProcessBackgroundColorCandidate(id, color, area);
} }
template <typename DisplayItemClass, typename... Args> template <typename DisplayItemClass, typename... Args>
...@@ -147,8 +132,9 @@ class PLATFORM_EXPORT PaintController { ...@@ -147,8 +132,9 @@ class PLATFORM_EXPORT PaintController {
"kDisplayItemAlignment."); "kDisplayItemAlignment.");
DisplayItemClass& display_item = DisplayItemClass& display_item =
new_display_item_list_.AllocateAndConstruct<DisplayItemClass>( new_paint_artifact_->GetDisplayItemList()
std::forward<Args>(args)...); .AllocateAndConstruct<DisplayItemClass>(
std::forward<Args>(args)...);
display_item.SetFragment(current_fragment_); display_item.SetFragment(current_fragment_);
ProcessNewItem(display_item); ProcessNewItem(display_item);
} }
...@@ -210,15 +196,12 @@ class PLATFORM_EXPORT PaintController { ...@@ -210,15 +196,12 @@ class PLATFORM_EXPORT PaintController {
// Get the artifact generated after the last commit. // Get the artifact generated after the last commit.
const PaintArtifact& GetPaintArtifact() const { const PaintArtifact& GetPaintArtifact() const {
#if DCHECK_IS_ON() CheckNoNewPaint();
DCHECK(new_display_item_list_.IsEmpty());
DCHECK(new_paint_chunks_.IsInInitialState());
DCHECK(current_paint_artifact_);
#endif
return *current_paint_artifact_; return *current_paint_artifact_;
} }
scoped_refptr<const PaintArtifact> GetPaintArtifactShared() const { scoped_refptr<const PaintArtifact> GetPaintArtifactShared() const {
return base::WrapRefCounted(&GetPaintArtifact()); CheckNoNewPaint();
return current_paint_artifact_;
} }
const DisplayItemList& GetDisplayItemList() const { const DisplayItemList& GetDisplayItemList() const {
return GetPaintArtifact().GetDisplayItemList(); return GetPaintArtifact().GetDisplayItemList();
...@@ -227,6 +210,11 @@ class PLATFORM_EXPORT PaintController { ...@@ -227,6 +210,11 @@ class PLATFORM_EXPORT PaintController {
return GetPaintArtifact().PaintChunks(); return GetPaintArtifact().PaintChunks();
} }
scoped_refptr<const PaintArtifact> GetNewPaintArtifactShared() const {
DCHECK(new_paint_artifact_);
return new_paint_artifact_;
}
class ScopedBenchmarkMode { class ScopedBenchmarkMode {
STACK_ALLOCATED(); STACK_ALLOCATED();
...@@ -255,10 +243,6 @@ class PLATFORM_EXPORT PaintController { ...@@ -255,10 +243,6 @@ class PLATFORM_EXPORT PaintController {
void SetTextPainted(); void SetTextPainted();
void SetImagePainted(); void SetImagePainted();
// Returns DisplayItemList added using CreateAndAppend() since beginning or
// the last CommitNewDisplayItems(). Use with care.
DisplayItemList& NewDisplayItemList() { return new_display_item_list_; }
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
void ShowCompactDebugData() const; void ShowCompactDebugData() const;
void ShowDebugData() const; void ShowDebugData() const;
...@@ -403,6 +387,14 @@ class PLATFORM_EXPORT PaintController { ...@@ -403,6 +387,14 @@ class PLATFORM_EXPORT PaintController {
bool ShouldInvalidateDisplayItemForBenchmark(); bool ShouldInvalidateDisplayItemForBenchmark();
bool ShouldInvalidateSubsequenceForBenchmark(); bool ShouldInvalidateSubsequenceForBenchmark();
void CheckNoNewPaint() const {
#if DCHECK_IS_ON()
DCHECK(!new_paint_artifact_ || new_paint_artifact_->IsEmpty());
DCHECK(paint_chunker_.IsInInitialState());
DCHECK(current_paint_artifact_);
#endif
}
Usage usage_; Usage usage_;
// The last paint artifact after CommitNewDisplayItems(). // The last paint artifact after CommitNewDisplayItems().
...@@ -410,8 +402,8 @@ class PLATFORM_EXPORT PaintController { ...@@ -410,8 +402,8 @@ class PLATFORM_EXPORT PaintController {
scoped_refptr<PaintArtifact> current_paint_artifact_; scoped_refptr<PaintArtifact> current_paint_artifact_;
// Data being used to build the next paint artifact. // Data being used to build the next paint artifact.
DisplayItemList new_display_item_list_; scoped_refptr<PaintArtifact> new_paint_artifact_;
PaintChunker new_paint_chunks_; PaintChunker paint_chunker_;
bool cache_is_all_invalid_ = true; bool cache_is_all_invalid_ = true;
bool committed_ = false; bool committed_ = false;
...@@ -486,7 +478,7 @@ class PLATFORM_EXPORT PaintController { ...@@ -486,7 +478,7 @@ class PLATFORM_EXPORT PaintController {
static size_t sum_num_subsequences_; static size_t sum_num_subsequences_;
static size_t sum_num_cached_subsequences_; static size_t sum_num_cached_subsequences_;
class DisplayItemListAsJSON; class PaintArtifactAsJSON;
DISALLOW_COPY_AND_ASSIGN(PaintController); DISALLOW_COPY_AND_ASSIGN(PaintController);
}; };
......
...@@ -10,17 +10,17 @@ ...@@ -10,17 +10,17 @@
namespace blink { namespace blink {
class PaintController::DisplayItemListAsJSON { class PaintController::PaintArtifactAsJSON {
STACK_ALLOCATED(); STACK_ALLOCATED();
public: public:
DisplayItemListAsJSON(const DisplayItemList&, PaintArtifactAsJSON(const PaintArtifact&,
const CachedSubsequenceMap&, const CachedSubsequenceMap&,
const Vector<PaintChunk>&, DisplayItemList::JsonFlags);
DisplayItemList::JsonFlags);
String ToString() { String ToString() {
return ChunksAsJSONArrayRecursive(0, chunks_.size())->ToPrettyJSONString(); return ChunksAsJSONArrayRecursive(0, artifact_.PaintChunks().size())
->ToPrettyJSONString();
} }
private: private:
...@@ -35,21 +35,17 @@ class PaintController::DisplayItemListAsJSON { ...@@ -35,21 +35,17 @@ class PaintController::DisplayItemListAsJSON {
wtf_size_t end_chunk_index; wtf_size_t end_chunk_index;
}; };
const DisplayItemList& list_; const PaintArtifact& artifact_;
Vector<SubsequenceInfo> subsequences_; Vector<SubsequenceInfo> subsequences_;
Vector<SubsequenceInfo>::const_iterator current_subsequence_; Vector<SubsequenceInfo>::const_iterator next_subsequence_;
const Vector<PaintChunk>& chunks_;
DisplayItemList::JsonFlags flags_; DisplayItemList::JsonFlags flags_;
}; };
PaintController::DisplayItemListAsJSON::DisplayItemListAsJSON( PaintController::PaintArtifactAsJSON::PaintArtifactAsJSON(
const DisplayItemList& list, const PaintArtifact& artifact,
const CachedSubsequenceMap& subsequence_map, const CachedSubsequenceMap& subsequence_map,
const Vector<PaintChunk>& chunks,
DisplayItemList::JsonFlags flags) DisplayItemList::JsonFlags flags)
: list_(list), : artifact_(artifact), flags_(flags) {
chunks_(chunks),
flags_(flags) {
for (const auto& item : subsequence_map) { for (const auto& item : subsequence_map) {
subsequences_.push_back(SubsequenceInfo{ subsequences_.push_back(SubsequenceInfo{
item.key, item.value.start_chunk_index, item.value.end_chunk_index}); item.key, item.value.start_chunk_index, item.value.end_chunk_index});
...@@ -61,13 +57,13 @@ PaintController::DisplayItemListAsJSON::DisplayItemListAsJSON( ...@@ -61,13 +57,13 @@ PaintController::DisplayItemListAsJSON::DisplayItemListAsJSON(
: a.start_chunk_index < b.start_chunk_index; : a.start_chunk_index < b.start_chunk_index;
}); });
current_subsequence_ = subsequences_.begin(); next_subsequence_ = subsequences_.begin();
} }
std::unique_ptr<JSONObject> std::unique_ptr<JSONObject>
PaintController::DisplayItemListAsJSON::SubsequenceAsJSONObjectRecursive() { PaintController::PaintArtifactAsJSON::SubsequenceAsJSONObjectRecursive() {
const auto& subsequence = *current_subsequence_; const auto& subsequence = *next_subsequence_;
++current_subsequence_; ++next_subsequence_;
auto json_object = std::make_unique<JSONObject>(); auto json_object = std::make_unique<JSONObject>();
...@@ -82,15 +78,15 @@ PaintController::DisplayItemListAsJSON::SubsequenceAsJSONObjectRecursive() { ...@@ -82,15 +78,15 @@ PaintController::DisplayItemListAsJSON::SubsequenceAsJSONObjectRecursive() {
} }
std::unique_ptr<JSONArray> std::unique_ptr<JSONArray>
PaintController::DisplayItemListAsJSON::ChunksAsJSONArrayRecursive( PaintController::PaintArtifactAsJSON::ChunksAsJSONArrayRecursive(
wtf_size_t start_chunk_index, wtf_size_t start_chunk_index,
wtf_size_t end_chunk_index) { wtf_size_t end_chunk_index) {
auto array = std::make_unique<JSONArray>(); auto array = std::make_unique<JSONArray>();
auto chunk_index = start_chunk_index; auto chunk_index = start_chunk_index;
while (current_subsequence_ != subsequences_.end() && while (next_subsequence_ != subsequences_.end() &&
current_subsequence_->start_chunk_index < end_chunk_index) { next_subsequence_->start_chunk_index < end_chunk_index) {
const auto& subsequence = *current_subsequence_; const auto& subsequence = *next_subsequence_;
DCHECK_GE(subsequence.start_chunk_index, chunk_index); DCHECK_GE(subsequence.start_chunk_index, chunk_index);
DCHECK_LE(subsequence.end_chunk_index, end_chunk_index); DCHECK_LE(subsequence.end_chunk_index, end_chunk_index);
...@@ -106,13 +102,13 @@ PaintController::DisplayItemListAsJSON::ChunksAsJSONArrayRecursive( ...@@ -106,13 +102,13 @@ PaintController::DisplayItemListAsJSON::ChunksAsJSONArrayRecursive(
return array; return array;
} }
void PaintController::DisplayItemListAsJSON::AppendChunksAsJSON( void PaintController::PaintArtifactAsJSON::AppendChunksAsJSON(
wtf_size_t start_chunk_index, wtf_size_t start_chunk_index,
wtf_size_t end_chunk_index, wtf_size_t end_chunk_index,
JSONArray& json_array) { JSONArray& json_array) {
DCHECK_GT(end_chunk_index, start_chunk_index); DCHECK_GT(end_chunk_index, start_chunk_index);
for (auto i = start_chunk_index; i < end_chunk_index; ++i) { for (auto i = start_chunk_index; i < end_chunk_index; ++i) {
const auto& chunk = chunks_[i]; const auto& chunk = artifact_.PaintChunks()[i];
auto json_object = std::make_unique<JSONObject>(); auto json_object = std::make_unique<JSONObject>();
json_object->SetString( json_object->SetString(
...@@ -122,16 +118,15 @@ void PaintController::DisplayItemListAsJSON::AppendChunksAsJSON( ...@@ -122,16 +118,15 @@ void PaintController::DisplayItemListAsJSON::AppendChunksAsJSON(
if (flags_ & DisplayItemList::kShowPaintRecords) if (flags_ & DisplayItemList::kShowPaintRecords)
json_object->SetString("chunkData", chunk.ToString()); json_object->SetString("chunkData", chunk.ToString());
json_object->SetArray( json_object->SetArray("displayItems",
"displayItems", DisplayItemList::DisplayItemsAsJSON(
DisplayItemList::DisplayItemsAsJSON( artifact_.DisplayItemsInChunk(i), flags_));
list_.ItemsInRange(chunk.begin_index, chunk.end_index), flags_));
json_array.PushObject(std::move(json_object)); json_array.PushObject(std::move(json_object));
} }
} }
String PaintController::DisplayItemListAsJSON::ClientName( String PaintController::PaintArtifactAsJSON::ClientName(
const DisplayItemClient& client) const { const DisplayItemClient& client) const {
return client.SafeDebugName(flags_ & DisplayItemList::kClientKnownToBeAlive); return client.SafeDebugName(flags_ & DisplayItemList::kClientKnownToBeAlive);
} }
...@@ -142,22 +137,25 @@ void PaintController::ShowDebugDataInternal( ...@@ -142,22 +137,25 @@ void PaintController::ShowDebugDataInternal(
// The clients in the current list are known to be alive before FinishCycle(). // The clients in the current list are known to be alive before FinishCycle().
if (committed_) if (committed_)
current_list_flags |= DisplayItemList::kClientKnownToBeAlive; current_list_flags |= DisplayItemList::kClientKnownToBeAlive;
LOG(INFO) << "current display item list: " LOG(INFO) << "current paint artifact: "
<< DisplayItemListAsJSON( << (current_paint_artifact_
current_paint_artifact_->GetDisplayItemList(), ? PaintArtifactAsJSON(*current_paint_artifact_,
current_cached_subsequences_, current_cached_subsequences_,
current_paint_artifact_->PaintChunks(), current_list_flags) current_list_flags)
.ToString() .ToString()
.Utf8(); .Utf8()
: "null");
LOG(INFO) << "new display item list: "
<< DisplayItemListAsJSON( LOG(INFO)
new_display_item_list_, new_cached_subsequences_, << "new paint artifact: "
new_paint_chunks_.PaintChunks(), << (new_paint_artifact_
// The clients in new_display_item_list_ are all alive. ? PaintArtifactAsJSON(
flags | DisplayItemList::kClientKnownToBeAlive) *new_paint_artifact_, new_cached_subsequences_,
.ToString() // The clients in new_display_item_list_ are all alive.
.Utf8(); flags | DisplayItemList::kClientKnownToBeAlive)
.ToString()
.Utf8()
: "null");
} }
void PaintController::ShowCompactDebugData() const { void PaintController::ShowCompactDebugData() const {
......
...@@ -844,6 +844,85 @@ TEST_P(PaintControllerTest, CachedSubsequenceAndDisplayItemsSwapOrder) { ...@@ -844,6 +844,85 @@ TEST_P(PaintControllerTest, CachedSubsequenceAndDisplayItemsSwapOrder) {
DefaultPaintChunkProperties()))); DefaultPaintChunkProperties())));
} }
TEST_P(PaintControllerTest, DisplayItemSwapOrderBeforeCachedSubsequence) {
FakeDisplayItemClient content1a("content1a");
FakeDisplayItemClient content1b("content1b");
FakeDisplayItemClient container2("container2");
FakeDisplayItemClient content3("content3");
GraphicsContext context(GetPaintController());
PaintChunk::Id content1a_id(content1a, kBackgroundType);
PaintChunk::Id content1b_id(content1b, kBackgroundType);
PaintChunk::Id container2_id(container2, kBackgroundType);
PaintChunk::Id content3_id(content3, kBackgroundType);
IntRect rect(100, 100, 50, 200);
InitRootChunk();
DrawRect(context, content1a, kBackgroundType, rect);
DrawRect(context, content1b, kBackgroundType, rect);
{
SubsequenceRecorder r(context, container2);
DrawRect(context, container2, kBackgroundType, rect);
}
DrawRect(context, content3, kBackgroundType, rect);
CommitAndFinishCycle();
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&content1a, kBackgroundType),
IsSameId(&content1b, kBackgroundType),
IsSameId(&container2, kBackgroundType),
IsSameId(&content3, kBackgroundType)));
// New paint order:
// Subsequence(container1): container1, content1b(cached), content1a(cached).
// Subsequence(container2): cached
// Subsequence(contaienr3): container3, content3
InitRootChunk();
if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) {
EXPECT_FALSE(DrawingRecorder::UseCachedDrawingIfPossible(context, content1b,
kBackgroundType));
DrawRect(context, content1b, kBackgroundType, rect);
EXPECT_FALSE(DrawingRecorder::UseCachedDrawingIfPossible(context, content1a,
kBackgroundType));
DrawRect(context, content1a, kBackgroundType, rect);
{
EXPECT_FALSE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
context, container2));
SubsequenceRecorder r(context, container2);
DrawRect(context, container2, kBackgroundType, rect);
}
EXPECT_FALSE(DrawingRecorder::UseCachedDrawingIfPossible(context, content3,
kBackgroundType));
DrawRect(context, content3, kBackgroundType, rect);
} else {
EXPECT_TRUE(DrawingRecorder::UseCachedDrawingIfPossible(context, content1b,
kBackgroundType));
EXPECT_TRUE(DrawingRecorder::UseCachedDrawingIfPossible(context, content1a,
kBackgroundType));
EXPECT_TRUE(SubsequenceRecorder::UseCachedSubsequenceIfPossible(
context, container2));
EXPECT_TRUE(DrawingRecorder::UseCachedDrawingIfPossible(context, content3,
kBackgroundType));
}
EXPECT_EQ(4u, NumCachedNewItems());
EXPECT_EQ(1u, NumCachedNewSubsequences());
#if DCHECK_IS_ON()
EXPECT_EQ(1u, NumIndexedItems());
EXPECT_EQ(2u, NumSequentialMatches());
EXPECT_EQ(1u, NumOutOfOrderMatches());
#endif
CommitAndFinishCycle();
EXPECT_THAT(GetPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&content1b, kBackgroundType),
IsSameId(&content1a, kBackgroundType),
IsSameId(&container2, kBackgroundType),
IsSameId(&content3, kBackgroundType)));
}
TEST_P(PaintControllerTest, CachedSubsequenceContainingFragments) { TEST_P(PaintControllerTest, CachedSubsequenceContainingFragments) {
GraphicsContext context(GetPaintController()); GraphicsContext context(GetPaintController());
FakeDisplayItemClient root("root"); FakeDisplayItemClient root("root");
...@@ -1246,17 +1325,19 @@ TEST_P(PaintControllerTest, SkipCache) { ...@@ -1246,17 +1325,19 @@ TEST_P(PaintControllerTest, SkipCache) {
GetPaintController().EndSkippingCache(); GetPaintController().EndSkippingCache();
// We should repaint everything on invalidation of the scope container. // We should repaint everything on invalidation of the scope container.
EXPECT_THAT(GetPaintController().NewDisplayItemList(), const auto& display_item_list =
GetPaintController().GetNewPaintArtifactShared()->GetDisplayItemList();
EXPECT_THAT(display_item_list,
ElementsAre(IsSameId(&multicol, kBackgroundType), ElementsAre(IsSameId(&multicol, kBackgroundType),
IsSameId(&content, kForegroundType), IsSameId(&content, kForegroundType),
IsSameId(&content, kForegroundType), IsSameId(&content, kForegroundType),
IsSameId(&content, kForegroundType))); IsSameId(&content, kForegroundType)));
EXPECT_NE(record1, static_cast<const DrawingDisplayItem&>( EXPECT_NE(record1,
GetPaintController().NewDisplayItemList()[1]) static_cast<const DrawingDisplayItem&>(display_item_list[1])
.GetPaintRecord()); .GetPaintRecord());
EXPECT_NE(record2, static_cast<const DrawingDisplayItem&>( EXPECT_NE(record2,
GetPaintController().NewDisplayItemList()[2]) static_cast<const DrawingDisplayItem&>(display_item_list[2])
.GetPaintRecord()); .GetPaintRecord());
CommitAndFinishCycle(); CommitAndFinishCycle();
EXPECT_DEFAULT_ROOT_CHUNK(4); EXPECT_DEFAULT_ROOT_CHUNK(4);
......
...@@ -46,7 +46,7 @@ class ScopedPaintChunkHint { ...@@ -46,7 +46,7 @@ class ScopedPaintChunkHint {
previous_force_new_chunk_(paint_controller_.WillForceNewChunk()) { previous_force_new_chunk_(paint_controller_.WillForceNewChunk()) {
if (!previous_force_new_chunk_ && previous_num_chunks_ && if (!previous_force_new_chunk_ && previous_num_chunks_ &&
!paint_controller_.LastChunkBounds().Contains(visual_rect)) !paint_controller_.LastChunkBounds().Contains(visual_rect))
paint_controller_.SetForceNewChunk(true); paint_controller_.SetWillForceNewChunk(true);
// This is after SetForceNewChunk(true) so that the possible new chunk will // This is after SetForceNewChunk(true) so that the possible new chunk will
// use the specified id. // use the specified id.
paint_chunk_properties_.emplace(paint_controller, properties, client, type); paint_chunk_properties_.emplace(paint_controller, properties, client, type);
...@@ -55,7 +55,7 @@ class ScopedPaintChunkHint { ...@@ -55,7 +55,7 @@ class ScopedPaintChunkHint {
~ScopedPaintChunkHint() { ~ScopedPaintChunkHint() {
paint_chunk_properties_ = base::nullopt; paint_chunk_properties_ = base::nullopt;
if (!HasCreatedPaintChunk()) if (!HasCreatedPaintChunk())
paint_controller_.SetForceNewChunk(previous_force_new_chunk_); paint_controller_.SetWillForceNewChunk(previous_force_new_chunk_);
} }
bool HasCreatedPaintChunk() const { bool HasCreatedPaintChunk() const {
......
...@@ -38,17 +38,18 @@ TestPaintArtifact& TestPaintArtifact::Chunk(int id) { ...@@ -38,17 +38,18 @@ TestPaintArtifact& TestPaintArtifact::Chunk(int id) {
TestPaintArtifact& TestPaintArtifact::Chunk(DisplayItemClient& client, TestPaintArtifact& TestPaintArtifact::Chunk(DisplayItemClient& client,
DisplayItem::Type type) { DisplayItem::Type type) {
paint_chunks_.push_back( auto& display_item_list = paint_artifact_->GetDisplayItemList();
PaintChunk(display_item_list_.size(), display_item_list_.size(), paint_artifact_->PaintChunks().emplace_back(
PaintChunk::Id(client, type), PropertyTreeState::Root())); display_item_list.size(), display_item_list.size(),
PaintChunk::Id(client, type), PropertyTreeState::Root());
// Assume PaintController has processed this chunk. // Assume PaintController has processed this chunk.
paint_chunks_.back().client_is_just_created = false; paint_artifact_->PaintChunks().back().client_is_just_created = false;
return *this; return *this;
} }
TestPaintArtifact& TestPaintArtifact::Properties( TestPaintArtifact& TestPaintArtifact::Properties(
const PropertyTreeStateOrAlias& properties) { const PropertyTreeStateOrAlias& properties) {
paint_chunks_.back().properties = properties; paint_artifact_->PaintChunks().back().properties = properties;
return *this; return *this;
} }
...@@ -66,8 +67,9 @@ TestPaintArtifact& TestPaintArtifact::ForeignLayer( ...@@ -66,8 +67,9 @@ TestPaintArtifact& TestPaintArtifact::ForeignLayer(
scoped_refptr<cc::Layer> layer, scoped_refptr<cc::Layer> layer,
const IntPoint& offset) { const IntPoint& offset) {
DEFINE_STATIC_LOCAL(LiteralDebugNameClient, client, ("ForeignLayer")); DEFINE_STATIC_LOCAL(LiteralDebugNameClient, client, ("ForeignLayer"));
display_item_list_.AllocateAndConstruct<ForeignLayerDisplayItem>( paint_artifact_->GetDisplayItemList()
client, DisplayItem::kForeignLayerFirst, std::move(layer), offset); .AllocateAndConstruct<ForeignLayerDisplayItem>(
client, DisplayItem::kForeignLayerFirst, std::move(layer), offset);
DidAddDisplayItem(); DidAddDisplayItem();
return *this; return *this;
} }
...@@ -82,9 +84,10 @@ TestPaintArtifact& TestPaintArtifact::RectDrawing(DisplayItemClient& client, ...@@ -82,9 +84,10 @@ TestPaintArtifact& TestPaintArtifact::RectDrawing(DisplayItemClient& client,
flags.setColor(color.Rgb()); flags.setColor(color.Rgb());
canvas->drawRect(bounds, flags); canvas->drawRect(bounds, flags);
} }
display_item_list_.AllocateAndConstruct<DrawingDisplayItem>( paint_artifact_->GetDisplayItemList()
client, DisplayItem::kDrawingFirst, bounds, .AllocateAndConstruct<DrawingDisplayItem>(
recorder.finishRecordingAsPicture()); client, DisplayItem::kDrawingFirst, bounds,
recorder.finishRecordingAsPicture());
DidAddDisplayItem(); DidAddDisplayItem();
return *this; return *this;
} }
...@@ -92,43 +95,44 @@ TestPaintArtifact& TestPaintArtifact::RectDrawing(DisplayItemClient& client, ...@@ -92,43 +95,44 @@ TestPaintArtifact& TestPaintArtifact::RectDrawing(DisplayItemClient& client,
TestPaintArtifact& TestPaintArtifact::ScrollHitTest( TestPaintArtifact& TestPaintArtifact::ScrollHitTest(
DisplayItemClient& client, DisplayItemClient& client,
const TransformPaintPropertyNode* scroll_translation) { const TransformPaintPropertyNode* scroll_translation) {
paint_chunks_.back().EnsureHitTestData().scroll_translation = paint_artifact_->PaintChunks().back().EnsureHitTestData().scroll_translation =
scroll_translation; scroll_translation;
return *this; return *this;
} }
TestPaintArtifact& TestPaintArtifact::SetRasterEffectOutset( TestPaintArtifact& TestPaintArtifact::SetRasterEffectOutset(
RasterEffectOutset outset) { RasterEffectOutset outset) {
paint_chunks_.back().raster_effect_outset = outset; paint_artifact_->PaintChunks().back().raster_effect_outset = outset;
return *this; return *this;
} }
TestPaintArtifact& TestPaintArtifact::KnownToBeOpaque() { TestPaintArtifact& TestPaintArtifact::KnownToBeOpaque() {
paint_chunks_.back().known_to_be_opaque = true; paint_artifact_->PaintChunks().back().known_to_be_opaque = true;
return *this; return *this;
} }
TestPaintArtifact& TestPaintArtifact::Bounds(const IntRect& bounds) { TestPaintArtifact& TestPaintArtifact::Bounds(const IntRect& bounds) {
paint_chunks_.back().bounds = bounds; auto& chunk = paint_artifact_->PaintChunks().back();
paint_chunks_.back().drawable_bounds = bounds; chunk.bounds = bounds;
chunk.drawable_bounds = bounds;
return *this; return *this;
} }
TestPaintArtifact& TestPaintArtifact::DrawableBounds( TestPaintArtifact& TestPaintArtifact::DrawableBounds(
const IntRect& drawable_bounds) { const IntRect& drawable_bounds) {
paint_chunks_.back().drawable_bounds = drawable_bounds; auto& chunk = paint_artifact_->PaintChunks().back();
DCHECK(paint_chunks_.back().bounds.Contains(drawable_bounds)); chunk.drawable_bounds = drawable_bounds;
DCHECK(chunk.bounds.Contains(drawable_bounds));
return *this; return *this;
} }
TestPaintArtifact& TestPaintArtifact::Uncacheable() { TestPaintArtifact& TestPaintArtifact::Uncacheable() {
paint_chunks_.back().is_cacheable = false; paint_artifact_->PaintChunks().back().is_cacheable = false;
return *this; return *this;
} }
scoped_refptr<PaintArtifact> TestPaintArtifact::Build() { scoped_refptr<PaintArtifact> TestPaintArtifact::Build() {
return base::MakeRefCounted<PaintArtifact>(std::move(display_item_list_), return std::move(paint_artifact_);
std::move(paint_chunks_));
} }
FakeDisplayItemClient& TestPaintArtifact::NewClient() { FakeDisplayItemClient& TestPaintArtifact::NewClient() {
...@@ -141,9 +145,9 @@ FakeDisplayItemClient& TestPaintArtifact::Client(wtf_size_t i) const { ...@@ -141,9 +145,9 @@ FakeDisplayItemClient& TestPaintArtifact::Client(wtf_size_t i) const {
} }
void TestPaintArtifact::DidAddDisplayItem() { void TestPaintArtifact::DidAddDisplayItem() {
auto& chunk = paint_chunks_.back(); auto& chunk = paint_artifact_->PaintChunks().back();
DCHECK_EQ(chunk.end_index, display_item_list_.size() - 1); DCHECK_EQ(chunk.end_index, paint_artifact_->GetDisplayItemList().size() - 1);
const auto& item = display_item_list_.Last(); const auto& item = paint_artifact_->GetDisplayItemList().Last();
chunk.bounds.Unite(item.VisualRect()); chunk.bounds.Unite(item.VisualRect());
if (item.DrawsContent()) if (item.DrawsContent())
chunk.drawable_bounds.Unite(item.VisualRect()); chunk.drawable_bounds.Unite(item.VisualRect());
......
...@@ -132,9 +132,8 @@ class TestPaintArtifact { ...@@ -132,9 +132,8 @@ class TestPaintArtifact {
void DidAddDisplayItem(); void DidAddDisplayItem();
Vector<std::unique_ptr<FakeDisplayItemClient>> clients_; Vector<std::unique_ptr<FakeDisplayItemClient>> clients_;
scoped_refptr<PaintArtifact> paint_artifact_ =
DisplayItemList display_item_list_; base::MakeRefCounted<PaintArtifact>();
Vector<PaintChunk> paint_chunks_;
}; };
} // namespace blink } // namespace blink
......
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