Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion flow/layers/layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,20 @@ namespace flutter {
Layer::Layer()
: parent_(nullptr),
needs_system_composite_(false),
paint_bounds_(SkRect::MakeEmpty()) {}
paint_bounds_(SkRect::MakeEmpty()),
unique_id_(NextUniqueID()) {}

Layer::~Layer() = default;

uint32_t Layer::NextUniqueID() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the rate that these ids are generated at, and how long are these objects expected to live?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usually a few (mostly fewer than 10, I never see more than 100) per frame. So that's about 100-200 at full 60fps animations, and I've never seen more than 1000 per second.

A layer may live for a very long time if the scene doesn't change at all. But I'd never expect to have many layers alive at one time. I think it's safe to say that most of the time, no more than 100 are alive at the same time. In extreme cases, maybe never more than 1000 at a time (otherwise compositing all those layers will be very janky).

If we take 1000 layers/second as the generation speed, it'll take 49 days to cycle the unique id.

If we take that no more than 1000 layers are alive at a time, the chance of collision (given that we've cycled the unique id after 49 days, and those 1000 layers live forever) is less than 2^-20 per layer and less than 2^-10 (0.1%) per second.

If that doesn't sound safe enough, I'm happy to use uint64_t for the id.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it's not hard to switch to uint64_t, then let's switch.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

static std::atomic<uint32_t> nextID(1);
uint32_t id;
do {
id = nextID.fetch_add(1);
} while (id == 0); // 0 is reserved for an invalid id.
return id;
}

void Layer::Preroll(PrerollContext* context, const SkMatrix& matrix) {}

#if defined(OS_FUCHSIA)
Expand Down
5 changes: 5 additions & 0 deletions flow/layers/layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,15 @@ class Layer {

bool needs_painting() const { return !paint_bounds_.isEmpty(); }

uint32_t unique_id() const { return unique_id_; }

private:
ContainerLayer* parent_;
bool needs_system_composite_;
SkRect paint_bounds_;
uint32_t unique_id_;

static uint32_t NextUniqueID();

FML_DISALLOW_COPY_AND_ASSIGN(Layer);
};
Expand Down
2 changes: 1 addition & 1 deletion flow/layers/physical_shape_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ void PhysicalShapeLayer::UpdateScene(SceneUpdateContext& context) {
// Retained rendering: speedup by reusing a retained entity node if possible.
// When an entity node is reused, no paint layer is added to the frame so we
// won't call PhysicalShapeLayer::Paint.
LayerRasterCacheKey key(this, context.Matrix());
LayerRasterCacheKey key(unique_id(), context.Matrix());
if (context.HasRetainedNode(key)) {
const scenic::EntityNode& retained_node = context.GetRetainedNode(key);
FML_DCHECK(context.top_entity());
Expand Down
4 changes: 2 additions & 2 deletions flow/raster_cache.cc
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ static inline size_t ClampSize(size_t value, size_t min, size_t max) {
void RasterCache::Prepare(PrerollContext* context,
Layer* layer,
const SkMatrix& ctm) {
LayerRasterCacheKey cache_key(layer, ctm);
LayerRasterCacheKey cache_key(layer->unique_id(), ctm);
Entry& entry = layer_cache_[cache_key];
entry.access_count = ClampSize(entry.access_count + 1, 0, access_threshold_);
entry.used_this_frame = true;
Expand Down Expand Up @@ -230,7 +230,7 @@ RasterCacheResult RasterCache::Get(const SkPicture& picture,
}

RasterCacheResult RasterCache::Get(Layer* layer, const SkMatrix& ctm) const {
LayerRasterCacheKey cache_key(layer, ctm);
LayerRasterCacheKey cache_key(layer->unique_id(), ctm);
auto it = layer_cache_.find(cache_key);
return it == layer_cache_.end() ? RasterCacheResult() : it->second.image;
}
Expand Down
3 changes: 2 additions & 1 deletion flow/raster_cache_key.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ using PictureRasterCacheKey = RasterCacheKey<uint32_t>;

class Layer;

using LayerRasterCacheKey = RasterCacheKey<Layer*>;
// The ID is the uint32_t layer unique_id
using LayerRasterCacheKey = RasterCacheKey<uint32_t>;

} // namespace flutter

Expand Down
10 changes: 7 additions & 3 deletions flow/scene_update_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -163,10 +163,14 @@ scenic::Image* SceneUpdateContext::GenerateImageIfNeeded(
return nullptr;

// Acquire a surface from the surface producer and register the paint tasks.

std::unique_ptr<SurfaceProducerSurface> surface =
surface_producer_->ProduceSurface(physical_size,
LayerRasterCacheKey(layer, Matrix()),
std::move(entity_node));
surface_producer_->ProduceSurface(
physical_size,
LayerRasterCacheKey(
// Root frame has a nullptr layer
layer ? layer->unique_id() : 0, Matrix()),
std::move(entity_node));

if (!surface) {
FML_LOG(ERROR) << "Could not acquire a surface from the surface producer "
Expand Down