blob: a9a7805d5b195b47952b2d17072c04994bd0a9df [file] [log] [blame]
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001/*
2 * Copyright 2014 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 */
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00007
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00008
9#include "SkTwoPointConicalGradient.h"
10
commit-bot@chromium.orgef93d292014-04-10 15:37:52 +000011#if SK_SUPPORT_GPU
egdaniel7ea439b2015-12-03 09:20:44 -080012#include "GrCoordTransform.h"
13#include "GrInvariantOutput.h"
joshualitt8ca93e72015-07-08 06:51:43 -070014#include "GrPaint.h"
egdaniel2d721d32015-11-11 13:06:05 -080015#include "glsl/GrGLSLFragmentShaderBuilder.h"
egdaniel018fb622015-10-28 07:26:40 -070016#include "glsl/GrGLSLProgramDataManager.h"
egdaniel7ea439b2015-12-03 09:20:44 -080017#include "glsl/GrGLSLUniformHandler.h"
brianosman9557c272016-09-15 06:59:15 -070018#include "SkTwoPointConicalGradient_gpu.h"
19
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +000020// For brevity
egdaniel018fb622015-10-28 07:26:40 -070021typedef GrGLSLProgramDataManager::UniformHandle UniformHandle;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +000022
commit-bot@chromium.org80894672014-04-22 21:24:22 +000023static const SkScalar kErrorTol = 0.00001f;
egdaniel8405ef92014-06-09 11:57:28 -070024static const SkScalar kEdgeErrorTol = 5.f * kErrorTol;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +000025
26/**
27 * We have three general cases for 2pt conical gradients. First we always assume that
28 * the start radius <= end radius. Our first case (kInside_) is when the start circle
29 * is completely enclosed by the end circle. The second case (kOutside_) is the case
30 * when the start circle is either completely outside the end circle or the circles
31 * overlap. The final case (kEdge_) is when the start circle is inside the end one,
32 * but the two are just barely touching at 1 point along their edges.
33 */
34enum ConicalType {
35 kInside_ConicalType,
36 kOutside_ConicalType,
37 kEdge_ConicalType,
38};
39
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000040//////////////////////////////////////////////////////////////////////////////
41
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +000042static void set_matrix_edge_conical(const SkTwoPointConicalGradient& shader,
43 SkMatrix* invLMatrix) {
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000044 // Inverse of the current local matrix is passed in then,
45 // translate to center1, rotate so center2 is on x axis.
46 const SkPoint& center1 = shader.getStartCenter();
47 const SkPoint& center2 = shader.getEndCenter();
48
49 invLMatrix->postTranslate(-center1.fX, -center1.fY);
50
51 SkPoint diff = center2 - center1;
52 SkScalar diffLen = diff.length();
53 if (0 != diffLen) {
54 SkScalar invDiffLen = SkScalarInvert(diffLen);
55 SkMatrix rot;
56 rot.setSinCos(-SkScalarMul(invDiffLen, diff.fY),
57 SkScalarMul(invDiffLen, diff.fX));
58 invLMatrix->postConcat(rot);
59 }
60}
61
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +000062class Edge2PtConicalEffect : public GrGradientEffect {
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +000063public:
fmenozzi55d318d2016-08-09 08:05:57 -070064 class GLSLEdge2PtConicalProcessor;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +000065
brianosman9557c272016-09-15 06:59:15 -070066 static sk_sp<GrFragmentProcessor> Make(const CreateArgs& args) {
67 return sk_sp<GrFragmentProcessor>(new Edge2PtConicalEffect(args));
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000068 }
69
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +000070 virtual ~Edge2PtConicalEffect() {}
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000071
mtklein36352bf2015-03-25 18:17:31 -070072 const char* name() const override {
joshualitteb2a6762014-12-04 11:35:33 -080073 return "Two-Point Conical Gradient Edge Touching";
74 }
75
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000076 // The radial gradient parameters can collapse to a linear (instead of quadratic) equation.
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000077 SkScalar center() const { return fCenterX1; }
78 SkScalar diffRadius() const { return fDiffRadius; }
79 SkScalar radius() const { return fRadius0; }
80
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000081private:
egdaniel57d3b032015-11-13 11:57:27 -080082 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -070083
egdaniel57d3b032015-11-13 11:57:27 -080084 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -070085
mtklein36352bf2015-03-25 18:17:31 -070086 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -070087 const Edge2PtConicalEffect& s = sBase.cast<Edge2PtConicalEffect>();
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000088 return (INHERITED::onIsEqual(sBase) &&
89 this->fCenterX1 == s.fCenterX1 &&
90 this->fRadius0 == s.fRadius0 &&
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +000091 this->fDiffRadius == s.fDiffRadius);
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000092 }
93
brianosman9557c272016-09-15 06:59:15 -070094 Edge2PtConicalEffect(const CreateArgs& args)
95 : INHERITED(args) {
96 const SkTwoPointConicalGradient& shader =
97 *static_cast<const SkTwoPointConicalGradient*>(args.fShader);
98 fCenterX1 = shader.getCenterX1();
99 fRadius0 = shader.getStartRadius();
100 fDiffRadius = shader.getDiffRadius();
joshualitteb2a6762014-12-04 11:35:33 -0800101 this->initClassID<Edge2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000102 // We should only be calling this shader if we are degenerate case with touching circles
egdaniel8405ef92014-06-09 11:57:28 -0700103 // When deciding if we are in edge case, we scaled by the end radius for cases when the
joshualitt01258472014-09-22 10:29:30 -0700104 // start radius was close to zero, otherwise we scaled by the start radius. In addition
105 // Our test for the edge case in set_matrix_circle_conical has a higher tolerance so we
106 // need the sqrt value below
107 SkASSERT(SkScalarAbs(SkScalarAbs(fDiffRadius) - fCenterX1) <
108 (fRadius0 < kErrorTol ? shader.getEndRadius() * kEdgeErrorTol :
109 fRadius0 * sqrt(kEdgeErrorTol)));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000110
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +0000111 // We pass the linear part of the quadratic as a varying.
112 // float b = -2.0 * (fCenterX1 * x + fRadius0 * fDiffRadius * z)
113 fBTransform = this->getCoordTransform();
114 SkMatrix& bMatrix = *fBTransform.accessMatrix();
115 SkScalar r0dr = SkScalarMul(fRadius0, fDiffRadius);
116 bMatrix[SkMatrix::kMScaleX] = -2 * (SkScalarMul(fCenterX1, bMatrix[SkMatrix::kMScaleX]) +
117 SkScalarMul(r0dr, bMatrix[SkMatrix::kMPersp0]));
118 bMatrix[SkMatrix::kMSkewX] = -2 * (SkScalarMul(fCenterX1, bMatrix[SkMatrix::kMSkewX]) +
119 SkScalarMul(r0dr, bMatrix[SkMatrix::kMPersp1]));
120 bMatrix[SkMatrix::kMTransX] = -2 * (SkScalarMul(fCenterX1, bMatrix[SkMatrix::kMTransX]) +
121 SkScalarMul(r0dr, bMatrix[SkMatrix::kMPersp2]));
122 this->addCoordTransform(&fBTransform);
123 }
124
joshualittb0a8a372014-09-23 09:50:21 -0700125 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +0000126
127 // @{
128 // Cache of values - these can change arbitrarily, EXCEPT
129 // we shouldn't change between degenerate and non-degenerate?!
130
131 GrCoordTransform fBTransform;
132 SkScalar fCenterX1;
133 SkScalar fRadius0;
134 SkScalar fDiffRadius;
135
136 // @}
137
138 typedef GrGradientEffect INHERITED;
139};
140
fmenozzi55d318d2016-08-09 08:05:57 -0700141class Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +0000142public:
fmenozzi55d318d2016-08-09 08:05:57 -0700143 GLSLEdge2PtConicalProcessor(const GrProcessor&);
144 virtual ~GLSLEdge2PtConicalProcessor() { }
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000145
wangyix7c157a92015-07-22 15:08:53 -0700146 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000147
jvanverthcfc18862015-04-28 08:48:20 -0700148 static void GenKey(const GrProcessor&, const GrGLSLCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000149
150protected:
egdaniel018fb622015-10-28 07:26:40 -0700151 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -0700152
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000153 UniformHandle fParamUni;
154
155 const char* fVSVaryingName;
156 const char* fFSVaryingName;
157
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000158 // @{
159 /// Values last uploaded as uniforms
160
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000161 SkScalar fCachedRadius;
162 SkScalar fCachedDiffRadius;
163
164 // @}
165
166private:
fmenozzi55d318d2016-08-09 08:05:57 -0700167 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000168
169};
170
egdaniel57d3b032015-11-13 11:57:27 -0800171void Edge2PtConicalEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
172 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -0700173 Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800174}
175
egdaniel57d3b032015-11-13 11:57:27 -0800176GrGLSLFragmentProcessor* Edge2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -0700177 return new Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor(*this);
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000178}
skia.committer@gmail.com221b9112014-04-04 03:04:32 +0000179
joshualittb0a8a372014-09-23 09:50:21 -0700180GR_DEFINE_FRAGMENT_PROCESSOR_TEST(Edge2PtConicalEffect);
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000181
joshualitt01258472014-09-22 10:29:30 -0700182/*
183 * All Two point conical gradient test create functions may occasionally create edge case shaders
184 */
bungeman06ca8ec2016-06-09 08:01:03 -0700185sk_sp<GrFragmentProcessor> Edge2PtConicalEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700186 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
187 SkScalar radius1 = d->fRandom->nextUScalar1();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000188 SkPoint center2;
189 SkScalar radius2;
190 do {
joshualitt0067ff52015-07-08 14:26:19 -0700191 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000192 // If the circles are identical the factory will give us an empty shader.
193 // This will happen if we pick identical centers
194 } while (center1 == center2);
195
196 // Below makes sure that circle one is contained within circle two
197 // and both circles are touching on an edge
198 SkPoint diff = center2 - center1;
199 SkScalar diffLen = diff.length();
200 radius2 = radius1 + diffLen;
201
202 SkColor colors[kMaxRandomGradientColors];
203 SkScalar stopsArray[kMaxRandomGradientColors];
204 SkScalar* stops = stopsArray;
205 SkShader::TileMode tm;
joshualitt0067ff52015-07-08 14:26:19 -0700206 int colorCount = RandomGradientParams(d->fRandom, colors, &stops, &tm);
reed8a21c9f2016-03-08 18:50:00 -0800207 auto shader = SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
208 colors, stops, colorCount, tm);
brianosman839345d2016-07-22 11:04:53 -0700209 SkMatrix viewMatrix = GrTest::TestMatrix(d->fRandom);
210 sk_sp<GrFragmentProcessor> fp = shader->asFragmentProcessor(SkShader::AsFPArgs(
brianosman1638c0d2016-07-25 05:12:53 -0700211 d->fContext, &viewMatrix, NULL, kNone_SkFilterQuality, nullptr,
212 SkSourceGammaTreatment::kRespect));
bsalomonc21b09e2015-08-28 18:46:56 -0700213 GrAlwaysAssert(fp);
joshualittb0a8a372014-09-23 09:50:21 -0700214 return fp;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000215}
216
fmenozzi55d318d2016-08-09 08:05:57 -0700217Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::GLSLEdge2PtConicalProcessor(const GrProcessor&)
halcanary96fcdcc2015-08-27 07:41:13 -0700218 : fVSVaryingName(nullptr)
219 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000220 , fCachedRadius(-SK_ScalarMax)
221 , fCachedDiffRadius(-SK_ScalarMax) {}
222
fmenozzi55d318d2016-08-09 08:05:57 -0700223void Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -0700224 const Edge2PtConicalEffect& ge = args.fFp.cast<Edge2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -0800225 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
226 this->emitUniforms(uniformHandler, ge);
jvanverthde11ee42016-02-26 13:58:40 -0800227 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
228 kVec3f_GrSLType, kDefault_GrSLPrecision,
229 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000230
231 SkString cName("c");
232 SkString tName("t");
233 SkString p0; // start radius
234 SkString p1; // start radius squared
235 SkString p2; // difference in radii (r1 - r0)
236
jvanverthde11ee42016-02-26 13:58:40 -0800237
238 p0.appendf("%s.x", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
239 p1.appendf("%s.y", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
240 p2.appendf("%s.z", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000241
242 // We interpolate the linear component in coords[1].
bsalomon1a1aa932016-09-12 09:30:36 -0700243 SkASSERT(args.fTransformedCoords[0].getType() == args.fTransformedCoords[1].getType());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000244 const char* coords2D;
245 SkString bVar;
cdalton85285412016-02-18 12:37:07 -0800246 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -0700247 if (kVec3f_GrSLType == args.fTransformedCoords[0].getType()) {
egdaniel4ca2e602015-11-18 08:01:26 -0800248 fragBuilder->codeAppendf("\tvec3 interpolants = vec3(%s.xy / %s.z, %s.x / %s.z);\n",
bsalomon1a1aa932016-09-12 09:30:36 -0700249 args.fTransformedCoords[0].c_str(),
250 args.fTransformedCoords[0].c_str(),
251 args.fTransformedCoords[1].c_str(),
252 args.fTransformedCoords[1].c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000253 coords2D = "interpolants.xy";
254 bVar = "interpolants.z";
255 } else {
bsalomon1a1aa932016-09-12 09:30:36 -0700256 coords2D = args.fTransformedCoords[0].c_str();
257 bVar.printf("%s.x", args.fTransformedCoords[1].c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000258 }
259
260 // output will default to transparent black (we simply won't write anything
261 // else to it if invalid, instead of discarding or returning prematurely)
egdaniel4ca2e602015-11-18 08:01:26 -0800262 fragBuilder->codeAppendf("\t%s = vec4(0.0,0.0,0.0,0.0);\n", args.fOutputColor);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000263
264 // c = (x^2)+(y^2) - params[1]
egdaniel4ca2e602015-11-18 08:01:26 -0800265 fragBuilder->codeAppendf("\tfloat %s = dot(%s, %s) - %s;\n",
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000266 cName.c_str(), coords2D, coords2D, p1.c_str());
267
268 // linear case: t = -c/b
egdaniel4ca2e602015-11-18 08:01:26 -0800269 fragBuilder->codeAppendf("\tfloat %s = -(%s / %s);\n", tName.c_str(),
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000270 cName.c_str(), bVar.c_str());
271
272 // if r(t) > 0, then t will be the x coordinate
egdaniel4ca2e602015-11-18 08:01:26 -0800273 fragBuilder->codeAppendf("\tif (%s * %s + %s > 0.0) {\n", tName.c_str(),
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000274 p2.c_str(), p0.c_str());
egdaniel4ca2e602015-11-18 08:01:26 -0800275 fragBuilder->codeAppend("\t");
egdaniel7ea439b2015-12-03 09:20:44 -0800276 this->emitColor(fragBuilder,
277 uniformHandler,
egdaniela2e3e0f2015-11-19 07:23:45 -0800278 args.fGLSLCaps,
egdaniel4ca2e602015-11-18 08:01:26 -0800279 ge,
280 tName.c_str(),
281 args.fOutputColor,
282 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -0700283 args.fTexSamplers);
egdaniel4ca2e602015-11-18 08:01:26 -0800284 fragBuilder->codeAppend("\t}\n");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000285}
286
fmenozzi55d318d2016-08-09 08:05:57 -0700287void Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::onSetData(
288 const GrGLSLProgramDataManager& pdman,
289 const GrProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -0700290 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -0700291 const Edge2PtConicalEffect& data = processor.cast<Edge2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000292 SkScalar radius0 = data.radius();
293 SkScalar diffRadius = data.diffRadius();
294
295 if (fCachedRadius != radius0 ||
296 fCachedDiffRadius != diffRadius) {
297
halcanary9d524f22016-03-29 09:03:52 -0700298 pdman.set3f(fParamUni, SkScalarToFloat(radius0),
jvanverthde11ee42016-02-26 13:58:40 -0800299 SkScalarToFloat(SkScalarMul(radius0, radius0)), SkScalarToFloat(diffRadius));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000300 fCachedRadius = radius0;
301 fCachedDiffRadius = diffRadius;
302 }
303}
304
fmenozzi55d318d2016-08-09 08:05:57 -0700305void Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::GenKey(const GrProcessor& processor,
jvanverthcfc18862015-04-28 08:48:20 -0700306 const GrGLSLCaps&, GrProcessorKeyBuilder* b) {
joshualittb0a8a372014-09-23 09:50:21 -0700307 b->add32(GenBaseGradientKey(processor));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000308}
309
310//////////////////////////////////////////////////////////////////////////////
311// Focal Conical Gradients
312//////////////////////////////////////////////////////////////////////////////
313
314static ConicalType set_matrix_focal_conical(const SkTwoPointConicalGradient& shader,
315 SkMatrix* invLMatrix, SkScalar* focalX) {
316 // Inverse of the current local matrix is passed in then,
317 // translate, scale, and rotate such that endCircle is unit circle on x-axis,
318 // and focal point is at the origin.
319 ConicalType conicalType;
320 const SkPoint& focal = shader.getStartCenter();
321 const SkPoint& centerEnd = shader.getEndCenter();
322 SkScalar radius = shader.getEndRadius();
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000323 SkScalar invRadius = 1.f / radius;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000324
325 SkMatrix matrix;
326
327 matrix.setTranslate(-centerEnd.fX, -centerEnd.fY);
328 matrix.postScale(invRadius, invRadius);
329
330 SkPoint focalTrans;
331 matrix.mapPoints(&focalTrans, &focal, 1);
332 *focalX = focalTrans.length();
333
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000334 if (0.f != *focalX) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000335 SkScalar invFocalX = SkScalarInvert(*focalX);
336 SkMatrix rot;
337 rot.setSinCos(-SkScalarMul(invFocalX, focalTrans.fY),
338 SkScalarMul(invFocalX, focalTrans.fX));
339 matrix.postConcat(rot);
340 }
341
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000342 matrix.postTranslate(-(*focalX), 0.f);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000343
344 // If the focal point is touching the edge of the circle it will
345 // cause a degenerate case that must be handled separately
egdaniel8405ef92014-06-09 11:57:28 -0700346 // kEdgeErrorTol = 5 * kErrorTol was picked after manual testing the
347 // stability trade off versus the linear approx used in the Edge Shader
348 if (SkScalarAbs(1.f - (*focalX)) < kEdgeErrorTol) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000349 return kEdge_ConicalType;
350 }
351
352 // Scale factor 1 / (1 - focalX * focalX)
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000353 SkScalar oneMinusF2 = 1.f - SkScalarMul(*focalX, *focalX);
reed80ea19c2015-05-12 10:37:34 -0700354 SkScalar s = SkScalarInvert(oneMinusF2);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000355
356
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000357 if (s >= 0.f) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000358 conicalType = kInside_ConicalType;
359 matrix.postScale(s, s * SkScalarSqrt(oneMinusF2));
360 } else {
361 conicalType = kOutside_ConicalType;
362 matrix.postScale(s, s);
363 }
364
365 invLMatrix->postConcat(matrix);
366
367 return conicalType;
368}
369
370//////////////////////////////////////////////////////////////////////////////
371
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000372class FocalOutside2PtConicalEffect : public GrGradientEffect {
373public:
fmenozzi55d318d2016-08-09 08:05:57 -0700374 class GLSLFocalOutside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000375
brianosman9557c272016-09-15 06:59:15 -0700376 static sk_sp<GrFragmentProcessor> Make(const CreateArgs& args, SkScalar focalX) {
bungeman06ca8ec2016-06-09 08:01:03 -0700377 return sk_sp<GrFragmentProcessor>(
brianosman9557c272016-09-15 06:59:15 -0700378 new FocalOutside2PtConicalEffect(args, focalX));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000379 }
380
381 virtual ~FocalOutside2PtConicalEffect() { }
382
mtklein36352bf2015-03-25 18:17:31 -0700383 const char* name() const override {
joshualitteb2a6762014-12-04 11:35:33 -0800384 return "Two-Point Conical Gradient Focal Outside";
385 }
386
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000387 bool isFlipped() const { return fIsFlipped; }
388 SkScalar focal() const { return fFocalX; }
389
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000390private:
egdaniel57d3b032015-11-13 11:57:27 -0800391 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -0700392
egdaniel57d3b032015-11-13 11:57:27 -0800393 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -0700394
mtklein36352bf2015-03-25 18:17:31 -0700395 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -0700396 const FocalOutside2PtConicalEffect& s = sBase.cast<FocalOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000397 return (INHERITED::onIsEqual(sBase) &&
398 this->fFocalX == s.fFocalX &&
399 this->fIsFlipped == s.fIsFlipped);
400 }
401
brianosman9557c272016-09-15 06:59:15 -0700402 FocalOutside2PtConicalEffect(const CreateArgs& args, SkScalar focalX)
403 : INHERITED(args)
joshualittb2456052015-07-08 09:36:59 -0700404 , fFocalX(focalX)
brianosman9557c272016-09-15 06:59:15 -0700405 , fIsFlipped(static_cast<const SkTwoPointConicalGradient*>(args.fShader)->isFlippedGrad()) {
joshualitteb2a6762014-12-04 11:35:33 -0800406 this->initClassID<FocalOutside2PtConicalEffect>();
407 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000408
joshualittb0a8a372014-09-23 09:50:21 -0700409 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000410
411 SkScalar fFocalX;
412 bool fIsFlipped;
413
414 typedef GrGradientEffect INHERITED;
415};
416
fmenozzi55d318d2016-08-09 08:05:57 -0700417class FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor
418 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000419public:
fmenozzi55d318d2016-08-09 08:05:57 -0700420 GLSLFocalOutside2PtConicalProcessor(const GrProcessor&);
421 virtual ~GLSLFocalOutside2PtConicalProcessor() { }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000422
wangyix7c157a92015-07-22 15:08:53 -0700423 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000424
jvanverthcfc18862015-04-28 08:48:20 -0700425 static void GenKey(const GrProcessor&, const GrGLSLCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000426
427protected:
egdaniel018fb622015-10-28 07:26:40 -0700428 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -0700429
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000430 UniformHandle fParamUni;
431
432 const char* fVSVaryingName;
433 const char* fFSVaryingName;
434
435 bool fIsFlipped;
436
437 // @{
438 /// Values last uploaded as uniforms
439
440 SkScalar fCachedFocal;
441
442 // @}
443
444private:
fmenozzi55d318d2016-08-09 08:05:57 -0700445 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000446
447};
448
egdaniel57d3b032015-11-13 11:57:27 -0800449void FocalOutside2PtConicalEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
450 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -0700451 FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800452}
453
egdaniel57d3b032015-11-13 11:57:27 -0800454GrGLSLFragmentProcessor* FocalOutside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -0700455 return new FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000456}
457
joshualittb0a8a372014-09-23 09:50:21 -0700458GR_DEFINE_FRAGMENT_PROCESSOR_TEST(FocalOutside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000459
joshualitt01258472014-09-22 10:29:30 -0700460/*
461 * All Two point conical gradient test create functions may occasionally create edge case shaders
462 */
bungeman06ca8ec2016-06-09 08:01:03 -0700463sk_sp<GrFragmentProcessor> FocalOutside2PtConicalEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700464 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000465 SkScalar radius1 = 0.f;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000466 SkPoint center2;
467 SkScalar radius2;
468 do {
joshualitt0067ff52015-07-08 14:26:19 -0700469 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +0000470 // Need to make sure the centers are not the same or else focal point will be inside
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000471 } while (center1 == center2);
472 SkPoint diff = center2 - center1;
473 SkScalar diffLen = diff.length();
474 // Below makes sure that the focal point is not contained within circle two
joshualitt0067ff52015-07-08 14:26:19 -0700475 radius2 = d->fRandom->nextRangeF(0.f, diffLen);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000476
477 SkColor colors[kMaxRandomGradientColors];
478 SkScalar stopsArray[kMaxRandomGradientColors];
479 SkScalar* stops = stopsArray;
480 SkShader::TileMode tm;
joshualitt0067ff52015-07-08 14:26:19 -0700481 int colorCount = RandomGradientParams(d->fRandom, colors, &stops, &tm);
reed8a21c9f2016-03-08 18:50:00 -0800482 auto shader = SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
483 colors, stops, colorCount, tm);
brianosman839345d2016-07-22 11:04:53 -0700484 SkMatrix viewMatrix = GrTest::TestMatrix(d->fRandom);
485 sk_sp<GrFragmentProcessor> fp = shader->asFragmentProcessor(SkShader::AsFPArgs(
brianosman1638c0d2016-07-25 05:12:53 -0700486 d->fContext, &viewMatrix, NULL, kNone_SkFilterQuality, nullptr,
487 SkSourceGammaTreatment::kRespect));
bsalomonc21b09e2015-08-28 18:46:56 -0700488 GrAlwaysAssert(fp);
489 return fp;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000490}
491
fmenozzi55d318d2016-08-09 08:05:57 -0700492FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor
493 ::GLSLFocalOutside2PtConicalProcessor(const GrProcessor& processor)
halcanary96fcdcc2015-08-27 07:41:13 -0700494 : fVSVaryingName(nullptr)
495 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000496 , fCachedFocal(SK_ScalarMax) {
joshualittb0a8a372014-09-23 09:50:21 -0700497 const FocalOutside2PtConicalEffect& data = processor.cast<FocalOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000498 fIsFlipped = data.isFlipped();
499}
500
fmenozzi55d318d2016-08-09 08:05:57 -0700501void FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -0700502 const FocalOutside2PtConicalEffect& ge = args.fFp.cast<FocalOutside2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -0800503 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
504 this->emitUniforms(uniformHandler, ge);
jvanverthde11ee42016-02-26 13:58:40 -0800505 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
506 kVec2f_GrSLType, kDefault_GrSLPrecision,
507 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000508 SkString tName("t");
509 SkString p0; // focalX
510 SkString p1; // 1 - focalX * focalX
511
jvanverthde11ee42016-02-26 13:58:40 -0800512 p0.appendf("%s.x", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
513 p1.appendf("%s.y", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000514
515 // if we have a vec3 from being in perspective, convert it to a vec2 first
cdalton85285412016-02-18 12:37:07 -0800516 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -0700517 SkString coords2DString = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +0000518 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000519
520 // t = p.x * focal.x +/- sqrt(p.x^2 + (1 - focal.x^2) * p.y^2)
521
522 // output will default to transparent black (we simply won't write anything
523 // else to it if invalid, instead of discarding or returning prematurely)
egdaniel4ca2e602015-11-18 08:01:26 -0800524 fragBuilder->codeAppendf("\t%s = vec4(0.0,0.0,0.0,0.0);\n", args.fOutputColor);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000525
egdaniel4ca2e602015-11-18 08:01:26 -0800526 fragBuilder->codeAppendf("\tfloat xs = %s.x * %s.x;\n", coords2D, coords2D);
527 fragBuilder->codeAppendf("\tfloat ys = %s.y * %s.y;\n", coords2D, coords2D);
528 fragBuilder->codeAppendf("\tfloat d = xs + %s * ys;\n", p1.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000529
530 // Must check to see if we flipped the circle order (to make sure start radius < end radius)
531 // If so we must also flip sign on sqrt
532 if (!fIsFlipped) {
egdaniel4ca2e602015-11-18 08:01:26 -0800533 fragBuilder->codeAppendf("\tfloat %s = %s.x * %s + sqrt(d);\n", tName.c_str(),
534 coords2D, p0.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000535 } else {
egdaniel4ca2e602015-11-18 08:01:26 -0800536 fragBuilder->codeAppendf("\tfloat %s = %s.x * %s - sqrt(d);\n", tName.c_str(),
537 coords2D, p0.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000538 }
539
egdaniel4ca2e602015-11-18 08:01:26 -0800540 fragBuilder->codeAppendf("\tif (%s >= 0.0 && d >= 0.0) {\n", tName.c_str());
541 fragBuilder->codeAppend("\t\t");
egdaniel7ea439b2015-12-03 09:20:44 -0800542 this->emitColor(fragBuilder,
543 uniformHandler,
egdaniela2e3e0f2015-11-19 07:23:45 -0800544 args.fGLSLCaps,
egdaniel4ca2e602015-11-18 08:01:26 -0800545 ge,
546 tName.c_str(),
547 args.fOutputColor,
548 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -0700549 args.fTexSamplers);
egdaniel4ca2e602015-11-18 08:01:26 -0800550 fragBuilder->codeAppend("\t}\n");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000551}
552
fmenozzi55d318d2016-08-09 08:05:57 -0700553void FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::onSetData(
554 const GrGLSLProgramDataManager& pdman,
555 const GrProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -0700556 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -0700557 const FocalOutside2PtConicalEffect& data = processor.cast<FocalOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000558 SkASSERT(data.isFlipped() == fIsFlipped);
559 SkScalar focal = data.focal();
560
561 if (fCachedFocal != focal) {
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000562 SkScalar oneMinus2F = 1.f - SkScalarMul(focal, focal);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000563
jvanverthde11ee42016-02-26 13:58:40 -0800564 pdman.set2f(fParamUni, SkScalarToFloat(focal), SkScalarToFloat(oneMinus2F));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000565 fCachedFocal = focal;
566 }
567}
568
fmenozzi55d318d2016-08-09 08:05:57 -0700569void FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::GenKey(
570 const GrProcessor& processor,
jvanverthcfc18862015-04-28 08:48:20 -0700571 const GrGLSLCaps&, GrProcessorKeyBuilder* b) {
bsalomon63e99f72014-07-21 08:03:14 -0700572 uint32_t* key = b->add32n(2);
joshualittb0a8a372014-09-23 09:50:21 -0700573 key[0] = GenBaseGradientKey(processor);
574 key[1] = processor.cast<FocalOutside2PtConicalEffect>().isFlipped();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000575}
576
577//////////////////////////////////////////////////////////////////////////////
578
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000579class FocalInside2PtConicalEffect : public GrGradientEffect {
580public:
fmenozzi55d318d2016-08-09 08:05:57 -0700581 class GLSLFocalInside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000582
brianosman9557c272016-09-15 06:59:15 -0700583 static sk_sp<GrFragmentProcessor> Make(const CreateArgs& args, SkScalar focalX) {
bungeman06ca8ec2016-06-09 08:01:03 -0700584 return sk_sp<GrFragmentProcessor>(
brianosman9557c272016-09-15 06:59:15 -0700585 new FocalInside2PtConicalEffect(args, focalX));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000586 }
587
588 virtual ~FocalInside2PtConicalEffect() {}
589
mtklein36352bf2015-03-25 18:17:31 -0700590 const char* name() const override {
joshualitteb2a6762014-12-04 11:35:33 -0800591 return "Two-Point Conical Gradient Focal Inside";
592 }
593
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000594 SkScalar focal() const { return fFocalX; }
595
fmenozzi55d318d2016-08-09 08:05:57 -0700596 typedef FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor GLSLProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000597
598private:
egdaniel57d3b032015-11-13 11:57:27 -0800599 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -0700600
egdaniel57d3b032015-11-13 11:57:27 -0800601 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -0700602
mtklein36352bf2015-03-25 18:17:31 -0700603 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -0700604 const FocalInside2PtConicalEffect& s = sBase.cast<FocalInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000605 return (INHERITED::onIsEqual(sBase) &&
606 this->fFocalX == s.fFocalX);
607 }
608
brianosman9557c272016-09-15 06:59:15 -0700609 FocalInside2PtConicalEffect(const CreateArgs& args, SkScalar focalX)
610 : INHERITED(args), fFocalX(focalX) {
joshualitteb2a6762014-12-04 11:35:33 -0800611 this->initClassID<FocalInside2PtConicalEffect>();
612 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000613
joshualittb0a8a372014-09-23 09:50:21 -0700614 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000615
616 SkScalar fFocalX;
617
618 typedef GrGradientEffect INHERITED;
619};
620
fmenozzi55d318d2016-08-09 08:05:57 -0700621class FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor
622 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000623public:
fmenozzi55d318d2016-08-09 08:05:57 -0700624 GLSLFocalInside2PtConicalProcessor(const GrProcessor&);
625 virtual ~GLSLFocalInside2PtConicalProcessor() {}
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000626
wangyix7c157a92015-07-22 15:08:53 -0700627 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000628
jvanverthcfc18862015-04-28 08:48:20 -0700629 static void GenKey(const GrProcessor&, const GrGLSLCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000630
631protected:
egdaniel018fb622015-10-28 07:26:40 -0700632 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -0700633
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000634 UniformHandle fFocalUni;
635
636 const char* fVSVaryingName;
637 const char* fFSVaryingName;
638
639 // @{
640 /// Values last uploaded as uniforms
641
642 SkScalar fCachedFocal;
643
644 // @}
645
646private:
fmenozzi55d318d2016-08-09 08:05:57 -0700647 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000648
649};
650
egdaniel57d3b032015-11-13 11:57:27 -0800651void FocalInside2PtConicalEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
652 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -0700653 FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800654}
655
egdaniel57d3b032015-11-13 11:57:27 -0800656GrGLSLFragmentProcessor* FocalInside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -0700657 return new FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000658}
659
joshualittb0a8a372014-09-23 09:50:21 -0700660GR_DEFINE_FRAGMENT_PROCESSOR_TEST(FocalInside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000661
joshualitt01258472014-09-22 10:29:30 -0700662/*
663 * All Two point conical gradient test create functions may occasionally create edge case shaders
664 */
bungeman06ca8ec2016-06-09 08:01:03 -0700665sk_sp<GrFragmentProcessor> FocalInside2PtConicalEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700666 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000667 SkScalar radius1 = 0.f;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000668 SkPoint center2;
669 SkScalar radius2;
670 do {
joshualitt0067ff52015-07-08 14:26:19 -0700671 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000672 // Below makes sure radius2 is larger enouch such that the focal point
673 // is inside the end circle
joshualitt0067ff52015-07-08 14:26:19 -0700674 SkScalar increase = d->fRandom->nextUScalar1();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000675 SkPoint diff = center2 - center1;
676 SkScalar diffLen = diff.length();
677 radius2 = diffLen + increase;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000678 // If the circles are identical the factory will give us an empty shader.
679 } while (radius1 == radius2 && center1 == center2);
680
681 SkColor colors[kMaxRandomGradientColors];
682 SkScalar stopsArray[kMaxRandomGradientColors];
683 SkScalar* stops = stopsArray;
684 SkShader::TileMode tm;
joshualitt0067ff52015-07-08 14:26:19 -0700685 int colorCount = RandomGradientParams(d->fRandom, colors, &stops, &tm);
reed8a21c9f2016-03-08 18:50:00 -0800686 auto shader = SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
687 colors, stops, colorCount, tm);
brianosman839345d2016-07-22 11:04:53 -0700688 SkMatrix viewMatrix = GrTest::TestMatrix(d->fRandom);
689 sk_sp<GrFragmentProcessor> fp = shader->asFragmentProcessor(SkShader::AsFPArgs(
brianosman1638c0d2016-07-25 05:12:53 -0700690 d->fContext, &viewMatrix, NULL, kNone_SkFilterQuality, nullptr,
691 SkSourceGammaTreatment::kRespect));
bsalomonc21b09e2015-08-28 18:46:56 -0700692 GrAlwaysAssert(fp);
joshualittb0a8a372014-09-23 09:50:21 -0700693 return fp;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000694}
695
fmenozzi55d318d2016-08-09 08:05:57 -0700696FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor
697 ::GLSLFocalInside2PtConicalProcessor(const GrProcessor&)
halcanary96fcdcc2015-08-27 07:41:13 -0700698 : fVSVaryingName(nullptr)
699 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000700 , fCachedFocal(SK_ScalarMax) {}
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000701
fmenozzi55d318d2016-08-09 08:05:57 -0700702void FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -0700703 const FocalInside2PtConicalEffect& ge = args.fFp.cast<FocalInside2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -0800704 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
705 this->emitUniforms(uniformHandler, ge);
cdalton5e58cee2016-02-11 12:49:47 -0800706 fFocalUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800707 kFloat_GrSLType, kDefault_GrSLPrecision,
708 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000709 SkString tName("t");
710
711 // this is the distance along x-axis from the end center to focal point in
712 // transformed coordinates
egdaniel7ea439b2015-12-03 09:20:44 -0800713 GrGLSLShaderVar focal = uniformHandler->getUniformVariable(fFocalUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000714
715 // if we have a vec3 from being in perspective, convert it to a vec2 first
cdalton85285412016-02-18 12:37:07 -0800716 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -0700717 SkString coords2DString = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +0000718 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000719
720 // t = p.x * focalX + length(p)
egdaniel4ca2e602015-11-18 08:01:26 -0800721 fragBuilder->codeAppendf("\tfloat %s = %s.x * %s + length(%s);\n", tName.c_str(),
egdaniel7ea439b2015-12-03 09:20:44 -0800722 coords2D, focal.c_str(), coords2D);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000723
egdaniel7ea439b2015-12-03 09:20:44 -0800724 this->emitColor(fragBuilder,
725 uniformHandler,
egdaniela2e3e0f2015-11-19 07:23:45 -0800726 args.fGLSLCaps,
egdaniel4ca2e602015-11-18 08:01:26 -0800727 ge,
728 tName.c_str(),
729 args.fOutputColor,
730 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -0700731 args.fTexSamplers);
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000732}
733
fmenozzi55d318d2016-08-09 08:05:57 -0700734void FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::onSetData(
735 const GrGLSLProgramDataManager& pdman,
736 const GrProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -0700737 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -0700738 const FocalInside2PtConicalEffect& data = processor.cast<FocalInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000739 SkScalar focal = data.focal();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000740
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000741 if (fCachedFocal != focal) {
kkinnunen7510b222014-07-30 00:04:16 -0700742 pdman.set1f(fFocalUni, SkScalarToFloat(focal));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000743 fCachedFocal = focal;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000744 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000745}
746
fmenozzi55d318d2016-08-09 08:05:57 -0700747void FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::GenKey(
748 const GrProcessor& processor,
749 const GrGLSLCaps&, GrProcessorKeyBuilder* b) {
joshualittb0a8a372014-09-23 09:50:21 -0700750 b->add32(GenBaseGradientKey(processor));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000751}
752
753//////////////////////////////////////////////////////////////////////////////
754// Circle Conical Gradients
755//////////////////////////////////////////////////////////////////////////////
756
757struct CircleConicalInfo {
758 SkPoint fCenterEnd;
759 SkScalar fA;
760 SkScalar fB;
761 SkScalar fC;
762};
763
764// Returns focal distance along x-axis in transformed coords
765static ConicalType set_matrix_circle_conical(const SkTwoPointConicalGradient& shader,
766 SkMatrix* invLMatrix, CircleConicalInfo* info) {
767 // Inverse of the current local matrix is passed in then,
768 // translate and scale such that start circle is on the origin and has radius 1
769 const SkPoint& centerStart = shader.getStartCenter();
770 const SkPoint& centerEnd = shader.getEndCenter();
771 SkScalar radiusStart = shader.getStartRadius();
772 SkScalar radiusEnd = shader.getEndRadius();
773
774 SkMatrix matrix;
775
776 matrix.setTranslate(-centerStart.fX, -centerStart.fY);
777
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000778 SkScalar invStartRad = 1.f / radiusStart;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000779 matrix.postScale(invStartRad, invStartRad);
780
781 radiusEnd /= radiusStart;
782
783 SkPoint centerEndTrans;
784 matrix.mapPoints(&centerEndTrans, &centerEnd, 1);
785
786 SkScalar A = centerEndTrans.fX * centerEndTrans.fX + centerEndTrans.fY * centerEndTrans.fY
787 - radiusEnd * radiusEnd + 2 * radiusEnd - 1;
788
789 // Check to see if start circle is inside end circle with edges touching.
790 // If touching we return that it is of kEdge_ConicalType, and leave the matrix setting
egdaniel8405ef92014-06-09 11:57:28 -0700791 // to the edge shader. kEdgeErrorTol = 5 * kErrorTol was picked after manual testing
792 // so that C = 1 / A is stable, and the linear approximation used in the Edge shader is
793 // still accurate.
794 if (SkScalarAbs(A) < kEdgeErrorTol) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000795 return kEdge_ConicalType;
796 }
797
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000798 SkScalar C = 1.f / A;
799 SkScalar B = (radiusEnd - 1.f) * C;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000800
801 matrix.postScale(C, C);
802
803 invLMatrix->postConcat(matrix);
804
805 info->fCenterEnd = centerEndTrans;
806 info->fA = A;
807 info->fB = B;
808 info->fC = C;
809
810 // if A ends up being negative, the start circle is contained completely inside the end cirlce
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000811 if (A < 0.f) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000812 return kInside_ConicalType;
813 }
814 return kOutside_ConicalType;
815}
816
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000817class CircleInside2PtConicalEffect : public GrGradientEffect {
818public:
fmenozzi55d318d2016-08-09 08:05:57 -0700819 class GLSLCircleInside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000820
brianosman9557c272016-09-15 06:59:15 -0700821 static sk_sp<GrFragmentProcessor> Make(const CreateArgs& args, const CircleConicalInfo& info) {
bungeman06ca8ec2016-06-09 08:01:03 -0700822 return sk_sp<GrFragmentProcessor>(
brianosman9557c272016-09-15 06:59:15 -0700823 new CircleInside2PtConicalEffect(args, info));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000824 }
825
826 virtual ~CircleInside2PtConicalEffect() {}
827
mtklein36352bf2015-03-25 18:17:31 -0700828 const char* name() const override { return "Two-Point Conical Gradient Inside"; }
joshualitteb2a6762014-12-04 11:35:33 -0800829
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000830 SkScalar centerX() const { return fInfo.fCenterEnd.fX; }
831 SkScalar centerY() const { return fInfo.fCenterEnd.fY; }
832 SkScalar A() const { return fInfo.fA; }
833 SkScalar B() const { return fInfo.fB; }
834 SkScalar C() const { return fInfo.fC; }
835
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000836private:
egdaniel57d3b032015-11-13 11:57:27 -0800837 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -0700838
egdaniel57d3b032015-11-13 11:57:27 -0800839 virtual void onGetGLSLProcessorKey(const GrGLSLCaps& caps,
840 GrProcessorKeyBuilder* b) const override;
wangyix4b3050b2015-08-04 07:59:37 -0700841
mtklein36352bf2015-03-25 18:17:31 -0700842 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -0700843 const CircleInside2PtConicalEffect& s = sBase.cast<CircleInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000844 return (INHERITED::onIsEqual(sBase) &&
845 this->fInfo.fCenterEnd == s.fInfo.fCenterEnd &&
846 this->fInfo.fA == s.fInfo.fA &&
847 this->fInfo.fB == s.fInfo.fB &&
848 this->fInfo.fC == s.fInfo.fC);
849 }
850
brianosman9557c272016-09-15 06:59:15 -0700851 CircleInside2PtConicalEffect(const CreateArgs& args, const CircleConicalInfo& info)
852 : INHERITED(args), fInfo(info) {
joshualitteb2a6762014-12-04 11:35:33 -0800853 this->initClassID<CircleInside2PtConicalEffect>();
854 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000855
joshualittb0a8a372014-09-23 09:50:21 -0700856 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000857
858 const CircleConicalInfo fInfo;
859
860 typedef GrGradientEffect INHERITED;
861};
862
fmenozzi55d318d2016-08-09 08:05:57 -0700863class CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor
864 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000865public:
fmenozzi55d318d2016-08-09 08:05:57 -0700866 GLSLCircleInside2PtConicalProcessor(const GrProcessor&);
867 virtual ~GLSLCircleInside2PtConicalProcessor() {}
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000868
wangyix7c157a92015-07-22 15:08:53 -0700869 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000870
jvanverthcfc18862015-04-28 08:48:20 -0700871 static void GenKey(const GrProcessor&, const GrGLSLCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000872
873protected:
egdaniel018fb622015-10-28 07:26:40 -0700874 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -0700875
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000876 UniformHandle fCenterUni;
877 UniformHandle fParamUni;
878
879 const char* fVSVaryingName;
880 const char* fFSVaryingName;
881
882 // @{
883 /// Values last uploaded as uniforms
884
885 SkScalar fCachedCenterX;
886 SkScalar fCachedCenterY;
887 SkScalar fCachedA;
888 SkScalar fCachedB;
889 SkScalar fCachedC;
890
891 // @}
892
893private:
fmenozzi55d318d2016-08-09 08:05:57 -0700894 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000895
896};
897
egdaniel57d3b032015-11-13 11:57:27 -0800898void CircleInside2PtConicalEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
899 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -0700900 CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800901}
902
egdaniel57d3b032015-11-13 11:57:27 -0800903GrGLSLFragmentProcessor* CircleInside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -0700904 return new CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000905}
906
joshualittb0a8a372014-09-23 09:50:21 -0700907GR_DEFINE_FRAGMENT_PROCESSOR_TEST(CircleInside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000908
joshualitt01258472014-09-22 10:29:30 -0700909/*
910 * All Two point conical gradient test create functions may occasionally create edge case shaders
911 */
bungeman06ca8ec2016-06-09 08:01:03 -0700912sk_sp<GrFragmentProcessor> CircleInside2PtConicalEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700913 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
914 SkScalar radius1 = d->fRandom->nextUScalar1() + 0.0001f; // make sure radius1 != 0
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000915 SkPoint center2;
916 SkScalar radius2;
917 do {
joshualitt0067ff52015-07-08 14:26:19 -0700918 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000919 // Below makes sure that circle one is contained within circle two
joshualitt0067ff52015-07-08 14:26:19 -0700920 SkScalar increase = d->fRandom->nextUScalar1();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000921 SkPoint diff = center2 - center1;
922 SkScalar diffLen = diff.length();
923 radius2 = radius1 + diffLen + increase;
924 // If the circles are identical the factory will give us an empty shader.
925 } while (radius1 == radius2 && center1 == center2);
926
927 SkColor colors[kMaxRandomGradientColors];
928 SkScalar stopsArray[kMaxRandomGradientColors];
929 SkScalar* stops = stopsArray;
930 SkShader::TileMode tm;
joshualitt0067ff52015-07-08 14:26:19 -0700931 int colorCount = RandomGradientParams(d->fRandom, colors, &stops, &tm);
reed8a21c9f2016-03-08 18:50:00 -0800932 auto shader = SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
933 colors, stops, colorCount, tm);
brianosman839345d2016-07-22 11:04:53 -0700934 SkMatrix viewMatrix = GrTest::TestMatrix(d->fRandom);
935 sk_sp<GrFragmentProcessor> fp = shader->asFragmentProcessor(SkShader::AsFPArgs(
brianosman1638c0d2016-07-25 05:12:53 -0700936 d->fContext, &viewMatrix, NULL, kNone_SkFilterQuality, nullptr,
937 SkSourceGammaTreatment::kRespect));
bsalomonc21b09e2015-08-28 18:46:56 -0700938 GrAlwaysAssert(fp);
joshualitt8ca93e72015-07-08 06:51:43 -0700939 return fp;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000940}
941
fmenozzi55d318d2016-08-09 08:05:57 -0700942CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor
943 ::GLSLCircleInside2PtConicalProcessor(const GrProcessor& processor)
halcanary96fcdcc2015-08-27 07:41:13 -0700944 : fVSVaryingName(nullptr)
945 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000946 , fCachedCenterX(SK_ScalarMax)
947 , fCachedCenterY(SK_ScalarMax)
948 , fCachedA(SK_ScalarMax)
949 , fCachedB(SK_ScalarMax)
950 , fCachedC(SK_ScalarMax) {}
951
fmenozzi55d318d2016-08-09 08:05:57 -0700952void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -0700953 const CircleInside2PtConicalEffect& ge = args.fFp.cast<CircleInside2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -0800954 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
955 this->emitUniforms(uniformHandler, ge);
cdalton5e58cee2016-02-11 12:49:47 -0800956 fCenterUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800957 kVec2f_GrSLType, kDefault_GrSLPrecision,
958 "Conical2FSCenter");
cdalton5e58cee2016-02-11 12:49:47 -0800959 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800960 kVec3f_GrSLType, kDefault_GrSLPrecision,
961 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000962 SkString tName("t");
963
egdaniel7ea439b2015-12-03 09:20:44 -0800964 GrGLSLShaderVar center = uniformHandler->getUniformVariable(fCenterUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000965 // params.x = A
966 // params.y = B
967 // params.z = C
egdaniel7ea439b2015-12-03 09:20:44 -0800968 GrGLSLShaderVar params = uniformHandler->getUniformVariable(fParamUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000969
970 // if we have a vec3 from being in perspective, convert it to a vec2 first
cdalton85285412016-02-18 12:37:07 -0800971 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -0700972 SkString coords2DString = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +0000973 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000974
975 // p = coords2D
976 // e = center end
977 // r = radius end
978 // A = dot(e, e) - r^2 + 2 * r - 1
979 // B = (r -1) / A
980 // C = 1 / A
981 // d = dot(e, p) + B
982 // t = d +/- sqrt(d^2 - A * dot(p, p) + C)
egdaniel4ca2e602015-11-18 08:01:26 -0800983 fragBuilder->codeAppendf("\tfloat pDotp = dot(%s, %s);\n", coords2D, coords2D);
984 fragBuilder->codeAppendf("\tfloat d = dot(%s, %s) + %s.y;\n", coords2D, center.c_str(),
985 params.c_str());
986 fragBuilder->codeAppendf("\tfloat %s = d + sqrt(d * d - %s.x * pDotp + %s.z);\n",
987 tName.c_str(), params.c_str(), params.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000988
egdaniel7ea439b2015-12-03 09:20:44 -0800989 this->emitColor(fragBuilder,
990 uniformHandler,
egdaniela2e3e0f2015-11-19 07:23:45 -0800991 args.fGLSLCaps,
egdaniel4ca2e602015-11-18 08:01:26 -0800992 ge,
993 tName.c_str(),
994 args.fOutputColor,
995 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -0700996 args.fTexSamplers);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000997}
998
fmenozzi55d318d2016-08-09 08:05:57 -0700999void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::onSetData(
1000 const GrGLSLProgramDataManager& pdman,
1001 const GrProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -07001002 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -07001003 const CircleInside2PtConicalEffect& data = processor.cast<CircleInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001004 SkScalar centerX = data.centerX();
1005 SkScalar centerY = data.centerY();
1006 SkScalar A = data.A();
1007 SkScalar B = data.B();
1008 SkScalar C = data.C();
1009
1010 if (fCachedCenterX != centerX || fCachedCenterY != centerY ||
1011 fCachedA != A || fCachedB != B || fCachedC != C) {
1012
kkinnunen7510b222014-07-30 00:04:16 -07001013 pdman.set2f(fCenterUni, SkScalarToFloat(centerX), SkScalarToFloat(centerY));
1014 pdman.set3f(fParamUni, SkScalarToFloat(A), SkScalarToFloat(B), SkScalarToFloat(C));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001015
1016 fCachedCenterX = centerX;
1017 fCachedCenterY = centerY;
1018 fCachedA = A;
1019 fCachedB = B;
1020 fCachedC = C;
1021 }
1022}
1023
fmenozzi55d318d2016-08-09 08:05:57 -07001024void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::GenKey(
1025 const GrProcessor& processor,
jvanverthcfc18862015-04-28 08:48:20 -07001026 const GrGLSLCaps&, GrProcessorKeyBuilder* b) {
joshualittb0a8a372014-09-23 09:50:21 -07001027 b->add32(GenBaseGradientKey(processor));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001028}
1029
1030//////////////////////////////////////////////////////////////////////////////
1031
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001032class CircleOutside2PtConicalEffect : public GrGradientEffect {
1033public:
fmenozzi55d318d2016-08-09 08:05:57 -07001034 class GLSLCircleOutside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001035
brianosman9557c272016-09-15 06:59:15 -07001036 static sk_sp<GrFragmentProcessor> Make(const CreateArgs& args, const CircleConicalInfo& info) {
bungeman06ca8ec2016-06-09 08:01:03 -07001037 return sk_sp<GrFragmentProcessor>(
brianosman9557c272016-09-15 06:59:15 -07001038 new CircleOutside2PtConicalEffect(args, info));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001039 }
1040
1041 virtual ~CircleOutside2PtConicalEffect() {}
1042
mtklein36352bf2015-03-25 18:17:31 -07001043 const char* name() const override { return "Two-Point Conical Gradient Outside"; }
joshualitteb2a6762014-12-04 11:35:33 -08001044
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001045 SkScalar centerX() const { return fInfo.fCenterEnd.fX; }
1046 SkScalar centerY() const { return fInfo.fCenterEnd.fY; }
1047 SkScalar A() const { return fInfo.fA; }
1048 SkScalar B() const { return fInfo.fB; }
1049 SkScalar C() const { return fInfo.fC; }
1050 SkScalar tLimit() const { return fTLimit; }
1051 bool isFlipped() const { return fIsFlipped; }
1052
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001053private:
egdaniel57d3b032015-11-13 11:57:27 -08001054 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -07001055
egdaniel57d3b032015-11-13 11:57:27 -08001056 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -07001057
mtklein36352bf2015-03-25 18:17:31 -07001058 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -07001059 const CircleOutside2PtConicalEffect& s = sBase.cast<CircleOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001060 return (INHERITED::onIsEqual(sBase) &&
1061 this->fInfo.fCenterEnd == s.fInfo.fCenterEnd &&
1062 this->fInfo.fA == s.fInfo.fA &&
1063 this->fInfo.fB == s.fInfo.fB &&
1064 this->fInfo.fC == s.fInfo.fC &&
1065 this->fTLimit == s.fTLimit &&
1066 this->fIsFlipped == s.fIsFlipped);
1067 }
1068
brianosman9557c272016-09-15 06:59:15 -07001069 CircleOutside2PtConicalEffect(const CreateArgs& args, const CircleConicalInfo& info)
1070 : INHERITED(args), fInfo(info) {
joshualitteb2a6762014-12-04 11:35:33 -08001071 this->initClassID<CircleOutside2PtConicalEffect>();
brianosman9557c272016-09-15 06:59:15 -07001072 const SkTwoPointConicalGradient& shader =
1073 *static_cast<const SkTwoPointConicalGradient*>(args.fShader);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001074 if (shader.getStartRadius() != shader.getEndRadius()) {
reed80ea19c2015-05-12 10:37:34 -07001075 fTLimit = shader.getStartRadius() / (shader.getStartRadius() - shader.getEndRadius());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001076 } else {
1077 fTLimit = SK_ScalarMin;
1078 }
1079
1080 fIsFlipped = shader.isFlippedGrad();
1081 }
1082
joshualittb0a8a372014-09-23 09:50:21 -07001083 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001084
1085 const CircleConicalInfo fInfo;
1086 SkScalar fTLimit;
1087 bool fIsFlipped;
1088
1089 typedef GrGradientEffect INHERITED;
1090};
1091
fmenozzi55d318d2016-08-09 08:05:57 -07001092class CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor
1093 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001094public:
fmenozzi55d318d2016-08-09 08:05:57 -07001095 GLSLCircleOutside2PtConicalProcessor(const GrProcessor&);
1096 virtual ~GLSLCircleOutside2PtConicalProcessor() {}
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001097
wangyix7c157a92015-07-22 15:08:53 -07001098 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001099
jvanverthcfc18862015-04-28 08:48:20 -07001100 static void GenKey(const GrProcessor&, const GrGLSLCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001101
1102protected:
egdaniel018fb622015-10-28 07:26:40 -07001103 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -07001104
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001105 UniformHandle fCenterUni;
1106 UniformHandle fParamUni;
1107
1108 const char* fVSVaryingName;
1109 const char* fFSVaryingName;
1110
1111 bool fIsFlipped;
1112
1113 // @{
1114 /// Values last uploaded as uniforms
1115
1116 SkScalar fCachedCenterX;
1117 SkScalar fCachedCenterY;
1118 SkScalar fCachedA;
1119 SkScalar fCachedB;
1120 SkScalar fCachedC;
1121 SkScalar fCachedTLimit;
1122
1123 // @}
1124
1125private:
fmenozzi55d318d2016-08-09 08:05:57 -07001126 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001127
1128};
1129
egdaniel57d3b032015-11-13 11:57:27 -08001130void CircleOutside2PtConicalEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
1131 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -07001132 CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -08001133}
1134
egdaniel57d3b032015-11-13 11:57:27 -08001135GrGLSLFragmentProcessor* CircleOutside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -07001136 return new CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001137}
1138
joshualittb0a8a372014-09-23 09:50:21 -07001139GR_DEFINE_FRAGMENT_PROCESSOR_TEST(CircleOutside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001140
joshualitt01258472014-09-22 10:29:30 -07001141/*
1142 * All Two point conical gradient test create functions may occasionally create edge case shaders
1143 */
bungeman06ca8ec2016-06-09 08:01:03 -07001144sk_sp<GrFragmentProcessor> CircleOutside2PtConicalEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -07001145 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
1146 SkScalar radius1 = d->fRandom->nextUScalar1() + 0.0001f; // make sure radius1 != 0
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001147 SkPoint center2;
1148 SkScalar radius2;
1149 SkScalar diffLen;
1150 do {
joshualitt0067ff52015-07-08 14:26:19 -07001151 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001152 // If the circles share a center than we can't be in the outside case
1153 } while (center1 == center2);
joshualitt01258472014-09-22 10:29:30 -07001154 SkPoint diff = center2 - center1;
1155 diffLen = diff.length();
1156 // Below makes sure that circle one is not contained within circle two
1157 // and have radius2 >= radius to match sorting on cpu side
joshualitt0067ff52015-07-08 14:26:19 -07001158 radius2 = radius1 + d->fRandom->nextRangeF(0.f, diffLen);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001159
1160 SkColor colors[kMaxRandomGradientColors];
1161 SkScalar stopsArray[kMaxRandomGradientColors];
1162 SkScalar* stops = stopsArray;
1163 SkShader::TileMode tm;
joshualitt0067ff52015-07-08 14:26:19 -07001164 int colorCount = RandomGradientParams(d->fRandom, colors, &stops, &tm);
reed8a21c9f2016-03-08 18:50:00 -08001165 auto shader = SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
1166 colors, stops, colorCount, tm);
brianosman839345d2016-07-22 11:04:53 -07001167 SkMatrix viewMatrix = GrTest::TestMatrix(d->fRandom);
1168 sk_sp<GrFragmentProcessor> fp = shader->asFragmentProcessor(SkShader::AsFPArgs(
brianosman1638c0d2016-07-25 05:12:53 -07001169 d->fContext, &viewMatrix, NULL, kNone_SkFilterQuality, nullptr,
1170 SkSourceGammaTreatment::kRespect));
bsalomonc21b09e2015-08-28 18:46:56 -07001171 GrAlwaysAssert(fp);
joshualitt8ca93e72015-07-08 06:51:43 -07001172 return fp;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001173}
1174
fmenozzi55d318d2016-08-09 08:05:57 -07001175CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor
1176 ::GLSLCircleOutside2PtConicalProcessor(const GrProcessor& processor)
halcanary96fcdcc2015-08-27 07:41:13 -07001177 : fVSVaryingName(nullptr)
1178 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001179 , fCachedCenterX(SK_ScalarMax)
1180 , fCachedCenterY(SK_ScalarMax)
1181 , fCachedA(SK_ScalarMax)
1182 , fCachedB(SK_ScalarMax)
1183 , fCachedC(SK_ScalarMax)
1184 , fCachedTLimit(SK_ScalarMax) {
joshualittb0a8a372014-09-23 09:50:21 -07001185 const CircleOutside2PtConicalEffect& data = processor.cast<CircleOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001186 fIsFlipped = data.isFlipped();
1187 }
1188
fmenozzi55d318d2016-08-09 08:05:57 -07001189void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -07001190 const CircleOutside2PtConicalEffect& ge = args.fFp.cast<CircleOutside2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -08001191 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
1192 this->emitUniforms(uniformHandler, ge);
cdalton5e58cee2016-02-11 12:49:47 -08001193 fCenterUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001194 kVec2f_GrSLType, kDefault_GrSLPrecision,
1195 "Conical2FSCenter");
cdalton5e58cee2016-02-11 12:49:47 -08001196 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001197 kVec4f_GrSLType, kDefault_GrSLPrecision,
1198 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001199 SkString tName("t");
1200
egdaniel7ea439b2015-12-03 09:20:44 -08001201 GrGLSLShaderVar center = uniformHandler->getUniformVariable(fCenterUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001202 // params.x = A
1203 // params.y = B
1204 // params.z = C
egdaniel7ea439b2015-12-03 09:20:44 -08001205 GrGLSLShaderVar params = uniformHandler->getUniformVariable(fParamUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001206
1207 // if we have a vec3 from being in perspective, convert it to a vec2 first
cdalton85285412016-02-18 12:37:07 -08001208 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -07001209 SkString coords2DString = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +00001210 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001211
1212 // output will default to transparent black (we simply won't write anything
1213 // else to it if invalid, instead of discarding or returning prematurely)
egdaniel4ca2e602015-11-18 08:01:26 -08001214 fragBuilder->codeAppendf("\t%s = vec4(0.0,0.0,0.0,0.0);\n", args.fOutputColor);
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001215
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001216 // p = coords2D
1217 // e = center end
1218 // r = radius end
1219 // A = dot(e, e) - r^2 + 2 * r - 1
1220 // B = (r -1) / A
1221 // C = 1 / A
1222 // d = dot(e, p) + B
1223 // t = d +/- sqrt(d^2 - A * dot(p, p) + C)
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001224
egdaniel4ca2e602015-11-18 08:01:26 -08001225 fragBuilder->codeAppendf("\tfloat pDotp = dot(%s, %s);\n", coords2D, coords2D);
1226 fragBuilder->codeAppendf("\tfloat d = dot(%s, %s) + %s.y;\n", coords2D, center.c_str(),
1227 params.c_str());
1228 fragBuilder->codeAppendf("\tfloat deter = d * d - %s.x * pDotp + %s.z;\n", params.c_str(),
1229 params.c_str());
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001230
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001231 // Must check to see if we flipped the circle order (to make sure start radius < end radius)
1232 // If so we must also flip sign on sqrt
1233 if (!fIsFlipped) {
egdaniel4ca2e602015-11-18 08:01:26 -08001234 fragBuilder->codeAppendf("\tfloat %s = d + sqrt(deter);\n", tName.c_str());
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001235 } else {
egdaniel4ca2e602015-11-18 08:01:26 -08001236 fragBuilder->codeAppendf("\tfloat %s = d - sqrt(deter);\n", tName.c_str());
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001237 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001238
egdaniel7ea439b2015-12-03 09:20:44 -08001239 fragBuilder->codeAppendf("\tif (%s >= %s.w && deter >= 0.0) {\n",
1240 tName.c_str(), params.c_str());
egdaniel4ca2e602015-11-18 08:01:26 -08001241 fragBuilder->codeAppend("\t\t");
egdaniel7ea439b2015-12-03 09:20:44 -08001242 this->emitColor(fragBuilder,
1243 uniformHandler,
egdaniela2e3e0f2015-11-19 07:23:45 -08001244 args.fGLSLCaps,
egdaniel4ca2e602015-11-18 08:01:26 -08001245 ge,
1246 tName.c_str(),
1247 args.fOutputColor,
1248 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -07001249 args.fTexSamplers);
egdaniel4ca2e602015-11-18 08:01:26 -08001250 fragBuilder->codeAppend("\t}\n");
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001251}
1252
fmenozzi55d318d2016-08-09 08:05:57 -07001253void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::onSetData(
1254 const GrGLSLProgramDataManager& pdman,
egdaniel018fb622015-10-28 07:26:40 -07001255 const GrProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -07001256 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -07001257 const CircleOutside2PtConicalEffect& data = processor.cast<CircleOutside2PtConicalEffect>();
commit-bot@chromium.org44d83c12014-04-21 13:10:25 +00001258 SkASSERT(data.isFlipped() == fIsFlipped);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001259 SkScalar centerX = data.centerX();
1260 SkScalar centerY = data.centerY();
1261 SkScalar A = data.A();
1262 SkScalar B = data.B();
1263 SkScalar C = data.C();
1264 SkScalar tLimit = data.tLimit();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001265
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001266 if (fCachedCenterX != centerX || fCachedCenterY != centerY ||
1267 fCachedA != A || fCachedB != B || fCachedC != C || fCachedTLimit != tLimit) {
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001268
kkinnunen7510b222014-07-30 00:04:16 -07001269 pdman.set2f(fCenterUni, SkScalarToFloat(centerX), SkScalarToFloat(centerY));
1270 pdman.set4f(fParamUni, SkScalarToFloat(A), SkScalarToFloat(B), SkScalarToFloat(C),
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001271 SkScalarToFloat(tLimit));
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001272
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001273 fCachedCenterX = centerX;
1274 fCachedCenterY = centerY;
1275 fCachedA = A;
1276 fCachedB = B;
1277 fCachedC = C;
1278 fCachedTLimit = tLimit;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001279 }
1280}
1281
fmenozzi55d318d2016-08-09 08:05:57 -07001282void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::GenKey(
1283 const GrProcessor& processor,
1284 const GrGLSLCaps&, GrProcessorKeyBuilder* b) {
bsalomon63e99f72014-07-21 08:03:14 -07001285 uint32_t* key = b->add32n(2);
joshualittb0a8a372014-09-23 09:50:21 -07001286 key[0] = GenBaseGradientKey(processor);
1287 key[1] = processor.cast<CircleOutside2PtConicalEffect>().isFlipped();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001288}
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001289
1290//////////////////////////////////////////////////////////////////////////////
1291
brianosman9557c272016-09-15 06:59:15 -07001292sk_sp<GrFragmentProcessor> Gr2PtConicalGradientEffect::Make(
1293 const GrGradientEffect::CreateArgs& args) {
1294 const SkTwoPointConicalGradient& shader =
1295 *static_cast<const SkTwoPointConicalGradient*>(args.fShader);
1296
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001297 SkMatrix matrix;
1298 if (!shader.getLocalMatrix().invert(&matrix)) {
halcanary96fcdcc2015-08-27 07:41:13 -07001299 return nullptr;
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001300 }
brianosman9557c272016-09-15 06:59:15 -07001301 if (args.fMatrix) {
commit-bot@chromium.org96fb7482014-05-09 20:28:11 +00001302 SkMatrix inv;
brianosman9557c272016-09-15 06:59:15 -07001303 if (!args.fMatrix->invert(&inv)) {
halcanary96fcdcc2015-08-27 07:41:13 -07001304 return nullptr;
commit-bot@chromium.org96fb7482014-05-09 20:28:11 +00001305 }
1306 matrix.postConcat(inv);
1307 }
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001308
brianosmanb9c51372016-09-15 11:09:45 -07001309 GrGradientEffect::CreateArgs newArgs(args.fContext, args.fShader, &matrix, args.fTileMode,
1310 std::move(args.fColorSpaceXform), args.fGammaCorrect);
brianosman9557c272016-09-15 06:59:15 -07001311
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001312 if (shader.getStartRadius() < kErrorTol) {
1313 SkScalar focalX;
1314 ConicalType type = set_matrix_focal_conical(shader, &matrix, &focalX);
1315 if (type == kInside_ConicalType) {
brianosman9557c272016-09-15 06:59:15 -07001316 return FocalInside2PtConicalEffect::Make(newArgs, focalX);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001317 } else if(type == kEdge_ConicalType) {
1318 set_matrix_edge_conical(shader, &matrix);
brianosman9557c272016-09-15 06:59:15 -07001319 return Edge2PtConicalEffect::Make(newArgs);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001320 } else {
brianosman9557c272016-09-15 06:59:15 -07001321 return FocalOutside2PtConicalEffect::Make(newArgs, focalX);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001322 }
1323 }
1324
1325 CircleConicalInfo info;
1326 ConicalType type = set_matrix_circle_conical(shader, &matrix, &info);
1327
1328 if (type == kInside_ConicalType) {
brianosman9557c272016-09-15 06:59:15 -07001329 return CircleInside2PtConicalEffect::Make(newArgs, info);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001330 } else if (type == kEdge_ConicalType) {
1331 set_matrix_edge_conical(shader, &matrix);
brianosman9557c272016-09-15 06:59:15 -07001332 return Edge2PtConicalEffect::Make(newArgs);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001333 } else {
brianosman9557c272016-09-15 06:59:15 -07001334 return CircleOutside2PtConicalEffect::Make(newArgs, info);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001335 }
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001336}
1337
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001338#endif