1 // Copyright 2012 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 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 <map> 12 #include <memory> 13 #include <unordered_map> 14 #include <utility> 15 #include <vector> 16 17 #include "cc/base/region.h" 18 #include "cc/base/tiling_data.h" 19 #include "cc/cc_export.h" 20 #include "cc/paint/paint_worklet_input.h" 21 #include "cc/tiles/tile.h" 22 #include "cc/tiles/tile_priority.h" 23 #include "cc/trees/occlusion.h" 24 #include "ui/gfx/geometry/axis_transform2d.h" 25 #include "ui/gfx/geometry/rect.h" 26 27 namespace base { 28 namespace trace_event { 29 class TracedValue; 30 } 31 } 32 33 namespace cc { 34 35 class RasterSource; 36 class PictureLayerTiling; 37 class PrioritizedTile; 38 39 class CC_EXPORT PictureLayerTilingClient { 40 public: 41 // Create a tile at the given content_rect (in the contents scale of the 42 // tiling) This might return null if the client cannot create such a tile. 43 virtual std::unique_ptr<Tile> CreateTile(const Tile::CreateInfo& info) = 0; 44 virtual gfx::Size CalculateTileSize(const gfx::Size& content_bounds) = 0; 45 // This invalidation region defines the area (if any, it can by null) that 46 // tiles can not be shared between pending and active trees. 47 virtual const Region* GetPendingInvalidation() = 0; 48 virtual const PictureLayerTiling* GetPendingOrActiveTwinTiling( 49 const PictureLayerTiling* tiling) const = 0; 50 virtual bool HasValidTilePriorities() const = 0; 51 virtual bool RequiresHighResToDraw() const = 0; 52 virtual const PaintWorkletRecordMap& GetPaintWorkletRecords() const = 0; 53 54 protected: ~PictureLayerTilingClient()55 virtual ~PictureLayerTilingClient() {} 56 }; 57 58 struct TileMapKey { TileMapKeyTileMapKey59 TileMapKey(int x, int y) : index_x(x), index_y(y) {} TileMapKeyTileMapKey60 explicit TileMapKey(const std::pair<int, int>& index) 61 : index_x(index.first), index_y(index.second) {} 62 63 bool operator==(const TileMapKey& other) const { 64 return index_x == other.index_x && index_y == other.index_y; 65 } 66 bool operator<(const TileMapKey& other) const { 67 return std::tie(index_x, index_y) < std::tie(other.index_x, other.index_y); 68 } 69 70 int index_x; 71 int index_y; 72 }; 73 74 struct TileMapKeyHash { operatorTileMapKeyHash75 size_t operator()(const TileMapKey& key) const { 76 uint16_t value1 = static_cast<uint16_t>(key.index_x); 77 uint16_t value2 = static_cast<uint16_t>(key.index_y); 78 uint32_t value1_32 = value1; 79 return (value1_32 << 16) | value2; 80 } 81 }; 82 83 class CC_EXPORT PictureLayerTiling { 84 public: 85 static const int kBorderTexels = 1; 86 87 // Note on raster_transform: In general raster_transform could be arbitrary, 88 // the only restriction is that the layer bounds after transform should 89 // be positive (because the tiling logic doesn't support negative space). 90 // Also the implementation checks the transformed bounds leaves less than 91 // 1px margin on top left edges, because there is few reason to do so. 92 PictureLayerTiling(WhichTree tree, 93 const gfx::AxisTransform2d& raster_transform, 94 scoped_refptr<RasterSource> raster_source, 95 PictureLayerTilingClient* client, 96 float min_preraster_distance, 97 float max_preraster_distance); 98 PictureLayerTiling(const PictureLayerTiling&) = delete; 99 ~PictureLayerTiling(); 100 101 PictureLayerTiling& operator=(const PictureLayerTiling&) = delete; 102 client()103 PictureLayerTilingClient* client() const { return client_; } 104 105 void SetRasterSourceAndResize(scoped_refptr<RasterSource> raster_source); 106 void Invalidate(const Region& layer_invalidation); 107 void CreateMissingTilesInLiveTilesRect(); 108 void TakeTilesAndPropertiesFrom(PictureLayerTiling* pending_twin, 109 const Region& layer_invalidation); 110 111 bool IsTileRequiredForActivation(const Tile* tile) const; 112 bool IsTileRequiredForDraw(const Tile* tile) const; 113 114 // Returns true if the tile should be processed for decoding images skipped 115 // during rasterization. 116 bool ShouldDecodeCheckeredImagesForTile(const Tile* tile) const; 117 set_resolution(TileResolution resolution)118 void set_resolution(TileResolution resolution) { 119 resolution_ = resolution; 120 may_contain_low_resolution_tiles_ |= resolution == LOW_RESOLUTION; 121 } resolution()122 TileResolution resolution() const { return resolution_; } may_contain_low_resolution_tiles()123 bool may_contain_low_resolution_tiles() const { 124 return may_contain_low_resolution_tiles_; 125 } reset_may_contain_low_resolution_tiles()126 void reset_may_contain_low_resolution_tiles() { 127 may_contain_low_resolution_tiles_ = false; 128 } set_can_require_tiles_for_activation(bool can_require_tiles)129 void set_can_require_tiles_for_activation(bool can_require_tiles) { 130 can_require_tiles_for_activation_ = can_require_tiles; 131 } can_require_tiles_for_activation()132 bool can_require_tiles_for_activation() const { 133 return can_require_tiles_for_activation_; 134 } 135 raster_source()136 const scoped_refptr<RasterSource>& raster_source() const { 137 return raster_source_; 138 } GetPaintWorkletRecords()139 const PaintWorkletRecordMap& GetPaintWorkletRecords() const { 140 return client_->GetPaintWorkletRecords(); 141 } tiling_size()142 gfx::Size tiling_size() const { return tiling_data_.tiling_size(); } live_tiles_rect()143 gfx::Rect live_tiles_rect() const { return live_tiles_rect_; } tile_size()144 gfx::Size tile_size() const { return tiling_data_.max_texture_size(); } 145 // PictureLayerTilingSet uses the scale component of the raster transform 146 // as the key for indexing and sorting. In theory we can have multiple 147 // tilings with the same scale but different translation, but currently 148 // we only allow tilings with unique scale for the sake of simplicity. contents_scale_key()149 float contents_scale_key() const { return raster_transform_.scale(); } raster_transform()150 const gfx::AxisTransform2d& raster_transform() const { 151 return raster_transform_; 152 } tiling_data()153 const TilingData* tiling_data() const { return &tiling_data_; } 154 TileAt(int i,int j)155 Tile* TileAt(int i, int j) const { 156 TileMap::const_iterator iter = tiles_.find(TileMapKey(i, j)); 157 return iter == tiles_.end() ? nullptr : iter->second.get(); 158 } 159 has_tiles()160 bool has_tiles() const { return !tiles_.empty(); } 161 // all_tiles_done() can return false negatives. all_tiles_done()162 bool all_tiles_done() const { return all_tiles_done_; } set_all_tiles_done(bool all_tiles_done)163 void set_all_tiles_done(bool all_tiles_done) { 164 all_tiles_done_ = all_tiles_done; 165 } 166 tree()167 WhichTree tree() const { return tree_; } 168 VerifyNoTileNeedsRaster()169 void VerifyNoTileNeedsRaster() const { 170 #if DCHECK_IS_ON() 171 for (const auto& tile_pair : tiles_) { 172 DCHECK(!tile_pair.second->draw_info().NeedsRaster() || 173 IsTileOccluded(tile_pair.second.get())); 174 } 175 #endif // DCHECK_IS_ON() 176 } 177 178 // For testing functionality. CreateAllTilesForTesting()179 void CreateAllTilesForTesting() { 180 SetLiveTilesRect(gfx::Rect(tiling_data_.tiling_size())); 181 } TilingDataForTesting()182 const TilingData& TilingDataForTesting() const { return tiling_data_; } AllTilesForTesting()183 std::vector<Tile*> AllTilesForTesting() const { 184 std::vector<Tile*> all_tiles; 185 for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) 186 all_tiles.push_back(it->second.get()); 187 return all_tiles; 188 } 189 UpdateAllRequiredStateForTesting()190 void UpdateAllRequiredStateForTesting() { 191 for (const auto& key_tile_pair : tiles_) { 192 Tile* tile = key_tile_pair.second.get(); 193 UpdateRequiredStatesOnTile(tile); 194 } 195 } 196 std::map<const Tile*, PrioritizedTile> 197 UpdateAndGetAllPrioritizedTilesForTesting() const; 198 SetAllTilesOccludedForTesting()199 void SetAllTilesOccludedForTesting() { 200 gfx::Rect viewport_in_layer_space = 201 EnclosingLayerRectFromContentsRect(current_visible_rect_); 202 current_occlusion_in_layer_space_ = 203 Occlusion(gfx::Transform(), 204 SimpleEnclosedRegion(viewport_in_layer_space), 205 SimpleEnclosedRegion(viewport_in_layer_space)); 206 } GetCurrentVisibleRectForTesting()207 const gfx::Rect& GetCurrentVisibleRectForTesting() const { 208 return current_visible_rect_; 209 } SetTilePriorityRectsForTesting(const gfx::Rect & visible_rect_in_content_space,const gfx::Rect & skewport,const gfx::Rect & soon_border_rect,const gfx::Rect & eventually_rect)210 void SetTilePriorityRectsForTesting( 211 const gfx::Rect& visible_rect_in_content_space, 212 const gfx::Rect& skewport, 213 const gfx::Rect& soon_border_rect, 214 const gfx::Rect& eventually_rect) { 215 SetTilePriorityRects(1.f, visible_rect_in_content_space, skewport, 216 soon_border_rect, eventually_rect, Occlusion()); 217 } 218 219 // Iterate over all tiles to fill content_rect. Even if tiles are invalid 220 // (i.e. no valid resource) this tiling should still iterate over them. 221 // The union of all geometry_rect calls for each element iterated over should 222 // exactly equal content_rect and no two geometry_rects should intersect. 223 class CC_EXPORT CoverageIterator { 224 public: 225 CoverageIterator(); 226 // This requests an iterator that produces a coverage of the 227 // |coverage_rect|, which is specified at |coverage_scale|. 228 CoverageIterator(const PictureLayerTiling* tiling, 229 float coverage_scale, 230 const gfx::Rect& coverage_rect); 231 ~CoverageIterator(); 232 233 // Visible rect (no borders), always in the space of |coverage_rect|, 234 // regardless of the contents scale of the tiling. 235 gfx::Rect geometry_rect() const; 236 // Texture rect (in texels) for geometry_rect 237 gfx::RectF texture_rect() const; 238 239 Tile* operator->() const { return current_tile_; } 240 Tile* operator*() const { return current_tile_; } 241 242 CoverageIterator& operator++(); 243 operator bool() const { return tile_j_ <= bottom_; } 244 i()245 int i() const { return tile_i_; } j()246 int j() const { return tile_j_; } 247 248 private: 249 gfx::Rect ComputeGeometryRect() const; 250 251 const PictureLayerTiling* tiling_ = nullptr; 252 gfx::Size coverage_rect_max_bounds_; 253 gfx::Rect coverage_rect_; 254 gfx::AxisTransform2d coverage_to_content_; 255 256 Tile* current_tile_ = nullptr; 257 gfx::Rect current_geometry_rect_; 258 int tile_i_ = 0; 259 int tile_j_ = 0; 260 int left_ = 0; 261 int top_ = 0; 262 int right_ = -1; 263 int bottom_ = -1; 264 265 friend class PictureLayerTiling; 266 }; 267 268 void Reset(); 269 270 void ComputeTilePriorityRects( 271 const gfx::Rect& visible_rect_in_layer_space, 272 const gfx::Rect& skewport_in_layer_space, 273 const gfx::Rect& soon_border_rect_in_layer_space, 274 const gfx::Rect& eventually_rect_in_layer_space, 275 float ideal_contents_scale, 276 const Occlusion& occlusion_in_layer_space); 277 278 void GetAllPrioritizedTilesForTracing( 279 std::vector<PrioritizedTile>* prioritized_tiles) const; 280 void AsValueInto(base::trace_event::TracedValue* array) const; 281 size_t GPUMemoryUsageInBytes() const; 282 283 void UpdateRequiredStatesOnTile(Tile* tile) const; 284 285 protected: 286 friend class CoverageIterator; 287 friend class PrioritizedTile; 288 friend class TilingSetRasterQueueAll; 289 friend class TilingSetRasterQueueRequired; 290 friend class TilingSetEvictionQueue; 291 292 // PENDING VISIBLE RECT refers to the visible rect that will become current 293 // upon activation (ie, the pending tree's visible rect). Tiles in this 294 // region that are not part of the current visible rect are all handled 295 // here. Note that when processing a pending tree, this rect is the same as 296 // the visible rect so no tiles are processed in this case. 297 enum PriorityRectType { 298 VISIBLE_RECT, 299 PENDING_VISIBLE_RECT, 300 SKEWPORT_RECT, 301 SOON_BORDER_RECT, 302 EVENTUALLY_RECT 303 }; 304 305 using TileMap = 306 std::unordered_map<TileMapKey, std::unique_ptr<Tile>, TileMapKeyHash>; 307 308 void SetLiveTilesRect(const gfx::Rect& live_tiles_rect); 309 void VerifyLiveTilesRect() const; 310 Tile* CreateTile(const Tile::CreateInfo& info); 311 // Removes the tile at i, j and returns it. Returns nullptr if the tile did 312 // not exist. 313 std::unique_ptr<Tile> TakeTileAt(int i, int j); 314 bool TilingMatchesTileIndices(const PictureLayerTiling* twin) const; 315 316 // Save the required data for computing tile priorities later. 317 void SetTilePriorityRects(float content_to_screen_scale, 318 const gfx::Rect& visible_rect_in_content_space, 319 const gfx::Rect& skewport, 320 const gfx::Rect& soon_border_rect, 321 const gfx::Rect& eventually_rect, 322 const Occlusion& occlusion_in_layer_space); 323 324 bool IsTileOccludedOnCurrentTree(const Tile* tile) const; 325 Tile::CreateInfo CreateInfoForTile(int i, int j) const; 326 bool ShouldCreateTileAt(const Tile::CreateInfo& info) const; 327 bool IsTileOccluded(const Tile* tile) const; 328 PrioritizedTile MakePrioritizedTile( 329 Tile* tile, 330 PriorityRectType priority_rect_type) const; 331 TilePriority ComputePriorityForTile( 332 const Tile* tile, 333 PriorityRectType priority_rect_type) const; 334 PriorityRectType ComputePriorityRectTypeForTile(const Tile* tile) const; has_visible_rect_tiles()335 bool has_visible_rect_tiles() const { return has_visible_rect_tiles_; } has_skewport_rect_tiles()336 bool has_skewport_rect_tiles() const { return has_skewport_rect_tiles_; } has_soon_border_rect_tiles()337 bool has_soon_border_rect_tiles() const { 338 return has_soon_border_rect_tiles_; 339 } has_eventually_rect_tiles()340 bool has_eventually_rect_tiles() const { return has_eventually_rect_tiles_; } 341 current_visible_rect()342 const gfx::Rect& current_visible_rect() const { 343 return current_visible_rect_; 344 } pending_visible_rect()345 gfx::Rect pending_visible_rect() const { 346 const PictureLayerTiling* pending_tiling = 347 tree_ == ACTIVE_TREE ? client_->GetPendingOrActiveTwinTiling(this) 348 : this; 349 if (pending_tiling) 350 return pending_tiling->current_visible_rect(); 351 return gfx::Rect(); 352 } current_skewport_rect()353 const gfx::Rect& current_skewport_rect() const { 354 return current_skewport_rect_; 355 } current_soon_border_rect()356 const gfx::Rect& current_soon_border_rect() const { 357 return current_soon_border_rect_; 358 } current_eventually_rect()359 const gfx::Rect& current_eventually_rect() const { 360 return current_eventually_rect_; 361 } 362 void RemoveTilesInRegion(const Region& layer_region, bool recreate_tiles); 363 364 gfx::Rect EnclosingContentsRectFromLayerRect( 365 const gfx::Rect& layer_rect) const; 366 gfx::Rect EnclosingLayerRectFromContentsRect( 367 const gfx::Rect& contents_rect) const; 368 369 // Given properties. 370 const gfx::AxisTransform2d raster_transform_; 371 PictureLayerTilingClient* const client_; 372 const WhichTree tree_; 373 scoped_refptr<RasterSource> raster_source_; 374 const float min_preraster_distance_; 375 const float max_preraster_distance_; 376 TileResolution resolution_ = NON_IDEAL_RESOLUTION; 377 bool may_contain_low_resolution_tiles_ = false; 378 379 // Internal data. 380 TilingData tiling_data_ = TilingData(gfx::Size(), gfx::Size(), kBorderTexels); 381 TileMap tiles_; // It is not legal to have a NULL tile in the tiles_ map. 382 gfx::Rect live_tiles_rect_; 383 384 bool can_require_tiles_for_activation_ = false; 385 386 // Iteration rects in content space. 387 gfx::Rect current_visible_rect_; 388 gfx::Rect current_skewport_rect_; 389 gfx::Rect current_soon_border_rect_; 390 gfx::Rect current_eventually_rect_; 391 // Other properties used for tile iteration and prioritization. 392 float current_content_to_screen_scale_ = 0.f; 393 Occlusion current_occlusion_in_layer_space_; 394 float max_skewport_extent_in_screen_space_ = 0.f; 395 396 bool has_visible_rect_tiles_ = false; 397 bool has_skewport_rect_tiles_ = false; 398 bool has_soon_border_rect_tiles_ = false; 399 bool has_eventually_rect_tiles_ = false; 400 bool all_tiles_done_ = true; 401 }; 402 403 } // namespace cc 404 405 #endif // CC_TILES_PICTURE_LAYER_TILING_H_ 406