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