Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(52)

Side by Side Diff: cc/playback/display_item_list.cc

Issue 2748263002: Move cc::DisplayItemList and related classes into cc/paint/ (Closed)
Patch Set: Merge branch 'master' into ccpaint Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « cc/playback/display_item_list.h ('k') | cc/playback/display_item_list_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "cc/playback/display_item_list.h"
6
7 #include <stddef.h>
8
9 #include <string>
10
11 #include "base/memory/ptr_util.h"
12 #include "base/numerics/safe_conversions.h"
13 #include "base/strings/stringprintf.h"
14 #include "base/trace_event/trace_event.h"
15 #include "base/trace_event/trace_event_argument.h"
16 #include "cc/base/math_util.h"
17 #include "cc/debug/picture_debug_util.h"
18 #include "cc/output/render_surface_filters.h"
19 #include "cc/playback/clip_display_item.h"
20 #include "cc/playback/clip_path_display_item.h"
21 #include "cc/playback/compositing_display_item.h"
22 #include "cc/playback/drawing_display_item.h"
23 #include "cc/playback/filter_display_item.h"
24 #include "cc/playback/float_clip_display_item.h"
25 #include "cc/playback/largest_display_item.h"
26 #include "cc/playback/transform_display_item.h"
27 #include "third_party/skia/include/core/SkCanvas.h"
28 #include "third_party/skia/include/core/SkImageFilter.h"
29 #include "third_party/skia/include/core/SkPaint.h"
30 #include "third_party/skia/include/core/SkPictureRecorder.h"
31 #include "ui/gfx/geometry/rect.h"
32 #include "ui/gfx/geometry/rect_conversions.h"
33 #include "ui/gfx/skia_util.h"
34
35 namespace cc {
36
37 namespace {
38
39 // We don't perform per-layer solid color analysis when there are too many skia
40 // operations.
41 const int kOpCountThatIsOkToAnalyze = 10;
42
43 bool GetCanvasClipBounds(SkCanvas* canvas, gfx::Rect* clip_bounds) {
44 SkRect canvas_clip_bounds;
45 if (!canvas->getLocalClipBounds(&canvas_clip_bounds))
46 return false;
47 *clip_bounds = ToEnclosingRect(gfx::SkRectToRectF(canvas_clip_bounds));
48 return true;
49 }
50
51 const int kDefaultNumDisplayItemsToReserve = 100;
52
53 NOINLINE DISABLE_CFI_PERF void RasterItem(const DisplayItem& base_item,
54 SkCanvas* canvas,
55 SkPicture::AbortCallback* callback) {
56 switch (base_item.type) {
57 case DisplayItem::CLIP: {
58 const auto& item = static_cast<const ClipDisplayItem&>(base_item);
59 canvas->save();
60 canvas->clipRect(gfx::RectToSkRect(item.clip_rect), item.antialias);
61 for (const auto& rrect : item.rounded_clip_rects) {
62 if (rrect.isRect()) {
63 canvas->clipRect(rrect.rect(), item.antialias);
64 } else {
65 canvas->clipRRect(rrect, item.antialias);
66 }
67 }
68 break;
69 }
70 case DisplayItem::END_CLIP:
71 canvas->restore();
72 break;
73 case DisplayItem::CLIP_PATH: {
74 const auto& item = static_cast<const ClipPathDisplayItem&>(base_item);
75 canvas->save();
76 canvas->clipPath(item.clip_path, item.antialias);
77 break;
78 }
79 case DisplayItem::END_CLIP_PATH:
80 canvas->restore();
81 break;
82 case DisplayItem::COMPOSITING: {
83 const auto& item = static_cast<const CompositingDisplayItem&>(base_item);
84 SkPaint paint;
85 paint.setBlendMode(item.xfermode);
86 paint.setAlpha(item.alpha);
87 paint.setColorFilter(item.color_filter);
88 const SkRect* bounds = item.has_bounds ? &item.bounds : nullptr;
89 if (item.lcd_text_requires_opaque_layer)
90 canvas->saveLayer(bounds, &paint);
91 else
92 canvas->saveLayerPreserveLCDTextRequests(bounds, &paint);
93 break;
94 }
95 case DisplayItem::END_COMPOSITING:
96 canvas->restore();
97 break;
98 case DisplayItem::DRAWING: {
99 const auto& item = static_cast<const DrawingDisplayItem&>(base_item);
100 if (canvas->quickReject(item.picture->cullRect()))
101 break;
102
103 // SkPicture always does a wrapping save/restore on the canvas, so it is
104 // not necessary here.
105 if (callback) {
106 item.picture->playback(canvas, callback);
107 } else {
108 // TODO(enne): switch this to playback once PaintRecord is real.
109 canvas->drawPicture(ToSkPicture(item.picture.get()));
110 }
111 break;
112 }
113 case DisplayItem::FLOAT_CLIP: {
114 const auto& item = static_cast<const FloatClipDisplayItem&>(base_item);
115 canvas->save();
116 canvas->clipRect(gfx::RectFToSkRect(item.clip_rect));
117 break;
118 }
119 case DisplayItem::END_FLOAT_CLIP:
120 canvas->restore();
121 break;
122 case DisplayItem::FILTER: {
123 const auto& item = static_cast<const FilterDisplayItem&>(base_item);
124 canvas->save();
125 canvas->translate(item.origin.x(), item.origin.y());
126
127 sk_sp<SkImageFilter> image_filter =
128 RenderSurfaceFilters::BuildImageFilter(item.filters,
129 item.bounds.size());
130 SkRect boundaries = RectFToSkRect(item.bounds);
131 boundaries.offset(-item.origin.x(), -item.origin.y());
132
133 SkPaint paint;
134 paint.setBlendMode(SkBlendMode::kSrcOver);
135 paint.setImageFilter(std::move(image_filter));
136 canvas->saveLayer(&boundaries, &paint);
137
138 canvas->translate(-item.origin.x(), -item.origin.y());
139 break;
140 }
141 case DisplayItem::END_FILTER:
142 canvas->restore();
143 canvas->restore();
144 break;
145 case DisplayItem::TRANSFORM: {
146 const auto& item = static_cast<const TransformDisplayItem&>(base_item);
147 canvas->save();
148 if (!item.transform.IsIdentity())
149 canvas->concat(item.transform.matrix());
150 break;
151 }
152 case DisplayItem::END_TRANSFORM:
153 canvas->restore();
154 break;
155 }
156 }
157
158 } // namespace
159
160 DisplayItemList::DisplayItemList()
161 : items_(LargestDisplayItemSize(),
162 LargestDisplayItemSize() * kDefaultNumDisplayItemsToReserve) {}
163
164 DisplayItemList::~DisplayItemList() = default;
165
166 void DisplayItemList::Raster(SkCanvas* canvas,
167 SkPicture::AbortCallback* callback,
168 const gfx::Rect& canvas_target_playback_rect,
169 float contents_scale) const {
170 canvas->save();
171 if (!canvas_target_playback_rect.IsEmpty()) {
172 // canvas_target_playback_rect is specified in device space. We can't
173 // use clipRect because canvas CTM will be applied on it. Use clipRegion
174 // instead because it ignores canvas CTM.
175 SkRegion device_clip;
176 device_clip.setRect(gfx::RectToSkIRect(canvas_target_playback_rect));
177 canvas->clipRegion(device_clip);
178 }
179 canvas->scale(contents_scale, contents_scale);
180 Raster(canvas, callback);
181 canvas->restore();
182 }
183
184 void DisplayItemList::Raster(SkCanvas* canvas,
185 SkPicture::AbortCallback* callback) const {
186 gfx::Rect canvas_playback_rect;
187 if (!GetCanvasClipBounds(canvas, &canvas_playback_rect))
188 return;
189
190 std::vector<size_t> indices;
191 rtree_.Search(canvas_playback_rect, &indices);
192 for (size_t index : indices) {
193 RasterItem(items_[index], canvas, callback);
194
195 // We use a callback during solid color analysis on the compositor thread to
196 // break out early. Since we're handling a sequence of pictures via rtree
197 // query results ourselves, we have to respect the callback and early out.
198 if (callback && callback->abort())
199 break;
200 }
201 }
202
203 void DisplayItemList::GrowCurrentBeginItemVisualRect(
204 const gfx::Rect& visual_rect) {
205 if (!begin_item_indices_.empty())
206 visual_rects_[begin_item_indices_.back()].Union(visual_rect);
207 }
208
209 void DisplayItemList::Finalize() {
210 TRACE_EVENT0("cc", "DisplayItemList::Finalize");
211 DCHECK(items_.size() == visual_rects_.size())
212 << "items.size() " << items_.size() << " visual_rects.size() "
213 << visual_rects_.size();
214 rtree_.Build(visual_rects_);
215
216 if (!retain_visual_rects_)
217 // This clears both the vector and the vector's capacity, since
218 // visual_rects won't be used anymore.
219 std::vector<gfx::Rect>().swap(visual_rects_);
220 }
221
222 bool DisplayItemList::IsSuitableForGpuRasterization() const {
223 // TODO(wkorman): This is more permissive than Picture's implementation, since
224 // none of the items might individually trigger a veto even though they
225 // collectively have enough "bad" operations that a corresponding Picture
226 // would get vetoed. See crbug.com/513016.
227 return all_items_are_suitable_for_gpu_rasterization_;
228 }
229
230 int DisplayItemList::ApproximateOpCount() const {
231 return approximate_op_count_;
232 }
233
234 size_t DisplayItemList::ApproximateMemoryUsage() const {
235 size_t memory_usage = sizeof(*this);
236
237 size_t external_memory_usage = 0;
238 for (const auto& item : items_) {
239 size_t bytes = 0;
240 switch (item.type) {
241 case DisplayItem::CLIP:
242 bytes = static_cast<const ClipDisplayItem&>(item).ExternalMemoryUsage();
243 break;
244 case DisplayItem::CLIP_PATH:
245 bytes =
246 static_cast<const ClipPathDisplayItem&>(item).ExternalMemoryUsage();
247 break;
248 case DisplayItem::COMPOSITING:
249 bytes = static_cast<const CompositingDisplayItem&>(item)
250 .ExternalMemoryUsage();
251 break;
252 case DisplayItem::DRAWING:
253 bytes =
254 static_cast<const DrawingDisplayItem&>(item).ExternalMemoryUsage();
255 break;
256 case DisplayItem::FLOAT_CLIP:
257 bytes = static_cast<const FloatClipDisplayItem&>(item)
258 .ExternalMemoryUsage();
259 break;
260 case DisplayItem::FILTER:
261 bytes =
262 static_cast<const FilterDisplayItem&>(item).ExternalMemoryUsage();
263 break;
264 case DisplayItem::TRANSFORM:
265 bytes = static_cast<const TransformDisplayItem&>(item)
266 .ExternalMemoryUsage();
267 break;
268 case DisplayItem::END_CLIP:
269 case DisplayItem::END_CLIP_PATH:
270 case DisplayItem::END_COMPOSITING:
271 case DisplayItem::END_FLOAT_CLIP:
272 case DisplayItem::END_FILTER:
273 case DisplayItem::END_TRANSFORM:
274 break;
275 }
276 external_memory_usage += bytes;
277 }
278
279 // Memory outside this class due to |items_|.
280 memory_usage += items_.GetCapacityInBytes() + external_memory_usage;
281
282 // TODO(jbroman): Does anything else owned by this class substantially
283 // contribute to memory usage?
284 // TODO(vmpstr): Probably DiscardableImageMap is worth counting here.
285
286 return memory_usage;
287 }
288
289 bool DisplayItemList::ShouldBeAnalyzedForSolidColor() const {
290 return ApproximateOpCount() <= kOpCountThatIsOkToAnalyze;
291 }
292
293 void DisplayItemList::EmitTraceSnapshot() const {
294 bool include_items;
295 TRACE_EVENT_CATEGORY_GROUP_ENABLED(
296 TRACE_DISABLED_BY_DEFAULT("cc.debug.display_items"), &include_items);
297 TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID(
298 TRACE_DISABLED_BY_DEFAULT("cc.debug.display_items") ","
299 TRACE_DISABLED_BY_DEFAULT("cc.debug.picture") ","
300 TRACE_DISABLED_BY_DEFAULT("devtools.timeline.picture"),
301 "cc::DisplayItemList", this, CreateTracedValue(include_items));
302 }
303
304 std::unique_ptr<base::trace_event::TracedValue>
305 DisplayItemList::CreateTracedValue(bool include_items) const {
306 auto state = base::MakeUnique<base::trace_event::TracedValue>();
307 state->BeginDictionary("params");
308
309 if (include_items) {
310 state->BeginArray("items");
311
312 auto visual_rects_it = visual_rects_.begin();
313 for (const DisplayItem& base_item : items_) {
314 gfx::Rect visual_rect;
315 if (visual_rects_it != visual_rects_.end()) {
316 visual_rect = *visual_rects_it;
317 ++visual_rects_it;
318 }
319
320 switch (base_item.type) {
321 case DisplayItem::CLIP: {
322 const auto& item = static_cast<const ClipDisplayItem&>(base_item);
323 std::string output =
324 base::StringPrintf("ClipDisplayItem rect: [%s] visualRect: [%s]",
325 item.clip_rect.ToString().c_str(),
326 visual_rect.ToString().c_str());
327 for (const SkRRect& rounded_rect : item.rounded_clip_rects) {
328 base::StringAppendF(
329 &output, " rounded_rect: [rect: [%s]",
330 gfx::SkRectToRectF(rounded_rect.rect()).ToString().c_str());
331 base::StringAppendF(&output, " radii: [");
332 SkVector upper_left_radius =
333 rounded_rect.radii(SkRRect::kUpperLeft_Corner);
334 base::StringAppendF(&output, "[%f,%f],", upper_left_radius.x(),
335 upper_left_radius.y());
336 SkVector upper_right_radius =
337 rounded_rect.radii(SkRRect::kUpperRight_Corner);
338 base::StringAppendF(&output, " [%f,%f],", upper_right_radius.x(),
339 upper_right_radius.y());
340 SkVector lower_right_radius =
341 rounded_rect.radii(SkRRect::kLowerRight_Corner);
342 base::StringAppendF(&output, " [%f,%f],", lower_right_radius.x(),
343 lower_right_radius.y());
344 SkVector lower_left_radius =
345 rounded_rect.radii(SkRRect::kLowerLeft_Corner);
346 base::StringAppendF(&output, " [%f,%f]]", lower_left_radius.x(),
347 lower_left_radius.y());
348 }
349 state->AppendString(output);
350 break;
351 }
352 case DisplayItem::END_CLIP:
353 state->AppendString(
354 base::StringPrintf("EndClipDisplayItem visualRect: [%s]",
355 visual_rect.ToString().c_str()));
356 break;
357 case DisplayItem::CLIP_PATH: {
358 const auto& item = static_cast<const ClipPathDisplayItem&>(base_item);
359 state->AppendString(base::StringPrintf(
360 "ClipPathDisplayItem length: %d visualRect: [%s]",
361 item.clip_path.countPoints(), visual_rect.ToString().c_str()));
362 break;
363 }
364 case DisplayItem::END_CLIP_PATH:
365 state->AppendString(
366 base::StringPrintf("EndClipPathDisplayItem visualRect: [%s]",
367 visual_rect.ToString().c_str()));
368 break;
369 case DisplayItem::COMPOSITING: {
370 const auto& item =
371 static_cast<const CompositingDisplayItem&>(base_item);
372 std::string output = base::StringPrintf(
373 "CompositingDisplayItem alpha: %d, xfermode: %d, visualRect: "
374 "[%s]",
375 item.alpha, static_cast<int>(item.xfermode),
376 visual_rect.ToString().c_str());
377 if (item.has_bounds) {
378 base::StringAppendF(
379 &output, ", bounds: [%s]",
380 gfx::SkRectToRectF(item.bounds).ToString().c_str());
381 }
382 state->AppendString(output);
383 break;
384 }
385 case DisplayItem::END_COMPOSITING:
386 state->AppendString(
387 base::StringPrintf("EndCompositingDisplayItem visualRect: [%s]",
388 visual_rect.ToString().c_str()));
389 break;
390 case DisplayItem::DRAWING: {
391 const auto& item = static_cast<const DrawingDisplayItem&>(base_item);
392 state->BeginDictionary();
393 state->SetString("name", "DrawingDisplayItem");
394
395 state->BeginArray("visualRect");
396 state->AppendInteger(visual_rect.x());
397 state->AppendInteger(visual_rect.y());
398 state->AppendInteger(visual_rect.width());
399 state->AppendInteger(visual_rect.height());
400 state->EndArray();
401
402 state->BeginArray("cullRect");
403 state->AppendInteger(item.picture->cullRect().x());
404 state->AppendInteger(item.picture->cullRect().y());
405 state->AppendInteger(item.picture->cullRect().width());
406 state->AppendInteger(item.picture->cullRect().height());
407 state->EndArray();
408
409 std::string b64_picture;
410 PictureDebugUtil::SerializeAsBase64(ToSkPicture(item.picture.get()),
411 &b64_picture);
412 state->SetString("skp64", b64_picture);
413 state->EndDictionary();
414 break;
415 }
416 case DisplayItem::FILTER: {
417 const auto& item = static_cast<const FilterDisplayItem&>(base_item);
418 state->AppendString(base::StringPrintf(
419 "FilterDisplayItem bounds: [%s] visualRect: [%s]",
420 item.bounds.ToString().c_str(), visual_rect.ToString().c_str()));
421 break;
422 }
423 case DisplayItem::END_FILTER:
424 state->AppendString(
425 base::StringPrintf("EndFilterDisplayItem visualRect: [%s]",
426 visual_rect.ToString().c_str()));
427 break;
428 case DisplayItem::FLOAT_CLIP: {
429 const auto& item =
430 static_cast<const FloatClipDisplayItem&>(base_item);
431 state->AppendString(base::StringPrintf(
432 "FloatClipDisplayItem rect: [%s] visualRect: [%s]",
433 item.clip_rect.ToString().c_str(),
434 visual_rect.ToString().c_str()));
435 break;
436 }
437 case DisplayItem::END_FLOAT_CLIP:
438 state->AppendString(
439 base::StringPrintf("EndFloatClipDisplayItem visualRect: [%s]",
440 visual_rect.ToString().c_str()));
441 break;
442 case DisplayItem::TRANSFORM: {
443 const auto& item =
444 static_cast<const TransformDisplayItem&>(base_item);
445 state->AppendString(base::StringPrintf(
446 "TransformDisplayItem transform: [%s] visualRect: [%s]",
447 item.transform.ToString().c_str(),
448 visual_rect.ToString().c_str()));
449 break;
450 }
451 case DisplayItem::END_TRANSFORM:
452 state->AppendString(
453 base::StringPrintf("EndTransformDisplayItem visualRect: [%s]",
454 visual_rect.ToString().c_str()));
455 break;
456 }
457 }
458 state->EndArray(); // "items".
459 }
460
461 MathUtil::AddToTracedValue("layer_rect", rtree_.GetBounds(), state.get());
462 state->EndDictionary(); // "params".
463
464 {
465 SkPictureRecorder recorder;
466 gfx::Rect bounds = rtree_.GetBounds();
467 SkCanvas* canvas = recorder.beginRecording(bounds.width(), bounds.height());
468 canvas->translate(-bounds.x(), -bounds.y());
469 canvas->clipRect(gfx::RectToSkRect(bounds));
470 Raster(canvas, nullptr, gfx::Rect(), 1.f);
471 sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture();
472
473 std::string b64_picture;
474 PictureDebugUtil::SerializeAsBase64(picture.get(), &b64_picture);
475 state->SetString("skp64", b64_picture);
476 }
477
478 return state;
479 }
480
481 void DisplayItemList::GenerateDiscardableImagesMetadata() {
482 // This should be only called once.
483 DCHECK(image_map_.empty());
484
485 gfx::Rect bounds = rtree_.GetBounds();
486 DiscardableImageMap::ScopedMetadataGenerator generator(
487 &image_map_, gfx::Size(bounds.right(), bounds.bottom()));
488 auto* canvas = generator.canvas();
489 for (const auto& item : items_)
490 RasterItem(item, canvas, nullptr);
491 }
492
493 void DisplayItemList::GetDiscardableImagesInRect(
494 const gfx::Rect& rect,
495 float contents_scale,
496 std::vector<DrawImage>* images) {
497 image_map_.GetDiscardableImagesInRect(rect, contents_scale, images);
498 }
499
500 gfx::Rect DisplayItemList::GetRectForImage(ImageId image_id) const {
501 return image_map_.GetRectForImage(image_id);
502 }
503
504 } // namespace cc
OLDNEW
« no previous file with comments | « cc/playback/display_item_list.h ('k') | cc/playback/display_item_list_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698