File: picture_layer_tiling.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (495 lines) | stat: -rw-r--r-- 18,487 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CC_TILES_PICTURE_LAYER_TILING_H_
#define CC_TILES_PICTURE_LAYER_TILING_H_

#include <stddef.h>
#include <stdint.h>

#include <algorithm>
#include <map>
#include <memory>
#include <unordered_map>
#include <utility>
#include <vector>

#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ptr_exclusion.h"
#include "cc/base/region.h"
#include "cc/base/tiling_data.h"
#include "cc/cc_export.h"
#include "cc/paint/paint_worklet_input.h"
#include "cc/paint/scroll_offset_map.h"
#include "cc/raster/raster_source.h"
#include "cc/tiles/tile.h"
#include "cc/tiles/tile_index.h"
#include "cc/tiles/tile_priority.h"
#include "cc/tiles/tiling_coverage_iterator.h"
#include "cc/trees/occlusion.h"
#include "ui/gfx/geometry/axis_transform2d.h"
#include "ui/gfx/geometry/rect.h"

namespace base {
namespace trace_event {
class TracedValue;
}
}

namespace cc {

class DrawImage;
class GlobalStateThatImpactsTilePriority;
class PictureLayerTiling;
class PrioritizedTile;

class CC_EXPORT PictureLayerTilingClient {
 public:
  // Create a tile at the given content_rect (in the contents scale of the
  // tiling) This might return null if the client cannot create such a tile.
  virtual std::unique_ptr<Tile> CreateTile(const Tile::CreateInfo& info) = 0;
  virtual gfx::Size CalculateTileSize(const gfx::Size& content_bounds) = 0;
  // This invalidation region defines the area (if any, it can by null) that
  // tiles can not be shared between pending and active trees.
  virtual const Region* GetPendingInvalidation() = 0;
  virtual const PictureLayerTiling* GetPendingOrActiveTwinTiling(
      const PictureLayerTiling* tiling) const = 0;
  virtual bool HasValidTilePriorities() const = 0;
  virtual bool RequiresHighResToDraw() const = 0;
  virtual const PaintWorkletRecordMap& GetPaintWorkletRecords() const = 0;
  virtual std::vector<const DrawImage*> GetDiscardableImagesInRect(
      const gfx::Rect& rect) const = 0;
  virtual ScrollOffsetMap GetRasterInducingScrollOffsets() const = 0;
  virtual const GlobalStateThatImpactsTilePriority& global_tile_state()
      const = 0;

 protected:
  virtual ~PictureLayerTilingClient() {}
};

class PictureLayerTilingCoverageIterator;

class CC_EXPORT PictureLayerTiling {
 public:
  using Tile = Tile;
  using CoverageIterator = PictureLayerTilingCoverageIterator;

  static const int kBorderTexels = 1;

  // Note on raster_transform: In general raster_transform could be arbitrary,
  // the only restriction is that the layer bounds after transform should
  // be positive (because the tiling logic doesn't support negative space).
  // Also the implementation checks the transformed bounds leaves less than
  // 1px margin on top left edges, because there is few reason to do so.
  PictureLayerTiling(WhichTree tree,
                     const gfx::AxisTransform2d& raster_transform,
                     scoped_refptr<RasterSource> raster_source,
                     PictureLayerTilingClient* client,
                     float min_preraster_distance,
                     float max_preraster_distance,
                     bool can_use_lcd_text);
  PictureLayerTiling(const PictureLayerTiling&) = delete;
  ~PictureLayerTiling();

  PictureLayerTiling& operator=(const PictureLayerTiling&) = delete;

  PictureLayerTilingClient* client() const { return client_; }

  // Returns true if the current tiling needs to update tile priority rects and
  // tiles.
  bool SetRasterSourceAndResize(scoped_refptr<RasterSource> raster_source);
  void Invalidate(const Region& layer_invalidation);
  void CreateMissingTilesInLiveTilesRect();
  void TakeTilesAndPropertiesFrom(PictureLayerTiling* pending_twin,
                                  const Region& layer_invalidation);

  bool IsTileRequiredForActivation(const Tile* tile) const {
    return IsTileRequiredForActivation(
        tile, [this](const Tile* tile) { return IsTileVisible(tile); },
        IsTileOccluded(tile));
  }

  bool IsTileRequiredForDraw(const Tile* tile) const {
    return IsTileRequiredForDraw(
        tile, [this](const Tile* tile) { return IsTileVisible(tile); });
  }

  // Returns true if the tile should be processed for decoding images skipped
  // during rasterization.
  bool ShouldDecodeCheckeredImagesForTile(const Tile* tile) const;

  void set_resolution(TileResolution resolution) {
    resolution_ = resolution;
  }
  TileResolution resolution() const { return resolution_; }
  void set_can_require_tiles_for_activation(bool can_require_tiles) {
    can_require_tiles_for_activation_ = can_require_tiles;
  }
  bool can_require_tiles_for_activation() const {
    return can_require_tiles_for_activation_;
  }

  gfx::Size raster_size() const { return raster_source()->size(); }
  const scoped_refptr<RasterSource>& raster_source() const {
    return raster_source_;
  }
  const PaintWorkletRecordMap& GetPaintWorkletRecords() const {
    return client_->GetPaintWorkletRecords();
  }
  ScrollOffsetMap GetRasterInducingScrollOffsets() const {
    return client_->GetRasterInducingScrollOffsets();
  }
  const gfx::Rect& tiling_rect() const { return tiling_data_.tiling_rect(); }
  const gfx::Rect& live_tiles_rect() const { return live_tiles_rect_; }
  gfx::Size tile_size() const { return tiling_data_.max_texture_size(); }
  // PictureLayerTilingSet uses the scale component of the raster transform
  // as the key for indexing and sorting. In theory we can have multiple
  // tilings with the same scale but different translation, but currently
  // we only allow tilings with unique scale for the sake of simplicity.
  float contents_scale_key() const {
    const gfx::Vector2dF& scale = raster_transform_.scale();
    return std::max(scale.x(), scale.y());
  }
  const gfx::AxisTransform2d& raster_transform() const {
    return raster_transform_;
  }
  const TilingData* tiling_data() const { return &tiling_data_; }

  Tile* TileAt(int i, int j) const { return TileAt(TileIndex(i, j)); }

  Tile* TileAt(const TileIndex& index) const {
    TileMap::const_iterator iter = tiles_.find(index);
    return iter == tiles_.end() ? nullptr : iter->second.get();
  }

  bool has_tiles() const { return !tiles_.empty(); }
  // all_tiles_done() can return false negatives.
  bool all_tiles_done() const { return all_tiles_done_; }
  void set_all_tiles_done(bool all_tiles_done) {
    all_tiles_done_ = all_tiles_done;
  }

  bool can_use_lcd_text() const { return can_use_lcd_text_; }

  WhichTree tree() const { return tree_; }

  void VerifyNoTileNeedsRaster() const {
#if DCHECK_IS_ON()
    for (const auto& tile_pair : tiles_) {
      DCHECK(!tile_pair.second->draw_info().NeedsRaster() ||
             IsTileOccluded(tile_pair.second.get()));
    }
#endif  // DCHECK_IS_ON()
  }

  // For testing functionality.
  void CreateAllTilesForTesting() {
    CreateAllTilesForTesting(tiling_data_.tiling_rect());
  }
  void CreateAllTilesForTesting(const gfx::Rect& rect_to_raster);
  const TilingData& TilingDataForTesting() const { return tiling_data_; }
  std::vector<Tile*> AllTilesForTesting() const {
    std::vector<Tile*> all_tiles;
    for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it)
      all_tiles.push_back(it->second.get());
    return all_tiles;
  }

  void UpdateAllRequiredStateForTesting() {
    for (const auto& [index, tile] : tiles_) {
      UpdateRequiredStatesOnTile(tile.get());
    }
  }
  std::map<const Tile*, PrioritizedTile>
  UpdateAndGetAllPrioritizedTilesForTesting() const;

  void SetAllTilesOccludedForTesting() {
    gfx::Rect viewport_in_layer_space =
        EnclosingLayerRectFromContentsRect(current_visible_rect_);
    current_occlusion_in_layer_space_ =
        Occlusion(gfx::Transform(),
                  SimpleEnclosedRegion(viewport_in_layer_space),
                  SimpleEnclosedRegion(viewport_in_layer_space));
  }
  const gfx::Rect& GetCurrentVisibleRectForTesting() const {
    return current_visible_rect_;
  }
  void SetTilePriorityRectsForTesting(const gfx::Rect& visible_rect,
                                      const gfx::Rect& skewport_rect,
                                      const gfx::Rect& soon_border_rect,
                                      const gfx::Rect& eventually_rect,
                                      bool evicts_tiles = false);

  using TileMap = std::unordered_map<TileIndex, std::unique_ptr<Tile>>;

  // Iterates over the tiles of a PictureLayerTiling. Order of iteration is not
  // defined.
  class CC_EXPORT TileIterator {
   public:
    explicit TileIterator(PictureLayerTiling* tiling);
    ~TileIterator();

    Tile* GetCurrent();
    void Next();
    bool AtEnd() const;

   private:
    raw_ptr<PictureLayerTiling> tiling_;
    PictureLayerTiling::TileMap::iterator iter_;
  };

  void Reset();

  void ComputeTilePriorityRects(
      const gfx::Rect& visible_rect_in_layer_space,
      const gfx::Rect& skewport_rect_in_layer_space,
      const gfx::Rect& soon_border_rect_in_layer_space,
      const gfx::Rect& eventually_rect_in_layer_space,
      float ideal_contents_scale,
      const Occlusion& occlusion_in_layer_space);

  void GetAllPrioritizedTilesForTracing(
      std::vector<PrioritizedTile>* prioritized_tiles) const;
  void AsValueInto(base::trace_event::TracedValue* array) const;
  size_t GPUMemoryUsageInBytes() const;

  void UpdateRequiredStatesOnTile(Tile* tile) const;

  // Creates a coverage iterator to iterate over a minimal set of tiles from
  // this tiling to cover `rect`, which has been pre-scaled by `scale`.
  CoverageIterator Cover(const gfx::Rect& rect, float scale) const;

 protected:
  friend class PrioritizedTile;
  friend class TileIterator;
  friend class TilingSetRasterQueueAll;
  friend class TilingSetRasterQueueRequired;
  friend class TilingSetEvictionQueue;
  friend class TilesWithResourceIterator;

  // PENDING VISIBLE RECT refers to the visible rect that will become current
  // upon activation (ie, the pending tree's visible rect). Tiles in this
  // region that are not part of the current visible rect are all handled
  // here. Note that when processing a pending tree, this rect is the same as
  // the visible rect so no tiles are processed in this case.
  enum PriorityRectType {
    VISIBLE_RECT,
    PENDING_VISIBLE_RECT,
    SKEWPORT_RECT,
    SOON_BORDER_RECT,
    EVENTUALLY_RECT
  };

  bool IsTileVisible(const Tile* tile) const {
    gfx::Rect tile_bounds =
        tiling_data_.TileBounds(tile->tiling_i_index(), tile->tiling_j_index());
    return tile_bounds.Intersects(current_visible_rect_);
  }

  template <typename VisibilityChecker>
  bool IsTileRequiredForActivation(const Tile* tile,
                                   VisibilityChecker is_visible,
                                   bool is_tile_occluded) const {
    if (tree_ == PENDING_TREE) {
      if (!can_require_tiles_for_activation_ ||
          resolution_ != HIGH_RESOLUTION || is_tile_occluded) {
        return false;
      }

      // We may be checking the active tree tile here (since this function is
      // also called for active trees below, ensure that this is at all a valid
      // tile on the pending tree.
      if (tile->tiling_i_index() >= tiling_data_.num_tiles_x() ||
          tile->tiling_j_index() >= tiling_data_.num_tiles_y()) {
        return false;
      }

      if (!is_visible(tile))
        return false;

      if (client_->RequiresHighResToDraw())
        return true;

      const PictureLayerTiling* active_twin =
          client_->GetPendingOrActiveTwinTiling(this);
      if (!active_twin || !TilingMatchesTileIndices(active_twin))
        return true;

      if (active_twin->raster_source()->size() != raster_source()->size() ||
          active_twin->raster_source()->recorded_bounds() !=
              raster_source()->recorded_bounds()) {
        return true;
      }

      if (active_twin->current_visible_rect_ != current_visible_rect_)
        return true;

      Tile* twin_tile =
          active_twin->TileAt(tile->tiling_i_index(), tile->tiling_j_index());
      if (!twin_tile)
        return false;
      return true;
    }

    DCHECK_EQ(tree_, ACTIVE_TREE);
    const PictureLayerTiling* pending_twin =
        client_->GetPendingOrActiveTwinTiling(this);
    // If we don't have a pending tree, or the pending tree will overwrite the
    // given tile, then it is not required for activation.
    if (!pending_twin || !TilingMatchesTileIndices(pending_twin) ||
        pending_twin->TileAt(tile->tiling_i_index(), tile->tiling_j_index())) {
      return false;
    }
    // Otherwise, ask the pending twin if this tile is required for activation.
    return pending_twin->IsTileRequiredForActivation(tile);
  }

  template <typename VisibilityChecker>
  bool IsTileRequiredForDraw(const Tile* tile,
                             VisibilityChecker is_visible) const {
    return tree_ == ACTIVE_TREE && resolution_ == HIGH_RESOLUTION &&
           is_visible(tile) && !IsTileOccludedOnCurrentTree(tile);
  }

  void SetLiveTilesRect(const gfx::Rect& live_tiles_rect);
  void VerifyTiles() const;
  Tile* CreateTile(const Tile::CreateInfo& info);
  // Removes the tile at i, j and returns it. Returns nullptr if the tile did
  // not exist.
  std::unique_ptr<Tile> TakeTileAt(int i, int j);
  bool TilingMatchesTileIndices(const PictureLayerTiling* twin) const;

  void SetPriorityRect(const gfx::Rect& rect_in_layer_space,
                       PriorityRectType rect_type,
                       bool evicts_tiles = false);

  bool IsTileOccludedOnCurrentTree(const Tile* tile) const;
  Tile::CreateInfo CreateInfoForTile(int i, int j) const;
  bool ShouldCreateTileAt(const Tile::CreateInfo& info) const;

  bool IsTileOccluded(const Tile* tile) const {
    // If this tile is not occluded on this tree, then it is not occluded.
    if (!IsTileOccludedOnCurrentTree(tile))
      return false;

    // Otherwise, if this is the pending tree, we're done and the tile is
    // occluded.
    if (tree_ == PENDING_TREE)
      return true;

    // On the active tree however, we need to check if this tile will be
    // unoccluded upon activation, in which case it has to be considered
    // unoccluded.
    const PictureLayerTiling* pending_twin =
        client_->GetPendingOrActiveTwinTiling(this);
    if (pending_twin) {
      // If there's a pending tile in the same position. Or if the pending twin
      // would have to be creating all tiles, then we don't need to worry about
      // occlusion on the twin.
      if (!TilingMatchesTileIndices(pending_twin) ||
          pending_twin->TileAt(tile->tiling_i_index(),
                               tile->tiling_j_index())) {
        return true;
      }
      return pending_twin->IsTileOccludedOnCurrentTree(tile);
    }
    return true;
  }

  PrioritizedTile MakePrioritizedTile(Tile* tile,
                                      PriorityRectType priority_rect_type,
                                      bool is_tile_occluded) const;
  TilePriority ComputePriorityForTile(const Tile* tile,
                                      PriorityRectType priority_rect_type,
                                      bool is_tile_occluded) const;
  PriorityRectType ComputePriorityRectTypeForTile(const Tile* tile) const;
  bool has_visible_rect_tiles() const { return has_visible_rect_tiles_; }
  bool has_skewport_rect_tiles() const { return has_skewport_rect_tiles_; }
  bool has_soon_border_rect_tiles() const {
    return has_soon_border_rect_tiles_;
  }
  bool has_eventually_rect_tiles() const { return has_eventually_rect_tiles_; }

  const gfx::Rect& current_visible_rect() const {
    return current_visible_rect_;
  }
  gfx::Rect pending_visible_rect() const {
    const PictureLayerTiling* pending_tiling =
        tree_ == ACTIVE_TREE ? client_->GetPendingOrActiveTwinTiling(this)
                             : this;
    if (pending_tiling)
      return pending_tiling->current_visible_rect();
    return gfx::Rect();
  }
  const gfx::Rect& current_skewport_rect() const {
    return current_skewport_rect_;
  }
  const gfx::Rect& current_soon_border_rect() const {
    return current_soon_border_rect_;
  }
  const gfx::Rect& current_eventually_rect() const {
    return current_eventually_rect_;
  }
  void RemoveTilesInRegion(const Region& layer_region, bool recreate_tiles);

  gfx::Rect EnclosingContentsRectFromLayerRect(
      const gfx::Rect& layer_rect) const;
  gfx::Rect EnclosingLayerRectFromContentsRect(
      const gfx::Rect& contents_rect) const;

  gfx::Rect ComputeTilingRect() const;
  void SetTilingRect(const gfx::Rect& tiling_rect);

  // Given properties.
  const gfx::AxisTransform2d raster_transform_;
  const raw_ptr<PictureLayerTilingClient> client_;
  const WhichTree tree_;
  scoped_refptr<RasterSource> raster_source_;
  const float min_preraster_distance_;
  const float max_preraster_distance_;
  TileResolution resolution_ = NON_IDEAL_RESOLUTION;

  // Internal data.
  TilingData tiling_data_{gfx::Size(), gfx::Rect(), kBorderTexels};
  TileMap tiles_;  // It is not legal to have a NULL tile in the tiles_ map.
  gfx::Rect live_tiles_rect_;

  bool can_require_tiles_for_activation_ = false;

  gfx::Rect tiling_rect_in_layer_space_;

  // Iteration rects in content space.
  gfx::Rect current_visible_rect_;
  gfx::Rect current_skewport_rect_;
  gfx::Rect current_soon_border_rect_;
  gfx::Rect current_eventually_rect_;

  // Iteration rects in layer space.
  gfx::Rect current_visible_rect_in_layer_space_;
  gfx::Rect current_skewport_rect_in_layer_space_;
  gfx::Rect current_soon_border_rect_in_layer_space_;
  gfx::Rect current_eventually_rect_in_layer_space_;

  // Other properties used for tile iteration and prioritization.
  float current_content_to_screen_scale_ = 0.f;
  Occlusion current_occlusion_in_layer_space_;
  float max_skewport_extent_in_screen_space_ = 0.f;

  bool has_visible_rect_tiles_ : 1 = false;
  bool has_skewport_rect_tiles_ : 1 = false;
  bool has_soon_border_rect_tiles_ : 1 = false;
  bool has_eventually_rect_tiles_ : 1 = false;
  bool all_tiles_done_ : 1 = true;
  bool can_use_lcd_text_ : 1;
};

class PictureLayerTilingCoverageIterator
    : public TilingCoverageIterator<PictureLayerTiling> {
 public:
  using TilingCoverageIterator<PictureLayerTiling>::TilingCoverageIterator;
};

}  // namespace cc

#endif  // CC_TILES_PICTURE_LAYER_TILING_H_