blob: 284f2a382c7f2102bf7863ef62f9d316e4087c0d [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"
[email protected]f7837a92013-08-21 03:00:058#include "cc/layers/content_layer_client.h"
[email protected]cc3cfaa2013-03-18 09:05:529#include "cc/layers/picture_layer_impl.h"
danakj920156852015-05-18 20:22:2910#include "cc/playback/display_list_recording_source.h"
dtrainor8e9da482016-01-04 09:53:0511#include "cc/proto/cc_conversions.h"
12#include "cc/proto/gfx_conversions.h"
13#include "cc/proto/layer.pb.h"
jamesr9b8fda32015-03-16 19:11:0514#include "cc/trees/layer_tree_host.h"
[email protected]556fd292013-03-18 08:03:0415#include "cc/trees/layer_tree_impl.h"
[email protected]de14c2c2014-04-24 01:02:2516#include "third_party/skia/include/core/SkPictureRecorder.h"
heejin.r.chungd28506ba2014-10-23 16:36:2017#include "ui/gfx/geometry/rect_conversions.h"
[email protected]d98c0242012-11-08 06:22:3518
19namespace cc {
20
loysoa6edaaff2015-05-25 03:26:4421scoped_refptr<PictureLayer> PictureLayer::Create(const LayerSettings& settings,
22 ContentLayerClient* client) {
23 return make_scoped_refptr(new PictureLayer(settings, client));
[email protected]d98c0242012-11-08 06:22:3524}
25
loysoa6edaaff2015-05-25 03:26:4426PictureLayer::PictureLayer(const LayerSettings& settings,
27 ContentLayerClient* client)
28 : Layer(settings),
29 client_(client),
[email protected]f6d55aa2014-03-11 20:42:5330 instrumentation_object_tracker_(id()),
[email protected]36df0632014-06-12 20:26:1531 update_source_frame_number_(-1),
jackhou24229612014-12-13 23:41:0032 is_mask_(false),
33 nearest_neighbor_(false) {
[email protected]36df0632014-06-12 20:26:1534}
[email protected]d98c0242012-11-08 06:22:3535
loysoa6edaaff2015-05-25 03:26:4436PictureLayer::PictureLayer(const LayerSettings& settings,
37 ContentLayerClient* client,
hendrikwddb87659a2015-10-06 20:23:3738 scoped_ptr<DisplayListRecordingSource> source)
loysoa6edaaff2015-05-25 03:26:4439 : PictureLayer(settings, client) {
danakja04855a2015-11-18 20:39:1040 recording_source_ = std::move(source);
danakja819c2552014-11-14 02:05:0441}
42
[email protected]d98c0242012-11-08 06:22:3543PictureLayer::~PictureLayer() {
44}
45
[email protected]8c406cda32013-03-14 16:20:3246scoped_ptr<LayerImpl> PictureLayer::CreateLayerImpl(LayerTreeImpl* tree_impl) {
aeliasd0070ba2015-01-31 13:44:4947 return PictureLayerImpl::Create(tree_impl, id(), is_mask_,
48 new LayerImpl::SyncedScrollOffset);
[email protected]d98c0242012-11-08 06:22:3549}
50
[email protected]7aba6662013-03-12 10:17:3451void PictureLayer::PushPropertiesTo(LayerImpl* base_layer) {
52 Layer::PushPropertiesTo(base_layer);
[email protected]3621e182012-11-09 22:37:0953 PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer);
danakja4ed6a22014-12-11 01:09:3854 // TODO(danakj): Make is_mask_ a constructor parameter for PictureLayer.
danakjd193f6b2014-12-16 00:06:2355 DCHECK_EQ(layer_impl->is_mask(), is_mask_);
dtrainor8e9da482016-01-04 09:53:0556 DropRecordingSourceContentIfInvalid();
[email protected]eda36f02013-10-23 08:15:3157
jackhou24229612014-12-13 23:41:0058 layer_impl->SetNearestNeighbor(nearest_neighbor_);
59
enneaf5bda32015-02-19 01:27:3660 // Preserve lcd text settings from the current raster source.
61 bool can_use_lcd_text = layer_impl->RasterSourceUsesLCDText();
hendrikwc7014b22015-10-19 23:45:0962 scoped_refptr<DisplayListRasterSource> raster_source =
enneaf5bda32015-02-19 01:27:3663 recording_source_->CreateRasterSource(can_use_lcd_text);
hendrikw757ba9e2015-03-23 21:13:0964 layer_impl->set_gpu_raster_max_texture_size(
65 layer_tree_host()->device_viewport_size());
chrishtrbb9af002015-12-09 02:00:1166 layer_impl->UpdateRasterSource(raster_source, invalidation_.region(),
danakja4ed6a22014-12-11 01:09:3867 nullptr);
chrishtrbb9af002015-12-09 02:00:1168 DCHECK(invalidation_.IsEmpty());
[email protected]3621e182012-11-09 22:37:0969}
70
[email protected]7aba6662013-03-12 10:17:3471void PictureLayer::SetLayerTreeHost(LayerTreeHost* host) {
72 Layer::SetLayerTreeHost(host);
ennebdb6fd202015-03-10 06:01:5773 if (!host)
74 return;
75
vmpstr5c4b6812015-09-29 19:57:1376 if (!recording_source_)
77 recording_source_.reset(new DisplayListRecordingSource);
ennebdb6fd202015-03-10 06:01:5778 recording_source_->SetSlowdownRasterScaleFactor(
79 host->debug_state().slow_down_raster_scale_factor);
vmpstrdfd22862015-09-25 17:42:4180 // If we need to enable image decode tasks, then we have to generate the
81 // discardable images metadata.
vmpstr5c4b6812015-09-29 19:57:1382 const LayerTreeSettings& settings = layer_tree_host()->settings();
vmpstrdfd22862015-09-25 17:42:4183 recording_source_->SetGenerateDiscardableImagesMetadata(
84 settings.image_decode_tasks_enabled);
[email protected]ce37a152013-01-08 17:12:3385}
86
danakj19f0c9e2014-10-11 03:24:4287void PictureLayer::SetNeedsDisplayRect(const gfx::Rect& layer_rect) {
chrishtrbb9af002015-12-09 02:00:1188 DCHECK(!layer_tree_host() || !layer_tree_host()->in_paint_layer_contents());
danakj19f0c9e2014-10-11 03:24:4289 if (!layer_rect.IsEmpty()) {
[email protected]7a9fc132013-01-10 00:54:5890 // Clamp invalidation to the layer bounds.
chrishtrbb9af002015-12-09 02:00:1191 invalidation_.Union(gfx::IntersectRects(layer_rect, gfx::Rect(bounds())));
[email protected]7a9fc132013-01-10 00:54:5892 }
[email protected]7aba6662013-03-12 10:17:3493 Layer::SetNeedsDisplayRect(layer_rect);
[email protected]3621e182012-11-09 22:37:0994}
95
danakj5f46636a2015-06-19 00:01:4096bool PictureLayer::Update() {
[email protected]abe51342013-10-28 22:04:3897 update_source_frame_number_ = layer_tree_host()->source_frame_number();
danakj5f46636a2015-06-19 00:01:4098 bool updated = Layer::Update();
[email protected]c50b997292013-08-03 18:44:3099
danakj64767d902015-06-19 00:10:43100 gfx::Rect update_rect = visible_layer_rect();
[email protected]a108f5db2014-07-16 06:10:27101 gfx::Size layer_size = paint_properties().bounds;
[email protected]4c1598952014-04-16 02:54:48102
danakj64767d902015-06-19 00:10:43103 if (last_updated_visible_layer_rect_ == update_rect &&
chrishtrbb9af002015-12-09 02:00:11104 recording_source_->GetSize() == layer_size && invalidation_.IsEmpty()) {
[email protected]048ff152013-11-25 21:02:11105 // Only early out if the visible content rect of this layer hasn't changed.
106 return updated;
107 }
108
enneffe57812015-02-14 02:37:20109 recording_source_->SetBackgroundColor(SafeOpaqueBackgroundColor());
110 recording_source_->SetRequiresClear(!contents_opaque() &&
111 !client_->FillsBoundsCompletely());
112
[email protected]08ac6f9e2013-12-04 05:44:09113 TRACE_EVENT1("cc", "PictureLayer::Update",
114 "source_frame_number",
115 layer_tree_host()->source_frame_number());
[email protected]8af1ce12014-06-15 12:18:36116 devtools_instrumentation::ScopedLayerTreeTask update_layer(
117 devtools_instrumentation::kUpdateLayer, id(), layer_tree_host()->id());
[email protected]08ac6f9e2013-12-04 05:44:09118
[email protected]8f322ba2014-06-18 23:48:18119 // UpdateAndExpandInvalidation will give us an invalidation that covers
120 // anything not explicitly recorded in this frame. We give this region
121 // to the impl side so that it drops tiles that may not have a recording
122 // for them.
[email protected]1d96e032014-03-25 05:59:08123 DCHECK(client_);
hendrikw9d909aa72014-11-11 20:19:52124 updated |= recording_source_->UpdateAndExpandInvalidation(
chrishtrbb9af002015-12-09 02:00:11125 client_, invalidation_.region(), layer_size, update_rect,
hendrikwddb87659a2015-10-06 20:23:37126 update_source_frame_number_, DisplayListRecordingSource::RECORD_NORMALLY);
danakj64767d902015-06-19 00:10:43127 last_updated_visible_layer_rect_ = visible_layer_rect();
[email protected]048ff152013-11-25 21:02:11128
[email protected]214c86972013-08-20 23:43:06129 if (updated) {
130 SetNeedsPushProperties();
131 } else {
hendrikw312ee8ac2014-11-12 23:24:34132 // If this invalidation did not affect the recording source, then it can be
133 // cleared as an optimization.
chrishtrbb9af002015-12-09 02:00:11134 invalidation_.Clear();
[email protected]49304bde2013-07-08 21:31:22135 }
[email protected]214c86972013-08-20 23:43:06136
[email protected]49304bde2013-07-08 21:31:22137 return updated;
[email protected]d98c0242012-11-08 06:22:35138}
139
[email protected]7aba6662013-03-12 10:17:34140void PictureLayer::SetIsMask(bool is_mask) {
hendrikw4e8c6322014-11-18 05:46:32141 is_mask_ = is_mask;
[email protected]f6776532012-12-21 20:24:33142}
143
[email protected]f7837a92013-08-21 03:00:05144skia::RefPtr<SkPicture> PictureLayer::GetPicture() const {
hendrikwddb87659a2015-10-06 20:23:37145 // We could either flatten the DisplayListRecordingSource into a single
146 // SkPicture, or paint a fresh one depending on what we intend to do with the
[email protected]f7837a92013-08-21 03:00:05147 // picture. For now we just paint a fresh one to get consistent results.
148 if (!DrawsContent())
149 return skia::RefPtr<SkPicture>();
150
pan.deng0bd2a732015-04-01 03:22:05151 gfx::Size layer_size = bounds();
hendrikwddb87659a2015-10-06 20:23:37152 scoped_ptr<DisplayListRecordingSource> recording_source(
153 new DisplayListRecordingSource);
pdrb42dfda32015-09-16 18:34:19154 Region recording_invalidation;
155 recording_source->UpdateAndExpandInvalidation(
156 client_, &recording_invalidation, layer_size, gfx::Rect(layer_size),
hendrikwddb87659a2015-10-06 20:23:37157 update_source_frame_number_, DisplayListRecordingSource::RECORD_NORMALLY);
pan.deng0bd2a732015-04-01 03:22:05158
hendrikwc7014b22015-10-19 23:45:09159 scoped_refptr<DisplayListRasterSource> raster_source =
pdrb42dfda32015-09-16 18:34:19160 recording_source->CreateRasterSource(false);
pan.deng0bd2a732015-04-01 03:22:05161
pdrb42dfda32015-09-16 18:34:19162 return raster_source->GetFlattenedPicture();
[email protected]f7837a92013-08-21 03:00:05163}
164
[email protected]a6c1b232014-05-05 23:53:08165bool PictureLayer::IsSuitableForGpuRasterization() const {
hendrikw9d909aa72014-11-11 20:19:52166 return recording_source_->IsSuitableForGpuRasterization();
[email protected]a6c1b232014-05-05 23:53:08167}
168
[email protected]ad63b2f2014-08-11 17:39:54169void PictureLayer::ClearClient() {
kulkarni.a4015690f12014-10-10 13:50:06170 client_ = nullptr;
[email protected]ad63b2f2014-08-11 17:39:54171 UpdateDrawsContent(HasDrawableContent());
172}
173
jackhou24229612014-12-13 23:41:00174void PictureLayer::SetNearestNeighbor(bool nearest_neighbor) {
175 if (nearest_neighbor_ == nearest_neighbor)
176 return;
177
178 nearest_neighbor_ = nearest_neighbor;
179 SetNeedsCommit();
180}
181
[email protected]ad63b2f2014-08-11 17:39:54182bool PictureLayer::HasDrawableContent() const {
183 return client_ && Layer::HasDrawableContent();
184}
185
dtrainor8e9da482016-01-04 09:53:05186void PictureLayer::SetTypeForProtoSerialization(proto::LayerNode* proto) const {
187 proto->set_type(proto::LayerType::PICTURE_LAYER);
188}
189
190void PictureLayer::LayerSpecificPropertiesToProto(
191 proto::LayerProperties* proto) {
192 Layer::LayerSpecificPropertiesToProto(proto);
193 DropRecordingSourceContentIfInvalid();
194
195 proto::PictureLayerProperties* picture = proto->mutable_picture();
196 recording_source_->ToProtobuf(picture->mutable_recording_source());
197 RegionToProto(*invalidation_.region(), picture->mutable_invalidation());
198 RectToProto(last_updated_visible_layer_rect_,
199 picture->mutable_last_updated_visible_layer_rect());
200 picture->set_is_mask(is_mask_);
201 picture->set_nearest_neighbor(nearest_neighbor_);
202
203 picture->set_update_source_frame_number(update_source_frame_number_);
204
205 invalidation_.Clear();
206}
207
208void PictureLayer::FromLayerSpecificPropertiesProto(
209 const proto::LayerProperties& proto) {
210 Layer::FromLayerSpecificPropertiesProto(proto);
211 const proto::PictureLayerProperties& picture = proto.picture();
212 recording_source_->FromProtobuf(picture.recording_source());
213
214 Region new_invalidation = RegionFromProto(picture.invalidation());
215 invalidation_.Swap(&new_invalidation);
216 last_updated_visible_layer_rect_ =
217 ProtoToRect(picture.last_updated_visible_layer_rect());
218 is_mask_ = picture.is_mask();
219 nearest_neighbor_ = picture.nearest_neighbor();
220
221 update_source_frame_number_ = picture.update_source_frame_number();
222}
223
[email protected]1a55d7dc2013-10-12 07:52:20224void PictureLayer::RunMicroBenchmark(MicroBenchmark* benchmark) {
225 benchmark->RunOnLayer(this);
226}
227
dtrainor8e9da482016-01-04 09:53:05228void PictureLayer::DropRecordingSourceContentIfInvalid() {
229 int source_frame_number = layer_tree_host()->source_frame_number();
230 gfx::Size recording_source_bounds = recording_source_->GetSize();
231
232 gfx::Size layer_bounds = bounds();
233 if (paint_properties().source_frame_number == source_frame_number)
234 layer_bounds = paint_properties().bounds;
235
236 // If update called, then recording source size must match bounds pushed to
237 // impl layer.
238 DCHECK(update_source_frame_number_ != source_frame_number ||
239 layer_bounds == recording_source_bounds)
240 << " bounds " << layer_bounds.ToString() << " recording source "
241 << recording_source_bounds.ToString();
242
243 if (update_source_frame_number_ != source_frame_number &&
244 recording_source_bounds != layer_bounds) {
245 // Update may not get called for the layer (if it's not in the viewport
246 // for example), even though it has resized making the recording source no
247 // longer valid. In this case just destroy the recording source.
248 recording_source_->SetEmptyBounds();
249 }
250}
251
[email protected]d98c0242012-11-08 06:22:35252} // namespace cc