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