OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "cc/layers/picture_layer.h" | 5 #include "cc/layers/picture_layer.h" |
6 | 6 |
7 #include "base/auto_reset.h" | 7 #include "base/auto_reset.h" |
8 #include "cc/layers/content_layer_client.h" | 8 #include "cc/layers/content_layer_client.h" |
9 #include "cc/layers/picture_layer_impl.h" | 9 #include "cc/layers/picture_layer_impl.h" |
| 10 #include "cc/resources/picture_pile.h" |
10 #include "cc/trees/layer_tree_impl.h" | 11 #include "cc/trees/layer_tree_impl.h" |
11 #include "third_party/skia/include/core/SkPictureRecorder.h" | 12 #include "third_party/skia/include/core/SkPictureRecorder.h" |
12 #include "ui/gfx/geometry/rect_conversions.h" | 13 #include "ui/gfx/geometry/rect_conversions.h" |
13 | 14 |
14 namespace cc { | 15 namespace cc { |
15 | 16 |
16 scoped_refptr<PictureLayer> PictureLayer::Create(ContentLayerClient* client) { | 17 scoped_refptr<PictureLayer> PictureLayer::Create(ContentLayerClient* client) { |
17 return make_scoped_refptr(new PictureLayer(client)); | 18 return make_scoped_refptr(new PictureLayer(client)); |
18 } | 19 } |
19 | 20 |
20 PictureLayer::PictureLayer(ContentLayerClient* client) | 21 PictureLayer::PictureLayer(ContentLayerClient* client) |
21 : client_(client), | 22 : client_(client), |
| 23 recording_source_(new PicturePile), |
22 instrumentation_object_tracker_(id()), | 24 instrumentation_object_tracker_(id()), |
23 update_source_frame_number_(-1), | 25 update_source_frame_number_(-1), |
24 can_use_lcd_text_last_frame_(can_use_lcd_text()) { | 26 can_use_lcd_text_last_frame_(can_use_lcd_text()) { |
25 } | 27 } |
26 | 28 |
27 PictureLayer::~PictureLayer() { | 29 PictureLayer::~PictureLayer() { |
28 } | 30 } |
29 | 31 |
30 scoped_ptr<LayerImpl> PictureLayer::CreateLayerImpl(LayerTreeImpl* tree_impl) { | 32 scoped_ptr<LayerImpl> PictureLayer::CreateLayerImpl(LayerTreeImpl* tree_impl) { |
31 return PictureLayerImpl::Create(tree_impl, id()); | 33 return PictureLayerImpl::Create(tree_impl, id()); |
32 } | 34 } |
33 | 35 |
34 void PictureLayer::PushPropertiesTo(LayerImpl* base_layer) { | 36 void PictureLayer::PushPropertiesTo(LayerImpl* base_layer) { |
35 Layer::PushPropertiesTo(base_layer); | 37 Layer::PushPropertiesTo(base_layer); |
36 PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer); | 38 PictureLayerImpl* layer_impl = static_cast<PictureLayerImpl*>(base_layer); |
37 | 39 |
38 int source_frame_number = layer_tree_host()->source_frame_number(); | 40 int source_frame_number = layer_tree_host()->source_frame_number(); |
39 gfx::Size impl_bounds = layer_impl->bounds(); | 41 gfx::Size impl_bounds = layer_impl->bounds(); |
40 gfx::Size pile_bounds = pile_.tiling_size(); | 42 gfx::Size recording_source_bounds = recording_source_->GetSize(); |
41 | 43 |
42 // If update called, then pile size must match bounds pushed to impl layer. | 44 // If update called, then recording source size must match bounds pushed to |
| 45 // impl layer. |
43 DCHECK_IMPLIES(update_source_frame_number_ == source_frame_number, | 46 DCHECK_IMPLIES(update_source_frame_number_ == source_frame_number, |
44 impl_bounds == pile_bounds) | 47 impl_bounds == recording_source_bounds) |
45 << " bounds " << impl_bounds.ToString() << " pile " | 48 << " bounds " << impl_bounds.ToString() << " recording source " |
46 << pile_bounds.ToString(); | 49 << recording_source_bounds.ToString(); |
47 | 50 |
48 if (update_source_frame_number_ != source_frame_number && | 51 if (update_source_frame_number_ != source_frame_number && |
49 pile_bounds != impl_bounds) { | 52 recording_source_bounds != impl_bounds) { |
50 // Update may not get called for the layer (if it's not in the viewport | 53 // Update may not get called for the layer (if it's not in the viewport |
51 // for example, even though it has resized making the pile no longer | 54 // for example, even though it has resized making the recording source no |
52 // valid. In this case just destroy the pile. | 55 // longer valid. In this case just destroy the recording source. |
53 pile_.SetEmptyBounds(); | 56 recording_source_->SetEmptyBounds(); |
54 } | 57 } |
55 | 58 |
56 // Unlike other properties, invalidation must always be set on layer_impl. | 59 // Unlike other properties, invalidation must always be set on layer_impl. |
57 // See PictureLayerImpl::PushPropertiesTo for more details. | 60 // See PictureLayerImpl::PushPropertiesTo for more details. |
58 layer_impl->invalidation_.Clear(); | 61 layer_impl->invalidation_.Clear(); |
59 layer_impl->invalidation_.Swap(&pile_invalidation_); | 62 layer_impl->invalidation_.Swap(&recording_invalidation_); |
60 layer_impl->UpdatePile(PicturePileImpl::CreateFromOther(&pile_)); | 63 layer_impl->UpdateRasterSource(recording_source_->CreateRasterSource()); |
61 } | 64 } |
62 | 65 |
63 void PictureLayer::SetLayerTreeHost(LayerTreeHost* host) { | 66 void PictureLayer::SetLayerTreeHost(LayerTreeHost* host) { |
64 Layer::SetLayerTreeHost(host); | 67 Layer::SetLayerTreeHost(host); |
65 if (host) { | 68 if (host) { |
66 pile_.SetMinContentsScale(host->settings().minimum_contents_scale); | 69 // TODO(hendrikw): Perhaps use and initialization function to do this work. |
67 pile_.SetTileGridSize(host->settings().default_tile_grid_size); | 70 recording_source_->SetMinContentsScale( |
68 pile_.set_slow_down_raster_scale_factor( | 71 host->settings().minimum_contents_scale); |
| 72 recording_source_->SetTileGridSize(host->settings().default_tile_grid_size); |
| 73 recording_source_->SetSlowdownRasterScaleFactor( |
69 host->debug_state().slow_down_raster_scale_factor); | 74 host->debug_state().slow_down_raster_scale_factor); |
70 pile_.set_show_debug_picture_borders( | |
71 host->debug_state().show_picture_borders); | |
72 } | 75 } |
73 } | 76 } |
74 | 77 |
75 void PictureLayer::SetNeedsDisplayRect(const gfx::Rect& layer_rect) { | 78 void PictureLayer::SetNeedsDisplayRect(const gfx::Rect& layer_rect) { |
76 if (!layer_rect.IsEmpty()) { | 79 if (!layer_rect.IsEmpty()) { |
77 // Clamp invalidation to the layer bounds. | 80 // Clamp invalidation to the layer bounds. |
78 pending_invalidation_.Union( | 81 pending_invalidation_.Union( |
79 gfx::IntersectRects(layer_rect, gfx::Rect(bounds()))); | 82 gfx::IntersectRects(layer_rect, gfx::Rect(bounds()))); |
80 } | 83 } |
81 Layer::SetNeedsDisplayRect(layer_rect); | 84 Layer::SetNeedsDisplayRect(layer_rect); |
82 } | 85 } |
83 | 86 |
84 bool PictureLayer::Update(ResourceUpdateQueue* queue, | 87 bool PictureLayer::Update(ResourceUpdateQueue* queue, |
85 const OcclusionTracker<Layer>* occlusion) { | 88 const OcclusionTracker<Layer>* occlusion) { |
86 update_source_frame_number_ = layer_tree_host()->source_frame_number(); | 89 update_source_frame_number_ = layer_tree_host()->source_frame_number(); |
87 bool updated = Layer::Update(queue, occlusion); | 90 bool updated = Layer::Update(queue, occlusion); |
88 | 91 |
89 { | 92 { |
90 base::AutoReset<bool> ignore_set_needs_commit(&ignore_set_needs_commit_, | 93 base::AutoReset<bool> ignore_set_needs_commit(&ignore_set_needs_commit_, |
91 true); | 94 true); |
92 UpdateCanUseLCDText(); | 95 UpdateCanUseLCDText(); |
93 } | 96 } |
94 | 97 |
95 gfx::Rect visible_layer_rect = gfx::ScaleToEnclosingRect( | 98 gfx::Rect visible_layer_rect = gfx::ScaleToEnclosingRect( |
96 visible_content_rect(), 1.f / contents_scale_x()); | 99 visible_content_rect(), 1.f / contents_scale_x()); |
97 gfx::Size layer_size = paint_properties().bounds; | 100 gfx::Size layer_size = paint_properties().bounds; |
98 | 101 |
99 if (last_updated_visible_content_rect_ == visible_content_rect() && | 102 if (last_updated_visible_content_rect_ == visible_content_rect() && |
100 pile_.tiling_size() == layer_size && pending_invalidation_.IsEmpty()) { | 103 recording_source_->GetSize() == layer_size && |
| 104 pending_invalidation_.IsEmpty()) { |
101 // Only early out if the visible content rect of this layer hasn't changed. | 105 // Only early out if the visible content rect of this layer hasn't changed. |
102 return updated; | 106 return updated; |
103 } | 107 } |
104 | 108 |
105 TRACE_EVENT1("cc", "PictureLayer::Update", | 109 TRACE_EVENT1("cc", "PictureLayer::Update", |
106 "source_frame_number", | 110 "source_frame_number", |
107 layer_tree_host()->source_frame_number()); | 111 layer_tree_host()->source_frame_number()); |
108 devtools_instrumentation::ScopedLayerTreeTask update_layer( | 112 devtools_instrumentation::ScopedLayerTreeTask update_layer( |
109 devtools_instrumentation::kUpdateLayer, id(), layer_tree_host()->id()); | 113 devtools_instrumentation::kUpdateLayer, id(), layer_tree_host()->id()); |
110 | 114 |
111 // Calling paint in WebKit can sometimes cause invalidations, so save | 115 // Calling paint in WebKit can sometimes cause invalidations, so save |
112 // off the invalidation prior to calling update. | 116 // off the invalidation prior to calling update. |
113 pending_invalidation_.Swap(&pile_invalidation_); | 117 pending_invalidation_.Swap(&recording_invalidation_); |
114 pending_invalidation_.Clear(); | 118 pending_invalidation_.Clear(); |
115 | 119 |
116 if (layer_tree_host()->settings().record_full_layer) { | 120 if (layer_tree_host()->settings().record_full_layer) { |
117 // Workaround for http://crbug.com/235910 - to retain backwards compat | 121 // Workaround for http://crbug.com/235910 - to retain backwards compat |
118 // the full page content must always be provided in the picture layer. | 122 // the full page content must always be provided in the picture layer. |
119 visible_layer_rect = gfx::Rect(layer_size); | 123 visible_layer_rect = gfx::Rect(layer_size); |
120 } | 124 } |
121 | 125 |
122 // UpdateAndExpandInvalidation will give us an invalidation that covers | 126 // UpdateAndExpandInvalidation will give us an invalidation that covers |
123 // anything not explicitly recorded in this frame. We give this region | 127 // anything not explicitly recorded in this frame. We give this region |
124 // to the impl side so that it drops tiles that may not have a recording | 128 // to the impl side so that it drops tiles that may not have a recording |
125 // for them. | 129 // for them. |
126 DCHECK(client_); | 130 DCHECK(client_); |
127 updated |= | 131 updated |= recording_source_->UpdateAndExpandInvalidation( |
128 pile_.UpdateAndExpandInvalidation(client_, | 132 client_, &recording_invalidation_, SafeOpaqueBackgroundColor(), |
129 &pile_invalidation_, | 133 contents_opaque(), client_->FillsBoundsCompletely(), layer_size, |
130 SafeOpaqueBackgroundColor(), | 134 visible_layer_rect, update_source_frame_number_, |
131 contents_opaque(), | 135 Picture::RECORD_NORMALLY); |
132 client_->FillsBoundsCompletely(), | |
133 layer_size, | |
134 visible_layer_rect, | |
135 update_source_frame_number_, | |
136 Picture::RECORD_NORMALLY, | |
137 rendering_stats_instrumentation()); | |
138 last_updated_visible_content_rect_ = visible_content_rect(); | 136 last_updated_visible_content_rect_ = visible_content_rect(); |
139 | 137 |
140 if (updated) { | 138 if (updated) { |
141 SetNeedsPushProperties(); | 139 SetNeedsPushProperties(); |
142 } else { | 140 } else { |
143 // If this invalidation did not affect the pile, then it can be cleared as | 141 // If this invalidation did not affect the recording source, then it can be |
144 // an optimization. | 142 // cleared as an optimization. |
145 pile_invalidation_.Clear(); | 143 recording_invalidation_.Clear(); |
146 } | 144 } |
147 | 145 |
148 return updated; | 146 return updated; |
149 } | 147 } |
150 | 148 |
151 void PictureLayer::SetIsMask(bool is_mask) { | 149 void PictureLayer::SetIsMask(bool is_mask) { |
152 pile_.set_is_mask(is_mask); | 150 recording_source_->SetIsMask(is_mask); |
153 } | 151 } |
154 | 152 |
155 bool PictureLayer::SupportsLCDText() const { | 153 bool PictureLayer::SupportsLCDText() const { |
156 return true; | 154 return true; |
157 } | 155 } |
158 | 156 |
159 void PictureLayer::UpdateCanUseLCDText() { | 157 void PictureLayer::UpdateCanUseLCDText() { |
160 if (can_use_lcd_text_last_frame_ == can_use_lcd_text()) | 158 if (can_use_lcd_text_last_frame_ == can_use_lcd_text()) |
161 return; | 159 return; |
162 | 160 |
163 can_use_lcd_text_last_frame_ = can_use_lcd_text(); | 161 can_use_lcd_text_last_frame_ = can_use_lcd_text(); |
164 if (client_) | 162 if (client_) |
165 client_->DidChangeLayerCanUseLCDText(); | 163 client_->DidChangeLayerCanUseLCDText(); |
166 } | 164 } |
167 | 165 |
168 skia::RefPtr<SkPicture> PictureLayer::GetPicture() const { | 166 skia::RefPtr<SkPicture> PictureLayer::GetPicture() const { |
169 // We could either flatten the PicturePile into a single SkPicture, | 167 // We could either flatten the RecordingSource into a single SkPicture, |
170 // or paint a fresh one depending on what we intend to do with the | 168 // or paint a fresh one depending on what we intend to do with the |
171 // picture. For now we just paint a fresh one to get consistent results. | 169 // picture. For now we just paint a fresh one to get consistent results. |
172 if (!DrawsContent()) | 170 if (!DrawsContent()) |
173 return skia::RefPtr<SkPicture>(); | 171 return skia::RefPtr<SkPicture>(); |
174 | 172 |
175 int width = bounds().width(); | 173 int width = bounds().width(); |
176 int height = bounds().height(); | 174 int height = bounds().height(); |
177 | 175 |
178 SkPictureRecorder recorder; | 176 SkPictureRecorder recorder; |
179 SkCanvas* canvas = recorder.beginRecording(width, height, nullptr, 0); | 177 SkCanvas* canvas = recorder.beginRecording(width, height, nullptr, 0); |
180 client_->PaintContents(canvas, | 178 client_->PaintContents(canvas, |
181 gfx::Rect(width, height), | 179 gfx::Rect(width, height), |
182 ContentLayerClient::GRAPHICS_CONTEXT_ENABLED); | 180 ContentLayerClient::GRAPHICS_CONTEXT_ENABLED); |
183 skia::RefPtr<SkPicture> picture = skia::AdoptRef(recorder.endRecording()); | 181 skia::RefPtr<SkPicture> picture = skia::AdoptRef(recorder.endRecording()); |
184 return picture; | 182 return picture; |
185 } | 183 } |
186 | 184 |
187 bool PictureLayer::IsSuitableForGpuRasterization() const { | 185 bool PictureLayer::IsSuitableForGpuRasterization() const { |
188 return pile_.is_suitable_for_gpu_rasterization(); | 186 return recording_source_->IsSuitableForGpuRasterization(); |
189 } | 187 } |
190 | 188 |
191 void PictureLayer::ClearClient() { | 189 void PictureLayer::ClearClient() { |
192 client_ = nullptr; | 190 client_ = nullptr; |
193 UpdateDrawsContent(HasDrawableContent()); | 191 UpdateDrawsContent(HasDrawableContent()); |
194 } | 192 } |
195 | 193 |
196 bool PictureLayer::HasDrawableContent() const { | 194 bool PictureLayer::HasDrawableContent() const { |
197 return client_ && Layer::HasDrawableContent(); | 195 return client_ && Layer::HasDrawableContent(); |
198 } | 196 } |
199 | 197 |
200 void PictureLayer::RunMicroBenchmark(MicroBenchmark* benchmark) { | 198 void PictureLayer::RunMicroBenchmark(MicroBenchmark* benchmark) { |
201 benchmark->RunOnLayer(this); | 199 benchmark->RunOnLayer(this); |
202 } | 200 } |
203 | 201 |
204 } // namespace cc | 202 } // namespace cc |
OLD | NEW |