Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright 2015 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "GrTestUtils.h"
      9 #include "GrProcessorUnitTest.h"
     10 #include "GrStyle.h"
     11 #include "SkColorSpace_Base.h"
     12 #include "SkDashPathPriv.h"
     13 #include "SkMatrix.h"
     14 #include "SkPath.h"
     15 #include "SkRRect.h"
     16 
     17 #if GR_TEST_UTILS
     18 
     19 static const SkMatrix& test_matrix(SkRandom* random,
     20                                    bool includeNonPerspective,
     21                                    bool includePerspective) {
     22     static SkMatrix gMatrices[5];
     23     static const int kPerspectiveCount = 1;
     24     static bool gOnce;
     25     if (!gOnce) {
     26         gOnce = true;
     27         gMatrices[0].reset();
     28         gMatrices[1].setTranslate(SkIntToScalar(-100), SkIntToScalar(100));
     29         gMatrices[2].setRotate(SkIntToScalar(17));
     30         gMatrices[3].setRotate(SkIntToScalar(185));
     31         gMatrices[3].postTranslate(SkIntToScalar(66), SkIntToScalar(-33));
     32         gMatrices[3].postScale(SkIntToScalar(2), SK_ScalarHalf);
     33 
     34         // Perspective matrices
     35         gMatrices[4].setRotate(SkIntToScalar(215));
     36         gMatrices[4].set(SkMatrix::kMPersp0, 0.00013f);
     37         gMatrices[4].set(SkMatrix::kMPersp1, -0.000039f);
     38     }
     39 
     40     uint32_t count = static_cast<uint32_t>(SK_ARRAY_COUNT(gMatrices));
     41     if (includeNonPerspective && includePerspective) {
     42         return gMatrices[random->nextULessThan(count)];
     43     } else if (!includeNonPerspective) {
     44         return gMatrices[count - 1 - random->nextULessThan(kPerspectiveCount)];
     45     } else {
     46         SkASSERT(includeNonPerspective && !includePerspective);
     47         return gMatrices[random->nextULessThan(count - kPerspectiveCount)];
     48     }
     49 }
     50 
     51 namespace GrTest {
     52 const SkMatrix& TestMatrix(SkRandom* random) { return test_matrix(random, true, true); }
     53 
     54 const SkMatrix& TestMatrixPreservesRightAngles(SkRandom* random) {
     55     static SkMatrix gMatrices[5];
     56     static bool gOnce;
     57     if (!gOnce) {
     58         gOnce = true;
     59         // identity
     60         gMatrices[0].reset();
     61         // translation
     62         gMatrices[1].setTranslate(SkIntToScalar(-100), SkIntToScalar(100));
     63         // scale
     64         gMatrices[2].setScale(SkIntToScalar(17), SkIntToScalar(17));
     65         // scale + translation
     66         gMatrices[3].setScale(SkIntToScalar(-17), SkIntToScalar(-17));
     67         gMatrices[3].postTranslate(SkIntToScalar(66), SkIntToScalar(-33));
     68         // orthogonal basis vectors
     69         gMatrices[4].reset();
     70         gMatrices[4].setScale(SkIntToScalar(-1), SkIntToScalar(-1));
     71         gMatrices[4].setRotate(47);
     72 
     73         for (size_t i = 0; i < SK_ARRAY_COUNT(gMatrices); i++) {
     74             SkASSERT(gMatrices[i].preservesRightAngles());
     75         }
     76     }
     77     return gMatrices[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gMatrices)))];
     78 }
     79 
     80 const SkMatrix& TestMatrixRectStaysRect(SkRandom* random) {
     81     static SkMatrix gMatrices[6];
     82     static bool gOnce;
     83     if (!gOnce) {
     84         gOnce = true;
     85         // identity
     86         gMatrices[0].reset();
     87         // translation
     88         gMatrices[1].setTranslate(SkIntToScalar(-100), SkIntToScalar(100));
     89         // scale
     90         gMatrices[2].setScale(SkIntToScalar(17), SkIntToScalar(17));
     91         // scale + translation
     92         gMatrices[3].setScale(SkIntToScalar(-17), SkIntToScalar(-17));
     93         gMatrices[3].postTranslate(SkIntToScalar(66), SkIntToScalar(-33));
     94         // reflection
     95         gMatrices[4].setScale(SkIntToScalar(-1), SkIntToScalar(-1));
     96         // 90 degress rotation
     97         gMatrices[5].setRotate(90);
     98 
     99         for (size_t i = 0; i < SK_ARRAY_COUNT(gMatrices); i++) {
    100             SkASSERT(gMatrices[i].rectStaysRect());
    101         }
    102     }
    103     return gMatrices[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gMatrices)))];
    104 }
    105 
    106 const SkMatrix& TestMatrixInvertible(SkRandom* random) { return test_matrix(random, true, false); }
    107 const SkMatrix& TestMatrixPerspective(SkRandom* random) { return test_matrix(random, false, true); }
    108 
    109 const SkRect& TestRect(SkRandom* random) {
    110     static SkRect gRects[7];
    111     static bool gOnce;
    112     if (!gOnce) {
    113         gOnce = true;
    114         gRects[0] = SkRect::MakeWH(1.f, 1.f);
    115         gRects[1] = SkRect::MakeWH(1.0f, 256.0f);
    116         gRects[2] = SkRect::MakeWH(256.0f, 1.0f);
    117         gRects[3] = SkRect::MakeLargest();
    118         gRects[4] = SkRect::MakeLTRB(-65535.0f, -65535.0f, 65535.0f, 65535.0f);
    119         gRects[5] = SkRect::MakeLTRB(-10.0f, -10.0f, 10.0f, 10.0f);
    120     }
    121     return gRects[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gRects)))];
    122 }
    123 
    124 // Just some simple rects for code which expects its input very sanitized
    125 const SkRect& TestSquare(SkRandom* random) {
    126     static SkRect gRects[2];
    127     static bool gOnce;
    128     if (!gOnce) {
    129         gOnce = true;
    130         gRects[0] = SkRect::MakeWH(128.f, 128.f);
    131         gRects[1] = SkRect::MakeWH(256.0f, 256.0f);
    132     }
    133     return gRects[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gRects)))];
    134 }
    135 
    136 const SkRRect& TestRRectSimple(SkRandom* random) {
    137     static SkRRect gRRect[2];
    138     static bool gOnce;
    139     if (!gOnce) {
    140         gOnce = true;
    141         SkRect rectangle = SkRect::MakeWH(10.f, 20.f);
    142         // true round rect with circular corners
    143         gRRect[0].setRectXY(rectangle, 1.f, 1.f);
    144         // true round rect with elliptical corners
    145         gRRect[1].setRectXY(rectangle, 2.0f, 1.0f);
    146 
    147         for (size_t i = 0; i < SK_ARRAY_COUNT(gRRect); i++) {
    148             SkASSERT(gRRect[i].isSimple());
    149         }
    150     }
    151     return gRRect[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gRRect)))];
    152 }
    153 
    154 const SkPath& TestPath(SkRandom* random) {
    155     static SkPath gPath[7];
    156     static bool gOnce;
    157     if (!gOnce) {
    158         gOnce = true;
    159         // line
    160         gPath[0].moveTo(0.f, 0.f);
    161         gPath[0].lineTo(10.f, 10.f);
    162         // quad
    163         gPath[1].moveTo(0.f, 0.f);
    164         gPath[1].quadTo(10.f, 10.f, 20.f, 20.f);
    165         // conic
    166         gPath[2].moveTo(0.f, 0.f);
    167         gPath[2].conicTo(10.f, 10.f, 20.f, 20.f, 1.f);
    168         // cubic
    169         gPath[3].moveTo(0.f, 0.f);
    170         gPath[3].cubicTo(10.f, 10.f, 20.f, 20.f, 30.f, 30.f);
    171         // all three
    172         gPath[4].moveTo(0.f, 0.f);
    173         gPath[4].lineTo(10.f, 10.f);
    174         gPath[4].quadTo(10.f, 10.f, 20.f, 20.f);
    175         gPath[4].conicTo(10.f, 10.f, 20.f, 20.f, 1.f);
    176         gPath[4].cubicTo(10.f, 10.f, 20.f, 20.f, 30.f, 30.f);
    177         // convex
    178         gPath[5].moveTo(0.0f, 0.0f);
    179         gPath[5].lineTo(10.0f, 0.0f);
    180         gPath[5].lineTo(10.0f, 10.0f);
    181         gPath[5].lineTo(0.0f, 10.0f);
    182         gPath[5].close();
    183         // concave
    184         gPath[6].moveTo(0.0f, 0.0f);
    185         gPath[6].lineTo(5.0f, 5.0f);
    186         gPath[6].lineTo(10.0f, 0.0f);
    187         gPath[6].lineTo(10.0f, 10.0f);
    188         gPath[6].lineTo(0.0f, 10.0f);
    189         gPath[6].close();
    190     }
    191 
    192     return gPath[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gPath)))];
    193 }
    194 
    195 const SkPath& TestPathConvex(SkRandom* random) {
    196     static SkPath gPath[3];
    197     static bool gOnce;
    198     if (!gOnce) {
    199         gOnce = true;
    200         // narrow rect
    201         gPath[0].moveTo(-1.5f, -50.0f);
    202         gPath[0].lineTo(-1.5f, -50.0f);
    203         gPath[0].lineTo( 1.5f, -50.0f);
    204         gPath[0].lineTo( 1.5f,  50.0f);
    205         gPath[0].lineTo(-1.5f,  50.0f);
    206         // degenerate
    207         gPath[1].moveTo(-0.025f, -0.025f);
    208         gPath[1].lineTo(-0.025f, -0.025f);
    209         gPath[1].lineTo( 0.025f, -0.025f);
    210         gPath[1].lineTo( 0.025f,  0.025f);
    211         gPath[1].lineTo(-0.025f,  0.025f);
    212         // clipped triangle
    213         gPath[2].moveTo(-10.0f, -50.0f);
    214         gPath[2].lineTo(-10.0f, -50.0f);
    215         gPath[2].lineTo( 10.0f, -50.0f);
    216         gPath[2].lineTo( 50.0f,  31.0f);
    217         gPath[2].lineTo( 40.0f,  50.0f);
    218         gPath[2].lineTo(-40.0f,  50.0f);
    219         gPath[2].lineTo(-50.0f,  31.0f);
    220 
    221         for (size_t i = 0; i < SK_ARRAY_COUNT(gPath); i++) {
    222             SkASSERT(SkPath::kConvex_Convexity == gPath[i].getConvexity());
    223         }
    224     }
    225 
    226     return gPath[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gPath)))];
    227 }
    228 
    229 static void randomize_stroke_rec(SkStrokeRec* rec, SkRandom* random) {
    230     bool strokeAndFill = random->nextBool();
    231     SkScalar strokeWidth = random->nextBool() ? 0.f : 1.f;
    232     rec->setStrokeStyle(strokeWidth, strokeAndFill);
    233 
    234     SkPaint::Cap cap = SkPaint::Cap(random->nextULessThan(SkPaint::kCapCount));
    235     SkPaint::Join join = SkPaint::Join(random->nextULessThan(SkPaint::kJoinCount));
    236     SkScalar miterLimit = random->nextRangeScalar(1.f, 5.f);
    237     rec->setStrokeParams(cap, join, miterLimit);
    238 }
    239 
    240 SkStrokeRec TestStrokeRec(SkRandom* random) {
    241     SkStrokeRec::InitStyle style =
    242             SkStrokeRec::InitStyle(random->nextULessThan(SkStrokeRec::kFill_InitStyle + 1));
    243     SkStrokeRec rec(style);
    244     randomize_stroke_rec(&rec, random);
    245     return rec;
    246 }
    247 
    248 void TestStyle(SkRandom* random, GrStyle* style) {
    249     SkStrokeRec::InitStyle initStyle =
    250             SkStrokeRec::InitStyle(random->nextULessThan(SkStrokeRec::kFill_InitStyle + 1));
    251     SkStrokeRec stroke(initStyle);
    252     randomize_stroke_rec(&stroke, random);
    253     sk_sp<SkPathEffect> pe;
    254     if (random->nextBool()) {
    255         int cnt = random->nextRangeU(1, 50) * 2;
    256         std::unique_ptr<SkScalar[]> intervals(new SkScalar[cnt]);
    257         SkScalar sum = 0;
    258         for (int i = 0; i < cnt; i++) {
    259             intervals[i] = random->nextRangeScalar(SkDoubleToScalar(0.01),
    260                                                    SkDoubleToScalar(10.0));
    261             sum += intervals[i];
    262         }
    263         SkScalar phase = random->nextRangeScalar(0, sum);
    264         pe = TestDashPathEffect::Make(intervals.get(), cnt, phase);
    265     }
    266     *style = GrStyle(stroke, std::move(pe));
    267 }
    268 
    269 TestDashPathEffect::TestDashPathEffect(const SkScalar* intervals, int count, SkScalar phase) {
    270     fCount = count;
    271     fIntervals.reset(count);
    272     memcpy(fIntervals.get(), intervals, count * sizeof(SkScalar));
    273     SkDashPath::CalcDashParameters(phase, intervals, count, &fInitialDashLength,
    274                                    &fInitialDashIndex, &fIntervalLength, &fPhase);
    275 }
    276 
    277     bool TestDashPathEffect::filterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec,
    278                                      const SkRect* cullRect) const {
    279     return SkDashPath::InternalFilter(dst, src, rec, cullRect, fIntervals.get(), fCount,
    280                                       fInitialDashLength, fInitialDashIndex, fIntervalLength);
    281 }
    282 
    283 SkPathEffect::DashType TestDashPathEffect::asADash(DashInfo* info) const {
    284     if (info) {
    285         if (info->fCount >= fCount && info->fIntervals) {
    286             memcpy(info->fIntervals, fIntervals.get(), fCount * sizeof(SkScalar));
    287         }
    288         info->fCount = fCount;
    289         info->fPhase = fPhase;
    290     }
    291     return kDash_DashType;
    292 }
    293 
    294 sk_sp<SkColorSpace> TestColorSpace(SkRandom* random) {
    295     static sk_sp<SkColorSpace> gColorSpaces[3];
    296     static bool gOnce;
    297     if (!gOnce) {
    298         gOnce = true;
    299         // No color space (legacy mode)
    300         gColorSpaces[0] = nullptr;
    301         // sRGB or Adobe
    302         gColorSpaces[1] = SkColorSpace::MakeSRGB();
    303         gColorSpaces[2] = SkColorSpace_Base::MakeNamed(SkColorSpace_Base::kAdobeRGB_Named);
    304     }
    305     return gColorSpaces[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gColorSpaces)))];
    306 }
    307 
    308 sk_sp<GrColorSpaceXform> TestColorXform(SkRandom* random) {
    309     static sk_sp<GrColorSpaceXform> gXforms[3];
    310     static bool gOnce;
    311     if (!gOnce) {
    312         gOnce = true;
    313         sk_sp<SkColorSpace> srgb = SkColorSpace::MakeSRGB();
    314         sk_sp<SkColorSpace> adobe = SkColorSpace_Base::MakeNamed(SkColorSpace_Base::kAdobeRGB_Named);
    315         // No gamut change
    316         gXforms[0] = nullptr;
    317         // To larger gamut
    318         gXforms[1] = GrColorSpaceXform::Make(srgb.get(), adobe.get());
    319         // To smaller gamut
    320         gXforms[2] = GrColorSpaceXform::Make(adobe.get(), srgb.get());
    321     }
    322     return gXforms[random->nextULessThan(static_cast<uint32_t>(SK_ARRAY_COUNT(gXforms)))];
    323 }
    324 
    325 TestAsFPArgs::TestAsFPArgs(GrProcessorTestData* d) {
    326     fViewMatrixStorage = TestMatrix(d->fRandom);
    327     fColorSpaceStorage = TestColorSpace(d->fRandom);
    328 
    329     fArgs.fContext = d->context();
    330     fArgs.fViewMatrix = &fViewMatrixStorage;
    331     fArgs.fLocalMatrix = nullptr;
    332     fArgs.fFilterQuality = kNone_SkFilterQuality;
    333     fArgs.fDstColorSpace = fColorSpaceStorage.get();
    334 }
    335 
    336 }  // namespace GrTest
    337 
    338 #endif
    339