Skip to content
Permalink
Browse files

Generate layer unique id for raster cache key (#8637)

The raw pointer isn't a reliable id as the allocator can reuse an
address that's just been released for another layer.

This will fix Fuchsia bug FL-216.

This problem was not affecting non-Fuchsia Flutter probably because
non-Fuchsia Flutter purges the raster cache key much more frequently so
we won't see a key collision. In Fuchsia, as the key has to wait for the
Vulkan surface to render asynchronously, this suddenly becomes an issue.
  • Loading branch information...
liyuqian committed Apr 18, 2019
1 parent c3bc5d8 commit d79eb2857d6f08598e6761f56a73e082839c2481
@@ -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;

uint64_t Layer::NextUniqueID() {
static std::atomic<uint64_t> nextID(1);
uint64_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)
@@ -143,10 +143,15 @@ class Layer {

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

uint64_t unique_id() const { return unique_id_; }

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

static uint64_t NextUniqueID();

FML_DISALLOW_COPY_AND_ASSIGN(Layer);
};
@@ -110,7 +110,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());
@@ -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;
@@ -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;
}
@@ -56,7 +56,8 @@ using PictureRasterCacheKey = RasterCacheKey<uint32_t>;

class Layer;

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

} // namespace flutter

@@ -164,9 +164,12 @@ scenic::Image* SceneUpdateContext::GenerateImageIfNeeded(

// 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 "

0 comments on commit d79eb28

Please sign in to comment.
You can’t perform that action at this time.