From 5122967e60915d2b4322bbd059f6f641c11f5216 Mon Sep 17 00:00:00 2001 From: fmalita Date: Mon, 22 Aug 2016 06:22:28 -0700 Subject: [PATCH] Add a gradient edge optimization test R=reed@google.com GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2267593002 Review-Url: https://codereview.chromium.org/2267593002 --- tests/GradientTest.cpp | 149 ++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 117 insertions(+), 32 deletions(-) diff --git a/tests/GradientTest.cpp b/tests/GradientTest.cpp index 3ed2f51..1e8f393 100644 --- a/tests/GradientTest.cpp +++ b/tests/GradientTest.cpp @@ -67,12 +67,12 @@ struct GradRec { }; -static void none_gradproc(skiatest::Reporter* reporter, const GradRec&) { +static void none_gradproc(skiatest::Reporter* reporter, const GradRec&, const GradRec&) { sk_sp s(SkShader::MakeEmptyShader()); REPORTER_ASSERT(reporter, SkShader::kNone_GradientType == s->asAGradient(nullptr)); } -static void color_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { +static void color_gradproc(skiatest::Reporter* reporter, const GradRec& rec, const GradRec&) { SkAutoTUnref s(new SkColorShader(rec.fColors[0])); REPORTER_ASSERT(reporter, SkShader::kColor_GradientType == s->asAGradient(nullptr)); @@ -83,48 +83,54 @@ static void color_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { REPORTER_ASSERT(reporter, 1 == info.fColorCount); } -static void linear_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { - sk_sp s(SkGradientShader::MakeLinear(rec.fPoint, rec.fColors, rec.fPos, - rec.fColorCount, rec.fTileMode)); +static void linear_gradproc(skiatest::Reporter* reporter, const GradRec& buildRec, + const GradRec& checkRec) { + sk_sp s(SkGradientShader::MakeLinear(buildRec.fPoint, buildRec.fColors, buildRec.fPos, + buildRec.fColorCount, buildRec.fTileMode)); SkShader::GradientInfo info; - rec.gradCheck(reporter, s, &info, SkShader::kLinear_GradientType); - REPORTER_ASSERT(reporter, !memcmp(info.fPoint, rec.fPoint, 2 * sizeof(SkPoint))); + checkRec.gradCheck(reporter, s, &info, SkShader::kLinear_GradientType); + REPORTER_ASSERT(reporter, !memcmp(info.fPoint, checkRec.fPoint, 2 * sizeof(SkPoint))); } -static void radial_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { - sk_sp s(SkGradientShader::MakeRadial(rec.fPoint[0], rec.fRadius[0], rec.fColors, - rec.fPos, rec.fColorCount, rec.fTileMode)); +static void radial_gradproc(skiatest::Reporter* reporter, const GradRec& buildRec, + const GradRec& checkRec) { + sk_sp s(SkGradientShader::MakeRadial(buildRec.fPoint[0], buildRec.fRadius[0], + buildRec.fColors, buildRec.fPos, + buildRec.fColorCount, buildRec.fTileMode)); SkShader::GradientInfo info; - rec.gradCheck(reporter, s, &info, SkShader::kRadial_GradientType); - REPORTER_ASSERT(reporter, info.fPoint[0] == rec.fPoint[0]); - REPORTER_ASSERT(reporter, info.fRadius[0] == rec.fRadius[0]); + checkRec.gradCheck(reporter, s, &info, SkShader::kRadial_GradientType); + REPORTER_ASSERT(reporter, info.fPoint[0] == checkRec.fPoint[0]); + REPORTER_ASSERT(reporter, info.fRadius[0] == checkRec.fRadius[0]); } -static void sweep_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { - sk_sp s(SkGradientShader::MakeSweep(rec.fPoint[0].fX, rec.fPoint[0].fY, rec.fColors, - rec.fPos, rec.fColorCount)); +static void sweep_gradproc(skiatest::Reporter* reporter, const GradRec& buildRec, + const GradRec& checkRec) { + sk_sp s(SkGradientShader::MakeSweep(buildRec.fPoint[0].fX, buildRec.fPoint[0].fY, + buildRec.fColors, buildRec.fPos, + buildRec.fColorCount)); SkShader::GradientInfo info; - rec.gradCheck(reporter, s, &info, SkShader::kSweep_GradientType); - REPORTER_ASSERT(reporter, info.fPoint[0] == rec.fPoint[0]); + checkRec.gradCheck(reporter, s, &info, SkShader::kSweep_GradientType); + REPORTER_ASSERT(reporter, info.fPoint[0] == checkRec.fPoint[0]); } -static void conical_gradproc(skiatest::Reporter* reporter, const GradRec& rec) { - sk_sp s(SkGradientShader::MakeTwoPointConical(rec.fPoint[0], - rec.fRadius[0], - rec.fPoint[1], - rec.fRadius[1], - rec.fColors, - rec.fPos, - rec.fColorCount, - rec.fTileMode)); +static void conical_gradproc(skiatest::Reporter* reporter, const GradRec& buildRec, + const GradRec& checkRec) { + sk_sp s(SkGradientShader::MakeTwoPointConical(buildRec.fPoint[0], + buildRec.fRadius[0], + buildRec.fPoint[1], + buildRec.fRadius[1], + buildRec.fColors, + buildRec.fPos, + buildRec.fColorCount, + buildRec.fTileMode)); SkShader::GradientInfo info; - rec.gradCheck(reporter, s, &info, SkShader::kConical_GradientType); - REPORTER_ASSERT(reporter, !memcmp(info.fPoint, rec.fPoint, 2 * sizeof(SkPoint))); - REPORTER_ASSERT(reporter, !memcmp(info.fRadius, rec.fRadius, 2 * sizeof(SkScalar))); + checkRec.gradCheck(reporter, s, &info, SkShader::kConical_GradientType); + REPORTER_ASSERT(reporter, !memcmp(info.fPoint, checkRec.fPoint, 2 * sizeof(SkPoint))); + REPORTER_ASSERT(reporter, !memcmp(info.fRadius, checkRec.fRadius, 2 * sizeof(SkScalar))); } // Ensure that repeated color gradients behave like drawing a single color @@ -150,7 +156,7 @@ static void TestConstantGradient(skiatest::Reporter*) { } } -typedef void (*GradProc)(skiatest::Reporter* reporter, const GradRec&); +typedef void (*GradProc)(skiatest::Reporter* reporter, const GradRec&, const GradRec&); static void TestGradientShaders(skiatest::Reporter* reporter) { static const SkColor gColors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE }; @@ -179,7 +185,85 @@ static void TestGradientShaders(skiatest::Reporter* reporter) { }; for (size_t i = 0; i < SK_ARRAY_COUNT(gProcs); ++i) { - gProcs[i](reporter, rec); + gProcs[i](reporter, rec, rec); + } +} + +static void TestGradientOptimization(skiatest::Reporter* reporter) { + static const struct { + GradProc fProc; + bool fIsClampRestricted; + } gProcInfo[] = { + { linear_gradproc , false }, + { radial_gradproc , false }, + { sweep_gradproc , true }, // sweep is funky in that it always pretends to be kClamp. + { conical_gradproc, false }, + }; + + static const SkColor gC_00[] = { 0xff000000, 0xff000000 }; + static const SkColor gC_01[] = { 0xff000000, 0xffffffff }; + static const SkColor gC_11[] = { 0xffffffff, 0xffffffff }; + static const SkColor gC_001[] = { 0xff000000, 0xff000000, 0xffffffff }; + static const SkColor gC_011[] = { 0xff000000, 0xffffffff, 0xffffffff }; + static const SkColor gC_0011[] = { 0xff000000, 0xff000000, 0xffffffff, 0xffffffff }; + + static const SkScalar gP_01[] = { 0, 1 }; + static const SkScalar gP_001[] = { 0, 0, 1 }; + static const SkScalar gP_011[] = { 0, 1, 1 }; + static const SkScalar gP_0x1[] = { 0, .5f, 1 }; + static const SkScalar gP_0011[] = { 0, 0, 1, 1 }; + + static const SkPoint gPts[] = { {0, 0}, {1, 1} }; + static const SkScalar gRadii[] = { 1, 2 }; + + static const struct { + const SkColor* fCol; + const SkScalar* fPos; + int fCount; + + const SkColor* fExpectedCol; + const SkScalar* fExpectedPos; + int fExpectedCount; + bool fRequiresNonClamp; + } gTests[] = { + { gC_001, gP_001, 3, gC_01, gP_01, 2, false }, + { gC_001, gP_011, 3, gC_00, gP_01, 2, true }, + { gC_001, gP_0x1, 3, gC_001, gP_0x1, 3, false }, + { gC_001, nullptr, 3, gC_001, gP_0x1, 3, false }, + + { gC_011, gP_001, 3, gC_11, gP_01, 2, true }, + { gC_011, gP_011, 3, gC_01, gP_01, 2, false }, + { gC_011, gP_0x1, 3, gC_011, gP_0x1, 3, false }, + { gC_011, nullptr, 3, gC_011, gP_0x1, 3, false }, + + { gC_0011, gP_0011, 4, gC_0011, gP_0011, 4, false }, + }; + + for (size_t i = 0; i < SK_ARRAY_COUNT(gProcInfo); ++i) { + for (int mode = 0; mode < SkShader::kTileModeCount; ++mode) { + if (gProcInfo[i].fIsClampRestricted && mode != SkShader::kClamp_TileMode) { + continue; + } + + for (size_t t = 0; t < SK_ARRAY_COUNT(gTests); ++t) { + GradRec rec; + rec.fColorCount = gTests[t].fCount; + rec.fColors = gTests[t].fCol; + rec.fPos = gTests[t].fPos; + rec.fTileMode = static_cast(mode); + rec.fPoint = gPts; + rec.fRadius = gRadii; + + GradRec expected = rec; + if (!gTests[t].fRequiresNonClamp || mode != SkShader::kClamp_TileMode) { + expected.fColorCount = gTests[t].fExpectedCount; + expected.fColors = gTests[t].fExpectedCol; + expected.fPos = gTests[t].fExpectedPos; + } + + gProcInfo[i].fProc(reporter, rec, expected); + } + } } } @@ -271,6 +355,7 @@ static void text_degenerate_linear(skiatest::Reporter*) { DEF_TEST(Gradient, reporter) { TestGradientShaders(reporter); + TestGradientOptimization(reporter); TestConstantGradient(reporter); test_big_grad(reporter); test_nearly_vertical(reporter); -- 2.7.4