• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "src/gpu/ganesh/GrTestUtils.h"
9 
10 #include "include/core/SkColorSpace.h"
11 #include "include/core/SkMatrix.h"
12 #include "include/core/SkPathBuilder.h"
13 #include "include/core/SkRRect.h"
14 #include "src/core/SkRectPriv.h"
15 #include "src/gpu/ganesh/GrColorInfo.h"
16 #include "src/gpu/ganesh/GrProcessorUnitTest.h"
17 #include "src/gpu/ganesh/GrStyle.h"
18 #include "src/utils/SkDashPathPriv.h"
19 
20 #if GR_TEST_UTILS
21 
test_matrix(SkRandom * random,bool includeNonPerspective,bool includePerspective)22 static const SkMatrix& test_matrix(SkRandom* random,
23                                    bool includeNonPerspective,
24                                    bool includePerspective) {
25     static SkMatrix gMatrices[5];
26     static const int kPerspectiveCount = 1;
27     static bool gOnce;
28     if (!gOnce) {
29         gOnce = true;
30         gMatrices[0].reset();
31         gMatrices[1].setTranslate(SkIntToScalar(-100), SkIntToScalar(100));
32         gMatrices[2].setRotate(SkIntToScalar(17));
33         gMatrices[3].setRotate(SkIntToScalar(185));
34         gMatrices[3].postTranslate(SkIntToScalar(66), SkIntToScalar(-33));
35         gMatrices[3].postScale(SkIntToScalar(2), SK_ScalarHalf);
36 
37         // Perspective matrices
38         gMatrices[4].setRotate(SkIntToScalar(215));
39         gMatrices[4].set(SkMatrix::kMPersp0, 0.00013f);
40         gMatrices[4].set(SkMatrix::kMPersp1, -0.000039f);
41     }
42 
43     uint32_t count = static_cast<uint32_t>(std::size(gMatrices));
44     if (includeNonPerspective && includePerspective) {
45         return gMatrices[random->nextULessThan(count)];
46     } else if (!includeNonPerspective) {
47         return gMatrices[count - 1 - random->nextULessThan(kPerspectiveCount)];
48     } else {
49         SkASSERT(includeNonPerspective && !includePerspective);
50         return gMatrices[random->nextULessThan(count - kPerspectiveCount)];
51     }
52 }
53 
54 namespace GrTest {
TestMatrix(SkRandom * random)55 const SkMatrix& TestMatrix(SkRandom* random) { return test_matrix(random, true, true); }
56 
TestMatrixPreservesRightAngles(SkRandom * random)57 const SkMatrix& TestMatrixPreservesRightAngles(SkRandom* random) {
58     static SkMatrix gMatrices[5];
59     static bool gOnce;
60     if (!gOnce) {
61         gOnce = true;
62         // identity
63         gMatrices[0].reset();
64         // translation
65         gMatrices[1].setTranslate(SkIntToScalar(-100), SkIntToScalar(100));
66         // scale
67         gMatrices[2].setScale(SkIntToScalar(17), SkIntToScalar(17));
68         // scale + translation
69         gMatrices[3].setScale(SkIntToScalar(-17), SkIntToScalar(-17));
70         gMatrices[3].postTranslate(SkIntToScalar(66), SkIntToScalar(-33));
71         // orthogonal basis vectors
72         gMatrices[4].reset();
73         gMatrices[4].setScale(SkIntToScalar(-1), SkIntToScalar(-1));
74         gMatrices[4].setRotate(47);
75 
76         for (size_t i = 0; i < std::size(gMatrices); i++) {
77             SkASSERT(gMatrices[i].preservesRightAngles());
78         }
79     }
80     return gMatrices[random->nextULessThan(static_cast<uint32_t>(std::size(gMatrices)))];
81 }
82 
TestMatrixRectStaysRect(SkRandom * random)83 const SkMatrix& TestMatrixRectStaysRect(SkRandom* random) {
84     static SkMatrix gMatrices[6];
85     static bool gOnce;
86     if (!gOnce) {
87         gOnce = true;
88         // identity
89         gMatrices[0].reset();
90         // translation
91         gMatrices[1].setTranslate(SkIntToScalar(-100), SkIntToScalar(100));
92         // scale
93         gMatrices[2].setScale(SkIntToScalar(17), SkIntToScalar(17));
94         // scale + translation
95         gMatrices[3].setScale(SkIntToScalar(-17), SkIntToScalar(-17));
96         gMatrices[3].postTranslate(SkIntToScalar(66), SkIntToScalar(-33));
97         // reflection
98         gMatrices[4].setScale(SkIntToScalar(-1), SkIntToScalar(-1));
99         // 90 degress rotation
100         gMatrices[5].setRotate(90);
101 
102         for (size_t i = 0; i < std::size(gMatrices); i++) {
103             SkASSERT(gMatrices[i].rectStaysRect());
104         }
105     }
106     return gMatrices[random->nextULessThan(static_cast<uint32_t>(std::size(gMatrices)))];
107 }
108 
TestMatrixInvertible(SkRandom * random)109 const SkMatrix& TestMatrixInvertible(SkRandom* random) { return test_matrix(random, true, false); }
TestMatrixPerspective(SkRandom * random)110 const SkMatrix& TestMatrixPerspective(SkRandom* random) { return test_matrix(random, false, true); }
111 
TestWrapModes(SkRandom * random,GrSamplerState::WrapMode wrapModes[2])112 void TestWrapModes(SkRandom* random, GrSamplerState::WrapMode wrapModes[2]) {
113     static const GrSamplerState::WrapMode kWrapModes[] = {
114             GrSamplerState::WrapMode::kClamp,
115             GrSamplerState::WrapMode::kRepeat,
116             GrSamplerState::WrapMode::kMirrorRepeat,
117     };
118     wrapModes[0] = kWrapModes[random->nextULessThan(std::size(kWrapModes))];
119     wrapModes[1] = kWrapModes[random->nextULessThan(std::size(kWrapModes))];
120 }
TestRect(SkRandom * random)121 const SkRect& TestRect(SkRandom* random) {
122     static SkRect gRects[7];
123     static bool gOnce;
124     if (!gOnce) {
125         gOnce = true;
126         gRects[0] = SkRect::MakeWH(1.f, 1.f);
127         gRects[1] = SkRect::MakeWH(1.0f, 256.0f);
128         gRects[2] = SkRect::MakeWH(256.0f, 1.0f);
129         gRects[3] = SkRectPriv::MakeLargest();
130         gRects[4] = SkRect::MakeLTRB(-65535.0f, -65535.0f, 65535.0f, 65535.0f);
131         gRects[5] = SkRect::MakeLTRB(-10.0f, -10.0f, 10.0f, 10.0f);
132     }
133     return gRects[random->nextULessThan(static_cast<uint32_t>(std::size(gRects)))];
134 }
135 
136 // Just some simple rects for code which expects its input very sanitized
TestSquare(SkRandom * random)137 const SkRect& TestSquare(SkRandom* random) {
138     static SkRect gRects[2];
139     static bool gOnce;
140     if (!gOnce) {
141         gOnce = true;
142         gRects[0] = SkRect::MakeWH(128.f, 128.f);
143         gRects[1] = SkRect::MakeWH(256.0f, 256.0f);
144     }
145     return gRects[random->nextULessThan(static_cast<uint32_t>(std::size(gRects)))];
146 }
147 
TestRRectSimple(SkRandom * random)148 const SkRRect& TestRRectSimple(SkRandom* random) {
149     static SkRRect gRRect[2];
150     static bool gOnce;
151     if (!gOnce) {
152         gOnce = true;
153         SkRect rectangle = SkRect::MakeWH(10.f, 20.f);
154         // true round rect with circular corners
155         gRRect[0].setRectXY(rectangle, 1.f, 1.f);
156         // true round rect with elliptical corners
157         gRRect[1].setRectXY(rectangle, 2.0f, 1.0f);
158 
159         for (size_t i = 0; i < std::size(gRRect); i++) {
160             SkASSERT(gRRect[i].isSimple());
161         }
162     }
163     return gRRect[random->nextULessThan(static_cast<uint32_t>(std::size(gRRect)))];
164 }
165 
TestPath(SkRandom * random)166 const SkPath& TestPath(SkRandom* random) {
167     static SkPath gPath[7];
168     static bool gOnce;
169     if (!gOnce) {
170         gOnce = true;
171         // line
172         gPath[0] = SkPathBuilder().moveTo(0.f, 0.f)
173                                   .lineTo(10.f, 10.f)
174                                   .detach();
175         // quad
176         gPath[1] = SkPathBuilder().moveTo(0.f, 0.f)
177                                   .quadTo(10.f, 10.f, 20.f, 20.f)
178                                   .detach();
179         // conic
180         gPath[2] = SkPathBuilder().moveTo(0.f, 0.f)
181                                   .conicTo(10.f, 10.f, 20.f, 20.f, 1.f)
182                                   .detach();
183         // cubic
184         gPath[3] = SkPathBuilder().moveTo(0.f, 0.f)
185                                   .cubicTo(10.f, 10.f, 20.f, 20.f, 30.f, 30.f)
186                                   .detach();
187         // all three
188         gPath[4] = SkPathBuilder().moveTo(0.f, 0.f)
189                                   .lineTo(10.f, 10.f)
190                                   .quadTo(10.f, 10.f, 20.f, 20.f)
191                                   .conicTo(10.f, 10.f, 20.f, 20.f, 1.f)
192                                   .cubicTo(10.f, 10.f, 20.f, 20.f, 30.f, 30.f)
193                                   .detach();
194         // convex
195         gPath[5] = SkPathBuilder().moveTo(0.0f, 0.0f)
196                                   .lineTo(10.0f, 0.0f)
197                                   .lineTo(10.0f, 10.0f)
198                                   .lineTo(0.0f, 10.0f)
199                                   .close()
200                                   .detach();
201         // concave
202         gPath[6] = SkPathBuilder().moveTo(0.0f, 0.0f)
203                                   .lineTo(5.0f, 5.0f)
204                                   .lineTo(10.0f, 0.0f)
205                                   .lineTo(10.0f, 10.0f)
206                                   .lineTo(0.0f, 10.0f)
207                                   .close()
208                                   .detach();
209     }
210 
211     return gPath[random->nextULessThan(static_cast<uint32_t>(std::size(gPath)))];
212 }
213 
TestPathConvex(SkRandom * random)214 const SkPath& TestPathConvex(SkRandom* random) {
215     static SkPath gPath[3];
216     static bool gOnce;
217     if (!gOnce) {
218         gOnce = true;
219         // narrow rect
220         gPath[0] = SkPath::Polygon({{-1.5f, -50.0f},
221                                     {-1.5f, -50.0f},
222                                     { 1.5f, -50.0f},
223                                     { 1.5f,  50.0f},
224                                     {-1.5f,  50.0f}}, false);
225         // degenerate
226         gPath[1] = SkPath::Polygon({{-0.025f, -0.025f},
227                                     {-0.025f, -0.025f},
228                                     { 0.025f, -0.025f},
229                                     { 0.025f,  0.025f},
230                                     {-0.025f,  0.025f}}, false);
231         // clipped triangle
232         gPath[2] = SkPath::Polygon({{-10.0f, -50.0f},
233                                     {-10.0f, -50.0f},
234                                     { 10.0f, -50.0f},
235                                     { 50.0f,  31.0f},
236                                     { 40.0f,  50.0f},
237                                     {-40.0f,  50.0f},
238                                     {-50.0f,  31.0f}}, false);
239 
240         for (size_t i = 0; i < std::size(gPath); i++) {
241             SkASSERT(gPath[i].isConvex());
242         }
243     }
244 
245     return gPath[random->nextULessThan(static_cast<uint32_t>(std::size(gPath)))];
246 }
247 
randomize_stroke_rec(SkStrokeRec * rec,SkRandom * random)248 static void randomize_stroke_rec(SkStrokeRec* rec, SkRandom* random) {
249     bool strokeAndFill = random->nextBool();
250     SkScalar strokeWidth = random->nextBool() ? 0.f : 1.f;
251     rec->setStrokeStyle(strokeWidth, strokeAndFill);
252 
253     SkPaint::Cap cap = SkPaint::Cap(random->nextULessThan(SkPaint::kCapCount));
254     SkPaint::Join join = SkPaint::Join(random->nextULessThan(SkPaint::kJoinCount));
255     SkScalar miterLimit = random->nextRangeScalar(1.f, 5.f);
256     rec->setStrokeParams(cap, join, miterLimit);
257 }
258 
TestStrokeRec(SkRandom * random)259 SkStrokeRec TestStrokeRec(SkRandom* random) {
260     SkStrokeRec::InitStyle style =
261             SkStrokeRec::InitStyle(random->nextULessThan(SkStrokeRec::kFill_InitStyle + 1));
262     SkStrokeRec rec(style);
263     randomize_stroke_rec(&rec, random);
264     return rec;
265 }
266 
TestStyle(SkRandom * random,GrStyle * style)267 void TestStyle(SkRandom* random, GrStyle* style) {
268     SkStrokeRec::InitStyle initStyle =
269             SkStrokeRec::InitStyle(random->nextULessThan(SkStrokeRec::kFill_InitStyle + 1));
270     SkStrokeRec stroke(initStyle);
271     randomize_stroke_rec(&stroke, random);
272     sk_sp<SkPathEffect> pe;
273     if (random->nextBool()) {
274         int cnt = random->nextRangeU(1, 50) * 2;
275         std::unique_ptr<SkScalar[]> intervals(new SkScalar[cnt]);
276         SkScalar sum = 0;
277         for (int i = 0; i < cnt; i++) {
278             intervals[i] = random->nextRangeScalar(SkDoubleToScalar(0.01),
279                                                    SkDoubleToScalar(10.0));
280             sum += intervals[i];
281         }
282         SkScalar phase = random->nextRangeScalar(0, sum);
283         pe = TestDashPathEffect::Make(intervals.get(), cnt, phase);
284     }
285     *style = GrStyle(stroke, std::move(pe));
286 }
287 
TestDashPathEffect(const SkScalar * intervals,int count,SkScalar phase)288 TestDashPathEffect::TestDashPathEffect(const SkScalar* intervals, int count, SkScalar phase) {
289     fCount = count;
290     fIntervals.reset(count);
291     memcpy(fIntervals.get(), intervals, count * sizeof(SkScalar));
292     SkDashPath::CalcDashParameters(phase, intervals, count, &fInitialDashLength,
293                                    &fInitialDashIndex, &fIntervalLength, &fPhase);
294 }
295 
onFilterPath(SkPath * dst,const SkPath & src,SkStrokeRec * rec,const SkRect * cullRect,const SkMatrix &) const296 bool TestDashPathEffect::onFilterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec,
297                                       const SkRect* cullRect, const SkMatrix&) const {
298     return SkDashPath::InternalFilter(dst, src, rec, cullRect, fIntervals.get(), fCount,
299                                       fInitialDashLength, fInitialDashIndex, fIntervalLength,
300                                       fPhase);
301 }
302 
onAsADash(DashInfo * info) const303 SkPathEffect::DashType TestDashPathEffect::onAsADash(DashInfo* info) const {
304     if (info) {
305         if (info->fCount >= fCount && info->fIntervals) {
306             memcpy(info->fIntervals, fIntervals.get(), fCount * sizeof(SkScalar));
307         }
308         info->fCount = fCount;
309         info->fPhase = fPhase;
310     }
311     return kDash_DashType;
312 }
313 
TestColorSpace(SkRandom * random)314 sk_sp<SkColorSpace> TestColorSpace(SkRandom* random) {
315     static sk_sp<SkColorSpace> gColorSpaces[3];
316     static bool gOnce;
317     if (!gOnce) {
318         gOnce = true;
319         // No color space (legacy mode)
320         gColorSpaces[0] = nullptr;
321         // sRGB or color-spin sRGB
322         gColorSpaces[1] = SkColorSpace::MakeSRGB();
323         gColorSpaces[2] = SkColorSpace::MakeSRGB()->makeColorSpin();
324     }
325     return gColorSpaces[random->nextULessThan(static_cast<uint32_t>(std::size(gColorSpaces)))];
326 }
327 
TestColorXform(SkRandom * random)328 sk_sp<GrColorSpaceXform> TestColorXform(SkRandom* random) {
329     // TODO: Add many more kinds of xforms here
330     static sk_sp<GrColorSpaceXform> gXforms[3];
331     static bool gOnce;
332     if (!gOnce) {
333         gOnce = true;
334         sk_sp<SkColorSpace> srgb = SkColorSpace::MakeSRGB();
335         sk_sp<SkColorSpace> spin = SkColorSpace::MakeSRGB()->makeColorSpin();
336         // No gamut change
337         gXforms[0] = nullptr;
338         gXforms[1] = GrColorSpaceXform::Make(srgb.get(), kPremul_SkAlphaType,
339                                              spin.get(), kPremul_SkAlphaType);
340         gXforms[2] = GrColorSpaceXform::Make(spin.get(), kPremul_SkAlphaType,
341                                              srgb.get(), kPremul_SkAlphaType);
342     }
343     return gXforms[random->nextULessThan(static_cast<uint32_t>(std::size(gXforms)))];
344 }
345 
TestAsFPArgs(GrProcessorTestData * d)346 TestAsFPArgs::TestAsFPArgs(GrProcessorTestData* d)
347         : fColorInfoStorage(std::make_unique<GrColorInfo>(GrColorType::kRGBA_8888,
348                                                           kPremul_SkAlphaType,
349                                                           TestColorSpace(d->fRandom)))
350         , fArgs(d->context(), fColorInfoStorage.get(), fSurfaceProps) {}
351 
~TestAsFPArgs()352 TestAsFPArgs::~TestAsFPArgs() {}
353 
RandomColor(SkRandom * random)354 GrColor RandomColor(SkRandom* random) {
355     // There are only a few cases of random colors which interest us
356     enum ColorMode {
357         kAllOnes_ColorMode,
358         kAllZeros_ColorMode,
359         kAlphaOne_ColorMode,
360         kRandom_ColorMode,
361         kLast_ColorMode = kRandom_ColorMode
362     };
363 
364     ColorMode colorMode = ColorMode(random->nextULessThan(kLast_ColorMode + 1));
365     GrColor color SK_INIT_TO_AVOID_WARNING;
366     switch (colorMode) {
367         case kAllOnes_ColorMode:
368             color = GrColorPackRGBA(0xFF, 0xFF, 0xFF, 0xFF);
369             break;
370         case kAllZeros_ColorMode:
371             color = GrColorPackRGBA(0, 0, 0, 0);
372             break;
373         case kAlphaOne_ColorMode:
374             color = GrColorPackRGBA(random->nextULessThan(256),
375                                     random->nextULessThan(256),
376                                     random->nextULessThan(256),
377                                     0xFF);
378             break;
379         case kRandom_ColorMode: {
380                 uint8_t alpha = random->nextULessThan(256);
381                 color = GrColorPackRGBA(random->nextRangeU(0, alpha),
382                                         random->nextRangeU(0, alpha),
383                                         random->nextRangeU(0, alpha),
384                                         alpha);
385             break;
386         }
387     }
388     return color;
389 }
390 
RandomCoverage(SkRandom * random)391 uint8_t RandomCoverage(SkRandom* random) {
392     enum CoverageMode {
393         kZero_CoverageMode,
394         kAllOnes_CoverageMode,
395         kRandom_CoverageMode,
396         kLast_CoverageMode = kRandom_CoverageMode
397     };
398 
399     CoverageMode colorMode = CoverageMode(random->nextULessThan(kLast_CoverageMode + 1));
400     uint8_t coverage SK_INIT_TO_AVOID_WARNING;
401     switch (colorMode) {
402         case kZero_CoverageMode:
403             coverage = 0;
404             break;
405         case kAllOnes_CoverageMode:
406             coverage = 0xff;
407             break;
408         case kRandom_CoverageMode:
409             coverage = random->nextULessThan(256);
410             break;
411     }
412     return coverage;
413 }
414 
415 }  // namespace GrTest
416 
417 #endif
418