Index: cc/playback/display_item_list.cc |
diff --git a/cc/playback/display_item_list.cc b/cc/playback/display_item_list.cc |
index 821dfce7db0294393bb2cd1e001f203a7611ca2f..a1a9cdbfc569a99c65c9243bb4cd41cc05fa0525 100644 |
--- a/cc/playback/display_item_list.cc |
+++ b/cc/playback/display_item_list.cc |
@@ -16,7 +16,6 @@ |
#include "cc/debug/traced_value.h" |
#include "cc/playback/display_item_list_settings.h" |
#include "cc/playback/display_item_proto_factory.h" |
-#include "cc/playback/drawing_display_item.h" |
#include "cc/playback/largest_display_item.h" |
#include "cc/proto/display_item.pb.h" |
#include "cc/proto/gfx_conversions.h" |
@@ -62,8 +61,10 @@ |
for (int i = 0; i < proto.items_size(); i++) { |
const proto::DisplayItem& item_proto = proto.items(i); |
- DisplayItemProtoFactory::AllocateAndConstruct(layer_rect, list.get(), |
- item_proto); |
+ DisplayItem* item = DisplayItemProtoFactory::AllocateAndConstruct( |
+ layer_rect, list.get(), item_proto); |
+ if (item) |
+ item->FromProtobuf(item_proto); |
} |
return list; |
@@ -79,7 +80,11 @@ |
layer_rect_(layer_rect), |
is_suitable_for_gpu_rasterization_(true), |
approximate_op_count_(0), |
- picture_memory_usage_(0) { |
+ picture_memory_usage_(0), |
+ external_memory_usage_(0) { |
+#if DCHECK_IS_ON() |
+ needs_process_ = false; |
+#endif |
if (settings_.use_cached_picture) { |
SkRTreeFactory factory; |
recorder_.reset(new SkPictureRecorder()); |
@@ -110,6 +115,7 @@ |
SkPicture::AbortCallback* callback, |
const gfx::Rect& canvas_target_playback_rect, |
float contents_scale) const { |
+ DCHECK(ProcessAppendedItemsCalled()); |
if (!settings_.use_cached_picture) { |
canvas->save(); |
canvas->scale(contents_scale, contents_scale); |
@@ -136,25 +142,68 @@ |
} |
} |
-void DisplayItemList::ProcessAppendedItem(const DisplayItem* item) { |
- if (settings_.use_cached_picture) { |
- DCHECK(canvas_); |
- item->Raster(canvas_.get(), gfx::Rect(), nullptr); |
- } |
- if (!retain_individual_display_items_) { |
+void DisplayItemList::ProcessAppendedItemsOnTheFly() { |
+ if (retain_individual_display_items_) |
+ return; |
+ if (items_.size() >= kDefaultNumDisplayItemsToReserve) { |
+ ProcessAppendedItems(); |
+ // This function exists to keep the |items_| from growing indefinitely if |
+ // we're not going to store them anyway. So the items better be deleted |
+ // after |items_| grows too large and we process it. |
+ DCHECK(items_.empty()); |
+ } |
+} |
+ |
+void DisplayItemList::ProcessAppendedItems() { |
+#if DCHECK_IS_ON() |
+ needs_process_ = false; |
+#endif |
+ for (const DisplayItem& item : items_) { |
+ if (settings_.use_cached_picture) { |
+ // When using a cached picture we will calculate gpu suitability on the |
+ // entire cached picture instead of the items. This is more permissive |
+ // 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. |
+ DCHECK(canvas_); |
+ approximate_op_count_ += item.approximate_op_count(); |
+ item.Raster(canvas_.get(), gfx::Rect(), nullptr); |
+ } else { |
+ is_suitable_for_gpu_rasterization_ &= |
+ item.is_suitable_for_gpu_rasterization(); |
+ approximate_op_count_ += item.approximate_op_count(); |
+ } |
+ |
+ if (retain_individual_display_items_) { |
+ // Warning: this double-counts SkPicture data if use_cached_picture is |
+ // also true. |
+ external_memory_usage_ += item.external_memory_usage(); |
+ } |
+ } |
+ |
+ if (!retain_individual_display_items_) |
items_.Clear(); |
- } |
} |
void DisplayItemList::RasterIntoCanvas(const DisplayItem& item) { |
DCHECK(canvas_); |
DCHECK(!retain_individual_display_items_); |
+ approximate_op_count_ += item.approximate_op_count(); |
item.Raster(canvas_.get(), gfx::Rect(), nullptr); |
} |
bool DisplayItemList::RetainsIndividualDisplayItems() const { |
return retain_individual_display_items_; |
+} |
+ |
+void DisplayItemList::RemoveLast() { |
+ // We cannot remove the last item if it has been squashed into a picture. |
+ // The last item should not have been handled by ProcessAppendedItems, so we |
+ // don't need to remove it from approximate_op_count_, etc. |
+ DCHECK(retain_individual_display_items_); |
+ DCHECK(!settings_.use_cached_picture); |
+ items_.RemoveLast(); |
} |
void DisplayItemList::Finalize() { |
@@ -166,6 +215,8 @@ |
// rects. For now we just clear them out since we won't ever need |
// them to stick around post-Finalize. http://crbug.com/527245 |
visual_rects_.clear(); |
+ |
+ ProcessAppendedItems(); |
if (settings_.use_cached_picture) { |
// Convert to an SkPicture for faster rasterization. |
@@ -177,18 +228,23 @@ |
SkPictureUtils::ApproximateBytesUsed(picture_.get()); |
recorder_.reset(); |
canvas_.clear(); |
+ is_suitable_for_gpu_rasterization_ = |
+ picture_->suitableForGpuRasterization(nullptr); |
} |
} |
bool DisplayItemList::IsSuitableForGpuRasterization() const { |
+ DCHECK(ProcessAppendedItemsCalled()); |
return is_suitable_for_gpu_rasterization_; |
} |
int DisplayItemList::ApproximateOpCount() const { |
+ DCHECK(ProcessAppendedItemsCalled()); |
return approximate_op_count_; |
} |
size_t DisplayItemList::ApproximateMemoryUsage() const { |
+ DCHECK(ProcessAppendedItemsCalled()); |
// We double-count in this case. Produce zero to avoid being misleading. |
if (settings_.use_cached_picture && retain_individual_display_items_) |
return 0; |
@@ -197,17 +253,8 @@ |
size_t memory_usage = sizeof(*this); |
- size_t external_memory_usage = 0; |
- if (retain_individual_display_items_) { |
- // Warning: this double-counts SkPicture data if use_cached_picture is |
- // also true. |
- for (const auto& item : items_) { |
- external_memory_usage += item.ExternalMemoryUsage(); |
- } |
- } |
- |
// Memory outside this class due to |items_|. |
- memory_usage += items_.GetCapacityInBytes() + external_memory_usage; |
+ memory_usage += items_.GetCapacityInBytes() + external_memory_usage_; |
// Memory outside this class due to |picture|. |
memory_usage += picture_memory_usage_; |
@@ -224,6 +271,7 @@ |
scoped_refptr<base::trace_event::ConvertableToTraceFormat> |
DisplayItemList::AsValue(bool include_items) const { |
+ DCHECK(ProcessAppendedItemsCalled()); |
scoped_refptr<base::trace_event::TracedValue> state = |
new base::trace_event::TracedValue(); |
@@ -262,6 +310,7 @@ |
} |
void DisplayItemList::EmitTraceSnapshot() const { |
+ DCHECK(ProcessAppendedItemsCalled()); |
TRACE_EVENT_OBJECT_SNAPSHOT_WITH_ID( |
TRACE_DISABLED_BY_DEFAULT("cc.debug.display_items") "," |
TRACE_DISABLED_BY_DEFAULT("cc.debug.picture") "," |
@@ -272,6 +321,7 @@ |
} |
void DisplayItemList::GenerateDiscardableImagesMetadata() { |
+ DCHECK(ProcessAppendedItemsCalled()); |
// This should be only called once, and only after CreateAndCacheSkPicture. |
DCHECK(image_map_.empty()); |
DCHECK(!settings_.use_cached_picture || picture_); |