Flutter Engine
 
Loading...
Searching...
No Matches
dl_rendering_unittests.cc File Reference
#include <utility>
#include "flutter/display_list/display_list.h"
#include "flutter/display_list/dl_builder.h"
#include "flutter/display_list/dl_op_flags.h"
#include "flutter/display_list/dl_sampling_options.h"
#include "flutter/display_list/dl_text_skia.h"
#include "flutter/display_list/effects/color_filters/dl_matrix_color_filter.h"
#include "flutter/display_list/effects/dl_image_filter.h"
#include "flutter/display_list/geometry/dl_geometry_conversions.h"
#include "flutter/display_list/geometry/dl_path_builder.h"
#include "flutter/display_list/skia/dl_sk_canvas.h"
#include "flutter/display_list/skia/dl_sk_conversions.h"
#include "flutter/display_list/skia/dl_sk_dispatcher.h"
#include "flutter/display_list/testing/dl_test_snippets.h"
#include "flutter/display_list/testing/dl_test_surface_provider.h"
#include "flutter/display_list/utils/dl_comparable.h"
#include "flutter/fml/file.h"
#include "flutter/fml/math.h"
#include "flutter/testing/display_list_testing.h"
#include "flutter/testing/testing.h"
#include "third_party/skia/include/core/SkBBHFactory.h"
#include "third_party/skia/include/core/SkColorFilter.h"
#include "third_party/skia/include/core/SkColorSpace.h"
#include "third_party/skia/include/core/SkFontMgr.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"
#include "third_party/skia/include/core/SkStream.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/core/SkTypeface.h"
#include "third_party/skia/include/effects/SkDashPathEffect.h"
#include "third_party/skia/include/effects/SkGradientShader.h"
#include "third_party/skia/include/effects/SkImageFilters.h"
#include "third_party/skia/include/encode/SkPngEncoder.h"
#include "third_party/skia/include/gpu/ganesh/GrDirectContext.h"
#include "third_party/skia/include/gpu/ganesh/GrRecordingContext.h"
#include "third_party/skia/include/gpu/ganesh/GrTypes.h"
#include "txt/platform.h"

Go to the source code of this file.

Classes

class  flutter::testing::SkImageSampling
 
class  flutter::testing::OncePerBackendWarning
 
class  flutter::testing::BoundsTolerance
 
struct  flutter::testing::RenderContext< C, P, I >
 
class  flutter::testing::RenderResult
 
class  flutter::testing::SkRenderResult
 
class  flutter::testing::ImpellerRenderResult
 
struct  flutter::testing::RenderJobInfo
 
struct  flutter::testing::JobRenderer
 
struct  flutter::testing::MatrixClipJobRenderer
 
struct  flutter::testing::SkJobRenderer
 
struct  flutter::testing::DlJobRenderer
 
struct  flutter::testing::SkPictureJobRenderer
 
struct  flutter::testing::DisplayListJobRenderer
 
class  flutter::testing::RenderEnvironment
 
class  flutter::testing::CaseParameters
 
class  flutter::testing::TestParameters
 
class  flutter::testing::CanvasCompareTester
 
class  flutter::testing::DisplayListRenderingTestBase< BaseT >
 
class  flutter::testing::DisplayListNopTest
 

Namespaces

namespace  flutter
 
namespace  flutter::testing
 

Macros

#define FOR_EACH_BLEND_MODE_ENUM(FUNC)
 
#define TEST_MODE(V)   test_mode(DlBlendMode::V);
 
#define TEST_MODE(V)   test_mode(DlBlendMode::V);
 
#define TEST_MODE(V)   test_mode_filter(DlBlendMode::V);
 
#define TEST_MODE(V)   test_mode_render(DlBlendMode::V);
 
#define TEST_MODE(V)   test_mode_render(DlBlendMode::V);
 

Typedefs

using flutter::testing::SkSetupContext = RenderContext< SkCanvas *, SkPaint &, sk_sp< SkImage > >
 
using flutter::testing::DlSetupContext = RenderContext< DlCanvas *, DlPaint &, sk_sp< DlImage > >
 
using flutter::testing::SkRenderContext = RenderContext< SkCanvas *, const SkPaint &, sk_sp< SkImage > >
 
using flutter::testing::DlRenderContext = RenderContext< DlCanvas *, const DlPaint &, sk_sp< DlImage > >
 
using flutter::testing::SkSetup = const std::function< void(const SkSetupContext &)>
 
using flutter::testing::SkRenderer = const std::function< void(const SkRenderContext &)>
 
using flutter::testing::DlSetup = const std::function< void(const DlSetupContext &)>
 
using flutter::testing::DlRenderer = const std::function< void(const DlRenderContext &)>
 
using flutter::testing::PixelFormat = DlSurfaceProvider::PixelFormat
 
using flutter::testing::DisplayListRendering = DisplayListRenderingTestBase<::testing::Test >
 

Functions

static void flutter::testing::DrawCheckerboard (DlCanvas *canvas)
 
static void flutter::testing::DrawCheckerboard (SkCanvas *canvas)
 
static std::shared_ptr< DlImageColorSourceflutter::testing::MakeColorSource (const sk_sp< DlImage > &image)
 
static sk_sp< SkShader > flutter::testing::MakeColorSource (const sk_sp< SkImage > &image)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawPaint)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawOpaqueColor)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawAlphaColor)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawDiagonalLines)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawHorizontalLines)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawVerticalLines)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawDiagonalDashedLines)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawRect)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawOval)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawCircle)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawRoundRect)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawDiffRoundRect)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawPath)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawArc)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawArcCenter)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawPointsAsPoints)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawPointsAsLines)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawPointsAsPolygon)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawVerticesWithColors)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawVerticesWithImage)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawImageNearest)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawImageNearestNoPaint)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawImageLinear)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawImageRectNearest)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawImageRectNearestNoPaint)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawImageRectLinear)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawImageNineNearest)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawImageNineNearestNoPaint)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawImageNineLinear)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawAtlasNearest)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawAtlasNearestNoPaint)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawAtlasLinear)
 
sk_sp< DisplayListflutter::testing::makeTestDisplayList ()
 
 flutter::testing::TEST_F (DisplayListRendering, DrawDisplayList)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawTextBlob)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawShadow)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawShadowTransparentOccluder)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawShadowDpr)
 
 flutter::testing::TEST_F (DisplayListRendering, SaveLayerClippedContentStillFilters)
 
 flutter::testing::TEST_F (DisplayListRendering, SaveLayerConsolidation)
 
 flutter::testing::TEST_F (DisplayListRendering, MatrixColorFilterModifyTransparencyCheck)
 
 flutter::testing::TEST_F (DisplayListRendering, MatrixColorFilterOpacityCommuteCheck)
 
 flutter::testing::TEST_F (DisplayListRendering, BlendColorFilterModifyTransparencyCheck)
 
 flutter::testing::TEST_F (DisplayListRendering, BlendColorFilterOpacityCommuteCheck)
 
 flutter::testing::TEST_F (DisplayListNopTest, BlendModeAndColorViaColorFilter)
 
 flutter::testing::TEST_F (DisplayListNopTest, BlendModeAndColorByRendering)
 
 flutter::testing::TEST_F (DisplayListNopTest, BlendModeAndColorAndFiltersByRendering)
 

Variables

constexpr int flutter::testing::kTestWidth = 200
 
constexpr int flutter::testing::kTestHeight = 200
 
constexpr int flutter::testing::kRenderWidth = 100
 
constexpr int flutter::testing::kRenderHeight = 100
 
constexpr int flutter::testing::kRenderLeft = (kTestWidth - kRenderWidth) / 2
 
constexpr int flutter::testing::kRenderTop = (kTestHeight - kRenderHeight) / 2
 
constexpr int flutter::testing::kRenderRight = kRenderLeft + kRenderWidth
 
constexpr int flutter::testing::kRenderBottom = kRenderTop + kRenderHeight
 
constexpr int flutter::testing::kRenderCenterX = (kRenderLeft + kRenderRight) / 2
 
constexpr int flutter::testing::kRenderCenterY = (kRenderTop + kRenderBottom) / 2
 
constexpr DlScalar flutter::testing::kRenderRadius = std::min(kRenderWidth, kRenderHeight) / 2.0
 
constexpr DlScalar flutter::testing::kRenderCornerRadius = kRenderRadius / 5.0
 
constexpr DlRect flutter::testing::kTestBounds2 = DlRect::MakeWH(kTestWidth, kTestHeight)
 
const DlPoint flutter::testing::kTestCenter2 = kTestBounds2.GetCenter()
 
constexpr DlRect flutter::testing::kRenderBounds
 
constexpr DlScalar flutter::testing::kMiterExtremeDiamondOffsetX = kRenderHeight * 0.04
 
constexpr DlScalar flutter::testing::kMiter10DiamondOffsetX = kRenderHeight * 0.051
 
constexpr DlScalar flutter::testing::kMiter4DiamondOffsetX = kRenderHeight * 0.14
 
constexpr DlScalar flutter::testing::kMiterExtremeDiamondOffsetY = kRenderWidth * 0.04
 
constexpr DlScalar flutter::testing::kMiter10DiamondOffsetY = kRenderWidth * 0.051
 
constexpr DlScalar flutter::testing::kMiter4DiamondOffsetY = kRenderWidth * 0.14
 
constexpr DlScalar flutter::testing::kXOffset0 = kRenderCenterX + 0.5
 
constexpr DlScalar flutter::testing::kXOffsetL1 = kXOffset0 - kMiter4DiamondOffsetX
 
constexpr DlScalar flutter::testing::kXOffsetL2 = kXOffsetL1 - kMiter10DiamondOffsetX
 
constexpr DlScalar flutter::testing::kXOffsetL3 = kXOffsetL2 - kMiter10DiamondOffsetX
 
constexpr DlScalar flutter::testing::kXOffsetR1 = kXOffset0 + kMiter4DiamondOffsetX
 
constexpr DlScalar flutter::testing::kXOffsetR2 = kXOffsetR1 + kMiterExtremeDiamondOffsetX
 
constexpr DlScalar flutter::testing::kXOffsetR3 = kXOffsetR2 + kMiterExtremeDiamondOffsetX
 
constexpr DlPoint flutter::testing::kVerticalMiterDiamondPoints []
 
const int flutter::testing::kVerticalMiterDiamondPointCount
 
constexpr DlScalar flutter::testing::kYOffset0 = kRenderCenterY + 0.5
 
constexpr DlScalar flutter::testing::kYOffsetU1 = kXOffset0 - kMiter4DiamondOffsetY
 
constexpr DlScalar flutter::testing::kYOffsetU2 = kYOffsetU1 - kMiter10DiamondOffsetY
 
constexpr DlScalar flutter::testing::kYOffsetU3 = kYOffsetU2 - kMiter10DiamondOffsetY
 
constexpr DlScalar flutter::testing::kYOffsetD1 = kXOffset0 + kMiter4DiamondOffsetY
 
constexpr DlScalar flutter::testing::kYOffsetD2 = kYOffsetD1 + kMiterExtremeDiamondOffsetY
 
constexpr DlScalar flutter::testing::kYOffsetD3 = kYOffsetD2 + kMiterExtremeDiamondOffsetY
 
const DlPoint flutter::testing::kHorizontalMiterDiamondPoints []
 
const int flutter::testing::kHorizontalMiterDiamondPointCount
 
static const SkSetup flutter::testing::kEmptySkSetup = [](const SkSetupContext&) {}
 
static const SkRenderer flutter::testing::kEmptySkRenderer = [](const SkRenderContext&) {}
 
static const DlSetup flutter::testing::kEmptyDlSetup = [](const DlSetupContext&) {}
 
static const DlRenderer flutter::testing::kEmptyDlRenderer = [](const DlRenderContext&) {}
 

Macro Definition Documentation

◆ FOR_EACH_BLEND_MODE_ENUM

#define FOR_EACH_BLEND_MODE_ENUM (   FUNC)
Value:
FUNC(kClear) \
FUNC(kSrc) \
FUNC(kDst) \
FUNC(kSrcOver) \
FUNC(kDstOver) \
FUNC(kSrcIn) \
FUNC(kDstIn) \
FUNC(kSrcOut) \
FUNC(kDstOut) \
FUNC(kSrcATop) \
FUNC(kDstATop) \
FUNC(kXor) \
FUNC(kPlus) \
FUNC(kModulate) \
FUNC(kScreen) \
FUNC(kOverlay) \
FUNC(kDarken) \
FUNC(kLighten) \
FUNC(kColorDodge) \
FUNC(kColorBurn) \
FUNC(kHardLight) \
FUNC(kSoftLight) \
FUNC(kDifference) \
FUNC(kExclusion) \
FUNC(kMultiply) \
FUNC(kHue) \
FUNC(kSaturation) \
FUNC(kColor) \
FUNC(kLuminosity)

Definition at line 4374 of file dl_rendering_unittests.cc.

4404 {
4405 auto test_mode_color = [](DlBlendMode mode, DlColor color) {
4406 std::stringstream desc_str;
4407 std::string mode_string = BlendModeToString(mode);
4408 desc_str << "blend[" << mode_string << ", " << color << "]";
4409 std::string desc = desc_str.str();
4410 DlBlendColorFilter filter(color, mode);
4411 if (filter.modifies_transparent_black()) {
4412 ASSERT_NE(DlColorFilter::MakeBlend(color, mode), nullptr) << desc;
4413 }
4414
4415 DlPaint paint(DlColor(0x7f7f7f7f));
4416 DlPaint filter_save_paint = DlPaint().setColorFilter(&filter);
4417
4418 DisplayListBuilder builder1;
4419 builder1.Translate(kTestCenter2.x, kTestCenter2.y);
4420 builder1.Rotate(45);
4421 builder1.Translate(-kTestCenter2.x, -kTestCenter2.y);
4422 builder1.DrawRect(kRenderBounds, paint);
4423 auto display_list1 = builder1.Build();
4424
4425 DisplayListBuilder builder2;
4426 builder2.Translate(kTestCenter2.x, kTestCenter2.y);
4427 builder2.Rotate(45);
4428 builder2.Translate(-kTestCenter2.x, -kTestCenter2.y);
4429 builder2.SaveLayer(kTestBounds2, &filter_save_paint);
4430 builder2.DrawRect(kRenderBounds, paint);
4431 builder2.Restore();
4432 auto display_list2 = builder2.Build();
4433
4434 for (auto& back_end : CanvasCompareTester::TestBackends) {
4435 auto provider = CanvasCompareTester::GetProvider(back_end);
4436 auto env = std::make_unique<RenderEnvironment>(
4437 provider.get(), PixelFormat::kN32PremulPixelFormat);
4438 auto results1 = env->getResult(display_list1);
4439 auto results2 = env->getResult(display_list2);
4440 int modified_transparent_pixels =
4441 CanvasCompareTester::countModifiedTransparentPixels(results1.get(),
4442 results2.get());
4443 EXPECT_EQ(filter.modifies_transparent_black(),
4444 modified_transparent_pixels != 0)
4445 << desc;
4446 }
4447 };
4448
4449 auto test_mode = [&test_mode_color](DlBlendMode mode) {
4450 test_mode_color(mode, DlColor::kTransparent());
4451 test_mode_color(mode, DlColor::kWhite());
4452 test_mode_color(mode, DlColor::kWhite().modulateOpacity(0.5));
4453 test_mode_color(mode, DlColor::kBlack());
4454 test_mode_color(mode, DlColor::kBlack().modulateOpacity(0.5));
4455 };
4456
4457#define TEST_MODE(V) test_mode(DlBlendMode::V);
4459#undef TEST_MODE
4460}
4461
4462TEST_F(DisplayListRendering, BlendColorFilterOpacityCommuteCheck) {
4463 auto test_mode_color = [](DlBlendMode mode, DlColor color) {
4464 std::stringstream desc_str;
4465 std::string mode_string = BlendModeToString(mode);
4466 desc_str << "blend[" << mode_string << ", " << color << "]";
4467 std::string desc = desc_str.str();
4468 DlBlendColorFilter filter(color, mode);
4469 if (filter.can_commute_with_opacity()) {
4470 // If it can commute with opacity, then it might also be a NOP,
4471 // so we won't necessarily get a non-null return from |::Make()|
4472 } else {
4473 ASSERT_NE(DlColorFilter::MakeBlend(color, mode), nullptr) << desc;
4474 }
4475
4476 DlPaint paint(DlColor(0x80808080));
4477 DlPaint opacity_save_paint = DlPaint().setOpacity(0.5);
4478 DlPaint filter_save_paint = DlPaint().setColorFilter(&filter);
4479
4480 DisplayListBuilder builder1;
4481 builder1.SaveLayer(kTestBounds2, &opacity_save_paint);
4482 builder1.SaveLayer(kTestBounds2, &filter_save_paint);
4483 // builder1.DrawRect(kRenderBounds.makeOffset(20, 20), DlPaint());
4484 builder1.DrawRect(kRenderBounds, paint);
4485 builder1.Restore();
4486 builder1.Restore();
4487 auto display_list1 = builder1.Build();
4488
4489 DisplayListBuilder builder2;
4490 builder2.SaveLayer(kTestBounds2, &filter_save_paint);
4491 builder2.SaveLayer(kTestBounds2, &opacity_save_paint);
4492 // builder1.DrawRect(kRenderBounds.makeOffset(20, 20), DlPaint());
4493 builder2.DrawRect(kRenderBounds, paint);
4494 builder2.Restore();
4495 builder2.Restore();
4496 auto display_list2 = builder2.Build();
4497
4498 for (auto& back_end : CanvasCompareTester::TestBackends) {
4499 auto provider = CanvasCompareTester::GetProvider(back_end);
4500 auto env = std::make_unique<RenderEnvironment>(
4501 provider.get(), PixelFormat::kN32PremulPixelFormat);
4502 auto results1 = env->getResult(display_list1);
4503 auto results2 = env->getResult(display_list2);
4504 if (filter.can_commute_with_opacity()) {
4505 CanvasCompareTester::compareToReference(
4506 results2.get(), results1.get(), desc, nullptr, nullptr,
4507 DlColor::kTransparent(), true, kTestWidth, kTestHeight, true);
4508 } else {
4509 CanvasCompareTester::quickCompareToReference(
4510 results1.get(), results2.get(), false, desc);
4511 }
4512 }
4513 };
4514
4515 auto test_mode = [&test_mode_color](DlBlendMode mode) {
4516 test_mode_color(mode, DlColor::kTransparent());
4517 test_mode_color(mode, DlColor::kWhite());
4518 test_mode_color(mode, DlColor::kWhite().modulateOpacity(0.5));
4519 test_mode_color(mode, DlColor::kBlack());
4520 test_mode_color(mode, DlColor::kBlack().modulateOpacity(0.5));
4521 };
4522
4523#define TEST_MODE(V) test_mode(DlBlendMode::V);
4525#undef TEST_MODE
4526}
4527
4528class DisplayListNopTest : public DisplayListRendering {
4529 // The following code uses the acronym MTB for "modifies_transparent_black"
4530
4531 protected:
4532 DisplayListNopTest() : DisplayListRendering() {
4533 test_src_colors = {
4534 DlColor::kBlack().withAlpha(0), // transparent black
4535 DlColor::kBlack().withAlpha(0x7f), // half transparent black
4536 DlColor::kWhite().withAlpha(0x7f), // half transparent white
4537 DlColor::kBlack(), // opaque black
4538 DlColor::kWhite(), // opaque white
4539 DlColor::kRed(), // opaque red
4540 DlColor::kGreen(), // opaque green
4541 DlColor::kBlue(), // opaque blue
4542 DlColor::kDarkGrey(), // dark grey
4543 DlColor::kLightGrey(), // light grey
4544 };
4545
4546 // We test against a color cube of 3x3x3 colors [55,aa,ff]
4547 // plus transparency as the first color/pixel
4548 test_dst_colors.push_back(DlColor::kTransparent());
4549 const int step = 0x55;
4550 static_assert(step * 3 == 255);
4551 for (int a = step; a < 256; a += step) {
4552 for (int r = step; r < 256; r += step) {
4553 for (int g = step; g < 256; g += step) {
4554 for (int b = step; b < 256; b += step) {
4555 test_dst_colors.push_back(DlColor(a << 24 | r << 16 | g << 8 | b));
4556 }
4557 }
4558 }
4559 }
4560
4561 static constexpr float color_filter_matrix_nomtb[] = {
4562 0.0001, 0.0001, 0.0001, 0.9997, 0.0, //
4563 0.0001, 0.0001, 0.0001, 0.9997, 0.0, //
4564 0.0001, 0.0001, 0.0001, 0.9997, 0.0, //
4565 0.0001, 0.0001, 0.0001, 0.9997, 0.0, //
4566 };
4567 static constexpr float color_filter_matrix_mtb[] = {
4568 0.0001, 0.0001, 0.0001, 0.9997, 0.0, //
4569 0.0001, 0.0001, 0.0001, 0.9997, 0.0, //
4570 0.0001, 0.0001, 0.0001, 0.9997, 0.0, //
4571 0.0001, 0.0001, 0.0001, 0.9997, 0.1, //
4572 };
4573 color_filter_nomtb = DlColorFilter::MakeMatrix(color_filter_matrix_nomtb);
4574 color_filter_mtb = DlColorFilter::MakeMatrix(color_filter_matrix_mtb);
4575 EXPECT_FALSE(color_filter_nomtb->modifies_transparent_black());
4576 EXPECT_TRUE(color_filter_mtb->modifies_transparent_black());
4577
4578 test_data =
4579 get_output(test_dst_colors.size(), 1, true, [this](SkCanvas* canvas) {
4580 int x = 0;
4581 for (DlColor color : test_dst_colors) {
4582 SkPaint paint;
4583 paint.setColor(ToSkColor4f(color));
4584 paint.setBlendMode(SkBlendMode::kSrc);
4585 canvas->drawRect(SkRect::MakeXYWH(x, 0, 1, 1), paint);
4586 x++;
4587 }
4588 });
4589
4590 // For image-on-image tests, the src and dest images will have repeated
4591 // rows/columns that have every color, but laid out at right angles to
4592 // each other so we see an interaction with every test color against
4593 // every other test color.
4594 int data_count = test_data->image()->width();
4595 test_image_dst_data = get_output(
4596 data_count, data_count, true, [this, data_count](SkCanvas* canvas) {
4597 ASSERT_EQ(test_data->width(), data_count);
4598 ASSERT_EQ(test_data->height(), 1);
4599 for (int y = 0; y < data_count; y++) {
4600 canvas->drawImage(test_data->image().get(), 0, y);
4601 }
4602 });
4603 test_image_src_data = get_output(
4604 data_count, data_count, true, [this, data_count](SkCanvas* canvas) {
4605 ASSERT_EQ(test_data->width(), data_count);
4606 ASSERT_EQ(test_data->height(), 1);
4607 canvas->translate(data_count, 0);
4608 canvas->rotate(90);
4609 for (int y = 0; y < data_count; y++) {
4610 canvas->drawImage(test_data->image().get(), 0, y);
4611 }
4612 });
4613 // Double check that the pixel data is laid out in orthogonal stripes
4614 for (int y = 0; y < data_count; y++) {
4615 for (int x = 0; x < data_count; x++) {
4616 EXPECT_EQ(*test_image_dst_data->addr32(x, y), *test_data->addr32(x, 0));
4617 EXPECT_EQ(*test_image_src_data->addr32(x, y), *test_data->addr32(y, 0));
4618 }
4619 }
4620 }
4621
4622 // These flags are 0 by default until they encounter a counter-example
4623 // result and get set.
4624 static constexpr int kWasNotNop = 0x1; // Some tested pixel was modified
4625 static constexpr int kWasMTB = 0x2; // A transparent pixel was modified
4626
4627 std::vector<DlColor> test_src_colors;
4628 std::vector<DlColor> test_dst_colors;
4629
4630 std::shared_ptr<const DlColorFilter> color_filter_nomtb;
4631 std::shared_ptr<const DlColorFilter> color_filter_mtb;
4632
4633 // A 1-row image containing every color in test_dst_colors
4634 std::unique_ptr<RenderResult> test_data;
4635
4636 // A square image containing test_data duplicated in each row
4637 std::unique_ptr<RenderResult> test_image_dst_data;
4638
4639 // A square image containing test_data duplicated in each column
4640 std::unique_ptr<RenderResult> test_image_src_data;
4641
4642 std::unique_ptr<RenderResult> get_output(
4643 int w,
4644 int h,
4645 bool snapshot,
4646 const std::function<void(SkCanvas*)>& renderer) {
4647 auto surface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(w, h));
4648 SkCanvas* canvas = surface->getCanvas();
4649 renderer(canvas);
4650 return std::make_unique<SkRenderResult>(surface, snapshot);
4651 }
4652
4653 int check_color_result(DlColor dst_color,
4654 DlColor result_color,
4655 const sk_sp<DisplayList>& dl,
4656 const std::string& desc) {
4657 int ret = 0;
4658 bool is_error = false;
4659 if (dst_color.isTransparent() && !result_color.isTransparent()) {
4660 ret |= kWasMTB;
4661 is_error = !dl->modifies_transparent_black();
4662 }
4663 if (result_color != dst_color) {
4664 ret |= kWasNotNop;
4665 is_error = (dl->op_count() == 0u);
4666 }
4667 if (is_error) {
4668 FML_LOG(ERROR) << std::hex << dst_color << " filters to " << result_color
4669 << desc;
4670 }
4671 return ret;
4672 }
4673
4674 int check_image_result(const std::unique_ptr<RenderResult>& dst_data,
4675 const std::unique_ptr<RenderResult>& result_data,
4676 const sk_sp<DisplayList>& dl,
4677 const std::string& desc) {
4678 EXPECT_EQ(dst_data->width(), result_data->width());
4679 EXPECT_EQ(dst_data->height(), result_data->height());
4680 int all_flags = 0;
4681 for (int y = 0; y < dst_data->height(); y++) {
4682 const uint32_t* dst_pixels = dst_data->addr32(0, y);
4683 const uint32_t* result_pixels = result_data->addr32(0, y);
4684 for (int x = 0; x < dst_data->width(); x++) {
4685 all_flags |= check_color_result(DlColor(dst_pixels[x]),
4686 DlColor(result_pixels[x]), dl, desc);
4687 }
4688 }
4689 return all_flags;
4690 }
4691
4692 void report_results(int all_flags,
4693 const sk_sp<DisplayList>& dl,
4694 const std::string& desc) {
4695 if (!dl->modifies_transparent_black()) {
4696 EXPECT_TRUE((all_flags & kWasMTB) == 0);
4697 } else if ((all_flags & kWasMTB) == 0) {
4698 FML_LOG(INFO) << "combination does not affect transparency: " << desc;
4699 }
4700 if (dl->op_count() == 0u) {
4701 EXPECT_TRUE((all_flags & kWasNotNop) == 0);
4702 } else if ((all_flags & kWasNotNop) == 0) {
4703 FML_LOG(INFO) << "combination could be classified as a nop: " << desc;
4704 }
4705 };
4706
4707 void test_mode_color_via_filter(DlBlendMode mode, DlColor color) {
4708 std::stringstream desc_stream;
4709 desc_stream << " using SkColorFilter::filterColor() with: ";
4710 desc_stream << BlendModeToString(mode);
4711 desc_stream << "/" << color;
4712 std::string desc = desc_stream.str();
4713 DisplayListBuilder builder(DlRect::MakeWH(100.0f, 100.0f));
4714 DlPaint paint = DlPaint(color).setBlendMode(mode);
4715 builder.DrawRect(DlRect::MakeLTRB(0.0f, 0.0f, 10.0f, 10.0f), paint);
4716 auto dl = builder.Build();
4717 if (dl->modifies_transparent_black()) {
4718 ASSERT_TRUE(dl->op_count() != 0u);
4719 }
4720
4721 auto sk_mode = static_cast<SkBlendMode>(mode);
4722 auto sk_color_filter =
4723 SkColorFilters::Blend(ToSkColor4f(color), nullptr, sk_mode);
4724 auto srgb = SkColorSpace::MakeSRGB();
4725 int all_flags = 0;
4726 if (sk_color_filter) {
4727 for (DlColor dst_color : test_dst_colors) {
4728 SkColor4f dst_color_f = ToSkColor4f(dst_color);
4729 DlColor result = DlColor(
4730 sk_color_filter->filterColor4f(dst_color_f, srgb.get(), srgb.get())
4731 .toSkColor());
4732 all_flags |= check_color_result(dst_color, result, dl, desc);
4733 }
4734 if ((all_flags & kWasMTB) != 0) {
4735 EXPECT_FALSE(sk_color_filter->isAlphaUnchanged());
4736 }
4737 }
4738 report_results(all_flags, dl, desc);
4739 };
4740
4741 void test_mode_color_via_rendering(DlBlendMode mode, DlColor color) {
4742 std::stringstream desc_stream;
4743 desc_stream << " rendering with: ";
4744 desc_stream << BlendModeToString(mode);
4745 desc_stream << "/" << color;
4746 std::string desc = desc_stream.str();
4747 auto test_image = test_data->image();
4748 DlRect test_bounds =
4749 DlRect::MakeWH(test_image->width(), test_image->height());
4750 DisplayListBuilder builder(test_bounds);
4751 DlPaint dl_paint = DlPaint(color).setBlendMode(mode);
4752 builder.DrawRect(test_bounds, dl_paint);
4753 auto dl = builder.Build();
4754 bool dl_is_elided = dl->op_count() == 0u;
4755 bool dl_affects_transparent_pixels = dl->modifies_transparent_black();
4756 ASSERT_TRUE(!dl_is_elided || !dl_affects_transparent_pixels);
4757
4758 auto sk_mode = static_cast<SkBlendMode>(mode);
4759 SkPaint sk_paint;
4760 sk_paint.setBlendMode(sk_mode);
4761 sk_paint.setColor(ToSkColor4f(color));
4762 for (auto& back_end : CanvasCompareTester::TestBackends) {
4763 auto provider = CanvasCompareTester::GetProvider(back_end);
4764 auto result_surface = provider->MakeOffscreenSurface(
4765 test_image->width(), test_image->height(),
4766 DlSurfaceProvider::kN32PremulPixelFormat);
4767 SkCanvas* result_canvas = result_surface->sk_surface()->getCanvas();
4768 result_canvas->clear(SK_ColorTRANSPARENT);
4769 result_canvas->drawImage(test_image.get(), 0, 0);
4770 result_canvas->drawRect(ToSkRect(test_bounds), sk_paint);
4771 if (GrDirectContext* direct_context = GrAsDirectContext(
4772 result_surface->sk_surface()->recordingContext())) {
4773 direct_context->flushAndSubmit();
4774 direct_context->flushAndSubmit(result_surface->sk_surface().get(),
4775 GrSyncCpu::kYes);
4776 }
4777 const std::unique_ptr<RenderResult> result_pixels =
4778 std::make_unique<SkRenderResult>(result_surface->sk_surface());
4779
4780 int all_flags = check_image_result(test_data, result_pixels, dl, desc);
4781 report_results(all_flags, dl, desc);
4782 }
4783 };
4784
4785 void test_attributes_image(DlBlendMode mode,
4786 DlColor color,
4787 const DlColorFilter* color_filter,
4788 DlImageFilter* image_filter) {
4789 // if (true) { return; }
4790 std::stringstream desc_stream;
4791 desc_stream << " rendering with: ";
4792 desc_stream << BlendModeToString(mode);
4793 desc_stream << "/" << color;
4794 std::string cf_mtb = color_filter
4795 ? color_filter->modifies_transparent_black()
4796 ? "modifies transparency"
4797 : "preserves transparency"
4798 : "no filter";
4799 desc_stream << ", CF: " << cf_mtb;
4800 std::string if_mtb = image_filter
4801 ? image_filter->modifies_transparent_black()
4802 ? "modifies transparency"
4803 : "preserves transparency"
4804 : "no filter";
4805 desc_stream << ", IF: " << if_mtb;
4806 std::string desc = desc_stream.str();
4807
4808 DisplayListBuilder builder(DlRect::MakeWH(100.0f, 100.0f));
4809 DlPaint paint = DlPaint(color) //
4810 .setBlendMode(mode) //
4811 .setColorFilter(color_filter) //
4812 .setImageFilter(image_filter);
4813 builder.DrawImage(DlImage::Make(test_image_src_data->image()),
4814 DlPoint(0, 0), DlImageSampling::kNearestNeighbor, &paint);
4815 auto dl = builder.Build();
4816
4817 int w = test_image_src_data->width();
4818 int h = test_image_src_data->height();
4819 auto sk_mode = static_cast<SkBlendMode>(mode);
4820 SkPaint sk_paint;
4821 sk_paint.setBlendMode(sk_mode);
4822 sk_paint.setColor(ToSkColor4f(color));
4823 sk_paint.setColorFilter(ToSk(color_filter));
4824 sk_paint.setImageFilter(ToSk(image_filter));
4825 for (auto& back_end : CanvasCompareTester::TestBackends) {
4826 auto provider = CanvasCompareTester::GetProvider(back_end);
4827 auto result_surface = provider->MakeOffscreenSurface(
4828 w, h, DlSurfaceProvider::kN32PremulPixelFormat);
4829 SkCanvas* result_canvas = result_surface->sk_surface()->getCanvas();
4830 result_canvas->clear(SK_ColorTRANSPARENT);
4831 result_canvas->drawImage(test_image_dst_data->image(), 0, 0);
4832 result_canvas->drawImage(test_image_src_data->image(), 0, 0,
4833 SkSamplingOptions(), &sk_paint);
4834 if (GrDirectContext* direct_context = GrAsDirectContext(
4835 result_surface->sk_surface()->recordingContext())) {
4836 direct_context->flushAndSubmit();
4837 direct_context->flushAndSubmit(result_surface->sk_surface().get(),
4838 GrSyncCpu::kYes);
4839 }
4840 std::unique_ptr<RenderResult> result_pixels =
4841 std::make_unique<SkRenderResult>(result_surface->sk_surface());
4842
4843 int all_flags =
4844 check_image_result(test_image_dst_data, result_pixels, dl, desc);
4845 report_results(all_flags, dl, desc);
4846 }
4847 };
4848};
4849
4850TEST_F(DisplayListNopTest, BlendModeAndColorViaColorFilter) {
4851 auto test_mode_filter = [this](DlBlendMode mode) {
4852 for (DlColor color : test_src_colors) {
4853 test_mode_color_via_filter(mode, color);
4854 }
4855 };
4856
4857#define TEST_MODE(V) test_mode_filter(DlBlendMode::V);
4859#undef TEST_MODE
4860}
4861
4862TEST_F(DisplayListNopTest, BlendModeAndColorByRendering) {
4863 auto test_mode_render = [this](DlBlendMode mode) {
4864 // First check rendering a variety of colors onto image
4865 for (DlColor color : test_src_colors) {
4866 test_mode_color_via_rendering(mode, color);
4867 }
4868 };
4869
4870#define TEST_MODE(V) test_mode_render(DlBlendMode::V);
4872#undef TEST_MODE
4873}
4874
4875TEST_F(DisplayListNopTest, BlendModeAndColorAndFiltersByRendering) {
4876 auto test_mode_render = [this](DlBlendMode mode) {
4877 auto image_filter_nomtb = DlColorFilterImageFilter(color_filter_nomtb);
4878 auto image_filter_mtb = DlColorFilterImageFilter(color_filter_mtb);
4879 for (DlColor color : test_src_colors) {
4880 test_attributes_image(mode, color, nullptr, nullptr);
4881 test_attributes_image(mode, color, color_filter_nomtb.get(), nullptr);
4882 test_attributes_image(mode, color, color_filter_mtb.get(), nullptr);
4883 test_attributes_image(mode, color, nullptr, &image_filter_nomtb);
4884 test_attributes_image(mode, color, nullptr, &image_filter_mtb);
4885 }
4886 };
4887
4888#define TEST_MODE(V) test_mode_render(DlBlendMode::V);
4890#undef TEST_MODE
4891}
4892
4893#undef FOR_EACH_BLEND_MODE_ENUM
4894
4895} // namespace testing
4896} // namespace flutter
DlPaint & setBlendMode(DlBlendMode mode)
Definition dl_paint.h:85
DlPaint & setImageFilter(std::nullptr_t filter)
Definition dl_paint.h:167
DlPaint & setOpacity(DlScalar opacity)
Definition dl_paint.h:78
DlPaint & setColorFilter(std::nullptr_t filter)
Definition dl_paint.h:149
int32_t x
#define FOR_EACH_BLEND_MODE_ENUM(FUNC)
#define TEST_MODE(V)
VkSurfaceKHR surface
Definition main.cc:65
#define FML_LOG(severity)
Definition logging.h:101
double y
DisplayListRenderingTestBase<::testing::Test > DisplayListRendering
SkPaint ToSk(const DlPaint &paint)
impeller::Rect DlRect
SkColor4f ToSkColor4f(DlColor color)
it will be possible to load the file into Perfetto s trace viewer use test Running tests that layout and measure text will not yield consistent results across various platforms Enabling this option will make font resolution default to the Ahem test font on all disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive mode
impeller::BlendMode DlBlendMode
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder h
Definition switch_defs.h:54
impeller::Point DlPoint
const SkRect & ToSkRect(const DlRect &rect)
const char * BlendModeToString(BlendMode blend_mode)
Definition color.cc:47
flutter::DlColor DlColor
flutter::DlPaint DlPaint

◆ TEST_MODE [1/5]

#define TEST_MODE (   V)    test_mode(DlBlendMode::V);

◆ TEST_MODE [2/5]

#define TEST_MODE (   V)    test_mode(DlBlendMode::V);

◆ TEST_MODE [3/5]

#define TEST_MODE (   V)    test_mode_filter(DlBlendMode::V);

◆ TEST_MODE [4/5]

#define TEST_MODE (   V)    test_mode_render(DlBlendMode::V);

◆ TEST_MODE [5/5]

#define TEST_MODE (   V)    test_mode_render(DlBlendMode::V);