Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Lazily allocate RasterCacheItems only when caching is enabled #45211

Merged
merged 1 commit into from
Aug 31, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
40 changes: 24 additions & 16 deletions flow/layers/cacheable_layer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,39 @@

namespace flutter {

AutoCache::AutoCache(RasterCacheItem* raster_cache_item,
AutoCache::AutoCache(CacheableLayer& cacheable_layer,
PrerollContext* context,
const SkMatrix& matrix)
: raster_cache_item_(raster_cache_item),
context_(context),
matrix_(matrix) {
if (IsCacheEnabled()) {
raster_cache_item->PrerollSetup(context, matrix);
bool caching_enabled) {
if (context->raster_cache && caching_enabled) {
raster_cache_item_ = cacheable_layer.realize_raster_cache_item();
if (raster_cache_item_) {
context_ = context;
matrix_ = context->state_stack.transform_3x3();
raster_cache_item_->PrerollSetup(context_, matrix_);
}
} else {
cacheable_layer.disable_raster_cache_item();
}
}

bool AutoCache::IsCacheEnabled() {
return raster_cache_item_ && context_ && context_->raster_cache;
}

AutoCache::~AutoCache() {
if (IsCacheEnabled()) {
if (raster_cache_item_) {
raster_cache_item_->PrerollFinalize(context_, matrix_);
}
}

CacheableContainerLayer::CacheableContainerLayer(int layer_cached_threshold,
bool can_cache_children) {
layer_raster_cache_item_ = LayerRasterCacheItem::Make(
this, layer_cached_threshold, can_cache_children);
RasterCacheItem* CacheableContainerLayer::realize_raster_cache_item() {
if (!layer_raster_cache_item_) {
layer_raster_cache_item_ = LayerRasterCacheItem::Make(
this, layer_cache_threshold_, can_cache_children_);
}
return layer_raster_cache_item_.get();
}

void CacheableContainerLayer::disable_raster_cache_item() {
if (layer_raster_cache_item_) {
layer_raster_cache_item_->reset_cache_state();
}
}

} // namespace flutter
35 changes: 29 additions & 6 deletions flow/layers/cacheable_layer.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,39 +9,62 @@

#include "flutter/flow/layers/container_layer.h"
#include "flutter/flow/layers/layer_raster_cache_item.h"
#include "flutter/flow/raster_cache_util.h"

namespace flutter {

class CacheableLayer {
protected:
virtual RasterCacheItem* realize_raster_cache_item() = 0;
virtual void disable_raster_cache_item() = 0;

friend class AutoCache;
};

class AutoCache {
public:
AutoCache(RasterCacheItem* raster_cache_item,
AutoCache(CacheableLayer& item_provider,
PrerollContext* context,
const SkMatrix& matrix);
bool caching_enabled = true);

void ShouldNotBeCached() { raster_cache_item_ = nullptr; }

~AutoCache();

private:
inline bool IsCacheEnabled();
RasterCacheItem* raster_cache_item_ = nullptr;
PrerollContext* context_ = nullptr;
const SkMatrix matrix_;
SkMatrix matrix_;

FML_DISALLOW_COPY_ASSIGN_AND_MOVE(AutoCache);
};

class CacheableContainerLayer : public ContainerLayer {
class CacheableContainerLayer : public ContainerLayer, public CacheableLayer {
public:
explicit CacheableContainerLayer(
int layer_cached_threshold =
RasterCacheUtil::kMinimumRendersBeforeCachingFilterLayer,
bool can_cache_children = false);
bool can_cache_children = false)
: layer_cache_threshold_(layer_cached_threshold),
can_cache_children_(can_cache_children) {}

const LayerRasterCacheItem* raster_cache_item() const {
return layer_raster_cache_item_.get();
}

void MarkCanCacheChildren(bool can_cache_children) {
if (layer_raster_cache_item_) {
layer_raster_cache_item_->MarkCanCacheChildren(can_cache_children);
}
}

protected:
RasterCacheItem* realize_raster_cache_item() override;
virtual void disable_raster_cache_item() override;
std::unique_ptr<LayerRasterCacheItem> layer_raster_cache_item_;

int layer_cache_threshold_;
bool can_cache_children_;
};

} // namespace flutter
Expand Down
55 changes: 49 additions & 6 deletions flow/layers/clip_path_layer_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -519,31 +519,74 @@ TEST_F(ClipPathLayerTest, LayerCached) {
use_mock_raster_cache();
preroll_context()->state_stack.set_preroll_delegate(initial_transform);

const auto* clip_cache_item = layer->raster_cache_item();

EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)0);
EXPECT_EQ(layer->raster_cache_item(), nullptr);

layer->Preroll(preroll_context());
EXPECT_NE(layer->raster_cache_item(), nullptr);
LayerTree::TryToRasterCache(cacheable_items(), &paint_context());

EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)0);
EXPECT_EQ(clip_cache_item->cache_state(), RasterCacheItem::CacheState::kNone);
EXPECT_EQ(layer->raster_cache_item()->cache_state(),
RasterCacheItem::CacheState::kNone);

layer->Preroll(preroll_context());
LayerTree::TryToRasterCache(cacheable_items(), &paint_context());
EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)0);
EXPECT_EQ(clip_cache_item->cache_state(), RasterCacheItem::CacheState::kNone);
EXPECT_EQ(layer->raster_cache_item()->cache_state(),
RasterCacheItem::CacheState::kNone);

layer->Preroll(preroll_context());
LayerTree::TryToRasterCache(cacheable_items(), &paint_context());
EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)1);
EXPECT_EQ(clip_cache_item->cache_state(),
EXPECT_EQ(layer->raster_cache_item()->cache_state(),
RasterCacheItem::CacheState::kCurrent);
DlPaint paint;
EXPECT_TRUE(raster_cache()->Draw(clip_cache_item->GetId().value(),
EXPECT_TRUE(raster_cache()->Draw(layer->raster_cache_item()->GetId().value(),
cache_canvas, &paint));
}

TEST_F(ClipPathLayerTest, NullRasterCacheResetsRasterCacheItem) {
auto path1 = SkPath().addRect({10, 10, 30, 30});
auto mock1 = MockLayer::MakeOpacityCompatible(path1);
auto layer_clip = SkPath()
.addRect(SkRect::MakeLTRB(5, 5, 25, 25))
.addOval(SkRect::MakeLTRB(20, 20, 40, 50));
auto layer =
std::make_shared<ClipPathLayer>(layer_clip, Clip::antiAliasWithSaveLayer);
layer->Add(mock1);

ASSERT_EQ(layer->raster_cache_item(), nullptr);

layer->Preroll(preroll_context());
ASSERT_EQ(layer->raster_cache_item(), nullptr);

use_mock_raster_cache();

int limit = RasterCacheUtil::kMinimumRendersBeforeCachingFilterLayer;
for (int i = 1; i < limit; i++) {
layer->Preroll(preroll_context());
ASSERT_NE(layer->raster_cache_item(), nullptr);
ASSERT_EQ(layer->raster_cache_item()->cache_state(),
RasterCacheItem::kNone);
ASSERT_FALSE(
layer->raster_cache_item()->TryToPrepareRasterCache(paint_context()));
}

layer->Preroll(preroll_context());
ASSERT_NE(layer->raster_cache_item(), nullptr);
ASSERT_EQ(layer->raster_cache_item()->cache_state(),
RasterCacheItem::kCurrent);
ASSERT_TRUE(
layer->raster_cache_item()->TryToPrepareRasterCache(paint_context()));

use_null_raster_cache();

layer->Preroll(preroll_context());
ASSERT_NE(layer->raster_cache_item(), nullptr);
ASSERT_EQ(layer->raster_cache_item()->cache_state(), RasterCacheItem::kNone);
}

TEST_F(ClipPathLayerTest, EmptyClipDoesNotCullPlatformView) {
const SkPoint view_offset = SkPoint::Make(0.0f, 0.0f);
const SkSize view_size = SkSize::Make(8.0f, 8.0f);
Expand Down
53 changes: 47 additions & 6 deletions flow/layers/clip_rect_layer_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -499,30 +499,71 @@ TEST_F(ClipRectLayerTest, LayerCached) {

use_mock_raster_cache();
preroll_context()->state_stack.set_preroll_delegate(initial_transform);

const auto* clip_cache_item = layer->raster_cache_item();
EXPECT_EQ(layer->raster_cache_item(), nullptr);

layer->Preroll(preroll_context());
EXPECT_NE(layer->raster_cache_item(), nullptr);
LayerTree::TryToRasterCache(cacheable_items(), &paint_context());

EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)0);
EXPECT_EQ(clip_cache_item->cache_state(), RasterCacheItem::CacheState::kNone);
EXPECT_EQ(layer->raster_cache_item()->cache_state(),
RasterCacheItem::CacheState::kNone);

layer->Preroll(preroll_context());
LayerTree::TryToRasterCache(cacheable_items(), &paint_context());
EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)0);
EXPECT_EQ(clip_cache_item->cache_state(), RasterCacheItem::CacheState::kNone);
EXPECT_EQ(layer->raster_cache_item()->cache_state(),
RasterCacheItem::CacheState::kNone);

layer->Preroll(preroll_context());
LayerTree::TryToRasterCache(cacheable_items(), &paint_context());
EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)1);
EXPECT_EQ(clip_cache_item->cache_state(),
EXPECT_EQ(layer->raster_cache_item()->cache_state(),
RasterCacheItem::CacheState::kCurrent);
DlPaint paint;
EXPECT_TRUE(raster_cache()->Draw(clip_cache_item->GetId().value(),
EXPECT_TRUE(raster_cache()->Draw(layer->raster_cache_item()->GetId().value(),
cache_canvas, &paint));
}

TEST_F(ClipRectLayerTest, NullRasterCacheResetsRasterCacheItem) {
auto path1 = SkPath().addRect({10, 10, 30, 30});
auto mock1 = MockLayer::MakeOpacityCompatible(path1);
SkRect clip_rect = SkRect::MakeWH(500, 500);
auto layer =
std::make_shared<ClipRectLayer>(clip_rect, Clip::antiAliasWithSaveLayer);
layer->Add(mock1);

ASSERT_EQ(layer->raster_cache_item(), nullptr);

layer->Preroll(preroll_context());
ASSERT_EQ(layer->raster_cache_item(), nullptr);

use_mock_raster_cache();

int limit = RasterCacheUtil::kMinimumRendersBeforeCachingFilterLayer;
for (int i = 1; i < limit; i++) {
layer->Preroll(preroll_context());
ASSERT_NE(layer->raster_cache_item(), nullptr);
ASSERT_EQ(layer->raster_cache_item()->cache_state(),
RasterCacheItem::kNone);
ASSERT_FALSE(
layer->raster_cache_item()->TryToPrepareRasterCache(paint_context()));
}

layer->Preroll(preroll_context());
ASSERT_NE(layer->raster_cache_item(), nullptr);
ASSERT_EQ(layer->raster_cache_item()->cache_state(),
RasterCacheItem::kCurrent);
ASSERT_TRUE(
layer->raster_cache_item()->TryToPrepareRasterCache(paint_context()));

use_null_raster_cache();

layer->Preroll(preroll_context());
ASSERT_NE(layer->raster_cache_item(), nullptr);
ASSERT_EQ(layer->raster_cache_item()->cache_state(), RasterCacheItem::kNone);
}

TEST_F(ClipRectLayerTest, EmptyClipDoesNotCullPlatformView) {
const SkPoint view_offset = SkPoint::Make(0.0f, 0.0f);
const SkSize view_size = SkSize::Make(8.0f, 8.0f);
Expand Down
64 changes: 53 additions & 11 deletions flow/layers/clip_rrect_layer_unittests.cc
Original file line number Diff line number Diff line change
Expand Up @@ -512,29 +512,72 @@ TEST_F(ClipRRectLayerTest, LayerCached) {

use_mock_raster_cache();
preroll_context()->state_stack.set_preroll_delegate(initial_transform);

const auto* clip_cache_item = layer->raster_cache_item();
EXPECT_EQ(layer->raster_cache_item(), nullptr);

layer->Preroll(preroll_context());
EXPECT_NE(layer->raster_cache_item(), nullptr);
LayerTree::TryToRasterCache(cacheable_items(), &paint_context());

EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)0);
EXPECT_EQ(clip_cache_item->cache_state(), RasterCacheItem::CacheState::kNone);
EXPECT_EQ(layer->raster_cache_item()->cache_state(),
RasterCacheItem::CacheState::kNone);

layer->Preroll(preroll_context());
LayerTree::TryToRasterCache(cacheable_items(), &paint_context());
EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)0);
EXPECT_EQ(clip_cache_item->cache_state(), RasterCacheItem::CacheState::kNone);
EXPECT_EQ(layer->raster_cache_item()->cache_state(),
RasterCacheItem::CacheState::kNone);

layer->Preroll(preroll_context());
LayerTree::TryToRasterCache(cacheable_items(), &paint_context());
EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)1);
EXPECT_EQ(clip_cache_item->cache_state(),
EXPECT_EQ(layer->raster_cache_item()->cache_state(),
RasterCacheItem::CacheState::kCurrent);
EXPECT_TRUE(raster_cache()->Draw(clip_cache_item->GetId().value(),
EXPECT_TRUE(raster_cache()->Draw(layer->raster_cache_item()->GetId().value(),
cache_canvas, &paint));
}

TEST_F(ClipRRectLayerTest, NullRasterCacheResetsRasterCacheItem) {
auto path1 = SkPath().addRect({10, 10, 30, 30});
DlPaint paint = DlPaint();
auto mock1 = MockLayer::MakeOpacityCompatible(path1);
SkRect clip_rect = SkRect::MakeWH(500, 500);
SkRRect clip_rrect = SkRRect::MakeRectXY(clip_rect, 20, 20);
auto layer = std::make_shared<ClipRRectLayer>(clip_rrect,
Clip::antiAliasWithSaveLayer);
layer->Add(mock1);

ASSERT_EQ(layer->raster_cache_item(), nullptr);

layer->Preroll(preroll_context());
ASSERT_EQ(layer->raster_cache_item(), nullptr);

use_mock_raster_cache();

int limit = RasterCacheUtil::kMinimumRendersBeforeCachingFilterLayer;
for (int i = 1; i < limit; i++) {
layer->Preroll(preroll_context());
ASSERT_NE(layer->raster_cache_item(), nullptr);
ASSERT_EQ(layer->raster_cache_item()->cache_state(),
RasterCacheItem::kNone);
ASSERT_FALSE(
layer->raster_cache_item()->TryToPrepareRasterCache(paint_context()));
}

layer->Preroll(preroll_context());
ASSERT_NE(layer->raster_cache_item(), nullptr);
ASSERT_EQ(layer->raster_cache_item()->cache_state(),
RasterCacheItem::kCurrent);
ASSERT_TRUE(
layer->raster_cache_item()->TryToPrepareRasterCache(paint_context()));

use_null_raster_cache();

layer->Preroll(preroll_context());
ASSERT_NE(layer->raster_cache_item(), nullptr);
ASSERT_EQ(layer->raster_cache_item()->cache_state(), RasterCacheItem::kNone);
}

TEST_F(ClipRRectLayerTest, NoSaveLayerShouldNotCache) {
auto path1 = SkPath().addRect({10, 10, 30, 30});

Expand All @@ -551,24 +594,23 @@ TEST_F(ClipRRectLayerTest, NoSaveLayerShouldNotCache) {

use_mock_raster_cache();
preroll_context()->state_stack.set_preroll_delegate(initial_transform);

const auto* clip_cache_item = layer->raster_cache_item();
EXPECT_EQ(layer->raster_cache_item(), nullptr);

layer->Preroll(preroll_context());
LayerTree::TryToRasterCache(cacheable_items(), &paint_context());

EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)0);
EXPECT_EQ(clip_cache_item->cache_state(), RasterCacheItem::CacheState::kNone);
EXPECT_EQ(layer->raster_cache_item(), nullptr);

layer->Preroll(preroll_context());
LayerTree::TryToRasterCache(cacheable_items(), &paint_context());
EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)0);
EXPECT_EQ(clip_cache_item->cache_state(), RasterCacheItem::CacheState::kNone);
EXPECT_EQ(layer->raster_cache_item(), nullptr);

layer->Preroll(preroll_context());
LayerTree::TryToRasterCache(cacheable_items(), &paint_context());
EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)0);
EXPECT_EQ(clip_cache_item->cache_state(), RasterCacheItem::CacheState::kNone);
EXPECT_EQ(layer->raster_cache_item(), nullptr);
}

TEST_F(ClipRRectLayerTest, EmptyClipDoesNotCullPlatformView) {
Expand Down
Loading