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