mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Reland "Add a way to raster cache the children of a Layer (#32370)" (flutter/engine#32378)
This commit is contained in:
parent
abb86f34f3
commit
ffe61d39ca
@ -29,6 +29,7 @@ TEST_F(BackdropFilterLayerTest, PaintingEmptyLayerDies) {
|
||||
|
||||
parent->Preroll(preroll_context(), SkMatrix());
|
||||
EXPECT_EQ(layer->paint_bounds(), kEmptyRect);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), kEmptyRect);
|
||||
EXPECT_FALSE(layer->needs_painting(paint_context()));
|
||||
|
||||
EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()),
|
||||
@ -44,6 +45,7 @@ TEST_F(BackdropFilterLayerTest, PaintBeforePrerollDies) {
|
||||
layer->Add(mock_layer);
|
||||
|
||||
EXPECT_EQ(layer->paint_bounds(), kEmptyRect);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), kEmptyRect);
|
||||
EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()),
|
||||
"needs_painting\\(context\\)");
|
||||
}
|
||||
@ -63,6 +65,7 @@ TEST_F(BackdropFilterLayerTest, EmptyFilter) {
|
||||
|
||||
parent->Preroll(preroll_context(), initial_transform);
|
||||
EXPECT_EQ(layer->paint_bounds(), child_bounds);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), child_bounds);
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
EXPECT_EQ(mock_layer->parent_matrix(), initial_transform);
|
||||
|
||||
@ -92,6 +95,7 @@ TEST_F(BackdropFilterLayerTest, SimpleFilter) {
|
||||
|
||||
parent->Preroll(preroll_context(), initial_transform);
|
||||
EXPECT_EQ(layer->paint_bounds(), child_bounds);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), child_bounds);
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
EXPECT_EQ(mock_layer->parent_matrix(), initial_transform);
|
||||
|
||||
@ -121,6 +125,7 @@ TEST_F(BackdropFilterLayerTest, NonSrcOverBlend) {
|
||||
|
||||
parent->Preroll(preroll_context(), initial_transform);
|
||||
EXPECT_EQ(layer->paint_bounds(), child_bounds);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), child_bounds);
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
EXPECT_EQ(mock_layer->parent_matrix(), initial_transform);
|
||||
|
||||
@ -163,6 +168,7 @@ TEST_F(BackdropFilterLayerTest, MultipleChildren) {
|
||||
EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds());
|
||||
EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds());
|
||||
EXPECT_EQ(layer->paint_bounds(), children_bounds);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), children_bounds);
|
||||
EXPECT_TRUE(mock_layer1->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(mock_layer2->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
|
||||
@ -28,6 +28,7 @@ TEST_F(ClipPathLayerTest, PaintingEmptyLayerDies) {
|
||||
EXPECT_EQ(preroll_context()->cull_rect, kGiantRect); // Untouched
|
||||
EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched
|
||||
EXPECT_EQ(layer->paint_bounds(), kEmptyRect);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), kEmptyRect);
|
||||
EXPECT_FALSE(layer->needs_painting(paint_context()));
|
||||
|
||||
EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()),
|
||||
@ -39,6 +40,7 @@ TEST_F(ClipPathLayerTest, PaintBeforePrerollDies) {
|
||||
const SkPath layer_path = SkPath().addRect(layer_bounds);
|
||||
auto layer = std::make_shared<ClipPathLayer>(layer_path, Clip::hardEdge);
|
||||
EXPECT_EQ(layer->paint_bounds(), kEmptyRect);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), kEmptyRect);
|
||||
EXPECT_FALSE(layer->needs_painting(paint_context()));
|
||||
|
||||
EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()),
|
||||
@ -63,6 +65,7 @@ TEST_F(ClipPathLayerTest, PaintingCulledLayerDies) {
|
||||
EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched
|
||||
EXPECT_EQ(mock_layer->paint_bounds(), child_bounds);
|
||||
EXPECT_EQ(layer->paint_bounds(), child_bounds);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), child_bounds);
|
||||
EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
EXPECT_EQ(mock_layer->parent_cull_rect(), kEmptyRect);
|
||||
@ -100,6 +103,7 @@ TEST_F(ClipPathLayerTest, ChildOutsideBounds) {
|
||||
EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched
|
||||
EXPECT_EQ(mock_layer->paint_bounds(), child_bounds);
|
||||
EXPECT_EQ(layer->paint_bounds(), child_intersect_bounds);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), child_bounds);
|
||||
EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
EXPECT_EQ(mock_layer->parent_cull_rect(), intersect_bounds);
|
||||
@ -135,6 +139,7 @@ TEST_F(ClipPathLayerTest, FullyContainedChild) {
|
||||
EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched
|
||||
EXPECT_EQ(mock_layer->paint_bounds(), child_bounds);
|
||||
EXPECT_EQ(layer->paint_bounds(), mock_layer->paint_bounds());
|
||||
EXPECT_EQ(layer->child_paint_bounds(), child_bounds);
|
||||
EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
EXPECT_EQ(mock_layer->parent_cull_rect(), layer_bounds);
|
||||
@ -177,6 +182,7 @@ TEST_F(ClipPathLayerTest, PartiallyContainedChild) {
|
||||
EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched
|
||||
EXPECT_EQ(mock_layer->paint_bounds(), child_bounds);
|
||||
EXPECT_EQ(layer->paint_bounds(), child_intersect_bounds);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), child_bounds);
|
||||
EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
EXPECT_EQ(mock_layer->parent_cull_rect(), intersect_bounds);
|
||||
|
||||
@ -28,6 +28,7 @@ TEST_F(ClipRectLayerTest, PaintingEmptyLayerDies) {
|
||||
EXPECT_EQ(preroll_context()->cull_rect, kGiantRect); // Untouched
|
||||
EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched
|
||||
EXPECT_EQ(layer->paint_bounds(), kEmptyRect);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), kEmptyRect);
|
||||
EXPECT_FALSE(layer->needs_painting(paint_context()));
|
||||
|
||||
EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()),
|
||||
@ -38,6 +39,7 @@ TEST_F(ClipRectLayerTest, PaintBeforePrerollDies) {
|
||||
const SkRect layer_bounds = SkRect::MakeXYWH(0.5, 1.0, 5.0, 6.0);
|
||||
auto layer = std::make_shared<ClipRectLayer>(layer_bounds, Clip::hardEdge);
|
||||
EXPECT_EQ(layer->paint_bounds(), kEmptyRect);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), kEmptyRect);
|
||||
EXPECT_FALSE(layer->needs_painting(paint_context()));
|
||||
|
||||
EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()),
|
||||
@ -61,6 +63,7 @@ TEST_F(ClipRectLayerTest, PaintingCulledLayerDies) {
|
||||
EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched
|
||||
EXPECT_EQ(mock_layer->paint_bounds(), child_bounds);
|
||||
EXPECT_EQ(layer->paint_bounds(), child_bounds);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), child_bounds);
|
||||
EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
EXPECT_EQ(mock_layer->parent_cull_rect(), kEmptyRect);
|
||||
@ -98,6 +101,7 @@ TEST_F(ClipRectLayerTest, ChildOutsideBounds) {
|
||||
EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched
|
||||
EXPECT_EQ(mock_layer->paint_bounds(), child_bounds);
|
||||
EXPECT_EQ(layer->paint_bounds(), child_intersect_bounds);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), child_bounds);
|
||||
EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
EXPECT_EQ(mock_layer->parent_cull_rect(), intersect_bounds);
|
||||
@ -133,6 +137,7 @@ TEST_F(ClipRectLayerTest, FullyContainedChild) {
|
||||
EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched
|
||||
EXPECT_EQ(mock_layer->paint_bounds(), child_bounds);
|
||||
EXPECT_EQ(layer->paint_bounds(), mock_layer->paint_bounds());
|
||||
EXPECT_EQ(layer->child_paint_bounds(), child_bounds);
|
||||
EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
EXPECT_EQ(mock_layer->parent_cull_rect(), layer_bounds);
|
||||
@ -175,6 +180,7 @@ TEST_F(ClipRectLayerTest, PartiallyContainedChild) {
|
||||
EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched
|
||||
EXPECT_EQ(mock_layer->paint_bounds(), child_bounds);
|
||||
EXPECT_EQ(layer->paint_bounds(), child_intersect_bounds);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), child_bounds);
|
||||
EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
EXPECT_EQ(mock_layer->parent_cull_rect(), intersect_bounds);
|
||||
|
||||
@ -30,6 +30,7 @@ TEST_F(ClipRRectLayerTest, PaintingEmptyLayerDies) {
|
||||
EXPECT_EQ(preroll_context()->cull_rect, kGiantRect); // Untouched
|
||||
EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched
|
||||
EXPECT_EQ(layer->paint_bounds(), kEmptyRect);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), kEmptyRect);
|
||||
EXPECT_FALSE(layer->needs_painting(paint_context()));
|
||||
|
||||
EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()),
|
||||
@ -41,6 +42,7 @@ TEST_F(ClipRRectLayerTest, PaintBeforePrerollDies) {
|
||||
const SkRRect layer_rrect = SkRRect::MakeRect(layer_bounds);
|
||||
auto layer = std::make_shared<ClipRRectLayer>(layer_rrect, Clip::hardEdge);
|
||||
EXPECT_EQ(layer->paint_bounds(), kEmptyRect);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), kEmptyRect);
|
||||
EXPECT_FALSE(layer->needs_painting(paint_context()));
|
||||
|
||||
EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()),
|
||||
@ -66,6 +68,7 @@ TEST_F(ClipRRectLayerTest, PaintingCulledLayerDies) {
|
||||
EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched
|
||||
EXPECT_EQ(mock_layer->paint_bounds(), child_bounds);
|
||||
EXPECT_EQ(layer->paint_bounds(), child_bounds);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), child_bounds);
|
||||
EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
EXPECT_EQ(mock_layer->parent_cull_rect(), kEmptyRect);
|
||||
@ -103,6 +106,7 @@ TEST_F(ClipRRectLayerTest, ChildOutsideBounds) {
|
||||
EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched
|
||||
EXPECT_EQ(mock_layer->paint_bounds(), child_bounds);
|
||||
EXPECT_EQ(layer->paint_bounds(), child_intersect_bounds);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), child_bounds);
|
||||
EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
EXPECT_EQ(mock_layer->parent_cull_rect(), intersect_bounds);
|
||||
@ -138,6 +142,7 @@ TEST_F(ClipRRectLayerTest, FullyContainedChild) {
|
||||
EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched
|
||||
EXPECT_EQ(mock_layer->paint_bounds(), child_bounds);
|
||||
EXPECT_EQ(layer->paint_bounds(), mock_layer->paint_bounds());
|
||||
EXPECT_EQ(layer->child_paint_bounds(), child_bounds);
|
||||
EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
EXPECT_EQ(mock_layer->parent_cull_rect(), layer_bounds);
|
||||
@ -180,6 +185,7 @@ TEST_F(ClipRRectLayerTest, PartiallyContainedChild) {
|
||||
EXPECT_TRUE(preroll_context()->mutators_stack.is_empty()); // Untouched
|
||||
EXPECT_EQ(mock_layer->paint_bounds(), child_bounds);
|
||||
EXPECT_EQ(layer->paint_bounds(), child_intersect_bounds);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), child_bounds);
|
||||
EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
EXPECT_EQ(mock_layer->parent_cull_rect(), intersect_bounds);
|
||||
|
||||
@ -31,10 +31,12 @@ void ColorFilterLayer::Preroll(PrerollContext* context,
|
||||
ContainerLayer::Preroll(context, matrix);
|
||||
|
||||
if (render_count_ >= kMinimumRendersBeforeCachingFilterLayer) {
|
||||
TryToPrepareRasterCache(context, this, matrix);
|
||||
TryToPrepareRasterCache(context, this, matrix,
|
||||
RasterCacheLayerStrategy::kLayer);
|
||||
} else {
|
||||
render_count_++;
|
||||
TryToPrepareRasterCache(context, GetCacheableChild(), matrix);
|
||||
TryToPrepareRasterCache(context, this, matrix,
|
||||
RasterCacheLayerStrategy::kLayerChildren);
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,14 +45,16 @@ void ColorFilterLayer::Paint(PaintContext& context) const {
|
||||
FML_DCHECK(needs_painting(context));
|
||||
|
||||
if (context.raster_cache) {
|
||||
if (context.raster_cache->Draw(this, *context.leaf_nodes_canvas)) {
|
||||
if (context.raster_cache->Draw(this, *context.leaf_nodes_canvas,
|
||||
RasterCacheLayerStrategy::kLayer)) {
|
||||
return;
|
||||
}
|
||||
SkPaint paint;
|
||||
paint.setColorFilter(filter_);
|
||||
|
||||
if (context.raster_cache->Draw(GetCacheableChild(),
|
||||
*context.leaf_nodes_canvas, &paint)) {
|
||||
if (context.raster_cache->Draw(this, *context.leaf_nodes_canvas,
|
||||
RasterCacheLayerStrategy::kLayerChildren,
|
||||
&paint)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
|
||||
namespace flutter {
|
||||
|
||||
class ColorFilterLayer : public MergedContainerLayer {
|
||||
class ColorFilterLayer : public ContainerLayer {
|
||||
public:
|
||||
explicit ColorFilterLayer(sk_sp<SkColorFilter> filter);
|
||||
|
||||
|
||||
@ -22,6 +22,7 @@ TEST_F(ColorFilterLayerTest, PaintingEmptyLayerDies) {
|
||||
|
||||
layer->Preroll(preroll_context(), SkMatrix());
|
||||
EXPECT_EQ(layer->paint_bounds(), kEmptyRect);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), kEmptyRect);
|
||||
EXPECT_FALSE(layer->needs_painting(paint_context()));
|
||||
|
||||
EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()),
|
||||
@ -36,6 +37,7 @@ TEST_F(ColorFilterLayerTest, PaintBeforePrerollDies) {
|
||||
layer->Add(mock_layer);
|
||||
|
||||
EXPECT_EQ(layer->paint_bounds(), kEmptyRect);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), kEmptyRect);
|
||||
EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()),
|
||||
"needs_painting\\(context\\)");
|
||||
}
|
||||
@ -52,6 +54,7 @@ TEST_F(ColorFilterLayerTest, EmptyFilter) {
|
||||
|
||||
layer->Preroll(preroll_context(), initial_transform);
|
||||
EXPECT_EQ(layer->paint_bounds(), child_bounds);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), child_bounds);
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
EXPECT_EQ(mock_layer->parent_matrix(), initial_transform);
|
||||
|
||||
@ -81,6 +84,7 @@ TEST_F(ColorFilterLayerTest, SimpleFilter) {
|
||||
|
||||
layer->Preroll(preroll_context(), initial_transform);
|
||||
EXPECT_EQ(layer->paint_bounds(), child_bounds);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), child_bounds);
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
EXPECT_EQ(mock_layer->parent_matrix(), initial_transform);
|
||||
|
||||
@ -119,6 +123,7 @@ TEST_F(ColorFilterLayerTest, MultipleChildren) {
|
||||
EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds());
|
||||
EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds());
|
||||
EXPECT_EQ(layer->paint_bounds(), children_bounds);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), children_bounds);
|
||||
EXPECT_TRUE(mock_layer1->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(mock_layer2->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
@ -166,7 +171,9 @@ TEST_F(ColorFilterLayerTest, Nested) {
|
||||
EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds());
|
||||
EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds());
|
||||
EXPECT_EQ(layer1->paint_bounds(), children_bounds);
|
||||
EXPECT_EQ(layer1->child_paint_bounds(), children_bounds);
|
||||
EXPECT_EQ(layer2->paint_bounds(), mock_layer2->paint_bounds());
|
||||
EXPECT_EQ(layer2->child_paint_bounds(), mock_layer2->paint_bounds());
|
||||
EXPECT_TRUE(mock_layer1->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(mock_layer2->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(layer1->needs_painting(paint_context()));
|
||||
@ -213,7 +220,7 @@ TEST_F(ColorFilterLayerTest, Readback) {
|
||||
EXPECT_FALSE(preroll_context()->surface_needs_readback);
|
||||
}
|
||||
|
||||
TEST_F(ColorFilterLayerTest, ChildIsCached) {
|
||||
TEST_F(ColorFilterLayerTest, CacheChild) {
|
||||
auto layer_filter =
|
||||
SkColorMatrixFilter::MakeLightingFilter(SK_ColorGREEN, SK_ColorYELLOW);
|
||||
auto initial_transform = SkMatrix::Translate(50.0, 25.5);
|
||||
@ -234,15 +241,31 @@ TEST_F(ColorFilterLayerTest, ChildIsCached) {
|
||||
EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)0);
|
||||
EXPECT_FALSE(raster_cache()->Draw(mock_layer.get(), other_canvas));
|
||||
EXPECT_FALSE(raster_cache()->Draw(mock_layer.get(), cache_canvas));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), other_canvas,
|
||||
RasterCacheLayerStrategy::kLayer));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), cache_canvas,
|
||||
RasterCacheLayerStrategy::kLayer));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), other_canvas,
|
||||
RasterCacheLayerStrategy::kLayerChildren));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), cache_canvas,
|
||||
RasterCacheLayerStrategy::kLayerChildren));
|
||||
|
||||
layer->Preroll(preroll_context(), initial_transform);
|
||||
|
||||
EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)1);
|
||||
EXPECT_FALSE(raster_cache()->Draw(mock_layer.get(), other_canvas));
|
||||
EXPECT_TRUE(raster_cache()->Draw(mock_layer.get(), cache_canvas));
|
||||
EXPECT_FALSE(raster_cache()->Draw(mock_layer.get(), cache_canvas));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), other_canvas,
|
||||
RasterCacheLayerStrategy::kLayer));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), cache_canvas,
|
||||
RasterCacheLayerStrategy::kLayer));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), other_canvas,
|
||||
RasterCacheLayerStrategy::kLayerChildren));
|
||||
EXPECT_TRUE(raster_cache()->Draw(layer.get(), cache_canvas,
|
||||
RasterCacheLayerStrategy::kLayerChildren));
|
||||
}
|
||||
|
||||
TEST_F(ColorFilterLayerTest, ChildrenNotCached) {
|
||||
TEST_F(ColorFilterLayerTest, CacheChildren) {
|
||||
auto layer_filter =
|
||||
SkColorMatrixFilter::MakeLightingFilter(SK_ColorGREEN, SK_ColorYELLOW);
|
||||
auto initial_transform = SkMatrix::Translate(50.0, 25.5);
|
||||
@ -268,6 +291,14 @@ TEST_F(ColorFilterLayerTest, ChildrenNotCached) {
|
||||
EXPECT_FALSE(raster_cache()->Draw(mock_layer1.get(), cache_canvas));
|
||||
EXPECT_FALSE(raster_cache()->Draw(mock_layer2.get(), other_canvas));
|
||||
EXPECT_FALSE(raster_cache()->Draw(mock_layer2.get(), cache_canvas));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), other_canvas,
|
||||
RasterCacheLayerStrategy::kLayer));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), cache_canvas,
|
||||
RasterCacheLayerStrategy::kLayer));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), other_canvas,
|
||||
RasterCacheLayerStrategy::kLayerChildren));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), cache_canvas,
|
||||
RasterCacheLayerStrategy::kLayerChildren));
|
||||
|
||||
layer->Preroll(preroll_context(), initial_transform);
|
||||
|
||||
@ -276,6 +307,14 @@ TEST_F(ColorFilterLayerTest, ChildrenNotCached) {
|
||||
EXPECT_FALSE(raster_cache()->Draw(mock_layer1.get(), cache_canvas));
|
||||
EXPECT_FALSE(raster_cache()->Draw(mock_layer2.get(), other_canvas));
|
||||
EXPECT_FALSE(raster_cache()->Draw(mock_layer2.get(), cache_canvas));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), other_canvas,
|
||||
RasterCacheLayerStrategy::kLayer));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), cache_canvas,
|
||||
RasterCacheLayerStrategy::kLayer));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), other_canvas,
|
||||
RasterCacheLayerStrategy::kLayerChildren));
|
||||
EXPECT_TRUE(raster_cache()->Draw(layer.get(), cache_canvas,
|
||||
RasterCacheLayerStrategy::kLayerChildren));
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
|
||||
@ -8,7 +8,7 @@
|
||||
|
||||
namespace flutter {
|
||||
|
||||
ContainerLayer::ContainerLayer() {}
|
||||
ContainerLayer::ContainerLayer() : child_paint_bounds_(SkRect::MakeEmpty()) {}
|
||||
|
||||
void ContainerLayer::Diff(DiffContext* context, const Layer* old_layer) {
|
||||
auto old_container = static_cast<const ContainerLayer*>(old_layer);
|
||||
@ -170,6 +170,7 @@ void ContainerLayer::PrerollChildren(PrerollContext* context,
|
||||
context->has_texture_layer = child_has_texture_layer;
|
||||
context->subtree_can_inherit_opacity = subtree_can_inherit_opacity;
|
||||
set_subtree_has_platform_view(child_has_platform_view);
|
||||
child_paint_bounds_ = *child_paint_bounds;
|
||||
}
|
||||
|
||||
void ContainerLayer::PaintChildren(PaintContext& context) const {
|
||||
@ -188,71 +189,19 @@ void ContainerLayer::PaintChildren(PaintContext& context) const {
|
||||
}
|
||||
}
|
||||
|
||||
void ContainerLayer::TryToPrepareRasterCache(PrerollContext* context,
|
||||
Layer* layer,
|
||||
const SkMatrix& matrix) {
|
||||
void ContainerLayer::TryToPrepareRasterCache(
|
||||
PrerollContext* context,
|
||||
Layer* layer,
|
||||
const SkMatrix& matrix,
|
||||
RasterCacheLayerStrategy strategy) {
|
||||
if (!context->has_platform_view && !context->has_texture_layer &&
|
||||
context->raster_cache &&
|
||||
SkRect::Intersects(context->cull_rect, layer->paint_bounds())) {
|
||||
context->raster_cache->Prepare(context, layer, matrix);
|
||||
context->raster_cache->Prepare(context, layer, matrix, strategy);
|
||||
} else if (context->raster_cache) {
|
||||
// Don't evict raster cache entry during partial repaint
|
||||
context->raster_cache->Touch(layer, matrix);
|
||||
context->raster_cache->Touch(layer, matrix, strategy);
|
||||
}
|
||||
}
|
||||
|
||||
MergedContainerLayer::MergedContainerLayer() {
|
||||
// Ensure the layer has only one direct child.
|
||||
//
|
||||
// Any children will actually be added as children of this empty
|
||||
// ContainerLayer which can be accessed via ::GetContainerLayer().
|
||||
// If only one child is ever added to this layer then that child
|
||||
// will become the layer returned from ::GetCacheableChild().
|
||||
// If multiple child layers are added, then this implicit container
|
||||
// child becomes the cacheable child, but at the potential cost of
|
||||
// not being as stable in the raster cache from frame to frame.
|
||||
ContainerLayer::Add(std::make_shared<ContainerLayer>());
|
||||
|
||||
// The interposing Container only recurses to its children with no
|
||||
// additional processing so, by default, it can pass an inherited
|
||||
// opacity on to its children, subject only to the accumulation
|
||||
// logic that happens during |PrerollChildren|.
|
||||
GetChildContainer()->set_layer_can_inherit_opacity(true);
|
||||
}
|
||||
|
||||
void MergedContainerLayer::DiffChildren(DiffContext* context,
|
||||
const ContainerLayer* old_layer) {
|
||||
if (context->IsSubtreeDirty()) {
|
||||
GetChildContainer()->Diff(context, nullptr);
|
||||
return;
|
||||
}
|
||||
FML_DCHECK(old_layer);
|
||||
|
||||
// For MergedContainerLayer we want to diff children of ChildContainer
|
||||
// instead of the ChildContainer itself. This works around the fact
|
||||
// that ChildContainerLayer is ephemeral and its original_layer_id_ is always
|
||||
// different.
|
||||
auto layer = static_cast<const MergedContainerLayer*>(old_layer);
|
||||
GetChildContainer()->DiffChildren(context, layer->GetChildContainer());
|
||||
}
|
||||
|
||||
void MergedContainerLayer::Add(std::shared_ptr<Layer> layer) {
|
||||
GetChildContainer()->Add(std::move(layer));
|
||||
}
|
||||
|
||||
ContainerLayer* MergedContainerLayer::GetChildContainer() const {
|
||||
FML_DCHECK(layers().size() == 1);
|
||||
|
||||
return static_cast<ContainerLayer*>(layers()[0].get());
|
||||
}
|
||||
|
||||
Layer* MergedContainerLayer::GetCacheableChild() const {
|
||||
ContainerLayer* child_container = GetChildContainer();
|
||||
if (child_container->layers().size() == 1) {
|
||||
return child_container->layers()[0].get();
|
||||
}
|
||||
|
||||
return child_container;
|
||||
}
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
@ -27,12 +27,15 @@ class ContainerLayer : public Layer {
|
||||
|
||||
virtual void DiffChildren(DiffContext* context,
|
||||
const ContainerLayer* old_layer);
|
||||
void PaintChildren(PaintContext& context) const;
|
||||
const ContainerLayer* as_container_layer() const override { return this; }
|
||||
|
||||
const SkRect& child_paint_bounds() const { return child_paint_bounds_; }
|
||||
|
||||
protected:
|
||||
void PrerollChildren(PrerollContext* context,
|
||||
const SkMatrix& child_matrix,
|
||||
SkRect* child_paint_bounds);
|
||||
void PaintChildren(PaintContext& context) const;
|
||||
|
||||
// Try to prepare the raster cache for a given layer.
|
||||
//
|
||||
@ -46,92 +49,16 @@ class ContainerLayer : public Layer {
|
||||
// cache a child layer and one can't access its child's protected method.
|
||||
static void TryToPrepareRasterCache(PrerollContext* context,
|
||||
Layer* layer,
|
||||
const SkMatrix& matrix);
|
||||
const SkMatrix& matrix,
|
||||
RasterCacheLayerStrategy strategy);
|
||||
|
||||
private:
|
||||
std::vector<std::shared_ptr<Layer>> layers_;
|
||||
SkRect child_paint_bounds_;
|
||||
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(ContainerLayer);
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/// Some ContainerLayer objects perform a rendering operation or filter on
|
||||
/// the rendered output of their children. Often that operation is changed
|
||||
/// slightly from frame to frame as part of an animation. During such an
|
||||
/// animation, the children can be cached if they are stable to avoid having
|
||||
/// to render them on every frame. Even if the children are not stable,
|
||||
/// rendering them into the raster cache during a Preroll operation will save
|
||||
/// an extra change of rendering surface during the Paint phase as compared
|
||||
/// to using the SaveLayer that would otherwise be needed with no caching.
|
||||
///
|
||||
/// Typically the Flutter Widget objects that lead to the creation of these
|
||||
/// layers will try to enforce only a single child Widget by their design.
|
||||
/// Unfortunately, the process of turning Widgets eventually into engine
|
||||
/// layers is not a 1:1 process so this layer might end up with multiple
|
||||
/// child layers even if the Widget only had a single child Widget.
|
||||
///
|
||||
/// When such a layer goes to cache the output of its children, it will
|
||||
/// need to supply a single layer to the cache mechanism since the raster
|
||||
/// cache uses a layer unique_id() as part of the cache key. If this layer
|
||||
/// ended up with multiple children, then it must first collect them into
|
||||
/// one layer for the cache mechanism. In order to provide a single layer
|
||||
/// for all of the children, this utility class will implicitly collect
|
||||
/// the children into a secondary ContainerLayer called the child container.
|
||||
///
|
||||
/// A by-product of creating a hidden child container, though, is that the
|
||||
/// child container is created new every time this layer is created with
|
||||
/// different properties, such as during an animation. In that scenario,
|
||||
/// it would be best to cache the single real child of this layer if it
|
||||
/// is unique and if it is stable from frame to frame. To facilitate this
|
||||
/// optimal caching strategy, this class implements two accessor methods
|
||||
/// to be used for different purposes:
|
||||
///
|
||||
/// When the layer needs to recurse to perform some operation on its children,
|
||||
/// it can call GetChildContainer() to return the hidden container containing
|
||||
/// all of the real children.
|
||||
///
|
||||
/// When the layer wants to cache the rendered contents of its children, it
|
||||
/// should call GetCacheableChild() for best performance. This method may
|
||||
/// end up returning the same layer as GetChildContainer(), but only if the
|
||||
/// conditions for optimal caching of a single child are not met.
|
||||
///
|
||||
class MergedContainerLayer : public ContainerLayer {
|
||||
public:
|
||||
MergedContainerLayer();
|
||||
|
||||
void Add(std::shared_ptr<Layer> layer) override;
|
||||
|
||||
void DiffChildren(DiffContext* context,
|
||||
const ContainerLayer* old_layer) override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief Returns the ContainerLayer used to hold all of the children of the
|
||||
* MergedContainerLayer. Note that this may not be the best layer to use
|
||||
* for caching the children.
|
||||
*
|
||||
* @see GetCacheableChild()
|
||||
* @return the ContainerLayer child used to hold the children
|
||||
*/
|
||||
ContainerLayer* GetChildContainer() const;
|
||||
|
||||
/**
|
||||
* @brief Returns the best choice for a Layer object that can be used
|
||||
* in RasterCache operations to cache the children.
|
||||
*
|
||||
* The returned Layer must represent all children and try to remain stable
|
||||
* if the MergedContainerLayer is reconstructed in subsequent frames of
|
||||
* the scene.
|
||||
*
|
||||
* @see GetChildContainer()
|
||||
* @return the best candidate Layer for caching the children
|
||||
*/
|
||||
Layer* GetCacheableChild() const;
|
||||
|
||||
private:
|
||||
FML_DISALLOW_COPY_AND_ASSIGN(MergedContainerLayer);
|
||||
};
|
||||
|
||||
} // namespace flutter
|
||||
|
||||
#endif // FLUTTER_FLOW_LAYERS_CONTAINER_LAYER_H_
|
||||
|
||||
@ -29,6 +29,7 @@ TEST_F(ContainerLayerTest, PaintingEmptyLayerDies) {
|
||||
|
||||
layer->Preroll(preroll_context(), SkMatrix());
|
||||
EXPECT_EQ(layer->paint_bounds(), SkRect::MakeEmpty());
|
||||
EXPECT_EQ(layer->child_paint_bounds(), SkRect::MakeEmpty());
|
||||
EXPECT_FALSE(layer->needs_painting(paint_context()));
|
||||
|
||||
EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()),
|
||||
@ -43,6 +44,7 @@ TEST_F(ContainerLayerTest, PaintBeforePrerollDies) {
|
||||
layer->Add(mock_layer);
|
||||
|
||||
EXPECT_EQ(layer->paint_bounds(), SkRect::MakeEmpty());
|
||||
EXPECT_EQ(layer->child_paint_bounds(), SkRect::MakeEmpty());
|
||||
EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()),
|
||||
"needs_painting\\(context\\)");
|
||||
}
|
||||
@ -62,6 +64,7 @@ TEST_F(ContainerLayerTest, Simple) {
|
||||
EXPECT_FALSE(preroll_context()->has_platform_view);
|
||||
EXPECT_EQ(mock_layer->paint_bounds(), child_path.getBounds());
|
||||
EXPECT_EQ(layer->paint_bounds(), child_path.getBounds());
|
||||
EXPECT_EQ(layer->child_paint_bounds(), layer->paint_bounds());
|
||||
EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
EXPECT_EQ(mock_layer->parent_matrix(), initial_transform);
|
||||
@ -96,6 +99,7 @@ TEST_F(ContainerLayerTest, Multiple) {
|
||||
EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds());
|
||||
EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds());
|
||||
EXPECT_EQ(layer->paint_bounds(), expected_total_bounds);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), layer->paint_bounds());
|
||||
EXPECT_TRUE(mock_layer1->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(mock_layer2->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
@ -132,6 +136,7 @@ TEST_F(ContainerLayerTest, MultipleWithEmpty) {
|
||||
EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds());
|
||||
EXPECT_EQ(mock_layer2->paint_bounds(), SkPath().getBounds());
|
||||
EXPECT_EQ(layer->paint_bounds(), child_path1.getBounds());
|
||||
EXPECT_EQ(layer->child_paint_bounds(), layer->paint_bounds());
|
||||
EXPECT_TRUE(mock_layer1->needs_painting(paint_context()));
|
||||
EXPECT_FALSE(mock_layer2->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
@ -169,6 +174,7 @@ TEST_F(ContainerLayerTest, NeedsSystemComposite) {
|
||||
EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds());
|
||||
EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds());
|
||||
EXPECT_EQ(layer->paint_bounds(), expected_total_bounds);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), layer->paint_bounds());
|
||||
EXPECT_TRUE(mock_layer1->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(mock_layer2->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
@ -186,71 +192,6 @@ TEST_F(ContainerLayerTest, NeedsSystemComposite) {
|
||||
child_path2, child_paint2}}}));
|
||||
}
|
||||
|
||||
TEST_F(ContainerLayerTest, MergedOneChild) {
|
||||
SkPath child_path;
|
||||
child_path.addRect(5.0f, 6.0f, 20.5f, 21.5f);
|
||||
SkPaint child_paint(SkColors::kGreen);
|
||||
SkMatrix initial_transform = SkMatrix::Translate(-0.5f, -0.5f);
|
||||
|
||||
auto mock_layer = std::make_shared<MockLayer>(child_path, child_paint);
|
||||
auto layer = std::make_shared<MergedContainerLayer>();
|
||||
layer->Add(mock_layer);
|
||||
|
||||
layer->Preroll(preroll_context(), initial_transform);
|
||||
EXPECT_FALSE(preroll_context()->has_platform_view);
|
||||
EXPECT_EQ(mock_layer->paint_bounds(), child_path.getBounds());
|
||||
EXPECT_EQ(layer->paint_bounds(), child_path.getBounds());
|
||||
EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
EXPECT_EQ(mock_layer->parent_matrix(), initial_transform);
|
||||
EXPECT_EQ(mock_layer->parent_cull_rect(), kGiantRect);
|
||||
|
||||
layer->Paint(paint_context());
|
||||
EXPECT_EQ(mock_canvas().draw_calls(),
|
||||
std::vector({MockCanvas::DrawCall{
|
||||
0, MockCanvas::DrawPathData{child_path, child_paint}}}));
|
||||
}
|
||||
|
||||
TEST_F(ContainerLayerTest, MergedMultipleChildren) {
|
||||
SkPath child_path1;
|
||||
child_path1.addRect(5.0f, 6.0f, 20.5f, 21.5f);
|
||||
SkPath child_path2;
|
||||
child_path2.addRect(58.0f, 2.0f, 16.5f, 14.5f);
|
||||
SkPaint child_paint1(SkColors::kGray);
|
||||
SkPaint child_paint2(SkColors::kGreen);
|
||||
SkMatrix initial_transform = SkMatrix::Translate(-0.5f, -0.5f);
|
||||
|
||||
auto mock_layer1 = std::make_shared<MockLayer>(child_path1, child_paint1);
|
||||
auto mock_layer2 = std::make_shared<MockLayer>(child_path2, child_paint2);
|
||||
auto layer = std::make_shared<MergedContainerLayer>();
|
||||
layer->Add(mock_layer1);
|
||||
layer->Add(mock_layer2);
|
||||
|
||||
SkRect expected_total_bounds = child_path1.getBounds();
|
||||
expected_total_bounds.join(child_path2.getBounds());
|
||||
layer->Preroll(preroll_context(), initial_transform);
|
||||
EXPECT_FALSE(preroll_context()->has_platform_view);
|
||||
EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds());
|
||||
EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds());
|
||||
EXPECT_EQ(layer->paint_bounds(), expected_total_bounds);
|
||||
EXPECT_TRUE(mock_layer1->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(mock_layer2->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
EXPECT_EQ(mock_layer1->parent_matrix(), initial_transform);
|
||||
EXPECT_EQ(mock_layer2->parent_matrix(), initial_transform);
|
||||
EXPECT_EQ(mock_layer1->parent_cull_rect(), kGiantRect);
|
||||
EXPECT_EQ(mock_layer2->parent_cull_rect(),
|
||||
kGiantRect); // Siblings are independent
|
||||
|
||||
layer->Paint(paint_context());
|
||||
EXPECT_EQ(
|
||||
mock_canvas().draw_calls(),
|
||||
std::vector({MockCanvas::DrawCall{
|
||||
0, MockCanvas::DrawPathData{child_path1, child_paint1}},
|
||||
MockCanvas::DrawCall{0, MockCanvas::DrawPathData{
|
||||
child_path2, child_paint2}}}));
|
||||
}
|
||||
|
||||
using ContainerLayerDiffTest = DiffContextTest;
|
||||
|
||||
// Insert PictureLayer amongst container layers
|
||||
|
||||
@ -63,7 +63,8 @@ void ImageFilterLayer::Preroll(PrerollContext* context,
|
||||
// times to consider its properties and children to be stable
|
||||
// from frame to frame so we try to cache the layer itself
|
||||
// for maximum performance.
|
||||
TryToPrepareRasterCache(context, this, matrix);
|
||||
TryToPrepareRasterCache(context, this, matrix,
|
||||
RasterCacheLayerStrategy::kLayer);
|
||||
} else {
|
||||
// This ImageFilterLayer is not yet considered stable so we
|
||||
// increment the count to measure how many times it has been
|
||||
@ -84,7 +85,8 @@ void ImageFilterLayer::Preroll(PrerollContext* context,
|
||||
// stable between frames and also avoiding a rendering surface
|
||||
// switch during the Paint phase even if they are not stable.
|
||||
// This benefit is seen most during animations.
|
||||
TryToPrepareRasterCache(context, GetCacheableChild(), matrix);
|
||||
TryToPrepareRasterCache(context, this, matrix,
|
||||
RasterCacheLayerStrategy::kLayerChildren);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -94,15 +96,16 @@ void ImageFilterLayer::Paint(PaintContext& context) const {
|
||||
FML_DCHECK(needs_painting(context));
|
||||
|
||||
if (context.raster_cache) {
|
||||
if (context.raster_cache->Draw(this, *context.leaf_nodes_canvas)) {
|
||||
if (context.raster_cache->Draw(this, *context.leaf_nodes_canvas,
|
||||
RasterCacheLayerStrategy::kLayer)) {
|
||||
return;
|
||||
}
|
||||
if (transformed_filter_) {
|
||||
SkPaint paint;
|
||||
paint.setImageFilter(transformed_filter_);
|
||||
|
||||
if (context.raster_cache->Draw(GetCacheableChild(),
|
||||
*context.leaf_nodes_canvas, &paint)) {
|
||||
if (context.raster_cache->Draw(this, *context.leaf_nodes_canvas,
|
||||
RasterCacheLayerStrategy::kLayerChildren,
|
||||
&paint)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -115,8 +118,8 @@ void ImageFilterLayer::Paint(PaintContext& context) const {
|
||||
// case the bounds of the child may not be the same as the filtered version
|
||||
// so we use the bounds of the child container which do not include any
|
||||
// modifications that the filter might apply.
|
||||
Layer::AutoSaveLayer save_layer = Layer::AutoSaveLayer::Create(
|
||||
context, GetChildContainer()->paint_bounds(), &paint);
|
||||
Layer::AutoSaveLayer save_layer =
|
||||
Layer::AutoSaveLayer::Create(context, child_paint_bounds(), &paint);
|
||||
PaintChildren(context);
|
||||
}
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@
|
||||
|
||||
namespace flutter {
|
||||
|
||||
class ImageFilterLayer : public MergedContainerLayer {
|
||||
class ImageFilterLayer : public ContainerLayer {
|
||||
public:
|
||||
explicit ImageFilterLayer(sk_sp<SkImageFilter> filter);
|
||||
|
||||
|
||||
@ -37,6 +37,7 @@ TEST_F(ImageFilterLayerTest, PaintBeforePrerollDies) {
|
||||
layer->Add(mock_layer);
|
||||
|
||||
EXPECT_EQ(layer->paint_bounds(), kEmptyRect);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), kEmptyRect);
|
||||
EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()),
|
||||
"needs_painting\\(context\\)");
|
||||
}
|
||||
@ -53,6 +54,7 @@ TEST_F(ImageFilterLayerTest, EmptyFilter) {
|
||||
|
||||
layer->Preroll(preroll_context(), initial_transform);
|
||||
EXPECT_EQ(layer->paint_bounds(), child_bounds);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), child_bounds);
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
EXPECT_EQ(mock_layer->parent_matrix(), initial_transform);
|
||||
|
||||
@ -87,6 +89,7 @@ TEST_F(ImageFilterLayerTest, SimpleFilter) {
|
||||
|
||||
layer->Preroll(preroll_context(), initial_transform);
|
||||
EXPECT_EQ(layer->paint_bounds(), child_rounded_bounds);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), child_bounds);
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
EXPECT_EQ(mock_layer->parent_matrix(), initial_transform);
|
||||
|
||||
@ -121,6 +124,7 @@ TEST_F(ImageFilterLayerTest, SimpleFilterBounds) {
|
||||
|
||||
layer->Preroll(preroll_context(), initial_transform);
|
||||
EXPECT_EQ(layer->paint_bounds(), filter_bounds);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), child_bounds);
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
EXPECT_EQ(mock_layer->parent_matrix(), initial_transform);
|
||||
|
||||
@ -163,6 +167,7 @@ TEST_F(ImageFilterLayerTest, MultipleChildren) {
|
||||
EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds());
|
||||
EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds());
|
||||
EXPECT_EQ(layer->paint_bounds(), children_rounded_bounds);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), children_bounds);
|
||||
EXPECT_TRUE(mock_layer1->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(mock_layer2->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
@ -217,7 +222,9 @@ TEST_F(ImageFilterLayerTest, Nested) {
|
||||
EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds());
|
||||
EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds());
|
||||
EXPECT_EQ(layer1->paint_bounds(), children_rounded_bounds);
|
||||
EXPECT_EQ(layer1->child_paint_bounds(), children_bounds);
|
||||
EXPECT_EQ(layer2->paint_bounds(), mock_layer2_rounded_bounds);
|
||||
EXPECT_EQ(layer2->child_paint_bounds(), child_path2.getBounds());
|
||||
EXPECT_TRUE(mock_layer1->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(mock_layer2->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(layer1->needs_painting(paint_context()));
|
||||
@ -267,7 +274,7 @@ TEST_F(ImageFilterLayerTest, Readback) {
|
||||
EXPECT_FALSE(preroll_context()->surface_needs_readback);
|
||||
}
|
||||
|
||||
TEST_F(ImageFilterLayerTest, ChildIsCached) {
|
||||
TEST_F(ImageFilterLayerTest, CacheChild) {
|
||||
auto layer_filter = SkImageFilters::MatrixTransform(
|
||||
SkMatrix(),
|
||||
SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear), nullptr);
|
||||
@ -289,15 +296,31 @@ TEST_F(ImageFilterLayerTest, ChildIsCached) {
|
||||
EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)0);
|
||||
EXPECT_FALSE(raster_cache()->Draw(mock_layer.get(), other_canvas));
|
||||
EXPECT_FALSE(raster_cache()->Draw(mock_layer.get(), cache_canvas));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), other_canvas,
|
||||
RasterCacheLayerStrategy::kLayer));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), cache_canvas,
|
||||
RasterCacheLayerStrategy::kLayer));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), other_canvas,
|
||||
RasterCacheLayerStrategy::kLayerChildren));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), cache_canvas,
|
||||
RasterCacheLayerStrategy::kLayerChildren));
|
||||
|
||||
layer->Preroll(preroll_context(), initial_transform);
|
||||
|
||||
EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)1);
|
||||
EXPECT_FALSE(raster_cache()->Draw(mock_layer.get(), other_canvas));
|
||||
EXPECT_TRUE(raster_cache()->Draw(mock_layer.get(), cache_canvas));
|
||||
EXPECT_FALSE(raster_cache()->Draw(mock_layer.get(), cache_canvas));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), other_canvas,
|
||||
RasterCacheLayerStrategy::kLayer));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), cache_canvas,
|
||||
RasterCacheLayerStrategy::kLayer));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), other_canvas,
|
||||
RasterCacheLayerStrategy::kLayerChildren));
|
||||
EXPECT_TRUE(raster_cache()->Draw(layer.get(), cache_canvas,
|
||||
RasterCacheLayerStrategy::kLayerChildren));
|
||||
}
|
||||
|
||||
TEST_F(ImageFilterLayerTest, ChildrenNotCached) {
|
||||
TEST_F(ImageFilterLayerTest, CacheChildren) {
|
||||
auto layer_filter = SkImageFilters::MatrixTransform(
|
||||
SkMatrix(),
|
||||
SkSamplingOptions(SkFilterMode::kLinear, SkMipmapMode::kLinear), nullptr);
|
||||
@ -324,6 +347,14 @@ TEST_F(ImageFilterLayerTest, ChildrenNotCached) {
|
||||
EXPECT_FALSE(raster_cache()->Draw(mock_layer1.get(), cache_canvas));
|
||||
EXPECT_FALSE(raster_cache()->Draw(mock_layer2.get(), other_canvas));
|
||||
EXPECT_FALSE(raster_cache()->Draw(mock_layer2.get(), cache_canvas));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), other_canvas,
|
||||
RasterCacheLayerStrategy::kLayer));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), cache_canvas,
|
||||
RasterCacheLayerStrategy::kLayer));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), other_canvas,
|
||||
RasterCacheLayerStrategy::kLayerChildren));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), cache_canvas,
|
||||
RasterCacheLayerStrategy::kLayerChildren));
|
||||
|
||||
layer->Preroll(preroll_context(), initial_transform);
|
||||
|
||||
@ -332,6 +363,14 @@ TEST_F(ImageFilterLayerTest, ChildrenNotCached) {
|
||||
EXPECT_FALSE(raster_cache()->Draw(mock_layer1.get(), cache_canvas));
|
||||
EXPECT_FALSE(raster_cache()->Draw(mock_layer2.get(), other_canvas));
|
||||
EXPECT_FALSE(raster_cache()->Draw(mock_layer2.get(), cache_canvas));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), other_canvas,
|
||||
RasterCacheLayerStrategy::kLayer));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), cache_canvas,
|
||||
RasterCacheLayerStrategy::kLayer));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), other_canvas,
|
||||
RasterCacheLayerStrategy::kLayerChildren));
|
||||
EXPECT_TRUE(raster_cache()->Draw(layer.get(), cache_canvas,
|
||||
RasterCacheLayerStrategy::kLayerChildren));
|
||||
}
|
||||
|
||||
using ImageFilterLayerDiffTest = DiffContextTest;
|
||||
|
||||
@ -82,6 +82,7 @@ struct PrerollContext {
|
||||
bool subtree_can_inherit_opacity = false;
|
||||
};
|
||||
|
||||
class ContainerLayer;
|
||||
class PictureLayer;
|
||||
class DisplayListLayer;
|
||||
class PerformanceOverlayLayer;
|
||||
@ -330,6 +331,7 @@ class Layer {
|
||||
|
||||
uint64_t unique_id() const { return unique_id_; }
|
||||
|
||||
virtual const ContainerLayer* as_container_layer() const { return nullptr; }
|
||||
virtual const PictureLayer* as_picture_layer() const { return nullptr; }
|
||||
virtual const DisplayListLayer* as_display_list_layer() const {
|
||||
return nullptr;
|
||||
|
||||
@ -37,7 +37,7 @@ void OpacityLayer::Diff(DiffContext* context, const Layer* old_layer) {
|
||||
|
||||
void OpacityLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
|
||||
TRACE_EVENT0("flutter", "OpacityLayer::Preroll");
|
||||
FML_DCHECK(!GetChildContainer()->layers().empty()); // We can't be a leaf.
|
||||
FML_DCHECK(!layers().empty()); // We can't be a leaf.
|
||||
|
||||
SkMatrix child_matrix = matrix;
|
||||
child_matrix.preTranslate(offset_.fX, offset_.fY);
|
||||
@ -63,7 +63,8 @@ void OpacityLayer::Preroll(PrerollContext* context, const SkMatrix& matrix) {
|
||||
#ifndef SUPPORT_FRACTIONAL_TRANSLATION
|
||||
child_matrix = RasterCache::GetIntegralTransCTM(child_matrix);
|
||||
#endif
|
||||
TryToPrepareRasterCache(context, GetCacheableChild(), child_matrix);
|
||||
TryToPrepareRasterCache(context, this, child_matrix,
|
||||
RasterCacheLayerStrategy::kLayerChildren);
|
||||
}
|
||||
|
||||
// Restore cull_rect
|
||||
@ -96,8 +97,9 @@ void OpacityLayer::Paint(PaintContext& context) const {
|
||||
paint.setAlphaf(subtree_opacity);
|
||||
|
||||
if (context.raster_cache &&
|
||||
context.raster_cache->Draw(GetCacheableChild(),
|
||||
*context.leaf_nodes_canvas, &paint)) {
|
||||
context.raster_cache->Draw(this, *context.leaf_nodes_canvas,
|
||||
RasterCacheLayerStrategy::kLayerChildren,
|
||||
&paint)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -13,7 +13,7 @@ namespace flutter {
|
||||
// OpacityLayer is very costly due to the saveLayer call. If there's no child,
|
||||
// having the OpacityLayer or not has the same effect. In debug_unopt build,
|
||||
// |Preroll| will assert if there are no children.
|
||||
class OpacityLayer : public MergedContainerLayer {
|
||||
class OpacityLayer : public ContainerLayer {
|
||||
public:
|
||||
// An offset is provided here because OpacityLayer.addToScene method in the
|
||||
// Flutter framework can take an optional offset argument.
|
||||
|
||||
@ -21,9 +21,8 @@ TEST_F(OpacityLayerTest, LeafLayer) {
|
||||
auto layer =
|
||||
std::make_shared<OpacityLayer>(SK_AlphaOPAQUE, SkPoint::Make(0.0f, 0.0f));
|
||||
|
||||
EXPECT_DEATH_IF_SUPPORTED(
|
||||
layer->Preroll(preroll_context(), SkMatrix()),
|
||||
"\\!GetChildContainer\\(\\)->layers\\(\\)\\.empty\\(\\)");
|
||||
EXPECT_DEATH_IF_SUPPORTED(layer->Preroll(preroll_context(), SkMatrix()),
|
||||
"\\!layers\\(\\)\\.empty\\(\\)");
|
||||
}
|
||||
|
||||
TEST_F(OpacityLayerTest, PaintingEmptyLayerDies) {
|
||||
@ -35,6 +34,7 @@ TEST_F(OpacityLayerTest, PaintingEmptyLayerDies) {
|
||||
layer->Preroll(preroll_context(), SkMatrix());
|
||||
EXPECT_EQ(mock_layer->paint_bounds(), SkPath().getBounds());
|
||||
EXPECT_EQ(layer->paint_bounds(), mock_layer->paint_bounds());
|
||||
EXPECT_EQ(layer->child_paint_bounds(), mock_layer->paint_bounds());
|
||||
EXPECT_FALSE(mock_layer->needs_painting(paint_context()));
|
||||
EXPECT_FALSE(layer->needs_painting(paint_context()));
|
||||
|
||||
@ -72,7 +72,7 @@ TEST_F(OpacityLayerTest, TranslateChildren) {
|
||||
EXPECT_EQ(layer_bounds, SkRect::MakeXYWH(40, 40, 20, 20));
|
||||
}
|
||||
|
||||
TEST_F(OpacityLayerTest, ChildIsCached) {
|
||||
TEST_F(OpacityLayerTest, CacheChild) {
|
||||
const SkAlpha alpha_half = 255 / 2;
|
||||
auto initial_transform = SkMatrix::Translate(50.0, 25.5);
|
||||
auto other_transform = SkMatrix::Scale(1.0, 2.0);
|
||||
@ -93,15 +93,31 @@ TEST_F(OpacityLayerTest, ChildIsCached) {
|
||||
EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)0);
|
||||
EXPECT_FALSE(raster_cache()->Draw(mock_layer.get(), other_canvas));
|
||||
EXPECT_FALSE(raster_cache()->Draw(mock_layer.get(), cache_canvas));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), other_canvas,
|
||||
RasterCacheLayerStrategy::kLayer));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), cache_canvas,
|
||||
RasterCacheLayerStrategy::kLayer));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), other_canvas,
|
||||
RasterCacheLayerStrategy::kLayerChildren));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), cache_canvas,
|
||||
RasterCacheLayerStrategy::kLayerChildren));
|
||||
|
||||
layer->Preroll(preroll_context(), initial_transform);
|
||||
|
||||
EXPECT_EQ(raster_cache()->GetLayerCachedEntriesCount(), (size_t)1);
|
||||
EXPECT_FALSE(raster_cache()->Draw(mock_layer.get(), other_canvas));
|
||||
EXPECT_TRUE(raster_cache()->Draw(mock_layer.get(), cache_canvas));
|
||||
EXPECT_FALSE(raster_cache()->Draw(mock_layer.get(), cache_canvas));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), other_canvas,
|
||||
RasterCacheLayerStrategy::kLayer));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), cache_canvas,
|
||||
RasterCacheLayerStrategy::kLayer));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), other_canvas,
|
||||
RasterCacheLayerStrategy::kLayerChildren));
|
||||
EXPECT_TRUE(raster_cache()->Draw(layer.get(), cache_canvas,
|
||||
RasterCacheLayerStrategy::kLayerChildren));
|
||||
}
|
||||
|
||||
TEST_F(OpacityLayerTest, ChildrenNotCached) {
|
||||
TEST_F(OpacityLayerTest, CacheChildren) {
|
||||
const SkAlpha alpha_half = 255 / 2;
|
||||
auto initial_transform = SkMatrix::Translate(50.0, 25.5);
|
||||
auto other_transform = SkMatrix::Scale(1.0, 2.0);
|
||||
@ -127,6 +143,14 @@ TEST_F(OpacityLayerTest, ChildrenNotCached) {
|
||||
EXPECT_FALSE(raster_cache()->Draw(mock_layer1.get(), cache_canvas));
|
||||
EXPECT_FALSE(raster_cache()->Draw(mock_layer2.get(), other_canvas));
|
||||
EXPECT_FALSE(raster_cache()->Draw(mock_layer2.get(), cache_canvas));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), other_canvas,
|
||||
RasterCacheLayerStrategy::kLayer));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), cache_canvas,
|
||||
RasterCacheLayerStrategy::kLayer));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), other_canvas,
|
||||
RasterCacheLayerStrategy::kLayerChildren));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), cache_canvas,
|
||||
RasterCacheLayerStrategy::kLayerChildren));
|
||||
|
||||
layer->Preroll(preroll_context(), initial_transform);
|
||||
|
||||
@ -135,6 +159,14 @@ TEST_F(OpacityLayerTest, ChildrenNotCached) {
|
||||
EXPECT_FALSE(raster_cache()->Draw(mock_layer1.get(), cache_canvas));
|
||||
EXPECT_FALSE(raster_cache()->Draw(mock_layer2.get(), other_canvas));
|
||||
EXPECT_FALSE(raster_cache()->Draw(mock_layer2.get(), cache_canvas));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), other_canvas,
|
||||
RasterCacheLayerStrategy::kLayer));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), cache_canvas,
|
||||
RasterCacheLayerStrategy::kLayer));
|
||||
EXPECT_FALSE(raster_cache()->Draw(layer.get(), other_canvas,
|
||||
RasterCacheLayerStrategy::kLayerChildren));
|
||||
EXPECT_TRUE(raster_cache()->Draw(layer.get(), cache_canvas,
|
||||
RasterCacheLayerStrategy::kLayerChildren));
|
||||
}
|
||||
|
||||
TEST_F(OpacityLayerTest, FullyOpaque) {
|
||||
@ -157,6 +189,7 @@ TEST_F(OpacityLayerTest, FullyOpaque) {
|
||||
layer->Preroll(preroll_context(), initial_transform);
|
||||
EXPECT_EQ(mock_layer->paint_bounds(), child_path.getBounds());
|
||||
EXPECT_EQ(layer->paint_bounds(), expected_layer_bounds);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), child_path.getBounds());
|
||||
EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
EXPECT_EQ(mock_layer->parent_matrix(),
|
||||
@ -208,6 +241,7 @@ TEST_F(OpacityLayerTest, FullyTransparent) {
|
||||
layer->Preroll(preroll_context(), initial_transform);
|
||||
EXPECT_EQ(mock_layer->paint_bounds(), child_path.getBounds());
|
||||
EXPECT_EQ(layer->paint_bounds(), expected_layer_bounds);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), child_path.getBounds());
|
||||
EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
EXPECT_EQ(mock_layer->parent_matrix(),
|
||||
@ -255,6 +289,7 @@ TEST_F(OpacityLayerTest, HalfTransparent) {
|
||||
layer->Preroll(preroll_context(), initial_transform);
|
||||
EXPECT_EQ(mock_layer->paint_bounds(), child_path.getBounds());
|
||||
EXPECT_EQ(layer->paint_bounds(), expected_layer_bounds);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), child_path.getBounds());
|
||||
EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
EXPECT_EQ(mock_layer->parent_matrix(),
|
||||
@ -321,16 +356,18 @@ TEST_F(OpacityLayerTest, Nested) {
|
||||
|
||||
const SkRect expected_layer2_bounds =
|
||||
layer2_transform.mapRect(child2_path.getBounds());
|
||||
SkRect expected_layer1_bounds = expected_layer2_bounds;
|
||||
expected_layer1_bounds.join(child1_path.getBounds());
|
||||
expected_layer1_bounds.join(child3_path.getBounds());
|
||||
expected_layer1_bounds = layer1_transform.mapRect(expected_layer1_bounds);
|
||||
SkRect layer1_child_bounds = expected_layer2_bounds;
|
||||
layer1_child_bounds.join(child1_path.getBounds());
|
||||
layer1_child_bounds.join(child3_path.getBounds());
|
||||
SkRect expected_layer1_bounds = layer1_transform.mapRect(layer1_child_bounds);
|
||||
layer1->Preroll(preroll_context(), initial_transform);
|
||||
EXPECT_EQ(mock_layer1->paint_bounds(), child1_path.getBounds());
|
||||
EXPECT_EQ(mock_layer2->paint_bounds(), child2_path.getBounds());
|
||||
EXPECT_EQ(mock_layer3->paint_bounds(), child3_path.getBounds());
|
||||
EXPECT_EQ(layer1->paint_bounds(), expected_layer1_bounds);
|
||||
EXPECT_EQ(layer1->child_paint_bounds(), layer1_child_bounds);
|
||||
EXPECT_EQ(layer2->paint_bounds(), expected_layer2_bounds);
|
||||
EXPECT_EQ(layer2->child_paint_bounds(), child2_path.getBounds());
|
||||
EXPECT_TRUE(mock_layer1->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(mock_layer2->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(mock_layer3->needs_painting(paint_context()));
|
||||
|
||||
@ -25,6 +25,7 @@ TEST_F(PhysicalShapeLayerTest, PaintingEmptyLayerDies) {
|
||||
|
||||
layer->Preroll(preroll_context(), SkMatrix());
|
||||
EXPECT_EQ(layer->paint_bounds(), SkRect::MakeEmpty());
|
||||
EXPECT_EQ(layer->child_paint_bounds(), SkRect::MakeEmpty());
|
||||
EXPECT_FALSE(layer->needs_painting(paint_context()));
|
||||
|
||||
EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()),
|
||||
@ -55,6 +56,7 @@ TEST_F(PhysicalShapeLayerTest, NonEmptyLayer) {
|
||||
layer_path, Clip::none);
|
||||
layer->Preroll(preroll_context(), SkMatrix());
|
||||
EXPECT_EQ(layer->paint_bounds(), layer_path.getBounds());
|
||||
EXPECT_EQ(layer->child_paint_bounds(), SkRect::MakeEmpty());
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
|
||||
SkPaint layer_paint;
|
||||
@ -93,6 +95,7 @@ TEST_F(PhysicalShapeLayerTest, ChildrenLargerThanPathClip) {
|
||||
child_paint_bounds.join(child2->paint_bounds());
|
||||
EXPECT_EQ(layer->paint_bounds(), layer_path.getBounds());
|
||||
EXPECT_NE(layer->paint_bounds(), child_paint_bounds);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), child_paint_bounds);
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
|
||||
SkPaint layer_paint;
|
||||
@ -142,13 +145,14 @@ TEST_F(PhysicalShapeLayerTest, ChildrenLargerThanPathNoClip) {
|
||||
layer->Add(child1);
|
||||
layer->Add(child2);
|
||||
|
||||
SkRect total_bounds = SkRect::MakeEmpty();
|
||||
layer->Preroll(preroll_context(), SkMatrix());
|
||||
total_bounds.join(child1->paint_bounds());
|
||||
total_bounds.join(child2->paint_bounds());
|
||||
SkRect child_bounds = child1->paint_bounds();
|
||||
child_bounds.join(child2->paint_bounds());
|
||||
SkRect total_bounds = child_bounds;
|
||||
total_bounds.join(layer_path.getBounds());
|
||||
EXPECT_NE(layer->paint_bounds(), layer_path.getBounds());
|
||||
EXPECT_EQ(layer->paint_bounds(), total_bounds);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), child_bounds);
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
|
||||
SkPaint layer_paint;
|
||||
|
||||
@ -23,6 +23,7 @@ TEST_F(ShaderMaskLayerTest, PaintingEmptyLayerDies) {
|
||||
|
||||
layer->Preroll(preroll_context(), SkMatrix());
|
||||
EXPECT_EQ(layer->paint_bounds(), kEmptyRect);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), kEmptyRect);
|
||||
EXPECT_FALSE(layer->needs_painting(paint_context()));
|
||||
|
||||
EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()),
|
||||
@ -38,6 +39,7 @@ TEST_F(ShaderMaskLayerTest, PaintBeforePrerollDies) {
|
||||
layer->Add(mock_layer);
|
||||
|
||||
EXPECT_EQ(layer->paint_bounds(), kEmptyRect);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), kEmptyRect);
|
||||
EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()),
|
||||
"needs_painting\\(context\\)");
|
||||
}
|
||||
@ -57,6 +59,7 @@ TEST_F(ShaderMaskLayerTest, EmptyFilter) {
|
||||
layer->Preroll(preroll_context(), initial_transform);
|
||||
EXPECT_EQ(mock_layer->paint_bounds(), child_bounds);
|
||||
EXPECT_EQ(layer->paint_bounds(), child_bounds);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), child_bounds);
|
||||
EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
EXPECT_EQ(mock_layer->parent_matrix(), initial_transform);
|
||||
@ -98,6 +101,7 @@ TEST_F(ShaderMaskLayerTest, SimpleFilter) {
|
||||
|
||||
layer->Preroll(preroll_context(), initial_transform);
|
||||
EXPECT_EQ(layer->paint_bounds(), child_bounds);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), child_bounds);
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
EXPECT_EQ(mock_layer->parent_matrix(), initial_transform);
|
||||
|
||||
@ -147,6 +151,7 @@ TEST_F(ShaderMaskLayerTest, MultipleChildren) {
|
||||
EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds());
|
||||
EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds());
|
||||
EXPECT_EQ(layer->paint_bounds(), children_bounds);
|
||||
EXPECT_EQ(layer->child_paint_bounds(), children_bounds);
|
||||
EXPECT_TRUE(mock_layer1->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(mock_layer2->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
@ -206,7 +211,9 @@ TEST_F(ShaderMaskLayerTest, Nested) {
|
||||
EXPECT_EQ(mock_layer1->paint_bounds(), child_path1.getBounds());
|
||||
EXPECT_EQ(mock_layer2->paint_bounds(), child_path2.getBounds());
|
||||
EXPECT_EQ(layer1->paint_bounds(), children_bounds);
|
||||
EXPECT_EQ(layer1->child_paint_bounds(), children_bounds);
|
||||
EXPECT_EQ(layer2->paint_bounds(), mock_layer2->paint_bounds());
|
||||
EXPECT_EQ(layer2->child_paint_bounds(), mock_layer2->paint_bounds());
|
||||
EXPECT_TRUE(mock_layer1->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(mock_layer2->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(layer1->needs_painting(paint_context()));
|
||||
|
||||
@ -21,6 +21,7 @@ TEST_F(TransformLayerTest, PaintingEmptyLayerDies) {
|
||||
|
||||
layer->Preroll(preroll_context(), SkMatrix());
|
||||
EXPECT_EQ(layer->paint_bounds(), SkRect::MakeEmpty());
|
||||
EXPECT_EQ(layer->child_paint_bounds(), SkRect::MakeEmpty());
|
||||
EXPECT_FALSE(layer->needs_painting(paint_context()));
|
||||
|
||||
EXPECT_DEATH_IF_SUPPORTED(layer->Paint(paint_context()),
|
||||
@ -51,6 +52,7 @@ TEST_F(TransformLayerTest, Identity) {
|
||||
layer->Preroll(preroll_context(), SkMatrix());
|
||||
EXPECT_EQ(mock_layer->paint_bounds(), child_path.getBounds());
|
||||
EXPECT_EQ(layer->paint_bounds(), mock_layer->paint_bounds());
|
||||
EXPECT_EQ(layer->child_paint_bounds(), mock_layer->paint_bounds());
|
||||
EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
EXPECT_EQ(mock_layer->parent_matrix(), SkMatrix()); // identity
|
||||
@ -81,6 +83,7 @@ TEST_F(TransformLayerTest, Simple) {
|
||||
EXPECT_EQ(mock_layer->paint_bounds(), child_path.getBounds());
|
||||
EXPECT_EQ(layer->paint_bounds(),
|
||||
layer_transform.mapRect(mock_layer->paint_bounds()));
|
||||
EXPECT_EQ(layer->child_paint_bounds(), mock_layer->paint_bounds());
|
||||
EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(layer->needs_painting(paint_context()));
|
||||
EXPECT_EQ(mock_layer->parent_matrix(),
|
||||
@ -123,8 +126,10 @@ TEST_F(TransformLayerTest, Nested) {
|
||||
EXPECT_EQ(mock_layer->paint_bounds(), child_path.getBounds());
|
||||
EXPECT_EQ(layer2->paint_bounds(),
|
||||
layer2_transform.mapRect(mock_layer->paint_bounds()));
|
||||
EXPECT_EQ(layer2->child_paint_bounds(), mock_layer->paint_bounds());
|
||||
EXPECT_EQ(layer1->paint_bounds(),
|
||||
layer1_transform.mapRect(layer2->paint_bounds()));
|
||||
EXPECT_EQ(layer1->child_paint_bounds(), layer2->paint_bounds());
|
||||
EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(layer2->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(layer1->needs_painting(paint_context()));
|
||||
@ -177,14 +182,18 @@ TEST_F(TransformLayerTest, NestedSeparated) {
|
||||
|
||||
preroll_context()->cull_rect = cull_rect;
|
||||
layer1->Preroll(preroll_context(), initial_transform);
|
||||
SkRect expected_layer1_bounds = layer2->paint_bounds();
|
||||
expected_layer1_bounds.join(mock_layer1->paint_bounds());
|
||||
SkRect layer1_child_bounds = layer2->paint_bounds();
|
||||
layer1_child_bounds.join(mock_layer1->paint_bounds());
|
||||
SkRect expected_layer1_bounds = layer1_child_bounds;
|
||||
layer1_transform.mapRect(&expected_layer1_bounds);
|
||||
|
||||
EXPECT_EQ(mock_layer2->paint_bounds(), child_path.getBounds());
|
||||
EXPECT_EQ(layer2->paint_bounds(),
|
||||
layer2_transform.mapRect(mock_layer2->paint_bounds()));
|
||||
EXPECT_EQ(layer2->child_paint_bounds(), mock_layer2->paint_bounds());
|
||||
EXPECT_EQ(mock_layer1->paint_bounds(), child_path.getBounds());
|
||||
EXPECT_EQ(layer1->paint_bounds(), expected_layer1_bounds);
|
||||
EXPECT_EQ(layer1->child_paint_bounds(), layer1_child_bounds);
|
||||
EXPECT_TRUE(mock_layer2->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(layer2->needs_painting(paint_context()));
|
||||
EXPECT_TRUE(mock_layer1->needs_painting(paint_context()));
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "flutter/common/constants.h"
|
||||
#include "flutter/flow/layers/container_layer.h"
|
||||
#include "flutter/flow/layers/layer.h"
|
||||
#include "flutter/flow/paint_utils.h"
|
||||
#include "flutter/fml/logging.h"
|
||||
@ -176,25 +177,59 @@ std::unique_ptr<RasterCacheResult> RasterCache::RasterizeDisplayList(
|
||||
|
||||
void RasterCache::Prepare(PrerollContext* context,
|
||||
Layer* layer,
|
||||
const SkMatrix& ctm) {
|
||||
RasterCacheKey cache_key(layer->unique_id(), RasterCacheKeyType::kLayer, ctm);
|
||||
Entry& entry = cache_[cache_key];
|
||||
const SkMatrix& ctm,
|
||||
RasterCacheLayerStrategy strategy) {
|
||||
auto cache_key_optional =
|
||||
TryToMakeRasterCacheKeyForLayer(layer, strategy, ctm);
|
||||
if (!cache_key_optional) {
|
||||
return;
|
||||
}
|
||||
Entry& entry = cache_[cache_key_optional.value()];
|
||||
entry.access_count++;
|
||||
entry.used_this_frame = true;
|
||||
if (!entry.image) {
|
||||
entry.image = RasterizeLayer(context, layer, ctm, checkerboard_images_);
|
||||
entry.image =
|
||||
RasterizeLayer(context, layer, strategy, ctm, checkerboard_images_);
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<RasterCacheKey> RasterCache::TryToMakeRasterCacheKeyForLayer(
|
||||
const Layer* layer,
|
||||
RasterCacheLayerStrategy strategy,
|
||||
const SkMatrix& ctm) const {
|
||||
switch (strategy) {
|
||||
case RasterCacheLayerStrategy::kLayer:
|
||||
return RasterCacheKey(layer->unique_id(), RasterCacheKeyType::kLayer,
|
||||
ctm);
|
||||
case RasterCacheLayerStrategy::kLayerChildren:
|
||||
FML_DCHECK(layer->as_container_layer());
|
||||
auto& children_layers = layer->as_container_layer()->layers();
|
||||
auto children_count = children_layers.size();
|
||||
if (children_count == 0) {
|
||||
return std::nullopt;
|
||||
}
|
||||
std::vector<uint64_t> ids;
|
||||
std::transform(children_layers.begin(), children_layers.end(),
|
||||
std::back_inserter(ids), [](auto& layer) -> uint64_t {
|
||||
return layer->unique_id();
|
||||
});
|
||||
return RasterCacheKey(RasterCacheKeyID(std::move(ids)),
|
||||
RasterCacheKeyType::kLayerChildren, ctm);
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<RasterCacheResult> RasterCache::RasterizeLayer(
|
||||
PrerollContext* context,
|
||||
Layer* layer,
|
||||
RasterCacheLayerStrategy strategy,
|
||||
const SkMatrix& ctm,
|
||||
bool checkerboard) const {
|
||||
const SkRect& paint_bounds = GetPaintBoundsFromLayer(layer, strategy);
|
||||
|
||||
return Rasterize(
|
||||
context->gr_context, ctm, context->dst_color_space, checkerboard,
|
||||
layer->paint_bounds(), "RasterCacheFlow::Layer",
|
||||
[layer, context](SkCanvas* canvas) {
|
||||
paint_bounds, "RasterCacheFlow::Layer",
|
||||
[layer, context, strategy](SkCanvas* canvas) {
|
||||
SkISize canvas_size = canvas->getBaseLayerSize();
|
||||
SkNWayCanvas internal_nodes_canvas(canvas_size.width(),
|
||||
canvas_size.height());
|
||||
@ -212,12 +247,32 @@ std::unique_ptr<RasterCacheResult> RasterCache::RasterizeLayer(
|
||||
context->has_platform_view ? nullptr : context->raster_cache,
|
||||
context->checkerboard_offscreen_layers,
|
||||
context->frame_device_pixel_ratio};
|
||||
if (layer->needs_painting(paintContext)) {
|
||||
layer->Paint(paintContext);
|
||||
switch (strategy) {
|
||||
case RasterCacheLayerStrategy::kLayer:
|
||||
if (layer->needs_painting(paintContext)) {
|
||||
layer->Paint(paintContext);
|
||||
}
|
||||
break;
|
||||
case RasterCacheLayerStrategy::kLayerChildren:
|
||||
FML_DCHECK(layer->as_container_layer());
|
||||
layer->as_container_layer()->PaintChildren(paintContext);
|
||||
break;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
const SkRect& RasterCache::GetPaintBoundsFromLayer(
|
||||
Layer* layer,
|
||||
RasterCacheLayerStrategy strategy) const {
|
||||
switch (strategy) {
|
||||
case RasterCacheLayerStrategy::kLayer:
|
||||
return layer->paint_bounds();
|
||||
case RasterCacheLayerStrategy::kLayerChildren:
|
||||
FML_DCHECK(layer->as_container_layer());
|
||||
return layer->as_container_layer()->child_paint_bounds();
|
||||
}
|
||||
}
|
||||
|
||||
bool RasterCache::Prepare(PrerollContext* context,
|
||||
SkPicture* picture,
|
||||
bool is_complex,
|
||||
@ -321,9 +376,15 @@ bool RasterCache::Prepare(PrerollContext* context,
|
||||
return true;
|
||||
}
|
||||
|
||||
void RasterCache::Touch(Layer* layer, const SkMatrix& ctm) {
|
||||
RasterCacheKey cache_key(layer->unique_id(), RasterCacheKeyType::kLayer, ctm);
|
||||
Touch(cache_key);
|
||||
void RasterCache::Touch(Layer* layer,
|
||||
const SkMatrix& ctm,
|
||||
RasterCacheLayerStrategy strategey) {
|
||||
auto cache_key_optional =
|
||||
TryToMakeRasterCacheKeyForLayer(layer, strategey, ctm);
|
||||
if (!cache_key_optional) {
|
||||
return;
|
||||
}
|
||||
Touch(cache_key_optional.value());
|
||||
}
|
||||
|
||||
void RasterCache::Touch(SkPicture* picture,
|
||||
@ -368,10 +429,14 @@ bool RasterCache::Draw(const DisplayList& display_list,
|
||||
|
||||
bool RasterCache::Draw(const Layer* layer,
|
||||
SkCanvas& canvas,
|
||||
RasterCacheLayerStrategy strategy,
|
||||
const SkPaint* paint) const {
|
||||
RasterCacheKey cache_key(layer->unique_id(), RasterCacheKeyType::kLayer,
|
||||
canvas.getTotalMatrix());
|
||||
return Draw(cache_key, canvas, paint);
|
||||
auto cache_key_optional =
|
||||
TryToMakeRasterCacheKeyForLayer(layer, strategy, canvas.getTotalMatrix());
|
||||
if (!cache_key_optional) {
|
||||
return false;
|
||||
}
|
||||
return Draw(cache_key_optional.value(), canvas, paint);
|
||||
}
|
||||
|
||||
bool RasterCache::Draw(const RasterCacheKey& cache_key,
|
||||
|
||||
@ -21,6 +21,8 @@ class SkColorSpace;
|
||||
|
||||
namespace flutter {
|
||||
|
||||
enum class RasterCacheLayerStrategy { kLayer, kLayerChildren };
|
||||
|
||||
class RasterCacheResult {
|
||||
public:
|
||||
RasterCacheResult(sk_sp<SkImage> image,
|
||||
@ -143,6 +145,7 @@ class RasterCache {
|
||||
virtual std::unique_ptr<RasterCacheResult> RasterizeLayer(
|
||||
PrerollContext* context,
|
||||
Layer* layer,
|
||||
RasterCacheLayerStrategy strategy,
|
||||
const SkMatrix& ctm,
|
||||
bool checkerboard) const;
|
||||
|
||||
@ -202,9 +205,16 @@ class RasterCache {
|
||||
// away.
|
||||
void Touch(SkPicture* picture, const SkMatrix& transformation_matrix);
|
||||
void Touch(DisplayList* display_list, const SkMatrix& transformation_matrix);
|
||||
void Touch(Layer* layer, const SkMatrix& ctm);
|
||||
void Touch(
|
||||
Layer* layer,
|
||||
const SkMatrix& ctm,
|
||||
RasterCacheLayerStrategy strategey = RasterCacheLayerStrategy::kLayer);
|
||||
|
||||
void Prepare(PrerollContext* context, Layer* layer, const SkMatrix& ctm);
|
||||
void Prepare(
|
||||
PrerollContext* context,
|
||||
Layer* layer,
|
||||
const SkMatrix& ctm,
|
||||
RasterCacheLayerStrategy strategey = RasterCacheLayerStrategy::kLayer);
|
||||
|
||||
// Find the raster cache for the picture and draw it to the canvas.
|
||||
//
|
||||
@ -226,9 +236,11 @@ class RasterCache {
|
||||
// (e.g., draw the raster cache with some opacity).
|
||||
//
|
||||
// Return true if the layer raster cache is found and drawn.
|
||||
bool Draw(const Layer* layer,
|
||||
SkCanvas& canvas,
|
||||
const SkPaint* paint = nullptr) const;
|
||||
bool Draw(
|
||||
const Layer* layer,
|
||||
SkCanvas& canvas,
|
||||
RasterCacheLayerStrategy strategey = RasterCacheLayerStrategy::kLayer,
|
||||
const SkPaint* paint = nullptr) const;
|
||||
|
||||
void PrepareNewFrame();
|
||||
void CleanupAfterFrame();
|
||||
@ -310,6 +322,15 @@ class RasterCache {
|
||||
picture_and_display_list_cache_limit_per_frame_;
|
||||
}
|
||||
|
||||
std::optional<RasterCacheKey> TryToMakeRasterCacheKeyForLayer(
|
||||
const Layer* layer,
|
||||
RasterCacheLayerStrategy strategy,
|
||||
const SkMatrix& ctm) const;
|
||||
|
||||
const SkRect& GetPaintBoundsFromLayer(
|
||||
Layer* layer,
|
||||
RasterCacheLayerStrategy strategy) const;
|
||||
|
||||
const size_t access_threshold_;
|
||||
const size_t picture_and_display_list_cache_limit_per_frame_;
|
||||
size_t picture_cached_this_frame_ = 0;
|
||||
|
||||
@ -6,6 +6,8 @@
|
||||
#define FLUTTER_FLOW_RASTER_CACHE_KEY_H_
|
||||
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "flutter/fml/hash_combine.h"
|
||||
#include "flutter/fml/logging.h"
|
||||
@ -13,19 +15,55 @@
|
||||
|
||||
namespace flutter {
|
||||
|
||||
enum class RasterCacheKeyType { kLayer, kPicture, kDisplayList };
|
||||
class RasterCacheKeyID {
|
||||
public:
|
||||
RasterCacheKeyID(const std::vector<uint64_t> ids) : ids_(ids) {}
|
||||
|
||||
const std::vector<uint64_t>& ids() { return ids_; }
|
||||
|
||||
std::size_t GetHash() const {
|
||||
std::size_t seed = fml::HashCombine();
|
||||
for (auto id : ids_) {
|
||||
fml::HashCombineSeed(seed, id);
|
||||
}
|
||||
return seed;
|
||||
}
|
||||
|
||||
bool operator==(const RasterCacheKeyID& other) const {
|
||||
return ids_ == other.ids_;
|
||||
}
|
||||
|
||||
bool operator!=(const RasterCacheKeyID& other) const {
|
||||
return !operator==(other);
|
||||
}
|
||||
|
||||
private:
|
||||
const std::vector<uint64_t> ids_;
|
||||
};
|
||||
|
||||
enum class RasterCacheKeyType {
|
||||
kLayer,
|
||||
kPicture,
|
||||
kDisplayList,
|
||||
kLayerChildren
|
||||
};
|
||||
|
||||
enum class RasterCacheKeyKind { kLayerMetrics, kPictureMetrics };
|
||||
|
||||
class RasterCacheKey {
|
||||
public:
|
||||
RasterCacheKey(uint64_t id, RasterCacheKeyType type, const SkMatrix& ctm)
|
||||
: id_(id), type_(type), matrix_(ctm) {
|
||||
: RasterCacheKey(RasterCacheKeyID({id}), type, ctm) {}
|
||||
|
||||
RasterCacheKey(RasterCacheKeyID id,
|
||||
RasterCacheKeyType type,
|
||||
const SkMatrix& ctm)
|
||||
: id_(std::move(id)), type_(type), matrix_(ctm) {
|
||||
matrix_[SkMatrix::kMTransX] = 0;
|
||||
matrix_[SkMatrix::kMTransY] = 0;
|
||||
}
|
||||
|
||||
uint64_t id() const { return id_; }
|
||||
const RasterCacheKeyID& id() const { return id_; }
|
||||
RasterCacheKeyType type() const { return type_; }
|
||||
const SkMatrix& matrix() const { return matrix_; }
|
||||
|
||||
@ -35,13 +73,14 @@ class RasterCacheKey {
|
||||
case RasterCacheKeyType::kDisplayList:
|
||||
return RasterCacheKeyKind::kPictureMetrics;
|
||||
case RasterCacheKeyType::kLayer:
|
||||
case RasterCacheKeyType::kLayerChildren:
|
||||
return RasterCacheKeyKind::kLayerMetrics;
|
||||
}
|
||||
}
|
||||
|
||||
struct Hash {
|
||||
std::size_t operator()(RasterCacheKey const& key) const {
|
||||
return fml::HashCombine(key.id_, key.type_);
|
||||
return fml::HashCombine(key.id_.GetHash(), key.type_);
|
||||
}
|
||||
};
|
||||
|
||||
@ -57,7 +96,7 @@ class RasterCacheKey {
|
||||
using Map = std::unordered_map<RasterCacheKey, Value, Hash, Equal>;
|
||||
|
||||
private:
|
||||
uint64_t id_;
|
||||
RasterCacheKeyID id_;
|
||||
|
||||
RasterCacheKeyType type_;
|
||||
|
||||
|
||||
@ -555,17 +555,27 @@ TEST(RasterCache, RasterCacheKeyHashFunction) {
|
||||
RasterCacheKey layer_key(id, RasterCacheKeyType::kLayer, matrix);
|
||||
RasterCacheKey picture_key(id, RasterCacheKeyType::kPicture, matrix);
|
||||
RasterCacheKey display_list_key(id, RasterCacheKeyType::kDisplayList, matrix);
|
||||
RasterCacheKey layer_children_key(id, RasterCacheKeyType::kLayerChildren,
|
||||
matrix);
|
||||
|
||||
auto raster_cache_key_id = RasterCacheKeyID({id});
|
||||
auto layer_hash_code = hash_function(layer_key);
|
||||
ASSERT_EQ(layer_hash_code, fml::HashCombine(id, RasterCacheKeyType::kLayer));
|
||||
ASSERT_EQ(layer_hash_code, fml::HashCombine(raster_cache_key_id.GetHash(),
|
||||
RasterCacheKeyType::kLayer));
|
||||
|
||||
auto picture_hash_code = hash_function(picture_key);
|
||||
ASSERT_EQ(picture_hash_code,
|
||||
fml::HashCombine(id, RasterCacheKeyType::kPicture));
|
||||
ASSERT_EQ(picture_hash_code, fml::HashCombine(raster_cache_key_id.GetHash(),
|
||||
RasterCacheKeyType::kPicture));
|
||||
|
||||
auto display_list_hash_code = hash_function(display_list_key);
|
||||
ASSERT_EQ(display_list_hash_code,
|
||||
fml::HashCombine(id, RasterCacheKeyType::kDisplayList));
|
||||
fml::HashCombine(raster_cache_key_id.GetHash(),
|
||||
RasterCacheKeyType::kDisplayList));
|
||||
|
||||
auto layer_children_hash_code = hash_function(layer_children_key);
|
||||
ASSERT_EQ(layer_children_hash_code,
|
||||
fml::HashCombine(raster_cache_key_id.GetHash(),
|
||||
RasterCacheKeyType::kLayerChildren));
|
||||
}
|
||||
|
||||
TEST(RasterCache, RasterCacheKeySameID) {
|
||||
@ -575,13 +585,17 @@ TEST(RasterCache, RasterCacheKeySameID) {
|
||||
RasterCacheKey layer_key(id, RasterCacheKeyType::kLayer, matrix);
|
||||
RasterCacheKey picture_key(id, RasterCacheKeyType::kPicture, matrix);
|
||||
RasterCacheKey display_list_key(id, RasterCacheKeyType::kDisplayList, matrix);
|
||||
RasterCacheKey layer_children_key(id, RasterCacheKeyType::kLayerChildren,
|
||||
matrix);
|
||||
map[layer_key] = 100;
|
||||
map[picture_key] = 200;
|
||||
map[display_list_key] = 300;
|
||||
map[layer_children_key] = 400;
|
||||
|
||||
ASSERT_EQ(map[layer_key], 100);
|
||||
ASSERT_EQ(map[picture_key], 200);
|
||||
ASSERT_EQ(map[display_list_key], 300);
|
||||
ASSERT_EQ(map[layer_children_key], 400);
|
||||
}
|
||||
|
||||
TEST(RasterCache, RasterCacheKeySameType) {
|
||||
@ -620,6 +634,46 @@ TEST(RasterCache, RasterCacheKeySameType) {
|
||||
ASSERT_EQ(map[display_list_first_key], 350);
|
||||
ASSERT_EQ(map[display_list_second_key], 400);
|
||||
ASSERT_EQ(map[display_list_third_key], 450);
|
||||
|
||||
type = RasterCacheKeyType::kLayerChildren;
|
||||
RasterCacheKey layer_children_first_key(RasterCacheKeyID({1, 2, 3}), type,
|
||||
matrix);
|
||||
RasterCacheKey layer_children_second_key(RasterCacheKeyID({2, 3, 1}), type,
|
||||
matrix);
|
||||
RasterCacheKey layer_children_third_key(RasterCacheKeyID({3, 2, 1}), type,
|
||||
matrix);
|
||||
map[layer_children_first_key] = 100;
|
||||
map[layer_children_second_key] = 200;
|
||||
map[layer_children_third_key] = 300;
|
||||
ASSERT_EQ(map[layer_children_first_key], 100);
|
||||
ASSERT_EQ(map[layer_children_second_key], 200);
|
||||
ASSERT_EQ(map[layer_children_third_key], 300);
|
||||
}
|
||||
|
||||
TEST(RasterCache, RasterCacheKeyID_Equal) {
|
||||
RasterCacheKeyID first = RasterCacheKeyID({1});
|
||||
RasterCacheKeyID second = RasterCacheKeyID({1});
|
||||
RasterCacheKeyID third = RasterCacheKeyID({2});
|
||||
ASSERT_EQ(first, second);
|
||||
ASSERT_NE(first, third);
|
||||
|
||||
RasterCacheKeyID fourth = RasterCacheKeyID({1, 2});
|
||||
RasterCacheKeyID fifth = RasterCacheKeyID({1, 2});
|
||||
RasterCacheKeyID sixth = RasterCacheKeyID({2, 1});
|
||||
ASSERT_EQ(fourth, fifth);
|
||||
ASSERT_NE(fourth, sixth);
|
||||
}
|
||||
|
||||
TEST(RasterCache, RasterCacheKeyID_HashCode) {
|
||||
uint64_t foo = 1;
|
||||
uint64_t bar = 2;
|
||||
RasterCacheKeyID first = RasterCacheKeyID({foo});
|
||||
RasterCacheKeyID second = RasterCacheKeyID({foo, bar});
|
||||
RasterCacheKeyID third = RasterCacheKeyID({bar, foo});
|
||||
|
||||
ASSERT_EQ(first.GetHash(), fml::HashCombine(foo));
|
||||
ASSERT_EQ(second.GetHash(), fml::HashCombine(foo, bar));
|
||||
ASSERT_EQ(third.GetHash(), fml::HashCombine(bar, foo));
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
|
||||
@ -28,6 +28,7 @@ std::unique_ptr<RasterCacheResult> MockRasterCache::RasterizePicture(
|
||||
std::unique_ptr<RasterCacheResult> MockRasterCache::RasterizeLayer(
|
||||
PrerollContext* context,
|
||||
Layer* layer,
|
||||
RasterCacheLayerStrategy strategy,
|
||||
const SkMatrix& ctm,
|
||||
bool checkerboard) const {
|
||||
SkRect logical_rect = layer->paint_bounds();
|
||||
|
||||
@ -66,6 +66,7 @@ class MockRasterCache : public RasterCache {
|
||||
std::unique_ptr<RasterCacheResult> RasterizeLayer(
|
||||
PrerollContext* context,
|
||||
Layer* layer,
|
||||
RasterCacheLayerStrategy stategy,
|
||||
const SkMatrix& ctm,
|
||||
bool checkerboard) const override;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user