blob: 89d56a36330c0edb43847fd25dbd30c42cfecd63 [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.
#ifndef PaintChunk_h
#define PaintChunk_h
#include <iosfwd>
#include "platform/PlatformExport.h"
#include "platform/geometry/FloatRect.h"
#include "platform/graphics/paint/DisplayItem.h"
#include "platform/graphics/paint/PaintChunkProperties.h"
#include "platform/graphics/paint/RasterInvalidationTracking.h"
#include "platform/wtf/Allocator.h"
#include "platform/wtf/Forward.h"
#include "platform/wtf/Vector.h"
namespace blink {
// A contiguous sequence of drawings with common paint properties.
//
// This is expected to be owned by the paint artifact which also owns the
// related drawings.
//
// This is a Slimming Paint v175+ class.
struct PLATFORM_EXPORT PaintChunk {
DISALLOW_NEW_EXCEPT_PLACEMENT_NEW();
using Id = DisplayItem::Id;
enum Cacheable {
kCacheable,
kUncacheable,
};
PaintChunk(size_t begin,
size_t end,
const Id& id,
const PaintChunkProperties& props,
Cacheable cacheable = kCacheable)
: begin_index(begin),
end_index(end),
id(id),
properties(props),
outset_for_raster_effects(0),
known_to_be_opaque(false),
is_cacheable(cacheable == kCacheable),
client_is_just_created(id.client.IsJustCreated()) {}
size_t size() const {
DCHECK_GE(end_index, begin_index);
return end_index - begin_index;
}
// 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 {
return old.is_cacheable && Matches(old.id);
}
bool Matches(const Id& other_id) const {
if (!is_cacheable || id != other_id)
return false;
#if DCHECK_IS_ON()
DCHECK(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 !client_is_just_created;
}
// Index of the first drawing in this chunk.
size_t begin_index;
// Index of the first drawing not in this chunk, so that there are
// |endIndex - beginIndex| drawings in the chunk.
size_t end_index;
// Identifier of this chunk. If it has a value, it should be unique. This is
// 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 the cache, normally because display items can't
// be uniquely identified), |id| is nullopt so that the chunk won't match any
// other chunk.
Id id;
// The paint properties which apply to this chunk.
PaintChunkProperties properties;
// The total bounds of this paint chunk's contents, in the coordinate space of
// the containing transform node.
FloatRect bounds;
// Some raster effects can exceed |bounds| in the rasterization space. This
// is the maximum DisplayItemClient::VisualRectOutsetForRasterEffects() of
// all clients of items in this chunk.
float outset_for_raster_effects;
// True if the bounds are filled entirely with opaque contents.
bool known_to_be_opaque : 1;
bool is_cacheable : 1;
// TODO(wangxianzhu): The following fields are 'mutable' for
// ContentLayerClientImpl to clear them, which will be unnecessary if we don't
// call PaintArtifactCompositor::Update() when paint artifact is unchanged.
mutable bool client_is_just_created : 1;
// Rectangles that need to be re-rasterized in this chunk, in the coordinate
// space of the containing transform node.
mutable Vector<FloatRect> raster_invalidation_rects;
mutable Vector<RasterInvalidationInfo> raster_invalidation_tracking;
String ToString() const;
};
inline bool operator==(const PaintChunk& a, const PaintChunk& b) {
return a.begin_index == b.begin_index && a.end_index == b.end_index &&
a.id == b.id && a.properties == b.properties && a.bounds == b.bounds &&
a.known_to_be_opaque == b.known_to_be_opaque &&
a.is_cacheable == b.is_cacheable &&
a.raster_invalidation_rects == b.raster_invalidation_rects;
}
inline bool operator!=(const PaintChunk& a, const PaintChunk& b) {
return !(a == b);
}
inline bool ChunkLessThanIndex(const PaintChunk& chunk, size_t index) {
return chunk.end_index <= index;
}
inline Vector<PaintChunk>::iterator FindChunkInVectorByDisplayItemIndex(
Vector<PaintChunk>& chunks,
size_t index) {
auto chunk =
std::lower_bound(chunks.begin(), chunks.end(), index, ChunkLessThanIndex);
DCHECK(chunk == chunks.end() ||
(index >= chunk->begin_index && index < chunk->end_index));
return chunk;
}
inline Vector<PaintChunk>::const_iterator FindChunkInVectorByDisplayItemIndex(
const Vector<PaintChunk>& chunks,
size_t index) {
return FindChunkInVectorByDisplayItemIndex(
const_cast<Vector<PaintChunk>&>(chunks), index);
}
// Redeclared here to avoid ODR issues.
// See platform/testing/PaintPrinters.h.
void PrintTo(const PaintChunk&, std::ostream*);
} // namespace blink
#endif // PaintChunk_h