[Impeller] move more aiks tests to DL. (flutter/engine#53792)

Move more impeller tests to display list format. This allows our integration tests to also test the display list -> aiks interop and be future compatible with the new canvas backend that removes AIKS.

Part of https://github.com/flutter/flutter/issues/142054
This commit is contained in:
Jonah Williams 2024-07-11 11:35:52 -07:00 committed by GitHub
parent 902e78dd2a
commit c04f249ca0
5 changed files with 476 additions and 351 deletions

View File

@ -145,6 +145,7 @@
../../../flutter/impeller/display_list/aiks_dl_gradient_unittests.cc ../../../flutter/impeller/display_list/aiks_dl_gradient_unittests.cc
../../../flutter/impeller/display_list/aiks_dl_opacity_unittests.cc ../../../flutter/impeller/display_list/aiks_dl_opacity_unittests.cc
../../../flutter/impeller/display_list/aiks_dl_path_unittests.cc ../../../flutter/impeller/display_list/aiks_dl_path_unittests.cc
../../../flutter/impeller/display_list/aiks_dl_unittests.cc
../../../flutter/impeller/display_list/aiks_dl_vertices_unittests.cc ../../../flutter/impeller/display_list/aiks_dl_vertices_unittests.cc
../../../flutter/impeller/display_list/dl_golden_blur_unittests.cc ../../../flutter/impeller/display_list/dl_golden_blur_unittests.cc
../../../flutter/impeller/display_list/dl_golden_unittests.cc ../../../flutter/impeller/display_list/dl_golden_unittests.cc

View File

@ -32,8 +32,9 @@ struct DlColor {
static constexpr DlColor kLightGrey() {return DlColor(0xFFC0C0C0);}; static constexpr DlColor kLightGrey() {return DlColor(0xFFC0C0C0);};
static constexpr DlColor kAliceBlue() {return DlColor(0xFFF0F8FF);}; static constexpr DlColor kAliceBlue() {return DlColor(0xFFF0F8FF);};
static constexpr DlColor kFuchsia() {return DlColor(0xFFFF00FF);}; static constexpr DlColor kFuchsia() {return DlColor(0xFFFF00FF);};
static constexpr DlColor kMaroon() {return DlColor(0xFF800000);} static constexpr DlColor kMaroon() {return DlColor(0xFF800000);};
static constexpr DlColor kSkyBlue() {return DlColor(0xFF87CEEB);} static constexpr DlColor kSkyBlue() {return DlColor(0xFF87CEEB);};
static constexpr DlColor kCornflowerBlue() {return DlColor(0xFF6495ED);};
// clang-format on // clang-format on
constexpr bool isOpaque() const { return getAlpha() == 0xFF; } constexpr bool isOpaque() const { return getAlpha() == 0xFF; }

View File

@ -1758,143 +1758,6 @@ TEST_P(AiksTest, ClearColorOptimizationDoesNotApplyForBackdropFilters) {
EXPECT_FALSE(actual_color.has_value()); EXPECT_FALSE(actual_color.has_value());
} }
TEST_P(AiksTest, CollapsedDrawPaintInSubpass) {
Canvas canvas;
canvas.DrawPaint(
{.color = Color::Yellow(), .blend_mode = BlendMode::kSource});
canvas.SaveLayer({.blend_mode = BlendMode::kMultiply});
canvas.DrawPaint({.color = Color::CornflowerBlue().WithAlpha(0.75),
.blend_mode = BlendMode::kSourceOver});
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}
TEST_P(AiksTest, CollapsedDrawPaintInSubpassBackdropFilter) {
// Bug: https://github.com/flutter/flutter/issues/131576
Canvas canvas;
canvas.DrawPaint(
{.color = Color::Yellow(), .blend_mode = BlendMode::kSource});
canvas.SaveLayer({}, {},
ImageFilter::MakeBlur(Sigma(20.0), Sigma(20.0),
FilterContents::BlurStyle::kNormal,
Entity::TileMode::kDecal));
canvas.DrawPaint(
{.color = Color::CornflowerBlue(), .blend_mode = BlendMode::kSourceOver});
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}
TEST_P(AiksTest, ColorMatrixFilterSubpassCollapseOptimization) {
Canvas canvas;
canvas.SaveLayer({
.color_filter =
ColorFilter::MakeMatrix({.array =
{
-1.0, 0, 0, 1.0, 0, //
0, -1.0, 0, 1.0, 0, //
0, 0, -1.0, 1.0, 0, //
1.0, 1.0, 1.0, 1.0, 0 //
}}),
});
canvas.Translate({500, 300, 0});
canvas.Rotate(Radians(2 * kPi / 3));
canvas.DrawRect(Rect::MakeXYWH(100, 100, 200, 200), {.color = Color::Blue()});
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}
TEST_P(AiksTest, LinearToSrgbFilterSubpassCollapseOptimization) {
Canvas canvas;
canvas.SaveLayer({
.color_filter = ColorFilter::MakeLinearToSrgb(),
});
canvas.Translate({500, 300, 0});
canvas.Rotate(Radians(2 * kPi / 3));
canvas.DrawRect(Rect::MakeXYWH(100, 100, 200, 200), {.color = Color::Blue()});
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}
TEST_P(AiksTest, SrgbToLinearFilterSubpassCollapseOptimization) {
Canvas canvas;
canvas.SaveLayer({
.color_filter = ColorFilter::MakeSrgbToLinear(),
});
canvas.Translate({500, 300, 0});
canvas.Rotate(Radians(2 * kPi / 3));
canvas.DrawRect(Rect::MakeXYWH(100, 100, 200, 200), {.color = Color::Blue()});
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}
TEST_P(AiksTest, TranslucentSaveLayerDrawsCorrectly) {
Canvas canvas;
canvas.DrawRect(Rect::MakeXYWH(100, 100, 300, 300), {.color = Color::Blue()});
canvas.SaveLayer({.color = Color::Black().WithAlpha(0.5)});
canvas.DrawRect(Rect::MakeXYWH(100, 500, 300, 300), {.color = Color::Blue()});
canvas.Restore();
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}
TEST_P(AiksTest, TranslucentSaveLayerWithBlendColorFilterDrawsCorrectly) {
Canvas canvas;
canvas.DrawRect(Rect::MakeXYWH(100, 100, 300, 300), {.color = Color::Blue()});
canvas.SaveLayer({
.color = Color::Black().WithAlpha(0.5),
.color_filter =
ColorFilter::MakeBlend(BlendMode::kDestinationOver, Color::Red()),
});
canvas.DrawRect(Rect::MakeXYWH(100, 500, 300, 300), {.color = Color::Blue()});
canvas.Restore();
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}
TEST_P(AiksTest, TranslucentSaveLayerWithBlendImageFilterDrawsCorrectly) {
Canvas canvas;
canvas.DrawRect(Rect::MakeXYWH(100, 100, 300, 300), {.color = Color::Blue()});
canvas.SaveLayer({
.color = Color::Black().WithAlpha(0.5),
.image_filter = ImageFilter::MakeFromColorFilter(
*ColorFilter::MakeBlend(BlendMode::kDestinationOver, Color::Red())),
});
canvas.DrawRect(Rect::MakeXYWH(100, 500, 300, 300), {.color = Color::Blue()});
canvas.Restore();
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}
TEST_P(AiksTest, TranslucentSaveLayerWithColorAndImageFilterDrawsCorrectly) {
Canvas canvas;
canvas.DrawRect(Rect::MakeXYWH(100, 100, 300, 300), {.color = Color::Blue()});
canvas.SaveLayer({
.color = Color::Black().WithAlpha(0.5),
.color_filter =
ColorFilter::MakeBlend(BlendMode::kDestinationOver, Color::Red()),
});
canvas.DrawRect(Rect::MakeXYWH(100, 500, 300, 300), {.color = Color::Blue()});
canvas.Restore();
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}
TEST_P(AiksTest, ImageFilteredSaveLayerWithUnboundedContents) { TEST_P(AiksTest, ImageFilteredSaveLayerWithUnboundedContents) {
Canvas canvas; Canvas canvas;
canvas.Scale(GetContentScale()); canvas.Scale(GetContentScale());
@ -1984,144 +1847,6 @@ TEST_P(AiksTest, ImageFilteredSaveLayerWithUnboundedContents) {
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
} }
TEST_P(AiksTest, ImageFilteredUnboundedSaveLayerWithUnboundedContents) {
Canvas canvas;
canvas.Scale(GetContentScale());
auto blur_filter = ImageFilter::MakeBlur(Sigma{10.0}, Sigma{10.0},
FilterContents::BlurStyle::kNormal,
Entity::TileMode::kDecal);
canvas.SaveLayer({.image_filter = blur_filter}, std::nullopt);
{
// DrawPaint to verify correct behavior when the contents are unbounded.
canvas.DrawPaint({.color = Color::Yellow()});
// Contrasting rectangle to see interior blurring
canvas.DrawRect(Rect::MakeLTRB(125, 125, 175, 175),
{.color = Color::Blue()});
}
canvas.Restore();
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}
TEST_P(AiksTest, TranslucentSaveLayerImageDrawsCorrectly) {
Canvas canvas;
auto image = std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
canvas.DrawImage(image, {100, 100}, {});
canvas.SaveLayer({.color = Color::Black().WithAlpha(0.5)});
canvas.DrawImage(image, {100, 500}, {});
canvas.Restore();
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}
TEST_P(AiksTest, TranslucentSaveLayerWithColorMatrixColorFilterDrawsCorrectly) {
Canvas canvas;
auto image = std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
canvas.DrawImage(image, {100, 100}, {});
canvas.SaveLayer({
.color = Color::Black().WithAlpha(0.5),
.color_filter = ColorFilter::MakeMatrix({.array =
{
1, 0, 0, 0, 0, //
0, 1, 0, 0, 0, //
0, 0, 1, 0, 0, //
0, 0, 0, 2, 0 //
}}),
});
canvas.DrawImage(image, {100, 500}, {});
canvas.Restore();
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}
TEST_P(AiksTest, TranslucentSaveLayerWithColorMatrixImageFilterDrawsCorrectly) {
Canvas canvas;
auto image = std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
canvas.DrawImage(image, {100, 100}, {});
canvas.SaveLayer({
.color = Color::Black().WithAlpha(0.5),
.image_filter = ImageFilter::MakeFromColorFilter(
*ColorFilter::MakeMatrix({.array =
{
1, 0, 0, 0, 0, //
0, 1, 0, 0, 0, //
0, 0, 1, 0, 0, //
0, 0, 0, 2, 0 //
}})),
});
canvas.DrawImage(image, {100, 500}, {});
canvas.Restore();
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}
TEST_P(AiksTest,
TranslucentSaveLayerWithColorFilterAndImageFilterDrawsCorrectly) {
Canvas canvas;
auto image = std::make_shared<Image>(CreateTextureForFixture("airplane.jpg"));
canvas.DrawImage(image, {100, 100}, {});
canvas.SaveLayer({
.color = Color::Black().WithAlpha(0.5),
.image_filter = ImageFilter::MakeFromColorFilter(
*ColorFilter::MakeMatrix({.array =
{
1, 0, 0, 0, 0, //
0, 1, 0, 0, 0, //
0, 0.2, 1, 0, 0, //
0, 0, 0, 0.5, 0 //
}})),
.color_filter =
ColorFilter::MakeBlend(BlendMode::kModulate, Color::Green()),
});
canvas.DrawImage(image, {100, 500}, {});
canvas.Restore();
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}
TEST_P(AiksTest, TranslucentSaveLayerWithAdvancedBlendModeDrawsCorrectly) {
Canvas canvas;
canvas.DrawRect(Rect::MakeXYWH(0, 0, 400, 400), {.color = Color::Red()});
canvas.SaveLayer({
.color = Color::Black().WithAlpha(0.5),
.blend_mode = BlendMode::kLighten,
});
canvas.DrawCircle({200, 200}, 100, {.color = Color::Green()});
canvas.Restore();
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}
/// This is a regression check for https://github.com/flutter/engine/pull/41129
/// The entire screen is green if successful. If failing, no frames will render,
/// or the entire screen will be transparent black.
TEST_P(AiksTest, CanRenderTinyOverlappingSubpasses) {
Canvas canvas;
canvas.DrawPaint({.color = Color::Red()});
// Draw two overlapping subpixel circles.
canvas.SaveLayer({});
canvas.DrawCircle({100, 100}, 0.1, {.color = Color::Yellow()});
canvas.Restore();
canvas.SaveLayer({});
canvas.DrawCircle({100, 100}, 0.1, {.color = Color::Yellow()});
canvas.Restore();
canvas.DrawPaint({.color = Color::Green()});
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}
TEST_P(AiksTest, OpaqueEntitiesGetCoercedToSource) { TEST_P(AiksTest, OpaqueEntitiesGetCoercedToSource) {
Canvas canvas; Canvas canvas;
canvas.Scale(Vector2(1.618, 1.618)); canvas.Scale(Vector2(1.618, 1.618));
@ -2151,20 +1876,6 @@ TEST_P(AiksTest, OpaqueEntitiesGetCoercedToSource) {
ASSERT_EQ(entity[0].GetBlendMode(), BlendMode::kSource); ASSERT_EQ(entity[0].GetBlendMode(), BlendMode::kSource);
} }
TEST_P(AiksTest, CanRenderDestructiveSaveLayer) {
Canvas canvas;
canvas.DrawPaint({.color = Color::Red()});
// Draw an empty savelayer with a destructive blend mode, which will replace
// the entire red screen with fully transparent black, except for the green
// circle drawn within the layer.
canvas.SaveLayer({.blend_mode = BlendMode::kSource});
canvas.DrawCircle({300, 300}, 100, {.color = Color::Green()});
canvas.Restore();
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}
// Regression test for https://github.com/flutter/flutter/issues/126701 . // Regression test for https://github.com/flutter/flutter/issues/126701 .
TEST_P(AiksTest, CanRenderClippedRuntimeEffects) { TEST_P(AiksTest, CanRenderClippedRuntimeEffects) {
auto runtime_stages = auto runtime_stages =
@ -2228,66 +1939,6 @@ TEST_P(AiksTest, DrawPaintTransformsBounds) {
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
} }
TEST_P(AiksTest, CanDrawPoints) {
std::vector<Point> points = {
{0, 0}, //
{100, 100}, //
{100, 0}, //
{0, 100}, //
{0, 0}, //
{48, 48}, //
{52, 52}, //
};
std::vector<PointStyle> caps = {
PointStyle::kRound,
PointStyle::kSquare,
};
Paint paint;
paint.color = Color::Yellow().WithAlpha(0.5);
Paint background;
background.color = Color::Black();
Canvas canvas;
canvas.DrawPaint(background);
canvas.Translate({200, 200});
canvas.DrawPoints(points, 10, paint, PointStyle::kRound);
canvas.Translate({150, 0});
canvas.DrawPoints(points, 10, paint, PointStyle::kSquare);
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}
TEST_P(AiksTest, CanDrawPointsWithTextureMap) {
auto texture = CreateTextureForFixture("table_mountain_nx.png",
/*enable_mipmapping=*/true);
std::vector<Point> points = {
{0, 0}, //
{100, 100}, //
{100, 0}, //
{0, 100}, //
{0, 0}, //
{48, 48}, //
{52, 52}, //
};
std::vector<PointStyle> caps = {
PointStyle::kRound,
PointStyle::kSquare,
};
Paint paint;
paint.color_source = ColorSource::MakeImage(texture, Entity::TileMode::kClamp,
Entity::TileMode::kClamp, {}, {});
Canvas canvas;
canvas.Translate({200, 200});
canvas.DrawPoints(points, 100, paint, PointStyle::kRound);
canvas.Translate({150, 0});
canvas.DrawPoints(points, 100, paint, PointStyle::kSquare);
ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture()));
}
// This currently renders solid blue, as the support for text color sources was // This currently renders solid blue, as the support for text color sources was
// moved into DLDispatching. Path data requires the SkTextBlobs which are not // moved into DLDispatching. Path data requires the SkTextBlobs which are not
// used in impeller::TextFrames. // used in impeller::TextFrames.

View File

@ -57,6 +57,7 @@ template("display_list_unittests_component") {
"aiks_dl_gradient_unittests.cc", "aiks_dl_gradient_unittests.cc",
"aiks_dl_opacity_unittests.cc", "aiks_dl_opacity_unittests.cc",
"aiks_dl_path_unittests.cc", "aiks_dl_path_unittests.cc",
"aiks_dl_unittests.cc",
"aiks_dl_vertices_unittests.cc", "aiks_dl_vertices_unittests.cc",
"dl_golden_blur_unittests.cc", "dl_golden_blur_unittests.cc",
"dl_golden_unittests.cc", "dl_golden_unittests.cc",

View File

@ -0,0 +1,471 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "display_list/dl_sampling_options.h"
#include "display_list/dl_tile_mode.h"
#include "display_list/effects/dl_color_filter.h"
#include "display_list/effects/dl_color_source.h"
#include "display_list/effects/dl_image_filter.h"
#include "display_list/geometry/dl_geometry_types.h"
#include "display_list/image/dl_image.h"
#include "flutter/impeller/aiks/aiks_unittests.h"
#include "flutter/display_list/dl_blend_mode.h"
#include "flutter/display_list/dl_builder.h"
#include "flutter/display_list/dl_color.h"
#include "flutter/display_list/dl_paint.h"
#include "flutter/testing/testing.h"
#include "imgui.h"
#include "impeller/display_list/dl_image_impeller.h"
#include "impeller/geometry/scalar.h"
#include "include/core/SkRSXform.h"
#include "include/core/SkRefCnt.h"
namespace impeller {
namespace testing {
using namespace flutter;
namespace {
SkRect GetCullRect(ISize window_size) {
return SkRect::MakeSize(SkSize::Make(window_size.width, window_size.height));
}
} // namespace
TEST_P(AiksTest, CollapsedDrawPaintInSubpass) {
DisplayListBuilder builder(GetCullRect(GetWindowSize()));
DlPaint paint;
paint.setColor(DlColor::kYellow());
paint.setBlendMode(DlBlendMode::kSrc);
builder.DrawPaint(paint);
DlPaint save_paint;
save_paint.setBlendMode(DlBlendMode::kMultiply);
builder.SaveLayer(nullptr, &save_paint);
DlPaint draw_paint;
draw_paint.setColor(DlColor::kCornflowerBlue().modulateOpacity(0.75f));
builder.DrawPaint(draw_paint);
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
TEST_P(AiksTest, CollapsedDrawPaintInSubpassBackdropFilter) {
// Bug: https://github.com/flutter/flutter/issues/131576
DisplayListBuilder builder(GetCullRect(GetWindowSize()));
DlPaint paint;
paint.setColor(DlColor::kYellow());
paint.setBlendMode(DlBlendMode::kSrc);
builder.DrawPaint(paint);
auto filter = DlBlurImageFilter::Make(20.0, 20.0, DlTileMode::kDecal);
builder.SaveLayer(nullptr, nullptr, filter.get());
DlPaint draw_paint;
draw_paint.setColor(DlColor::kCornflowerBlue());
builder.DrawPaint(draw_paint);
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
TEST_P(AiksTest, ColorMatrixFilterSubpassCollapseOptimization) {
DisplayListBuilder builder(GetCullRect(GetWindowSize()));
const float matrix[20] = {
-1.0, 0, 0, 1.0, 0, //
0, -1.0, 0, 1.0, 0, //
0, 0, -1.0, 1.0, 0, //
1.0, 1.0, 1.0, 1.0, 0 //
};
auto filter = DlMatrixColorFilter::Make(matrix);
DlPaint paint;
paint.setColorFilter(filter);
builder.SaveLayer(nullptr, &paint);
builder.Translate(500, 300);
builder.Rotate(120); // 120 deg
DlPaint draw_paint;
draw_paint.setColor(DlColor::kBlue());
builder.DrawRect(SkRect::MakeXYWH(100, 100, 200, 200), draw_paint);
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
TEST_P(AiksTest, LinearToSrgbFilterSubpassCollapseOptimization) {
DisplayListBuilder builder(GetCullRect(GetWindowSize()));
DlPaint paint;
paint.setColorFilter(DlLinearToSrgbGammaColorFilter::kInstance);
builder.SaveLayer(nullptr, &paint);
builder.Translate(500, 300);
builder.Rotate(120); // 120 deg.
DlPaint draw_paint;
draw_paint.setColor(DlColor::kBlue());
builder.DrawRect(SkRect::MakeXYWH(100, 100, 200, 200), draw_paint);
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
TEST_P(AiksTest, SrgbToLinearFilterSubpassCollapseOptimization) {
DisplayListBuilder builder(GetCullRect(GetWindowSize()));
DlPaint paint;
paint.setColorFilter(DlLinearToSrgbGammaColorFilter::kInstance);
builder.SaveLayer(nullptr, &paint);
builder.Translate(500, 300);
builder.Rotate(120); // 120 deg
DlPaint draw_paint;
draw_paint.setColor(DlColor::kBlue());
builder.DrawRect(SkRect::MakeXYWH(100, 100, 200, 200), draw_paint);
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
TEST_P(AiksTest, TranslucentSaveLayerDrawsCorrectly) {
DisplayListBuilder builder(GetCullRect(GetWindowSize()));
DlPaint paint;
paint.setColor(DlColor::kBlue());
builder.DrawRect(SkRect::MakeXYWH(100, 100, 300, 300), paint);
DlPaint save_paint;
save_paint.setColor(DlColor::kBlack().withAlpha(128));
builder.SaveLayer(nullptr, &save_paint);
builder.DrawRect(SkRect::MakeXYWH(100, 500, 300, 300), paint);
builder.Restore();
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
TEST_P(AiksTest, TranslucentSaveLayerWithBlendColorFilterDrawsCorrectly) {
DisplayListBuilder builder(GetCullRect(GetWindowSize()));
DlPaint paint;
paint.setColor(DlColor::kBlue());
builder.DrawRect(SkRect::MakeXYWH(100, 100, 300, 300), paint);
DlPaint save_paint;
paint.setColor(DlColor::kBlack().withAlpha(128));
paint.setColorFilter(
DlBlendColorFilter::Make(DlColor::kRed(), DlBlendMode::kDstOver));
builder.SaveLayer(nullptr, &paint);
DlPaint draw_paint;
draw_paint.setColor(DlColor::kBlue());
builder.DrawRect(SkRect::MakeXYWH(100, 500, 300, 300), draw_paint);
builder.Restore();
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
TEST_P(AiksTest, TranslucentSaveLayerWithBlendImageFilterDrawsCorrectly) {
DisplayListBuilder builder(GetCullRect(GetWindowSize()));
DlPaint paint;
paint.setColor(DlColor::kBlue());
builder.DrawRect(SkRect::MakeXYWH(100, 100, 300, 300), paint);
DlPaint save_paint;
save_paint.setColor(DlColor::kBlack().withAlpha(128));
save_paint.setImageFilter(DlColorFilterImageFilter::Make(
DlBlendColorFilter::Make(DlColor::kRed(), DlBlendMode::kDstOver)));
builder.SaveLayer(nullptr, &save_paint);
DlPaint draw_paint;
draw_paint.setColor(DlColor::kBlue());
builder.DrawRect(SkRect::MakeXYWH(100, 500, 300, 300), draw_paint);
builder.Restore();
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
TEST_P(AiksTest, TranslucentSaveLayerWithColorAndImageFilterDrawsCorrectly) {
DisplayListBuilder builder(GetCullRect(GetWindowSize()));
DlPaint paint;
paint.setColor(DlColor::kBlue());
builder.DrawRect(SkRect::MakeXYWH(100, 100, 300, 300), paint);
DlPaint save_paint;
save_paint.setColor(DlColor::kBlack().withAlpha(128));
save_paint.setColorFilter(
DlBlendColorFilter::Make(DlColor::kRed(), DlBlendMode::kDstOver));
builder.SaveLayer(nullptr, &save_paint);
DlPaint draw_paint;
draw_paint.setColor(DlColor::kBlue());
builder.DrawRect(SkRect::MakeXYWH(100, 500, 300, 300), draw_paint);
builder.Restore();
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
TEST_P(AiksTest, ImageFilteredUnboundedSaveLayerWithUnboundedContents) {
DisplayListBuilder builder(GetCullRect(GetWindowSize()));
builder.Scale(GetContentScale().x, GetContentScale().y);
DlPaint save_paint;
save_paint.setImageFilter(
DlBlurImageFilter::Make(10.0, 10.0, DlTileMode::kDecal));
builder.SaveLayer(nullptr, &save_paint);
{
// DrawPaint to verify correct behavior when the contents are unbounded.
DlPaint draw_paint;
draw_paint.setColor(DlColor::kYellow());
builder.DrawPaint(draw_paint);
// Contrasting rectangle to see interior blurring
DlPaint draw_rect;
draw_rect.setColor(DlColor::kBlue());
builder.DrawRect(SkRect::MakeLTRB(125, 125, 175, 175), draw_rect);
}
builder.Restore();
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
TEST_P(AiksTest, TranslucentSaveLayerImageDrawsCorrectly) {
DisplayListBuilder builder(GetCullRect(GetWindowSize()));
auto image = DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
builder.DrawImage(image, {100, 100}, DlImageSampling::kMipmapLinear);
DlPaint paint;
paint.setColor(DlColor::kBlack().withAlpha(128));
builder.SaveLayer(nullptr, &paint);
builder.DrawImage(image, {100, 500}, DlImageSampling::kMipmapLinear);
builder.Restore();
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
TEST_P(AiksTest, TranslucentSaveLayerWithColorMatrixColorFilterDrawsCorrectly) {
DisplayListBuilder builder(GetCullRect(GetWindowSize()));
auto image = DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
builder.DrawImage(image, {100, 100}, {});
const float matrix[20] = {
1, 0, 0, 0, 0, //
0, 1, 0, 0, 0, //
0, 0, 1, 0, 0, //
0, 0, 0, 2, 0 //
};
DlPaint paint;
paint.setColor(DlColor::kBlack().withAlpha(128));
paint.setColorFilter(DlMatrixColorFilter::Make(matrix));
builder.SaveLayer(nullptr, &paint);
builder.DrawImage(image, {100, 500}, {});
builder.Restore();
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
TEST_P(AiksTest, TranslucentSaveLayerWithColorMatrixImageFilterDrawsCorrectly) {
DisplayListBuilder builder(GetCullRect(GetWindowSize()));
auto image = DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
builder.DrawImage(image, {100, 100}, {});
const float matrix[20] = {
1, 0, 0, 0, 0, //
0, 1, 0, 0, 0, //
0, 0, 1, 0, 0, //
0, 0, 0, 2, 0 //
};
DlPaint paint;
paint.setColor(DlColor::kBlack().withAlpha(128));
paint.setColorFilter(DlMatrixColorFilter::Make(matrix));
builder.SaveLayer(nullptr, &paint);
builder.DrawImage(image, {100, 500}, {});
builder.Restore();
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
TEST_P(AiksTest,
TranslucentSaveLayerWithColorFilterAndImageFilterDrawsCorrectly) {
DisplayListBuilder builder(GetCullRect(GetWindowSize()));
auto image = DlImageImpeller::Make(CreateTextureForFixture("airplane.jpg"));
builder.DrawImage(image, {100, 100}, {});
const float matrix[20] = {
1, 0, 0, 0, 0, //
0, 1, 0, 0, 0, //
0, 0.2, 1, 0, 0, //
0, 0, 0, 0.5, 0 //
};
DlPaint paint;
paint.setColor(DlColor::kBlack().withAlpha(128));
paint.setImageFilter(
DlColorFilterImageFilter::Make(DlMatrixColorFilter::Make(matrix)));
paint.setColorFilter(
DlBlendColorFilter::Make(DlColor::kGreen(), DlBlendMode::kModulate));
builder.SaveLayer(nullptr, &paint);
builder.DrawImage(image, {100, 500}, {});
builder.Restore();
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
TEST_P(AiksTest, TranslucentSaveLayerWithAdvancedBlendModeDrawsCorrectly) {
DisplayListBuilder builder(GetCullRect(GetWindowSize()));
DlPaint paint;
paint.setColor(DlColor::kRed());
builder.DrawRect(SkRect::MakeXYWH(0, 0, 400, 400), paint);
DlPaint save_paint;
save_paint.setAlpha(128);
save_paint.setBlendMode(DlBlendMode::kLighten);
builder.SaveLayer(nullptr, &save_paint);
DlPaint draw_paint;
draw_paint.setColor(DlColor::kGreen());
builder.DrawCircle({200, 200}, 100, draw_paint);
builder.Restore();
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
/// This is a regression check for https://github.com/flutter/engine/pull/41129
/// The entire screen is green if successful. If failing, no frames will render,
/// or the entire screen will be transparent black.
TEST_P(AiksTest, CanRenderTinyOverlappingSubpasses) {
DisplayListBuilder builder(GetCullRect(GetWindowSize()));
DlPaint paint;
paint.setColor(DlColor::kRed());
builder.DrawPaint(paint);
// Draw two overlapping subpixel circles.
builder.SaveLayer({});
DlPaint yellow_paint;
yellow_paint.setColor(DlColor::kYellow());
builder.DrawCircle({100, 100}, 0.1, yellow_paint);
builder.Restore();
builder.SaveLayer({});
builder.DrawCircle({100, 100}, 0.1, yellow_paint);
builder.Restore();
DlPaint draw_paint;
draw_paint.setColor(DlColor::kGreen());
builder.DrawPaint(draw_paint);
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
TEST_P(AiksTest, CanRenderDestructiveSaveLayer) {
DisplayListBuilder builder(GetCullRect(GetWindowSize()));
DlPaint paint;
paint.setColor(DlColor::kRed());
builder.DrawPaint(paint);
// Draw an empty savelayer with a destructive blend mode, which will replace
// the entire red screen with fully transparent black, except for the green
// circle drawn within the layer.
DlPaint save_paint;
save_paint.setBlendMode(DlBlendMode::kSrc);
builder.SaveLayer(nullptr, &save_paint);
DlPaint draw_paint;
draw_paint.setColor(DlColor::kGreen());
builder.DrawCircle({300, 300}, 100, draw_paint);
builder.Restore();
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
TEST_P(AiksTest, CanDrawPoints) {
std::vector<SkPoint> points = {
{0, 0}, //
{100, 100}, //
{100, 0}, //
{0, 100}, //
{0, 0}, //
{48, 48}, //
{52, 52}, //
};
DlPaint paint_round;
paint_round.setColor(DlColor::kYellow().withAlpha(128));
paint_round.setStrokeCap(DlStrokeCap::kRound);
paint_round.setStrokeWidth(20);
DlPaint paint_square;
paint_square.setColor(DlColor::kYellow().withAlpha(128));
paint_square.setStrokeCap(DlStrokeCap::kSquare);
paint_square.setStrokeWidth(20);
DlPaint background;
background.setColor(DlColor::kBlack());
DisplayListBuilder builder(GetCullRect(GetWindowSize()));
builder.DrawPaint(background);
builder.Translate(200, 200);
builder.DrawPoints(DlCanvas::PointMode::kPoints, points.size(), points.data(),
paint_round);
builder.Translate(150, 0);
builder.DrawPoints(DlCanvas::PointMode::kPoints, points.size(), points.data(),
paint_square);
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
TEST_P(AiksTest, CanDrawPointsWithTextureMap) {
auto texture = DlImageImpeller::Make(
CreateTextureForFixture("table_mountain_nx.png",
/*enable_mipmapping=*/true));
std::vector<SkPoint> points = {
{0, 0}, //
{100, 100}, //
{100, 0}, //
{0, 100}, //
{0, 0}, //
{48, 48}, //
{52, 52}, //
};
auto image_src = std::make_shared<DlImageColorSource>(
texture, DlTileMode::kClamp, DlTileMode::kClamp);
DlPaint paint_round;
paint_round.setStrokeCap(DlStrokeCap::kRound);
paint_round.setColorSource(image_src);
paint_round.setStrokeWidth(200);
DlPaint paint_square;
paint_square.setStrokeCap(DlStrokeCap::kSquare);
paint_square.setColorSource(image_src);
paint_square.setStrokeWidth(200);
DisplayListBuilder builder(GetCullRect(GetWindowSize()));
builder.Translate(200, 200);
builder.DrawPoints(DlCanvas::PointMode::kPoints, points.size(), points.data(),
paint_round);
builder.Translate(150, 0);
builder.DrawPoints(DlCanvas::PointMode::kPoints, points.size(), points.data(),
paint_square);
ASSERT_TRUE(OpenPlaygroundHere(builder.Build()));
}
} // namespace testing
} // namespace impeller