| // Copyright 2024 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_LAYERS_TILE_DISPLAY_LAYER_IMPL_H_ |
| #define CC_LAYERS_TILE_DISPLAY_LAYER_IMPL_H_ |
| |
| #include <memory> |
| #include <utility> |
| #include <variant> |
| #include <vector> |
| |
| #include "base/memory/raw_ref.h" |
| #include "cc/base/tiling_data.h" |
| #include "cc/cc_export.h" |
| #include "cc/layers/tile_based_layer_impl.h" |
| #include "cc/mojom/missing_tile_reason.mojom.h" |
| #include "cc/tiles/tile_draw_info.h" |
| #include "cc/tiles/tile_index.h" |
| #include "cc/tiles/tile_priority.h" |
| #include "cc/tiles/tiling_coverage_iterator.h" |
| #include "cc/tiles/tiling_set_coverage_iterator.h" |
| #include "components/viz/common/resources/shared_image_format.h" |
| #include "components/viz/common/resources/transferable_resource.h" |
| #include "third_party/abseil-cpp/absl/container/flat_hash_map.h" |
| #include "ui/gfx/geometry/axis_transform2d.h" |
| #include "ui/gfx/geometry/rect.h" |
| #include "ui/gfx/geometry/size.h" |
| |
| namespace cc { |
| |
| class TileDisplayLayerImpl; |
| class TileDisplayLayerTiling; |
| class DisplayTilingCoverageIterator; |
| |
| struct TileDisplayLayerNoContents { |
| mojom::MissingTileReason reason = mojom::MissingTileReason::kResourceNotReady; |
| |
| TileDisplayLayerNoContents() = default; |
| explicit TileDisplayLayerNoContents(mojom::MissingTileReason r) : reason(r) {} |
| }; |
| |
| struct TileDisplayLayerTileResource { |
| viz::ResourceId resource_id; |
| gfx::Size resource_size; |
| }; |
| |
| using TileDisplayLayerTileContents = std::variant<TileDisplayLayerNoContents, |
| SkColor4f, |
| TileDisplayLayerTileResource>; |
| |
| class CC_EXPORT TileDisplayLayerTile { |
| public: |
| explicit TileDisplayLayerTile(TileDisplayLayerImpl& layer, |
| const TileDisplayLayerTileContents& contents); |
| ~TileDisplayLayerTile(); |
| TileDisplayLayerTile(TileDisplayLayerTile&&); |
| |
| TileDrawInfo::Mode draw_mode() { |
| CHECK(IsReadyToDraw()); |
| if (solid_color()) { |
| return TileDrawInfo::SOLID_COLOR_MODE; |
| } else if (is_oom()) { |
| return TileDrawInfo::OOM_MODE; |
| } else { |
| CHECK(resource()); |
| return TileDrawInfo::RESOURCE_MODE; |
| } |
| } |
| |
| const TileDisplayLayerTileContents& contents() const { return contents_; } |
| |
| std::optional<SkColor4f> solid_color() const { |
| if (std::holds_alternative<SkColor4f>(contents_)) { |
| return std::get<SkColor4f>(contents_); |
| } |
| return std::nullopt; |
| } |
| |
| std::optional<TileDisplayLayerTileResource> resource() const { |
| if (std::holds_alternative<TileDisplayLayerTileResource>(contents_)) { |
| return std::get<TileDisplayLayerTileResource>(contents_); |
| } |
| return std::nullopt; |
| } |
| |
| bool is_oom() const { |
| if (std::holds_alternative<TileDisplayLayerNoContents>(contents_)) { |
| return std::get<TileDisplayLayerNoContents>(contents_).reason == |
| mojom::MissingTileReason::kOutOfMemory; |
| } |
| return false; |
| } |
| |
| bool IsReadyToDraw() const { |
| return !std::holds_alternative<TileDisplayLayerNoContents>(contents_) || |
| is_oom(); |
| } |
| |
| private: |
| const raw_ref<TileDisplayLayerImpl> layer_; |
| TileDisplayLayerTileContents contents_; |
| }; |
| |
| class CC_EXPORT TileDisplayLayerTiling { |
| public: |
| using Tile = TileDisplayLayerTile; |
| using TileMap = absl::flat_hash_map<TileIndex, std::unique_ptr<Tile>>; |
| using CoverageIterator = DisplayTilingCoverageIterator; |
| |
| explicit TileDisplayLayerTiling(TileDisplayLayerImpl& layer, float scale_key); |
| ~TileDisplayLayerTiling(); |
| |
| Tile* TileAt(const TileIndex& index) const; |
| |
| float contents_scale_key() const { return scale_key_; } |
| TileResolution resolution() const { return HIGH_RESOLUTION; } |
| const TilingData* tiling_data() const { return &tiling_data_; } |
| gfx::Size raster_size() const; |
| const gfx::AxisTransform2d& raster_transform() const { |
| return raster_transform_; |
| } |
| const gfx::Size tile_size() const { return tiling_data_.max_texture_size(); } |
| const gfx::Rect tiling_rect() const { return tiling_data_.tiling_rect(); } |
| const TileMap& tiles() const { return tiles_; } |
| |
| void SetRasterTransform(const gfx::AxisTransform2d& transform); |
| void SetTileSize(const gfx::Size& size); |
| void SetTilingRect(const gfx::Rect& rect); |
| void SetTileContents(const TileIndex& key, |
| const TileDisplayLayerTileContents& contents, |
| bool update_damage); |
| |
| CoverageIterator Cover(const gfx::Rect& coverage_rect, |
| float coverage_scale) const; |
| |
| private: |
| const raw_ref<TileDisplayLayerImpl> layer_; |
| const float scale_key_; |
| gfx::AxisTransform2d raster_transform_; |
| TilingData tiling_data_{gfx::Size(), gfx::Rect(), /*border_texels=*/1}; |
| TileMap tiles_; |
| }; |
| |
| class CC_EXPORT DisplayTilingCoverageIterator |
| : public TilingCoverageIterator<TileDisplayLayerTiling> { |
| public: |
| using TilingCoverageIterator<TileDisplayLayerTiling>::TilingCoverageIterator; |
| }; |
| |
| // Viz-side counterpart to a client-side PictureLayerImpl when TreesInViz is |
| // enabled. Clients push tiling information and tile contents from a picture |
| // layer down to Viz, and this layer uses that information to draw tile quads. |
| class CC_EXPORT TileDisplayLayerImpl |
| : public TileBasedLayerImpl<TileDisplayLayerTiling> { |
| public: |
| using NoContents = TileDisplayLayerNoContents; |
| using TileResource = TileDisplayLayerTileResource; |
| using TileContents = TileDisplayLayerTileContents; |
| |
| TileDisplayLayerImpl(LayerTreeImpl& tree, int id); |
| ~TileDisplayLayerImpl() override; |
| |
| TileDisplayLayerTiling& GetOrCreateTilingFromScaleKey(float scale_key); |
| void RemoveTiling(float scale_key); |
| void SetIsDirectlyCompositedImage(bool is_directly_composited_image) { |
| is_directly_composited_image_ = is_directly_composited_image; |
| } |
| void SetNearestNeighbor(bool nearest_neighbor) { |
| nearest_neighbor_ = nearest_neighbor; |
| } |
| void SetRecordedBounds(const gfx::Rect& bounds) { recorded_bounds_ = bounds; } |
| bool IsDirectlyCompositedImage() const override; |
| void SetProposedTilingScalesForDeletion( |
| std::vector<float> proposed_tiling_scales) { |
| proposed_tiling_scales_for_deletion_ = std::move(proposed_tiling_scales); |
| } |
| const gfx::Rect& recorded_bounds_for_testing() const { |
| return recorded_bounds_; |
| } |
| const std::vector<float>& proposed_tiling_scales_for_deletion_for_testing() |
| const { |
| return proposed_tiling_scales_for_deletion_; |
| } |
| bool nearest_neighbor() const { return nearest_neighbor_; } |
| |
| // LayerImpl overrides: |
| mojom::LayerType GetLayerType() const override; |
| std::unique_ptr<LayerImpl> CreateLayerImpl( |
| LayerTreeImpl* tree_impl) const override; |
| void PushPropertiesTo(LayerImpl* layer) override; |
| void GetContentsResourceId(viz::ResourceId* resource_id, |
| gfx::Size* resource_size, |
| gfx::SizeF* resource_uv_size) const override; |
| gfx::Rect GetDamageRect() const override; |
| void ResetChangeTracking() override; |
| gfx::ContentColorUsage GetContentColorUsage() const override; |
| |
| void SetContentColorUsage(gfx::ContentColorUsage content_color_usage) { |
| content_color_usage_ = content_color_usage; |
| } |
| |
| void RecordDamage(const gfx::Rect& damage_rect); |
| |
| const TileDisplayLayerTiling* GetTilingForTesting(float scale_key) const; |
| void DiscardResource(viz::ResourceId resource); |
| |
| // Returns a list of tiling scales that were proposed for deletion by |
| // renderer and were *not* used in the most recent frame, meaning they |
| // safe to clean up. |
| std::vector<float> GetSafeToDeleteTilings(); |
| |
| // For testing |
| std::optional<SkColor4f> solid_color_for_testing() const { |
| return solid_color(); |
| } |
| |
| private: |
| // TileBasedLayerImpl: |
| void AppendQuadsSpecialization(const AppendQuadsContext& context, |
| viz::CompositorRenderPass* render_pass, |
| AppendQuadsData* append_quads_data, |
| viz::SharedQuadState* shared_quad_state, |
| const Occlusion& scaled_occlusion, |
| const gfx::Vector2d& quad_offset, |
| float max_contents_scale) override; |
| float GetMaximumContentsScaleForUseInAppendQuads() const override; |
| float GetIdealContentsScaleKey() const override; |
| void AppendQuadsForResourcelessSoftwareDraw( |
| const AppendQuadsContext& context, |
| viz::CompositorRenderPass* render_pass, |
| AppendQuadsData* append_quads_data, |
| viz::SharedQuadState* shared_quad_state, |
| const Occlusion& scaled_occlusion) override; |
| TilingSetCoverageIterator<TileDisplayLayerTiling> Cover( |
| const gfx::Rect& coverage_rect, |
| float coverage_scale, |
| float ideal_contents_scale) override; |
| TilingResolution GetTilingResolutionForDebugBorders( |
| const TileDisplayLayerTiling* tiling) const override; |
| |
| void AppendQuadForTile(TilingSetCoverageIterator<TileDisplayLayerTiling> iter, |
| const AppendQuadsContext& context, |
| viz::CompositorRenderPass* render_pass, |
| AppendQuadsData* append_quads_data, |
| viz::SharedQuadState* shared_quad_state, |
| const Occlusion& scaled_occlusion, |
| const gfx::Vector2d& quad_offset, |
| float max_contents_scale); |
| |
| bool is_directly_composited_image_ = false; |
| bool nearest_neighbor_ = false; |
| gfx::ContentColorUsage content_color_usage_ = gfx::ContentColorUsage::kSRGB; |
| gfx::Rect recorded_bounds_; |
| |
| // Denotes an area that is damaged and needs redraw. This is in the layer's |
| // space. |
| gfx::Rect damage_rect_; |
| std::vector<std::unique_ptr<TileDisplayLayerTiling>> tilings_; |
| |
| // A list of tiling scale keys that the client has nominated for deletion. |
| // This allows the client to suggest cleanup, but Viz makes the final |
| // decision. After each frame, we determine which of these candidate scales |
| // were *not* used for drawing (by checking against |
| // `last_append_quads_scales_`). That final set of unused scales is then sent |
| // back to the client, confirming that the corresponding tilings can be safely |
| // destroyed. |
| std::vector<float> proposed_tiling_scales_for_deletion_; |
| }; |
| |
| } // namespace cc |
| |
| #endif // CC_LAYERS_TILE_DISPLAY_LAYER_IMPL_H_ |