blob: a18c0e2661c065f66c5127a7c7dcad4530a5c424 [file] [log] [blame]
// 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.
#ifndef CC_PLAYBACK_DISPLAY_ITEM_LIST_H_
#define CC_PLAYBACK_DISPLAY_ITEM_LIST_H_
#include <stddef.h>
#include <memory>
#include <utility>
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/trace_event/trace_event.h"
#include "cc/base/cc_export.h"
#include "cc/base/contiguous_container.h"
#include "cc/base/rtree.h"
#include "cc/playback/discardable_image_map.h"
#include "cc/playback/display_item.h"
#include "cc/playback/display_item_list_settings.h"
#include "third_party/skia/include/core/SkPicture.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_conversions.h"
class SkCanvas;
namespace cc {
class ClientPictureCache;
class DisplayItem;
namespace proto {
class DisplayItemList;
}
class CC_EXPORT DisplayItemList
: public base::RefCountedThreadSafe<DisplayItemList> {
public:
// Creates a display item list.
static scoped_refptr<DisplayItemList> Create(
const DisplayItemListSettings& settings);
// Creates a DisplayItemList from a Protobuf.
// TODO(dtrainor): Pass in a list of possible DisplayItems to reuse
// (crbug.com/548434).
static scoped_refptr<DisplayItemList> CreateFromProto(
const proto::DisplayItemList& proto,
ClientPictureCache* client_picture_cache,
std::vector<uint32_t>* used_engine_picture_ids);
// Creates a Protobuf representing the state of this DisplayItemList.
void ToProtobuf(proto::DisplayItemList* proto);
// TODO(trchen): Deprecated. Apply clip and scale on the canvas instead.
void Raster(SkCanvas* canvas,
SkPicture::AbortCallback* callback,
const gfx::Rect& canvas_target_playback_rect,
float contents_scale) const;
void Raster(SkCanvas* canvas, SkPicture::AbortCallback* callback) const;
// Because processing happens in these CreateAndAppend functions, all the set
// up for the item should be done via the args, which is why the return type
// needs to be const, to prevent set-after-processing mistakes.
// Most paired begin item types default to an empty visual rect, which will
// subsequently be grown as needed to encompass any contained items that draw
// content, such as drawing or filter items.
template <typename DisplayItemType, typename... Args>
const DisplayItemType& CreateAndAppendPairedBeginItem(Args&&... args) {
return CreateAndAppendPairedBeginItemWithVisualRect<DisplayItemType>(
gfx::Rect(), std::forward<Args>(args)...);
}
// This method variant is exposed to allow filters to specify their visual
// rect since they may draw content despite containing no drawing items.
template <typename DisplayItemType, typename... Args>
const DisplayItemType& CreateAndAppendPairedBeginItemWithVisualRect(
const gfx::Rect& visual_rect,
Args&&... args) {
size_t item_index = inputs_.visual_rects.size();
inputs_.visual_rects.push_back(visual_rect);
inputs_.begin_item_indices.push_back(item_index);
return AllocateAndConstruct<DisplayItemType>(std::forward<Args>(args)...);
}
template <typename DisplayItemType, typename... Args>
const DisplayItemType& CreateAndAppendPairedEndItem(Args&&... args) {
DCHECK(!inputs_.begin_item_indices.empty());
size_t last_begin_index = inputs_.begin_item_indices.back();
inputs_.begin_item_indices.pop_back();
// Note that we are doing two separate things below:
//
// 1. Appending a new rect to the |visual_rects| list associated with
// the newly-being-added paired end item, with that visual rect
// having same bounds as its paired begin item, referenced via
// |last_begin_index|. The paired begin item may or may not be the
// current last visual rect in |visual_rects|, and its bounds has
// potentially been grown via calls to CreateAndAppendDrawingItem().
//
// 2. If there is still a containing paired begin item after closing the
// pair ended in this method call, growing that item's visual rect to
// incorporate the bounds of the now-finished pair.
//
// Thus we're carefully pushing and growing by the visual rect of the
// paired begin item we're closing in this method call, which is not
// necessarily the same as |visual_rects.back()|, and given that the
// |visual_rects| list is mutated in step 1 before step 2, we also can't
// shorten the reference via a |const auto| reference. We could make a
// copy of the rect before list mutation, but that would incur copy
// overhead.
// Ending bounds match the starting bounds.
inputs_.visual_rects.push_back(inputs_.visual_rects[last_begin_index]);
// The block that ended needs to be included in the bounds of the enclosing
// block.
GrowCurrentBeginItemVisualRect(inputs_.visual_rects[last_begin_index]);
return AllocateAndConstruct<DisplayItemType>(std::forward<Args>(args)...);
}
template <typename DisplayItemType, typename... Args>
const DisplayItemType& CreateAndAppendDrawingItem(
const gfx::Rect& visual_rect,
Args&&... args) {
inputs_.visual_rects.push_back(visual_rect);
GrowCurrentBeginItemVisualRect(visual_rect);
return AllocateAndConstruct<DisplayItemType>(std::forward<Args>(args)...);
}
// Called after all items are appended, to process the items and, if
// applicable, create an internally cached SkPicture.
void Finalize();
void SetIsSuitableForGpuRasterization(bool is_suitable) {
inputs_.all_items_are_suitable_for_gpu_rasterization = is_suitable;
}
bool IsSuitableForGpuRasterization() const;
void SetImpliedColorSpace(const gfx::ColorSpace& implied_color_space) {
inputs_.implied_color_space_specified = true;
inputs_.implied_color_space = implied_color_space;
}
bool HasImpliedColorSpace() const {
return inputs_.implied_color_space_specified;
}
const gfx::ColorSpace& GetImpliedColorSpace() const {
return inputs_.implied_color_space;
}
int ApproximateOpCount() const;
size_t ApproximateMemoryUsage() const;
bool ShouldBeAnalyzedForSolidColor() const;
std::unique_ptr<base::trace_event::ConvertableToTraceFormat> AsValue(
bool include_items) const;
void EmitTraceSnapshot() const;
void GenerateDiscardableImagesMetadata();
void GetDiscardableImagesInRect(const gfx::Rect& rect,
const gfx::SizeF& raster_scales,
std::vector<DrawImage>* images);
void SetRetainVisualRectsForTesting(bool retain) {
retain_visual_rects_ = retain;
}
size_t size() const { return inputs_.items.size(); }
gfx::Rect VisualRectForTesting(int index) {
return inputs_.visual_rects[index];
}
ContiguousContainer<DisplayItem>::const_iterator begin() const {
return inputs_.items.begin();
}
ContiguousContainer<DisplayItem>::const_iterator end() const {
return inputs_.items.end();
}
private:
explicit DisplayItemList(
const DisplayItemListSettings& display_list_settings);
~DisplayItemList();
RTree rtree_;
// For testing purposes only. Whether to keep visual rects across calls to
// Finalize().
bool retain_visual_rects_ = false;
// If we're currently within a paired display item block, unions the
// given visual rect with the begin display item's visual rect.
void GrowCurrentBeginItemVisualRect(const gfx::Rect& visual_rect);
template <typename DisplayItemType, typename... Args>
const DisplayItemType& AllocateAndConstruct(Args&&... args) {
auto* item = &inputs_.items.AllocateAndConstruct<DisplayItemType>(
std::forward<Args>(args)...);
approximate_op_count_ += item->ApproximateOpCount();
return *item;
}
int approximate_op_count_ = 0;
DiscardableImageMap image_map_;
struct Inputs {
explicit Inputs(const DisplayItemListSettings& settings);
~Inputs();
ContiguousContainer<DisplayItem> items;
// The visual rects associated with each of the display items in the
// display item list. There is one rect per display item, and the
// position in |visual_rects| matches the position of the item in
// |items| . These rects are intentionally kept separate
// because they are not needed while walking the |items| for raster.
std::vector<gfx::Rect> visual_rects;
std::vector<size_t> begin_item_indices;
const DisplayItemListSettings settings;
bool all_items_are_suitable_for_gpu_rasterization = true;
bool implied_color_space_specified = false;
gfx::ColorSpace implied_color_space;
};
Inputs inputs_;
friend class base::RefCountedThreadSafe<DisplayItemList>;
FRIEND_TEST_ALL_PREFIXES(DisplayItemListTest, ApproximateMemoryUsage);
DISALLOW_COPY_AND_ASSIGN(DisplayItemList);
};
} // namespace cc
#endif // CC_PLAYBACK_DISPLAY_ITEM_LIST_H_