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