Index: cc/playback/display_item_list.cc |
diff --git a/cc/playback/display_item_list.cc b/cc/playback/display_item_list.cc |
deleted file mode 100644 |
index f9a827de633688ebbf977bdbcf751d2bceeb081e..0000000000000000000000000000000000000000 |
--- a/cc/playback/display_item_list.cc |
+++ /dev/null |
@@ -1,504 +0,0 @@ |
-// Copyright 2014 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "cc/playback/display_item_list.h" |
- |
-#include <stddef.h> |
- |
-#include <string> |
- |
-#include "base/memory/ptr_util.h" |
-#include "base/numerics/safe_conversions.h" |
-#include "base/strings/stringprintf.h" |
-#include "base/trace_event/trace_event.h" |
-#include "base/trace_event/trace_event_argument.h" |
-#include "cc/base/math_util.h" |
-#include "cc/debug/picture_debug_util.h" |
-#include "cc/output/render_surface_filters.h" |
-#include "cc/playback/clip_display_item.h" |
-#include "cc/playback/clip_path_display_item.h" |
-#include "cc/playback/compositing_display_item.h" |
-#include "cc/playback/drawing_display_item.h" |
-#include "cc/playback/filter_display_item.h" |
-#include "cc/playback/float_clip_display_item.h" |
-#include "cc/playback/largest_display_item.h" |
-#include "cc/playback/transform_display_item.h" |
-#include "third_party/skia/include/core/SkCanvas.h" |
-#include "third_party/skia/include/core/SkImageFilter.h" |
-#include "third_party/skia/include/core/SkPaint.h" |
-#include "third_party/skia/include/core/SkPictureRecorder.h" |
-#include "ui/gfx/geometry/rect.h" |
-#include "ui/gfx/geometry/rect_conversions.h" |
-#include "ui/gfx/skia_util.h" |
- |
-namespace cc { |
- |
-namespace { |
- |
-// We don't perform per-layer solid color analysis when there are too many skia |
-// operations. |
-const int kOpCountThatIsOkToAnalyze = 10; |
- |
-bool GetCanvasClipBounds(SkCanvas* canvas, gfx::Rect* clip_bounds) { |
- SkRect canvas_clip_bounds; |
- if (!canvas->getLocalClipBounds(&canvas_clip_bounds)) |
- return false; |
- *clip_bounds = ToEnclosingRect(gfx::SkRectToRectF(canvas_clip_bounds)); |
- return true; |
-} |
- |
-const int kDefaultNumDisplayItemsToReserve = 100; |
- |
-NOINLINE DISABLE_CFI_PERF void RasterItem(const DisplayItem& base_item, |
- SkCanvas* canvas, |
- SkPicture::AbortCallback* callback) { |
- switch (base_item.type) { |
- case DisplayItem::CLIP: { |
- const auto& item = static_cast<const ClipDisplayItem&>(base_item); |
- canvas->save(); |
- canvas->clipRect(gfx::RectToSkRect(item.clip_rect), item.antialias); |
- for (const auto& rrect : item.rounded_clip_rects) { |
- if (rrect.isRect()) { |
- canvas->clipRect(rrect.rect(), item.antialias); |
- } else { |
- canvas->clipRRect(rrect, item.antialias); |
- } |
- } |
- break; |
- } |
- case DisplayItem::END_CLIP: |
- canvas->restore(); |
- break; |
- case DisplayItem::CLIP_PATH: { |
- const auto& item = static_cast<const ClipPathDisplayItem&>(base_item); |
- canvas->save(); |
- canvas->clipPath(item.clip_path, item.antialias); |
- break; |
- } |
- case DisplayItem::END_CLIP_PATH: |
- canvas->restore(); |
- break; |
- case DisplayItem::COMPOSITING: { |
- const auto& item = static_cast<const CompositingDisplayItem&>(base_item); |
- SkPaint paint; |
- paint.setBlendMode(item.xfermode); |
- paint.setAlpha(item.alpha); |
- paint.setColorFilter(item.color_filter); |
- const SkRect* bounds = item.has_bounds ? &item.bounds : nullptr; |
- if (item.lcd_text_requires_opaque_layer) |
- canvas->saveLayer(bounds, &paint); |
- else |
- canvas->saveLayerPreserveLCDTextRequests(bounds, &paint); |
- break; |
- } |
- case DisplayItem::END_COMPOSITING: |
- canvas->restore(); |
- break; |
- case DisplayItem::DRAWING: { |
- const auto& item = static_cast<const DrawingDisplayItem&>(base_item); |
- if (canvas->quickReject(item.picture->cullRect())) |
- break; |
- |
- // SkPicture always does a wrapping save/restore on the canvas, so it is |
- // not necessary here. |
- if (callback) { |
- item.picture->playback(canvas, callback); |
- } else { |
- // TODO(enne): switch this to playback once PaintRecord is real. |
- canvas->drawPicture(ToSkPicture(item.picture.get())); |
- } |
- break; |
- } |
- case DisplayItem::FLOAT_CLIP: { |
- const auto& item = static_cast<const FloatClipDisplayItem&>(base_item); |
- canvas->save(); |
- canvas->clipRect(gfx::RectFToSkRect(item.clip_rect)); |
- break; |
- } |
- case DisplayItem::END_FLOAT_CLIP: |
- canvas->restore(); |
- break; |
- case DisplayItem::FILTER: { |
- const auto& item = static_cast<const FilterDisplayItem&>(base_item); |
- canvas->save(); |
- canvas->translate(item.origin.x(), item.origin.y()); |
- |
- sk_sp<SkImageFilter> image_filter = |
- RenderSurfaceFilters::BuildImageFilter(item.filters, |
- item.bounds.size()); |
- SkRect boundaries = RectFToSkRect(item.bounds); |
- boundaries.offset(-item.origin.x(), -item.origin.y()); |
- |
- SkPaint paint; |
- paint.setBlendMode(SkBlendMode::kSrcOver); |
- paint.setImageFilter(std::move(image_filter)); |
- canvas->saveLayer(&boundaries, &paint); |
- |
- canvas->translate(-item.origin.x(), -item.origin.y()); |
- break; |
- } |
- case DisplayItem::END_FILTER: |
- canvas->restore(); |
- canvas->restore(); |
- break; |
- case DisplayItem::TRANSFORM: { |
- const auto& item = static_cast<const TransformDisplayItem&>(base_item); |
- canvas->save(); |
- if (!item.transform.IsIdentity()) |
- canvas->concat(item.transform.matrix()); |
- break; |
- } |
- case DisplayItem::END_TRANSFORM: |
- canvas->restore(); |
- break; |
- } |
-} |
- |
-} // namespace |
- |
-DisplayItemList::DisplayItemList() |
- : items_(LargestDisplayItemSize(), |
- LargestDisplayItemSize() * kDefaultNumDisplayItemsToReserve) {} |
- |
-DisplayItemList::~DisplayItemList() = default; |
- |
-void DisplayItemList::Raster(SkCanvas* canvas, |
- SkPicture::AbortCallback* callback, |
- const gfx::Rect& canvas_target_playback_rect, |
- float contents_scale) const { |
- canvas->save(); |
- if (!canvas_target_playback_rect.IsEmpty()) { |
- // canvas_target_playback_rect is specified in device space. We can't |
- // use clipRect because canvas CTM will be applied on it. Use clipRegion |
- // instead because it ignores canvas CTM. |
- SkRegion device_clip; |
- device_clip.setRect(gfx::RectToSkIRect(canvas_target_playback_rect)); |
- canvas->clipRegion(device_clip); |
- } |
- canvas->scale(contents_scale, contents_scale); |
- Raster(canvas, callback); |
- canvas->restore(); |
-} |
- |
-void DisplayItemList::Raster(SkCanvas* canvas, |
- SkPicture::AbortCallback* callback) const { |
- gfx::Rect canvas_playback_rect; |
- if (!GetCanvasClipBounds(canvas, &canvas_playback_rect)) |
- return; |
- |
- std::vector<size_t> indices; |
- rtree_.Search(canvas_playback_rect, &indices); |
- for (size_t index : indices) { |
- RasterItem(items_[index], canvas, callback); |
- |
- // We use a callback during solid color analysis on the compositor thread to |
- // break out early. Since we're handling a sequence of pictures via rtree |
- // query results ourselves, we have to respect the callback and early out. |
- if (callback && callback->abort()) |
- break; |
- } |
-} |
- |
-void DisplayItemList::GrowCurrentBeginItemVisualRect( |
- const gfx::Rect& visual_rect) { |
- if (!begin_item_indices_.empty()) |
- visual_rects_[begin_item_indices_.back()].Union(visual_rect); |
-} |
- |
-void DisplayItemList::Finalize() { |
- TRACE_EVENT0("cc", "DisplayItemList::Finalize"); |
- DCHECK(items_.size() == visual_rects_.size()) |
- << "items.size() " << items_.size() << " visual_rects.size() " |
- << visual_rects_.size(); |
- rtree_.Build(visual_rects_); |
- |
- if (!retain_visual_rects_) |
- // This clears both the vector and the vector's capacity, since |
- // visual_rects won't be used anymore. |
- std::vector<gfx::Rect>().swap(visual_rects_); |
-} |
- |
-bool DisplayItemList::IsSuitableForGpuRasterization() const { |
- // TODO(wkorman): This is more permissive than Picture's implementation, since |
- // none of the items might individually trigger a veto even though they |
- // collectively have enough "bad" operations that a corresponding Picture |
- // would get vetoed. See crbug.com/513016. |
- return all_items_are_suitable_for_gpu_rasterization_; |
-} |
- |
-int DisplayItemList::ApproximateOpCount() const { |
- return approximate_op_count_; |
-} |
- |
-size_t DisplayItemList::ApproximateMemoryUsage() const { |
- size_t memory_usage = sizeof(*this); |
- |
- size_t external_memory_usage = 0; |
- for (const auto& item : items_) { |
- size_t bytes = 0; |
- switch (item.type) { |
- case DisplayItem::CLIP: |
- bytes = static_cast<const ClipDisplayItem&>(item).ExternalMemoryUsage(); |
- break; |
- case DisplayItem::CLIP_PATH: |
- bytes = |
- static_cast<const ClipPathDisplayItem&>(item).ExternalMemoryUsage(); |
- break; |
- case DisplayItem::COMPOSITING: |
- bytes = static_cast<const CompositingDisplayItem&>(item) |
- .ExternalMemoryUsage(); |
- break; |
- case DisplayItem::DRAWING: |
- bytes = |
- static_cast<const DrawingDisplayItem&>(item).ExternalMemoryUsage(); |
- break; |
- case DisplayItem::FLOAT_CLIP: |
- bytes = static_cast<const FloatClipDisplayItem&>(item) |
- .ExternalMemoryUsage(); |
- break; |
- case DisplayItem::FILTER: |
- bytes = |
- static_cast<const FilterDisplayItem&>(item).ExternalMemoryUsage(); |
- break; |
- case DisplayItem::TRANSFORM: |
- bytes = static_cast<const TransformDisplayItem&>(item) |
- .ExternalMemoryUsage(); |
- break; |
- case DisplayItem::END_CLIP: |
- case DisplayItem::END_CLIP_PATH: |
- case DisplayItem::END_COMPOSITING: |
- case DisplayItem::END_FLOAT_CLIP: |
- case DisplayItem::END_FILTER: |
- case DisplayItem::END_TRANSFORM: |
- break; |
- } |
- external_memory_usage += bytes; |
- } |
- |
- // Memory outside this class due to |items_|. |
- memory_usage += items_.GetCapacityInBytes() + external_memory_usage; |
- |
- // TODO(jbroman): Does anything else owned by this class substantially |
- // contribute to memory usage? |
- // TODO(vmpstr): Probably DiscardableImageMap is worth counting here. |
- |
- return memory_usage; |
-} |
- |
-bool DisplayItemList::ShouldBeAnalyzedForSolidColor() const { |
- return ApproximateOpCount() <= kOpCountThatIsOkToAnalyze; |
-} |
- |
-void DisplayItemList::EmitTraceSnapshot() const { |
- bool include_items; |
- TRACE_EVENT_CATEGORY_GROUP_ENABLED( |
- TRACE_DISABLED_BY_DEFAULT("cc.debug.display_items"), &include_items); |
- TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( |
- TRACE_DISABLED_BY_DEFAULT("cc.debug.display_items") "," |
- TRACE_DISABLED_BY_DEFAULT("cc.debug.picture") "," |
- TRACE_DISABLED_BY_DEFAULT("devtools.timeline.picture"), |
- "cc::DisplayItemList", this, CreateTracedValue(include_items)); |
-} |
- |
-std::unique_ptr<base::trace_event::TracedValue> |
-DisplayItemList::CreateTracedValue(bool include_items) const { |
- auto state = base::MakeUnique<base::trace_event::TracedValue>(); |
- state->BeginDictionary("params"); |
- |
- if (include_items) { |
- state->BeginArray("items"); |
- |
- auto visual_rects_it = visual_rects_.begin(); |
- for (const DisplayItem& base_item : items_) { |
- gfx::Rect visual_rect; |
- if (visual_rects_it != visual_rects_.end()) { |
- visual_rect = *visual_rects_it; |
- ++visual_rects_it; |
- } |
- |
- switch (base_item.type) { |
- case DisplayItem::CLIP: { |
- const auto& item = static_cast<const ClipDisplayItem&>(base_item); |
- std::string output = |
- base::StringPrintf("ClipDisplayItem rect: [%s] visualRect: [%s]", |
- item.clip_rect.ToString().c_str(), |
- visual_rect.ToString().c_str()); |
- for (const SkRRect& rounded_rect : item.rounded_clip_rects) { |
- base::StringAppendF( |
- &output, " rounded_rect: [rect: [%s]", |
- gfx::SkRectToRectF(rounded_rect.rect()).ToString().c_str()); |
- base::StringAppendF(&output, " radii: ["); |
- SkVector upper_left_radius = |
- rounded_rect.radii(SkRRect::kUpperLeft_Corner); |
- base::StringAppendF(&output, "[%f,%f],", upper_left_radius.x(), |
- upper_left_radius.y()); |
- SkVector upper_right_radius = |
- rounded_rect.radii(SkRRect::kUpperRight_Corner); |
- base::StringAppendF(&output, " [%f,%f],", upper_right_radius.x(), |
- upper_right_radius.y()); |
- SkVector lower_right_radius = |
- rounded_rect.radii(SkRRect::kLowerRight_Corner); |
- base::StringAppendF(&output, " [%f,%f],", lower_right_radius.x(), |
- lower_right_radius.y()); |
- SkVector lower_left_radius = |
- rounded_rect.radii(SkRRect::kLowerLeft_Corner); |
- base::StringAppendF(&output, " [%f,%f]]", lower_left_radius.x(), |
- lower_left_radius.y()); |
- } |
- state->AppendString(output); |
- break; |
- } |
- case DisplayItem::END_CLIP: |
- state->AppendString( |
- base::StringPrintf("EndClipDisplayItem visualRect: [%s]", |
- visual_rect.ToString().c_str())); |
- break; |
- case DisplayItem::CLIP_PATH: { |
- const auto& item = static_cast<const ClipPathDisplayItem&>(base_item); |
- state->AppendString(base::StringPrintf( |
- "ClipPathDisplayItem length: %d visualRect: [%s]", |
- item.clip_path.countPoints(), visual_rect.ToString().c_str())); |
- break; |
- } |
- case DisplayItem::END_CLIP_PATH: |
- state->AppendString( |
- base::StringPrintf("EndClipPathDisplayItem visualRect: [%s]", |
- visual_rect.ToString().c_str())); |
- break; |
- case DisplayItem::COMPOSITING: { |
- const auto& item = |
- static_cast<const CompositingDisplayItem&>(base_item); |
- std::string output = base::StringPrintf( |
- "CompositingDisplayItem alpha: %d, xfermode: %d, visualRect: " |
- "[%s]", |
- item.alpha, static_cast<int>(item.xfermode), |
- visual_rect.ToString().c_str()); |
- if (item.has_bounds) { |
- base::StringAppendF( |
- &output, ", bounds: [%s]", |
- gfx::SkRectToRectF(item.bounds).ToString().c_str()); |
- } |
- state->AppendString(output); |
- break; |
- } |
- case DisplayItem::END_COMPOSITING: |
- state->AppendString( |
- base::StringPrintf("EndCompositingDisplayItem visualRect: [%s]", |
- visual_rect.ToString().c_str())); |
- break; |
- case DisplayItem::DRAWING: { |
- const auto& item = static_cast<const DrawingDisplayItem&>(base_item); |
- state->BeginDictionary(); |
- state->SetString("name", "DrawingDisplayItem"); |
- |
- state->BeginArray("visualRect"); |
- state->AppendInteger(visual_rect.x()); |
- state->AppendInteger(visual_rect.y()); |
- state->AppendInteger(visual_rect.width()); |
- state->AppendInteger(visual_rect.height()); |
- state->EndArray(); |
- |
- state->BeginArray("cullRect"); |
- state->AppendInteger(item.picture->cullRect().x()); |
- state->AppendInteger(item.picture->cullRect().y()); |
- state->AppendInteger(item.picture->cullRect().width()); |
- state->AppendInteger(item.picture->cullRect().height()); |
- state->EndArray(); |
- |
- std::string b64_picture; |
- PictureDebugUtil::SerializeAsBase64(ToSkPicture(item.picture.get()), |
- &b64_picture); |
- state->SetString("skp64", b64_picture); |
- state->EndDictionary(); |
- break; |
- } |
- case DisplayItem::FILTER: { |
- const auto& item = static_cast<const FilterDisplayItem&>(base_item); |
- state->AppendString(base::StringPrintf( |
- "FilterDisplayItem bounds: [%s] visualRect: [%s]", |
- item.bounds.ToString().c_str(), visual_rect.ToString().c_str())); |
- break; |
- } |
- case DisplayItem::END_FILTER: |
- state->AppendString( |
- base::StringPrintf("EndFilterDisplayItem visualRect: [%s]", |
- visual_rect.ToString().c_str())); |
- break; |
- case DisplayItem::FLOAT_CLIP: { |
- const auto& item = |
- static_cast<const FloatClipDisplayItem&>(base_item); |
- state->AppendString(base::StringPrintf( |
- "FloatClipDisplayItem rect: [%s] visualRect: [%s]", |
- item.clip_rect.ToString().c_str(), |
- visual_rect.ToString().c_str())); |
- break; |
- } |
- case DisplayItem::END_FLOAT_CLIP: |
- state->AppendString( |
- base::StringPrintf("EndFloatClipDisplayItem visualRect: [%s]", |
- visual_rect.ToString().c_str())); |
- break; |
- case DisplayItem::TRANSFORM: { |
- const auto& item = |
- static_cast<const TransformDisplayItem&>(base_item); |
- state->AppendString(base::StringPrintf( |
- "TransformDisplayItem transform: [%s] visualRect: [%s]", |
- item.transform.ToString().c_str(), |
- visual_rect.ToString().c_str())); |
- break; |
- } |
- case DisplayItem::END_TRANSFORM: |
- state->AppendString( |
- base::StringPrintf("EndTransformDisplayItem visualRect: [%s]", |
- visual_rect.ToString().c_str())); |
- break; |
- } |
- } |
- state->EndArray(); // "items". |
- } |
- |
- MathUtil::AddToTracedValue("layer_rect", rtree_.GetBounds(), state.get()); |
- state->EndDictionary(); // "params". |
- |
- { |
- SkPictureRecorder recorder; |
- gfx::Rect bounds = rtree_.GetBounds(); |
- SkCanvas* canvas = recorder.beginRecording(bounds.width(), bounds.height()); |
- canvas->translate(-bounds.x(), -bounds.y()); |
- canvas->clipRect(gfx::RectToSkRect(bounds)); |
- Raster(canvas, nullptr, gfx::Rect(), 1.f); |
- sk_sp<SkPicture> picture = recorder.finishRecordingAsPicture(); |
- |
- std::string b64_picture; |
- PictureDebugUtil::SerializeAsBase64(picture.get(), &b64_picture); |
- state->SetString("skp64", b64_picture); |
- } |
- |
- return state; |
-} |
- |
-void DisplayItemList::GenerateDiscardableImagesMetadata() { |
- // This should be only called once. |
- DCHECK(image_map_.empty()); |
- |
- gfx::Rect bounds = rtree_.GetBounds(); |
- DiscardableImageMap::ScopedMetadataGenerator generator( |
- &image_map_, gfx::Size(bounds.right(), bounds.bottom())); |
- auto* canvas = generator.canvas(); |
- for (const auto& item : items_) |
- RasterItem(item, canvas, nullptr); |
-} |
- |
-void DisplayItemList::GetDiscardableImagesInRect( |
- const gfx::Rect& rect, |
- float contents_scale, |
- std::vector<DrawImage>* images) { |
- image_map_.GetDiscardableImagesInRect(rect, contents_scale, images); |
-} |
- |
-gfx::Rect DisplayItemList::GetRectForImage(ImageId image_id) const { |
- return image_map_.GetRectForImage(image_id); |
-} |
- |
-} // namespace cc |