Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Namespaces | Macros | Typedefs | Functions | Variables
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/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/SkGradientShader.h"
#include "third_party/skia/include/effects/SkImageFilters.h"
#include "third_party/skia/include/encode/SkPngEncoder.h"
#include "third_party/skia/include/gpu/GrDirectContext.h"
#include "third_party/skia/include/gpu/GrRecordingContext.h"
#include "third_party/skia/include/gpu/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 MODE_CASE(m)
 
#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< SkShaderflutter::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, DrawHorizontalLine)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawVerticalLine)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawRect)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawOval)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawCircle)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawRRect)
 
 flutter::testing::TEST_F (DisplayListRendering, DrawDRRect)
 
 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)
 
static std::string flutter::testing::BlendModeToString (DlBlendMode mode)
 
 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::kRenderHalfWidth = 50
 
constexpr int flutter::testing::kRenderHalfHeight = 50
 
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 SkScalar flutter::testing::kRenderRadius = std::min(kRenderWidth, kRenderHeight) / 2.0
 
constexpr SkScalar flutter::testing::kRenderCornerRadius = kRenderRadius / 5.0
 
constexpr SkPoint flutter::testing::kTestCenter = SkPoint::Make(kTestWidth / 2, kTestHeight / 2)
 
constexpr SkRect flutter::testing::kTestBounds2 = SkRect::MakeWH(kTestWidth, kTestHeight)
 
constexpr SkRect flutter::testing::kRenderBounds
 
constexpr SkScalar flutter::testing::kMiterExtremeDiamondOffsetX = kRenderHeight * 0.04
 
constexpr SkScalar flutter::testing::kMiter10DiamondOffsetX = kRenderHeight * 0.051
 
constexpr SkScalar flutter::testing::kMiter4DiamondOffsetX = kRenderHeight * 0.14
 
constexpr SkScalar flutter::testing::kMiterExtremeDiamondOffsetY = kRenderWidth * 0.04
 
constexpr SkScalar flutter::testing::kMiter10DiamondOffsetY = kRenderWidth * 0.051
 
constexpr SkScalar flutter::testing::kMiter4DiamondOffsetY = kRenderWidth * 0.14
 
constexpr SkScalar flutter::testing::kXOffset0 = kRenderCenterX + 0.5
 
constexpr SkScalar flutter::testing::kXOffsetL1 = kXOffset0 - kMiter4DiamondOffsetX
 
constexpr SkScalar flutter::testing::kXOffsetL2 = kXOffsetL1 - kMiter10DiamondOffsetX
 
constexpr SkScalar flutter::testing::kXOffsetL3 = kXOffsetL2 - kMiter10DiamondOffsetX
 
constexpr SkScalar flutter::testing::kXOffsetR1 = kXOffset0 + kMiter4DiamondOffsetX
 
constexpr SkScalar flutter::testing::kXOffsetR2 = kXOffsetR1 + kMiterExtremeDiamondOffsetX
 
constexpr SkScalar flutter::testing::kXOffsetR3 = kXOffsetR2 + kMiterExtremeDiamondOffsetX
 
constexpr SkPoint flutter::testing::kVerticalMiterDiamondPoints []
 
const int flutter::testing::kVerticalMiterDiamondPointCount
 
constexpr SkScalar flutter::testing::kYOffset0 = kRenderCenterY + 0.5
 
constexpr SkScalar flutter::testing::kYOffsetU1 = kXOffset0 - kMiter4DiamondOffsetY
 
constexpr SkScalar flutter::testing::kYOffsetU2 = kYOffsetU1 - kMiter10DiamondOffsetY
 
constexpr SkScalar flutter::testing::kYOffsetU3 = kYOffsetU2 - kMiter10DiamondOffsetY
 
constexpr SkScalar flutter::testing::kYOffsetD1 = kXOffset0 + kMiter4DiamondOffsetY
 
constexpr SkScalar flutter::testing::kYOffsetD2 = kYOffsetD1 + kMiterExtremeDiamondOffsetY
 
constexpr SkScalar flutter::testing::kYOffsetD3 = kYOffsetD2 + kMiterExtremeDiamondOffsetY
 
const SkPoint 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) \
static constexpr SkColor kColor
@ kSrcOut
r = s * (1-da)
@ kExclusion
rc = s + d - two(s*d), ra = kSrcOver
@ kSaturation
saturation of source with hue and luminosity of destination
@ kColorBurn
darken destination to reflect source
@ kPlus
r = min(s + d, 1)
@ kLighten
rc = s + d - min(s*da, d*sa), ra = kSrcOver
@ kHue
hue of source with saturation and luminosity of destination
@ kDstIn
r = d * sa
@ kModulate
r = s*d
@ kMultiply
r = s*(1-da) + d*(1-sa) + s*d
@ kColorDodge
brighten destination to reflect source
@ kScreen
r = s + d - s*d
@ kSrcOver
r = s + (1-sa)*d
@ kXor
r = s*(1-da) + d*(1-sa)
@ kLuminosity
luminosity of source with hue and saturation of destination
@ kSoftLight
lighten or darken, depending on source
@ kDifference
rc = s + d - 2*(min(s*da, d*sa)), ra = kSrcOver
@ kOverlay
multiply or screen, depending on destination
@ kSrcATop
r = s*da + d*(1-sa)
@ kDstATop
r = d*sa + s*(1-da)
@ kDstOver
r = d + (1-da)*s
@ kHardLight
multiply or screen, depending on source
@ kDstOut
r = d * (1-sa)
@ kDarken
rc = s + d - max(s*da, d*sa), ra = kSrcOver
@ kSrcIn
r = s * da
@ kClear
r = 0

Definition at line 4170 of file dl_rendering_unittests.cc.

4202 {
4203 switch (mode) {
4204#define MODE_CASE(m) \
4205 case DlBlendMode::m: \
4206 return #m;
4208#undef MODE_CASE
4209 }
4210}
4211
4212TEST_F(DisplayListRendering, BlendColorFilterModifyTransparencyCheck) {
4213 auto test_mode_color = [](DlBlendMode mode, DlColor color) {
4214 std::stringstream desc_str;
4215 std::string mode_string = BlendModeToString(mode);
4216 desc_str << "blend[" << mode_string << ", " << color << "]";
4217 std::string desc = desc_str.str();
4218 DlBlendColorFilter filter(color, mode);
4219 if (filter.modifies_transparent_black()) {
4220 ASSERT_NE(DlBlendColorFilter::Make(color, mode), nullptr) << desc;
4221 }
4222
4223 DlPaint paint(DlColor(0x7f7f7f7f));
4224 DlPaint filter_save_paint = DlPaint().setColorFilter(&filter);
4225
4226 DisplayListBuilder builder1;
4227 builder1.Translate(kTestCenter.fX, kTestCenter.fY);
4228 builder1.Rotate(45);
4229 builder1.Translate(-kTestCenter.fX, -kTestCenter.fY);
4230 builder1.DrawRect(kRenderBounds, paint);
4231 auto display_list1 = builder1.Build();
4232
4233 DisplayListBuilder builder2;
4234 builder2.Translate(kTestCenter.fX, kTestCenter.fY);
4235 builder2.Rotate(45);
4236 builder2.Translate(-kTestCenter.fX, -kTestCenter.fY);
4237 builder2.SaveLayer(&kTestBounds2, &filter_save_paint);
4238 builder2.DrawRect(kRenderBounds, paint);
4239 builder2.Restore();
4240 auto display_list2 = builder2.Build();
4241
4242 for (auto& back_end : CanvasCompareTester::TestBackends) {
4243 auto provider = CanvasCompareTester::GetProvider(back_end);
4244 auto env = std::make_unique<RenderEnvironment>(
4245 provider.get(), PixelFormat::kN32PremulPixelFormat);
4246 auto results1 = env->getResult(display_list1);
4247 auto results2 = env->getResult(display_list2);
4248 int modified_transparent_pixels =
4249 CanvasCompareTester::countModifiedTransparentPixels(results1.get(),
4250 results2.get());
4251 EXPECT_EQ(filter.modifies_transparent_black(),
4252 modified_transparent_pixels != 0)
4253 << desc;
4254 }
4255 };
4256
4257 auto test_mode = [&test_mode_color](DlBlendMode mode) {
4258 test_mode_color(mode, DlColor::kTransparent());
4259 test_mode_color(mode, DlColor::kWhite());
4260 test_mode_color(mode, DlColor::kWhite().modulateOpacity(0.5));
4261 test_mode_color(mode, DlColor::kBlack());
4262 test_mode_color(mode, DlColor::kBlack().modulateOpacity(0.5));
4263 };
4264
4265#define TEST_MODE(V) test_mode(DlBlendMode::V);
4267#undef TEST_MODE
4268}
4269
4270TEST_F(DisplayListRendering, BlendColorFilterOpacityCommuteCheck) {
4271 auto test_mode_color = [](DlBlendMode mode, DlColor color) {
4272 std::stringstream desc_str;
4273 std::string mode_string = BlendModeToString(mode);
4274 desc_str << "blend[" << mode_string << ", " << color << "]";
4275 std::string desc = desc_str.str();
4276 DlBlendColorFilter filter(color, mode);
4277 if (filter.can_commute_with_opacity()) {
4278 // If it can commute with opacity, then it might also be a NOP,
4279 // so we won't necessarily get a non-null return from |::Make()|
4280 } else {
4281 ASSERT_NE(DlBlendColorFilter::Make(color, mode), nullptr) << desc;
4282 }
4283
4284 DlPaint paint(DlColor(0x80808080));
4285 DlPaint opacity_save_paint = DlPaint().setOpacity(0.5);
4286 DlPaint filter_save_paint = DlPaint().setColorFilter(&filter);
4287
4288 DisplayListBuilder builder1;
4289 builder1.SaveLayer(&kTestBounds2, &opacity_save_paint);
4290 builder1.SaveLayer(&kTestBounds2, &filter_save_paint);
4291 // builder1.DrawRect(kRenderBounds.makeOffset(20, 20), DlPaint());
4292 builder1.DrawRect(kRenderBounds, paint);
4293 builder1.Restore();
4294 builder1.Restore();
4295 auto display_list1 = builder1.Build();
4296
4297 DisplayListBuilder builder2;
4298 builder2.SaveLayer(&kTestBounds2, &filter_save_paint);
4299 builder2.SaveLayer(&kTestBounds2, &opacity_save_paint);
4300 // builder1.DrawRect(kRenderBounds.makeOffset(20, 20), DlPaint());
4301 builder2.DrawRect(kRenderBounds, paint);
4302 builder2.Restore();
4303 builder2.Restore();
4304 auto display_list2 = builder2.Build();
4305
4306 for (auto& back_end : CanvasCompareTester::TestBackends) {
4307 auto provider = CanvasCompareTester::GetProvider(back_end);
4308 auto env = std::make_unique<RenderEnvironment>(
4309 provider.get(), PixelFormat::kN32PremulPixelFormat);
4310 auto results1 = env->getResult(display_list1);
4311 auto results2 = env->getResult(display_list2);
4312 if (filter.can_commute_with_opacity()) {
4313 CanvasCompareTester::compareToReference(
4314 results2.get(), results1.get(), desc, nullptr, nullptr,
4315 DlColor::kTransparent(), true, kTestWidth, kTestHeight, true);
4316 } else {
4317 CanvasCompareTester::quickCompareToReference(
4318 results1.get(), results2.get(), false, desc);
4319 }
4320 }
4321 };
4322
4323 auto test_mode = [&test_mode_color](DlBlendMode mode) {
4324 test_mode_color(mode, DlColor::kTransparent());
4325 test_mode_color(mode, DlColor::kWhite());
4326 test_mode_color(mode, DlColor::kWhite().modulateOpacity(0.5));
4327 test_mode_color(mode, DlColor::kBlack());
4328 test_mode_color(mode, DlColor::kBlack().modulateOpacity(0.5));
4329 };
4330
4331#define TEST_MODE(V) test_mode(DlBlendMode::V);
4333#undef TEST_MODE
4334}
4335
4336class DisplayListNopTest : public DisplayListRendering {
4337 // The following code uses the acronym MTB for "modifies_transparent_black"
4338
4339 protected:
4340 DisplayListNopTest() : DisplayListRendering() {
4341 test_src_colors = {
4342 DlColor::kBlack().withAlpha(0), // transparent black
4343 DlColor::kBlack().withAlpha(0x7f), // half transparent black
4344 DlColor::kWhite().withAlpha(0x7f), // half transparent white
4345 DlColor::kBlack(), // opaque black
4346 DlColor::kWhite(), // opaque white
4347 DlColor::kRed(), // opaque red
4348 DlColor::kGreen(), // opaque green
4349 DlColor::kBlue(), // opaque blue
4350 DlColor::kDarkGrey(), // dark grey
4351 DlColor::kLightGrey(), // light grey
4352 };
4353
4354 // We test against a color cube of 3x3x3 colors [55,aa,ff]
4355 // plus transparency as the first color/pixel
4356 test_dst_colors.push_back(DlColor::kTransparent());
4357 const int step = 0x55;
4358 static_assert(step * 3 == 255);
4359 for (int a = step; a < 256; a += step) {
4360 for (int r = step; r < 256; r += step) {
4361 for (int g = step; g < 256; g += step) {
4362 for (int b = step; b < 256; b += step) {
4363 test_dst_colors.push_back(DlColor(a << 24 | r << 16 | g << 8 | b));
4364 }
4365 }
4366 }
4367 }
4368
4369 static constexpr float color_filter_matrix_nomtb[] = {
4370 0.0001, 0.0001, 0.0001, 0.9997, 0.0, //
4371 0.0001, 0.0001, 0.0001, 0.9997, 0.0, //
4372 0.0001, 0.0001, 0.0001, 0.9997, 0.0, //
4373 0.0001, 0.0001, 0.0001, 0.9997, 0.0, //
4374 };
4375 static constexpr float color_filter_matrix_mtb[] = {
4376 0.0001, 0.0001, 0.0001, 0.9997, 0.0, //
4377 0.0001, 0.0001, 0.0001, 0.9997, 0.0, //
4378 0.0001, 0.0001, 0.0001, 0.9997, 0.0, //
4379 0.0001, 0.0001, 0.0001, 0.9997, 0.1, //
4380 };
4381 color_filter_nomtb = DlMatrixColorFilter::Make(color_filter_matrix_nomtb);
4382 color_filter_mtb = DlMatrixColorFilter::Make(color_filter_matrix_mtb);
4383 EXPECT_FALSE(color_filter_nomtb->modifies_transparent_black());
4384 EXPECT_TRUE(color_filter_mtb->modifies_transparent_black());
4385
4386 test_data =
4387 get_output(test_dst_colors.size(), 1, true, [this](SkCanvas* canvas) {
4388 int x = 0;
4389 for (DlColor color : test_dst_colors) {
4390 SkPaint paint;
4391 paint.setColor(ToSk(color));
4392 paint.setBlendMode(SkBlendMode::kSrc);
4393 canvas->drawRect(SkRect::MakeXYWH(x, 0, 1, 1), paint);
4394 x++;
4395 }
4396 });
4397
4398 // For image-on-image tests, the src and dest images will have repeated
4399 // rows/columns that have every color, but laid out at right angles to
4400 // each other so we see an interaction with every test color against
4401 // every other test color.
4402 int data_count = test_data->image()->width();
4403 test_image_dst_data = get_output(
4404 data_count, data_count, true, [this, data_count](SkCanvas* canvas) {
4405 ASSERT_EQ(test_data->width(), data_count);
4406 ASSERT_EQ(test_data->height(), 1);
4407 for (int y = 0; y < data_count; y++) {
4408 canvas->drawImage(test_data->image().get(), 0, y);
4409 }
4410 });
4411 test_image_src_data = get_output(
4412 data_count, data_count, true, [this, data_count](SkCanvas* canvas) {
4413 ASSERT_EQ(test_data->width(), data_count);
4414 ASSERT_EQ(test_data->height(), 1);
4415 canvas->translate(data_count, 0);
4416 canvas->rotate(90);
4417 for (int y = 0; y < data_count; y++) {
4418 canvas->drawImage(test_data->image().get(), 0, y);
4419 }
4420 });
4421 // Double check that the pixel data is laid out in orthogonal stripes
4422 for (int y = 0; y < data_count; y++) {
4423 for (int x = 0; x < data_count; x++) {
4424 EXPECT_EQ(*test_image_dst_data->addr32(x, y), *test_data->addr32(x, 0));
4425 EXPECT_EQ(*test_image_src_data->addr32(x, y), *test_data->addr32(y, 0));
4426 }
4427 }
4428 }
4429
4430 // These flags are 0 by default until they encounter a counter-example
4431 // result and get set.
4432 static constexpr int kWasNotNop = 0x1; // Some tested pixel was modified
4433 static constexpr int kWasMTB = 0x2; // A transparent pixel was modified
4434
4435 std::vector<DlColor> test_src_colors;
4436 std::vector<DlColor> test_dst_colors;
4437
4438 std::shared_ptr<DlColorFilter> color_filter_nomtb;
4439 std::shared_ptr<DlColorFilter> color_filter_mtb;
4440
4441 // A 1-row image containing every color in test_dst_colors
4442 std::unique_ptr<RenderResult> test_data;
4443
4444 // A square image containing test_data duplicated in each row
4445 std::unique_ptr<RenderResult> test_image_dst_data;
4446
4447 // A square image containing test_data duplicated in each column
4448 std::unique_ptr<RenderResult> test_image_src_data;
4449
4450 std::unique_ptr<RenderResult> get_output(
4451 int w,
4452 int h,
4453 bool snapshot,
4454 const std::function<void(SkCanvas*)>& renderer) {
4456 SkCanvas* canvas = surface->getCanvas();
4457 renderer(canvas);
4458 return std::make_unique<SkRenderResult>(surface, snapshot);
4459 }
4460
4461 int check_color_result(DlColor dst_color,
4462 DlColor result_color,
4463 const sk_sp<DisplayList>& dl,
4464 const std::string& desc) {
4465 int ret = 0;
4466 bool is_error = false;
4467 if (dst_color.isTransparent() && !result_color.isTransparent()) {
4468 ret |= kWasMTB;
4469 is_error = !dl->modifies_transparent_black();
4470 }
4471 if (result_color != dst_color) {
4472 ret |= kWasNotNop;
4473 is_error = (dl->op_count() == 0u);
4474 }
4475 if (is_error) {
4476 FML_LOG(ERROR) << std::hex << dst_color << " filters to " << result_color
4477 << desc;
4478 }
4479 return ret;
4480 }
4481
4482 int check_image_result(const std::unique_ptr<RenderResult>& dst_data,
4483 const std::unique_ptr<RenderResult>& result_data,
4484 const sk_sp<DisplayList>& dl,
4485 const std::string& desc) {
4486 EXPECT_EQ(dst_data->width(), result_data->width());
4487 EXPECT_EQ(dst_data->height(), result_data->height());
4488 int all_flags = 0;
4489 for (int y = 0; y < dst_data->height(); y++) {
4490 const uint32_t* dst_pixels = dst_data->addr32(0, y);
4491 const uint32_t* result_pixels = result_data->addr32(0, y);
4492 for (int x = 0; x < dst_data->width(); x++) {
4493 all_flags |= check_color_result(DlColor(dst_pixels[x]),
4494 DlColor(result_pixels[x]), dl, desc);
4495 }
4496 }
4497 return all_flags;
4498 }
4499
4500 void report_results(int all_flags,
4501 const sk_sp<DisplayList>& dl,
4502 const std::string& desc) {
4503 if (!dl->modifies_transparent_black()) {
4504 EXPECT_TRUE((all_flags & kWasMTB) == 0);
4505 } else if ((all_flags & kWasMTB) == 0) {
4506 FML_LOG(INFO) << "combination does not affect transparency: " << desc;
4507 }
4508 if (dl->op_count() == 0u) {
4509 EXPECT_TRUE((all_flags & kWasNotNop) == 0);
4510 } else if ((all_flags & kWasNotNop) == 0) {
4511 FML_LOG(INFO) << "combination could be classified as a nop: " << desc;
4512 }
4513 };
4514
4515 void test_mode_color_via_filter(DlBlendMode mode, DlColor color) {
4516 std::stringstream desc_stream;
4517 desc_stream << " using SkColorFilter::filterColor() with: ";
4518 desc_stream << BlendModeToString(mode);
4519 desc_stream << "/" << color;
4520 std::string desc = desc_stream.str();
4521 DisplayListBuilder builder({0.0f, 0.0f, 100.0f, 100.0f});
4522 DlPaint paint = DlPaint(color).setBlendMode(mode);
4523 builder.DrawRect({0.0f, 0.0f, 10.0f, 10.0f}, paint);
4524 auto dl = builder.Build();
4525 if (dl->modifies_transparent_black()) {
4526 ASSERT_TRUE(dl->op_count() != 0u);
4527 }
4528
4529 auto sk_mode = static_cast<SkBlendMode>(mode);
4530 auto sk_color_filter = SkColorFilters::Blend(ToSk(color), sk_mode);
4531 auto srgb = SkColorSpace::MakeSRGB();
4532 int all_flags = 0;
4533 if (sk_color_filter) {
4534 for (DlColor dst_color : test_dst_colors) {
4535 SkColor4f dst_color_f = SkColor4f::FromColor(ToSk(dst_color));
4536 DlColor result = DlColor(
4537 sk_color_filter->filterColor4f(dst_color_f, srgb.get(), srgb.get())
4538 .toSkColor());
4539 all_flags |= check_color_result(dst_color, result, dl, desc);
4540 }
4541 if ((all_flags & kWasMTB) != 0) {
4542 EXPECT_FALSE(sk_color_filter->isAlphaUnchanged());
4543 }
4544 }
4545 report_results(all_flags, dl, desc);
4546 };
4547
4548 void test_mode_color_via_rendering(DlBlendMode mode, DlColor color) {
4549 std::stringstream desc_stream;
4550 desc_stream << " rendering with: ";
4551 desc_stream << BlendModeToString(mode);
4552 desc_stream << "/" << color;
4553 std::string desc = desc_stream.str();
4554 auto test_image = test_data->image();
4556 SkRect::MakeWH(test_image->width(), test_image->height());
4557 DisplayListBuilder builder(test_bounds);
4558 DlPaint dl_paint = DlPaint(color).setBlendMode(mode);
4559 builder.DrawRect(test_bounds, dl_paint);
4560 auto dl = builder.Build();
4561 bool dl_is_elided = dl->op_count() == 0u;
4562 bool dl_affects_transparent_pixels = dl->modifies_transparent_black();
4563 ASSERT_TRUE(!dl_is_elided || !dl_affects_transparent_pixels);
4564
4565 auto sk_mode = static_cast<SkBlendMode>(mode);
4566 SkPaint sk_paint;
4567 sk_paint.setBlendMode(sk_mode);
4568 sk_paint.setColor(ToSk(color));
4569 for (auto& back_end : CanvasCompareTester::TestBackends) {
4570 auto provider = CanvasCompareTester::GetProvider(back_end);
4571 auto result_surface = provider->MakeOffscreenSurface(
4572 test_image->width(), test_image->height(),
4573 DlSurfaceProvider::kN32PremulPixelFormat);
4574 SkCanvas* result_canvas = result_surface->sk_surface()->getCanvas();
4575 result_canvas->clear(SK_ColorTRANSPARENT);
4576 result_canvas->drawImage(test_image.get(), 0, 0);
4577 result_canvas->drawRect(test_bounds, sk_paint);
4578 if (GrDirectContext* direct_context = GrAsDirectContext(
4579 result_surface->sk_surface()->recordingContext())) {
4580 direct_context->flushAndSubmit();
4581 direct_context->flushAndSubmit(result_surface->sk_surface().get(),
4583 }
4584 const std::unique_ptr<RenderResult> result_pixels =
4585 std::make_unique<SkRenderResult>(result_surface->sk_surface());
4586
4587 int all_flags = check_image_result(test_data, result_pixels, dl, desc);
4588 report_results(all_flags, dl, desc);
4589 }
4590 };
4591
4592 void test_attributes_image(DlBlendMode mode,
4593 DlColor color,
4594 DlColorFilter* color_filter,
4595 DlImageFilter* image_filter) {
4596 // if (true) { return; }
4597 std::stringstream desc_stream;
4598 desc_stream << " rendering with: ";
4599 desc_stream << BlendModeToString(mode);
4600 desc_stream << "/" << color;
4601 std::string cf_mtb = color_filter
4602 ? color_filter->modifies_transparent_black()
4603 ? "modifies transparency"
4604 : "preserves transparency"
4605 : "no filter";
4606 desc_stream << ", CF: " << cf_mtb;
4607 std::string if_mtb = image_filter
4608 ? image_filter->modifies_transparent_black()
4609 ? "modifies transparency"
4610 : "preserves transparency"
4611 : "no filter";
4612 desc_stream << ", IF: " << if_mtb;
4613 std::string desc = desc_stream.str();
4614
4615 DisplayListBuilder builder({0.0f, 0.0f, 100.0f, 100.0f});
4616 DlPaint paint = DlPaint(color) //
4617 .setBlendMode(mode) //
4618 .setColorFilter(color_filter) //
4619 .setImageFilter(image_filter);
4620 builder.DrawImage(DlImage::Make(test_image_src_data->image()), {0, 0},
4621 DlImageSampling::kNearestNeighbor, &paint);
4622 auto dl = builder.Build();
4623
4624 int w = test_image_src_data->width();
4625 int h = test_image_src_data->height();
4626 auto sk_mode = static_cast<SkBlendMode>(mode);
4627 SkPaint sk_paint;
4628 sk_paint.setBlendMode(sk_mode);
4629 sk_paint.setColor(ToSk(color));
4630 sk_paint.setColorFilter(ToSk(color_filter));
4631 sk_paint.setImageFilter(ToSk(image_filter));
4632 for (auto& back_end : CanvasCompareTester::TestBackends) {
4633 auto provider = CanvasCompareTester::GetProvider(back_end);
4634 auto result_surface = provider->MakeOffscreenSurface(
4635 w, h, DlSurfaceProvider::kN32PremulPixelFormat);
4636 SkCanvas* result_canvas = result_surface->sk_surface()->getCanvas();
4637 result_canvas->clear(SK_ColorTRANSPARENT);
4638 result_canvas->drawImage(test_image_dst_data->image(), 0, 0);
4639 result_canvas->drawImage(test_image_src_data->image(), 0, 0,
4640 SkSamplingOptions(), &sk_paint);
4641 if (GrDirectContext* direct_context = GrAsDirectContext(
4642 result_surface->sk_surface()->recordingContext())) {
4643 direct_context->flushAndSubmit();
4644 direct_context->flushAndSubmit(result_surface->sk_surface().get(),
4646 }
4647 std::unique_ptr<RenderResult> result_pixels =
4648 std::make_unique<SkRenderResult>(result_surface->sk_surface());
4649
4650 int all_flags =
4651 check_image_result(test_image_dst_data, result_pixels, dl, desc);
4652 report_results(all_flags, dl, desc);
4653 }
4654 };
4655};
4656
4657TEST_F(DisplayListNopTest, BlendModeAndColorViaColorFilter) {
4658 auto test_mode_filter = [this](DlBlendMode mode) {
4659 for (DlColor color : test_src_colors) {
4660 test_mode_color_via_filter(mode, color);
4661 }
4662 };
4663
4664#define TEST_MODE(V) test_mode_filter(DlBlendMode::V);
4666#undef TEST_MODE
4667}
4668
4669TEST_F(DisplayListNopTest, BlendModeAndColorByRendering) {
4670 auto test_mode_render = [this](DlBlendMode mode) {
4671 // First check rendering a variety of colors onto image
4672 for (DlColor color : test_src_colors) {
4673 test_mode_color_via_rendering(mode, color);
4674 }
4675 };
4676
4677#define TEST_MODE(V) test_mode_render(DlBlendMode::V);
4679#undef TEST_MODE
4680}
4681
4682TEST_F(DisplayListNopTest, BlendModeAndColorAndFiltersByRendering) {
4683 auto test_mode_render = [this](DlBlendMode mode) {
4684 auto image_filter_nomtb = DlColorFilterImageFilter(color_filter_nomtb);
4685 auto image_filter_mtb = DlColorFilterImageFilter(color_filter_mtb);
4686 for (DlColor color : test_src_colors) {
4687 test_attributes_image(mode, color, nullptr, nullptr);
4688 test_attributes_image(mode, color, color_filter_nomtb.get(), nullptr);
4689 test_attributes_image(mode, color, color_filter_mtb.get(), nullptr);
4690 test_attributes_image(mode, color, nullptr, &image_filter_nomtb);
4691 test_attributes_image(mode, color, nullptr, &image_filter_mtb);
4692 }
4693 };
4694
4695#define TEST_MODE(V) test_mode_render(DlBlendMode::V);
4697#undef TEST_MODE
4698}
4699
4700#undef FOR_EACH_BLEND_MODE_ENUM
4701
4702} // namespace testing
4703} // namespace flutter
static int step(int x, SkScalar min, SkScalar max)
Definition BlurTest.cpp:215
static void test_bounds(skiatest::Reporter *reporter, SkClipStack::Element::DeviceSpaceType primType)
static GrDirectContext * GrAsDirectContext(GrContext_Base *base)
SkColor4f color
SkBlendMode
Definition SkBlendMode.h:38
constexpr SkColor SK_ColorTRANSPARENT
Definition SkColor.h:99
static sk_sp< SkImage > color_filter(const SkImage *image, SkColorFilter *colorFilter)
static void test_image(const sk_sp< SkSpecialImage > &img, skiatest::Reporter *reporter, GrRecordingContext *rContext, bool isGPUBacked)
void drawRect(const SkRect &rect, const SkPaint &paint)
void translate(SkScalar dx, SkScalar dy)
void clear(SkColor color)
Definition SkCanvas.h:1199
void rotate(SkScalar degrees)
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
Definition SkCanvas.h:1528
static sk_sp< SkColorFilter > Blend(const SkColor4f &c, sk_sp< SkColorSpace >, SkBlendMode mode)
static sk_sp< SkColorSpace > MakeSRGB()
void setColor(SkColor color)
Definition SkPaint.cpp:119
void setImageFilter(sk_sp< SkImageFilter > imageFilter)
void setBlendMode(SkBlendMode mode)
Definition SkPaint.cpp:151
void setColorFilter(sk_sp< SkColorFilter > colorFilter)
const Paint & paint
#define FOR_EACH_BLEND_MODE_ENUM(FUNC)
#define TEST_MODE(V)
#define MODE_CASE(m)
VkSurfaceKHR surface
Definition main.cc:49
static bool b
struct MyStruct a[10]
TEST_F(FlGnomeSettingsTest, ClockFormat)
GAsyncResult * result
#define FML_LOG(severity)
Definition logging.h:82
double y
double x
SK_API sk_sp< SkSurface > Raster(const SkImageInfo &imageInfo, size_t rowBytes, const SkSurfaceProps *surfaceProps)
Definition __init__.py:1
static std::string BlendModeToString(DlBlendMode mode)
DisplayListRenderingTestBase<::testing::Test > DisplayListRendering
constexpr SkPoint kTestCenter
SkPaint ToSk(const DlPaint &paint)
it will be possible to load the file into Perfetto s trace viewer 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
Definition switches.h:228
SkScalar w
SkScalar h
static SkImageInfo MakeN32Premul(int width, int height)
float fX
x-axis value
float fY
y-axis value
static SkRGBA4f FromColor(SkColor color)
static constexpr SkRect MakeWH(float w, float h)
Definition SkRect.h:609
#define ERROR(message)
static constexpr int kTestHeight
static constexpr int kTestWidth
#define EXPECT_TRUE(handle)
Definition unit_test.h:685

◆ MODE_CASE

#define MODE_CASE (   m)
Value:
case DlBlendMode::m: \
return #m;

◆ 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);