blob: 82b11078a1c14efd3d603947181361ef2dc35ac5 [file] [log] [blame]
// Copyright 2014 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 THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_DISPLAY_ITEM_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_DISPLAY_ITEM_H_
#include "third_party/blink/renderer/platform/geometry/int_rect.h"
#include "third_party/blink/renderer/platform/graphics/contiguous_container.h"
#include "third_party/blink/renderer/platform/graphics/paint/display_item_client.h"
#include "third_party/blink/renderer/platform/platform_export.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h"
#if DCHECK_IS_ON()
#include "third_party/blink/renderer/platform/json/json_values.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#endif
namespace blink {
enum class PaintPhase;
class PLATFORM_EXPORT DisplayItem {
DISALLOW_NEW();
public:
enum {
// Must be kept in sync with core/paint/PaintPhase.h.
kPaintPhaseMax = 12,
};
// A display item type uniquely identifies a display item of a client.
// Some display item types can be categorized using the following directives:
// - In enum Type:
// - enum value <Category>First;
// - enum values of the category, first of which should equal
// <Category>First (for ease of maintenance, the values should be in
// alphabetic order);
// - enum value <Category>Last which should be equal to the last of the enum
// values of the category
// - DEFINE_CATEGORY_METHODS(<Category>) to define is<Category>Type(Type) and
// is<Category>() methods.
//
// A category or subset of a category can contain types each of which
// corresponds to a PaintPhase:
// - In enum Type:
// - enum value <Category>[<Subset>]PaintPhaseFirst;
// - enum value <Category>[<Subset>]PaintPhaseLast =
// <Category>[<Subset>]PaintPhaseFirst + PaintPhaseMax;
// - DEFINE_PAINT_PHASE_CONVERSION_METHOD(<Category>[<Subset>]) to define
// paintPhaseTo<Category>[<Subset>]Type(PaintPhase) method.
enum Type {
kDrawingFirst,
kDrawingPaintPhaseFirst = kDrawingFirst,
kDrawingPaintPhaseLast = kDrawingFirst + kPaintPhaseMax,
kBoxDecorationBackground,
kCapsLockIndicator,
kCaret,
kClippingMask,
kColumnRules,
kDebugDrawing,
kDocumentRootBackdrop,
kDocumentBackground,
kDragImage,
kDragCaret,
kForcedColorsModeBackplate,
kSVGImage,
kLinkHighlight,
kImageAreaFocusRing,
kOverflowControls,
kFrameOverlay,
kPopupContainerBorder,
kPopupListBoxBackground,
kPopupListBoxRow,
kPrintedContentDestinationLocations,
kPrintedContentPDFURLRect,
kReflectionMask,
kResizer,
kSVGClip,
kSVGMask,
kScrollCorner,
// The following 3 types are used during cc::Scrollbar::PaintPart() only.
// During Paint stage of document lifecycle update, we record
// ScrollbarDisplayItem instead of DrawingItems of these types.
kScrollbarTrackAndButtons,
kScrollbarThumb,
kScrollbarTickmarks,
kSelectionTint,
kTableCollapsedBorders,
kVideoBitmap,
kWebFont,
kWebPlugin,
kDrawingLast = kWebPlugin,
kForeignLayerFirst,
kForeignLayerCanvas = kForeignLayerFirst,
kForeignLayerDevToolsOverlay,
kForeignLayerPlugin,
kForeignLayerVideo,
kForeignLayerRemoteFrame,
kForeignLayerContentsWrapper,
kForeignLayerLinkHighlight,
kForeignLayerViewportScroll,
kForeignLayerViewportScrollbar,
kForeignLayerLast = kForeignLayerViewportScrollbar,
kClipPaintPhaseFirst,
kClipPaintPhaseLast = kClipPaintPhaseFirst + kPaintPhaseMax,
kScrollPaintPhaseFirst,
kScrollPaintPhaseLast = kScrollPaintPhaseFirst + kPaintPhaseMax,
kSVGTransformPaintPhaseFirst,
kSVGTransformPaintPhaseLast = kSVGTransformPaintPhaseFirst + kPaintPhaseMax,
kSVGEffectPaintPhaseFirst,
kSVGEffectPaintPhaseLast = kSVGEffectPaintPhaseFirst + kPaintPhaseMax,
// The following hit test types are for paint chunks containing hit test
// data, when we don't have an previously set explicit chunk id when
// creating the paint chunk, or we need dedicated paint chunk for the hit
// test data.
// Compositor hit testing requires that layers are created and sized to
// include content that does not paint. Hit test data ensure a layer exists
// and is sized properly even if no content would otherwise be painted.
kHitTest,
// Used both for specifying the paint-order scroll location, and for non-
// composited scroll hit testing (see: hit_test_data.h).
kScrollHitTest,
// Used to prevent composited scrolling on the resize handle.
kResizerScrollHitTest,
// Used to prevent composited scrolling on plugins with wheel handlers.
kPluginScrollHitTest,
// Used to prevent composited scrolling on custom scrollbars.
kCustomScrollbarHitTest,
// These are for paint chunks that are forced for layers.
kLayerChunk,
// This is used if a layer has any negative-z-index children. Otherwise the
// foreground is in the kLayerChunk chunk.
kLayerChunkForeground,
// The following 2 types are For ScrollbarDisplayItem.
kScrollbarHorizontal,
kScrollbarVertical,
kUninitializedType,
kTypeLast = kUninitializedType
};
// Some fields are copied from |client|, because we need to access them in
// later paint cycles when |client| may have been destroyed.
DisplayItem(const DisplayItemClient& client,
Type type,
wtf_size_t derived_size,
const IntRect& visual_rect,
bool draws_content = false)
: client_(&client),
visual_rect_(visual_rect),
fragment_(0),
type_(type),
derived_size_(derived_size),
raster_effect_outset_(
static_cast<unsigned>(client.VisualRectOutsetForRasterEffects())),
draws_content_(draws_content),
is_cacheable_(client.IsCacheable()),
is_tombstone_(false) {
// |derived_size| must fit in |derived_size_|.
// If it doesn't, enlarge |derived_size_| and fix this assert.
SECURITY_DCHECK(derived_size == derived_size_);
SECURITY_DCHECK(derived_size >= sizeof(*this));
DCHECK_EQ(client.VisualRectOutsetForRasterEffects(),
GetRasterEffectOutset());
}
virtual ~DisplayItem() = default;
// Ids are for matching new DisplayItems with existing DisplayItems.
struct Id {
DISALLOW_NEW();
Id(const DisplayItemClient& client, Type type, wtf_size_t fragment = 0)
: client(client), type(type), fragment(fragment) {}
Id(const Id& id, wtf_size_t fragment)
: client(id.client), type(id.type), fragment(fragment) {}
String ToString() const;
const DisplayItemClient& client;
const Type type;
const wtf_size_t fragment;
};
Id GetId() const { return Id(*client_, GetType(), fragment_); }
const DisplayItemClient& Client() const {
DCHECK(client_);
return *client_;
}
// The bounding box of all pixels of this display item, in the transform space
// of the containing paint chunk.
const IntRect& VisualRect() const { return visual_rect_; }
RasterEffectOutset GetRasterEffectOutset() const {
return static_cast<RasterEffectOutset>(raster_effect_outset_);
}
Type GetType() const { return static_cast<Type>(type_); }
// Size of this object in memory, used to move it with memcpy.
// This is not sizeof(*this), because it needs to account for the size of
// the derived class (i.e. runtime type). Derived classes are expected to
// supply this to the DisplayItem constructor.
wtf_size_t DerivedSize() const { return derived_size_; }
// The fragment is part of the id, to uniquely identify display items in
// different fragments for the same client and type.
wtf_size_t Fragment() const { return fragment_; }
void SetFragment(wtf_size_t fragment) { fragment_ = fragment; }
// See comments of enum Type for usage of the following macros.
#define DEFINE_CATEGORY_METHODS(Category) \
static constexpr bool Is##Category##Type(Type type) { \
return type >= k##Category##First && type <= k##Category##Last; \
} \
bool Is##Category() const { return Is##Category##Type(GetType()); }
#define DEFINE_PAINT_PHASE_CONVERSION_METHOD(Category) \
static constexpr Type PaintPhaseTo##Category##Type(PaintPhase paint_phase) { \
static_assert( \
k##Category##PaintPhaseLast - k##Category##PaintPhaseFirst == \
kPaintPhaseMax, \
"Invalid paint-phase-based category " #Category \
". See comments of DisplayItem::Type"); \
return static_cast<Type>(static_cast<int>(paint_phase) + \
k##Category##PaintPhaseFirst); \
}
DEFINE_CATEGORY_METHODS(Drawing)
DEFINE_PAINT_PHASE_CONVERSION_METHOD(Drawing)
DEFINE_CATEGORY_METHODS(ForeignLayer)
DEFINE_PAINT_PHASE_CONVERSION_METHOD(Clip)
DEFINE_PAINT_PHASE_CONVERSION_METHOD(Scroll)
DEFINE_PAINT_PHASE_CONVERSION_METHOD(SVGTransform)
DEFINE_PAINT_PHASE_CONVERSION_METHOD(SVGEffect)
bool IsScrollbar() const {
return type_ == kScrollbarHorizontal || type_ == kScrollbarVertical;
}
bool IsCacheable() const { return is_cacheable_; }
void SetUncacheable() { is_cacheable_ = false; }
virtual bool Equals(const DisplayItem& other) const {
// Failure of this DCHECK would cause bad casts in subclasses.
SECURITY_CHECK(!is_tombstone_);
return client_ == other.client_ && type_ == other.type_ &&
fragment_ == other.fragment_ && derived_size_ == other.derived_size_;
}
// True if this DisplayItem is the tombstone/"dead display item" as part of
// moving an item from one list to another. See the default constructor of
// DisplayItem.
bool IsTombstone() const { return is_tombstone_; }
bool DrawsContent() const { return draws_content_; }
#if DCHECK_IS_ON()
static WTF::String TypeAsDebugString(DisplayItem::Type);
WTF::String AsDebugString() const;
virtual void PropertiesAsJSON(JSONObject&) const;
#endif
private:
template <typename T, wtf_size_t alignment>
friend class ContiguousContainer;
friend class DisplayItemList;
// The default DisplayItem constructor is only used by ContiguousContainer::
// AppendByMoving() where a tombstone DisplayItem is constructed at the source
// location. Only set draws_content_ to false and is_tombstone_ to true,
// leaving other fields as-is so that we can get their original values.
// |visual_rect_| and |raster_effect_outset_| are special, see
// DisplayItemList::AppendByMoving().
DisplayItem() : draws_content_(false), is_tombstone_(true) {}
const DisplayItemClient* client_;
IntRect visual_rect_;
wtf_size_t fragment_;
static_assert(kTypeLast < (1 << 8),
"DisplayItem::Type should fit in uint8_t");
unsigned type_ : 8;
unsigned derived_size_ : 8; // size of the actual derived class
unsigned raster_effect_outset_ : 2;
unsigned draws_content_ : 1;
unsigned is_cacheable_ : 1;
unsigned is_tombstone_ : 1;
};
inline bool operator==(const DisplayItem::Id& a, const DisplayItem::Id& b) {
return a.client == b.client && a.type == b.type && a.fragment == b.fragment;
}
inline bool operator!=(const DisplayItem::Id& a, const DisplayItem::Id& b) {
return !(a == b);
}
PLATFORM_EXPORT std::ostream& operator<<(std::ostream&, DisplayItem::Type);
PLATFORM_EXPORT std::ostream& operator<<(std::ostream&, const DisplayItem::Id&);
PLATFORM_EXPORT std::ostream& operator<<(std::ostream&, const DisplayItem&);
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_DISPLAY_ITEM_H_