blob: a80b47d6dd8da7b8d38012541bddb654b965ce7b [file] [log] [blame]
// Copyright 2015 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/PaintChunker.h"
#include "platform/RuntimeEnabledFeatures.h"
namespace blink {
PaintChunker::PaintChunker() : force_new_chunk_(false) {}
PaintChunker::~PaintChunker() {}
void PaintChunker::UpdateCurrentPaintChunkProperties(
const PaintChunk::Id* chunk_id,
const PaintChunkProperties& properties) {
DCHECK(RuntimeEnabledFeatures::SlimmingPaintV2Enabled());
current_chunk_id_ = WTF::nullopt;
if (chunk_id)
current_chunk_id_.emplace(*chunk_id);
current_properties_ = properties;
}
bool PaintChunker::IncrementDisplayItemIndex(const DisplayItem& item) {
DCHECK(RuntimeEnabledFeatures::SlimmingPaintV2Enabled());
#if DCHECK_IS_ON()
// Property nodes should never be null because they should either be set to
// properties created by a LayoutObject/FrameView, or be set to a non-null
// root node. If these DCHECKs are hit we are missing a call to update the
// properties. See: ScopedPaintChunkProperties.
DCHECK(current_properties_.property_tree_state.Transform());
DCHECK(current_properties_.property_tree_state.Clip());
DCHECK(current_properties_.property_tree_state.Effect());
#endif
bool item_forces_new_chunk = item.IsForeignLayer() || item.IsScrollHitTest();
if (item_forces_new_chunk) {
force_new_chunk_ = true;
// Clear current_chunk_id_ so that we will use the current display item's id
// as the chunk id, and any display items after the forcing item 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 forced chunk.
current_chunk_id_ = WTF::nullopt;
}
size_t new_chunk_begin_index;
if (chunks_.IsEmpty()) {
new_chunk_begin_index = 0;
} else {
auto& last_chunk = chunks_.back();
if (!force_new_chunk_ && current_properties_ == last_chunk.properties) {
// Continue the current chunk.
last_chunk.end_index++;
return false;
}
new_chunk_begin_index = last_chunk.end_index;
}
auto cacheable =
item.SkippedCache() ? PaintChunk::kUncacheable : PaintChunk::kCacheable;
PaintChunk new_chunk(new_chunk_begin_index, new_chunk_begin_index + 1,
current_chunk_id_ ? *current_chunk_id_ : item.GetId(),
current_properties_, cacheable);
chunks_.push_back(new_chunk);
// When forcing a new chunk, we still need to force new chunk for the next
// display item. Otherwise reset force_new_chunk_ to false.
if (!item_forces_new_chunk)
force_new_chunk_ = false;
return true;
}
void PaintChunker::Clear() {
chunks_.clear();
current_chunk_id_ = WTF::nullopt;
current_properties_ = PaintChunkProperties();
}
Vector<PaintChunk> PaintChunker::ReleasePaintChunks() {
Vector<PaintChunk> chunks;
chunks.swap(chunks_);
current_chunk_id_ = WTF::nullopt;
current_properties_ = PaintChunkProperties();
return chunks;
}
} // namespace blink