blob: 711b7182a5815b50858ead9a796bd47d4e6a3af6 [file] [log] [blame]
// 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.
#ifndef FLUTTER_FLOW_DISPLAY_LIST_COMPLEXITY_UNITTESTS_H_
#define FLUTTER_FLOW_DISPLAY_LIST_COMPLEXITY_UNITTESTS_H_
#include "flutter/display_list/display_list.h"
#include "flutter/display_list/display_list_builder.h"
#include "third_party/skia/include/core/SkPicture.h"
#include "third_party/skia/include/core/SkPictureRecorder.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/effects/SkBlenders.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"
namespace flutter {
namespace testing {
sk_sp<DisplayList> GetSampleDisplayList();
sk_sp<DisplayList> GetSampleDisplayList(int ops);
sk_sp<DisplayList> GetSampleNestedDisplayList();
typedef const std::function<void(DisplayListBuilder&)> DlInvoker;
constexpr SkPoint kEndPoints[] = {
{0, 0},
{100, 100},
};
const DlColor kColors[] = {
DlColor::kGreen(),
DlColor::kYellow(),
DlColor::kBlue(),
};
constexpr float kStops[] = {
0.0,
0.5,
1.0,
};
static std::vector<uint32_t> color_vector(kColors, kColors + 3);
static std::vector<float> stops_vector(kStops, kStops + 3);
// clang-format off
constexpr float kRotateColorMatrix[20] = {
0, 1, 0, 0, 0,
0, 0, 1, 0, 0,
1, 0, 0, 0, 0,
0, 0, 0, 1, 0,
};
constexpr float kInvertColorMatrix[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,
};
// clang-format on
const SkScalar kTestDashes1[] = {4.0, 2.0};
const SkScalar kTestDashes2[] = {1.0, 1.5};
constexpr SkPoint TestPoints[] = {
{10, 10},
{20, 20},
{10, 20},
{20, 10},
};
#define TestPointCount sizeof(TestPoints) / (sizeof(TestPoints[0]))
static DlImageSampling kNearestSampling = DlImageSampling::kNearestNeighbor;
static DlImageSampling kLinearSampling = DlImageSampling::kLinear;
static sk_sp<DlImage> MakeTestImage(int w, int h, int checker_size) {
sk_sp<SkSurface> surface = SkSurface::MakeRasterN32Premul(w, h);
SkCanvas* canvas = surface->getCanvas();
SkPaint p0, p1;
p0.setStyle(SkPaint::kFill_Style);
p0.setColor(SK_ColorGREEN);
p1.setStyle(SkPaint::kFill_Style);
p1.setColor(SK_ColorBLUE);
p1.setAlpha(128);
for (int y = 0; y < w; y += checker_size) {
for (int x = 0; x < h; x += checker_size) {
SkPaint& cellp = ((x + y) & 1) == 0 ? p0 : p1;
canvas->drawRect(SkRect::MakeXYWH(x, y, checker_size, checker_size),
cellp);
}
}
return DlImage::Make(surface->makeImageSnapshot());
}
static auto TestImage1 = MakeTestImage(40, 40, 5);
static auto TestImage2 = MakeTestImage(50, 50, 5);
static const sk_sp<SkBlender> kTestBlender1 =
SkBlenders::Arithmetic(0.2, 0.2, 0.2, 0.2, false);
static const sk_sp<SkBlender> kTestBlender2 =
SkBlenders::Arithmetic(0.2, 0.2, 0.2, 0.2, true);
static const sk_sp<SkBlender> kTestBlender3 =
SkBlenders::Arithmetic(0.3, 0.3, 0.3, 0.3, true);
static const DlImageColorSource kTestSource1(TestImage1,
DlTileMode::kClamp,
DlTileMode::kMirror,
kLinearSampling);
static const std::shared_ptr<DlColorSource> kTestSource2 =
DlColorSource::MakeLinear(kEndPoints[0],
kEndPoints[1],
3,
kColors,
kStops,
DlTileMode::kMirror);
static const std::shared_ptr<DlColorSource> kTestSource3 =
DlColorSource::MakeRadial(kEndPoints[0],
10.0,
3,
kColors,
kStops,
DlTileMode::kMirror);
static const std::shared_ptr<DlColorSource> kTestSource4 =
DlColorSource::MakeConical(kEndPoints[0],
10.0,
kEndPoints[1],
200.0,
3,
kColors,
kStops,
DlTileMode::kDecal);
static const std::shared_ptr<DlColorSource> kTestSource5 =
DlColorSource::MakeSweep(kEndPoints[0],
0.0,
360.0,
3,
kColors,
kStops,
DlTileMode::kDecal);
static const DlBlendColorFilter kTestBlendColorFilter1(DlColor::kRed(),
DlBlendMode::kDstATop);
static const DlBlendColorFilter kTestBlendColorFilter2(DlColor::kBlue(),
DlBlendMode::kDstATop);
static const DlBlendColorFilter kTestBlendColorFilter3(DlColor::kRed(),
DlBlendMode::kDstIn);
static const DlMatrixColorFilter kTestMatrixColorFilter1(kRotateColorMatrix);
static const DlMatrixColorFilter kTestMatrixColorFilter2(kInvertColorMatrix);
static const DlBlurImageFilter kTestBlurImageFilter1(5.0,
5.0,
DlTileMode::kClamp);
static const DlBlurImageFilter kTestBlurImageFilter2(6.0,
5.0,
DlTileMode::kClamp);
static const DlBlurImageFilter kTestBlurImageFilter3(5.0,
6.0,
DlTileMode::kClamp);
static const DlBlurImageFilter kTestBlurImageFilter4(5.0,
5.0,
DlTileMode::kDecal);
static const DlDilateImageFilter kTestDilateImageFilter1(5.0, 5.0);
static const DlDilateImageFilter kTestDilateImageFilter2(6.0, 5.0);
static const DlDilateImageFilter kTestDilateImageFilter3(5.0, 6.0);
static const DlErodeImageFilter kTestErodeImageFilter1(5.0, 5.0);
static const DlErodeImageFilter kTestErodeImageFilter2(6.0, 5.0);
static const DlErodeImageFilter kTestErodeImageFilter3(5.0, 6.0);
static const DlMatrixImageFilter kTestMatrixImageFilter1(
SkMatrix::RotateDeg(45),
kNearestSampling);
static const DlMatrixImageFilter kTestMatrixImageFilter2(
SkMatrix::RotateDeg(85),
kNearestSampling);
static const DlMatrixImageFilter kTestMatrixImageFilter3(
SkMatrix::RotateDeg(45),
kLinearSampling);
static const DlComposeImageFilter kTestComposeImageFilter1(
kTestBlurImageFilter1,
kTestMatrixImageFilter1);
static const DlComposeImageFilter kTestComposeImageFilter2(
kTestBlurImageFilter2,
kTestMatrixImageFilter1);
static const DlComposeImageFilter kTestComposeImageFilter3(
kTestBlurImageFilter1,
kTestMatrixImageFilter2);
static const DlColorFilterImageFilter kTestCFImageFilter1(
kTestBlendColorFilter1);
static const DlColorFilterImageFilter kTestCFImageFilter2(
kTestBlendColorFilter2);
static const std::shared_ptr<DlPathEffect> kTestPathEffect1 =
DlDashPathEffect::Make(kTestDashes1, 2, 0.0f);
static const std::shared_ptr<DlPathEffect> kTestPathEffect2 =
DlDashPathEffect::Make(kTestDashes2, 2, 0.0f);
static const DlBlurMaskFilter kTestMaskFilter1(kNormal_SkBlurStyle, 3.0);
static const DlBlurMaskFilter kTestMaskFilter2(kNormal_SkBlurStyle, 5.0);
static const DlBlurMaskFilter kTestMaskFilter3(kSolid_SkBlurStyle, 3.0);
static const DlBlurMaskFilter kTestMaskFilter4(kInner_SkBlurStyle, 3.0);
static const DlBlurMaskFilter kTestMaskFilter5(kOuter_SkBlurStyle, 3.0);
constexpr SkRect kTestBounds = SkRect::MakeLTRB(10, 10, 50, 60);
static const SkRRect kTestRRect = SkRRect::MakeRectXY(kTestBounds, 5, 5);
static const SkRRect kTestRRectRect = SkRRect::MakeRect(kTestBounds);
static const SkRRect kTestInnerRRect =
SkRRect::MakeRectXY(kTestBounds.makeInset(5, 5), 2, 2);
static const SkPath kTestPathRect = SkPath::Rect(kTestBounds);
static const SkPath kTestPathOval = SkPath::Oval(kTestBounds);
static const SkPath kTestPath1 =
SkPath::Polygon({{0, 0}, {10, 10}, {10, 0}, {0, 10}}, true);
static const SkPath kTestPath2 =
SkPath::Polygon({{0, 0}, {10, 10}, {0, 10}, {10, 0}}, true);
static const SkPath kTestPath3 =
SkPath::Polygon({{0, 0}, {10, 10}, {10, 0}, {0, 10}}, false);
static const SkMatrix kTestMatrix1 = SkMatrix::Scale(2, 2);
static const SkMatrix kTestMatrix2 = SkMatrix::RotateDeg(45);
static std::shared_ptr<const DlVertices> TestVertices1 =
DlVertices::Make(DlVertexMode::kTriangles, //
3,
TestPoints,
nullptr,
kColors);
static std::shared_ptr<const DlVertices> TestVertices2 =
DlVertices::Make(DlVertexMode::kTriangleFan, //
3,
TestPoints,
nullptr,
kColors);
static constexpr int kTestDivs1[] = {10, 20, 30};
static constexpr int kTestDivs2[] = {15, 20, 25};
static constexpr int kTestDivs3[] = {15, 25};
static constexpr SkCanvas::Lattice::RectType kTestRTypes[] = {
SkCanvas::Lattice::RectType::kDefault,
SkCanvas::Lattice::RectType::kTransparent,
SkCanvas::Lattice::RectType::kFixedColor,
SkCanvas::Lattice::RectType::kDefault,
SkCanvas::Lattice::RectType::kTransparent,
SkCanvas::Lattice::RectType::kFixedColor,
SkCanvas::Lattice::RectType::kDefault,
SkCanvas::Lattice::RectType::kTransparent,
SkCanvas::Lattice::RectType::kFixedColor,
};
static constexpr SkColor kTestLatticeColors[] = {
SK_ColorBLUE, SK_ColorGREEN, SK_ColorYELLOW,
SK_ColorBLUE, SK_ColorGREEN, SK_ColorYELLOW,
SK_ColorBLUE, SK_ColorGREEN, SK_ColorYELLOW,
};
static constexpr SkIRect kTestLatticeSrcRect = {1, 1, 39, 39};
static sk_sp<SkPicture> MakeTestPicture(int w, int h, SkColor color) {
SkPictureRecorder recorder;
SkRTreeFactory rtree_factory;
SkCanvas* cv = recorder.beginRecording(kTestBounds, &rtree_factory);
SkPaint paint;
paint.setColor(color);
paint.setStyle(SkPaint::kFill_Style);
cv->drawRect(SkRect::MakeWH(w, h), paint);
return recorder.finishRecordingAsPicture();
}
static sk_sp<SkPicture> TestPicture1 = MakeTestPicture(20, 20, SK_ColorGREEN);
static sk_sp<SkPicture> TestPicture2 = MakeTestPicture(25, 25, SK_ColorBLUE);
static sk_sp<DisplayList> MakeTestDisplayList(int w, int h, SkColor color) {
DisplayListBuilder builder;
builder.setColor(color);
builder.drawRect(SkRect::MakeWH(w, h));
return builder.Build();
}
static sk_sp<DisplayList> TestDisplayList1 =
MakeTestDisplayList(20, 20, SK_ColorGREEN);
static sk_sp<DisplayList> TestDisplayList2 =
MakeTestDisplayList(25, 25, SK_ColorBLUE);
static sk_sp<SkTextBlob> MakeTextBlob(std::string string) {
return SkTextBlob::MakeFromText(string.c_str(), string.size(), SkFont(),
SkTextEncoding::kUTF8);
}
static sk_sp<SkTextBlob> TestBlob1 = MakeTextBlob("TestBlob1");
static sk_sp<SkTextBlob> TestBlob2 = MakeTextBlob("TestBlob2");
struct DisplayListInvocation {
unsigned int op_count_;
size_t byte_count_;
// in some cases, running the sequence through an SkCanvas will result
// in fewer ops/bytes. Attribute invocations are recorded in an SkPaint
// and not forwarded on, and SkCanvas culls unused save/restore/transforms.
int sk_op_count_;
size_t sk_byte_count_;
DlInvoker invoker;
bool supports_group_opacity_ = false;
bool sk_version_matches() {
return (static_cast<int>(op_count_) == sk_op_count_ &&
byte_count_ == sk_byte_count_);
}
// A negative sk_op_count means "do not test this op".
// Used mainly for these cases:
// - we cannot encode a DrawShadowRec (Skia private header)
// - SkCanvas cannot receive a DisplayList
// - SkCanvas may or may not inline an SkPicture
bool sk_testing_invalid() { return sk_op_count_ < 0; }
bool is_empty() { return byte_count_ == 0; }
bool supports_group_opacity() { return supports_group_opacity_; }
unsigned int op_count() { return op_count_; }
// byte count for the individual ops, no DisplayList overhead
size_t raw_byte_count() { return byte_count_; }
// byte count for the ops with DisplayList overhead, comparable
// to |DisplayList.byte_count().
size_t byte_count() { return sizeof(DisplayList) + byte_count_; }
int sk_op_count() { return sk_op_count_; }
// byte count for the ops with DisplayList overhead as translated
// through an SkCanvas interface, comparable to |DisplayList.byte_count().
size_t sk_byte_count() { return sizeof(DisplayList) + sk_byte_count_; }
void Invoke(DisplayListBuilder& builder) { invoker(builder); }
sk_sp<DisplayList> Build() {
DisplayListBuilder builder;
invoker(builder);
return builder.Build();
}
};
struct DisplayListInvocationGroup {
std::string op_name;
std::vector<DisplayListInvocation> variants;
};
std::vector<DisplayListInvocationGroup> CreateAllRenderingOps();
std::vector<DisplayListInvocationGroup> CreateAllGroups();
} // namespace testing
} // namespace flutter
#endif // FLUTTER_FLOW_DISPLAY_LIST_COMPLEXITY_UNITTESTS_H_