blob: 081e3158841943ab15a3d8bfaeff318afe457f5e [file] [log] [blame]
[email protected]d98c0242012-11-08 06:22:351// Copyright 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]cc3cfaa2013-03-18 09:05:525#include "cc/layers/picture_layer.h"
[email protected]f117a4c2012-12-16 04:53:106
[email protected]4ea293f72014-08-13 03:03:177#include "base/auto_reset.h"
danakj7a3089f2016-01-16 01:20:138#include "base/trace_event/trace_event.h"
[email protected]f7837a92013-08-21 03:00:059#include "cc/layers/content_layer_client.h"
[email protected]cc3cfaa2013-03-18 09:05:5210#include "cc/layers/picture_layer_impl.h"
vmpstre17fd212016-03-30 20:03:3211#include "cc/playback/recording_source.h"
dtrainor8e9da482016-01-04 09:53:0512#include "cc/proto/cc_conversions.h"
13#include "cc/proto/gfx_conversions.h"
14#include "cc/proto/layer.pb.h"
jamesr9b8fda32015-03-16 19:11:0515#include "cc/trees/layer_tree_host.h"
[email protected]556fd292013-03-18 08:03:0416#include "cc/trees/layer_tree_impl.h"
[email protected]de14c2c2014-04-24 01:02:2517#include "third_party/skia/include/core/SkPictureRecorder.h"
heejin.r.chungd28506ba2014-10-23 16:36:2018#include "ui/gfx/geometry/rect_conversions.h"
[email protected]d98c0242012-11-08 06:22:3519
20namespace cc {
21
loyso0940d412016-03-14 01:30:3122scoped_refptr<PictureLayer> PictureLayer::Create(ContentLayerClient* client) {
23 return make_scoped_refptr(new PictureLayer(client));
[email protected]d98c0242012-11-08 06:22:3524}
25
loyso0940d412016-03-14 01:30:3126PictureLayer::PictureLayer(ContentLayerClient* client)
mlliu42f52222016-07-11 19:15:2627 : instrumentation_object_tracker_(id()),
[email protected]36df0632014-06-12 20:26:1528 update_source_frame_number_(-1),
mlliu42f52222016-07-11 19:15:2629 is_mask_(false) {
30 inputs_.client = client;
31}
[email protected]d98c0242012-11-08 06:22:3532
loyso0940d412016-03-14 01:30:3133PictureLayer::PictureLayer(ContentLayerClient* client,
danakj60bc3bc2016-04-09 00:24:4834 std::unique_ptr<RecordingSource> source)
loyso0940d412016-03-14 01:30:3135 : PictureLayer(client) {
danakja04855a2015-11-18 20:39:1036 recording_source_ = std::move(source);
danakja819c2552014-11-14 02:05:0437}
38
[email protected]d98c0242012-11-08 06:22:3539PictureLayer::~PictureLayer() {
40}
41
danakj60bc3bc2016-04-09 00:24:4842std::unique_ptr<LayerImpl> PictureLayer::CreateLayerImpl(
43 LayerTreeImpl* tree_impl) {
sunxdc36713a2016-03-03 22:31:1044 return PictureLayerImpl::Create(tree_impl, id(), is_mask_);
[email protected]d98c0242012-11-08 06:22:3545}
46
[email protected]7aba6662013-03-12 10:17:3447void PictureLayer::PushPropertiesTo(LayerImpl* base_layer) {
48 Layer::PushPropertiesTo(base_layer);
danakj7a3089f2016-01-16 01:20:1349 TRACE_EVENT0("cc", "PictureLayer::PushPropertiesTo");
[email protected]3621e182012-11-09 22:37:0950 PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer);
danakja4ed6a22014-12-11 01:09:3851 // TODO(danakj): Make is_mask_ a constructor parameter for PictureLayer.
danakjd193f6b2014-12-16 00:06:2352 DCHECK_EQ(layer_impl->is_mask(), is_mask_);
dtrainor8e9da482016-01-04 09:53:0553 DropRecordingSourceContentIfInvalid();
[email protected]eda36f02013-10-23 08:15:3154
mlliu42f52222016-07-11 19:15:2655 layer_impl->SetNearestNeighbor(inputs_.nearest_neighbor);
jackhou24229612014-12-13 23:41:0056
enneaf5bda32015-02-19 01:27:3657 // Preserve lcd text settings from the current raster source.
58 bool can_use_lcd_text = layer_impl->RasterSourceUsesLCDText();
vmpstr41d68f882016-03-30 01:20:2359 scoped_refptr<RasterSource> raster_source =
enneaf5bda32015-02-19 01:27:3660 recording_source_->CreateRasterSource(can_use_lcd_text);
hendrikw757ba9e2015-03-23 21:13:0961 layer_impl->set_gpu_raster_max_texture_size(
62 layer_tree_host()->device_viewport_size());
chrishtrc41aca7b2016-03-18 15:44:2963 layer_impl->UpdateRasterSource(raster_source, &last_updated_invalidation_,
danakja4ed6a22014-12-11 01:09:3864 nullptr);
chrishtrc41aca7b2016-03-18 15:44:2965 DCHECK(last_updated_invalidation_.IsEmpty());
[email protected]3621e182012-11-09 22:37:0966}
67
[email protected]7aba6662013-03-12 10:17:3468void PictureLayer::SetLayerTreeHost(LayerTreeHost* host) {
69 Layer::SetLayerTreeHost(host);
ennebdb6fd202015-03-10 06:01:5770 if (!host)
71 return;
72
vmpstr5c4b6812015-09-29 19:57:1373 if (!recording_source_)
vmpstre17fd212016-03-30 20:03:3274 recording_source_.reset(new RecordingSource);
ennebdb6fd202015-03-10 06:01:5775 recording_source_->SetSlowdownRasterScaleFactor(
76 host->debug_state().slow_down_raster_scale_factor);
vmpstrdfd22862015-09-25 17:42:4177 // If we need to enable image decode tasks, then we have to generate the
78 // discardable images metadata.
vmpstr5c4b6812015-09-29 19:57:1379 const LayerTreeSettings& settings = layer_tree_host()->settings();
vmpstrdfd22862015-09-25 17:42:4180 recording_source_->SetGenerateDiscardableImagesMetadata(
81 settings.image_decode_tasks_enabled);
[email protected]ce37a152013-01-08 17:12:3382}
83
danakj19f0c9e2014-10-11 03:24:4284void PictureLayer::SetNeedsDisplayRect(const gfx::Rect& layer_rect) {
chrishtrbb9af002015-12-09 02:00:1185 DCHECK(!layer_tree_host() || !layer_tree_host()->in_paint_layer_contents());
chrishtrc41aca7b2016-03-18 15:44:2986 if (recording_source_)
87 recording_source_->SetNeedsDisplayRect(layer_rect);
[email protected]7aba6662013-03-12 10:17:3488 Layer::SetNeedsDisplayRect(layer_rect);
[email protected]3621e182012-11-09 22:37:0989}
90
danakj5f46636a2015-06-19 00:01:4091bool PictureLayer::Update() {
[email protected]abe51342013-10-28 22:04:3892 update_source_frame_number_ = layer_tree_host()->source_frame_number();
danakj5f46636a2015-06-19 00:01:4093 bool updated = Layer::Update();
[email protected]c50b997292013-08-03 18:44:3094
[email protected]a108f5db2014-07-16 06:10:2795 gfx::Size layer_size = paint_properties().bounds;
[email protected]4c1598952014-04-16 02:54:4896
enneffe57812015-02-14 02:37:2097 recording_source_->SetBackgroundColor(SafeOpaqueBackgroundColor());
98 recording_source_->SetRequiresClear(!contents_opaque() &&
mlliu42f52222016-07-11 19:15:2699 !inputs_.client->FillsBoundsCompletely());
enneffe57812015-02-14 02:37:20100
[email protected]08ac6f9e2013-12-04 05:44:09101 TRACE_EVENT1("cc", "PictureLayer::Update",
102 "source_frame_number",
103 layer_tree_host()->source_frame_number());
[email protected]8af1ce12014-06-15 12:18:36104 devtools_instrumentation::ScopedLayerTreeTask update_layer(
105 devtools_instrumentation::kUpdateLayer, id(), layer_tree_host()->id());
[email protected]08ac6f9e2013-12-04 05:44:09106
[email protected]8f322ba2014-06-18 23:48:18107 // UpdateAndExpandInvalidation will give us an invalidation that covers
108 // anything not explicitly recorded in this frame. We give this region
109 // to the impl side so that it drops tiles that may not have a recording
110 // for them.
mlliu42f52222016-07-11 19:15:26111 DCHECK(inputs_.client);
hendrikw9d909aa72014-11-11 20:19:52112 updated |= recording_source_->UpdateAndExpandInvalidation(
mlliu42f52222016-07-11 19:15:26113 inputs_.client, &last_updated_invalidation_, layer_size,
vmpstre17fd212016-03-30 20:03:32114 update_source_frame_number_, RecordingSource::RECORD_NORMALLY);
[email protected]048ff152013-11-25 21:02:11115
[email protected]214c86972013-08-20 23:43:06116 if (updated) {
117 SetNeedsPushProperties();
118 } else {
hendrikw312ee8ac2014-11-12 23:24:34119 // If this invalidation did not affect the recording source, then it can be
120 // cleared as an optimization.
chrishtrc41aca7b2016-03-18 15:44:29121 last_updated_invalidation_.Clear();
[email protected]49304bde2013-07-08 21:31:22122 }
[email protected]214c86972013-08-20 23:43:06123
[email protected]49304bde2013-07-08 21:31:22124 return updated;
[email protected]d98c0242012-11-08 06:22:35125}
126
[email protected]7aba6662013-03-12 10:17:34127void PictureLayer::SetIsMask(bool is_mask) {
hendrikw4e8c6322014-11-18 05:46:32128 is_mask_ = is_mask;
[email protected]f6776532012-12-21 20:24:33129}
130
fmalita2d743282016-03-22 13:32:10131sk_sp<SkPicture> PictureLayer::GetPicture() const {
vmpstre17fd212016-03-30 20:03:32132 // We could either flatten the RecordingSource into a single
hendrikwddb87659a2015-10-06 20:23:37133 // SkPicture, or paint a fresh one depending on what we intend to do with the
[email protected]f7837a92013-08-21 03:00:05134 // picture. For now we just paint a fresh one to get consistent results.
135 if (!DrawsContent())
fmalita2d743282016-03-22 13:32:10136 return nullptr;
[email protected]f7837a92013-08-21 03:00:05137
pan.deng0bd2a732015-04-01 03:22:05138 gfx::Size layer_size = bounds();
danakj60bc3bc2016-04-09 00:24:48139 std::unique_ptr<RecordingSource> recording_source(new RecordingSource);
pdrb42dfda32015-09-16 18:34:19140 Region recording_invalidation;
141 recording_source->UpdateAndExpandInvalidation(
mlliu42f52222016-07-11 19:15:26142 inputs_.client, &recording_invalidation, layer_size,
143 update_source_frame_number_, RecordingSource::RECORD_NORMALLY);
pan.deng0bd2a732015-04-01 03:22:05144
vmpstr41d68f882016-03-30 01:20:23145 scoped_refptr<RasterSource> raster_source =
pdrb42dfda32015-09-16 18:34:19146 recording_source->CreateRasterSource(false);
pan.deng0bd2a732015-04-01 03:22:05147
pdrb42dfda32015-09-16 18:34:19148 return raster_source->GetFlattenedPicture();
[email protected]f7837a92013-08-21 03:00:05149}
150
[email protected]a6c1b232014-05-05 23:53:08151bool PictureLayer::IsSuitableForGpuRasterization() const {
hendrikw9d909aa72014-11-11 20:19:52152 return recording_source_->IsSuitableForGpuRasterization();
[email protected]a6c1b232014-05-05 23:53:08153}
154
[email protected]ad63b2f2014-08-11 17:39:54155void PictureLayer::ClearClient() {
mlliu42f52222016-07-11 19:15:26156 inputs_.client = nullptr;
[email protected]ad63b2f2014-08-11 17:39:54157 UpdateDrawsContent(HasDrawableContent());
158}
159
jackhou24229612014-12-13 23:41:00160void PictureLayer::SetNearestNeighbor(bool nearest_neighbor) {
mlliu42f52222016-07-11 19:15:26161 if (inputs_.nearest_neighbor == nearest_neighbor)
jackhou24229612014-12-13 23:41:00162 return;
163
mlliu42f52222016-07-11 19:15:26164 inputs_.nearest_neighbor = nearest_neighbor;
jackhou24229612014-12-13 23:41:00165 SetNeedsCommit();
166}
167
[email protected]ad63b2f2014-08-11 17:39:54168bool PictureLayer::HasDrawableContent() const {
mlliu42f52222016-07-11 19:15:26169 return inputs_.client && Layer::HasDrawableContent();
[email protected]ad63b2f2014-08-11 17:39:54170}
171
dtrainor8e9da482016-01-04 09:53:05172void PictureLayer::SetTypeForProtoSerialization(proto::LayerNode* proto) const {
nyquist607e072e92016-02-19 00:30:41173 proto->set_type(proto::LayerNode::PICTURE_LAYER);
dtrainor8e9da482016-01-04 09:53:05174}
175
176void PictureLayer::LayerSpecificPropertiesToProto(
177 proto::LayerProperties* proto) {
178 Layer::LayerSpecificPropertiesToProto(proto);
179 DropRecordingSourceContentIfInvalid();
180
181 proto::PictureLayerProperties* picture = proto->mutable_picture();
nyquistfbaee112016-06-24 23:15:13182 recording_source_->ToProtobuf(picture->mutable_recording_source());
183
184 // Add all SkPicture items to the picture cache.
185 const DisplayItemList* display_list = recording_source_->GetDisplayItemList();
186 if (display_list) {
187 for (auto it = display_list->begin(); it != display_list->end(); ++it) {
188 sk_sp<const SkPicture> picture = it->GetPicture();
189 // Only DrawingDisplayItems have SkPictures.
190 if (!picture)
191 continue;
192
193 layer_tree_host()->engine_picture_cache()->MarkUsed(picture.get());
194 }
195 }
196
chrishtrc41aca7b2016-03-18 15:44:29197 RegionToProto(last_updated_invalidation_, picture->mutable_invalidation());
dtrainor8e9da482016-01-04 09:53:05198 picture->set_is_mask(is_mask_);
mlliu42f52222016-07-11 19:15:26199 picture->set_nearest_neighbor(inputs_.nearest_neighbor);
dtrainor8e9da482016-01-04 09:53:05200
201 picture->set_update_source_frame_number(update_source_frame_number_);
202
chrishtrc41aca7b2016-03-18 15:44:29203 last_updated_invalidation_.Clear();
dtrainor8e9da482016-01-04 09:53:05204}
205
206void PictureLayer::FromLayerSpecificPropertiesProto(
207 const proto::LayerProperties& proto) {
208 Layer::FromLayerSpecificPropertiesProto(proto);
209 const proto::PictureLayerProperties& picture = proto.picture();
nyquist34a0f412016-02-19 00:19:15210 // If this is a new layer, ensure it has a recording source. During layer
211 // hierarchy deserialization, ::SetLayerTreeHost(...) is not called, but
212 // instead the member is set directly, so it needs to be set here explicitly.
213 if (!recording_source_)
vmpstre17fd212016-03-30 20:03:32214 recording_source_.reset(new RecordingSource);
nyquist34a0f412016-02-19 00:19:15215
nyquistfbaee112016-06-24 23:15:13216 std::vector<uint32_t> used_engine_picture_ids;
217 recording_source_->FromProtobuf(picture.recording_source(),
218 layer_tree_host()->client_picture_cache(),
219 &used_engine_picture_ids);
220
221 // Inform picture cache about which SkPictures are now in use.
222 for (uint32_t engine_picture_id : used_engine_picture_ids)
223 layer_tree_host()->client_picture_cache()->MarkUsed(engine_picture_id);
dtrainor8e9da482016-01-04 09:53:05224
225 Region new_invalidation = RegionFromProto(picture.invalidation());
chrishtrc41aca7b2016-03-18 15:44:29226 last_updated_invalidation_.Swap(&new_invalidation);
dtrainor8e9da482016-01-04 09:53:05227 is_mask_ = picture.is_mask();
mlliu42f52222016-07-11 19:15:26228 inputs_.nearest_neighbor = picture.nearest_neighbor();
dtrainor8e9da482016-01-04 09:53:05229
230 update_source_frame_number_ = picture.update_source_frame_number();
231}
232
[email protected]1a55d7dc2013-10-12 07:52:20233void PictureLayer::RunMicroBenchmark(MicroBenchmark* benchmark) {
234 benchmark->RunOnLayer(this);
235}
236
dtrainor8e9da482016-01-04 09:53:05237void PictureLayer::DropRecordingSourceContentIfInvalid() {
238 int source_frame_number = layer_tree_host()->source_frame_number();
239 gfx::Size recording_source_bounds = recording_source_->GetSize();
240
241 gfx::Size layer_bounds = bounds();
242 if (paint_properties().source_frame_number == source_frame_number)
243 layer_bounds = paint_properties().bounds;
244
245 // If update called, then recording source size must match bounds pushed to
246 // impl layer.
247 DCHECK(update_source_frame_number_ != source_frame_number ||
248 layer_bounds == recording_source_bounds)
249 << " bounds " << layer_bounds.ToString() << " recording source "
250 << recording_source_bounds.ToString();
251
252 if (update_source_frame_number_ != source_frame_number &&
253 recording_source_bounds != layer_bounds) {
254 // Update may not get called for the layer (if it's not in the viewport
255 // for example), even though it has resized making the recording source no
256 // longer valid. In this case just destroy the recording source.
257 recording_source_->SetEmptyBounds();
258 }
259}
260
[email protected]d98c0242012-11-08 06:22:35261} // namespace cc