[M108 Migration][VD] Avoid pending frame counter becoming negative
[platform/framework/web/chromium-efl.git] / cc / tiles / picture_layer_tiling.h
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #ifndef CC_TILES_PICTURE_LAYER_TILING_H_
6 #define CC_TILES_PICTURE_LAYER_TILING_H_
7
8 #include <stddef.h>
9 #include <stdint.h>
10
11 #include <algorithm>
12 #include <map>
13 #include <memory>
14 #include <unordered_map>
15 #include <utility>
16 #include <vector>
17
18 #include "base/memory/raw_ptr.h"
19 #include "cc/base/region.h"
20 #include "cc/base/tiling_data.h"
21 #include "cc/cc_export.h"
22 #include "cc/paint/paint_worklet_input.h"
23 #include "cc/raster/raster_source.h"
24 #include "cc/tiles/tile.h"
25 #include "cc/tiles/tile_priority.h"
26 #include "cc/trees/occlusion.h"
27 #include "ui/gfx/geometry/axis_transform2d.h"
28 #include "ui/gfx/geometry/rect.h"
29
30 namespace base {
31 namespace trace_event {
32 class TracedValue;
33 }
34 }
35
36 namespace cc {
37
38 class PictureLayerTiling;
39 class PrioritizedTile;
40
41 class CC_EXPORT PictureLayerTilingClient {
42  public:
43   // Create a tile at the given content_rect (in the contents scale of the
44   // tiling) This might return null if the client cannot create such a tile.
45   virtual std::unique_ptr<Tile> CreateTile(const Tile::CreateInfo& info) = 0;
46   virtual gfx::Size CalculateTileSize(const gfx::Size& content_bounds) = 0;
47   // This invalidation region defines the area (if any, it can by null) that
48   // tiles can not be shared between pending and active trees.
49   virtual const Region* GetPendingInvalidation() = 0;
50   virtual const PictureLayerTiling* GetPendingOrActiveTwinTiling(
51       const PictureLayerTiling* tiling) const = 0;
52   virtual bool HasValidTilePriorities() const = 0;
53   virtual bool RequiresHighResToDraw() const = 0;
54   virtual const PaintWorkletRecordMap& GetPaintWorkletRecords() const = 0;
55   virtual bool IsDirectlyCompositedImage() const = 0;
56   virtual bool ScrollInteractionInProgress() const = 0;
57   virtual bool CurrentScrollCheckerboardsDueToNoRecording() const = 0;
58
59  protected:
60   virtual ~PictureLayerTilingClient() {}
61 };
62
63 struct TileMapKey {
64   TileMapKey(int x, int y) : index_x(x), index_y(y) {}
65   explicit TileMapKey(const std::pair<int, int>& index)
66       : index_x(index.first), index_y(index.second) {}
67
68   bool operator==(const TileMapKey& other) const {
69     return index_x == other.index_x && index_y == other.index_y;
70   }
71   bool operator<(const TileMapKey& other) const {
72     return std::tie(index_x, index_y) < std::tie(other.index_x, other.index_y);
73   }
74
75   int index_x;
76   int index_y;
77 };
78
79 struct TileMapKeyHash {
80   size_t operator()(const TileMapKey& key) const {
81     uint16_t value1 = static_cast<uint16_t>(key.index_x);
82     uint16_t value2 = static_cast<uint16_t>(key.index_y);
83     uint32_t value1_32 = value1;
84     return (value1_32 << 16) | value2;
85   }
86 };
87
88 class CC_EXPORT PictureLayerTiling {
89  public:
90   static const int kBorderTexels = 1;
91
92   // Note on raster_transform: In general raster_transform could be arbitrary,
93   // the only restriction is that the layer bounds after transform should
94   // be positive (because the tiling logic doesn't support negative space).
95   // Also the implementation checks the transformed bounds leaves less than
96   // 1px margin on top left edges, because there is few reason to do so.
97   PictureLayerTiling(WhichTree tree,
98                      const gfx::AxisTransform2d& raster_transform,
99                      scoped_refptr<RasterSource> raster_source,
100                      PictureLayerTilingClient* client,
101                      float min_preraster_distance,
102                      float max_preraster_distance,
103                      bool can_use_lcd_text);
104   PictureLayerTiling(const PictureLayerTiling&) = delete;
105   ~PictureLayerTiling();
106
107   PictureLayerTiling& operator=(const PictureLayerTiling&) = delete;
108
109   PictureLayerTilingClient* client() const { return client_; }
110
111   void SetRasterSourceAndResize(scoped_refptr<RasterSource> raster_source);
112   void Invalidate(const Region& layer_invalidation);
113   void CreateMissingTilesInLiveTilesRect();
114   void TakeTilesAndPropertiesFrom(PictureLayerTiling* pending_twin,
115                                   const Region& layer_invalidation);
116
117   bool IsTileRequiredForActivation(const Tile* tile) const {
118     return IsTileRequiredForActivation(
119         tile, [this](const Tile* tile) { return IsTileVisible(tile); },
120         IsTileOccluded(tile));
121   }
122
123   bool IsTileRequiredForDraw(const Tile* tile) const {
124     return IsTileRequiredForDraw(
125         tile, [this](const Tile* tile) { return IsTileVisible(tile); });
126   }
127
128   // Returns true if the tile should be processed for decoding images skipped
129   // during rasterization.
130   bool ShouldDecodeCheckeredImagesForTile(const Tile* tile) const;
131
132   void set_resolution(TileResolution resolution) {
133     resolution_ = resolution;
134     may_contain_low_resolution_tiles_ |= resolution == LOW_RESOLUTION;
135   }
136   TileResolution resolution() const { return resolution_; }
137   bool may_contain_low_resolution_tiles() const {
138     return may_contain_low_resolution_tiles_;
139   }
140   void reset_may_contain_low_resolution_tiles() {
141     may_contain_low_resolution_tiles_ = false;
142   }
143   void set_can_require_tiles_for_activation(bool can_require_tiles) {
144     can_require_tiles_for_activation_ = can_require_tiles;
145   }
146   bool can_require_tiles_for_activation() const {
147     return can_require_tiles_for_activation_;
148   }
149
150   const scoped_refptr<RasterSource>& raster_source() const {
151     return raster_source_;
152   }
153   const PaintWorkletRecordMap& GetPaintWorkletRecords() const {
154     return client_->GetPaintWorkletRecords();
155   }
156   gfx::Size tiling_size() const { return tiling_data_.tiling_size(); }
157   gfx::Rect live_tiles_rect() const { return live_tiles_rect_; }
158   gfx::Size tile_size() const { return tiling_data_.max_texture_size(); }
159   // PictureLayerTilingSet uses the scale component of the raster transform
160   // as the key for indexing and sorting. In theory we can have multiple
161   // tilings with the same scale but different translation, but currently
162   // we only allow tilings with unique scale for the sake of simplicity.
163   float contents_scale_key() const {
164     const gfx::Vector2dF& scale = raster_transform_.scale();
165     return std::max(scale.x(), scale.y());
166   }
167   const gfx::AxisTransform2d& raster_transform() const {
168     return raster_transform_;
169   }
170   const TilingData* tiling_data() const { return &tiling_data_; }
171
172   Tile* TileAt(int i, int j) const {
173     TileMap::const_iterator iter = tiles_.find(TileMapKey(i, j));
174     return iter == tiles_.end() ? nullptr : iter->second.get();
175   }
176
177   bool has_tiles() const { return !tiles_.empty(); }
178   // all_tiles_done() can return false negatives.
179   bool all_tiles_done() const { return all_tiles_done_; }
180   void set_all_tiles_done(bool all_tiles_done) {
181     all_tiles_done_ = all_tiles_done;
182   }
183
184   bool can_use_lcd_text() const { return can_use_lcd_text_; }
185
186   WhichTree tree() const { return tree_; }
187
188   void VerifyNoTileNeedsRaster() const {
189 #if DCHECK_IS_ON()
190     for (const auto& tile_pair : tiles_) {
191       DCHECK(!tile_pair.second->draw_info().NeedsRaster() ||
192              IsTileOccluded(tile_pair.second.get()));
193     }
194 #endif  // DCHECK_IS_ON()
195   }
196
197   // For testing functionality.
198   void CreateAllTilesForTesting() {
199     SetLiveTilesRect(gfx::Rect(tiling_data_.tiling_size()));
200   }
201   const TilingData& TilingDataForTesting() const { return tiling_data_; }
202   std::vector<Tile*> AllTilesForTesting() const {
203     std::vector<Tile*> all_tiles;
204     for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it)
205       all_tiles.push_back(it->second.get());
206     return all_tiles;
207   }
208
209   void UpdateAllRequiredStateForTesting() {
210     for (const auto& key_tile_pair : tiles_) {
211       Tile* tile = key_tile_pair.second.get();
212       UpdateRequiredStatesOnTile(tile);
213     }
214   }
215   std::map<const Tile*, PrioritizedTile>
216   UpdateAndGetAllPrioritizedTilesForTesting() const;
217
218   void SetAllTilesOccludedForTesting() {
219     gfx::Rect viewport_in_layer_space =
220         EnclosingLayerRectFromContentsRect(current_visible_rect_);
221     current_occlusion_in_layer_space_ =
222         Occlusion(gfx::Transform(),
223                   SimpleEnclosedRegion(viewport_in_layer_space),
224                   SimpleEnclosedRegion(viewport_in_layer_space));
225   }
226   const gfx::Rect& GetCurrentVisibleRectForTesting() const {
227     return current_visible_rect_;
228   }
229   void SetTilePriorityRectsForTesting(
230       const gfx::Rect& visible_rect_in_content_space,
231       const gfx::Rect& skewport,
232       const gfx::Rect& soon_border_rect,
233       const gfx::Rect& eventually_rect) {
234     SetTilePriorityRects(1.f, visible_rect_in_content_space, skewport,
235                          soon_border_rect, eventually_rect, Occlusion());
236   }
237
238   using TileMap =
239       std::unordered_map<TileMapKey, std::unique_ptr<Tile>, TileMapKeyHash>;
240
241   // Iterates over the tiles of a PictureLayerTiling. Order of iteration is not
242   // defined.
243   class CC_EXPORT TileIterator {
244    public:
245     explicit TileIterator(PictureLayerTiling* tiling);
246     ~TileIterator();
247
248     Tile* GetCurrent();
249     void Next();
250     bool AtEnd() const;
251
252    private:
253     PictureLayerTiling* tiling_;
254     PictureLayerTiling::TileMap::iterator iter_;
255   };
256
257   // Iterate over all tiles to fill content_rect.  Even if tiles are invalid
258   // (i.e. no valid resource) this tiling should still iterate over them.
259   // The union of all geometry_rect calls for each element iterated over should
260   // exactly equal content_rect and no two geometry_rects should intersect.
261   class CC_EXPORT CoverageIterator {
262    public:
263     CoverageIterator();
264     // This requests an iterator that produces a coverage of the
265     // |coverage_rect|, which is specified at |coverage_scale|.
266     CoverageIterator(const PictureLayerTiling* tiling,
267                      float coverage_scale,
268                      const gfx::Rect& coverage_rect);
269     ~CoverageIterator();
270
271     // Visible rect (no borders), always in the space of |coverage_rect|,
272     // regardless of the contents scale of the tiling.
273     gfx::Rect geometry_rect() const;
274     // Texture rect (in texels) for geometry_rect
275     gfx::RectF texture_rect() const;
276
277     Tile* operator->() const { return current_tile_; }
278     Tile* operator*() const { return current_tile_; }
279
280     CoverageIterator& operator++();
281     operator bool() const { return tile_j_ <= bottom_; }
282
283     int i() const { return tile_i_; }
284     int j() const { return tile_j_; }
285
286    private:
287     gfx::Rect ComputeGeometryRect() const;
288
289     // `tiling_` is not a raw_ptr<...> for performance reasons (based on
290     // analysis of sampling profiler data and tab_search:top100:2020).
291     RAW_PTR_EXCLUSION const PictureLayerTiling* tiling_ = nullptr;
292
293     gfx::Size coverage_rect_max_bounds_;
294     gfx::Rect coverage_rect_;
295     gfx::AxisTransform2d coverage_to_content_;
296
297     // `current_tile_` is not a raw_ptr<...> for performance reasons (based on
298     // analysis of sampling profiler data and tab_search:top100:2020).
299     RAW_PTR_EXCLUSION Tile* current_tile_ = nullptr;
300
301     gfx::Rect current_geometry_rect_;
302     int tile_i_ = 0;
303     int tile_j_ = 0;
304     int left_ = 0;
305     int top_ = 0;
306     int right_ = -1;
307     int bottom_ = -1;
308
309     friend class PictureLayerTiling;
310   };
311
312   void Reset();
313
314   void ComputeTilePriorityRects(
315       const gfx::Rect& visible_rect_in_layer_space,
316       const gfx::Rect& skewport_in_layer_space,
317       const gfx::Rect& soon_border_rect_in_layer_space,
318       const gfx::Rect& eventually_rect_in_layer_space,
319       float ideal_contents_scale,
320       const Occlusion& occlusion_in_layer_space);
321
322   void GetAllPrioritizedTilesForTracing(
323       std::vector<PrioritizedTile>* prioritized_tiles) const;
324   void AsValueInto(base::trace_event::TracedValue* array) const;
325   size_t GPUMemoryUsageInBytes() const;
326
327   void UpdateRequiredStatesOnTile(Tile* tile) const;
328
329  protected:
330   friend class CoverageIterator;
331   friend class PrioritizedTile;
332   friend class TileIterator;
333   friend class TilingSetRasterQueueAll;
334   friend class TilingSetRasterQueueRequired;
335   friend class TilingSetEvictionQueue;
336   friend class TilesWithResourceIterator;
337
338   // PENDING VISIBLE RECT refers to the visible rect that will become current
339   // upon activation (ie, the pending tree's visible rect). Tiles in this
340   // region that are not part of the current visible rect are all handled
341   // here. Note that when processing a pending tree, this rect is the same as
342   // the visible rect so no tiles are processed in this case.
343   enum PriorityRectType {
344     VISIBLE_RECT,
345     PENDING_VISIBLE_RECT,
346     SKEWPORT_RECT,
347     SOON_BORDER_RECT,
348     EVENTUALLY_RECT
349   };
350
351   bool IsTileVisible(const Tile* tile) const {
352     gfx::Rect tile_bounds =
353         tiling_data_.TileBounds(tile->tiling_i_index(), tile->tiling_j_index());
354     return tile_bounds.Intersects(current_visible_rect_);
355   }
356
357   template <typename VisibilityChecker>
358   bool IsTileRequiredForActivation(const Tile* tile,
359                                    VisibilityChecker is_visible,
360                                    bool is_tile_occluded) const {
361     if (tree_ == PENDING_TREE) {
362       if (!can_require_tiles_for_activation_ ||
363           resolution_ != HIGH_RESOLUTION || is_tile_occluded) {
364         return false;
365       }
366
367       // We may be checking the active tree tile here (since this function is
368       // also called for active trees below, ensure that this is at all a valid
369       // tile on the pending tree.
370       if (tile->tiling_i_index() >= tiling_data_.num_tiles_x() ||
371           tile->tiling_j_index() >= tiling_data_.num_tiles_y()) {
372         return false;
373       }
374
375       if (!is_visible(tile))
376         return false;
377
378       if (client_->RequiresHighResToDraw())
379         return true;
380
381       const PictureLayerTiling* active_twin =
382           client_->GetPendingOrActiveTwinTiling(this);
383       if (!active_twin || !TilingMatchesTileIndices(active_twin))
384         return true;
385
386       if (active_twin->raster_source()->GetSize() != raster_source()->GetSize())
387         return true;
388
389       if (active_twin->current_visible_rect_ != current_visible_rect_)
390         return true;
391
392       Tile* twin_tile =
393           active_twin->TileAt(tile->tiling_i_index(), tile->tiling_j_index());
394       if (!twin_tile)
395         return false;
396       return true;
397     }
398
399     DCHECK_EQ(tree_, ACTIVE_TREE);
400     const PictureLayerTiling* pending_twin =
401         client_->GetPendingOrActiveTwinTiling(this);
402     // If we don't have a pending tree, or the pending tree will overwrite the
403     // given tile, then it is not required for activation.
404     if (!pending_twin || !TilingMatchesTileIndices(pending_twin) ||
405         pending_twin->TileAt(tile->tiling_i_index(), tile->tiling_j_index())) {
406       return false;
407     }
408     // Otherwise, ask the pending twin if this tile is required for activation.
409     return pending_twin->IsTileRequiredForActivation(tile);
410   }
411
412   template <typename VisibilityChecker>
413   bool IsTileRequiredForDraw(const Tile* tile,
414                              VisibilityChecker is_visible) const {
415     return tree_ == ACTIVE_TREE && resolution_ == HIGH_RESOLUTION &&
416            is_visible(tile) && !IsTileOccludedOnCurrentTree(tile);
417   }
418
419   void SetLiveTilesRect(const gfx::Rect& live_tiles_rect);
420   void VerifyLiveTilesRect() const;
421   Tile* CreateTile(const Tile::CreateInfo& info);
422   // Removes the tile at i, j and returns it. Returns nullptr if the tile did
423   // not exist.
424   std::unique_ptr<Tile> TakeTileAt(int i, int j);
425   bool TilingMatchesTileIndices(const PictureLayerTiling* twin) const;
426
427   // Save the required data for computing tile priorities later.
428   void SetTilePriorityRects(float content_to_screen_scale,
429                             const gfx::Rect& visible_rect_in_content_space,
430                             const gfx::Rect& skewport,
431                             const gfx::Rect& soon_border_rect,
432                             const gfx::Rect& eventually_rect,
433                             const Occlusion& occlusion_in_layer_space);
434
435   bool IsTileOccludedOnCurrentTree(const Tile* tile) const;
436   Tile::CreateInfo CreateInfoForTile(int i, int j) const;
437   bool ShouldCreateTileAt(const Tile::CreateInfo& info) const;
438
439   bool IsTileOccluded(const Tile* tile) const {
440     // If this tile is not occluded on this tree, then it is not occluded.
441     if (!IsTileOccludedOnCurrentTree(tile))
442       return false;
443
444     // Otherwise, if this is the pending tree, we're done and the tile is
445     // occluded.
446     if (tree_ == PENDING_TREE)
447       return true;
448
449     // On the active tree however, we need to check if this tile will be
450     // unoccluded upon activation, in which case it has to be considered
451     // unoccluded.
452     const PictureLayerTiling* pending_twin =
453         client_->GetPendingOrActiveTwinTiling(this);
454     if (pending_twin) {
455       // If there's a pending tile in the same position. Or if the pending twin
456       // would have to be creating all tiles, then we don't need to worry about
457       // occlusion on the twin.
458       if (!TilingMatchesTileIndices(pending_twin) ||
459           pending_twin->TileAt(tile->tiling_i_index(),
460                                tile->tiling_j_index())) {
461         return true;
462       }
463       return pending_twin->IsTileOccludedOnCurrentTree(tile);
464     }
465     return true;
466   }
467
468   PrioritizedTile MakePrioritizedTile(Tile* tile,
469                                       PriorityRectType priority_rect_type,
470                                       bool is_tile_occluded) const;
471   TilePriority ComputePriorityForTile(const Tile* tile,
472                                       PriorityRectType priority_rect_type,
473                                       bool is_tile_occluded) const;
474   PriorityRectType ComputePriorityRectTypeForTile(const Tile* tile) const;
475   bool has_visible_rect_tiles() const { return has_visible_rect_tiles_; }
476   bool has_skewport_rect_tiles() const { return has_skewport_rect_tiles_; }
477   bool has_soon_border_rect_tiles() const {
478     return has_soon_border_rect_tiles_;
479   }
480   bool has_eventually_rect_tiles() const { return has_eventually_rect_tiles_; }
481
482   const gfx::Rect& current_visible_rect() const {
483     return current_visible_rect_;
484   }
485   gfx::Rect pending_visible_rect() const {
486     const PictureLayerTiling* pending_tiling =
487         tree_ == ACTIVE_TREE ? client_->GetPendingOrActiveTwinTiling(this)
488                              : this;
489     if (pending_tiling)
490       return pending_tiling->current_visible_rect();
491     return gfx::Rect();
492   }
493   const gfx::Rect& current_skewport_rect() const {
494     return current_skewport_rect_;
495   }
496   const gfx::Rect& current_soon_border_rect() const {
497     return current_soon_border_rect_;
498   }
499   const gfx::Rect& current_eventually_rect() const {
500     return current_eventually_rect_;
501   }
502   void RemoveTilesInRegion(const Region& layer_region, bool recreate_tiles);
503
504   gfx::Rect EnclosingContentsRectFromLayerRect(
505       const gfx::Rect& layer_rect) const;
506   gfx::Rect EnclosingLayerRectFromContentsRect(
507       const gfx::Rect& contents_rect) const;
508
509   // Given properties.
510   const gfx::AxisTransform2d raster_transform_;
511   const raw_ptr<PictureLayerTilingClient> client_;
512   const WhichTree tree_;
513   scoped_refptr<RasterSource> raster_source_;
514   const float min_preraster_distance_;
515   const float max_preraster_distance_;
516   TileResolution resolution_ = NON_IDEAL_RESOLUTION;
517   bool may_contain_low_resolution_tiles_ = false;
518
519   // Internal data.
520   TilingData tiling_data_ = TilingData(gfx::Size(), gfx::Size(), kBorderTexels);
521   TileMap tiles_;  // It is not legal to have a NULL tile in the tiles_ map.
522   gfx::Rect live_tiles_rect_;
523
524   bool can_require_tiles_for_activation_ = false;
525
526   // Iteration rects in content space.
527   gfx::Rect current_visible_rect_;
528   gfx::Rect current_skewport_rect_;
529   gfx::Rect current_soon_border_rect_;
530   gfx::Rect current_eventually_rect_;
531   // Other properties used for tile iteration and prioritization.
532   float current_content_to_screen_scale_ = 0.f;
533   Occlusion current_occlusion_in_layer_space_;
534   float max_skewport_extent_in_screen_space_ = 0.f;
535
536   bool has_visible_rect_tiles_ = false;
537   bool has_skewport_rect_tiles_ = false;
538   bool has_soon_border_rect_tiles_ = false;
539   bool has_eventually_rect_tiles_ = false;
540   bool all_tiles_done_ = true;
541   bool can_use_lcd_text_;
542 };
543
544 }  // namespace cc
545
546 #endif  // CC_TILES_PICTURE_LAYER_TILING_H_