Commit dfa0f14f authored by Xianzhu Wang's avatar Xianzhu Wang Committed by Commit Bot

[PE] Ensure PaintChunk::hit_test_data is updated in a cached subsequence

Previously PaintChunk::hit_test_data was updated only in
HitTestData::RecordHitTestRect(), so when we copied cached subsequence,
the PaintChunks didn't have hit_test_data.

Now add HitTestDisplayItem to store the hit test data in display items,
and update PaintChunk::hit_test_data in PaintArtifact constructor.

Change-Id: I8a96823f15c0107fc21e5b388763ebfc3925eef0
Reviewed-on: https://chromium-review.googlesource.com/c/1325570
Commit-Queue: Xianzhu Wang <wangxianzhu@chromium.org>
Reviewed-by: default avatarPhilip Rogers <pdr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#606921}
parent 5a86c241
...@@ -272,7 +272,7 @@ static void UpdateLayerTouchActionRects(GraphicsLayer& layer) { ...@@ -272,7 +272,7 @@ static void UpdateLayerTouchActionRects(GraphicsLayer& layer) {
return; return;
} }
for (const auto& chunk : layer.GetPaintController().PaintChunks()) { for (const auto& chunk : layer.GetPaintController().PaintChunks()) {
const auto* hit_test_data = chunk.GetHitTestData(); const auto* hit_test_data = chunk.hit_test_data.get();
if (!hit_test_data || hit_test_data->touch_action_rects.IsEmpty()) if (!hit_test_data || hit_test_data->touch_action_rects.IsEmpty())
continue; continue;
......
...@@ -236,6 +236,68 @@ TEST_F(BlockPainterTestWithPaintTouchAction, TouchActionRectsWithoutPaint) { ...@@ -236,6 +236,68 @@ TEST_F(BlockPainterTestWithPaintTouchAction, TouchActionRectsWithoutPaint) {
ElementsAre(IsSameId(&scrolling_client, kDocumentBackgroundType))); ElementsAre(IsSameId(&scrolling_client, kDocumentBackgroundType)));
} }
TEST_F(BlockPainterTestWithPaintTouchAction,
TouchActionRectSubsequenceCaching) {
SetBodyInnerHTML(R"HTML(
<style>
body { margin: 0; }
#touchaction {
width: 100px;
height: 100px;
touch-action: none;
}
#sibling {
width: 100px;
height: 100px;
background: blue;
}
</style>
<div id='touchaction'></div>
)HTML");
const auto& scrolling_client = ViewScrollingBackgroundClient();
const auto* touchaction = GetLayoutObjectByElementId("touchaction");
EXPECT_THAT(RootPaintController().GetDisplayItemList(),
ElementsAre(IsSameId(&scrolling_client, kDocumentBackgroundType),
IsSameId(touchaction, DisplayItem::kHitTest)));
const auto& hit_test_client = *touchaction->EnclosingLayer();
EXPECT_SUBSEQUENCE(hit_test_client, 1u, 2u);
PaintChunk::Id root_chunk_id(scrolling_client, kDocumentBackgroundType);
auto root_chunk_properties =
GetLayoutView().FirstFragment().ContentsProperties();
PaintChunk::Id hit_test_chunk_id(hit_test_client,
kNonScrollingBackgroundChunkType);
auto hit_test_chunk_properties = touchaction->EnclosingLayer()
->GetLayoutObject()
.FirstFragment()
.ContentsProperties();
HitTestData hit_test_data;
hit_test_data.touch_action_rects.emplace_back(LayoutRect(0, 0, 100, 100));
EXPECT_THAT(
RootPaintController().PaintChunks(),
ElementsAre(IsPaintChunk(0, 1, root_chunk_id, root_chunk_properties),
IsPaintChunk(1, 2, hit_test_chunk_id,
hit_test_chunk_properties, hit_test_data)));
// Trigger a repaint with the whole HTML subsequence cached.
GetLayoutView().Layer()->SetNeedsRepaint();
EXPECT_TRUE(PaintWithoutCommit());
EXPECT_EQ(2, NumCachedNewItems());
CommitAndFinishCycle();
EXPECT_SUBSEQUENCE(hit_test_client, 1u, 2u);
EXPECT_THAT(
RootPaintController().PaintChunks(),
ElementsAre(IsPaintChunk(0, 1, root_chunk_id, root_chunk_properties),
IsPaintChunk(1, 2, hit_test_chunk_id,
hit_test_chunk_properties, hit_test_data)));
}
TEST_F(BlockPainterTestWithPaintTouchAction, TouchActionRectPaintCaching) { TEST_F(BlockPainterTestWithPaintTouchAction, TouchActionRectPaintCaching) {
SetBodyInnerHTML(R"HTML( SetBodyInnerHTML(R"HTML(
<style> <style>
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h" #include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
#include "third_party/blink/renderer/platform/graphics/paint/display_item_cache_skipper.h" #include "third_party/blink/renderer/platform/graphics/paint/display_item_cache_skipper.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h" #include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h"
#include "third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h" #include "third_party/blink/renderer/platform/graphics/paint/scoped_paint_chunk_properties.h"
namespace blink { namespace blink {
...@@ -267,8 +268,8 @@ void BoxPainter::RecordHitTestData(const PaintInfo& paint_info, ...@@ -267,8 +268,8 @@ void BoxPainter::RecordHitTestData(const PaintInfo& paint_info,
if (touch_action == TouchAction::kTouchActionAuto) if (touch_action == TouchAction::kTouchActionAuto)
return; return;
HitTestData::RecordHitTestRect(paint_info.context, background_client, HitTestDisplayItem::Record(paint_info.context, background_client,
HitTestRect(paint_rect, touch_action)); HitTestRect(paint_rect, touch_action));
} }
} // namespace blink } // namespace blink
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "third_party/blink/renderer/core/paint/paint_info.h" #include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h" #include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h" #include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h"
namespace blink { namespace blink {
...@@ -345,7 +346,7 @@ void InlineFlowBoxPainter::RecordHitTestData(const PaintInfo& paint_info, ...@@ -345,7 +346,7 @@ void InlineFlowBoxPainter::RecordHitTestData(const PaintInfo& paint_info,
if (touch_action == TouchAction::kTouchActionAuto) if (touch_action == TouchAction::kTouchActionAuto)
return; return;
HitTestData::RecordHitTestRect( HitTestDisplayItem::Record(
paint_info.context, inline_flow_box_, paint_info.context, inline_flow_box_,
HitTestRect(AdjustedPaintRect(paint_offset), touch_action)); HitTestRect(AdjustedPaintRect(paint_offset), touch_action));
} }
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h" #include "third_party/blink/renderer/platform/graphics/graphics_context_state_saver.h"
#include "third_party/blink/renderer/platform/graphics/paint/display_item_cache_skipper.h" #include "third_party/blink/renderer/platform/graphics/paint/display_item_cache_skipper.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h" #include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h"
#include "third_party/blink/renderer/platform/scroll/scroll_types.h" #include "third_party/blink/renderer/platform/scroll/scroll_types.h"
namespace blink { namespace blink {
...@@ -219,7 +220,7 @@ void NGBoxFragmentPainter::RecordHitTestData(const PaintInfo& paint_info, ...@@ -219,7 +220,7 @@ void NGBoxFragmentPainter::RecordHitTestData(const PaintInfo& paint_info,
if (physical_fragment.IsInline()) if (physical_fragment.IsInline())
border_box.offset += box_fragment_.InlineOffsetToContainerBox(); border_box.offset += box_fragment_.InlineOffsetToContainerBox();
border_box.offset += NGPhysicalOffset(paint_offset); border_box.offset += NGPhysicalOffset(paint_offset);
HitTestData::RecordHitTestRect( HitTestDisplayItem::Record(
paint_info.context, box_fragment_, paint_info.context, box_fragment_,
HitTestRect(border_box.ToLayoutRect(), touch_action)); HitTestRect(border_box.ToLayoutRect(), touch_action));
} }
......
...@@ -116,6 +116,11 @@ class PaintControllerPaintTestBase : public RenderingTest { ...@@ -116,6 +116,11 @@ class PaintControllerPaintTestBase : public RenderingTest {
bool ClientCacheIsValid(const DisplayItemClient& client) { bool ClientCacheIsValid(const DisplayItemClient& client) {
return RootPaintController().ClientCacheIsValid(client); return RootPaintController().ClientCacheIsValid(client);
} }
using SubsequenceMarkers = PaintController::SubsequenceMarkers;
SubsequenceMarkers* GetSubsequenceMarkers(const DisplayItemClient& client) {
return RootPaintController().GetSubsequenceMarkers(client);
}
}; };
class PaintControllerPaintTest : public PaintTestConfigurations, class PaintControllerPaintTest : public PaintTestConfigurations,
...@@ -137,6 +142,17 @@ const DisplayItem::Type kScrollingContentsBackgroundChunkType = ...@@ -137,6 +142,17 @@ const DisplayItem::Type kScrollingContentsBackgroundChunkType =
DisplayItem::PaintPhaseToClipType( DisplayItem::PaintPhaseToClipType(
PaintPhase::kDescendantBlockBackgroundsOnly); PaintPhase::kDescendantBlockBackgroundsOnly);
#define EXPECT_SUBSEQUENCE(client, expected_start, expected_end) \
do { \
auto* subsequence = GetSubsequenceMarkers(client); \
ASSERT_NE(nullptr, subsequence); \
EXPECT_EQ(expected_start, subsequence->start); \
EXPECT_EQ(expected_end, subsequence->end); \
} while (false)
#define EXPECT_NO_SUBSEQUENCE(client) \
EXPECT_EQ(nullptr, GetSubsequenceMarkers(client)
} // namespace blink } // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_CONTROLLER_PAINT_TEST_H_ #endif // THIRD_PARTY_BLINK_RENDERER_CORE_PAINT_PAINT_CONTROLLER_PAINT_TEST_H_
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
#include "third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h" #include "third_party/blink/renderer/core/layout/svg/layout_svg_model_object.h"
#include "third_party/blink/renderer/core/paint/object_painter.h" #include "third_party/blink/renderer/core/paint/object_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h" #include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/platform/graphics/paint/hit_test_data.h" #include "third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h"
namespace blink { namespace blink {
...@@ -44,8 +44,8 @@ void SVGModelObjectPainter::RecordHitTestData( ...@@ -44,8 +44,8 @@ void SVGModelObjectPainter::RecordHitTestData(
auto rect = auto rect =
LayoutRect(layout_svg_model_object.VisualRectInLocalSVGCoordinates()); LayoutRect(layout_svg_model_object.VisualRectInLocalSVGCoordinates());
HitTestData::RecordHitTestRect(paint_info.context, layout_svg_model_object, HitTestDisplayItem::Record(paint_info.context, layout_svg_model_object,
HitTestRect(rect, touch_action)); HitTestRect(rect, touch_action));
} }
void SVGModelObjectPainter::PaintOutline(const PaintInfo& paint_info) { void SVGModelObjectPainter::PaintOutline(const PaintInfo& paint_info) {
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "third_party/blink/renderer/core/paint/block_painter.h" #include "third_party/blink/renderer/core/paint/block_painter.h"
#include "third_party/blink/renderer/core/paint/paint_info.h" #include "third_party/blink/renderer/core/paint/paint_info.h"
#include "third_party/blink/renderer/core/paint/scoped_svg_paint_state.h" #include "third_party/blink/renderer/core/paint/scoped_svg_paint_state.h"
#include "third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h"
namespace blink { namespace blink {
...@@ -47,8 +48,8 @@ void SVGTextPainter::RecordHitTestData(const PaintInfo& paint_info) { ...@@ -47,8 +48,8 @@ void SVGTextPainter::RecordHitTestData(const PaintInfo& paint_info) {
return; return;
auto rect = LayoutRect(layout_svg_text_.VisualRectInLocalSVGCoordinates()); auto rect = LayoutRect(layout_svg_text_.VisualRectInLocalSVGCoordinates());
HitTestData::RecordHitTestRect(paint_info.context, layout_svg_text_, HitTestDisplayItem::Record(paint_info.context, layout_svg_text_,
HitTestRect(rect, touch_action)); HitTestRect(rect, touch_action));
} }
} // namespace blink } // namespace blink
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "third_party/blink/renderer/core/paint/scoped_paint_state.h" #include "third_party/blink/renderer/core/paint/scoped_paint_state.h"
#include "third_party/blink/renderer/core/paint/table_cell_painter.h" #include "third_party/blink/renderer/core/paint/table_cell_painter.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h" #include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
#include "third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h"
namespace blink { namespace blink {
...@@ -84,8 +85,8 @@ void TableRowPainter::RecordHitTestData(const PaintInfo& paint_info, ...@@ -84,8 +85,8 @@ void TableRowPainter::RecordHitTestData(const PaintInfo& paint_info,
auto rect = layout_table_row_.BorderBoxRect(); auto rect = layout_table_row_.BorderBoxRect();
rect.MoveBy(paint_offset); rect.MoveBy(paint_offset);
HitTestData::RecordHitTestRect(paint_info.context, layout_table_row_, HitTestDisplayItem::Record(paint_info.context, layout_table_row_,
HitTestRect(rect, touch_action)); HitTestRect(rect, touch_action));
} }
void TableRowPainter::PaintBoxDecorationBackground( void TableRowPainter::PaintBoxDecorationBackground(
......
...@@ -265,15 +265,12 @@ TEST_P(ViewPainterTestWithPaintTouchAction, ...@@ -265,15 +265,12 @@ TEST_P(ViewPainterTestWithPaintTouchAction,
0, 2, 0, 2,
PaintChunk::Id(*view->Layer(), kNonScrollingBackgroundChunkType), PaintChunk::Id(*view->Layer(), kNonScrollingBackgroundChunkType),
non_scrolling_properties, view_hit_test_data))); non_scrolling_properties, view_hit_test_data)));
#if 0
// TODO(wangxianzhu): Enable this in crrev.com/c/1325570.
EXPECT_THAT( EXPECT_THAT(
RootPaintController().PaintChunks(), RootPaintController().PaintChunks(),
ElementsAre(IsPaintChunk( ElementsAre(IsPaintChunk(
0, 3, 0, 3,
PaintChunk::Id(*html->Layer(), kNonScrollingBackgroundChunkType), PaintChunk::Id(*html->Layer(), kNonScrollingBackgroundChunkType),
scrolling_properties, scrolling_hit_test_data))); scrolling_properties, scrolling_hit_test_data)));
#endif
} }
} }
......
...@@ -1036,6 +1036,8 @@ jumbo_component("platform") { ...@@ -1036,6 +1036,8 @@ jumbo_component("platform") {
"graphics/paint/geometry_mapper_transform_cache.h", "graphics/paint/geometry_mapper_transform_cache.h",
"graphics/paint/hit_test_data.cc", "graphics/paint/hit_test_data.cc",
"graphics/paint/hit_test_data.h", "graphics/paint/hit_test_data.h",
"graphics/paint/hit_test_display_item.cc",
"graphics/paint/hit_test_display_item.h",
"graphics/paint/paint_artifact.cc", "graphics/paint/paint_artifact.cc",
"graphics/paint/paint_artifact.h", "graphics/paint/paint_artifact.h",
"graphics/paint/paint_canvas.h", "graphics/paint/paint_canvas.h",
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "base/memory/scoped_refptr.h" #include "base/memory/scoped_refptr.h"
#include "cc/layers/layer_collections.h"
#include "third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.h" #include "third_party/blink/renderer/platform/graphics/compositing/property_tree_manager.h"
#include "third_party/blink/renderer/platform/graphics/graphics_layer_client.h" #include "third_party/blink/renderer/platform/graphics/graphics_layer_client.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h" #include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
......
...@@ -34,6 +34,7 @@ ...@@ -34,6 +34,7 @@
#include "cc/input/overscroll_behavior.h" #include "cc/input/overscroll_behavior.h"
#include "cc/input/scroll_snap_data.h" #include "cc/input/scroll_snap_data.h"
#include "cc/layers/content_layer_client.h" #include "cc/layers/content_layer_client.h"
#include "cc/layers/layer.h"
#include "cc/layers/layer_client.h" #include "cc/layers/layer_client.h"
#include "cc/layers/layer_sticky_position_constraint.h" #include "cc/layers/layer_sticky_position_constraint.h"
#include "third_party/blink/renderer/platform/geometry/float_point.h" #include "third_party/blink/renderer/platform/geometry/float_point.h"
...@@ -59,7 +60,6 @@ ...@@ -59,7 +60,6 @@
#include "third_party/skia/include/core/SkRefCnt.h" #include "third_party/skia/include/core/SkRefCnt.h"
namespace cc { namespace cc {
class Layer;
class PictureImageLayer; class PictureImageLayer;
class PictureLayer; class PictureLayer;
} }
......
...@@ -251,6 +251,7 @@ class PLATFORM_EXPORT DisplayItem { ...@@ -251,6 +251,7 @@ class PLATFORM_EXPORT DisplayItem {
DEFINE_PAINT_PHASE_CONVERSION_METHOD(SVGTransform) DEFINE_PAINT_PHASE_CONVERSION_METHOD(SVGTransform)
DEFINE_PAINT_PHASE_CONVERSION_METHOD(SVGEffect) DEFINE_PAINT_PHASE_CONVERSION_METHOD(SVGEffect)
bool IsHitTest() const { return type_ == kHitTest; }
bool IsScrollHitTest() const { return type_ == kScrollHitTest; } bool IsScrollHitTest() const { return type_ == kScrollHitTest; }
bool IsCacheable() const { return is_cacheable_; } bool IsCacheable() const { return is_cacheable_; }
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
#include "third_party/blink/renderer/platform/graphics/contiguous_container.h" #include "third_party/blink/renderer/platform/graphics/contiguous_container.h"
#include "third_party/blink/renderer/platform/graphics/paint/display_item.h" #include "third_party/blink/renderer/platform/graphics/paint/display_item.h"
#include "third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h" #include "third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h"
#include "third_party/blink/renderer/platform/wtf/alignment.h" #include "third_party/blink/renderer/platform/wtf/alignment.h"
#include "third_party/blink/renderer/platform/wtf/assertions.h" #include "third_party/blink/renderer/platform/wtf/assertions.h"
...@@ -20,9 +20,8 @@ struct PaintChunk; ...@@ -20,9 +20,8 @@ struct PaintChunk;
// each derived display item; the ideal value is the least common multiple. // each derived display item; the ideal value is the least common multiple.
// The validity of kDisplayItemAlignment and kMaximumDisplayItemSize are checked // The validity of kDisplayItemAlignment and kMaximumDisplayItemSize are checked
// in PaintController::CreateAndAppend(). // in PaintController::CreateAndAppend().
static const size_t kDisplayItemAlignment = static const size_t kDisplayItemAlignment = WTF_ALIGN_OF(HitTestDisplayItem);
WTF_ALIGN_OF(ForeignLayerDisplayItem); static const size_t kMaximumDisplayItemSize = sizeof(HitTestDisplayItem);
static const size_t kMaximumDisplayItemSize = sizeof(ForeignLayerDisplayItem);
// A container for a list of display items. // A container for a list of display items.
class PLATFORM_EXPORT DisplayItemList class PLATFORM_EXPORT DisplayItemList
......
...@@ -25,18 +25,19 @@ namespace blink { ...@@ -25,18 +25,19 @@ namespace blink {
// PaintRecord, and is in the space of the DisplayItemList. This allows the // PaintRecord, and is in the space of the DisplayItemList. This allows the
// visual_rect to be compared between DrawingDisplayItems, and to give bounds // visual_rect to be compared between DrawingDisplayItems, and to give bounds
// around what the user can actually see from the PaintRecord. // around what the user can actually see from the PaintRecord.
class PLATFORM_EXPORT DrawingDisplayItem final : public DisplayItem { class PLATFORM_EXPORT DrawingDisplayItem : public DisplayItem {
public: public:
DISABLE_CFI_PERF DISABLE_CFI_PERF
DrawingDisplayItem(const DisplayItemClient& client, DrawingDisplayItem(const DisplayItemClient& client,
Type type, Type type,
sk_sp<const PaintRecord> record, sk_sp<const PaintRecord> record,
bool known_to_be_opaque); bool known_to_be_opaque = false,
size_t derived_size = sizeof(DrawingDisplayItem));
void Replay(GraphicsContext&) const override; void Replay(GraphicsContext&) const final;
void AppendToDisplayItemList(const FloatSize& visual_rect_offset, void AppendToDisplayItemList(const FloatSize& visual_rect_offset,
cc::DisplayItemList&) const override; cc::DisplayItemList&) const final;
bool DrawsContent() const override; bool DrawsContent() const final;
const sk_sp<const PaintRecord>& GetPaintRecord() const { return record_; } const sk_sp<const PaintRecord>& GetPaintRecord() const { return record_; }
...@@ -45,13 +46,14 @@ class PLATFORM_EXPORT DrawingDisplayItem final : public DisplayItem { ...@@ -45,13 +46,14 @@ class PLATFORM_EXPORT DrawingDisplayItem final : public DisplayItem {
return known_to_be_opaque_; return known_to_be_opaque_;
} }
bool Equals(const DisplayItem& other) const final; bool Equals(const DisplayItem& other) const override;
private: protected:
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
void PropertiesAsJSON(JSONObject&) const override; void PropertiesAsJSON(JSONObject&) const override;
#endif #endif
private:
sk_sp<const PaintRecord> record_; sk_sp<const PaintRecord> record_;
// True if there are no transparent areas. Only used for SlimmingPaintV2. // True if there are no transparent areas. Only used for SlimmingPaintV2.
...@@ -63,8 +65,9 @@ DISABLE_CFI_PERF ...@@ -63,8 +65,9 @@ DISABLE_CFI_PERF
inline DrawingDisplayItem::DrawingDisplayItem(const DisplayItemClient& client, inline DrawingDisplayItem::DrawingDisplayItem(const DisplayItemClient& client,
Type type, Type type,
sk_sp<const PaintRecord> record, sk_sp<const PaintRecord> record,
bool known_to_be_opaque = false) bool known_to_be_opaque,
: DisplayItem(client, type, sizeof(*this)), size_t derived_size)
: DisplayItem(client, type, derived_size),
record_(record && record->size() ? std::move(record) : nullptr), record_(record && record->size() ? std::move(record) : nullptr),
known_to_be_opaque_(known_to_be_opaque) { known_to_be_opaque_(known_to_be_opaque) {
DCHECK(IsDrawingType(type)); DCHECK(IsDrawingType(type));
......
...@@ -4,36 +4,11 @@ ...@@ -4,36 +4,11 @@
#include "third_party/blink/renderer/platform/graphics/paint/hit_test_data.h" #include "third_party/blink/renderer/platform/graphics/paint/hit_test_data.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
#include "third_party/blink/renderer/platform/wtf/text/string_builder.h" #include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink { namespace blink {
void HitTestData::RecordHitTestRect(GraphicsContext& context,
const DisplayItemClient& client,
const HitTestRect& action) {
DCHECK(RuntimeEnabledFeatures::PaintTouchActionRectsEnabled());
PaintController& paint_controller = context.GetPaintController();
if (paint_controller.DisplayItemConstructionIsDisabled())
return;
if (!paint_controller.UseCachedDrawingIfPossible(client,
DisplayItem::kHitTest)) {
// A display item must be created to ensure a paint chunk exists. For
// example, without this, an empty div with a transform will incorrectly use
// the parent paint chunk instead of creating a new one.
paint_controller.CreateAndAppend<DrawingDisplayItem>(
client, DisplayItem::kHitTest, nullptr, false);
}
auto& chunk = paint_controller.CurrentPaintChunk();
chunk.EnsureHitTestData().touch_action_rects.push_back(action);
}
static String HitTestRectsAsString(HitTestRects rects) { static String HitTestRectsAsString(HitTestRects rects) {
StringBuilder sb; StringBuilder sb;
sb.Append("["); sb.Append("[");
......
...@@ -5,15 +5,11 @@ ...@@ -5,15 +5,11 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_HIT_TEST_DATA_H_ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_HIT_TEST_DATA_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_HIT_TEST_DATA_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_HIT_TEST_DATA_H_
#include "third_party/blink/renderer/platform/geometry/region.h"
#include "third_party/blink/renderer/platform/graphics/hit_test_rect.h" #include "third_party/blink/renderer/platform/graphics/hit_test_rect.h"
#include "third_party/blink/renderer/platform/platform_export.h" #include "third_party/blink/renderer/platform/platform_export.h"
namespace blink { namespace blink {
class DisplayItemClient;
class GraphicsContext;
using HitTestRects = Vector<HitTestRect>; using HitTestRects = Vector<HitTestRect>;
struct PLATFORM_EXPORT HitTestData { struct PLATFORM_EXPORT HitTestData {
...@@ -33,14 +29,12 @@ struct PLATFORM_EXPORT HitTestData { ...@@ -33,14 +29,12 @@ struct PLATFORM_EXPORT HitTestData {
non_fast_scrollable_region == rhs.non_fast_scrollable_region; non_fast_scrollable_region == rhs.non_fast_scrollable_region;
} }
bool operator!=(const HitTestData& rhs) const { return !(*this == rhs); } void Append(const HitTestRect& rect) {
// TODO(836905): Support other types of hit testing.
touch_action_rects.push_back(rect);
}
// Records a display item for hit testing to ensure a paint chunk exists and bool operator!=(const HitTestData& rhs) const { return !(*this == rhs); }
// is sized to include hit test rects, then adds the hit test rect to
// |HitTestData.touch_action_rects|.
static void RecordHitTestRect(GraphicsContext&,
const DisplayItemClient&,
const HitTestRect&);
String ToString() const; String ToString() const;
}; };
......
// Copyright 2018 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 "third_party/blink/renderer/platform/graphics/paint/hit_test_display_item.h"
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
#include "third_party/blink/renderer/platform/graphics/paint/paint_controller.h"
namespace blink {
void HitTestDisplayItem::Record(GraphicsContext& context,
const DisplayItemClient& client,
const HitTestRect& hit_test_rect) {
DCHECK(RuntimeEnabledFeatures::PaintTouchActionRectsEnabled());
auto& paint_controller = context.GetPaintController();
if (paint_controller.DisplayItemConstructionIsDisabled())
return;
if (paint_controller.UseCachedDrawingIfPossible(client,
DisplayItem::kHitTest))
return;
paint_controller.CreateAndAppend<HitTestDisplayItem>(client, hit_test_rect);
}
#if DCHECK_IS_ON()
void HitTestDisplayItem::PropertiesAsJSON(JSONObject& json) const {
DrawingDisplayItem::PropertiesAsJSON(json);
json.SetString("hitTestRect", hit_test_rect_.ToString());
}
#endif
bool HitTestDisplayItem::Equals(const DisplayItem& other) const {
return DrawingDisplayItem::Equals(other) &&
hit_test_rect_ ==
static_cast<const HitTestDisplayItem&>(other).hit_test_rect_;
}
} // namespace blink
// Copyright 2018 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_HIT_TEST_DISPLAY_ITEM_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_HIT_TEST_DISPLAY_ITEM_H_
#include "third_party/blink/renderer/platform/graphics/paint/drawing_display_item.h"
#include "third_party/blink/renderer/platform/graphics/hit_test_rect.h"
namespace blink {
// A special DrawingDisplayItem containing hit test data.
class PLATFORM_EXPORT HitTestDisplayItem final : public DrawingDisplayItem {
public:
HitTestDisplayItem(const DisplayItemClient& client,
const HitTestRect& hit_test_rect)
: DrawingDisplayItem(client, kHitTest, nullptr, false, sizeof(*this)),
hit_test_rect_(hit_test_rect) {
DCHECK(RuntimeEnabledFeatures::PaintTouchActionRectsEnabled());
}
const HitTestRect& GetHitTestRect() const { return hit_test_rect_; }
static void Record(GraphicsContext&,
const DisplayItemClient&,
const HitTestRect&);
bool Equals(const DisplayItem& other) const final;
private:
#if DCHECK_IS_ON()
void PropertiesAsJSON(JSONObject&) const override;
#endif
HitTestRect hit_test_rect_;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_HIT_TEST_DISPLAY_ITEM_H_
...@@ -17,20 +17,19 @@ namespace blink { ...@@ -17,20 +17,19 @@ namespace blink {
namespace { namespace {
void ComputeChunkBoundsAndOpaqueness(const DisplayItemList& display_items, void ComputeChunkDerivedData(const DisplayItemList& display_items,
Vector<PaintChunk>& paint_chunks) { PaintChunk& chunk) {
for (PaintChunk& chunk : paint_chunks) { // This happens in tests testing paint chunks without display items.
// This happens in tests testing paint chunks without display items. if (!chunk.size())
if (!chunk.size()) return;
continue;
SkRegion known_to_be_opaque_region;
FloatRect bounds; for (const DisplayItem& item : display_items.ItemsInPaintChunk(chunk)) {
SkRegion known_to_be_opaque_region; chunk.bounds.Unite(item.VisualRect());
for (const DisplayItem& item : display_items.ItemsInPaintChunk(chunk)) { chunk.outset_for_raster_effects = std::max(chunk.outset_for_raster_effects,
bounds.Unite(item.VisualRect()); item.OutsetForRasterEffects());
if (!RuntimeEnabledFeatures::SlimmingPaintV2Enabled() ||
!item.IsDrawing()) if (RuntimeEnabledFeatures::SlimmingPaintV2Enabled() && item.IsDrawing()) {
continue;
const auto& drawing = static_cast<const DrawingDisplayItem&>(item); const auto& drawing = static_cast<const DrawingDisplayItem&>(item);
if (drawing.GetPaintRecord() && drawing.KnownToBeOpaque()) { if (drawing.GetPaintRecord() && drawing.KnownToBeOpaque()) {
known_to_be_opaque_region.op( known_to_be_opaque_region.op(
...@@ -38,12 +37,30 @@ void ComputeChunkBoundsAndOpaqueness(const DisplayItemList& display_items, ...@@ -38,12 +37,30 @@ void ComputeChunkBoundsAndOpaqueness(const DisplayItemList& display_items,
SkRegion::kUnion_Op); SkRegion::kUnion_Op);
} }
} }
chunk.bounds = bounds;
if (known_to_be_opaque_region.contains(EnclosingIntRect(bounds))) if (RuntimeEnabledFeatures::PaintTouchActionRectsEnabled() &&
chunk.known_to_be_opaque = true; item.IsHitTest()) {
const auto& hit_test = static_cast<const HitTestDisplayItem&>(item);
if (!chunk.hit_test_data)
chunk.hit_test_data = std::make_unique<HitTestData>();
chunk.hit_test_data->Append(hit_test.GetHitTestRect());
}
} }
if (known_to_be_opaque_region.contains(EnclosingIntRect(chunk.bounds)))
chunk.known_to_be_opaque = true;
} }
// For PaintArtifact::AppendDebugDrawing().
class DebugDrawingClient final : public DisplayItemClient {
public:
DebugDrawingClient() { Invalidate(PaintInvalidationReason::kUncacheable); }
String DebugName() const final { return "DebugDrawing"; }
LayoutRect VisualRect() const final {
return LayoutRect(LayoutRect::InfiniteIntRect());
}
};
} // namespace } // namespace
PaintArtifact::PaintArtifact() : display_item_list_(0) {} PaintArtifact::PaintArtifact() : display_item_list_(0) {}
...@@ -51,7 +68,8 @@ PaintArtifact::PaintArtifact() : display_item_list_(0) {} ...@@ -51,7 +68,8 @@ PaintArtifact::PaintArtifact() : display_item_list_(0) {}
PaintArtifact::PaintArtifact(DisplayItemList display_items, PaintArtifact::PaintArtifact(DisplayItemList display_items,
Vector<PaintChunk> chunks) Vector<PaintChunk> chunks)
: display_item_list_(std::move(display_items)), chunks_(std::move(chunks)) { : display_item_list_(std::move(display_items)), chunks_(std::move(chunks)) {
ComputeChunkBoundsAndOpaqueness(display_item_list_, chunks_); for (auto& chunk : chunks_)
ComputeChunkDerivedData(display_item_list_, chunk);
} }
PaintArtifact::~PaintArtifact() = default; PaintArtifact::~PaintArtifact() = default;
...@@ -76,6 +94,22 @@ size_t PaintArtifact::ApproximateUnsharedMemoryUsage() const { ...@@ -76,6 +94,22 @@ size_t PaintArtifact::ApproximateUnsharedMemoryUsage() const {
return total_size; return total_size;
} }
void PaintArtifact::AppendDebugDrawing(
sk_sp<const PaintRecord> record,
const PropertyTreeState& property_tree_state) {
DEFINE_STATIC_LOCAL(DebugDrawingClient, debug_drawing_client, ());
DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV2Enabled());
auto& display_item =
display_item_list_.AllocateAndConstruct<DrawingDisplayItem>(
debug_drawing_client, DisplayItem::kDebugDrawing, std::move(record));
// Create a PaintChunk for the debug drawing.
chunks_.emplace_back(display_item_list_.size() - 1, display_item_list_.size(),
display_item.GetId(), property_tree_state);
ComputeChunkDerivedData(display_item_list_, chunks_.back());
}
void PaintArtifact::Replay(GraphicsContext& graphics_context, void PaintArtifact::Replay(GraphicsContext& graphics_context,
const PropertyTreeState& replay_state, const PropertyTreeState& replay_state,
const IntPoint& offset) const { const IntPoint& offset) const {
......
...@@ -67,6 +67,8 @@ class PLATFORM_EXPORT PaintArtifact final : public RefCounted<PaintArtifact> { ...@@ -67,6 +67,8 @@ class PLATFORM_EXPORT PaintArtifact final : public RefCounted<PaintArtifact> {
// shared with the embedder after copying to cc::DisplayItemList. // shared with the embedder after copying to cc::DisplayItemList.
size_t ApproximateUnsharedMemoryUsage() const; size_t ApproximateUnsharedMemoryUsage() const;
void AppendDebugDrawing(sk_sp<const PaintRecord>, const PropertyTreeState&);
// Draws the paint artifact to a GraphicsContext, into the ancestor state // Draws the paint artifact to a GraphicsContext, into the ancestor state
// given by |replay_state|. // given by |replay_state|.
void Replay(GraphicsContext&, void Replay(GraphicsContext&,
......
...@@ -36,11 +36,8 @@ struct PLATFORM_EXPORT PaintChunk { ...@@ -36,11 +36,8 @@ struct PLATFORM_EXPORT PaintChunk {
end_index(end), end_index(end),
id(id), id(id),
properties(props), properties(props),
outset_for_raster_effects(0),
known_to_be_opaque(false),
is_cacheable(id.client.IsCacheable()), is_cacheable(id.client.IsCacheable()),
client_is_just_created(id.client.IsJustCreated()), client_is_just_created(id.client.IsJustCreated()) {}
hit_test_data(nullptr) {}
size_t size() const { size_t size() const {
DCHECK_GE(end_index, begin_index); DCHECK_GE(end_index, begin_index);
...@@ -66,14 +63,6 @@ struct PLATFORM_EXPORT PaintChunk { ...@@ -66,14 +63,6 @@ struct PLATFORM_EXPORT PaintChunk {
return !client_is_just_created; return !client_is_just_created;
} }
HitTestData& EnsureHitTestData() {
if (!hit_test_data)
hit_test_data = std::make_unique<HitTestData>();
return *hit_test_data.get();
}
HitTestData* GetHitTestData() const { return hit_test_data.get(); }
size_t MemoryUsageInBytes() const { size_t MemoryUsageInBytes() const {
size_t total_size = sizeof(*this); size_t total_size = sizeof(*this);
if (hit_test_data) { if (hit_test_data) {
...@@ -84,6 +73,8 @@ struct PLATFORM_EXPORT PaintChunk { ...@@ -84,6 +73,8 @@ struct PLATFORM_EXPORT PaintChunk {
return total_size; return total_size;
} }
String ToString() const;
// Index of the first drawing in this chunk. // Index of the first drawing in this chunk.
size_t begin_index; size_t begin_index;
...@@ -99,6 +90,12 @@ struct PLATFORM_EXPORT PaintChunk { ...@@ -99,6 +90,12 @@ struct PLATFORM_EXPORT PaintChunk {
// The paint properties which apply to this chunk. // The paint properties which apply to this chunk.
RefCountedPropertyTreeState properties; RefCountedPropertyTreeState properties;
// The following fields are not initialized when the chunk is created because
// they depend on the display items in this chunk. They are updated by the
// constructor of PaintArtifact.
std::unique_ptr<HitTestData> hit_test_data;
// The total bounds of this paint chunk's contents, in the coordinate space of // The total bounds of this paint chunk's contents, in the coordinate space of
// the containing transform node. // the containing transform node.
FloatRect bounds; FloatRect bounds;
...@@ -106,19 +103,15 @@ struct PLATFORM_EXPORT PaintChunk { ...@@ -106,19 +103,15 @@ struct PLATFORM_EXPORT PaintChunk {
// Some raster effects can exceed |bounds| in the rasterization space. This // Some raster effects can exceed |bounds| in the rasterization space. This
// is the maximum DisplayItemClient::VisualRectOutsetForRasterEffects() of // is the maximum DisplayItemClient::VisualRectOutsetForRasterEffects() of
// all clients of items in this chunk. // all clients of items in this chunk.
float outset_for_raster_effects; float outset_for_raster_effects = 0;
// True if the bounds are filled entirely with opaque contents. // True if the bounds are filled entirely with opaque contents.
bool known_to_be_opaque : 1; bool known_to_be_opaque = false;
bool is_cacheable : 1;
bool client_is_just_created : 1;
String ToString() const; // End of derived data.
// The following fields are put here to avoid memory gap.
private: bool is_cacheable;
std::unique_ptr<HitTestData> hit_test_data; bool client_is_just_created;
}; };
inline bool ChunkLessThanIndex(const PaintChunk& chunk, size_t index) { inline bool ChunkLessThanIndex(const PaintChunk& chunk, size_t index) {
......
...@@ -214,25 +214,15 @@ void PaintController::ProcessNewItem(DisplayItem& display_item) { ...@@ -214,25 +214,15 @@ void PaintController::ProcessNewItem(DisplayItem& display_item) {
if (IsSkippingCache() && usage_ == kMultiplePaints) if (IsSkippingCache() && usage_ == kMultiplePaints)
display_item.Client().Invalidate(PaintInvalidationReason::kUncacheable); display_item.Client().Invalidate(PaintInvalidationReason::kUncacheable);
#if DCHECK_IS_ON() bool chunk_added = new_paint_chunks_.IncrementDisplayItemIndex(display_item);
bool chunk_added =
#endif
new_paint_chunks_.IncrementDisplayItemIndex(display_item);
auto& last_chunk = new_paint_chunks_.LastChunk();
#if DCHECK_IS_ON() #if DCHECK_IS_ON()
if (chunk_added && last_chunk.is_cacheable) { if (chunk_added && CurrentPaintChunk().is_cacheable) {
AddToIndicesByClientMap(last_chunk.id.client, AddToIndicesByClientMap(CurrentPaintChunk().id.client,
new_paint_chunks_.LastChunkIndex(), new_paint_chunks_.LastChunkIndex(),
new_paint_chunk_indices_by_client_); new_paint_chunk_indices_by_client_);
} }
#endif
last_chunk.outset_for_raster_effects =
std::max(last_chunk.outset_for_raster_effects,
display_item.OutsetForRasterEffects());
#if DCHECK_IS_ON()
if (usage_ == kMultiplePaints && !IsSkippingCache()) { if (usage_ == kMultiplePaints && !IsSkippingCache()) {
size_t index = FindMatchingItemFromIndex( size_t index = FindMatchingItemFromIndex(
display_item.GetId(), new_display_item_indices_by_client_, display_item.GetId(), new_display_item_indices_by_client_,
...@@ -249,7 +239,9 @@ void PaintController::ProcessNewItem(DisplayItem& display_item) { ...@@ -249,7 +239,9 @@ void PaintController::ProcessNewItem(DisplayItem& display_item) {
new_display_item_list_.size() - 1, new_display_item_list_.size() - 1,
new_display_item_indices_by_client_); new_display_item_indices_by_client_);
} }
#endif // DCHECK_IS_ON() #else // DCHECK_IS_ON()
std::ignore = chunk_added;
#endif
if (usage_ == kMultiplePaints && if (usage_ == kMultiplePaints &&
RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled())
...@@ -457,9 +449,8 @@ void PaintController::CopyCachedSubsequence(size_t begin_index, ...@@ -457,9 +449,8 @@ void PaintController::CopyCachedSubsequence(size_t begin_index,
#endif #endif
ProcessNewItem(MoveItemFromCurrentListToNewList(current_index)); ProcessNewItem(MoveItemFromCurrentListToNewList(current_index));
DCHECK((!new_paint_chunks_.LastChunk().is_cacheable && DCHECK((!CurrentPaintChunk().is_cacheable && !cached_chunk->is_cacheable) ||
!cached_chunk->is_cacheable) || CurrentPaintChunk().Matches(*cached_chunk));
new_paint_chunks_.LastChunk().Matches(*cached_chunk));
} }
if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) { if (RuntimeEnabledFeatures::PaintUnderInvalidationCheckingEnabled()) {
...@@ -600,35 +591,12 @@ size_t PaintController::ApproximateUnsharedMemoryUsage() const { ...@@ -600,35 +591,12 @@ size_t PaintController::ApproximateUnsharedMemoryUsage() const {
return memory_usage; return memory_usage;
} }
namespace {
class DebugDrawingClient final : public DisplayItemClient {
public:
DebugDrawingClient() { Invalidate(PaintInvalidationReason::kUncacheable); }
String DebugName() const final { return "DebugDrawing"; }
LayoutRect VisualRect() const final {
return LayoutRect(LayoutRect::InfiniteIntRect());
}
};
} // anonymous namespace
void PaintController::AppendDebugDrawingAfterCommit( void PaintController::AppendDebugDrawingAfterCommit(
sk_sp<const PaintRecord> record, sk_sp<const PaintRecord> record,
const PropertyTreeState& property_tree_state) { const PropertyTreeState& property_tree_state) {
DEFINE_STATIC_LOCAL(DebugDrawingClient, debug_drawing_client, ());
DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV2Enabled()); DCHECK(!RuntimeEnabledFeatures::SlimmingPaintV2Enabled());
DCHECK(new_display_item_list_.IsEmpty()); DCHECK(new_display_item_list_.IsEmpty());
auto& display_item_list = current_paint_artifact_->GetDisplayItemList(); current_paint_artifact_->AppendDebugDrawing(record, property_tree_state);
auto& display_item =
display_item_list.AllocateAndConstruct<DrawingDisplayItem>(
debug_drawing_client, DisplayItem::kDebugDrawing, std::move(record));
// Create a PaintChunk for the debug drawing.
current_paint_artifact_->PaintChunks().emplace_back(
display_item_list.size() - 1, display_item_list.size(),
display_item.GetId(), property_tree_state);
} }
void PaintController::ShowUnderInvalidationError( void PaintController::ShowUnderInvalidationError(
......
...@@ -119,9 +119,9 @@ inline bool CheckChunk(const PaintChunk& chunk, ...@@ -119,9 +119,9 @@ inline bool CheckChunk(const PaintChunk& chunk,
const HitTestData* hit_test_data = nullptr) { const HitTestData* hit_test_data = nullptr) {
return chunk.begin_index == begin && chunk.end_index == end && return chunk.begin_index == begin && chunk.end_index == end &&
chunk.id == id && chunk.properties == properties && chunk.id == id && chunk.properties == properties &&
((!chunk.GetHitTestData() && !hit_test_data) || ((!chunk.hit_test_data && !hit_test_data) ||
(chunk.GetHitTestData() && hit_test_data && (chunk.hit_test_data && hit_test_data &&
*chunk.GetHitTestData() == *hit_test_data)); *chunk.hit_test_data == *hit_test_data));
} }
MATCHER_P4(IsPaintChunk, begin, end, id, properties, "") { MATCHER_P4(IsPaintChunk, begin, end, id, properties, "") {
return CheckChunk(arg, begin, end, id, properties); return CheckChunk(arg, begin, end, id, properties);
......
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