1 // 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 
5 #include "cc/layers/picture_layer.h"
6 
7 #include "base/auto_reset.h"
8 #include "base/debug/crash_logging.h"
9 #include "base/debug/dump_without_crashing.h"
10 #include "base/trace_event/trace_event.h"
11 #include "cc/layers/content_layer_client.h"
12 #include "cc/layers/picture_layer_impl.h"
13 #include "cc/layers/recording_source.h"
14 #include "cc/paint/paint_record.h"
15 #include "cc/trees/layer_tree_host.h"
16 #include "cc/trees/layer_tree_impl.h"
17 #include "cc/trees/transform_node.h"
18 #include "ui/gfx/geometry/rect_conversions.h"
19 
20 namespace cc {
21 
22 PictureLayer::PictureLayerInputs::PictureLayerInputs() = default;
23 
24 PictureLayer::PictureLayerInputs::~PictureLayerInputs() = default;
25 
Create(ContentLayerClient * client)26 scoped_refptr<PictureLayer> PictureLayer::Create(ContentLayerClient* client) {
27   return base::WrapRefCounted(new PictureLayer(client));
28 }
29 
PictureLayer(ContentLayerClient * client)30 PictureLayer::PictureLayer(ContentLayerClient* client)
31     : instrumentation_object_tracker_(id()), update_source_frame_number_(-1) {
32   picture_layer_inputs_.client = client;
33 }
34 
PictureLayer(ContentLayerClient * client,std::unique_ptr<RecordingSource> source)35 PictureLayer::PictureLayer(ContentLayerClient* client,
36                            std::unique_ptr<RecordingSource> source)
37     : PictureLayer(client) {
38   recording_source_ = std::move(source);
39 }
40 
41 PictureLayer::~PictureLayer() = default;
42 
CreateLayerImpl(LayerTreeImpl * tree_impl)43 std::unique_ptr<LayerImpl> PictureLayer::CreateLayerImpl(
44     LayerTreeImpl* tree_impl) {
45   return PictureLayerImpl::Create(tree_impl, id());
46 }
47 
PushPropertiesTo(LayerImpl * base_layer)48 void PictureLayer::PushPropertiesTo(LayerImpl* base_layer) {
49   // TODO(enne): http://crbug.com/918126 debugging
50   CHECK(this);
51 
52   PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer);
53 
54   Layer::PushPropertiesTo(base_layer);
55   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
56                "PictureLayer::PushPropertiesTo");
57   DropRecordingSourceContentIfInvalid();
58 
59   layer_impl->SetNearestNeighbor(picture_layer_inputs_.nearest_neighbor);
60   layer_impl->SetUseTransformedRasterization(
61       ShouldUseTransformedRasterization());
62   layer_impl->set_gpu_raster_max_texture_size(
63       layer_tree_host()->device_viewport_rect().size());
64   layer_impl->SetIsBackdropFilterMask(is_backdrop_filter_mask());
65   layer_impl->SetDirectlyCompositedImageSize(
66       picture_layer_inputs_.directly_composited_image_size);
67 
68   // TODO(enne): http://crbug.com/918126 debugging
69   CHECK(this);
70   if (!recording_source_) {
71     bool valid_host = layer_tree_host();
72     bool has_parent = parent();
73     bool parent_has_host = parent() && parent()->layer_tree_host();
74 
75     auto str = base::StringPrintf("vh: %d, hp: %d, phh: %d", valid_host,
76                                   has_parent, parent_has_host);
77     static auto* crash_key = base::debug::AllocateCrashKeyString(
78         "issue918126", base::debug::CrashKeySize::Size32);
79     base::debug::SetCrashKeyString(crash_key, str);
80     base::debug::DumpWithoutCrashing();
81   }
82 
83   layer_impl->UpdateRasterSource(recording_source_->CreateRasterSource(),
84                                  &last_updated_invalidation_, nullptr, nullptr);
85   DCHECK(last_updated_invalidation_.IsEmpty());
86 }
87 
SetLayerTreeHost(LayerTreeHost * host)88 void PictureLayer::SetLayerTreeHost(LayerTreeHost* host) {
89   Layer::SetLayerTreeHost(host);
90 
91   if (!host)
92     return;
93 
94   if (!recording_source_)
95     recording_source_.reset(new RecordingSource);
96   recording_source_->SetSlowdownRasterScaleFactor(
97       host->GetDebugState().slow_down_raster_scale_factor);
98 
99   // Source frame numbers are relative the LayerTreeHost, so this needs
100   // to be reset.
101   update_source_frame_number_ = -1;
102 }
103 
SetNeedsDisplayRect(const gfx::Rect & layer_rect)104 void PictureLayer::SetNeedsDisplayRect(const gfx::Rect& layer_rect) {
105   DCHECK(!layer_tree_host() || !layer_tree_host()->in_paint_layer_contents());
106   if (recording_source_)
107     recording_source_->SetNeedsDisplayRect(layer_rect);
108   Layer::SetNeedsDisplayRect(layer_rect);
109 }
110 
Update()111 bool PictureLayer::Update() {
112   update_source_frame_number_ = layer_tree_host()->SourceFrameNumber();
113   bool updated = Layer::Update();
114 
115   gfx::Size layer_size = bounds();
116 
117   recording_source_->SetBackgroundColor(SafeOpaqueBackgroundColor());
118   recording_source_->SetRequiresClear(
119       !contents_opaque() &&
120       !picture_layer_inputs_.client->FillsBoundsCompletely());
121 
122   TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("cc.debug"), "PictureLayer::Update",
123                "source_frame_number", layer_tree_host()->SourceFrameNumber());
124   devtools_instrumentation::ScopedLayerTreeTask update_layer(
125       devtools_instrumentation::kUpdateLayer, id(), layer_tree_host()->GetId());
126 
127   // UpdateAndExpandInvalidation will give us an invalidation that covers
128   // anything not explicitly recorded in this frame. We give this region
129   // to the impl side so that it drops tiles that may not have a recording
130   // for them.
131   DCHECK(picture_layer_inputs_.client);
132 
133   auto recorded_viewport = picture_layer_inputs_.client->PaintableRegion();
134 
135   updated |= recording_source_->UpdateAndExpandInvalidation(
136       &last_updated_invalidation_, layer_size, recorded_viewport);
137 
138   if (updated) {
139     picture_layer_inputs_.display_list =
140         picture_layer_inputs_.client->PaintContentsToDisplayList(
141             ContentLayerClient::PAINTING_BEHAVIOR_NORMAL);
142     picture_layer_inputs_.painter_reported_memory_usage =
143         picture_layer_inputs_.client->GetApproximateUnsharedMemoryUsage();
144     recording_source_->UpdateDisplayItemList(
145         picture_layer_inputs_.display_list,
146         picture_layer_inputs_.painter_reported_memory_usage,
147         layer_tree_host()->recording_scale_factor());
148 
149     SetNeedsPushProperties();
150     IncreasePaintCount();
151   } else {
152     // If this invalidation did not affect the recording source, then it can be
153     // cleared as an optimization.
154     last_updated_invalidation_.Clear();
155   }
156 
157   return updated;
158 }
159 
GetPicture() const160 sk_sp<SkPicture> PictureLayer::GetPicture() const {
161   // We could either flatten the RecordingSource into a single SkPicture, or
162   // paint a fresh one depending on what we intend to do with it.  For now we
163   // just paint a fresh one to get consistent results.
164   if (!DrawsContent())
165     return nullptr;
166 
167   gfx::Size layer_size = bounds();
168   RecordingSource recording_source;
169   Region recording_invalidation;
170 
171   gfx::Rect new_recorded_viewport =
172       picture_layer_inputs_.client->PaintableRegion();
173   scoped_refptr<DisplayItemList> display_list =
174       picture_layer_inputs_.client->PaintContentsToDisplayList(
175           ContentLayerClient::PAINTING_BEHAVIOR_NORMAL);
176   size_t painter_reported_memory_usage =
177       picture_layer_inputs_.client->GetApproximateUnsharedMemoryUsage();
178 
179   recording_source.UpdateAndExpandInvalidation(
180       &recording_invalidation, layer_size, new_recorded_viewport);
181   recording_source.UpdateDisplayItemList(
182       display_list, painter_reported_memory_usage,
183       layer_tree_host()->recording_scale_factor());
184 
185   scoped_refptr<RasterSource> raster_source =
186       recording_source.CreateRasterSource();
187   return raster_source->GetFlattenedPicture();
188 }
189 
ClearClient()190 void PictureLayer::ClearClient() {
191   picture_layer_inputs_.client = nullptr;
192   UpdateDrawsContent(HasDrawableContent());
193 }
194 
SetNearestNeighbor(bool nearest_neighbor)195 void PictureLayer::SetNearestNeighbor(bool nearest_neighbor) {
196   if (picture_layer_inputs_.nearest_neighbor == nearest_neighbor)
197     return;
198 
199   picture_layer_inputs_.nearest_neighbor = nearest_neighbor;
200   SetNeedsCommit();
201 }
202 
SetTransformedRasterizationAllowed(bool allowed)203 void PictureLayer::SetTransformedRasterizationAllowed(bool allowed) {
204   if (picture_layer_inputs_.transformed_rasterization_allowed == allowed)
205     return;
206 
207   picture_layer_inputs_.transformed_rasterization_allowed = allowed;
208   SetNeedsCommit();
209 }
210 
HasDrawableContent() const211 bool PictureLayer::HasDrawableContent() const {
212   return picture_layer_inputs_.client && Layer::HasDrawableContent();
213 }
214 
SetIsBackdropFilterMask(bool is_backdrop_filter_mask)215 void PictureLayer::SetIsBackdropFilterMask(bool is_backdrop_filter_mask) {
216   if (picture_layer_inputs_.is_backdrop_filter_mask == is_backdrop_filter_mask)
217     return;
218 
219   picture_layer_inputs_.is_backdrop_filter_mask = is_backdrop_filter_mask;
220   SetNeedsCommit();
221 }
222 
RunMicroBenchmark(MicroBenchmark * benchmark)223 void PictureLayer::RunMicroBenchmark(MicroBenchmark* benchmark) {
224   benchmark->RunOnLayer(this);
225 }
226 
CaptureContent(const gfx::Rect & rect,std::vector<NodeId> * content)227 void PictureLayer::CaptureContent(const gfx::Rect& rect,
228                                   std::vector<NodeId>* content) {
229   if (!DrawsContent())
230     return;
231 
232   const DisplayItemList* display_item_list = GetDisplayItemList();
233   if (!display_item_list)
234     return;
235 
236   // We could run into this situation as CaptureContent could start at any time.
237   if (transform_tree_index() == TransformTree::kInvalidNodeId)
238     return;
239 
240   gfx::Transform inverse_screen_space_transform;
241   if (!ScreenSpaceTransform().GetInverse(&inverse_screen_space_transform))
242     return;
243   gfx::Rect transformed = MathUtil::ProjectEnclosingClippedRect(
244       inverse_screen_space_transform, rect);
245 
246   transformed.Intersect(gfx::Rect(bounds()));
247   if (transformed.IsEmpty())
248     return;
249 
250   display_item_list->CaptureContent(transformed, content);
251 }
252 
DropRecordingSourceContentIfInvalid()253 void PictureLayer::DropRecordingSourceContentIfInvalid() {
254   int source_frame_number = layer_tree_host()->SourceFrameNumber();
255   gfx::Size recording_source_bounds = recording_source_->GetSize();
256 
257   gfx::Size layer_bounds = bounds();
258 
259   // If update called, then recording source size must match bounds pushed to
260   // impl layer.
261   DCHECK(update_source_frame_number_ != source_frame_number ||
262          layer_bounds == recording_source_bounds)
263       << " bounds " << layer_bounds.ToString() << " recording source "
264       << recording_source_bounds.ToString();
265 
266   if (update_source_frame_number_ != source_frame_number &&
267       recording_source_bounds != layer_bounds) {
268     // Update may not get called for the layer (if it's not in the viewport
269     // for example), even though it has resized making the recording source no
270     // longer valid. In this case just destroy the recording source.
271     recording_source_->SetEmptyBounds();
272     picture_layer_inputs_.display_list = nullptr;
273     picture_layer_inputs_.painter_reported_memory_usage = 0;
274   }
275 }
276 
ShouldUseTransformedRasterization() const277 bool PictureLayer::ShouldUseTransformedRasterization() const {
278   if (!picture_layer_inputs_.transformed_rasterization_allowed)
279     return false;
280 
281   // Background color overfill is undesirable with transformed rasterization.
282   // However, without background overfill, the tiles will be non-opaque on
283   // external edges, and layer opaque region can't be computed in layer space
284   // due to rounding under extreme scaling. This defeats many opaque layer
285   // optimization. Prefer optimization over quality for this particular case.
286   if (contents_opaque())
287     return false;
288 
289   const TransformTree& transform_tree =
290       layer_tree_host()->property_trees()->transform_tree;
291   DCHECK(!transform_tree.needs_update());
292   auto* transform_node = transform_tree.Node(transform_tree_index());
293   DCHECK(transform_node);
294   // TODO(pdr): This is a workaround for https://crbug.com/708951 to avoid
295   // crashing when there's no transform node. This workaround should be removed.
296   if (!transform_node)
297     return false;
298 
299   if (transform_node->to_screen_is_potentially_animated)
300     return false;
301 
302   const gfx::Transform& to_screen =
303       transform_tree.ToScreen(transform_tree_index());
304   if (!to_screen.IsScaleOrTranslation())
305     return false;
306 
307   float origin_x =
308       to_screen.matrix().getFloat(0, 3) + offset_to_transform_parent().x();
309   float origin_y =
310       to_screen.matrix().getFloat(1, 3) + offset_to_transform_parent().y();
311   if (origin_x - floorf(origin_x) == 0.f && origin_y - floorf(origin_y) == 0.f)
312     return false;
313 
314   return true;
315 }
316 
GetDisplayItemList()317 const DisplayItemList* PictureLayer::GetDisplayItemList() {
318   return picture_layer_inputs_.display_list.get();
319 }
320 
321 }  // namespace cc
322