Skip to content

Commit

Permalink
cc: Switch display item list's rtree to store op offsets.
Browse files Browse the repository at this point in the history
This patch switches the display item list's rtree to store individual
op offsets, instead of indices. In order to accomplish that, the patch
does the following:

1. Introduces push functionality on display item lists so that
   it can record op offsets before forwarding the args to the
   buffer.
2. Hides the paint_op_buffer from the display item lists interface,
   so that users have to use the push on the DIL itself.
3. Changes the POB::Iterator to use offsets instead of indices.

Most of the patch are changes caused by 1 and 2 above.

R=enne@chromium.org, danakj@chromium.org

Cq-Include-Trybots: master.tryserver.blink:linux_trusty_blink_rel;master.tryserver.chromium.linux:linux_layout_tests_slimming_paint_v2
Change-Id: I9ca04d944edac59de77fa12b642fc08df9c7b47b
Reviewed-on: https://chromium-review.googlesource.com/552837
Commit-Queue: Vladimir Levin <vmpstr@chromium.org>
Reviewed-by: Chris Harrelson <chrishtr@chromium.org>
Reviewed-by: Sadrul Chowdhury <sadrul@chromium.org>
Reviewed-by: danakj <danakj@chromium.org>
Reviewed-by: enne <enne@chromium.org>
Cr-Commit-Position: refs/heads/master@{#489147}
  • Loading branch information
vmpstr authored and Commit Bot committed Jul 24, 2017
1 parent cf97ed5 commit 53a4abf
Show file tree
Hide file tree
Showing 34 changed files with 900 additions and 641 deletions.
8 changes: 5 additions & 3 deletions cc/base/rtree.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,11 @@ class RTree {
template <typename Container>
void Build(const Container& items);

// Build helper that takes a container and a function used to get gfx::Rect
// from each item. That is, "bounds_getter(items[i]);" should return a
// gfx::Rect representing the bounds of items[i] for each i.
// Build helper that takes a container, a function used to get gfx::Rect
// from each item, and a function used to get the payload for each item. That
// is, "bounds_getter(items, i);" should return a gfx::Rect representing the
// bounds of ith item, and "payload_getter(items, i);" should return the
// payload (aka T) of ith item.
template <typename Container, typename BoundsFunctor, typename PayloadFunctor>
void Build(const Container& items,
const BoundsFunctor& bounds_getter,
Expand Down
77 changes: 40 additions & 37 deletions cc/blink/web_display_item_list_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -40,25 +40,26 @@ void WebDisplayItemListImpl::AppendDrawingItem(
const blink::WebRect& visual_rect,
sk_sp<const cc::PaintOpBuffer> record,
const blink::WebRect& record_bounds) {
cc::PaintOpBuffer* buffer = display_item_list_->StartPaint();
buffer->push<cc::DrawRecordOp>(std::move(record));
display_item_list_->StartPaint();
display_item_list_->push<cc::DrawRecordOp>(std::move(record));
display_item_list_->EndPaintOfUnpaired(visual_rect);
}

void WebDisplayItemListImpl::AppendClipItem(
const blink::WebRect& clip_rect,
const blink::WebVector<SkRRect>& rounded_clip_rects) {
bool antialias = true;
cc::PaintOpBuffer* buffer = display_item_list_->StartPaint();
buffer->push<cc::SaveOp>();
buffer->push<cc::ClipRectOp>(gfx::RectToSkRect(clip_rect),
SkClipOp::kIntersect, antialias);
display_item_list_->StartPaint();
display_item_list_->push<cc::SaveOp>();
display_item_list_->push<cc::ClipRectOp>(gfx::RectToSkRect(clip_rect),
SkClipOp::kIntersect, antialias);
for (const SkRRect& rrect : rounded_clip_rects) {
if (rrect.isRect()) {
buffer->push<cc::ClipRectOp>(rrect.rect(), SkClipOp::kIntersect,
antialias);
display_item_list_->push<cc::ClipRectOp>(rrect.rect(),
SkClipOp::kIntersect, antialias);
} else {
buffer->push<cc::ClipRRectOp>(rrect, SkClipOp::kIntersect, antialias);
display_item_list_->push<cc::ClipRRectOp>(rrect, SkClipOp::kIntersect,
antialias);
}
}
display_item_list_->EndPaintOfPairedBegin();
Expand All @@ -70,9 +71,10 @@ void WebDisplayItemListImpl::AppendEndClipItem() {

void WebDisplayItemListImpl::AppendClipPathItem(const SkPath& clip_path,
bool antialias) {
cc::PaintOpBuffer* buffer = display_item_list_->StartPaint();
buffer->push<cc::SaveOp>();
buffer->push<cc::ClipPathOp>(clip_path, SkClipOp::kIntersect, antialias);
display_item_list_->StartPaint();
display_item_list_->push<cc::SaveOp>();
display_item_list_->push<cc::ClipPathOp>(clip_path, SkClipOp::kIntersect,
antialias);
display_item_list_->EndPaintOfPairedBegin();
}

Expand All @@ -83,10 +85,10 @@ void WebDisplayItemListImpl::AppendEndClipPathItem() {
void WebDisplayItemListImpl::AppendFloatClipItem(
const blink::WebFloatRect& clip_rect) {
bool antialias = false;
cc::PaintOpBuffer* buffer = display_item_list_->StartPaint();
buffer->push<cc::SaveOp>();
buffer->push<cc::ClipRectOp>(gfx::RectFToSkRect(clip_rect),
SkClipOp::kIntersect, antialias);
display_item_list_->StartPaint();
display_item_list_->push<cc::SaveOp>();
display_item_list_->push<cc::ClipRectOp>(gfx::RectFToSkRect(clip_rect),
SkClipOp::kIntersect, antialias);
display_item_list_->EndPaintOfPairedBegin();
}

Expand All @@ -95,10 +97,10 @@ void WebDisplayItemListImpl::AppendEndFloatClipItem() {
}

void WebDisplayItemListImpl::AppendTransformItem(const SkMatrix44& matrix) {
cc::PaintOpBuffer* buffer = display_item_list_->StartPaint();
buffer->push<cc::SaveOp>();
display_item_list_->StartPaint();
display_item_list_->push<cc::SaveOp>();
if (!matrix.isIdentity())
buffer->push<cc::ConcatOp>(static_cast<SkMatrix>(matrix));
display_item_list_->push<cc::ConcatOp>(static_cast<SkMatrix>(matrix));
display_item_list_->EndPaintOfPairedBegin();
}

Expand All @@ -119,8 +121,8 @@ void WebDisplayItemListImpl::AppendCompositingItem(
auto alpha = static_cast<uint8_t>(gfx::ToFlooredInt(255 * opacity));

if (xfermode == SkBlendMode::kSrcOver && !color_filter) {
cc::PaintOpBuffer* buffer = display_item_list_->StartPaint();
buffer->push<cc::SaveLayerAlphaOp>(bounds, alpha, false);
display_item_list_->StartPaint();
display_item_list_->push<cc::SaveLayerAlphaOp>(bounds, alpha, false);
display_item_list_->EndPaintOfPairedBegin();
return;
}
Expand All @@ -130,8 +132,8 @@ void WebDisplayItemListImpl::AppendCompositingItem(
flags.setAlpha(alpha);
flags.setColorFilter(sk_ref_sp(color_filter));

cc::PaintOpBuffer* buffer = display_item_list_->StartPaint();
buffer->push<cc::SaveLayerOp>(bounds, &flags);
display_item_list_->StartPaint();
display_item_list_->push<cc::SaveLayerOp>(bounds, &flags);
display_item_list_->EndPaintOfPairedBegin();
}

Expand All @@ -143,41 +145,42 @@ void WebDisplayItemListImpl::AppendFilterItem(
const cc::FilterOperations& filters,
const blink::WebFloatRect& filter_bounds,
const blink::WebFloatPoint& origin) {
cc::PaintOpBuffer* buffer = display_item_list_->StartPaint();
display_item_list_->StartPaint();

// TODO(danakj): Skip the save+translate+restore if the origin is 0,0. This
// should be easier to do when this code is part of the blink DisplayItem
// which can keep related state.
buffer->push<cc::SaveOp>();
buffer->push<cc::TranslateOp>(origin.x, origin.y);
display_item_list_->push<cc::SaveOp>();
display_item_list_->push<cc::TranslateOp>(origin.x, origin.y);

cc::PaintFlags flags;
flags.setImageFilter(cc::RenderSurfaceFilters::BuildImageFilter(
filters, gfx::SizeF(filter_bounds.width, filter_bounds.height)));

SkRect layer_bounds = gfx::RectFToSkRect(filter_bounds);
layer_bounds.offset(-origin.x, -origin.y);
buffer->push<cc::SaveLayerOp>(&layer_bounds, &flags);
buffer->push<cc::TranslateOp>(-origin.x, -origin.y);
display_item_list_->push<cc::SaveLayerOp>(&layer_bounds, &flags);
display_item_list_->push<cc::TranslateOp>(-origin.x, -origin.y);

display_item_list_->EndPaintOfPairedBegin(
gfx::ToEnclosingRect(filter_bounds));
}

void WebDisplayItemListImpl::AppendEndFilterItem() {
cc::PaintOpBuffer* buffer = display_item_list_->StartPaint();
buffer->push<cc::RestoreOp>(); // For SaveLayerOp.
buffer->push<cc::RestoreOp>(); // For SaveOp.
display_item_list_->StartPaint();
display_item_list_->push<cc::RestoreOp>(); // For SaveLayerOp.
display_item_list_->push<cc::RestoreOp>(); // For SaveOp.
display_item_list_->EndPaintOfPairedEnd();
}

void WebDisplayItemListImpl::AppendScrollItem(
const blink::WebSize& scroll_offset,
ScrollContainerId) {
cc::PaintOpBuffer* buffer = display_item_list_->StartPaint();
buffer->push<cc::SaveOp>();
buffer->push<cc::TranslateOp>(static_cast<float>(-scroll_offset.width),
static_cast<float>(-scroll_offset.height));
display_item_list_->StartPaint();
display_item_list_->push<cc::SaveOp>();
display_item_list_->push<cc::TranslateOp>(
static_cast<float>(-scroll_offset.width),
static_cast<float>(-scroll_offset.height));
display_item_list_->EndPaintOfPairedBegin();
}

Expand All @@ -186,8 +189,8 @@ void WebDisplayItemListImpl::AppendEndScrollItem() {
}

void WebDisplayItemListImpl::AppendRestore() {
cc::PaintOpBuffer* buffer = display_item_list_->StartPaint();
buffer->push<cc::RestoreOp>();
display_item_list_->StartPaint();
display_item_list_->push<cc::RestoreOp>();
display_item_list_->EndPaintOfPairedEnd();
}

Expand Down
11 changes: 6 additions & 5 deletions cc/layers/picture_image_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -68,19 +68,20 @@ scoped_refptr<DisplayItemList> PictureImageLayer::PaintContentsToDisplayList(

auto display_list = base::MakeRefCounted<DisplayItemList>();

PaintOpBuffer* buffer = display_list->StartPaint();
display_list->StartPaint();
if (has_scale) {
buffer->push<SaveOp>();
buffer->push<ScaleOp>(content_to_layer_scale_x, content_to_layer_scale_y);
display_list->push<SaveOp>();
display_list->push<ScaleOp>(content_to_layer_scale_x,
content_to_layer_scale_y);
}

// Because Android WebView resourceless software draw mode rasters directly
// to the root canvas, this draw must use the SkBlendMode::kSrcOver so that
// transparent images blend correctly.
buffer->push<DrawImageOp>(image_, 0.f, 0.f, nullptr);
display_list->push<DrawImageOp>(image_, 0.f, 0.f, nullptr);

if (has_scale)
buffer->push<RestoreOp>();
display_list->push<RestoreOp>();
display_list->EndPaintOfUnpaired(PaintableRegion());
display_list->Finalize();
return display_list;
Expand Down
31 changes: 16 additions & 15 deletions cc/paint/discardable_image_map_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -380,11 +380,11 @@ TEST_F(DiscardableImageMapTest, PaintDestroyedWhileImageIsDrawn) {

scoped_refptr<DisplayItemList> display_list = new DisplayItemList;
PaintFlags paint;
PaintOpBuffer* buffer = display_list->StartPaint();
display_list->StartPaint();
SkRect visible_sk_rect(gfx::RectToSkRect(visible_rect));
buffer->push<SaveLayerOp>(&visible_sk_rect, &paint);
buffer->push<DrawRecordOp>(std::move(record));
buffer->push<RestoreOp>();
display_list->push<SaveLayerOp>(&visible_sk_rect, &paint);
display_list->push<DrawRecordOp>(std::move(record));
display_list->push<RestoreOp>();
display_list->EndPaintOfUnpaired(visible_rect);
display_list->Finalize();

Expand All @@ -405,11 +405,11 @@ TEST_F(DiscardableImageMapTest, NullPaintOnSaveLayer) {
sk_sp<PaintRecord> record = CreateRecording(discardable_image, visible_rect);

scoped_refptr<DisplayItemList> display_list = new DisplayItemList;
PaintOpBuffer* buffer = display_list->StartPaint();
display_list->StartPaint();
SkRect visible_sk_rect(gfx::RectToSkRect(visible_rect));
buffer->push<SaveLayerOp>(&visible_sk_rect, nullptr);
buffer->push<DrawRecordOp>(std::move(record));
buffer->push<RestoreOp>();
display_list->push<SaveLayerOp>(&visible_sk_rect, nullptr);
display_list->push<DrawRecordOp>(std::move(record));
display_list->push<RestoreOp>();
display_list->EndPaintOfUnpaired(visible_rect);
display_list->Finalize();

Expand Down Expand Up @@ -633,10 +633,10 @@ TEST_F(DiscardableImageMapTest, ClipsImageRects) {

scoped_refptr<DisplayItemList> display_list = new DisplayItemList;

PaintOpBuffer* buffer = display_list->StartPaint();
buffer->push<ClipRectOp>(gfx::RectToSkRect(gfx::Rect(250, 250)),
SkClipOp::kIntersect, false);
buffer->push<DrawRecordOp>(std::move(record));
display_list->StartPaint();
display_list->push<ClipRectOp>(gfx::RectToSkRect(gfx::Rect(250, 250)),
SkClipOp::kIntersect, false);
display_list->push<DrawRecordOp>(std::move(record));
display_list->EndPaintOfUnpaired(gfx::Rect(250, 250));

display_list->Finalize();
Expand Down Expand Up @@ -664,9 +664,10 @@ TEST_F(DiscardableImageMapTest, GathersDiscardableImagesFromNestedOps) {
PaintImage discardable_image2 =
CreateDiscardablePaintImage(gfx::Size(100, 100));

scoped_refptr<DisplayItemList> display_list = new DisplayItemList;
PaintOpBuffer* buffer = display_list->StartPaint();
buffer->push<DrawImageOp>(discardable_image2, 100.f, 100.f, nullptr);
scoped_refptr<DisplayItemList> display_list =
new DisplayItemList(DisplayItemList::kToBeReleasedAsPaintOpBuffer);
display_list->StartPaint();
display_list->push<DrawImageOp>(discardable_image2, 100.f, 100.f, nullptr);
display_list->EndPaintOfUnpaired(gfx::Rect(100, 100, 100, 100));
display_list->Finalize();

Expand Down
56 changes: 40 additions & 16 deletions cc/paint/display_item_list.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,25 +35,31 @@ bool GetCanvasClipBounds(SkCanvas* canvas, gfx::Rect* clip_bounds) {

} // namespace

DisplayItemList::DisplayItemList() {
visual_rects_.reserve(1024);
begin_paired_indices_.reserve(32);
DisplayItemList::DisplayItemList(UsageHint usage_hint)
: usage_hint_(usage_hint) {
if (usage_hint_ == kTopLevelDisplayItemList) {
visual_rects_.reserve(1024);
offsets_.reserve(1024);
begin_paired_indices_.reserve(32);
}
}

DisplayItemList::~DisplayItemList() = default;

void DisplayItemList::Raster(SkCanvas* canvas,
SkPicture::AbortCallback* callback) const {
DCHECK(usage_hint_ == kTopLevelDisplayItemList);
gfx::Rect canvas_playback_rect;
if (!GetCanvasClipBounds(canvas, &canvas_playback_rect))
return;

std::vector<size_t> indices = rtree_.Search(canvas_playback_rect);
paint_op_buffer_.Playback(canvas, callback, &indices);
std::vector<size_t> offsets = rtree_.Search(canvas_playback_rect);
paint_op_buffer_.Playback(canvas, callback, &offsets);
}

void DisplayItemList::GrowCurrentBeginItemVisualRect(
const gfx::Rect& visual_rect) {
DCHECK(usage_hint_ == kTopLevelDisplayItemList);
if (!begin_paired_indices_.empty())
visual_rects_[begin_paired_indices_.back().first].Union(visual_rect);
}
Expand All @@ -65,12 +71,25 @@ void DisplayItemList::Finalize() {
// If this fails we had more calls to EndPaintOfPairedBegin() than
// to EndPaintOfPairedEnd().
DCHECK_EQ(0, in_paired_begin_count_);

DCHECK_EQ(visual_rects_.size(), offsets_.size());

if (usage_hint_ == kTopLevelDisplayItemList) {
rtree_.Build(visual_rects_,
[](const std::vector<gfx::Rect>& rects, size_t index) {
return rects[index];
},
[this](const std::vector<gfx::Rect>& rects, size_t index) {
// Ignore the given rects, since the payload comes from
// offsets. However, the indices match, so we can just index
// into offsets.
return offsets_[index];
});
}
paint_op_buffer_.ShrinkToFit();
rtree_.Build(visual_rects_);

visual_rects_.clear();
visual_rects_.shrink_to_fit();
offsets_.clear();
offsets_.shrink_to_fit();
begin_paired_indices_.shrink_to_fit();
}

Expand Down Expand Up @@ -101,14 +120,13 @@ DisplayItemList::CreateTracedValue(bool include_items) const {
if (include_items) {
state->BeginArray("items");

for (size_t i = 0; i < paint_op_buffer_.size(); ++i) {
for (const PaintOp* op : PaintOpBuffer::Iterator(&paint_op_buffer_)) {
state->BeginDictionary();

SkPictureRecorder recorder;
SkCanvas* canvas =
recorder.beginRecording(gfx::RectToSkRect(rtree_.GetBounds()));
std::vector<size_t> indices{i};
paint_op_buffer_.Playback(canvas, nullptr, &indices);
op->Raster(canvas, SkMatrix::I());
sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture();

std::string b64_picture;
Expand Down Expand Up @@ -141,6 +159,7 @@ DisplayItemList::CreateTracedValue(bool include_items) const {
}

void DisplayItemList::GenerateDiscardableImagesMetadata() {
DCHECK(usage_hint_ == kTopLevelDisplayItemList);
image_map_.Generate(&paint_op_buffer_, rtree_.GetBounds());
}

Expand All @@ -152,7 +171,11 @@ void DisplayItemList::Reset() {
image_map_.Reset();
paint_op_buffer_.Reset();
visual_rects_.clear();
visual_rects_.shrink_to_fit();
offsets_.clear();
offsets_.shrink_to_fit();
begin_paired_indices_.clear();
begin_paired_indices_.shrink_to_fit();
current_range_start_ = 0;
in_paired_begin_count_ = 0;
in_painting_ = false;
Expand All @@ -169,16 +192,17 @@ sk_sp<PaintRecord> DisplayItemList::ReleaseAsRecord() {
bool DisplayItemList::GetColorIfSolidInRect(const gfx::Rect& rect,
SkColor* color,
int max_ops_to_analyze) {
std::vector<size_t>* indices_to_use = nullptr;
std::vector<size_t> indices;
DCHECK(usage_hint_ == kTopLevelDisplayItemList);
std::vector<size_t>* offsets_to_use = nullptr;
std::vector<size_t> offsets;
if (!rect.Contains(rtree_.GetBounds())) {
indices = rtree_.Search(rect);
indices_to_use = &indices;
offsets = rtree_.Search(rect);
offsets_to_use = &offsets;
}

base::Optional<SkColor> solid_color =
SolidColorAnalyzer::DetermineIfSolidColor(
&paint_op_buffer_, rect, max_ops_to_analyze, indices_to_use);
&paint_op_buffer_, rect, max_ops_to_analyze, offsets_to_use);
if (solid_color) {
*color = *solid_color;
return true;
Expand Down
Loading

0 comments on commit 53a4abf

Please sign in to comment.