1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2011 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker
8*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkAlphaType.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBitmap.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorPriv.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorSpace.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorType.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImageInfo.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkMatrix.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPixmap.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkShader.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurface.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurfaceProps.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTileMode.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "include/effects/SkGradientShader.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/GpuTypes.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrDirectContext.h"
32*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/SkSurfaceGanesh.h"
33*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/mock/GrMockTypes.h"
34*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTemplates.h"
35*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTo.h"
36*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/gpu/ganesh/GrTypesPriv.h"
37*c8dee2aaSAndroid Build Coastguard Worker #include "src/base/SkTLazy.h"
38*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrColorInfo.h"
39*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrFPArgs.h"
40*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrFragmentProcessors.h"
41*c8dee2aaSAndroid Build Coastguard Worker #include "src/shaders/SkShaderBase.h"
42*c8dee2aaSAndroid Build Coastguard Worker #include "tests/CtsEnforcement.h"
43*c8dee2aaSAndroid Build Coastguard Worker #include "tests/Test.h"
44*c8dee2aaSAndroid Build Coastguard Worker
45*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
46*c8dee2aaSAndroid Build Coastguard Worker #include <cstring>
47*c8dee2aaSAndroid Build Coastguard Worker #include <string>
48*c8dee2aaSAndroid Build Coastguard Worker
49*c8dee2aaSAndroid Build Coastguard Worker // #if defined(SK_GRAPHITE)
50*c8dee2aaSAndroid Build Coastguard Worker // #include "include/gpu/graphite/Context.h"
51*c8dee2aaSAndroid Build Coastguard Worker // #include "include/gpu/graphite/Surface.h"
52*c8dee2aaSAndroid Build Coastguard Worker // #endif
53*c8dee2aaSAndroid Build Coastguard Worker
54*c8dee2aaSAndroid Build Coastguard Worker struct GrContextOptions;
55*c8dee2aaSAndroid Build Coastguard Worker
56*c8dee2aaSAndroid Build Coastguard Worker using namespace skia_private;
57*c8dee2aaSAndroid Build Coastguard Worker
58*c8dee2aaSAndroid Build Coastguard Worker // https://code.google.com/p/chromium/issues/detail?id=448299
59*c8dee2aaSAndroid Build Coastguard Worker // Giant (inverse) matrix causes overflow when converting/computing using 32.32
60*c8dee2aaSAndroid Build Coastguard Worker // Before the fix, we would assert (and then crash).
test_big_grad(skiatest::Reporter * reporter)61*c8dee2aaSAndroid Build Coastguard Worker static void test_big_grad(skiatest::Reporter* reporter) {
62*c8dee2aaSAndroid Build Coastguard Worker const SkColor colors[] = { SK_ColorRED, SK_ColorBLUE };
63*c8dee2aaSAndroid Build Coastguard Worker const SkPoint pts[] = {{ 15, 14.7112684f }, { 0.709064007f, 12.6108112f }};
64*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
65*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkTileMode::kClamp));
66*c8dee2aaSAndroid Build Coastguard Worker
67*c8dee2aaSAndroid Build Coastguard Worker SkBitmap bm;
68*c8dee2aaSAndroid Build Coastguard Worker bm.allocN32Pixels(2000, 1);
69*c8dee2aaSAndroid Build Coastguard Worker SkCanvas c(bm);
70*c8dee2aaSAndroid Build Coastguard Worker
71*c8dee2aaSAndroid Build Coastguard Worker const SkScalar affine[] = {
72*c8dee2aaSAndroid Build Coastguard Worker 1.06608627e-06f, 4.26434525e-07f, 6.2855f, 2.6611f, 273.4393f, 244.0046f
73*c8dee2aaSAndroid Build Coastguard Worker };
74*c8dee2aaSAndroid Build Coastguard Worker SkMatrix matrix;
75*c8dee2aaSAndroid Build Coastguard Worker matrix.setAffine(affine);
76*c8dee2aaSAndroid Build Coastguard Worker c.concat(matrix);
77*c8dee2aaSAndroid Build Coastguard Worker
78*c8dee2aaSAndroid Build Coastguard Worker c.drawPaint(paint);
79*c8dee2aaSAndroid Build Coastguard Worker }
80*c8dee2aaSAndroid Build Coastguard Worker
81*c8dee2aaSAndroid Build Coastguard Worker struct GradRec {
82*c8dee2aaSAndroid Build Coastguard Worker int fColorCount;
83*c8dee2aaSAndroid Build Coastguard Worker const SkColor* fColors;
84*c8dee2aaSAndroid Build Coastguard Worker const SkScalar* fPos;
85*c8dee2aaSAndroid Build Coastguard Worker const SkPoint* fPoint; // 2
86*c8dee2aaSAndroid Build Coastguard Worker const SkScalar* fRadius; // 2
87*c8dee2aaSAndroid Build Coastguard Worker SkTileMode fTileMode;
88*c8dee2aaSAndroid Build Coastguard Worker
gradCheckGradRec89*c8dee2aaSAndroid Build Coastguard Worker void gradCheck(skiatest::Reporter* reporter,
90*c8dee2aaSAndroid Build Coastguard Worker const sk_sp<SkShader>& shader,
91*c8dee2aaSAndroid Build Coastguard Worker SkShaderBase::GradientInfo* info,
92*c8dee2aaSAndroid Build Coastguard Worker SkShaderBase::GradientType gt,
93*c8dee2aaSAndroid Build Coastguard Worker const SkMatrix& localMatrix = SkMatrix::I()) const {
94*c8dee2aaSAndroid Build Coastguard Worker AutoTMalloc<SkColor> colorStorage(fColorCount);
95*c8dee2aaSAndroid Build Coastguard Worker AutoTMalloc<SkScalar> posStorage(fColorCount);
96*c8dee2aaSAndroid Build Coastguard Worker
97*c8dee2aaSAndroid Build Coastguard Worker info->fColorCount = fColorCount;
98*c8dee2aaSAndroid Build Coastguard Worker info->fColors = colorStorage;
99*c8dee2aaSAndroid Build Coastguard Worker info->fColorOffsets = posStorage.get();
100*c8dee2aaSAndroid Build Coastguard Worker SkMatrix shaderLocalMatrix;
101*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, as_SB(shader)->asGradient(info, &shaderLocalMatrix) == gt);
102*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, shaderLocalMatrix == localMatrix);
103*c8dee2aaSAndroid Build Coastguard Worker
104*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, info->fColorCount == fColorCount);
105*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter,
106*c8dee2aaSAndroid Build Coastguard Worker !memcmp(info->fColors, fColors, fColorCount * sizeof(SkColor)));
107*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter,
108*c8dee2aaSAndroid Build Coastguard Worker !memcmp(info->fColorOffsets, fPos, fColorCount * sizeof(SkScalar)));
109*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, fTileMode == (SkTileMode)info->fTileMode);
110*c8dee2aaSAndroid Build Coastguard Worker }
111*c8dee2aaSAndroid Build Coastguard Worker };
112*c8dee2aaSAndroid Build Coastguard Worker
113*c8dee2aaSAndroid Build Coastguard Worker
none_gradproc(skiatest::Reporter * reporter,const GradRec &,const GradRec &)114*c8dee2aaSAndroid Build Coastguard Worker static void none_gradproc(skiatest::Reporter* reporter, const GradRec&, const GradRec&) {
115*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkShader> s(SkShaders::Empty());
116*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, SkShaderBase::GradientType::kNone == as_SB(s)->asGradient());
117*c8dee2aaSAndroid Build Coastguard Worker }
118*c8dee2aaSAndroid Build Coastguard Worker
color_gradproc(skiatest::Reporter * reporter,const GradRec & rec,const GradRec &)119*c8dee2aaSAndroid Build Coastguard Worker static void color_gradproc(skiatest::Reporter* reporter, const GradRec& rec, const GradRec&) {
120*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkShader> s(SkShaders::Color(rec.fColors[0]));
121*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, SkShaderBase::GradientType::kNone == as_SB(s)->asGradient());
122*c8dee2aaSAndroid Build Coastguard Worker }
123*c8dee2aaSAndroid Build Coastguard Worker
linear_gradproc(skiatest::Reporter * reporter,const GradRec & buildRec,const GradRec & checkRec)124*c8dee2aaSAndroid Build Coastguard Worker static void linear_gradproc(skiatest::Reporter* reporter, const GradRec& buildRec,
125*c8dee2aaSAndroid Build Coastguard Worker const GradRec& checkRec) {
126*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkShader> s(SkGradientShader::MakeLinear(buildRec.fPoint, buildRec.fColors, buildRec.fPos,
127*c8dee2aaSAndroid Build Coastguard Worker buildRec.fColorCount, buildRec.fTileMode));
128*c8dee2aaSAndroid Build Coastguard Worker
129*c8dee2aaSAndroid Build Coastguard Worker SkShaderBase::GradientInfo info;
130*c8dee2aaSAndroid Build Coastguard Worker checkRec.gradCheck(reporter, s, &info, SkShaderBase::GradientType::kLinear);
131*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !memcmp(info.fPoint, checkRec.fPoint, 2 * sizeof(SkPoint)));
132*c8dee2aaSAndroid Build Coastguard Worker }
133*c8dee2aaSAndroid Build Coastguard Worker
radial_gradproc(skiatest::Reporter * reporter,const GradRec & buildRec,const GradRec & checkRec)134*c8dee2aaSAndroid Build Coastguard Worker static void radial_gradproc(skiatest::Reporter* reporter, const GradRec& buildRec,
135*c8dee2aaSAndroid Build Coastguard Worker const GradRec& checkRec) {
136*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkShader> s(SkGradientShader::MakeRadial(buildRec.fPoint[0], buildRec.fRadius[0],
137*c8dee2aaSAndroid Build Coastguard Worker buildRec.fColors, buildRec.fPos,
138*c8dee2aaSAndroid Build Coastguard Worker buildRec.fColorCount, buildRec.fTileMode));
139*c8dee2aaSAndroid Build Coastguard Worker
140*c8dee2aaSAndroid Build Coastguard Worker SkShaderBase::GradientInfo info;
141*c8dee2aaSAndroid Build Coastguard Worker checkRec.gradCheck(reporter, s, &info, SkShaderBase::GradientType::kRadial);
142*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, info.fPoint[0] == checkRec.fPoint[0]);
143*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, info.fRadius[0] == checkRec.fRadius[0]);
144*c8dee2aaSAndroid Build Coastguard Worker }
145*c8dee2aaSAndroid Build Coastguard Worker
sweep_gradproc(skiatest::Reporter * reporter,const GradRec & buildRec,const GradRec & checkRec)146*c8dee2aaSAndroid Build Coastguard Worker static void sweep_gradproc(skiatest::Reporter* reporter, const GradRec& buildRec,
147*c8dee2aaSAndroid Build Coastguard Worker const GradRec& checkRec) {
148*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkShader> s(SkGradientShader::MakeSweep(buildRec.fPoint[0].fX, buildRec.fPoint[0].fY,
149*c8dee2aaSAndroid Build Coastguard Worker buildRec.fColors, buildRec.fPos,
150*c8dee2aaSAndroid Build Coastguard Worker buildRec.fColorCount));
151*c8dee2aaSAndroid Build Coastguard Worker
152*c8dee2aaSAndroid Build Coastguard Worker SkShaderBase::GradientInfo info;
153*c8dee2aaSAndroid Build Coastguard Worker checkRec.gradCheck(reporter, s, &info, SkShaderBase::GradientType::kSweep);
154*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, info.fPoint[0] == checkRec.fPoint[0]);
155*c8dee2aaSAndroid Build Coastguard Worker }
156*c8dee2aaSAndroid Build Coastguard Worker
conical_gradproc(skiatest::Reporter * reporter,const GradRec & buildRec,const GradRec & checkRec)157*c8dee2aaSAndroid Build Coastguard Worker static void conical_gradproc(skiatest::Reporter* reporter, const GradRec& buildRec,
158*c8dee2aaSAndroid Build Coastguard Worker const GradRec& checkRec) {
159*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkShader> s(SkGradientShader::MakeTwoPointConical(buildRec.fPoint[0],
160*c8dee2aaSAndroid Build Coastguard Worker buildRec.fRadius[0],
161*c8dee2aaSAndroid Build Coastguard Worker buildRec.fPoint[1],
162*c8dee2aaSAndroid Build Coastguard Worker buildRec.fRadius[1],
163*c8dee2aaSAndroid Build Coastguard Worker buildRec.fColors,
164*c8dee2aaSAndroid Build Coastguard Worker buildRec.fPos,
165*c8dee2aaSAndroid Build Coastguard Worker buildRec.fColorCount,
166*c8dee2aaSAndroid Build Coastguard Worker buildRec.fTileMode));
167*c8dee2aaSAndroid Build Coastguard Worker
168*c8dee2aaSAndroid Build Coastguard Worker SkShaderBase::GradientInfo info;
169*c8dee2aaSAndroid Build Coastguard Worker checkRec.gradCheck(reporter, s, &info, SkShaderBase::GradientType::kConical);
170*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !memcmp(info.fPoint, checkRec.fPoint, 2 * sizeof(SkPoint)));
171*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !memcmp(info.fRadius, checkRec.fRadius, 2 * sizeof(SkScalar)));
172*c8dee2aaSAndroid Build Coastguard Worker }
173*c8dee2aaSAndroid Build Coastguard Worker
linear_gradproc_matrix(skiatest::Reporter * reporter,const GradRec & buildRec,const GradRec & checkRec)174*c8dee2aaSAndroid Build Coastguard Worker static void linear_gradproc_matrix(skiatest::Reporter* reporter, const GradRec& buildRec,
175*c8dee2aaSAndroid Build Coastguard Worker const GradRec& checkRec) {
176*c8dee2aaSAndroid Build Coastguard Worker SkMatrix localMatrix = SkMatrix::RotateDeg(45, {100, 100});
177*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkShader> s(SkGradientShader::MakeLinear(buildRec.fPoint, buildRec.fColors, buildRec.fPos,
178*c8dee2aaSAndroid Build Coastguard Worker buildRec.fColorCount, buildRec.fTileMode,
179*c8dee2aaSAndroid Build Coastguard Worker /*flags=*/0,
180*c8dee2aaSAndroid Build Coastguard Worker &localMatrix));
181*c8dee2aaSAndroid Build Coastguard Worker
182*c8dee2aaSAndroid Build Coastguard Worker SkShaderBase::GradientInfo info;
183*c8dee2aaSAndroid Build Coastguard Worker checkRec.gradCheck(reporter, s, &info, SkShaderBase::GradientType::kLinear, localMatrix);
184*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !memcmp(info.fPoint, checkRec.fPoint, 2 * sizeof(SkPoint)));
185*c8dee2aaSAndroid Build Coastguard Worker
186*c8dee2aaSAndroid Build Coastguard Worker // Same but using a local matrix wrapper.
187*c8dee2aaSAndroid Build Coastguard Worker s = SkGradientShader::MakeLinear(buildRec.fPoint, buildRec.fColors, buildRec.fPos,
188*c8dee2aaSAndroid Build Coastguard Worker buildRec.fColorCount, buildRec.fTileMode);
189*c8dee2aaSAndroid Build Coastguard Worker s = s->makeWithLocalMatrix(localMatrix);
190*c8dee2aaSAndroid Build Coastguard Worker checkRec.gradCheck(reporter, s, &info, SkShaderBase::GradientType::kLinear, localMatrix);
191*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, !memcmp(info.fPoint, checkRec.fPoint, 2 * sizeof(SkPoint)));
192*c8dee2aaSAndroid Build Coastguard Worker }
193*c8dee2aaSAndroid Build Coastguard Worker
194*c8dee2aaSAndroid Build Coastguard Worker // Ensure that repeated color gradients behave like drawing a single color
TestConstantGradient(skiatest::Reporter *)195*c8dee2aaSAndroid Build Coastguard Worker static void TestConstantGradient(skiatest::Reporter*) {
196*c8dee2aaSAndroid Build Coastguard Worker const SkPoint pts[] = {
197*c8dee2aaSAndroid Build Coastguard Worker { 0, 0 },
198*c8dee2aaSAndroid Build Coastguard Worker { SkIntToScalar(10), 0 }
199*c8dee2aaSAndroid Build Coastguard Worker };
200*c8dee2aaSAndroid Build Coastguard Worker SkColor colors[] = { SK_ColorBLUE, SK_ColorBLUE };
201*c8dee2aaSAndroid Build Coastguard Worker const SkScalar pos[] = { 0, SK_Scalar1 };
202*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
203*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(SkGradientShader::MakeLinear(pts, colors, pos, 2, SkTileMode::kClamp));
204*c8dee2aaSAndroid Build Coastguard Worker SkBitmap outBitmap;
205*c8dee2aaSAndroid Build Coastguard Worker outBitmap.allocN32Pixels(10, 1);
206*c8dee2aaSAndroid Build Coastguard Worker SkCanvas canvas(outBitmap);
207*c8dee2aaSAndroid Build Coastguard Worker canvas.drawPaint(paint);
208*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < 10; i++) {
209*c8dee2aaSAndroid Build Coastguard Worker // The following is commented out because it currently fails
210*c8dee2aaSAndroid Build Coastguard Worker // Related bug: https://code.google.com/p/skia/issues/detail?id=1098
211*c8dee2aaSAndroid Build Coastguard Worker
212*c8dee2aaSAndroid Build Coastguard Worker // REPORTER_ASSERT(reporter, SK_ColorBLUE == outBitmap.getColor(i, 0));
213*c8dee2aaSAndroid Build Coastguard Worker }
214*c8dee2aaSAndroid Build Coastguard Worker }
215*c8dee2aaSAndroid Build Coastguard Worker
216*c8dee2aaSAndroid Build Coastguard Worker typedef void (*GradProc)(skiatest::Reporter* reporter, const GradRec&, const GradRec&);
217*c8dee2aaSAndroid Build Coastguard Worker
TestGradientShaders(skiatest::Reporter * reporter)218*c8dee2aaSAndroid Build Coastguard Worker static void TestGradientShaders(skiatest::Reporter* reporter) {
219*c8dee2aaSAndroid Build Coastguard Worker static const SkColor gColors[] = { SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE };
220*c8dee2aaSAndroid Build Coastguard Worker static const SkScalar gPos[] = { 0, SK_ScalarHalf, SK_Scalar1 };
221*c8dee2aaSAndroid Build Coastguard Worker static const SkPoint gPts[] = {
222*c8dee2aaSAndroid Build Coastguard Worker { 0, 0 },
223*c8dee2aaSAndroid Build Coastguard Worker { SkIntToScalar(10), SkIntToScalar(20) }
224*c8dee2aaSAndroid Build Coastguard Worker };
225*c8dee2aaSAndroid Build Coastguard Worker static const SkScalar gRad[] = { SkIntToScalar(1), SkIntToScalar(2) };
226*c8dee2aaSAndroid Build Coastguard Worker
227*c8dee2aaSAndroid Build Coastguard Worker GradRec rec;
228*c8dee2aaSAndroid Build Coastguard Worker rec.fColorCount = std::size(gColors);
229*c8dee2aaSAndroid Build Coastguard Worker rec.fColors = gColors;
230*c8dee2aaSAndroid Build Coastguard Worker rec.fPos = gPos;
231*c8dee2aaSAndroid Build Coastguard Worker rec.fPoint = gPts;
232*c8dee2aaSAndroid Build Coastguard Worker rec.fRadius = gRad;
233*c8dee2aaSAndroid Build Coastguard Worker rec.fTileMode = SkTileMode::kClamp;
234*c8dee2aaSAndroid Build Coastguard Worker
235*c8dee2aaSAndroid Build Coastguard Worker static const GradProc gProcs[] = {
236*c8dee2aaSAndroid Build Coastguard Worker none_gradproc,
237*c8dee2aaSAndroid Build Coastguard Worker color_gradproc,
238*c8dee2aaSAndroid Build Coastguard Worker linear_gradproc,
239*c8dee2aaSAndroid Build Coastguard Worker linear_gradproc_matrix,
240*c8dee2aaSAndroid Build Coastguard Worker radial_gradproc,
241*c8dee2aaSAndroid Build Coastguard Worker sweep_gradproc,
242*c8dee2aaSAndroid Build Coastguard Worker conical_gradproc,
243*c8dee2aaSAndroid Build Coastguard Worker };
244*c8dee2aaSAndroid Build Coastguard Worker
245*c8dee2aaSAndroid Build Coastguard Worker for (size_t i = 0; i < std::size(gProcs); ++i) {
246*c8dee2aaSAndroid Build Coastguard Worker gProcs[i](reporter, rec, rec);
247*c8dee2aaSAndroid Build Coastguard Worker }
248*c8dee2aaSAndroid Build Coastguard Worker }
249*c8dee2aaSAndroid Build Coastguard Worker
test_nearly_vertical(skiatest::Reporter * reporter)250*c8dee2aaSAndroid Build Coastguard Worker static void test_nearly_vertical(skiatest::Reporter* reporter) {
251*c8dee2aaSAndroid Build Coastguard Worker auto surface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(200, 200)));
252*c8dee2aaSAndroid Build Coastguard Worker
253*c8dee2aaSAndroid Build Coastguard Worker const SkPoint pts[] = {{ 100, 50 }, { 100.0001f, 50000 }};
254*c8dee2aaSAndroid Build Coastguard Worker const SkColor colors[] = { SK_ColorBLACK, SK_ColorWHITE };
255*c8dee2aaSAndroid Build Coastguard Worker const SkScalar pos[] = { 0, 1 };
256*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
257*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(SkGradientShader::MakeLinear(pts, colors, pos, 2, SkTileMode::kClamp));
258*c8dee2aaSAndroid Build Coastguard Worker
259*c8dee2aaSAndroid Build Coastguard Worker surface->getCanvas()->drawPaint(paint);
260*c8dee2aaSAndroid Build Coastguard Worker }
261*c8dee2aaSAndroid Build Coastguard Worker
test_vertical(skiatest::Reporter * reporter)262*c8dee2aaSAndroid Build Coastguard Worker static void test_vertical(skiatest::Reporter* reporter) {
263*c8dee2aaSAndroid Build Coastguard Worker auto surface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(200, 200)));
264*c8dee2aaSAndroid Build Coastguard Worker
265*c8dee2aaSAndroid Build Coastguard Worker const SkPoint pts[] = {{ 100, 50 }, { 100, 50 }};
266*c8dee2aaSAndroid Build Coastguard Worker const SkColor colors[] = { SK_ColorBLACK, SK_ColorWHITE };
267*c8dee2aaSAndroid Build Coastguard Worker const SkScalar pos[] = { 0, 1 };
268*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
269*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(SkGradientShader::MakeLinear(pts, colors, pos, 2, SkTileMode::kClamp));
270*c8dee2aaSAndroid Build Coastguard Worker
271*c8dee2aaSAndroid Build Coastguard Worker surface->getCanvas()->drawPaint(paint);
272*c8dee2aaSAndroid Build Coastguard Worker }
273*c8dee2aaSAndroid Build Coastguard Worker
274*c8dee2aaSAndroid Build Coastguard Worker // A linear gradient interval can, due to numerical imprecision (likely in the divide)
275*c8dee2aaSAndroid Build Coastguard Worker // finish an interval with the final fx not landing outside of [p0...p1].
276*c8dee2aaSAndroid Build Coastguard Worker // The old code had an assert which this test triggered.
277*c8dee2aaSAndroid Build Coastguard Worker // We now explicitly clamp the resulting fx value.
test_linear_fuzz(skiatest::Reporter * reporter)278*c8dee2aaSAndroid Build Coastguard Worker static void test_linear_fuzz(skiatest::Reporter* reporter) {
279*c8dee2aaSAndroid Build Coastguard Worker auto surface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(1300, 630)));
280*c8dee2aaSAndroid Build Coastguard Worker
281*c8dee2aaSAndroid Build Coastguard Worker const SkPoint pts[] = {{ 179.5f, -179.5f }, { 1074.5f, 715.5f }};
282*c8dee2aaSAndroid Build Coastguard Worker const SkColor colors[] = { SK_ColorBLACK, SK_ColorWHITE, SK_ColorBLACK, SK_ColorWHITE };
283*c8dee2aaSAndroid Build Coastguard Worker const SkScalar pos[] = {0, 0.200000003f, 0.800000012f, 1 };
284*c8dee2aaSAndroid Build Coastguard Worker
285*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
286*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(SkGradientShader::MakeLinear(pts, colors, pos, 4, SkTileMode::kClamp));
287*c8dee2aaSAndroid Build Coastguard Worker
288*c8dee2aaSAndroid Build Coastguard Worker SkRect r = {0, 83, 1254, 620};
289*c8dee2aaSAndroid Build Coastguard Worker surface->getCanvas()->drawRect(r, paint);
290*c8dee2aaSAndroid Build Coastguard Worker }
291*c8dee2aaSAndroid Build Coastguard Worker
292*c8dee2aaSAndroid Build Coastguard Worker // https://bugs.chromium.org/p/skia/issues/detail?id=5023
293*c8dee2aaSAndroid Build Coastguard Worker // We should still shade pixels for which the radius is exactly 0.
test_two_point_conical_zero_radius(skiatest::Reporter * reporter)294*c8dee2aaSAndroid Build Coastguard Worker static void test_two_point_conical_zero_radius(skiatest::Reporter* reporter) {
295*c8dee2aaSAndroid Build Coastguard Worker auto surface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(5, 5)));
296*c8dee2aaSAndroid Build Coastguard Worker surface->getCanvas()->clear(SK_ColorRED);
297*c8dee2aaSAndroid Build Coastguard Worker
298*c8dee2aaSAndroid Build Coastguard Worker const SkColor colors[] = { SK_ColorGREEN, SK_ColorBLUE };
299*c8dee2aaSAndroid Build Coastguard Worker SkPaint p;
300*c8dee2aaSAndroid Build Coastguard Worker p.setShader(SkGradientShader::MakeTwoPointConical(
301*c8dee2aaSAndroid Build Coastguard Worker SkPoint::Make(2.5f, 2.5f), 0,
302*c8dee2aaSAndroid Build Coastguard Worker SkPoint::Make(3.0f, 3.0f), 10,
303*c8dee2aaSAndroid Build Coastguard Worker colors, nullptr, std::size(colors), SkTileMode::kClamp));
304*c8dee2aaSAndroid Build Coastguard Worker surface->getCanvas()->drawPaint(p);
305*c8dee2aaSAndroid Build Coastguard Worker
306*c8dee2aaSAndroid Build Coastguard Worker // r == 0 for the center pixel.
307*c8dee2aaSAndroid Build Coastguard Worker // verify that we draw it (no red bleed)
308*c8dee2aaSAndroid Build Coastguard Worker SkPMColor centerPMColor;
309*c8dee2aaSAndroid Build Coastguard Worker surface->readPixels(SkImageInfo::MakeN32Premul(1, 1), ¢erPMColor, sizeof(SkPMColor), 2, 2);
310*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, SkGetPackedR32(centerPMColor) == 0);
311*c8dee2aaSAndroid Build Coastguard Worker }
312*c8dee2aaSAndroid Build Coastguard Worker
313*c8dee2aaSAndroid Build Coastguard Worker // http://crbug.com/599458
test_clamping_overflow(skiatest::Reporter *)314*c8dee2aaSAndroid Build Coastguard Worker static void test_clamping_overflow(skiatest::Reporter*) {
315*c8dee2aaSAndroid Build Coastguard Worker SkPaint p;
316*c8dee2aaSAndroid Build Coastguard Worker const SkColor colors[] = { SK_ColorRED, SK_ColorGREEN };
317*c8dee2aaSAndroid Build Coastguard Worker const SkPoint pts1[] = { SkPoint::Make(1001, 1000001), SkPoint::Make(1000.99f, 1000000) };
318*c8dee2aaSAndroid Build Coastguard Worker
319*c8dee2aaSAndroid Build Coastguard Worker p.setShader(SkGradientShader::MakeLinear(pts1, colors, nullptr, 2, SkTileMode::kClamp));
320*c8dee2aaSAndroid Build Coastguard Worker
321*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> surface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(50, 50)));
322*c8dee2aaSAndroid Build Coastguard Worker surface->getCanvas()->scale(100, 100);
323*c8dee2aaSAndroid Build Coastguard Worker surface->getCanvas()->drawPaint(p);
324*c8dee2aaSAndroid Build Coastguard Worker
325*c8dee2aaSAndroid Build Coastguard Worker const SkPoint pts2[] = { SkPoint::Make(10000.99f, 1000000), SkPoint::Make(10001, 1000001) };
326*c8dee2aaSAndroid Build Coastguard Worker p.setShader(SkGradientShader::MakeLinear(pts2, colors, nullptr, 2, SkTileMode::kClamp));
327*c8dee2aaSAndroid Build Coastguard Worker surface->getCanvas()->drawPaint(p);
328*c8dee2aaSAndroid Build Coastguard Worker
329*c8dee2aaSAndroid Build Coastguard Worker // Passes if we don't trigger asserts.
330*c8dee2aaSAndroid Build Coastguard Worker }
331*c8dee2aaSAndroid Build Coastguard Worker
332*c8dee2aaSAndroid Build Coastguard Worker // http://crbug.com/636194
test_degenerate_linear(skiatest::Reporter *)333*c8dee2aaSAndroid Build Coastguard Worker static void test_degenerate_linear(skiatest::Reporter*) {
334*c8dee2aaSAndroid Build Coastguard Worker SkPaint p;
335*c8dee2aaSAndroid Build Coastguard Worker const SkColor colors[] = { SK_ColorRED, SK_ColorGREEN };
336*c8dee2aaSAndroid Build Coastguard Worker const SkPoint pts[] = {
337*c8dee2aaSAndroid Build Coastguard Worker SkPoint::Make(-46058024627067344430605278824628224.0f, 0),
338*c8dee2aaSAndroid Build Coastguard Worker SkPoint::Make(SK_ScalarMax, 0)
339*c8dee2aaSAndroid Build Coastguard Worker };
340*c8dee2aaSAndroid Build Coastguard Worker
341*c8dee2aaSAndroid Build Coastguard Worker p.setShader(SkGradientShader::MakeLinear(pts, colors, nullptr, 2, SkTileMode::kClamp));
342*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> surface(SkSurfaces::Raster(SkImageInfo::MakeN32Premul(50, 50)));
343*c8dee2aaSAndroid Build Coastguard Worker surface->getCanvas()->drawPaint(p);
344*c8dee2aaSAndroid Build Coastguard Worker
345*c8dee2aaSAndroid Build Coastguard Worker // Passes if we don't trigger asserts.
346*c8dee2aaSAndroid Build Coastguard Worker }
347*c8dee2aaSAndroid Build Coastguard Worker
348*c8dee2aaSAndroid Build Coastguard Worker // http://crbug.com/1149216
test_unsorted_degenerate(skiatest::Reporter * r)349*c8dee2aaSAndroid Build Coastguard Worker static void test_unsorted_degenerate(skiatest::Reporter* r) {
350*c8dee2aaSAndroid Build Coastguard Worker // Passes if a valid solid color is computed for the degenerate gradient
351*c8dee2aaSAndroid Build Coastguard Worker // (unsorted positions are fixed during regular gradient construction, so this ensures the
352*c8dee2aaSAndroid Build Coastguard Worker // same fixing happens for degenerate gradients as well). If they aren't fixed, this test
353*c8dee2aaSAndroid Build Coastguard Worker // case produces a negative alpha, which asserts during SkPMColor4f::isOpaque().
354*c8dee2aaSAndroid Build Coastguard Worker const SkColor4f colors[] = { {0.f, 0.f, 0.f, 0.f},
355*c8dee2aaSAndroid Build Coastguard Worker {0.00784314f, 0.f, 0.f, 0.0627451f},
356*c8dee2aaSAndroid Build Coastguard Worker {0.f, 0.00392157f, 0.f, 0.f} };
357*c8dee2aaSAndroid Build Coastguard Worker const SkScalar positions[] = {0.00753367f, 8.54792e-44f, 1.46955e-39f};
358*c8dee2aaSAndroid Build Coastguard Worker
359*c8dee2aaSAndroid Build Coastguard Worker const SkPoint points[] { { 0.f, 0.f }, { 1e-20f, -1e-8f }}; // must be degenerate
360*c8dee2aaSAndroid Build Coastguard Worker // Use kMirror to go through average color stop calculation, vs. kClamp which would pick a color
361*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkShader> gradient = SkGradientShader::MakeLinear(points, colors, nullptr, positions, 3,
362*c8dee2aaSAndroid Build Coastguard Worker SkTileMode::kMirror);
363*c8dee2aaSAndroid Build Coastguard Worker
364*c8dee2aaSAndroid Build Coastguard Worker // The degenerate gradient shouldn't be null
365*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(r, SkToBool(gradient));
366*c8dee2aaSAndroid Build Coastguard Worker // And it shouldn't crash when creating a fragment processor
367*c8dee2aaSAndroid Build Coastguard Worker
368*c8dee2aaSAndroid Build Coastguard Worker GrColorInfo dstColorInfo(GrColorType::kRGBA_8888, kPremul_SkAlphaType,
369*c8dee2aaSAndroid Build Coastguard Worker SkColorSpace::MakeSRGB());
370*c8dee2aaSAndroid Build Coastguard Worker SkSurfaceProps props;
371*c8dee2aaSAndroid Build Coastguard Worker GrMockOptions options;
372*c8dee2aaSAndroid Build Coastguard Worker auto context = GrDirectContext::MakeMock(&options);
373*c8dee2aaSAndroid Build Coastguard Worker
374*c8dee2aaSAndroid Build Coastguard Worker GrFPArgs args(context.get(), &dstColorInfo, props, GrFPArgs::Scope::kDefault);
375*c8dee2aaSAndroid Build Coastguard Worker GrFragmentProcessors::Make(gradient.get(), args, SkMatrix::I());
376*c8dee2aaSAndroid Build Coastguard Worker }
377*c8dee2aaSAndroid Build Coastguard Worker
378*c8dee2aaSAndroid Build Coastguard Worker // "Interesting" fuzzer values.
test_linear_fuzzer(skiatest::Reporter *)379*c8dee2aaSAndroid Build Coastguard Worker static void test_linear_fuzzer(skiatest::Reporter*) {
380*c8dee2aaSAndroid Build Coastguard Worker static const SkColor gColors0[] = { 0x30303030, 0x30303030 };
381*c8dee2aaSAndroid Build Coastguard Worker static const SkColor gColors1[] = { 0x30303030, 0x30303030, 0x30303030 };
382*c8dee2aaSAndroid Build Coastguard Worker
383*c8dee2aaSAndroid Build Coastguard Worker static const SkScalar gPos1[] = { 0, 0, 1 };
384*c8dee2aaSAndroid Build Coastguard Worker
385*c8dee2aaSAndroid Build Coastguard Worker static const SkScalar gMatrix0[9] = {
386*c8dee2aaSAndroid Build Coastguard Worker 6.40969056e-10f, 0 , 6.40969056e-10f,
387*c8dee2aaSAndroid Build Coastguard Worker 0 , 4.42539023e-39f, 6.40969056e-10f,
388*c8dee2aaSAndroid Build Coastguard Worker 0 , 0 , 1
389*c8dee2aaSAndroid Build Coastguard Worker };
390*c8dee2aaSAndroid Build Coastguard Worker static const SkScalar gMatrix1[9] = {
391*c8dee2aaSAndroid Build Coastguard Worker -2.75294113f , 6.40969056e-10f, 6.40969056e-10f,
392*c8dee2aaSAndroid Build Coastguard Worker 6.40969056e-10f, 6.40969056e-10f, -3.32810161e+24f,
393*c8dee2aaSAndroid Build Coastguard Worker 6.40969056e-10f, 6.40969056e-10f, 0
394*c8dee2aaSAndroid Build Coastguard Worker };
395*c8dee2aaSAndroid Build Coastguard Worker static const SkScalar gMatrix2[9] = {
396*c8dee2aaSAndroid Build Coastguard Worker 7.93481258e+17f, 6.40969056e-10f, 6.40969056e-10f,
397*c8dee2aaSAndroid Build Coastguard Worker 6.40969056e-10f, 6.40969056e-10f, 6.40969056e-10f,
398*c8dee2aaSAndroid Build Coastguard Worker 6.40969056e-10f, 6.40969056e-10f, 0.688235283f
399*c8dee2aaSAndroid Build Coastguard Worker };
400*c8dee2aaSAndroid Build Coastguard Worker static const SkScalar gMatrix3[9] = {
401*c8dee2aaSAndroid Build Coastguard Worker 1.89180674e+11f, 6.40969056e-10f, 6.40969056e-10f,
402*c8dee2aaSAndroid Build Coastguard Worker 6.40969056e-10f, 6.40969056e-10f, 6.40969056e-10f,
403*c8dee2aaSAndroid Build Coastguard Worker 6.40969056e-10f, 11276.0469f , 8.12524808e+20f
404*c8dee2aaSAndroid Build Coastguard Worker };
405*c8dee2aaSAndroid Build Coastguard Worker
406*c8dee2aaSAndroid Build Coastguard Worker static const struct {
407*c8dee2aaSAndroid Build Coastguard Worker SkPoint fPts[2];
408*c8dee2aaSAndroid Build Coastguard Worker const SkColor* fColors;
409*c8dee2aaSAndroid Build Coastguard Worker const SkScalar* fPos;
410*c8dee2aaSAndroid Build Coastguard Worker int fCount;
411*c8dee2aaSAndroid Build Coastguard Worker SkTileMode fTileMode;
412*c8dee2aaSAndroid Build Coastguard Worker uint32_t fFlags;
413*c8dee2aaSAndroid Build Coastguard Worker const SkScalar* fLocalMatrix;
414*c8dee2aaSAndroid Build Coastguard Worker const SkScalar* fGlobalMatrix;
415*c8dee2aaSAndroid Build Coastguard Worker } gConfigs[] = {
416*c8dee2aaSAndroid Build Coastguard Worker {
417*c8dee2aaSAndroid Build Coastguard Worker {{0, -2.752941f}, {0, 0}},
418*c8dee2aaSAndroid Build Coastguard Worker gColors0,
419*c8dee2aaSAndroid Build Coastguard Worker nullptr,
420*c8dee2aaSAndroid Build Coastguard Worker std::size(gColors0),
421*c8dee2aaSAndroid Build Coastguard Worker SkTileMode::kClamp,
422*c8dee2aaSAndroid Build Coastguard Worker 0,
423*c8dee2aaSAndroid Build Coastguard Worker gMatrix0,
424*c8dee2aaSAndroid Build Coastguard Worker nullptr
425*c8dee2aaSAndroid Build Coastguard Worker },
426*c8dee2aaSAndroid Build Coastguard Worker {
427*c8dee2aaSAndroid Build Coastguard Worker {{4.42539023e-39f, -4.42539023e-39f}, {9.78041162e-15f, 4.42539023e-39f}},
428*c8dee2aaSAndroid Build Coastguard Worker gColors1,
429*c8dee2aaSAndroid Build Coastguard Worker gPos1,
430*c8dee2aaSAndroid Build Coastguard Worker std::size(gColors1),
431*c8dee2aaSAndroid Build Coastguard Worker SkTileMode::kClamp,
432*c8dee2aaSAndroid Build Coastguard Worker 0,
433*c8dee2aaSAndroid Build Coastguard Worker nullptr,
434*c8dee2aaSAndroid Build Coastguard Worker gMatrix1
435*c8dee2aaSAndroid Build Coastguard Worker },
436*c8dee2aaSAndroid Build Coastguard Worker {
437*c8dee2aaSAndroid Build Coastguard Worker {{4.42539023e-39f, 6.40969056e-10f}, {6.40969056e-10f, 1.49237238e-19f}},
438*c8dee2aaSAndroid Build Coastguard Worker gColors1,
439*c8dee2aaSAndroid Build Coastguard Worker gPos1,
440*c8dee2aaSAndroid Build Coastguard Worker std::size(gColors1),
441*c8dee2aaSAndroid Build Coastguard Worker SkTileMode::kClamp,
442*c8dee2aaSAndroid Build Coastguard Worker 0,
443*c8dee2aaSAndroid Build Coastguard Worker nullptr,
444*c8dee2aaSAndroid Build Coastguard Worker gMatrix2
445*c8dee2aaSAndroid Build Coastguard Worker },
446*c8dee2aaSAndroid Build Coastguard Worker {
447*c8dee2aaSAndroid Build Coastguard Worker {{6.40969056e-10f, 6.40969056e-10f}, {6.40969056e-10f, -0.688235283f}},
448*c8dee2aaSAndroid Build Coastguard Worker gColors0,
449*c8dee2aaSAndroid Build Coastguard Worker nullptr,
450*c8dee2aaSAndroid Build Coastguard Worker std::size(gColors0),
451*c8dee2aaSAndroid Build Coastguard Worker SkTileMode::kClamp,
452*c8dee2aaSAndroid Build Coastguard Worker 0,
453*c8dee2aaSAndroid Build Coastguard Worker gMatrix3,
454*c8dee2aaSAndroid Build Coastguard Worker nullptr
455*c8dee2aaSAndroid Build Coastguard Worker },
456*c8dee2aaSAndroid Build Coastguard Worker };
457*c8dee2aaSAndroid Build Coastguard Worker
458*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkColorSpace> srgb = SkColorSpace::MakeSRGB();
459*c8dee2aaSAndroid Build Coastguard Worker SkColorSpace* colorSpaces[] = {
460*c8dee2aaSAndroid Build Coastguard Worker nullptr, // hits the legacy gradient impl
461*c8dee2aaSAndroid Build Coastguard Worker srgb.get(), // triggers 4f/raster-pipeline
462*c8dee2aaSAndroid Build Coastguard Worker };
463*c8dee2aaSAndroid Build Coastguard Worker
464*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
465*c8dee2aaSAndroid Build Coastguard Worker
466*c8dee2aaSAndroid Build Coastguard Worker for (const SkColorSpace* colorSpace : colorSpaces) {
467*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> surface = SkSurfaces::Raster(SkImageInfo::Make(
468*c8dee2aaSAndroid Build Coastguard Worker 100, 100, kN32_SkColorType, kPremul_SkAlphaType, sk_ref_sp(colorSpace)));
469*c8dee2aaSAndroid Build Coastguard Worker SkCanvas* canvas = surface->getCanvas();
470*c8dee2aaSAndroid Build Coastguard Worker
471*c8dee2aaSAndroid Build Coastguard Worker for (const auto& config : gConfigs) {
472*c8dee2aaSAndroid Build Coastguard Worker SkAutoCanvasRestore acr(canvas, false);
473*c8dee2aaSAndroid Build Coastguard Worker SkTLazy<SkMatrix> localMatrix;
474*c8dee2aaSAndroid Build Coastguard Worker if (config.fLocalMatrix) {
475*c8dee2aaSAndroid Build Coastguard Worker localMatrix.init();
476*c8dee2aaSAndroid Build Coastguard Worker localMatrix->set9(config.fLocalMatrix);
477*c8dee2aaSAndroid Build Coastguard Worker }
478*c8dee2aaSAndroid Build Coastguard Worker
479*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(SkGradientShader::MakeLinear(config.fPts,
480*c8dee2aaSAndroid Build Coastguard Worker config.fColors,
481*c8dee2aaSAndroid Build Coastguard Worker config.fPos,
482*c8dee2aaSAndroid Build Coastguard Worker config.fCount,
483*c8dee2aaSAndroid Build Coastguard Worker config.fTileMode,
484*c8dee2aaSAndroid Build Coastguard Worker config.fFlags,
485*c8dee2aaSAndroid Build Coastguard Worker localMatrix.getMaybeNull()));
486*c8dee2aaSAndroid Build Coastguard Worker if (config.fGlobalMatrix) {
487*c8dee2aaSAndroid Build Coastguard Worker SkMatrix m;
488*c8dee2aaSAndroid Build Coastguard Worker m.set9(config.fGlobalMatrix);
489*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
490*c8dee2aaSAndroid Build Coastguard Worker canvas->concat(m);
491*c8dee2aaSAndroid Build Coastguard Worker }
492*c8dee2aaSAndroid Build Coastguard Worker
493*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPaint(paint);
494*c8dee2aaSAndroid Build Coastguard Worker }
495*c8dee2aaSAndroid Build Coastguard Worker }
496*c8dee2aaSAndroid Build Coastguard Worker }
497*c8dee2aaSAndroid Build Coastguard Worker
test_sweep_fuzzer(skiatest::Reporter *)498*c8dee2aaSAndroid Build Coastguard Worker static void test_sweep_fuzzer(skiatest::Reporter*) {
499*c8dee2aaSAndroid Build Coastguard Worker static const SkColor gColors0[] = { 0x30303030, 0x30303030, 0x30303030 };
500*c8dee2aaSAndroid Build Coastguard Worker static const SkScalar gPos0[] = { -47919293023455565225163489280.0f, 0, 1 };
501*c8dee2aaSAndroid Build Coastguard Worker static const SkScalar gMatrix0[9] = {
502*c8dee2aaSAndroid Build Coastguard Worker 1.12116716e-13f, 0 , 8.50489682e+16f,
503*c8dee2aaSAndroid Build Coastguard Worker 4.1917041e-41f , 3.51369881e-23f, -2.54344271e-26f,
504*c8dee2aaSAndroid Build Coastguard Worker 9.61111907e+17f, -3.35263808e-29f, -1.35659403e+14f
505*c8dee2aaSAndroid Build Coastguard Worker };
506*c8dee2aaSAndroid Build Coastguard Worker static const struct {
507*c8dee2aaSAndroid Build Coastguard Worker SkPoint fCenter;
508*c8dee2aaSAndroid Build Coastguard Worker const SkColor* fColors;
509*c8dee2aaSAndroid Build Coastguard Worker const SkScalar* fPos;
510*c8dee2aaSAndroid Build Coastguard Worker int fCount;
511*c8dee2aaSAndroid Build Coastguard Worker const SkScalar* fGlobalMatrix;
512*c8dee2aaSAndroid Build Coastguard Worker } gConfigs[] = {
513*c8dee2aaSAndroid Build Coastguard Worker {
514*c8dee2aaSAndroid Build Coastguard Worker { 0, 0 },
515*c8dee2aaSAndroid Build Coastguard Worker gColors0,
516*c8dee2aaSAndroid Build Coastguard Worker gPos0,
517*c8dee2aaSAndroid Build Coastguard Worker std::size(gColors0),
518*c8dee2aaSAndroid Build Coastguard Worker gMatrix0
519*c8dee2aaSAndroid Build Coastguard Worker },
520*c8dee2aaSAndroid Build Coastguard Worker };
521*c8dee2aaSAndroid Build Coastguard Worker
522*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> surface = SkSurfaces::Raster(SkImageInfo::MakeN32Premul(100, 100));
523*c8dee2aaSAndroid Build Coastguard Worker SkCanvas* canvas = surface->getCanvas();
524*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
525*c8dee2aaSAndroid Build Coastguard Worker
526*c8dee2aaSAndroid Build Coastguard Worker for (const auto& config : gConfigs) {
527*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(SkGradientShader::MakeSweep(config.fCenter.x(),
528*c8dee2aaSAndroid Build Coastguard Worker config.fCenter.y(),
529*c8dee2aaSAndroid Build Coastguard Worker config.fColors,
530*c8dee2aaSAndroid Build Coastguard Worker config.fPos,
531*c8dee2aaSAndroid Build Coastguard Worker config.fCount));
532*c8dee2aaSAndroid Build Coastguard Worker
533*c8dee2aaSAndroid Build Coastguard Worker SkAutoCanvasRestore acr(canvas, false);
534*c8dee2aaSAndroid Build Coastguard Worker if (config.fGlobalMatrix) {
535*c8dee2aaSAndroid Build Coastguard Worker SkMatrix m;
536*c8dee2aaSAndroid Build Coastguard Worker m.set9(config.fGlobalMatrix);
537*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
538*c8dee2aaSAndroid Build Coastguard Worker canvas->concat(m);
539*c8dee2aaSAndroid Build Coastguard Worker }
540*c8dee2aaSAndroid Build Coastguard Worker canvas->drawPaint(paint);
541*c8dee2aaSAndroid Build Coastguard Worker }
542*c8dee2aaSAndroid Build Coastguard Worker }
543*c8dee2aaSAndroid Build Coastguard Worker
544*c8dee2aaSAndroid Build Coastguard Worker // Draw a sweep gradient in a translated canvas such that the colors in the center pixels of the
545*c8dee2aaSAndroid Build Coastguard Worker // gradient will be evaluated at x = 0. The gradient implementation must not call atan2(y, x) with
546*c8dee2aaSAndroid Build Coastguard Worker // x == 0, as this will result in undefined behavior and likely incorrect results.
547*c8dee2aaSAndroid Build Coastguard Worker // https://crbug.com/1468916
test_sweep_gradient_zero_x(skiatest::Reporter * reporter,SkSurface * surface)548*c8dee2aaSAndroid Build Coastguard Worker void test_sweep_gradient_zero_x(skiatest::Reporter* reporter, SkSurface* surface) {
549*c8dee2aaSAndroid Build Coastguard Worker // The gradient drawn has yellow for the first half and blue for the second half, using hard
550*c8dee2aaSAndroid Build Coastguard Worker // stops and running clockwise from (1, 0), so we should draw a rectangle with a blue top-half
551*c8dee2aaSAndroid Build Coastguard Worker // and yellow bottom-half.
552*c8dee2aaSAndroid Build Coastguard Worker constexpr float pts[4] = {0.0f, 0.5f, 0.5f, 1.0f};
553*c8dee2aaSAndroid Build Coastguard Worker constexpr SkColor colors[4] = {SK_ColorYELLOW, SK_ColorYELLOW, SK_ColorBLUE, SK_ColorBLUE};
554*c8dee2aaSAndroid Build Coastguard Worker SkCanvas* canvas = surface->getCanvas();
555*c8dee2aaSAndroid Build Coastguard Worker canvas->save();
556*c8dee2aaSAndroid Build Coastguard Worker canvas->translate(2.5f, 2.5f);
557*c8dee2aaSAndroid Build Coastguard Worker SkPaint paint;
558*c8dee2aaSAndroid Build Coastguard Worker paint.setShader(SkGradientShader::MakeSweep(0.0f, 0.0f, colors, pts, 4));
559*c8dee2aaSAndroid Build Coastguard Worker canvas->drawRect(SkRect::MakeXYWH(-2.5f, -2.5f, 5.0f, 5.0f), paint);
560*c8dee2aaSAndroid Build Coastguard Worker canvas->restore();
561*c8dee2aaSAndroid Build Coastguard Worker
562*c8dee2aaSAndroid Build Coastguard Worker // Read pixels.
563*c8dee2aaSAndroid Build Coastguard Worker SkBitmap bitmap;
564*c8dee2aaSAndroid Build Coastguard Worker SkPixmap pixmap;
565*c8dee2aaSAndroid Build Coastguard Worker bitmap.allocPixels(surface->imageInfo());
566*c8dee2aaSAndroid Build Coastguard Worker SkAssertResult(bitmap.peekPixels(&pixmap));
567*c8dee2aaSAndroid Build Coastguard Worker if (!surface->readPixels(pixmap, 0, 0)) {
568*c8dee2aaSAndroid Build Coastguard Worker ERRORF(reporter, "readPixels failed");
569*c8dee2aaSAndroid Build Coastguard Worker return;
570*c8dee2aaSAndroid Build Coastguard Worker }
571*c8dee2aaSAndroid Build Coastguard Worker
572*c8dee2aaSAndroid Build Coastguard Worker // Check the results.
573*c8dee2aaSAndroid Build Coastguard Worker SkColor4f topColor = pixmap.getColor4f(2, 0);
574*c8dee2aaSAndroid Build Coastguard Worker SkColor4f bottomColor = pixmap.getColor4f(2, 4);
575*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, topColor == SkColors::kBlue);
576*c8dee2aaSAndroid Build Coastguard Worker REPORTER_ASSERT(reporter, bottomColor == SkColors::kYellow);
577*c8dee2aaSAndroid Build Coastguard Worker }
578*c8dee2aaSAndroid Build Coastguard Worker
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(TestSweepGradientZeroXGanesh,reporter,contextInfo,CtsEnforcement::kApiLevel_V)579*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(TestSweepGradientZeroXGanesh,
580*c8dee2aaSAndroid Build Coastguard Worker reporter,
581*c8dee2aaSAndroid Build Coastguard Worker contextInfo,
582*c8dee2aaSAndroid Build Coastguard Worker CtsEnforcement::kApiLevel_V) {
583*c8dee2aaSAndroid Build Coastguard Worker SkImageInfo ii = SkImageInfo::Make(SkISize::Make(5, 5),
584*c8dee2aaSAndroid Build Coastguard Worker SkColorType::kRGBA_8888_SkColorType,
585*c8dee2aaSAndroid Build Coastguard Worker SkAlphaType::kPremul_SkAlphaType);
586*c8dee2aaSAndroid Build Coastguard Worker GrDirectContext* context = contextInfo.directContext();
587*c8dee2aaSAndroid Build Coastguard Worker sk_sp<SkSurface> surface = SkSurfaces::RenderTarget(context, skgpu::Budgeted::kYes, ii);
588*c8dee2aaSAndroid Build Coastguard Worker test_sweep_gradient_zero_x(reporter, surface.get());
589*c8dee2aaSAndroid Build Coastguard Worker }
590*c8dee2aaSAndroid Build Coastguard Worker
591*c8dee2aaSAndroid Build Coastguard Worker // TODO: Fix this bug in Graphite as well.
592*c8dee2aaSAndroid Build Coastguard Worker // #if defined(SK_GRAPHITE)
593*c8dee2aaSAndroid Build Coastguard Worker // DEF_GRAPHITE_TEST_FOR_RENDERING_CONTEXTS(TestSweepGradientZeroXGraphite, reporter, context,
594*c8dee2aaSAndroid Build Coastguard Worker // CtsEnforcement::kNextRelease) {
595*c8dee2aaSAndroid Build Coastguard Worker // using namespace skgpu::graphite;
596*c8dee2aaSAndroid Build Coastguard Worker // SkImageInfo ii = SkImageInfo::Make(SkISize::Make(5, 5),
597*c8dee2aaSAndroid Build Coastguard Worker // SkColorType::kRGBA_8888_SkColorType,
598*c8dee2aaSAndroid Build Coastguard Worker // SkAlphaType::kPremul_SkAlphaType);
599*c8dee2aaSAndroid Build Coastguard Worker // std::unique_ptr<Recorder> recorder = context->makeRecorder();
600*c8dee2aaSAndroid Build Coastguard Worker // sk_sp<SkSurface> surface = SkSurfaces::RenderTarget(recorder.get(), ii);
601*c8dee2aaSAndroid Build Coastguard Worker // test_sweep_gradient_zero_x(reporter, surface.get());
602*c8dee2aaSAndroid Build Coastguard Worker // }
603*c8dee2aaSAndroid Build Coastguard Worker // #endif
604*c8dee2aaSAndroid Build Coastguard Worker
DEF_TEST(Gradient,reporter)605*c8dee2aaSAndroid Build Coastguard Worker DEF_TEST(Gradient, reporter) {
606*c8dee2aaSAndroid Build Coastguard Worker TestGradientShaders(reporter);
607*c8dee2aaSAndroid Build Coastguard Worker TestConstantGradient(reporter);
608*c8dee2aaSAndroid Build Coastguard Worker test_big_grad(reporter);
609*c8dee2aaSAndroid Build Coastguard Worker test_nearly_vertical(reporter);
610*c8dee2aaSAndroid Build Coastguard Worker test_vertical(reporter);
611*c8dee2aaSAndroid Build Coastguard Worker test_linear_fuzz(reporter);
612*c8dee2aaSAndroid Build Coastguard Worker test_two_point_conical_zero_radius(reporter);
613*c8dee2aaSAndroid Build Coastguard Worker test_clamping_overflow(reporter);
614*c8dee2aaSAndroid Build Coastguard Worker test_degenerate_linear(reporter);
615*c8dee2aaSAndroid Build Coastguard Worker test_linear_fuzzer(reporter);
616*c8dee2aaSAndroid Build Coastguard Worker test_sweep_fuzzer(reporter);
617*c8dee2aaSAndroid Build Coastguard Worker test_unsorted_degenerate(reporter);
618*c8dee2aaSAndroid Build Coastguard Worker }
619