blob: 0102db4580381af77582b279cd549c1d9fa2b22a [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"
danakj920156852015-05-18 20:22:2911#include "cc/playback/display_list_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
loysoa6edaaff2015-05-25 03:26:4422scoped_refptr<PictureLayer> PictureLayer::Create(const LayerSettings& settings,
23 ContentLayerClient* client) {
24 return make_scoped_refptr(new PictureLayer(settings, client));
[email protected]d98c0242012-11-08 06:22:3525}
26
loysoa6edaaff2015-05-25 03:26:4427PictureLayer::PictureLayer(const LayerSettings& settings,
28 ContentLayerClient* client)
29 : Layer(settings),
30 client_(client),
[email protected]f6d55aa2014-03-11 20:42:5331 instrumentation_object_tracker_(id()),
[email protected]36df0632014-06-12 20:26:1532 update_source_frame_number_(-1),
jackhou24229612014-12-13 23:41:0033 is_mask_(false),
34 nearest_neighbor_(false) {
[email protected]36df0632014-06-12 20:26:1535}
[email protected]d98c0242012-11-08 06:22:3536
loysoa6edaaff2015-05-25 03:26:4437PictureLayer::PictureLayer(const LayerSettings& settings,
38 ContentLayerClient* client,
hendrikwddb87659a2015-10-06 20:23:3739 scoped_ptr<DisplayListRecordingSource> source)
loysoa6edaaff2015-05-25 03:26:4440 : PictureLayer(settings, client) {
danakja04855a2015-11-18 20:39:1041 recording_source_ = std::move(source);
danakja819c2552014-11-14 02:05:0442}
43
[email protected]d98c0242012-11-08 06:22:3544PictureLayer::~PictureLayer() {
45}
46
[email protected]8c406cda32013-03-14 16:20:3247scoped_ptr<LayerImpl> PictureLayer::CreateLayerImpl(LayerTreeImpl* tree_impl) {
aeliasd0070ba2015-01-31 13:44:4948 return PictureLayerImpl::Create(tree_impl, id(), is_mask_,
49 new LayerImpl::SyncedScrollOffset);
[email protected]d98c0242012-11-08 06:22:3550}
51
[email protected]7aba6662013-03-12 10:17:3452void PictureLayer::PushPropertiesTo(LayerImpl* base_layer) {
53 Layer::PushPropertiesTo(base_layer);
danakj7a3089f2016-01-16 01:20:1354 TRACE_EVENT0("cc", "PictureLayer::PushPropertiesTo");
[email protected]3621e182012-11-09 22:37:0955 PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer);
danakja4ed6a22014-12-11 01:09:3856 // TODO(danakj): Make is_mask_ a constructor parameter for PictureLayer.
danakjd193f6b2014-12-16 00:06:2357 DCHECK_EQ(layer_impl->is_mask(), is_mask_);
dtrainor8e9da482016-01-04 09:53:0558 DropRecordingSourceContentIfInvalid();
[email protected]eda36f02013-10-23 08:15:3159
jackhou24229612014-12-13 23:41:0060 layer_impl->SetNearestNeighbor(nearest_neighbor_);
61
enneaf5bda32015-02-19 01:27:3662 // Preserve lcd text settings from the current raster source.
63 bool can_use_lcd_text = layer_impl->RasterSourceUsesLCDText();
hendrikwc7014b22015-10-19 23:45:0964 scoped_refptr<DisplayListRasterSource> raster_source =
enneaf5bda32015-02-19 01:27:3665 recording_source_->CreateRasterSource(can_use_lcd_text);
hendrikw757ba9e2015-03-23 21:13:0966 layer_impl->set_gpu_raster_max_texture_size(
67 layer_tree_host()->device_viewport_size());
chrishtrbb9af002015-12-09 02:00:1168 layer_impl->UpdateRasterSource(raster_source, invalidation_.region(),
danakja4ed6a22014-12-11 01:09:3869 nullptr);
chrishtrbb9af002015-12-09 02:00:1170 DCHECK(invalidation_.IsEmpty());
[email protected]3621e182012-11-09 22:37:0971}
72
[email protected]7aba6662013-03-12 10:17:3473void PictureLayer::SetLayerTreeHost(LayerTreeHost* host) {
74 Layer::SetLayerTreeHost(host);
ennebdb6fd202015-03-10 06:01:5775 if (!host)
76 return;
77
vmpstr5c4b6812015-09-29 19:57:1378 if (!recording_source_)
79 recording_source_.reset(new DisplayListRecordingSource);
ennebdb6fd202015-03-10 06:01:5780 recording_source_->SetSlowdownRasterScaleFactor(
81 host->debug_state().slow_down_raster_scale_factor);
vmpstrdfd22862015-09-25 17:42:4182 // If we need to enable image decode tasks, then we have to generate the
83 // discardable images metadata.
vmpstr5c4b6812015-09-29 19:57:1384 const LayerTreeSettings& settings = layer_tree_host()->settings();
vmpstrdfd22862015-09-25 17:42:4185 recording_source_->SetGenerateDiscardableImagesMetadata(
86 settings.image_decode_tasks_enabled);
[email protected]ce37a152013-01-08 17:12:3387}
88
danakj19f0c9e2014-10-11 03:24:4289void PictureLayer::SetNeedsDisplayRect(const gfx::Rect& layer_rect) {
chrishtrbb9af002015-12-09 02:00:1190 DCHECK(!layer_tree_host() || !layer_tree_host()->in_paint_layer_contents());
danakj19f0c9e2014-10-11 03:24:4291 if (!layer_rect.IsEmpty()) {
[email protected]7a9fc132013-01-10 00:54:5892 // Clamp invalidation to the layer bounds.
chrishtrbb9af002015-12-09 02:00:1193 invalidation_.Union(gfx::IntersectRects(layer_rect, gfx::Rect(bounds())));
[email protected]7a9fc132013-01-10 00:54:5894 }
[email protected]7aba6662013-03-12 10:17:3495 Layer::SetNeedsDisplayRect(layer_rect);
[email protected]3621e182012-11-09 22:37:0996}
97
danakj5f46636a2015-06-19 00:01:4098bool PictureLayer::Update() {
[email protected]abe51342013-10-28 22:04:3899 update_source_frame_number_ = layer_tree_host()->source_frame_number();
danakj5f46636a2015-06-19 00:01:40100 bool updated = Layer::Update();
[email protected]c50b997292013-08-03 18:44:30101
danakj64767d902015-06-19 00:10:43102 gfx::Rect update_rect = visible_layer_rect();
[email protected]a108f5db2014-07-16 06:10:27103 gfx::Size layer_size = paint_properties().bounds;
[email protected]4c1598952014-04-16 02:54:48104
danakj64767d902015-06-19 00:10:43105 if (last_updated_visible_layer_rect_ == update_rect &&
chrishtrbb9af002015-12-09 02:00:11106 recording_source_->GetSize() == layer_size && invalidation_.IsEmpty()) {
[email protected]048ff152013-11-25 21:02:11107 // Only early out if the visible content rect of this layer hasn't changed.
108 return updated;
109 }
110
enneffe57812015-02-14 02:37:20111 recording_source_->SetBackgroundColor(SafeOpaqueBackgroundColor());
112 recording_source_->SetRequiresClear(!contents_opaque() &&
113 !client_->FillsBoundsCompletely());
114
[email protected]08ac6f9e2013-12-04 05:44:09115 TRACE_EVENT1("cc", "PictureLayer::Update",
116 "source_frame_number",
117 layer_tree_host()->source_frame_number());
[email protected]8af1ce12014-06-15 12:18:36118 devtools_instrumentation::ScopedLayerTreeTask update_layer(
119 devtools_instrumentation::kUpdateLayer, id(), layer_tree_host()->id());
[email protected]08ac6f9e2013-12-04 05:44:09120
[email protected]8f322ba2014-06-18 23:48:18121 // UpdateAndExpandInvalidation will give us an invalidation that covers
122 // anything not explicitly recorded in this frame. We give this region
123 // to the impl side so that it drops tiles that may not have a recording
124 // for them.
[email protected]1d96e032014-03-25 05:59:08125 DCHECK(client_);
hendrikw9d909aa72014-11-11 20:19:52126 updated |= recording_source_->UpdateAndExpandInvalidation(
chrishtrbb9af002015-12-09 02:00:11127 client_, invalidation_.region(), layer_size, update_rect,
hendrikwddb87659a2015-10-06 20:23:37128 update_source_frame_number_, DisplayListRecordingSource::RECORD_NORMALLY);
danakj64767d902015-06-19 00:10:43129 last_updated_visible_layer_rect_ = visible_layer_rect();
[email protected]048ff152013-11-25 21:02:11130
[email protected]214c86972013-08-20 23:43:06131 if (updated) {
132 SetNeedsPushProperties();
133 } else {
hendrikw312ee8ac2014-11-12 23:24:34134 // If this invalidation did not affect the recording source, then it can be
135 // cleared as an optimization.
chrishtrbb9af002015-12-09 02:00:11136 invalidation_.Clear();
[email protected]49304bde2013-07-08 21:31:22137 }
[email protected]214c86972013-08-20 23:43:06138
[email protected]49304bde2013-07-08 21:31:22139 return updated;
[email protected]d98c0242012-11-08 06:22:35140}
141
[email protected]7aba6662013-03-12 10:17:34142void PictureLayer::SetIsMask(bool is_mask) {
hendrikw4e8c6322014-11-18 05:46:32143 is_mask_ = is_mask;
[email protected]f6776532012-12-21 20:24:33144}
145
[email protected]f7837a92013-08-21 03:00:05146skia::RefPtr<SkPicture> PictureLayer::GetPicture() const {
hendrikwddb87659a2015-10-06 20:23:37147 // We could either flatten the DisplayListRecordingSource into a single
148 // SkPicture, or paint a fresh one depending on what we intend to do with the
[email protected]f7837a92013-08-21 03:00:05149 // picture. For now we just paint a fresh one to get consistent results.
150 if (!DrawsContent())
151 return skia::RefPtr<SkPicture>();
152
pan.deng0bd2a732015-04-01 03:22:05153 gfx::Size layer_size = bounds();
hendrikwddb87659a2015-10-06 20:23:37154 scoped_ptr<DisplayListRecordingSource> recording_source(
155 new DisplayListRecordingSource);
pdrb42dfda32015-09-16 18:34:19156 Region recording_invalidation;
157 recording_source->UpdateAndExpandInvalidation(
158 client_, &recording_invalidation, layer_size, gfx::Rect(layer_size),
hendrikwddb87659a2015-10-06 20:23:37159 update_source_frame_number_, DisplayListRecordingSource::RECORD_NORMALLY);
pan.deng0bd2a732015-04-01 03:22:05160
hendrikwc7014b22015-10-19 23:45:09161 scoped_refptr<DisplayListRasterSource> raster_source =
pdrb42dfda32015-09-16 18:34:19162 recording_source->CreateRasterSource(false);
pan.deng0bd2a732015-04-01 03:22:05163
pdrb42dfda32015-09-16 18:34:19164 return raster_source->GetFlattenedPicture();
[email protected]f7837a92013-08-21 03:00:05165}
166
[email protected]a6c1b232014-05-05 23:53:08167bool PictureLayer::IsSuitableForGpuRasterization() const {
hendrikw9d909aa72014-11-11 20:19:52168 return recording_source_->IsSuitableForGpuRasterization();
[email protected]a6c1b232014-05-05 23:53:08169}
170
[email protected]ad63b2f2014-08-11 17:39:54171void PictureLayer::ClearClient() {
kulkarni.a4015690f12014-10-10 13:50:06172 client_ = nullptr;
[email protected]ad63b2f2014-08-11 17:39:54173 UpdateDrawsContent(HasDrawableContent());
174}
175
jackhou24229612014-12-13 23:41:00176void PictureLayer::SetNearestNeighbor(bool nearest_neighbor) {
177 if (nearest_neighbor_ == nearest_neighbor)
178 return;
179
180 nearest_neighbor_ = nearest_neighbor;
181 SetNeedsCommit();
182}
183
[email protected]ad63b2f2014-08-11 17:39:54184bool PictureLayer::HasDrawableContent() const {
185 return client_ && Layer::HasDrawableContent();
186}
187
dtrainor8e9da482016-01-04 09:53:05188void PictureLayer::SetTypeForProtoSerialization(proto::LayerNode* proto) const {
189 proto->set_type(proto::LayerType::PICTURE_LAYER);
190}
191
192void PictureLayer::LayerSpecificPropertiesToProto(
193 proto::LayerProperties* proto) {
194 Layer::LayerSpecificPropertiesToProto(proto);
195 DropRecordingSourceContentIfInvalid();
196
197 proto::PictureLayerProperties* picture = proto->mutable_picture();
nyquist16febb42016-02-12 00:15:04198 recording_source_->ToProtobuf(
199 picture->mutable_recording_source(),
200 layer_tree_host()->image_serialization_processor());
dtrainor8e9da482016-01-04 09:53:05201 RegionToProto(*invalidation_.region(), picture->mutable_invalidation());
202 RectToProto(last_updated_visible_layer_rect_,
203 picture->mutable_last_updated_visible_layer_rect());
204 picture->set_is_mask(is_mask_);
205 picture->set_nearest_neighbor(nearest_neighbor_);
206
207 picture->set_update_source_frame_number(update_source_frame_number_);
208
209 invalidation_.Clear();
210}
211
212void PictureLayer::FromLayerSpecificPropertiesProto(
213 const proto::LayerProperties& proto) {
214 Layer::FromLayerSpecificPropertiesProto(proto);
215 const proto::PictureLayerProperties& picture = proto.picture();
nyquist34a0f412016-02-19 00:19:15216 // If this is a new layer, ensure it has a recording source. During layer
217 // hierarchy deserialization, ::SetLayerTreeHost(...) is not called, but
218 // instead the member is set directly, so it needs to be set here explicitly.
219 if (!recording_source_)
220 recording_source_.reset(new DisplayListRecordingSource);
221
nyquist16febb42016-02-12 00:15:04222 recording_source_->FromProtobuf(
223 picture.recording_source(),
224 layer_tree_host()->image_serialization_processor());
dtrainor8e9da482016-01-04 09:53:05225
226 Region new_invalidation = RegionFromProto(picture.invalidation());
227 invalidation_.Swap(&new_invalidation);
228 last_updated_visible_layer_rect_ =
229 ProtoToRect(picture.last_updated_visible_layer_rect());
230 is_mask_ = picture.is_mask();
231 nearest_neighbor_ = picture.nearest_neighbor();
232
233 update_source_frame_number_ = picture.update_source_frame_number();
234}
235
[email protected]1a55d7dc2013-10-12 07:52:20236void PictureLayer::RunMicroBenchmark(MicroBenchmark* benchmark) {
237 benchmark->RunOnLayer(this);
238}
239
dtrainor8e9da482016-01-04 09:53:05240void PictureLayer::DropRecordingSourceContentIfInvalid() {
241 int source_frame_number = layer_tree_host()->source_frame_number();
242 gfx::Size recording_source_bounds = recording_source_->GetSize();
243
244 gfx::Size layer_bounds = bounds();
245 if (paint_properties().source_frame_number == source_frame_number)
246 layer_bounds = paint_properties().bounds;
247
248 // If update called, then recording source size must match bounds pushed to
249 // impl layer.
250 DCHECK(update_source_frame_number_ != source_frame_number ||
251 layer_bounds == recording_source_bounds)
252 << " bounds " << layer_bounds.ToString() << " recording source "
253 << recording_source_bounds.ToString();
254
255 if (update_source_frame_number_ != source_frame_number &&
256 recording_source_bounds != layer_bounds) {
257 // Update may not get called for the layer (if it's not in the viewport
258 // for example), even though it has resized making the recording source no
259 // longer valid. In this case just destroy the recording source.
260 recording_source_->SetEmptyBounds();
261 }
262}
263
[email protected]d98c0242012-11-08 06:22:35264} // namespace cc