[go: nahoru, domu]

blob: fe3bdc7ef7ae3823a782801e838b04c7cb1af832 [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_PAINT_DISPLAY_ITEM_LIST_H_
#define CC_PAINT_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/rtree.h"
#include "cc/paint/discardable_image_map.h"
#include "cc/paint/image_id.h"
#include "cc/paint/paint_export.h"
#include "cc/paint/paint_op_buffer.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 base {
namespace trace_event {
class TracedValue;
}
}
namespace cc {
class CC_PAINT_EXPORT DisplayItemList
: public base::RefCountedThreadSafe<DisplayItemList> {
public:
DisplayItemList();
void Raster(SkCanvas* canvas,
SkPicture::AbortCallback* callback = nullptr) const;
PaintOpBuffer* StartPaint() {
DCHECK(!in_painting_);
in_painting_ = true;
return &paint_op_buffer_;
}
void EndPaintOfUnpaired(const gfx::Rect& visual_rect) {
in_painting_ = false;
// Empty paint item.
if (visual_rects_.size() == paint_op_buffer_.size())
return;
while (visual_rects_.size() < paint_op_buffer_.size())
visual_rects_.push_back(visual_rect);
GrowCurrentBeginItemVisualRect(visual_rect);
}
void EndPaintOfPairedBegin(const gfx::Rect& visual_rect = gfx::Rect()) {
DCHECK_NE(visual_rects_.size(), paint_op_buffer_.size());
size_t count = paint_op_buffer_.size() - visual_rects_.size();
for (size_t i = 0; i < count; ++i)
visual_rects_.push_back(visual_rect);
begin_paired_indices_.push_back(
std::make_pair(visual_rects_.size() - 1, count));
in_painting_ = false;
in_paired_begin_count_++;
}
void EndPaintOfPairedEnd() {
DCHECK_NE(current_range_start_, paint_op_buffer_.size());
DCHECK(in_paired_begin_count_);
size_t last_begin_index = begin_paired_indices_.back().first;
size_t last_begin_count = begin_paired_indices_.back().second;
DCHECK_GT(last_begin_count, 0u);
DCHECK_GE(last_begin_index, last_begin_count - 1);
// Copy the visual rect at |last_begin_index| to all indices that constitute
// the begin item. Note that because we possibly reallocate the
// |visual_rects_| buffer below, we need an actual copy instead of a const
// reference which can become dangling.
auto visual_rect = visual_rects_[last_begin_index];
for (size_t i = last_begin_index - last_begin_count + 1;
i < last_begin_index; ++i) {
visual_rects_[i] = visual_rect;
}
begin_paired_indices_.pop_back();
// Copy the visual rect of the matching begin item to the end item(s).
while (visual_rects_.size() < paint_op_buffer_.size())
visual_rects_.push_back(visual_rect);
// The block that ended needs to be included in the bounds of the enclosing
// block.
GrowCurrentBeginItemVisualRect(visual_rect);
in_painting_ = false;
in_paired_begin_count_--;
}
// Called after all items are appended, to process the items.
void Finalize();
int NumSlowPaths() const { return paint_op_buffer_.numSlowPaths(); }
// This gives the total number of PaintOps.
size_t op_count() const { return paint_op_buffer_.size(); }
size_t BytesUsed() const;
bool ShouldBeAnalyzedForSolidColor() const;
void EmitTraceSnapshot() const;
void GenerateDiscardableImagesMetadata();
void GetDiscardableImagesInRect(const gfx::Rect& rect,
float contents_scale,
const gfx::ColorSpace& target_color_space,
std::vector<DrawImage>* images);
gfx::Rect GetRectForImage(PaintImage::Id image_id) const;
gfx::Rect VisualRectForTesting(int index) { return visual_rects_[index]; }
void GatherDiscardableImages(DiscardableImageStore* image_store) const;
const DiscardableImageMap& discardable_image_map_for_testing() const {
return image_map_;
}
bool HasDiscardableImages() const {
return paint_op_buffer_.HasDiscardableImages();
}
// Generate a PaintRecord from this DisplayItemList, leaving |this| in
// an empty state.
sk_sp<PaintRecord> ReleaseAsRecord();
private:
FRIEND_TEST_ALL_PREFIXES(DisplayItemListTest, AsValueWithNoOps);
FRIEND_TEST_ALL_PREFIXES(DisplayItemListTest, AsValueWithOps);
~DisplayItemList();
void Reset();
std::unique_ptr<base::trace_event::TracedValue> CreateTracedValue(
bool include_items) const;
// 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);
// RTree stores indices into the paint op buffer.
// TODO(vmpstr): Update the rtree to store offsets instead.
RTree<size_t> rtree_;
DiscardableImageMap image_map_;
PaintOpBuffer paint_op_buffer_;
// The visual rects associated with each of the display items in the
// display item list. These rects are intentionally kept separate because they
// are used to decide which ops to walk for raster.
std::vector<gfx::Rect> visual_rects_;
// A stack of pairs of indices and counts. The indices are into the
// |visual_rects_| for each paired begin range that hasn't been closed. The
// counts refer to the number of visual rects in that begin sequence that end
// with the index.
std::vector<std::pair<size_t, size_t>> begin_paired_indices_;
// While recording a range of ops, this is the position in the PaintOpBuffer
// where the recording started.
size_t current_range_start_ = 0;
// For debugging, tracks the number of currently nested visual rects being
// added.
int in_paired_begin_count_ = 0;
// For debugging, tracks if we're painting a visual rect range, to prevent
// nesting.
bool in_painting_ = false;
size_t op_count_ = 0u;
friend class base::RefCountedThreadSafe<DisplayItemList>;
FRIEND_TEST_ALL_PREFIXES(DisplayItemListTest, BytesUsed);
DISALLOW_COPY_AND_ASSIGN(DisplayItemList);
};
} // namespace cc
#endif // CC_PAINT_DISPLAY_ITEM_LIST_H_