switch from MockCanvas to DisplayListBuilder in layer unit tests (flutter/engine#41889)

Part of an ongoing set of efforts to address https://github.com/flutter/flutter/issues/106448

The layer unittests have been using a MockCanvas class to record the painting of trees of layers and then testing for the expected output.

A while back a similar mechanism was created to compare DisplayList output and to print out a human-friendly version of the differences found, but it was only used in a few tests written at the time it was created and a few since then.

This is the first in a series of PRs that will move all the rest of the unit tests onto the new DL comparison mechanism, starting with the layer types that just do basic drawing. Some of the remaining layers will require creating new hooks in, for instance, the Texture registry, the performance overlay TextBlob generation, etc.
This commit is contained in:
Jim Graham
2023-05-10 12:00:18 -07:00
committed by GitHub
parent b676910c42
commit 7fea2b0933
17 changed files with 779 additions and 560 deletions

View File

@@ -92,6 +92,22 @@ class DisplayListTestBase : public BaseT {
};
using DisplayListTest = DisplayListTestBase<::testing::Test>;
TEST_F(DisplayListTest, EmptyBuild) {
DisplayListBuilder builder;
auto dl = builder.Build();
EXPECT_EQ(dl->op_count(), 0u);
EXPECT_EQ(dl->bytes(), sizeof(DisplayList));
}
TEST_F(DisplayListTest, EmptyRebuild) {
DisplayListBuilder builder;
auto dl1 = builder.Build();
auto dl2 = builder.Build();
auto dl3 = builder.Build();
ASSERT_TRUE(dl1->Equals(dl2));
ASSERT_TRUE(dl2->Equals(dl3));
}
TEST_F(DisplayListTest, BuilderCanBeReused) {
DisplayListBuilder builder(kTestBounds);
builder.DrawRect(kTestBounds, DlPaint());

View File

@@ -578,15 +578,18 @@ void DisplayListBuilder::Transform2DAffine(
SkScalar myx, SkScalar myy, SkScalar myt) {
if (SkScalarsAreFinite(mxx, myx) &&
SkScalarsAreFinite(mxy, myy) &&
SkScalarsAreFinite(mxt, myt) &&
!(mxx == 1 && mxy == 0 && mxt == 0 &&
myx == 0 && myy == 1 && myt == 0)) {
checkForDeferredSave();
Push<Transform2DAffineOp>(0, 1,
mxx, mxy, mxt,
myx, myy, myt);
tracker_.transform2DAffine(mxx, mxy, mxt,
myx, myy, myt);
SkScalarsAreFinite(mxt, myt)) {
if (mxx == 1 && mxy == 0 &&
myx == 0 && myy == 1) {
Translate(mxt, myt);
} else {
checkForDeferredSave();
Push<Transform2DAffineOp>(0, 1,
mxx, mxy, mxt,
myx, myy, myt);
tracker_.transform2DAffine(mxx, mxy, mxt,
myx, myy, myt);
}
}
}
// full 4x4 transform in row major order

View File

@@ -113,11 +113,17 @@ class DisplayListBuilder final : public virtual DlCanvas,
SkMatrix GetTransform() const override { return tracker_.matrix_3x3(); }
// |DlCanvas|
void ClipRect(const SkRect& rect, ClipOp clip_op, bool is_aa) override;
void ClipRect(const SkRect& rect,
ClipOp clip_op = ClipOp::kIntersect,
bool is_aa = false) override;
// |DlCanvas|
void ClipRRect(const SkRRect& rrect, ClipOp clip_op, bool is_aa) override;
void ClipRRect(const SkRRect& rrect,
ClipOp clip_op = ClipOp::kIntersect,
bool is_aa = false) override;
// |DlCanvas|
void ClipPath(const SkPath& path, ClipOp clip_op, bool is_aa) override;
void ClipPath(const SkPath& path,
ClipOp clip_op = ClipOp::kIntersect,
bool is_aa = false) override;
/// Conservative estimate of the bounds of all outstanding clip operations
/// measured in the coordinate space within which this DisplayList will

View File

@@ -11,9 +11,6 @@
#include "flutter/flow/testing/layer_test.h"
#include "flutter/flow/testing/mock_layer.h"
#include "flutter/fml/macros.h"
#include "flutter/testing/mock_canvas.h"
#include "third_party/skia/include/core/SkImageFilter.h"
#include "third_party/skia/include/effects/SkImageFilters.h"
namespace flutter {
namespace testing {
@@ -72,15 +69,30 @@ TEST_F(BackdropFilterLayerTest, EmptyFilter) {
EXPECT_TRUE(layer->needs_painting(paint_context()));
EXPECT_EQ(mock_layer->parent_matrix(), initial_transform);
layer->Paint(paint_context());
EXPECT_EQ(
mock_canvas().draw_calls(),
std::vector({MockCanvas::DrawCall{
0, MockCanvas::SaveLayerData{child_bounds, DlPaint(),
nullptr, 1}},
MockCanvas::DrawCall{
1, MockCanvas::DrawPathData{child_path, child_paint}},
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}}));
parent->Paint(display_list_paint_context());
DisplayListBuilder expected_builder;
/* (ClipRect)parent::Paint */ {
expected_builder.Save();
{
expected_builder.ClipRect(child_bounds, DlCanvas::ClipOp::kIntersect,
false);
/* (BackdropFilter)layer::Paint */ {
expected_builder.Save();
{
expected_builder.SaveLayer(&child_bounds, nullptr, nullptr);
{
/* mock_layer::Paint */ {
expected_builder.DrawPath(child_path, child_paint);
}
}
expected_builder.Restore();
}
expected_builder.Restore();
}
}
expected_builder.Restore();
}
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
}
TEST_F(BackdropFilterLayerTest, SimpleFilter) {
@@ -104,15 +116,31 @@ TEST_F(BackdropFilterLayerTest, SimpleFilter) {
EXPECT_TRUE(layer->needs_painting(paint_context()));
EXPECT_EQ(mock_layer->parent_matrix(), initial_transform);
layer->Paint(paint_context());
EXPECT_EQ(
mock_canvas().draw_calls(),
std::vector({MockCanvas::DrawCall{
0, MockCanvas::SaveLayerData{child_bounds, DlPaint(),
layer_filter, 1}},
MockCanvas::DrawCall{
1, MockCanvas::DrawPathData{child_path, child_paint}},
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}}));
parent->Paint(display_list_paint_context());
DisplayListBuilder expected_builder;
/* (ClipRect)parent::Paint */ {
expected_builder.Save();
{
expected_builder.ClipRect(child_bounds, DlCanvas::ClipOp::kIntersect,
false);
/* (BackdropFilter)layer::Paint */ {
expected_builder.Save();
{
expected_builder.SaveLayer(&child_bounds, nullptr,
layer_filter.get());
{
/* mock_layer::Paint */ {
expected_builder.DrawPath(child_path, child_paint);
}
}
expected_builder.Restore();
}
expected_builder.Restore();
}
}
expected_builder.Restore();
}
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
}
TEST_F(BackdropFilterLayerTest, NonSrcOverBlend) {
@@ -139,15 +167,32 @@ TEST_F(BackdropFilterLayerTest, NonSrcOverBlend) {
DlPaint filter_paint = DlPaint();
filter_paint.setBlendMode(DlBlendMode::kSrc);
layer->Paint(paint_context());
EXPECT_EQ(
mock_canvas().draw_calls(),
std::vector({MockCanvas::DrawCall{
0, MockCanvas::SaveLayerData{child_bounds, filter_paint,
layer_filter, 1}},
MockCanvas::DrawCall{
1, MockCanvas::DrawPathData{child_path, child_paint}},
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}}));
parent->Paint(display_list_paint_context());
DisplayListBuilder expected_builder;
/* (ClipRect)parent::Paint */ {
expected_builder.Save();
{
expected_builder.ClipRect(child_bounds, DlCanvas::ClipOp::kIntersect,
false);
/* (BackdropFilter)layer::Paint */ {
expected_builder.Save();
{
DlPaint save_paint = DlPaint().setBlendMode(DlBlendMode::kSrc);
expected_builder.SaveLayer(&child_bounds, &save_paint,
layer_filter.get());
{
/* mock_layer::Paint */ {
expected_builder.DrawPath(child_path, child_paint);
}
}
expected_builder.Restore();
}
expected_builder.Restore();
}
}
expected_builder.Restore();
}
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
}
TEST_F(BackdropFilterLayerTest, MultipleChildren) {
@@ -184,17 +229,34 @@ TEST_F(BackdropFilterLayerTest, MultipleChildren) {
EXPECT_EQ(mock_layer1->parent_matrix(), initial_transform);
EXPECT_EQ(mock_layer2->parent_matrix(), initial_transform);
layer->Paint(paint_context());
EXPECT_EQ(
mock_canvas().draw_calls(),
std::vector({MockCanvas::DrawCall{
0, MockCanvas::SaveLayerData{children_bounds, DlPaint(),
layer_filter, 1}},
MockCanvas::DrawCall{
1, MockCanvas::DrawPathData{child_path1, child_paint1}},
MockCanvas::DrawCall{
1, MockCanvas::DrawPathData{child_path2, child_paint2}},
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}}));
parent->Paint(display_list_paint_context());
DisplayListBuilder expected_builder;
/* (ClipRect)parent::Paint */ {
expected_builder.Save();
{
expected_builder.ClipRect(children_bounds, DlCanvas::ClipOp::kIntersect,
false);
/* (BackdropFilter)layer::Paint */ {
expected_builder.Save();
{
expected_builder.SaveLayer(&children_bounds, nullptr,
layer_filter.get());
{
/* mock_layer1::Paint */ {
expected_builder.DrawPath(child_path1, child_paint1);
}
/* mock_layer2::Paint */ {
expected_builder.DrawPath(child_path2, child_paint2);
}
}
expected_builder.Restore();
}
expected_builder.Restore();
}
}
expected_builder.Restore();
}
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
}
TEST_F(BackdropFilterLayerTest, Nested) {
@@ -238,21 +300,45 @@ TEST_F(BackdropFilterLayerTest, Nested) {
EXPECT_EQ(mock_layer1->parent_matrix(), initial_transform);
EXPECT_EQ(mock_layer2->parent_matrix(), initial_transform);
layer1->Paint(paint_context());
EXPECT_EQ(
mock_canvas().draw_calls(),
std::vector({MockCanvas::DrawCall{
0, MockCanvas::SaveLayerData{children_bounds, DlPaint(),
layer_filter1, 1}},
MockCanvas::DrawCall{
1, MockCanvas::DrawPathData{child_path1, child_paint1}},
MockCanvas::DrawCall{
1, MockCanvas::SaveLayerData{children_bounds, DlPaint(),
layer_filter2, 2}},
MockCanvas::DrawCall{
2, MockCanvas::DrawPathData{child_path2, child_paint2}},
MockCanvas::DrawCall{2, MockCanvas::RestoreData{1}},
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}}));
parent->Paint(display_list_paint_context());
DisplayListBuilder expected_builder;
/* (ClipRect)parent::Paint */ {
expected_builder.Save();
{
expected_builder.ClipRect(children_bounds, DlCanvas::ClipOp::kIntersect,
false);
/* (BackdropFilter)layer1::Paint */ {
expected_builder.Save();
{
expected_builder.SaveLayer(&children_bounds, nullptr,
layer_filter1.get());
{
/* mock_layer1::Paint */ {
expected_builder.DrawPath(child_path1, child_paint1);
}
/* (BackdropFilter)layer2::Paint */ {
expected_builder.Save();
{
expected_builder.SaveLayer(&children_bounds, nullptr,
layer_filter2.get());
{
/* mock_layer2::Paint */ {
expected_builder.DrawPath(child_path2, child_paint2);
}
}
expected_builder.Restore();
}
expected_builder.Restore();
}
}
expected_builder.Restore();
}
expected_builder.Restore();
}
}
expected_builder.Restore();
}
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
}
TEST_F(BackdropFilterLayerTest, Readback) {

View File

@@ -12,7 +12,6 @@
#include "flutter/flow/testing/mock_embedder.h"
#include "flutter/flow/testing/mock_layer.h"
#include "flutter/fml/macros.h"
#include "flutter/testing/mock_canvas.h"
#include "gtest/gtest.h"
namespace flutter {
@@ -170,17 +169,19 @@ TEST_F(ClipPathLayerTest, FullyContainedChild) {
EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix);
EXPECT_EQ(mock_layer->parent_mutators(), std::vector({Mutator(layer_path)}));
layer->Paint(paint_context());
EXPECT_EQ(
mock_canvas().draw_calls(),
std::vector(
{MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
MockCanvas::DrawCall{
1, MockCanvas::ClipPathData{layer_path, ClipOp::kIntersect,
MockCanvas::kHard_ClipEdgeStyle}},
MockCanvas::DrawCall{
1, MockCanvas::DrawPathData{child_path, child_paint}},
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}}));
layer->Paint(display_list_paint_context());
DisplayListBuilder expected_builder;
/* (ClipPath)layer::Paint */ {
expected_builder.Save();
{
expected_builder.ClipPath(layer_path);
/* mock_layer::Paint */ {
expected_builder.DrawPath(child_path, child_paint);
}
}
expected_builder.Restore();
}
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
}
TEST_F(ClipPathLayerTest, PartiallyContainedChild) {
@@ -224,17 +225,19 @@ TEST_F(ClipPathLayerTest, PartiallyContainedChild) {
EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix);
EXPECT_EQ(mock_layer->parent_mutators(), std::vector({Mutator(clip_path)}));
layer->Paint(paint_context());
EXPECT_EQ(
mock_canvas().draw_calls(),
std::vector(
{MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
MockCanvas::DrawCall{
1, MockCanvas::ClipPathData{clip_path, ClipOp::kIntersect,
MockCanvas::kHard_ClipEdgeStyle}},
MockCanvas::DrawCall{
1, MockCanvas::DrawPathData{child_path, child_paint}},
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}}));
layer->Paint(display_list_paint_context());
DisplayListBuilder expected_builder;
/* (ClipPath)layer::Paint */ {
expected_builder.Save();
{
expected_builder.ClipPath(clip_path);
/* mock_layer::Paint */ {
expected_builder.DrawPath(child_path, child_paint);
}
}
expected_builder.Restore();
}
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
}
static bool ReadbackResult(PrerollContext* context,

View File

@@ -11,7 +11,6 @@
#include "flutter/flow/testing/mock_embedder.h"
#include "flutter/flow/testing/mock_layer.h"
#include "flutter/fml/macros.h"
#include "flutter/testing/mock_canvas.h"
namespace flutter {
namespace testing {
@@ -164,17 +163,19 @@ TEST_F(ClipRectLayerTest, FullyContainedChild) {
EXPECT_EQ(mock_layer->parent_mutators(),
std::vector({Mutator(layer_bounds)}));
layer->Paint(paint_context());
EXPECT_EQ(
mock_canvas().draw_calls(),
std::vector(
{MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
MockCanvas::DrawCall{
1, MockCanvas::ClipRectData{layer_bounds, ClipOp::kIntersect,
MockCanvas::kHard_ClipEdgeStyle}},
MockCanvas::DrawCall{
1, MockCanvas::DrawPathData{child_path, child_paint}},
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}}));
layer->Paint(display_list_paint_context());
DisplayListBuilder expected_builder;
/* (ClipRect)layer::Paint */ {
expected_builder.Save();
{
expected_builder.ClipRect(layer_bounds);
/* mock_layer::Paint */ {
expected_builder.DrawPath(child_path, child_paint);
}
}
expected_builder.Restore();
}
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
}
TEST_F(ClipRectLayerTest, PartiallyContainedChild) {
@@ -213,17 +214,19 @@ TEST_F(ClipRectLayerTest, PartiallyContainedChild) {
EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix);
EXPECT_EQ(mock_layer->parent_mutators(), std::vector({Mutator(clip_rect)}));
layer->Paint(paint_context());
EXPECT_EQ(
mock_canvas().draw_calls(),
std::vector(
{MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
MockCanvas::DrawCall{
1, MockCanvas::ClipRectData{clip_rect, ClipOp::kIntersect,
MockCanvas::kHard_ClipEdgeStyle}},
MockCanvas::DrawCall{
1, MockCanvas::DrawPathData{child_path, child_paint}},
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}}));
layer->Paint(display_list_paint_context());
DisplayListBuilder expected_builder;
/* (ClipRect)layer::Paint */ {
expected_builder.Save();
{
expected_builder.ClipRect(clip_rect);
/* mock_layer::Paint */ {
expected_builder.DrawPath(child_path, child_paint);
}
}
expected_builder.Restore();
}
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
}
static bool ReadbackResult(PrerollContext* context,
@@ -488,8 +491,8 @@ TEST_F(ClipRectLayerTest, LayerCached) {
auto initial_transform = SkMatrix::Translate(50.0, 25.5);
SkMatrix cache_ctm = initial_transform;
MockCanvas cache_canvas;
cache_canvas.SetTransform(cache_ctm);
DisplayListBuilder cache_canvas;
cache_canvas.Transform(cache_ctm);
use_mock_raster_cache();
preroll_context()->state_stack.set_preroll_delegate(initial_transform);

View File

@@ -11,7 +11,6 @@
#include "flutter/flow/testing/mock_embedder.h"
#include "flutter/flow/testing/mock_layer.h"
#include "flutter/fml/macros.h"
#include "flutter/testing/mock_canvas.h"
namespace flutter {
namespace testing {
@@ -170,17 +169,19 @@ TEST_F(ClipRRectLayerTest, FullyContainedChild) {
EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix);
EXPECT_EQ(mock_layer->parent_mutators(), std::vector({Mutator(layer_rrect)}));
layer->Paint(paint_context());
EXPECT_EQ(
mock_canvas().draw_calls(),
std::vector(
{MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
MockCanvas::DrawCall{
1, MockCanvas::ClipRRectData{layer_rrect, ClipOp::kIntersect,
MockCanvas::kHard_ClipEdgeStyle}},
MockCanvas::DrawCall{
1, MockCanvas::DrawPathData{child_path, child_paint}},
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}}));
layer->Paint(display_list_paint_context());
DisplayListBuilder expected_builder;
/* (ClipRRect)layer::Paint */ {
expected_builder.Save();
{
expected_builder.ClipRRect(layer_rrect);
/* mock_layer::Paint */ {
expected_builder.DrawPath(child_path, child_paint);
}
}
expected_builder.Restore();
}
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
}
TEST_F(ClipRRectLayerTest, PartiallyContainedChild) {
@@ -220,19 +221,19 @@ TEST_F(ClipRRectLayerTest, PartiallyContainedChild) {
EXPECT_EQ(mock_layer->parent_matrix(), initial_matrix);
EXPECT_EQ(mock_layer->parent_mutators(), std::vector({Mutator(clip_rrect)}));
EXPECT_TRUE(mock_layer->needs_painting(paint_context()));
EXPECT_TRUE(layer->needs_painting(paint_context()));
layer->Paint(paint_context());
EXPECT_EQ(
mock_canvas().draw_calls(),
std::vector(
{MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
MockCanvas::DrawCall{
1, MockCanvas::ClipRRectData{clip_rrect, ClipOp::kIntersect,
MockCanvas::kHard_ClipEdgeStyle}},
MockCanvas::DrawCall{
1, MockCanvas::DrawPathData{child_path, child_paint}},
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}}));
layer->Paint(display_list_paint_context());
DisplayListBuilder expected_builder;
/* (ClipRRect)layer::Paint */ {
expected_builder.Save();
{
expected_builder.ClipRRect(clip_rrect);
/* mock_layer::Paint */ {
expected_builder.DrawPath(child_path, child_paint);
}
}
expected_builder.Restore();
}
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
}
static bool ReadbackResult(PrerollContext* context,
@@ -503,8 +504,8 @@ TEST_F(ClipRRectLayerTest, LayerCached) {
auto initial_transform = SkMatrix::Translate(50.0, 25.5);
SkMatrix cache_ctm = initial_transform;
MockCanvas cache_canvas;
cache_canvas.SetTransform(cache_ctm);
DisplayListBuilder cache_canvas;
cache_canvas.Transform(cache_ctm);
use_mock_raster_cache();
preroll_context()->state_stack.set_preroll_delegate(initial_transform);

View File

@@ -16,7 +16,6 @@
#include "flutter/flow/testing/layer_test.h"
#include "flutter/flow/testing/mock_layer.h"
#include "flutter/fml/macros.h"
#include "flutter/testing/mock_canvas.h"
namespace flutter {
namespace testing {
@@ -67,12 +66,18 @@ TEST_F(ColorFilterLayerTest, EmptyFilter) {
EXPECT_TRUE(layer->needs_painting(paint_context()));
EXPECT_EQ(mock_layer->parent_matrix(), initial_transform);
layer->Paint(paint_context());
EXPECT_EQ(mock_canvas().draw_calls(),
std::vector({
MockCanvas::DrawCall{
0, MockCanvas::DrawPathData{child_path, child_paint}},
}));
layer->Paint(display_list_paint_context());
DisplayListBuilder expected_builder;
/* (ColorFilter)layer::Paint */ {
expected_builder.Save();
{
/* mock_layer::Paint */ {
expected_builder.DrawPath(child_path, child_paint);
}
}
expected_builder.Restore();
}
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
}
TEST_F(ColorFilterLayerTest, SimpleFilter) {
@@ -257,10 +262,10 @@ TEST_F(ColorFilterLayerTest, CacheChild) {
layer->Add(mock_layer);
SkMatrix cache_ctm = initial_transform;
MockCanvas cache_canvas;
cache_canvas.SetTransform(cache_ctm);
MockCanvas other_canvas;
other_canvas.SetTransform(other_transform);
DisplayListBuilder cache_canvas;
cache_canvas.Transform(cache_ctm);
DisplayListBuilder other_canvas;
other_canvas.Transform(other_transform);
use_mock_raster_cache();
const auto* cacheable_color_filter_item = layer->raster_cache_item();
@@ -301,10 +306,10 @@ TEST_F(ColorFilterLayerTest, CacheChildren) {
DlPaint paint = DlPaint();
SkMatrix cache_ctm = initial_transform;
MockCanvas cache_canvas;
cache_canvas.SetTransform(cache_ctm);
MockCanvas other_canvas;
other_canvas.SetTransform(other_transform);
DisplayListBuilder cache_canvas;
cache_canvas.Transform(cache_ctm);
DisplayListBuilder other_canvas;
other_canvas.Transform(other_transform);
use_mock_raster_cache();
@@ -347,10 +352,10 @@ TEST_F(ColorFilterLayerTest, CacheColorFilterLayerSelf) {
DlPaint paint = DlPaint();
SkMatrix cache_ctm = initial_transform;
MockCanvas cache_canvas;
cache_canvas.SetTransform(cache_ctm);
MockCanvas other_canvas;
other_canvas.SetTransform(other_transform);
DisplayListBuilder cache_canvas;
cache_canvas.Transform(cache_ctm);
DisplayListBuilder other_canvas;
other_canvas.Transform(other_transform);
use_mock_raster_cache();
preroll_context()->state_stack.set_preroll_delegate(initial_transform);

View File

@@ -10,9 +10,7 @@
#include "flutter/flow/testing/layer_test.h"
#include "flutter/flow/testing/mock_layer.h"
#include "flutter/fml/macros.h"
#include "flutter/testing/mock_canvas.h"
#include "gtest/gtest.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkMatrix.h"
namespace flutter {
@@ -111,10 +109,14 @@ TEST_F(ContainerLayerTest, Simple) {
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}}}));
layer->Paint(display_list_paint_context());
DisplayListBuilder expected_builder;
/* (Container)layer::Paint */ {
/* mock_layer::Paint */ {
expected_builder.DrawPath(child_path, child_paint);
}
}
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
}
TEST_F(ContainerLayerTest, Multiple) {
@@ -151,13 +153,17 @@ TEST_F(ContainerLayerTest, Multiple) {
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}}}));
layer->Paint(display_list_paint_context());
DisplayListBuilder expected_builder;
/* (Container)layer::Paint */ {
/* mock_layer1::Paint */ {
expected_builder.DrawPath(child_path1, child_paint1);
}
/* mock_layer2::Paint */ {
expected_builder.DrawPath(child_path2, child_paint2);
}
}
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
}
TEST_F(ContainerLayerTest, MultipleWithEmpty) {
@@ -188,10 +194,15 @@ TEST_F(ContainerLayerTest, MultipleWithEmpty) {
EXPECT_EQ(mock_layer1->parent_cull_rect(), kGiantRect);
EXPECT_EQ(mock_layer2->parent_cull_rect(), kGiantRect);
layer->Paint(paint_context());
EXPECT_EQ(mock_canvas().draw_calls(),
std::vector({MockCanvas::DrawCall{
0, MockCanvas::DrawPathData{child_path1, child_paint1}}}));
layer->Paint(display_list_paint_context());
DisplayListBuilder expected_builder;
/* (Container)layer::Paint */ {
/* mock_layer1::Paint */ {
expected_builder.DrawPath(child_path1, child_paint1);
}
// mock_layer2 not drawn due to needs_painting() returning false
}
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
}
TEST_F(ContainerLayerTest, NeedsSystemComposite) {
@@ -227,13 +238,17 @@ TEST_F(ContainerLayerTest, NeedsSystemComposite) {
EXPECT_EQ(mock_layer1->parent_cull_rect(), kGiantRect);
EXPECT_EQ(mock_layer2->parent_cull_rect(), kGiantRect);
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}}}));
layer->Paint(display_list_paint_context());
DisplayListBuilder expected_builder;
/* (Container)layer::Paint */ {
/* mock_layer1::Paint */ {
expected_builder.DrawPath(child_path1, child_paint1);
}
/* mock_layer2::Paint */ {
expected_builder.DrawPath(child_path2, child_paint2);
}
}
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
}
TEST_F(ContainerLayerTest, RasterCacheTest) {

View File

@@ -10,7 +10,6 @@
#include "flutter/flow/layers/layer_tree.h"
#include "flutter/flow/testing/diff_context_test.h"
#include "flutter/fml/macros.h"
#include "flutter/testing/mock_canvas.h"
namespace flutter {
namespace testing {
@@ -69,8 +68,6 @@ TEST_F(DisplayListLayerTest, InvalidDisplayListDies) {
TEST_F(DisplayListLayerTest, SimpleDisplayList) {
const SkPoint layer_offset = SkPoint::Make(1.5f, -0.5f);
const SkMatrix layer_offset_matrix =
SkMatrix::Translate(layer_offset.fX, layer_offset.fY);
const SkRect picture_bounds = SkRect::MakeLTRB(5.0f, 6.0f, 20.5f, 21.5f);
DisplayListBuilder builder;
builder.DrawRect(picture_bounds, DlPaint());
@@ -84,15 +81,18 @@ TEST_F(DisplayListLayerTest, SimpleDisplayList) {
EXPECT_EQ(layer->display_list(), display_list.get());
EXPECT_TRUE(layer->needs_painting(paint_context()));
layer->Paint(paint_context());
auto expected_draw_calls = std::vector(
{MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
MockCanvas::DrawCall{
1, MockCanvas::ConcatMatrixData{SkM44(layer_offset_matrix)}},
MockCanvas::DrawCall{1,
MockCanvas::DrawDisplayListData{display_list, 1}},
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}});
EXPECT_EQ(mock_canvas().draw_calls(), expected_draw_calls);
layer->Paint(display_list_paint_context());
DisplayListBuilder expected_builder;
/* (DisplayList)layer::Paint */ {
expected_builder.Save();
{
expected_builder.Translate(layer_offset.fX, layer_offset.fY);
expected_builder.DrawDisplayList(display_list);
}
expected_builder.Restore();
}
EXPECT_TRUE(
DisplayListsEQ_Verbose(this->display_list(), expected_builder.Build()));
}
TEST_F(DisplayListLayerTest, CachingDoesNotChangeCullRect) {

View File

@@ -11,7 +11,6 @@
#include "flutter/flow/testing/layer_test.h"
#include "flutter/flow/testing/mock_layer.h"
#include "flutter/fml/macros.h"
#include "flutter/testing/mock_canvas.h"
#include "gtest/gtest.h"
#include "include/core/SkPath.h"
#include "third_party/skia/include/effects/SkImageFilters.h"
@@ -63,12 +62,16 @@ TEST_F(ImageFilterLayerTest, EmptyFilter) {
EXPECT_TRUE(layer->needs_painting(paint_context()));
EXPECT_EQ(mock_layer->parent_matrix(), initial_transform);
layer->Paint(paint_context());
EXPECT_EQ(mock_canvas().draw_calls(),
std::vector({
MockCanvas::DrawCall{
0, MockCanvas::DrawPathData{child_path, child_paint}},
}));
layer->Paint(display_list_paint_context());
DisplayListBuilder expected_builder;
/* (ImageFilter)layer::Paint */ {
expected_builder.Save();
/* mock_layer1::Paint */ {
expected_builder.DrawPath(child_path, child_paint);
}
expected_builder.Restore();
}
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
}
TEST_F(ImageFilterLayerTest, SimpleFilter) {
@@ -354,10 +357,10 @@ TEST_F(ImageFilterLayerTest, CacheChild) {
layer->Add(mock_layer);
SkMatrix cache_ctm = initial_transform;
MockCanvas cache_canvas;
cache_canvas.SetTransform(cache_ctm);
MockCanvas other_canvas;
other_canvas.SetTransform(other_transform);
DisplayListBuilder cache_canvas;
cache_canvas.Transform(cache_ctm);
DisplayListBuilder other_canvas;
other_canvas.Transform(other_transform);
DlPaint paint;
use_mock_raster_cache();
@@ -400,10 +403,10 @@ TEST_F(ImageFilterLayerTest, CacheChildren) {
layer->Add(mock_layer2);
SkMatrix cache_ctm = initial_transform;
MockCanvas cache_canvas;
cache_canvas.SetTransform(cache_ctm);
MockCanvas other_canvas;
other_canvas.SetTransform(other_transform);
DisplayListBuilder cache_canvas;
cache_canvas.Transform(cache_ctm);
DisplayListBuilder other_canvas;
other_canvas.Transform(other_transform);
use_mock_raster_cache();
@@ -430,34 +433,36 @@ TEST_F(ImageFilterLayerTest, CacheChildren) {
EXPECT_FALSE(raster_cache()->Draw(
cacheable_image_filter_item->GetId().value(), other_canvas, &paint));
mock_canvas().reset_draw_calls();
layer->Preroll(preroll_context());
layer->Paint(paint_context());
EXPECT_EQ(mock_canvas().draw_calls().size(), 8UL);
auto call0 = MockCanvas::DrawCall{0, MockCanvas::SaveData{1}};
EXPECT_EQ(mock_canvas().draw_calls()[0], call0);
auto call1 = MockCanvas::DrawCall{
1, MockCanvas::ConcatMatrixData{SkM44(SkMatrix::Translate(offset))}};
EXPECT_EQ(mock_canvas().draw_calls()[1], call1);
auto call2 = MockCanvas::DrawCall{
1, MockCanvas::SetMatrixData{SkM44(SkMatrix::Translate(offset))}};
EXPECT_EQ(mock_canvas().draw_calls()[2], call2);
auto call3 = MockCanvas::DrawCall{1, MockCanvas::SaveData{2}};
EXPECT_EQ(mock_canvas().draw_calls()[3], call3);
auto call4 = MockCanvas::DrawCall{
2, MockCanvas::SetMatrixData{SkM44(SkMatrix::Translate(0.0, 0.0))}};
EXPECT_EQ(mock_canvas().draw_calls()[4], call4);
EXPECT_EQ(mock_canvas().draw_calls()[5].layer, 2);
EXPECT_TRUE(std::holds_alternative<MockCanvas::DrawImageData>(
mock_canvas().draw_calls()[5].data));
auto call5_data =
std::get<MockCanvas::DrawImageData>(mock_canvas().draw_calls()[5].data);
EXPECT_EQ(call5_data.x, offset.fX);
EXPECT_EQ(call5_data.y, offset.fY);
auto call6 = MockCanvas::DrawCall{2, MockCanvas::RestoreData{1}};
EXPECT_EQ(mock_canvas().draw_calls()[6], call6);
auto call7 = MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}};
EXPECT_EQ(mock_canvas().draw_calls()[7], call7);
SkRect children_bounds = child_path1.getBounds();
children_bounds.join(child_path2.getBounds());
SkMatrix snapped_matrix = SkMatrix::MakeAll( //
1, 0, SkScalarRoundToScalar(offset.fX), //
0, 1, SkScalarRoundToScalar(offset.fY), //
0, 0, 1);
SkMatrix cache_matrix = initial_transform;
cache_matrix.preConcat(snapped_matrix);
auto transformed_filter = dl_image_filter->makeWithLocalMatrix(cache_matrix);
layer->Paint(display_list_paint_context());
DisplayListBuilder expected_builder;
/* (ImageFilter)layer::Paint() */ {
expected_builder.Save();
{
expected_builder.Translate(offset.fX, offset.fY);
// snap translation components to pixels due to using raster cache
expected_builder.TransformReset();
expected_builder.Transform(snapped_matrix);
DlPaint dl_paint;
dl_paint.setImageFilter(transformed_filter.get());
raster_cache()->Draw(cacheable_image_filter_item->GetId().value(),
expected_builder, &dl_paint);
}
expected_builder.Restore();
}
expected_builder.Restore();
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
}
TEST_F(ImageFilterLayerTest, CacheImageFilterLayerSelf) {
@@ -470,53 +475,58 @@ TEST_F(ImageFilterLayerTest, CacheImageFilterLayerSelf) {
const SkPath child_path = SkPath().addRect(child_rect);
auto mock_layer = std::make_shared<MockLayer>(child_path);
auto offset = SkPoint::Make(53.8, 24.4);
auto offset_rounded =
SkPoint::Make(std::round(offset.x()), std::round(offset.y()));
auto offset_rounded_out =
SkPoint::Make(std::floor(offset.x()), std::floor(offset.y()));
auto layer = std::make_shared<ImageFilterLayer>(dl_image_filter, offset);
layer->Add(mock_layer);
SkMatrix cache_ctm = initial_transform;
MockCanvas cache_canvas;
cache_canvas.SetTransform(cache_ctm);
MockCanvas other_canvas;
other_canvas.SetTransform(other_transform);
DisplayListBuilder cache_canvas;
cache_canvas.Transform(cache_ctm);
DisplayListBuilder other_canvas;
other_canvas.Transform(other_transform);
DlPaint paint;
SkMatrix snapped_matrix = SkMatrix::MakeAll( //
1, 0, SkScalarRoundToScalar(offset.fX), //
0, 1, SkScalarRoundToScalar(offset.fY), //
0, 0, 1);
use_mock_raster_cache();
preroll_context()->state_stack.set_preroll_delegate(initial_transform);
const auto* cacheable_image_filter_item = layer->raster_cache_item();
// frame 1.
layer->Preroll(preroll_context());
layer->Paint(paint_context());
EXPECT_EQ(mock_canvas().draw_calls().size(), 7UL);
auto uncached_call0 = MockCanvas::DrawCall{0, MockCanvas::SaveData{1}};
EXPECT_EQ(mock_canvas().draw_calls()[0], uncached_call0);
auto uncached_call1 = MockCanvas::DrawCall{
1, MockCanvas::ConcatMatrixData{SkM44(SkMatrix::Translate(offset))}};
EXPECT_EQ(mock_canvas().draw_calls()[1], uncached_call1);
auto uncached_call2 = MockCanvas::DrawCall{
1, MockCanvas::SetMatrixData{SkM44(SkMatrix::Translate(offset_rounded))}};
EXPECT_EQ(mock_canvas().draw_calls()[2], uncached_call2);
EXPECT_EQ(mock_canvas().draw_calls()[3].layer, 1);
auto uncached_call3_data =
std::get<MockCanvas::SaveLayerData>(mock_canvas().draw_calls()[3].data);
EXPECT_EQ(uncached_call3_data.save_bounds, child_rect);
EXPECT_EQ(uncached_call3_data.save_to_layer, 2);
auto uncached_call4 =
MockCanvas::DrawCall{2, MockCanvas::DrawPathData{child_path, DlPaint()}};
EXPECT_EQ(mock_canvas().draw_calls()[4], uncached_call4);
auto uncached_call5 = MockCanvas::DrawCall{2, MockCanvas::RestoreData{1}};
EXPECT_EQ(mock_canvas().draw_calls()[5], uncached_call5);
auto uncached_call6 = MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}};
EXPECT_EQ(mock_canvas().draw_calls()[6], uncached_call6);
layer->Paint(display_list_paint_context());
{
DisplayListBuilder expected_builder;
/* (ImageFilter)layer::Paint */ {
expected_builder.Save();
{
expected_builder.Translate(offset.fX, offset.fY);
// Snap to pixel translation due to use of raster cache
expected_builder.TransformReset();
expected_builder.Transform(snapped_matrix);
DlPaint save_paint = DlPaint().setImageFilter(dl_image_filter);
expected_builder.SaveLayer(&child_rect, &save_paint);
{
/* mock_layer::Paint */ {
expected_builder.DrawPath(child_path, DlPaint());
}
}
expected_builder.Restore();
}
expected_builder.Restore();
}
EXPECT_TRUE(
DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
}
// frame 2.
layer->Preroll(preroll_context());
layer->Paint(paint_context());
layer->Paint(display_list_paint_context());
// frame 3.
layer->Preroll(preroll_context());
layer->Paint(paint_context());
layer->Paint(display_list_paint_context());
LayerTree::TryToRasterCache(cacheable_items(), &paint_context());
// frame1,2 cache the ImageFilter's children layer, frame3 cache the
@@ -533,24 +543,24 @@ TEST_F(ImageFilterLayerTest, CacheImageFilterLayerSelf) {
EXPECT_FALSE(raster_cache()->Draw(
cacheable_image_filter_item->GetId().value(), other_canvas, &paint));
mock_canvas().reset_draw_calls();
layer->Preroll(preroll_context());
layer->Paint(paint_context());
EXPECT_EQ(mock_canvas().draw_calls().size(), 4UL);
auto cached_call0 = MockCanvas::DrawCall{0, MockCanvas::SaveData{1}};
EXPECT_EQ(mock_canvas().draw_calls()[0], cached_call0);
auto cached_call1 = MockCanvas::DrawCall{
1, MockCanvas::SetMatrixData{SkM44(SkMatrix::Translate(0.0, 0.0))}};
EXPECT_EQ(mock_canvas().draw_calls()[1], cached_call1);
EXPECT_EQ(mock_canvas().draw_calls()[2].layer, 1);
EXPECT_TRUE(std::holds_alternative<MockCanvas::DrawImageDataNoPaint>(
mock_canvas().draw_calls()[2].data));
auto cached_call2_data = std::get<MockCanvas::DrawImageDataNoPaint>(
mock_canvas().draw_calls()[2].data);
EXPECT_EQ(cached_call2_data.x, offset_rounded_out.fX);
EXPECT_EQ(cached_call2_data.y, offset_rounded_out.fY);
auto cached_call3 = MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}};
EXPECT_EQ(mock_canvas().draw_calls()[3], cached_call3);
reset_display_list();
layer->Paint(display_list_paint_context());
{
DisplayListBuilder expected_builder;
/* (ImageFilter)layer::Paint */ {
expected_builder.Save();
{
EXPECT_TRUE(
raster_cache()->Draw(cacheable_image_filter_item->GetId().value(),
expected_builder, nullptr));
}
expected_builder.Restore();
}
EXPECT_TRUE(
DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
}
}
TEST_F(ImageFilterLayerTest, OpacityInheritance) {

View File

@@ -9,7 +9,6 @@
#include "flutter/flow/layers/layer.h"
#include "flutter/flow/layers/layer_state_stack.h"
#include "flutter/testing/display_list_testing.h"
#include "flutter/testing/mock_canvas.h"
namespace flutter {
namespace testing {
@@ -63,9 +62,10 @@ TEST(LayerStateStack, SingularDelegate) {
LayerStateStack state_stack;
ASSERT_EQ(state_stack.canvas_delegate(), nullptr);
// Two kinds of DlCanvas implementation
// Two different DlCanvas implementators
DisplayListBuilder builder;
MockCanvas canvas;
DisplayListBuilder builder2;
DlCanvas& canvas = builder2;
// no delegate -> builder delegate
state_stack.set_delegate(&builder);
@@ -92,7 +92,8 @@ TEST(LayerStateStack, SingularDelegate) {
TEST(LayerStateStack, OldDelegateIsRolledBack) {
LayerStateStack state_stack;
DisplayListBuilder builder;
MockCanvas canvas;
DisplayListBuilder builder2;
DlCanvas& canvas = builder2;
ASSERT_TRUE(builder.GetTransform().isIdentity());
ASSERT_TRUE(canvas.GetTransform().isIdentity());

View File

@@ -16,7 +16,6 @@
#include "flutter/flow/testing/mock_layer.h"
#include "flutter/fml/macros.h"
#include "flutter/testing/display_list_testing.h"
#include "flutter/testing/mock_canvas.h"
#include "gtest/gtest.h"
namespace flutter {
@@ -93,10 +92,10 @@ TEST_F(OpacityLayerTest, CacheChild) {
DlPaint paint;
SkMatrix cache_ctm = initial_transform;
MockCanvas cache_canvas;
cache_canvas.SetTransform(cache_ctm);
MockCanvas other_canvas;
other_canvas.SetTransform(other_transform);
DisplayListBuilder cache_canvas;
cache_canvas.Transform(cache_ctm);
DisplayListBuilder other_canvas;
other_canvas.Transform(other_transform);
use_mock_raster_cache();
@@ -142,10 +141,10 @@ TEST_F(OpacityLayerTest, CacheChildren) {
layer->Add(mock_layer2);
SkMatrix cache_ctm = initial_transform;
MockCanvas cache_canvas;
cache_canvas.SetTransform(cache_ctm);
MockCanvas other_canvas;
other_canvas.SetTransform(other_transform);
DisplayListBuilder cache_canvas;
cache_canvas.Transform(cache_ctm);
DisplayListBuilder other_canvas;
other_canvas.Transform(other_transform);
use_mock_raster_cache();
@@ -233,18 +232,20 @@ TEST_F(OpacityLayerTest, FullyOpaque) {
EXPECT_EQ(mock_layer->parent_mutators(),
std::vector({Mutator(layer_transform)}));
SkRect opacity_bounds;
expected_layer_bounds.makeOffset(-layer_offset.fX, -layer_offset.fY)
.roundOut(&opacity_bounds);
auto expected_draw_calls =
std::vector({MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
MockCanvas::DrawCall{
1, MockCanvas::ConcatMatrixData{SkM44(layer_transform)}},
MockCanvas::DrawCall{
1, MockCanvas::DrawPathData{child_path, child_paint}},
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}});
layer->Paint(paint_context());
EXPECT_EQ(mock_canvas().draw_calls(), expected_draw_calls);
DisplayListBuilder expected_builder;
/* (Opacity)layer::Paint */ {
expected_builder.Save();
{
expected_builder.Translate(layer_offset.fX, layer_offset.fY);
// Opaque alpha needs no SaveLayer, just recurse into painting mock_layer
/* mock_layer::Paint */ {
expected_builder.DrawPath(child_path, child_paint);
}
}
expected_builder.Restore();
}
layer->Paint(display_list_paint_context());
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
}
TEST_F(OpacityLayerTest, FullyTransparent) {
@@ -275,20 +276,24 @@ TEST_F(OpacityLayerTest, FullyTransparent) {
mock_layer->parent_mutators(),
std::vector({Mutator(layer_transform), Mutator(SK_AlphaTRANSPARENT)}));
auto expected_draw_calls = std::vector(
{MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
MockCanvas::DrawCall{
1, MockCanvas::ConcatMatrixData{SkM44(layer_transform)}},
MockCanvas::DrawCall{
1,
MockCanvas::SaveLayerData{
child_bounds, DlPaint(DlColor::kTransparent()), nullptr, 2}},
MockCanvas::DrawCall{2,
MockCanvas::DrawPathData{child_path, child_paint}},
MockCanvas::DrawCall{2, MockCanvas::RestoreData{1}},
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}});
layer->Paint(paint_context());
EXPECT_EQ(mock_canvas().draw_calls(), expected_draw_calls);
DisplayListBuilder expected_builder;
/* (Opacity)layer::Paint */ {
expected_builder.Save();
{
expected_builder.Translate(layer_offset.fX, layer_offset.fY);
/* (Opacity)layer::PaintChildren */ {
DlPaint save_paint(DlPaint().setOpacity(layer->opacity()));
expected_builder.SaveLayer(&child_bounds, &save_paint);
/* mock_layer::Paint */ {
expected_builder.DrawPath(child_path, child_paint);
}
expected_builder.Restore();
}
}
expected_builder.Restore();
}
layer->Paint(display_list_paint_context());
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
}
TEST_F(OpacityLayerTest, HalfTransparent) {
@@ -324,12 +329,18 @@ TEST_F(OpacityLayerTest, HalfTransparent) {
DlPaint child_dl_paint = DlPaint(DlColor::kGreen());
auto expected_builder = DisplayListBuilder();
expected_builder.Save();
expected_builder.Translate(layer_offset.fX, layer_offset.fY);
expected_builder.SaveLayer(&opacity_bounds, &save_paint);
expected_builder.DrawPath(child_path, child_dl_paint);
expected_builder.Restore();
expected_builder.Restore();
/* (Opacity)layer::Paint */ {
expected_builder.Save();
expected_builder.Translate(layer_offset.fX, layer_offset.fY);
/* (Opacity)layer::PaintChildren */ {
expected_builder.SaveLayer(&opacity_bounds, &save_paint);
/* mock_layer::Paint */ {
expected_builder.DrawPath(child_path, child_dl_paint);
}
expected_builder.Restore();
}
expected_builder.Restore();
}
sk_sp<DisplayList> expected_display_list = expected_builder.Build();
layer->Paint(display_list_paint_context());
@@ -384,53 +395,65 @@ TEST_F(OpacityLayerTest, Nested) {
EXPECT_TRUE(layer2->needs_painting(paint_context()));
EXPECT_EQ(mock_layer1->parent_matrix(),
SkMatrix::Concat(initial_transform, layer1_transform));
// EXPECT_EQ(mock_layer1->parent_mutators(),
// std::vector({Mutator(layer1_transform), Mutator(alpha1)}));
EXPECT_EQ(mock_layer1->parent_mutators(),
std::vector({Mutator(layer1_transform), Mutator(alpha1)}));
EXPECT_EQ(
mock_layer2->parent_matrix(),
SkMatrix::Concat(SkMatrix::Concat(initial_transform, layer1_transform),
layer2_transform));
// EXPECT_EQ(mock_layer2->parent_mutators(),
// std::vector({Mutator(layer1_transform), Mutator(alpha1),
// Mutator(layer2_transform), Mutator(alpha2)}));
EXPECT_EQ(mock_layer2->parent_mutators(),
std::vector({Mutator(layer1_transform), Mutator(alpha1),
Mutator(layer2_transform), Mutator(alpha2)}));
EXPECT_EQ(mock_layer3->parent_matrix(),
SkMatrix::Concat(initial_transform, layer1_transform));
// EXPECT_EQ(mock_layer3->parent_mutators(),
// std::vector({Mutator(layer1_transform), Mutator(alpha1)}));
EXPECT_EQ(mock_layer3->parent_mutators(),
std::vector({Mutator(layer1_transform), Mutator(alpha1)}));
DlPaint opacity1_paint;
opacity1_paint.setOpacity(alpha1 * (1.0 / SK_AlphaOPAQUE));
DlPaint opacity2_paint;
opacity2_paint.setOpacity(alpha2 * (1.0 / SK_AlphaOPAQUE));
SkRect opacity1_bounds =
expected_layer1_bounds.makeOffset(-layer1_offset.fX, -layer1_offset.fY);
SkRect opacity2_bounds =
expected_layer2_bounds.makeOffset(-layer2_offset.fX, -layer2_offset.fY);
auto expected_draw_calls = std::vector(
{MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
MockCanvas::DrawCall{
1, MockCanvas::ConcatMatrixData{SkM44(layer1_transform)}},
MockCanvas::DrawCall{
1, MockCanvas::SaveLayerData{opacity1_bounds, opacity1_paint,
nullptr, 2}},
MockCanvas::DrawCall{
2, MockCanvas::DrawPathData{child1_path, child1_paint}},
MockCanvas::DrawCall{2, MockCanvas::SaveData{3}},
MockCanvas::DrawCall{
3, MockCanvas::ConcatMatrixData{SkM44(layer2_transform)}},
MockCanvas::DrawCall{
3, MockCanvas::SaveLayerData{opacity2_bounds, opacity2_paint,
nullptr, 4}},
MockCanvas::DrawCall{
4, MockCanvas::DrawPathData{child2_path, child2_paint}},
MockCanvas::DrawCall{4, MockCanvas::RestoreData{3}},
MockCanvas::DrawCall{3, MockCanvas::RestoreData{2}},
MockCanvas::DrawCall{
2, MockCanvas::DrawPathData{child3_path, child3_paint}},
MockCanvas::DrawCall{2, MockCanvas::RestoreData{1}},
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}});
layer1->Paint(paint_context());
EXPECT_EQ(mock_canvas().draw_calls(), expected_draw_calls);
DlPaint opacity1_paint;
opacity1_paint.setOpacity(alpha1 * (1.0 / SK_AlphaOPAQUE));
DlPaint opacity2_paint;
opacity2_paint.setOpacity(alpha2 * (1.0 / SK_AlphaOPAQUE));
DisplayListBuilder expected_builder;
/* (Opacity)layer1::Paint */ {
expected_builder.Save();
{
expected_builder.Translate(layer1_offset.fX, layer1_offset.fY);
/* (Opacity)layer1::PaintChildren */ {
expected_builder.SaveLayer(&opacity1_bounds, &opacity1_paint);
/* mock_layer1::Paint */ {
expected_builder.DrawPath(child1_path, child1_paint);
}
/* (Opacity)layer2::Paint */ {
expected_builder.Save();
{
expected_builder.Translate(layer2_offset.fX, layer2_offset.fY);
/* (Opacity)layer2::PaintChidren */ {
expected_builder.SaveLayer(&opacity2_bounds, &opacity2_paint);
{
/* mock_layer2::Paint */ {
expected_builder.DrawPath(child2_path, child2_paint);
}
}
expected_builder.Restore();
}
}
expected_builder.Restore();
}
/* mock_layer3::Paint */ {
expected_builder.DrawPath(child3_path, child3_paint);
}
expected_builder.Restore();
}
}
expected_builder.Restore();
}
layer1->Paint(display_list_paint_context());
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
}
TEST_F(OpacityLayerTest, Readback) {
@@ -658,16 +681,12 @@ TEST_F(OpacityLayerDiffTest, FractionalTranslationWithRasterCache) {
}
TEST_F(OpacityLayerTest, FullyOpaqueWithFractionalValues) {
use_mock_raster_cache(); // Ensure non-fractional alignment.
use_mock_raster_cache(); // Ensure pixel-snapped alignment.
const SkPath child_path = SkPath().addRect(SkRect::MakeWH(5.0f, 5.0f));
const SkPoint layer_offset = SkPoint::Make(0.5f, 1.5f);
const SkMatrix initial_transform = SkMatrix::Translate(0.5f, 0.5f);
const SkMatrix layer_transform =
SkMatrix::Translate(layer_offset.fX, layer_offset.fY);
const DlPaint child_paint = DlPaint(DlColor::kGreen());
const SkRect expected_layer_bounds =
layer_transform.mapRect(child_path.getBounds());
auto mock_layer = std::make_shared<MockLayer>(child_path, child_paint);
auto layer = std::make_shared<OpacityLayer>(SK_AlphaOPAQUE, layer_offset);
layer->Add(mock_layer);
@@ -675,21 +694,25 @@ TEST_F(OpacityLayerTest, FullyOpaqueWithFractionalValues) {
preroll_context()->state_stack.set_preroll_delegate(initial_transform);
layer->Preroll(preroll_context());
SkRect opacity_bounds;
expected_layer_bounds.makeOffset(-layer_offset.fX, -layer_offset.fY)
.roundOut(&opacity_bounds);
auto expected_draw_calls = std::vector(
{MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
MockCanvas::DrawCall{
1, MockCanvas::ConcatMatrixData{SkM44(layer_transform)}},
MockCanvas::DrawCall{
1, MockCanvas::SetMatrixData{SkM44(
RasterCacheUtil::GetIntegralTransCTM(layer_transform))}},
MockCanvas::DrawCall{1,
MockCanvas::DrawPathData{child_path, child_paint}},
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}});
layer->Paint(paint_context());
EXPECT_EQ(mock_canvas().draw_calls(), expected_draw_calls);
auto expected_builder = DisplayListBuilder();
/* (Opacity)layer::Paint */ {
expected_builder.Save();
expected_builder.Translate(layer_offset.fX, layer_offset.fY);
// Opaque alpha needs no SaveLayer, just recurse into painting mock_layer
// but since we use the mock raster cache we pixel snap the transform
expected_builder.TransformReset();
expected_builder.Transform2DAffine(
1, 0, SkScalarRoundToScalar(layer_offset.fX), //
0, 1, SkScalarRoundToScalar(layer_offset.fY));
/* mock_layer::Paint */ {
expected_builder.DrawPath(child_path, child_paint);
}
expected_builder.Restore();
}
sk_sp<DisplayList> expected_display_list = expected_builder.Build();
layer->Paint(display_list_paint_context());
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_display_list));
}
TEST_F(OpacityLayerTest, FullyTransparentDoesNotCullPlatformView) {

View File

@@ -11,10 +11,7 @@
#include "flutter/flow/testing/layer_test.h"
#include "flutter/flow/testing/mock_layer.h"
#include "flutter/fml/macros.h"
#include "flutter/testing/mock_canvas.h"
#include "gtest/gtest.h"
#include "third_party/skia/include/core/SkShader.h"
#include "third_party/skia/include/effects/SkPerlinNoiseShader.h"
namespace flutter {
namespace testing {
@@ -86,23 +83,27 @@ TEST_F(ShaderMaskLayerTest, EmptyFilter) {
DlPaint filter_paint;
filter_paint.setBlendMode(DlBlendMode::kSrc);
filter_paint.setColorSource(nullptr);
layer->Paint(paint_context());
EXPECT_EQ(
mock_canvas().draw_calls(),
std::vector({MockCanvas::DrawCall{
0, MockCanvas::SaveLayerData{child_bounds, DlPaint(),
nullptr, 1}},
MockCanvas::DrawCall{
1, MockCanvas::DrawPathData{child_path, child_paint}},
MockCanvas::DrawCall{
1, MockCanvas::ConcatMatrixData{SkM44::Translate(
layer_bounds.fLeft, layer_bounds.fTop)}},
MockCanvas::DrawCall{
1, MockCanvas::DrawRectData{SkRect::MakeWH(
layer_bounds.width(),
layer_bounds.height()),
filter_paint}},
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}}));
layer->Paint(display_list_paint_context());
DisplayListBuilder expected_builder;
/* (ShaderMask)layer::Paint */ {
expected_builder.Save();
{
expected_builder.SaveLayer(&child_bounds);
{
/* mock_layer::Paint */ {
expected_builder.DrawPath(child_path, child_paint);
}
expected_builder.Translate(layer_bounds.fLeft, layer_bounds.fTop);
expected_builder.DrawRect(
SkRect::MakeWH(layer_bounds.width(), layer_bounds.height()),
filter_paint);
}
expected_builder.Restore();
}
expected_builder.Restore();
}
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
}
TEST_F(ShaderMaskLayerTest, SimpleFilter) {
@@ -127,23 +128,27 @@ TEST_F(ShaderMaskLayerTest, SimpleFilter) {
DlPaint filter_paint;
filter_paint.setBlendMode(DlBlendMode::kSrc);
filter_paint.setColorSource(dl_filter);
layer->Paint(paint_context());
EXPECT_EQ(
mock_canvas().draw_calls(),
std::vector({MockCanvas::DrawCall{
0, MockCanvas::SaveLayerData{child_bounds, DlPaint(),
nullptr, 1}},
MockCanvas::DrawCall{
1, MockCanvas::DrawPathData{child_path, child_paint}},
MockCanvas::DrawCall{
1, MockCanvas::ConcatMatrixData{SkM44::Translate(
layer_bounds.fLeft, layer_bounds.fTop)}},
MockCanvas::DrawCall{
1, MockCanvas::DrawRectData{SkRect::MakeWH(
layer_bounds.width(),
layer_bounds.height()),
filter_paint}},
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}}));
layer->Paint(display_list_paint_context());
DisplayListBuilder expected_builder;
/* (ShaderMask)layer::Paint */ {
expected_builder.Save();
{
expected_builder.SaveLayer(&child_bounds);
{
/* mock_layer::Paint */ {
expected_builder.DrawPath(child_path, child_paint);
}
expected_builder.Translate(layer_bounds.fLeft, layer_bounds.fTop);
expected_builder.DrawRect(
SkRect::MakeWH(layer_bounds.width(), layer_bounds.height()),
filter_paint);
}
expected_builder.Restore();
}
expected_builder.Restore();
}
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
}
TEST_F(ShaderMaskLayerTest, MultipleChildren) {
@@ -180,25 +185,30 @@ TEST_F(ShaderMaskLayerTest, MultipleChildren) {
DlPaint filter_paint;
filter_paint.setBlendMode(DlBlendMode::kSrc);
filter_paint.setColorSource(dl_filter);
layer->Paint(paint_context());
EXPECT_EQ(
mock_canvas().draw_calls(),
std::vector({MockCanvas::DrawCall{
0, MockCanvas::SaveLayerData{children_bounds, DlPaint(),
nullptr, 1}},
MockCanvas::DrawCall{
1, MockCanvas::DrawPathData{child_path1, child_paint1}},
MockCanvas::DrawCall{
1, MockCanvas::DrawPathData{child_path2, child_paint2}},
MockCanvas::DrawCall{
1, MockCanvas::ConcatMatrixData{SkM44::Translate(
layer_bounds.fLeft, layer_bounds.fTop)}},
MockCanvas::DrawCall{
1, MockCanvas::DrawRectData{SkRect::MakeWH(
layer_bounds.width(),
layer_bounds.height()),
filter_paint}},
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}}));
layer->Paint(display_list_paint_context());
DisplayListBuilder expected_builder;
/* (ShaderMask)layer::Paint */ {
expected_builder.Save();
{
expected_builder.SaveLayer(&children_bounds);
{
/* mock_layer1::Paint */ {
expected_builder.DrawPath(child_path1, child_paint1);
}
/* mock_layer2::Paint */ {
expected_builder.DrawPath(child_path2, child_paint2);
}
expected_builder.Translate(layer_bounds.fLeft, layer_bounds.fTop);
expected_builder.DrawRect(
SkRect::MakeWH(layer_bounds.width(), layer_bounds.height()),
filter_paint);
}
expected_builder.Restore();
}
expected_builder.Restore();
}
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
}
TEST_F(ShaderMaskLayerTest, Nested) {
@@ -244,38 +254,44 @@ TEST_F(ShaderMaskLayerTest, Nested) {
filter_paint2.setBlendMode(DlBlendMode::kSrc);
filter_paint1.setColorSource(dl_filter1);
filter_paint2.setColorSource(dl_filter2);
layer1->Paint(paint_context());
EXPECT_EQ(
mock_canvas().draw_calls(),
std::vector(
{MockCanvas::DrawCall{
0, MockCanvas::SaveLayerData{children_bounds, DlPaint(), nullptr,
1}},
MockCanvas::DrawCall{
1, MockCanvas::DrawPathData{child_path1, child_paint1}},
MockCanvas::DrawCall{
1, MockCanvas::SaveLayerData{child_path2.getBounds(), DlPaint(),
nullptr, 2}},
MockCanvas::DrawCall{
2, MockCanvas::DrawPathData{child_path2, child_paint2}},
MockCanvas::DrawCall{2,
MockCanvas::ConcatMatrixData{SkM44::Translate(
layer_bounds.fLeft, layer_bounds.fTop)}},
MockCanvas::DrawCall{
2,
MockCanvas::DrawRectData{
SkRect::MakeWH(layer_bounds.width(), layer_bounds.height()),
filter_paint2}},
MockCanvas::DrawCall{2, MockCanvas::RestoreData{1}},
MockCanvas::DrawCall{1,
MockCanvas::ConcatMatrixData{SkM44::Translate(
layer_bounds.fLeft, layer_bounds.fTop)}},
MockCanvas::DrawCall{
1,
MockCanvas::DrawRectData{
SkRect::MakeWH(layer_bounds.width(), layer_bounds.height()),
filter_paint1}},
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}}));
layer1->Paint(display_list_paint_context());
DisplayListBuilder expected_builder;
/* (ShaderMask)layer1::Paint */ {
expected_builder.Save();
{
expected_builder.SaveLayer(&children_bounds);
{
/* mock_layer1::Paint */ {
expected_builder.DrawPath(child_path1, child_paint1);
}
/* (ShaderMask)layer2::Paint */ {
expected_builder.Save();
{
expected_builder.SaveLayer(&child_path2.getBounds());
{
/* mock_layer2::Paint */ {
expected_builder.DrawPath(child_path2, child_paint2);
}
expected_builder.Translate(layer_bounds.fLeft, layer_bounds.fTop);
expected_builder.DrawRect(
SkRect::MakeWH(layer_bounds.width(), layer_bounds.height()),
filter_paint2);
}
expected_builder.Restore();
}
expected_builder.Restore();
}
expected_builder.Translate(layer_bounds.fLeft, layer_bounds.fTop);
expected_builder.DrawRect(
SkRect::MakeWH(layer_bounds.width(), layer_bounds.height()),
filter_paint1);
}
expected_builder.Restore();
}
expected_builder.Restore();
}
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
}
TEST_F(ShaderMaskLayerTest, Readback) {
@@ -310,8 +326,8 @@ TEST_F(ShaderMaskLayerTest, LayerCached) {
layer->Add(mock_layer);
SkMatrix cache_ctm = initial_transform;
MockCanvas cache_canvas;
cache_canvas.SetTransform(cache_ctm);
DisplayListBuilder cache_canvas;
cache_canvas.Transform(cache_ctm);
use_mock_raster_cache();
preroll_context()->state_stack.set_preroll_delegate(initial_transform);
@@ -398,7 +414,7 @@ TEST_F(ShaderMaskLayerTest, OpacityInheritance) {
EXPECT_TRUE(DisplayListsEQ_Verbose(expected_builder.Build(), display_list()));
}
TEST_F(ShaderMaskLayerTest, SimpleFilterWithRasterCache) {
TEST_F(ShaderMaskLayerTest, SimpleFilterWithRasterCacheLayerNotCached) {
use_mock_raster_cache(); // Ensure non-fractional alignment.
const SkMatrix initial_transform = SkMatrix::Translate(0.5f, 1.0f);
@@ -418,27 +434,31 @@ TEST_F(ShaderMaskLayerTest, SimpleFilterWithRasterCache) {
DlPaint filter_paint;
filter_paint.setBlendMode(DlBlendMode::kSrc);
filter_paint.setColorSource(dl_filter);
layer->Paint(paint_context());
EXPECT_EQ(
mock_canvas().draw_calls(),
std::vector({MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
MockCanvas::DrawCall{1, MockCanvas::SetMatrixData{SkM44(
SkMatrix::Translate(0.0, 0.0))}},
MockCanvas::DrawCall{
1, MockCanvas::SaveLayerData{child_bounds, DlPaint(),
nullptr, 2}},
MockCanvas::DrawCall{
2, MockCanvas::DrawPathData{child_path, child_paint}},
MockCanvas::DrawCall{
2, MockCanvas::ConcatMatrixData{SkM44::Translate(
layer_bounds.fLeft, layer_bounds.fTop)}},
MockCanvas::DrawCall{
2, MockCanvas::DrawRectData{SkRect::MakeWH(
layer_bounds.width(),
layer_bounds.height()),
filter_paint}},
MockCanvas::DrawCall{2, MockCanvas::RestoreData{1}},
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}}));
layer->Paint(display_list_paint_context());
DisplayListBuilder expected_builder;
/* (ShaderMask)layer::Paint */ {
expected_builder.Save();
{
expected_builder.TransformReset();
// The layer will perform this Identity transform operation by default,
// but it should be ignored both here and in the layer paint
expected_builder.Transform(SkMatrix());
expected_builder.SaveLayer(&child_bounds);
{
/* mock_layer::Paint */ {
expected_builder.DrawPath(child_path, child_paint);
}
expected_builder.Translate(layer_bounds.fLeft, layer_bounds.fTop);
expected_builder.DrawRect(
SkRect::MakeWH(layer_bounds.width(), layer_bounds.height()),
filter_paint);
}
expected_builder.Restore();
}
expected_builder.Restore();
}
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
}
} // namespace testing

View File

@@ -8,7 +8,6 @@
#include "flutter/flow/testing/layer_test.h"
#include "flutter/flow/testing/mock_layer.h"
#include "flutter/fml/macros.h"
#include "flutter/testing/mock_canvas.h"
namespace flutter {
namespace testing {
@@ -59,10 +58,19 @@ TEST_F(TransformLayerTest, Identity) {
EXPECT_EQ(mock_layer->parent_cull_rect(), cull_rect);
EXPECT_EQ(mock_layer->parent_mutators(), MutatorsStack());
layer->Paint(paint_context());
EXPECT_EQ(mock_canvas().draw_calls(),
std::vector({MockCanvas::DrawCall{
0, MockCanvas::DrawPathData{child_path, DlPaint()}}}));
layer->Paint(display_list_paint_context());
DisplayListBuilder expected_builder;
/* (Transform)layer::Paint */ {
expected_builder.Save();
{
expected_builder.Transform(SkMatrix());
/* mock_layer::Paint */ {
expected_builder.DrawPath(child_path, DlPaint());
}
}
expected_builder.Restore();
}
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
}
TEST_F(TransformLayerTest, Simple) {
@@ -95,15 +103,19 @@ TEST_F(TransformLayerTest, Simple) {
EXPECT_EQ(mock_layer->parent_mutators(),
std::vector({Mutator(layer_transform)}));
layer->Paint(paint_context());
EXPECT_EQ(
mock_canvas().draw_calls(),
std::vector({MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
MockCanvas::DrawCall{
1, MockCanvas::ConcatMatrixData{SkM44(layer_transform)}},
MockCanvas::DrawCall{
1, MockCanvas::DrawPathData{child_path, DlPaint()}},
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}}));
layer->Paint(display_list_paint_context());
DisplayListBuilder expected_builder;
/* (Transform)layer::Paint */ {
expected_builder.Save();
{
expected_builder.Transform(layer_transform);
/* mock_layer::Paint */ {
expected_builder.DrawPath(child_path, DlPaint());
}
}
expected_builder.Restore();
}
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
}
TEST_F(TransformLayerTest, Nested) {
@@ -113,7 +125,7 @@ TEST_F(TransformLayerTest, Nested) {
SkRect local_cull_rect = SkRect::MakeXYWH(2.0f, 2.0f, 14.0f, 14.0f);
SkRect device_cull_rect = initial_transform.mapRect(local_cull_rect);
SkMatrix layer1_transform = SkMatrix::Translate(2.5f, 2.5f);
SkMatrix layer2_transform = SkMatrix::Translate(2.5f, 2.5f);
SkMatrix layer2_transform = SkMatrix::Translate(3.5f, 3.5f);
SkMatrix inverse_layer1_transform, inverse_layer2_transform;
EXPECT_TRUE(layer1_transform.invert(&inverse_layer1_transform));
EXPECT_TRUE(layer2_transform.invert(&inverse_layer2_transform));
@@ -146,21 +158,28 @@ TEST_F(TransformLayerTest, Nested) {
inverse_layer1_transform.mapRect(local_cull_rect)));
EXPECT_EQ(
mock_layer->parent_mutators(),
std::vector({Mutator(layer2_transform), Mutator(layer1_transform)}));
std::vector({Mutator(layer1_transform), Mutator(layer2_transform)}));
layer1->Paint(paint_context());
EXPECT_EQ(mock_canvas().draw_calls(),
std::vector(
{MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
MockCanvas::DrawCall{
1, MockCanvas::ConcatMatrixData{SkM44(layer1_transform)}},
MockCanvas::DrawCall{1, MockCanvas::SaveData{2}},
MockCanvas::DrawCall{
2, MockCanvas::ConcatMatrixData{SkM44(layer2_transform)}},
MockCanvas::DrawCall{
2, MockCanvas::DrawPathData{child_path, DlPaint()}},
MockCanvas::DrawCall{2, MockCanvas::RestoreData{1}},
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}}));
layer1->Paint(display_list_paint_context());
DisplayListBuilder expected_builder;
/* (Transform)layer1::Paint */ {
expected_builder.Save();
{
expected_builder.Transform(layer1_transform);
/* (Transform)layer1::Paint */ {
expected_builder.Save();
{
expected_builder.Transform(layer2_transform);
/* mock_layer::Paint */ {
expected_builder.DrawPath(child_path, DlPaint());
}
}
expected_builder.Restore();
}
}
expected_builder.Restore();
}
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
}
TEST_F(TransformLayerTest, NestedSeparated) {
@@ -170,15 +189,15 @@ TEST_F(TransformLayerTest, NestedSeparated) {
SkRect local_cull_rect = SkRect::MakeXYWH(2.0f, 2.0f, 14.0f, 14.0f);
SkRect device_cull_rect = initial_transform.mapRect(local_cull_rect);
SkMatrix layer1_transform = SkMatrix::Translate(2.5f, 2.5f);
SkMatrix layer2_transform = SkMatrix::Translate(2.5f, 2.5f);
SkMatrix layer2_transform = SkMatrix::Translate(3.5f, 3.5f);
SkMatrix inverse_layer1_transform, inverse_layer2_transform;
EXPECT_TRUE(layer1_transform.invert(&inverse_layer1_transform));
EXPECT_TRUE(layer2_transform.invert(&inverse_layer2_transform));
DlPaint child_paint1(DlColor::kBlue());
DlPaint child_paint2(DlColor::kGreen());
auto mock_layer1 =
std::make_shared<MockLayer>(child_path, DlPaint(DlColor::kBlue()));
auto mock_layer2 =
std::make_shared<MockLayer>(child_path, DlPaint(DlColor::kGreen()));
auto mock_layer1 = std::make_shared<MockLayer>(child_path, child_paint1);
auto mock_layer2 = std::make_shared<MockLayer>(child_path, child_paint2);
auto layer1 = std::make_shared<TransformLayer>(layer1_transform);
auto layer2 = std::make_shared<TransformLayer>(layer2_transform);
layer1->Add(mock_layer1);
@@ -219,25 +238,31 @@ TEST_F(TransformLayerTest, NestedSeparated) {
std::vector({Mutator(layer1_transform)}));
EXPECT_EQ(
mock_layer2->parent_mutators(),
std::vector({Mutator(layer2_transform), Mutator(layer1_transform)}));
std::vector({Mutator(layer1_transform), Mutator(layer2_transform)}));
layer1->Paint(paint_context());
EXPECT_EQ(mock_canvas().draw_calls(),
std::vector(
{MockCanvas::DrawCall{0, MockCanvas::SaveData{1}},
MockCanvas::DrawCall{
1, MockCanvas::ConcatMatrixData{SkM44(layer1_transform)}},
MockCanvas::DrawCall{
1, MockCanvas::DrawPathData{child_path,
DlPaint(DlColor::kBlue())}},
MockCanvas::DrawCall{1, MockCanvas::SaveData{2}},
MockCanvas::DrawCall{
2, MockCanvas::ConcatMatrixData{SkM44(layer2_transform)}},
MockCanvas::DrawCall{
2, MockCanvas::DrawPathData{child_path,
DlPaint(DlColor::kGreen())}},
MockCanvas::DrawCall{2, MockCanvas::RestoreData{1}},
MockCanvas::DrawCall{1, MockCanvas::RestoreData{0}}}));
layer1->Paint(display_list_paint_context());
DisplayListBuilder expected_builder;
/* (Transform)layer1::Paint */ {
expected_builder.Save();
{
expected_builder.Transform(layer1_transform);
/* mock_layer::Paint */ {
expected_builder.DrawPath(child_path, child_paint1);
}
/* (Transform)layer1::Paint */ {
expected_builder.Save();
{
expected_builder.Transform(layer2_transform);
/* mock_layer::Paint */ {
expected_builder.DrawPath(child_path, child_paint2);
}
}
expected_builder.Restore();
}
}
expected_builder.Restore();
}
EXPECT_TRUE(DisplayListsEQ_Verbose(display_list(), expected_builder.Build()));
}
TEST_F(TransformLayerTest, OpacityInheritance) {

View File

@@ -172,15 +172,19 @@ class LayerTestBase : public CanvasTestBase<BaseT> {
sk_sp<DisplayList> display_list() {
if (display_list_ == nullptr) {
// null out the canvas and recorder fields of the PaintContext
// and the delegate of the state_stack to prevent future use.
display_list_paint_context_.state_stack.clear_delegate();
display_list_paint_context_.canvas = nullptr;
display_list_ = display_list_builder_.Build();
}
return display_list_;
}
void reset_display_list() {
display_list_ = nullptr;
// Build() will leave the builder in a state to start recording a new DL
display_list_builder_.Build();
// Make sure we are starting from a fresh state stack
FML_DCHECK(display_list_state_stack_.is_empty());
}
void enable_leaf_layer_tracing() {
paint_context_.enable_leaf_layer_tracing = true;
paint_context_.layer_snapshot_store = &snapshot_store_;

View File

@@ -159,8 +159,6 @@ class MockCanvas final : public DlCanvas {
MockCanvas(int width, int height);
~MockCanvas();
// SkNWayCanvas* internal_canvas() { return &internal_canvas_; }
const std::vector<DrawCall>& draw_calls() const { return draw_calls_; }
void reset_draw_calls() { draw_calls_.clear(); }