blob: ec11cf7a7ed963c9abe2a4a7c871218ec66218b2 [file]
// 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_