display_item_list.h 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  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. #ifndef CC_PAINT_DISPLAY_ITEM_LIST_H_
  5. #define CC_PAINT_DISPLAY_ITEM_LIST_H_
  6. #include <cstddef>
  7. #include <memory>
  8. #include <string>
  9. #include <utility>
  10. #include <vector>
  11. #include "base/gtest_prod_util.h"
  12. #include "base/memory/ref_counted.h"
  13. #include "cc/base/rtree.h"
  14. #include "cc/paint/discardable_image_map.h"
  15. #include "cc/paint/image_id.h"
  16. #include "cc/paint/paint_export.h"
  17. #include "cc/paint/paint_op_buffer.h"
  18. #include "third_party/abseil-cpp/absl/types/optional.h"
  19. #include "third_party/skia/include/core/SkPicture.h"
  20. #include "ui/gfx/color_space.h"
  21. #include "ui/gfx/geometry/rect.h"
  22. #include "ui/gfx/geometry/rect_conversions.h"
  23. #include "ui/gfx/geometry/rect_f.h"
  24. class SkCanvas;
  25. namespace gpu {
  26. namespace raster {
  27. class RasterImplementation;
  28. class RasterImplementationGLES;
  29. } // namespace raster
  30. } // namespace gpu
  31. namespace base {
  32. namespace trace_event {
  33. class TracedValue;
  34. }
  35. }
  36. namespace cc {
  37. // DisplayItemList is a container of paint operations. One can populate the list
  38. // using StartPaint, followed by push{,_with_data,_with_array} functions
  39. // specialized with ops coming from paint_op_buffer.h. Internally, the
  40. // DisplayItemList contains a PaintOpBuffer and defers op saving to it.
  41. // Additionally, it store some meta information about the paint operations.
  42. // Specifically, it creates an rtree to assist in rasterization: when
  43. // rasterizing a rect, it queries the rtree to extract only the byte offsets of
  44. // the ops required and replays those into a canvas.
  45. class CC_PAINT_EXPORT DisplayItemList
  46. : public base::RefCountedThreadSafe<DisplayItemList> {
  47. public:
  48. // TODO(vmpstr): It would be cool if we didn't need this, and instead used
  49. // PaintOpBuffer directly when we needed to release this as a paint op buffer.
  50. enum UsageHint { kTopLevelDisplayItemList, kToBeReleasedAsPaintOpBuffer };
  51. explicit DisplayItemList(UsageHint = kTopLevelDisplayItemList);
  52. DisplayItemList(const DisplayItemList&) = delete;
  53. DisplayItemList& operator=(const DisplayItemList&) = delete;
  54. void Raster(SkCanvas* canvas, ImageProvider* image_provider = nullptr) const;
  55. // Captures |DrawTextBlobOp|s intersecting |rect| and returns the associated
  56. // |NodeId|s in |content|.
  57. void CaptureContent(const gfx::Rect& rect,
  58. std::vector<NodeInfo>* content) const;
  59. // Returns the approximate total area covered by |DrawTextBlobOp|s
  60. // intersecting |rect|, used for statistics purpose.
  61. double AreaOfDrawText(const gfx::Rect& rect) const;
  62. void StartPaint() {
  63. #if DCHECK_IS_ON()
  64. DCHECK(!IsPainting());
  65. current_range_start_ = paint_op_buffer_.size();
  66. #endif
  67. }
  68. // Push functions construct a new op on the paint op buffer, while maintaining
  69. // bookkeeping information. Must be called after invoking StartPaint().
  70. // Returns the id (which is an opaque value) of the operation that can be used
  71. // in UpdateSaveLayerBounds().
  72. template <typename T, typename... Args>
  73. size_t push(Args&&... args) {
  74. #if DCHECK_IS_ON()
  75. DCHECK(IsPainting());
  76. #endif
  77. size_t offset = paint_op_buffer_.next_op_offset();
  78. if (usage_hint_ == kTopLevelDisplayItemList)
  79. offsets_.push_back(offset);
  80. const T* op = paint_op_buffer_.push<T>(std::forward<Args>(args)...);
  81. DCHECK(op->IsValid());
  82. return offset;
  83. }
  84. // Called by blink::PaintChunksToCcLayer when an effect ends, to update the
  85. // bounds of a SaveLayer[Alpha]Op which was emitted when the effect started.
  86. // This is needed because blink doesn't know the bounds when an effect starts.
  87. // Don't add other mutation methods like this if there is better alternative.
  88. void UpdateSaveLayerBounds(size_t id, const SkRect& bounds) {
  89. paint_op_buffer_.UpdateSaveLayerBounds(id, bounds);
  90. }
  91. void EndPaintOfUnpaired(const gfx::Rect& visual_rect) {
  92. #if DCHECK_IS_ON()
  93. DCHECK(IsPainting());
  94. current_range_start_ = kNotPainting;
  95. #endif
  96. if (usage_hint_ == kToBeReleasedAsPaintOpBuffer)
  97. return;
  98. visual_rects_.resize(paint_op_buffer_.size(), visual_rect);
  99. GrowCurrentBeginItemVisualRect(visual_rect);
  100. }
  101. void EndPaintOfPairedBegin() {
  102. #if DCHECK_IS_ON()
  103. DCHECK(IsPainting());
  104. DCHECK_LT(current_range_start_, paint_op_buffer_.size());
  105. current_range_start_ = kNotPainting;
  106. #endif
  107. if (usage_hint_ == kToBeReleasedAsPaintOpBuffer)
  108. return;
  109. DCHECK_LT(visual_rects_.size(), paint_op_buffer_.size());
  110. size_t count = paint_op_buffer_.size() - visual_rects_.size();
  111. paired_begin_stack_.push_back({visual_rects_.size(), count});
  112. visual_rects_.resize(paint_op_buffer_.size());
  113. }
  114. void EndPaintOfPairedEnd();
  115. // Called after all items are appended, to process the items.
  116. void Finalize();
  117. struct DirectlyCompositedImageResult {
  118. // See PictureLayerImpl::direct_composited_image_default_raster_scale_.
  119. gfx::Vector2dF default_raster_scale;
  120. bool nearest_neighbor;
  121. };
  122. // If this list represents an image that should be directly composited (i.e.
  123. // rasterized at the intrinsic size of the image), return the intrinsic size
  124. // of the image and whether or not to use nearest neighbor filtering when
  125. // scaling the layer.
  126. absl::optional<DirectlyCompositedImageResult>
  127. GetDirectlyCompositedImageResult() const;
  128. int num_slow_paths_up_to_min_for_MSAA() const {
  129. return paint_op_buffer_.num_slow_paths_up_to_min_for_MSAA();
  130. }
  131. bool HasNonAAPaint() const { return paint_op_buffer_.HasNonAAPaint(); }
  132. // This gives the total number of PaintOps.
  133. size_t TotalOpCount() const { return paint_op_buffer_.total_op_count(); }
  134. size_t BytesUsed() const {
  135. // TODO(jbroman): Does anything else owned by this class substantially
  136. // contribute to memory usage?
  137. // TODO(vmpstr): Probably DiscardableImageMap is worth counting here.
  138. return sizeof(*this) + paint_op_buffer_.bytes_used();
  139. }
  140. size_t OpBytesUsed() const { return paint_op_buffer_.paint_ops_size(); }
  141. const DiscardableImageMap& discardable_image_map() const {
  142. return image_map_;
  143. }
  144. base::flat_map<PaintImage::Id, PaintImage::DecodingMode>
  145. TakeDecodingModeMap() {
  146. return image_map_.TakeDecodingModeMap();
  147. }
  148. void EmitTraceSnapshot() const;
  149. void GenerateDiscardableImagesMetadata();
  150. gfx::Rect VisualRectForTesting(int index) {
  151. return visual_rects_[static_cast<size_t>(index)];
  152. }
  153. // Generate a PaintRecord from this DisplayItemList, leaving |this| in
  154. // an empty state.
  155. sk_sp<PaintRecord> ReleaseAsRecord();
  156. // If a rectangle is solid color, returns that color. |max_ops_to_analyze|
  157. // indicates the maximum number of draw ops we consider when determining if a
  158. // rectangle is solid color.
  159. bool GetColorIfSolidInRect(const gfx::Rect& rect,
  160. SkColor4f* color,
  161. int max_ops_to_analyze = 1);
  162. std::string ToString() const;
  163. bool has_draw_ops() const { return paint_op_buffer_.has_draw_ops(); }
  164. bool has_draw_text_ops() const {
  165. return paint_op_buffer_.has_draw_text_ops();
  166. }
  167. // Ops with nested paint ops are considered as a single op.
  168. size_t num_paint_ops() const { return paint_op_buffer_.size(); }
  169. bool NeedsAdditionalInvalidationForLCDText(
  170. const DisplayItemList& old_list) const {
  171. return paint_op_buffer_.NeedsAdditionalInvalidationForLCDText(
  172. old_list.paint_op_buffer_);
  173. }
  174. private:
  175. friend class DisplayItemListTest;
  176. friend gpu::raster::RasterImplementation;
  177. friend gpu::raster::RasterImplementationGLES;
  178. ~DisplayItemList();
  179. void Reset();
  180. std::unique_ptr<base::trace_event::TracedValue> CreateTracedValue(
  181. bool include_items) const;
  182. void AddToValue(base::trace_event::TracedValue*, bool include_items) const;
  183. // If we're currently within a paired display item block, unions the
  184. // given visual rect with the begin display item's visual rect.
  185. void GrowCurrentBeginItemVisualRect(const gfx::Rect& visual_rect) {
  186. DCHECK_EQ(usage_hint_, kTopLevelDisplayItemList);
  187. if (!paired_begin_stack_.empty())
  188. visual_rects_[paired_begin_stack_.back().first_index].Union(visual_rect);
  189. }
  190. // RTree stores indices into the paint op buffer.
  191. // TODO(vmpstr): Update the rtree to store offsets instead.
  192. RTree<size_t> rtree_;
  193. DiscardableImageMap image_map_;
  194. PaintOpBuffer paint_op_buffer_;
  195. // The visual rects associated with each of the display items in the
  196. // display item list. These rects are intentionally kept separate because they
  197. // are used to decide which ops to walk for raster.
  198. std::vector<gfx::Rect> visual_rects_;
  199. // Byte offsets associated with each of the ops.
  200. std::vector<size_t> offsets_;
  201. // A stack of paired begin sequences that haven't been closed.
  202. struct PairedBeginInfo {
  203. // Index (into virual_rects_ and offsets_) of the first operation in the
  204. // paired begin sequence.
  205. size_t first_index;
  206. // Number of operations in the paired begin sequence.
  207. size_t count;
  208. };
  209. std::vector<PairedBeginInfo> paired_begin_stack_;
  210. #if DCHECK_IS_ON()
  211. // While recording a range of ops, this is the position in the PaintOpBuffer
  212. // where the recording started.
  213. bool IsPainting() const { return current_range_start_ != kNotPainting; }
  214. const size_t kNotPainting = static_cast<size_t>(-1);
  215. size_t current_range_start_ = kNotPainting;
  216. #endif
  217. UsageHint usage_hint_;
  218. friend class base::RefCountedThreadSafe<DisplayItemList>;
  219. FRIEND_TEST_ALL_PREFIXES(DisplayItemListTest, BytesUsed);
  220. };
  221. } // namespace cc
  222. #endif // CC_PAINT_DISPLAY_ITEM_LIST_H_