OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/playback/display_item_list.h" | 5 #include "cc/playback/display_item_list.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/numerics/safe_conversions.h" | 9 #include "base/numerics/safe_conversions.h" |
10 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
11 #include "base/trace_event/trace_event.h" | 11 #include "base/trace_event/trace_event.h" |
12 #include "base/trace_event/trace_event_argument.h" | 12 #include "base/trace_event/trace_event_argument.h" |
13 #include "cc/base/math_util.h" | 13 #include "cc/base/math_util.h" |
14 #include "cc/debug/picture_debug_util.h" | 14 #include "cc/debug/picture_debug_util.h" |
15 #include "cc/debug/traced_display_item_list.h" | 15 #include "cc/debug/traced_display_item_list.h" |
16 #include "cc/debug/traced_value.h" | 16 #include "cc/debug/traced_value.h" |
17 #include "cc/playback/display_item_list_settings.h" | 17 #include "cc/playback/display_item_list_settings.h" |
18 #include "cc/playback/display_item_proto_factory.h" | 18 #include "cc/playback/display_item_proto_factory.h" |
19 #include "cc/playback/drawing_display_item.h" | |
19 #include "cc/playback/largest_display_item.h" | 20 #include "cc/playback/largest_display_item.h" |
20 #include "cc/proto/display_item.pb.h" | 21 #include "cc/proto/display_item.pb.h" |
21 #include "cc/proto/gfx_conversions.h" | 22 #include "cc/proto/gfx_conversions.h" |
22 #include "third_party/skia/include/core/SkCanvas.h" | 23 #include "third_party/skia/include/core/SkCanvas.h" |
23 #include "third_party/skia/include/core/SkPictureRecorder.h" | 24 #include "third_party/skia/include/core/SkPictureRecorder.h" |
24 #include "third_party/skia/include/utils/SkPictureUtils.h" | 25 #include "third_party/skia/include/utils/SkPictureUtils.h" |
25 #include "ui/gfx/geometry/rect.h" | 26 #include "ui/gfx/geometry/rect.h" |
26 #include "ui/gfx/skia_util.h" | 27 #include "ui/gfx/skia_util.h" |
27 | 28 |
28 namespace cc { | 29 namespace cc { |
(...skipping 25 matching lines...) Expand all Loading... | |
54 | 55 |
55 scoped_refptr<DisplayItemList> DisplayItemList::CreateFromProto( | 56 scoped_refptr<DisplayItemList> DisplayItemList::CreateFromProto( |
56 const proto::DisplayItemList& proto) { | 57 const proto::DisplayItemList& proto) { |
57 gfx::Rect layer_rect = ProtoToRect(proto.layer_rect()); | 58 gfx::Rect layer_rect = ProtoToRect(proto.layer_rect()); |
58 scoped_refptr<DisplayItemList> list = | 59 scoped_refptr<DisplayItemList> list = |
59 DisplayItemList::Create(ProtoToRect(proto.layer_rect()), | 60 DisplayItemList::Create(ProtoToRect(proto.layer_rect()), |
60 DisplayItemListSettings(proto.settings())); | 61 DisplayItemListSettings(proto.settings())); |
61 | 62 |
62 for (int i = 0; i < proto.items_size(); i++) { | 63 for (int i = 0; i < proto.items_size(); i++) { |
63 const proto::DisplayItem& item_proto = proto.items(i); | 64 const proto::DisplayItem& item_proto = proto.items(i); |
64 DisplayItem* item = DisplayItemProtoFactory::AllocateAndConstruct( | 65 DisplayItemProtoFactory::AllocateAndConstruct(layer_rect, list.get(), |
65 layer_rect, list.get(), item_proto); | 66 item_proto); |
66 if (item) | |
67 item->FromProtobuf(item_proto); | |
68 } | 67 } |
69 | 68 |
70 return list; | 69 return list; |
71 } | 70 } |
72 | 71 |
73 DisplayItemList::DisplayItemList(gfx::Rect layer_rect, | 72 DisplayItemList::DisplayItemList(gfx::Rect layer_rect, |
74 const DisplayItemListSettings& settings, | 73 const DisplayItemListSettings& settings, |
75 bool retain_individual_display_items) | 74 bool retain_individual_display_items) |
76 : items_(LargestDisplayItemSize(), | 75 : items_(LargestDisplayItemSize(), |
77 LargestDisplayItemSize() * kDefaultNumDisplayItemsToReserve), | 76 LargestDisplayItemSize() * kDefaultNumDisplayItemsToReserve), |
78 settings_(settings), | 77 settings_(settings), |
79 retain_individual_display_items_(retain_individual_display_items), | 78 retain_individual_display_items_(retain_individual_display_items), |
80 layer_rect_(layer_rect), | 79 layer_rect_(layer_rect), |
81 is_suitable_for_gpu_rasterization_(true), | 80 is_suitable_for_gpu_rasterization_(true), |
82 approximate_op_count_(0), | 81 approximate_op_count_(0), |
83 picture_memory_usage_(0), | 82 picture_memory_usage_(0) { |
84 external_memory_usage_(0) { | |
85 #if DCHECK_IS_ON() | |
86 needs_process_ = false; | |
87 #endif | |
88 if (settings_.use_cached_picture) { | 83 if (settings_.use_cached_picture) { |
89 SkRTreeFactory factory; | 84 SkRTreeFactory factory; |
90 recorder_.reset(new SkPictureRecorder()); | 85 recorder_.reset(new SkPictureRecorder()); |
91 canvas_ = skia::SharePtr(recorder_->beginRecording( | 86 canvas_ = skia::SharePtr(recorder_->beginRecording( |
92 layer_rect_.width(), layer_rect_.height(), &factory)); | 87 layer_rect_.width(), layer_rect_.height(), &factory)); |
93 canvas_->translate(-layer_rect_.x(), -layer_rect_.y()); | 88 canvas_->translate(-layer_rect_.x(), -layer_rect_.y()); |
94 canvas_->clipRect(gfx::RectToSkRect(layer_rect_)); | 89 canvas_->clipRect(gfx::RectToSkRect(layer_rect_)); |
95 } | 90 } |
96 } | 91 } |
97 | 92 |
(...skipping 10 matching lines...) Expand all Loading... | |
108 | 103 |
109 DCHECK_EQ(0, proto->items_size()); | 104 DCHECK_EQ(0, proto->items_size()); |
110 for (const auto& item : items_) | 105 for (const auto& item : items_) |
111 item.ToProtobuf(proto->add_items()); | 106 item.ToProtobuf(proto->add_items()); |
112 } | 107 } |
113 | 108 |
114 void DisplayItemList::Raster(SkCanvas* canvas, | 109 void DisplayItemList::Raster(SkCanvas* canvas, |
115 SkPicture::AbortCallback* callback, | 110 SkPicture::AbortCallback* callback, |
116 const gfx::Rect& canvas_target_playback_rect, | 111 const gfx::Rect& canvas_target_playback_rect, |
117 float contents_scale) const { | 112 float contents_scale) const { |
118 DCHECK(ProcessAppendedItemsCalled()); | |
119 if (!settings_.use_cached_picture) { | 113 if (!settings_.use_cached_picture) { |
120 canvas->save(); | 114 canvas->save(); |
121 canvas->scale(contents_scale, contents_scale); | 115 canvas->scale(contents_scale, contents_scale); |
122 for (const auto& item : items_) | 116 for (const auto& item : items_) |
123 item.Raster(canvas, canvas_target_playback_rect, callback); | 117 item.Raster(canvas, canvas_target_playback_rect, callback); |
124 canvas->restore(); | 118 canvas->restore(); |
125 } else { | 119 } else { |
126 DCHECK(picture_); | 120 DCHECK(picture_); |
127 | 121 |
128 canvas->save(); | 122 canvas->save(); |
129 canvas->scale(contents_scale, contents_scale); | 123 canvas->scale(contents_scale, contents_scale); |
130 canvas->translate(layer_rect_.x(), layer_rect_.y()); | 124 canvas->translate(layer_rect_.x(), layer_rect_.y()); |
131 if (callback) { | 125 if (callback) { |
132 // If we have a callback, we need to call |draw()|, |drawPicture()| | 126 // If we have a callback, we need to call |draw()|, |drawPicture()| |
133 // doesn't take a callback. This is used by |AnalysisCanvas| to early | 127 // doesn't take a callback. This is used by |AnalysisCanvas| to early |
134 // out. | 128 // out. |
135 picture_->playback(canvas, callback); | 129 picture_->playback(canvas, callback); |
136 } else { | 130 } else { |
137 // Prefer to call |drawPicture()| on the canvas since it could place the | 131 // Prefer to call |drawPicture()| on the canvas since it could place the |
138 // entire picture on the canvas instead of parsing the skia operations. | 132 // entire picture on the canvas instead of parsing the skia operations. |
139 canvas->drawPicture(picture_.get()); | 133 canvas->drawPicture(picture_.get()); |
140 } | 134 } |
141 canvas->restore(); | 135 canvas->restore(); |
142 } | 136 } |
143 } | 137 } |
144 | 138 |
145 void DisplayItemList::ProcessAppendedItemsOnTheFly() { | 139 void DisplayItemList::ProcessAppendedItem(const DisplayItem* item) { |
146 if (retain_individual_display_items_) | 140 if (settings_.use_cached_picture) { |
147 return; | 141 DCHECK(canvas_); |
148 if (items_.size() >= kDefaultNumDisplayItemsToReserve) { | 142 item->Raster(canvas_.get(), gfx::Rect(), nullptr); |
149 ProcessAppendedItems(); | |
150 // This function exists to keep the |items_| from growing indefinitely if | |
151 // we're not going to store them anyway. So the items better be deleted | |
152 // after |items_| grows too large and we process it. | |
153 DCHECK(items_.empty()); | |
154 } | 143 } |
155 } | 144 if (!retain_individual_display_items_) { |
156 | 145 items_.Clear(); |
157 void DisplayItemList::ProcessAppendedItems() { | |
158 #if DCHECK_IS_ON() | |
159 needs_process_ = false; | |
160 #endif | |
161 for (const DisplayItem& item : items_) { | |
162 if (settings_.use_cached_picture) { | |
163 // When using a cached picture we will calculate gpu suitability on the | |
164 // entire cached picture instead of the items. This is more permissive | |
165 // since none of the items might individually trigger a veto even though | |
166 // they collectively have enough "bad" operations that a corresponding | |
167 // Picture would get vetoed. See crbug.com/513016. | |
168 DCHECK(canvas_); | |
169 approximate_op_count_ += item.approximate_op_count(); | |
170 item.Raster(canvas_.get(), gfx::Rect(), nullptr); | |
171 } else { | |
172 is_suitable_for_gpu_rasterization_ &= | |
173 item.is_suitable_for_gpu_rasterization(); | |
174 approximate_op_count_ += item.approximate_op_count(); | |
175 } | |
176 | |
177 if (retain_individual_display_items_) { | |
178 // Warning: this double-counts SkPicture data if use_cached_picture is | |
179 // also true. | |
180 external_memory_usage_ += item.external_memory_usage(); | |
181 } | |
182 } | 146 } |
183 | |
184 if (!retain_individual_display_items_) | |
185 items_.Clear(); | |
186 } | 147 } |
187 | 148 |
188 void DisplayItemList::RasterIntoCanvas(const DisplayItem& item) { | 149 void DisplayItemList::RasterIntoCanvas(const DisplayItem& item) { |
189 DCHECK(canvas_); | 150 DCHECK(canvas_); |
190 DCHECK(!retain_individual_display_items_); | 151 DCHECK(!retain_individual_display_items_); |
191 approximate_op_count_ += item.approximate_op_count(); | |
192 | 152 |
193 item.Raster(canvas_.get(), gfx::Rect(), nullptr); | 153 item.Raster(canvas_.get(), gfx::Rect(), nullptr); |
194 } | 154 } |
195 | 155 |
196 bool DisplayItemList::RetainsIndividualDisplayItems() const { | 156 bool DisplayItemList::RetainsIndividualDisplayItems() const { |
197 return retain_individual_display_items_; | 157 return retain_individual_display_items_; |
198 } | 158 } |
199 | 159 |
200 void DisplayItemList::RemoveLast() { | |
201 // We cannot remove the last item if it has been squashed into a picture. | |
202 // The last item should not have been handled by ProcessAppendedItems, so we | |
203 // don't need to remove it from approximate_op_count_, etc. | |
204 DCHECK(retain_individual_display_items_); | |
205 DCHECK(!settings_.use_cached_picture); | |
206 items_.RemoveLast(); | |
207 } | |
208 | |
209 void DisplayItemList::Finalize() { | 160 void DisplayItemList::Finalize() { |
danakj
2015/12/08 19:18:15
Do we actually need the Finalize method after this
enne (OOO)
2015/12/08 19:47:27
Yes. We can remove Finalize once we no longer use
| |
210 // TODO(wkorman): Uncomment the assert below once we've investigated | 161 // TODO(wkorman): Uncomment the assert below once we've investigated |
211 // and resolved issues. http://crbug.com/557905 | 162 // and resolved issues. http://crbug.com/557905 |
212 // DCHECK_EQ(items_.size(), visual_rects_.size()); | 163 // DCHECK_EQ(items_.size(), visual_rects_.size()); |
213 | 164 |
214 // TODO(vmpstr): Build and make use of an RTree from the visual | 165 // TODO(vmpstr): Build and make use of an RTree from the visual |
215 // rects. For now we just clear them out since we won't ever need | 166 // rects. For now we just clear them out since we won't ever need |
216 // them to stick around post-Finalize. http://crbug.com/527245 | 167 // them to stick around post-Finalize. http://crbug.com/527245 |
217 visual_rects_.clear(); | 168 visual_rects_.clear(); |
218 | 169 |
219 ProcessAppendedItems(); | |
220 | |
221 if (settings_.use_cached_picture) { | 170 if (settings_.use_cached_picture) { |
222 // Convert to an SkPicture for faster rasterization. | 171 // Convert to an SkPicture for faster rasterization. |
223 DCHECK(settings_.use_cached_picture); | 172 DCHECK(settings_.use_cached_picture); |
224 DCHECK(!picture_); | 173 DCHECK(!picture_); |
225 picture_ = skia::AdoptRef(recorder_->endRecordingAsPicture()); | 174 picture_ = skia::AdoptRef(recorder_->endRecordingAsPicture()); |
226 DCHECK(picture_); | 175 DCHECK(picture_); |
227 picture_memory_usage_ = | 176 picture_memory_usage_ = |
228 SkPictureUtils::ApproximateBytesUsed(picture_.get()); | 177 SkPictureUtils::ApproximateBytesUsed(picture_.get()); |
229 recorder_.reset(); | 178 recorder_.reset(); |
230 canvas_.clear(); | 179 canvas_.clear(); |
231 is_suitable_for_gpu_rasterization_ = | |
232 picture_->suitableForGpuRasterization(nullptr); | |
233 } | 180 } |
234 } | 181 } |
235 | 182 |
236 bool DisplayItemList::IsSuitableForGpuRasterization() const { | 183 bool DisplayItemList::IsSuitableForGpuRasterization() const { |
237 DCHECK(ProcessAppendedItemsCalled()); | |
238 return is_suitable_for_gpu_rasterization_; | 184 return is_suitable_for_gpu_rasterization_; |
239 } | 185 } |
240 | 186 |
241 int DisplayItemList::ApproximateOpCount() const { | 187 int DisplayItemList::ApproximateOpCount() const { |
242 DCHECK(ProcessAppendedItemsCalled()); | |
243 return approximate_op_count_; | 188 return approximate_op_count_; |
244 } | 189 } |
245 | 190 |
246 size_t DisplayItemList::ApproximateMemoryUsage() const { | 191 size_t DisplayItemList::ApproximateMemoryUsage() const { |
247 DCHECK(ProcessAppendedItemsCalled()); | |
248 // We double-count in this case. Produce zero to avoid being misleading. | 192 // We double-count in this case. Produce zero to avoid being misleading. |
249 if (settings_.use_cached_picture && retain_individual_display_items_) | 193 if (settings_.use_cached_picture && retain_individual_display_items_) |
250 return 0; | 194 return 0; |
251 | 195 |
252 DCHECK(!settings_.use_cached_picture || picture_); | 196 DCHECK(!settings_.use_cached_picture || picture_); |
253 | 197 |
254 size_t memory_usage = sizeof(*this); | 198 size_t memory_usage = sizeof(*this); |
255 | 199 |
200 size_t external_memory_usage = 0; | |
201 if (retain_individual_display_items_) { | |
202 // Warning: this double-counts SkPicture data if use_cached_picture is | |
203 // also true. | |
204 for (const DisplayItem& item : items_) { | |
danakj
2015/12/08 19:18:14
no auto? :)
| |
205 external_memory_usage += item.ExternalMemoryUsage(); | |
206 } | |
207 } | |
208 | |
256 // Memory outside this class due to |items_|. | 209 // Memory outside this class due to |items_|. |
257 memory_usage += items_.GetCapacityInBytes() + external_memory_usage_; | 210 memory_usage += items_.GetCapacityInBytes() + external_memory_usage; |
258 | 211 |
259 // Memory outside this class due to |picture|. | 212 // Memory outside this class due to |picture|. |
260 memory_usage += picture_memory_usage_; | 213 memory_usage += picture_memory_usage_; |
261 | 214 |
262 // TODO(jbroman): Does anything else owned by this class substantially | 215 // TODO(jbroman): Does anything else owned by this class substantially |
263 // contribute to memory usage? | 216 // contribute to memory usage? |
264 | 217 |
265 return memory_usage; | 218 return memory_usage; |
266 } | 219 } |
267 | 220 |
268 bool DisplayItemList::ShouldBeAnalyzedForSolidColor() const { | 221 bool DisplayItemList::ShouldBeAnalyzedForSolidColor() const { |
269 return ApproximateOpCount() <= kOpCountThatIsOkToAnalyze; | 222 return ApproximateOpCount() <= kOpCountThatIsOkToAnalyze; |
270 } | 223 } |
271 | 224 |
272 scoped_refptr<base::trace_event::ConvertableToTraceFormat> | 225 scoped_refptr<base::trace_event::ConvertableToTraceFormat> |
273 DisplayItemList::AsValue(bool include_items) const { | 226 DisplayItemList::AsValue(bool include_items) const { |
274 DCHECK(ProcessAppendedItemsCalled()); | |
275 scoped_refptr<base::trace_event::TracedValue> state = | 227 scoped_refptr<base::trace_event::TracedValue> state = |
276 new base::trace_event::TracedValue(); | 228 new base::trace_event::TracedValue(); |
277 | 229 |
278 state->BeginDictionary("params"); | 230 state->BeginDictionary("params"); |
279 if (include_items) { | 231 if (include_items) { |
280 state->BeginArray("items"); | 232 state->BeginArray("items"); |
281 size_t item_index = 0; | 233 size_t item_index = 0; |
282 for (const DisplayItem& item : items_) { | 234 for (const DisplayItem& item : items_) { |
283 item.AsValueInto(visual_rects_.size() >= item_index | 235 item.AsValueInto(visual_rects_.size() >= item_index |
284 ? visual_rects_[item_index] | 236 ? visual_rects_[item_index] |
(...skipping 18 matching lines...) Expand all Loading... | |
303 | 255 |
304 std::string b64_picture; | 256 std::string b64_picture; |
305 PictureDebugUtil::SerializeAsBase64(picture.get(), &b64_picture); | 257 PictureDebugUtil::SerializeAsBase64(picture.get(), &b64_picture); |
306 state->SetString("skp64", b64_picture); | 258 state->SetString("skp64", b64_picture); |
307 } | 259 } |
308 | 260 |
309 return state; | 261 return state; |
310 } | 262 } |
311 | 263 |
312 void DisplayItemList::EmitTraceSnapshot() const { | 264 void DisplayItemList::EmitTraceSnapshot() const { |
313 DCHECK(ProcessAppendedItemsCalled()); | |
314 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( | 265 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( |
315 TRACE_DISABLED_BY_DEFAULT("cc.debug.display_items") "," | 266 TRACE_DISABLED_BY_DEFAULT("cc.debug.display_items") "," |
316 TRACE_DISABLED_BY_DEFAULT("cc.debug.picture") "," | 267 TRACE_DISABLED_BY_DEFAULT("cc.debug.picture") "," |
317 TRACE_DISABLED_BY_DEFAULT("devtools.timeline.picture"), | 268 TRACE_DISABLED_BY_DEFAULT("devtools.timeline.picture"), |
318 "cc::DisplayItemList", this, | 269 "cc::DisplayItemList", this, |
319 TracedDisplayItemList::AsTraceableDisplayItemList(this, | 270 TracedDisplayItemList::AsTraceableDisplayItemList(this, |
320 DisplayItemsTracingEnabled())); | 271 DisplayItemsTracingEnabled())); |
321 } | 272 } |
322 | 273 |
323 void DisplayItemList::GenerateDiscardableImagesMetadata() { | 274 void DisplayItemList::GenerateDiscardableImagesMetadata() { |
324 DCHECK(ProcessAppendedItemsCalled()); | |
325 // This should be only called once, and only after CreateAndCacheSkPicture. | 275 // This should be only called once, and only after CreateAndCacheSkPicture. |
326 DCHECK(image_map_.empty()); | 276 DCHECK(image_map_.empty()); |
327 DCHECK(!settings_.use_cached_picture || picture_); | 277 DCHECK(!settings_.use_cached_picture || picture_); |
328 if (settings_.use_cached_picture && !picture_->willPlayBackBitmaps()) | 278 if (settings_.use_cached_picture && !picture_->willPlayBackBitmaps()) |
329 return; | 279 return; |
330 | 280 |
331 // The cached picture is translated by -layer_rect_.origin during record, | 281 // The cached picture is translated by -layer_rect_.origin during record, |
332 // so we need to offset that back in order to get right positioning for | 282 // so we need to offset that back in order to get right positioning for |
333 // images. | 283 // images. |
334 DiscardableImageMap::ScopedMetadataGenerator generator( | 284 DiscardableImageMap::ScopedMetadataGenerator generator( |
335 &image_map_, gfx::Size(layer_rect_.right(), layer_rect_.bottom())); | 285 &image_map_, gfx::Size(layer_rect_.right(), layer_rect_.bottom())); |
336 Raster(generator.canvas(), nullptr, | 286 Raster(generator.canvas(), nullptr, |
337 gfx::Rect(layer_rect_.right(), layer_rect_.bottom()), 1.f); | 287 gfx::Rect(layer_rect_.right(), layer_rect_.bottom()), 1.f); |
338 } | 288 } |
339 | 289 |
340 void DisplayItemList::GetDiscardableImagesInRect( | 290 void DisplayItemList::GetDiscardableImagesInRect( |
341 const gfx::Rect& rect, | 291 const gfx::Rect& rect, |
342 float raster_scale, | 292 float raster_scale, |
343 std::vector<DrawImage>* images) { | 293 std::vector<DrawImage>* images) { |
344 image_map_.GetDiscardableImagesInRect(rect, raster_scale, images); | 294 image_map_.GetDiscardableImagesInRect(rect, raster_scale, images); |
345 } | 295 } |
346 | 296 |
347 } // namespace cc | 297 } // namespace cc |
OLD | NEW |