blob: 3e9ee25c6ebd8bf6190875b596aba7c20692e277 [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
Brian Salomon94efbf52016-11-29 13:43:05 -050084 void onGetGLSLProcessorKey(const GrShaderCaps&, 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
Brian Salomon94efbf52016-11-29 13:43:05 -0500148 static void GenKey(const GrProcessor&, const GrShaderCaps& 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
Brian Salomon94efbf52016-11-29 13:43:05 -0500171void Edge2PtConicalEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800172 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
Brian Osman3f748602016-10-03 18:29:03 -0400202 RandomGradientParams params(d->fRandom);
Brian Osmana2196532016-10-17 12:48:13 -0400203 auto shader = params.fUseColors4f ?
204 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
205 params.fColors4f, params.fColorSpace, params.fStops,
206 params.fColorCount, params.fTileMode) :
207 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
208 params.fColors, params.fStops,
209 params.fColorCount, params.fTileMode);
Brian Osman9f532a32016-10-19 11:12:09 -0400210 GrTest::TestAsFPArgs asFPArgs(d);
211 sk_sp<GrFragmentProcessor> fp = shader->asFragmentProcessor(asFPArgs.args());
bsalomonc21b09e2015-08-28 18:46:56 -0700212 GrAlwaysAssert(fp);
joshualittb0a8a372014-09-23 09:50:21 -0700213 return fp;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000214}
215
fmenozzi55d318d2016-08-09 08:05:57 -0700216Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::GLSLEdge2PtConicalProcessor(const GrProcessor&)
halcanary96fcdcc2015-08-27 07:41:13 -0700217 : fVSVaryingName(nullptr)
218 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000219 , fCachedRadius(-SK_ScalarMax)
220 , fCachedDiffRadius(-SK_ScalarMax) {}
221
fmenozzi55d318d2016-08-09 08:05:57 -0700222void Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -0700223 const Edge2PtConicalEffect& ge = args.fFp.cast<Edge2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -0800224 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
225 this->emitUniforms(uniformHandler, ge);
jvanverthde11ee42016-02-26 13:58:40 -0800226 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
227 kVec3f_GrSLType, kDefault_GrSLPrecision,
228 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000229
230 SkString cName("c");
231 SkString tName("t");
232 SkString p0; // start radius
233 SkString p1; // start radius squared
234 SkString p2; // difference in radii (r1 - r0)
235
jvanverthde11ee42016-02-26 13:58:40 -0800236
237 p0.appendf("%s.x", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
238 p1.appendf("%s.y", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
239 p2.appendf("%s.z", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000240
241 // We interpolate the linear component in coords[1].
bsalomon1a1aa932016-09-12 09:30:36 -0700242 SkASSERT(args.fTransformedCoords[0].getType() == args.fTransformedCoords[1].getType());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000243 const char* coords2D;
244 SkString bVar;
cdalton85285412016-02-18 12:37:07 -0800245 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -0700246 if (kVec3f_GrSLType == args.fTransformedCoords[0].getType()) {
egdaniel4ca2e602015-11-18 08:01:26 -0800247 fragBuilder->codeAppendf("\tvec3 interpolants = vec3(%s.xy / %s.z, %s.x / %s.z);\n",
bsalomon1a1aa932016-09-12 09:30:36 -0700248 args.fTransformedCoords[0].c_str(),
249 args.fTransformedCoords[0].c_str(),
250 args.fTransformedCoords[1].c_str(),
251 args.fTransformedCoords[1].c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000252 coords2D = "interpolants.xy";
253 bVar = "interpolants.z";
254 } else {
bsalomon1a1aa932016-09-12 09:30:36 -0700255 coords2D = args.fTransformedCoords[0].c_str();
256 bVar.printf("%s.x", args.fTransformedCoords[1].c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000257 }
258
259 // output will default to transparent black (we simply won't write anything
260 // else to it if invalid, instead of discarding or returning prematurely)
egdaniel4ca2e602015-11-18 08:01:26 -0800261 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 +0000262
263 // c = (x^2)+(y^2) - params[1]
egdaniel4ca2e602015-11-18 08:01:26 -0800264 fragBuilder->codeAppendf("\tfloat %s = dot(%s, %s) - %s;\n",
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000265 cName.c_str(), coords2D, coords2D, p1.c_str());
266
267 // linear case: t = -c/b
egdaniel4ca2e602015-11-18 08:01:26 -0800268 fragBuilder->codeAppendf("\tfloat %s = -(%s / %s);\n", tName.c_str(),
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000269 cName.c_str(), bVar.c_str());
270
271 // if r(t) > 0, then t will be the x coordinate
egdaniel4ca2e602015-11-18 08:01:26 -0800272 fragBuilder->codeAppendf("\tif (%s * %s + %s > 0.0) {\n", tName.c_str(),
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000273 p2.c_str(), p0.c_str());
egdaniel4ca2e602015-11-18 08:01:26 -0800274 fragBuilder->codeAppend("\t");
egdaniel7ea439b2015-12-03 09:20:44 -0800275 this->emitColor(fragBuilder,
276 uniformHandler,
egdaniela2e3e0f2015-11-19 07:23:45 -0800277 args.fGLSLCaps,
egdaniel4ca2e602015-11-18 08:01:26 -0800278 ge,
279 tName.c_str(),
280 args.fOutputColor,
281 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -0700282 args.fTexSamplers);
egdaniel4ca2e602015-11-18 08:01:26 -0800283 fragBuilder->codeAppend("\t}\n");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000284}
285
fmenozzi55d318d2016-08-09 08:05:57 -0700286void Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::onSetData(
287 const GrGLSLProgramDataManager& pdman,
288 const GrProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -0700289 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -0700290 const Edge2PtConicalEffect& data = processor.cast<Edge2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000291 SkScalar radius0 = data.radius();
292 SkScalar diffRadius = data.diffRadius();
293
294 if (fCachedRadius != radius0 ||
295 fCachedDiffRadius != diffRadius) {
296
halcanary9d524f22016-03-29 09:03:52 -0700297 pdman.set3f(fParamUni, SkScalarToFloat(radius0),
jvanverthde11ee42016-02-26 13:58:40 -0800298 SkScalarToFloat(SkScalarMul(radius0, radius0)), SkScalarToFloat(diffRadius));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000299 fCachedRadius = radius0;
300 fCachedDiffRadius = diffRadius;
301 }
302}
303
fmenozzi55d318d2016-08-09 08:05:57 -0700304void Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::GenKey(const GrProcessor& processor,
Brian Salomon94efbf52016-11-29 13:43:05 -0500305 const GrShaderCaps&, GrProcessorKeyBuilder* b) {
joshualittb0a8a372014-09-23 09:50:21 -0700306 b->add32(GenBaseGradientKey(processor));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000307}
308
309//////////////////////////////////////////////////////////////////////////////
310// Focal Conical Gradients
311//////////////////////////////////////////////////////////////////////////////
312
313static ConicalType set_matrix_focal_conical(const SkTwoPointConicalGradient& shader,
314 SkMatrix* invLMatrix, SkScalar* focalX) {
315 // Inverse of the current local matrix is passed in then,
316 // translate, scale, and rotate such that endCircle is unit circle on x-axis,
317 // and focal point is at the origin.
318 ConicalType conicalType;
319 const SkPoint& focal = shader.getStartCenter();
320 const SkPoint& centerEnd = shader.getEndCenter();
321 SkScalar radius = shader.getEndRadius();
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000322 SkScalar invRadius = 1.f / radius;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000323
324 SkMatrix matrix;
325
326 matrix.setTranslate(-centerEnd.fX, -centerEnd.fY);
327 matrix.postScale(invRadius, invRadius);
328
329 SkPoint focalTrans;
330 matrix.mapPoints(&focalTrans, &focal, 1);
331 *focalX = focalTrans.length();
332
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000333 if (0.f != *focalX) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000334 SkScalar invFocalX = SkScalarInvert(*focalX);
335 SkMatrix rot;
336 rot.setSinCos(-SkScalarMul(invFocalX, focalTrans.fY),
337 SkScalarMul(invFocalX, focalTrans.fX));
338 matrix.postConcat(rot);
339 }
340
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000341 matrix.postTranslate(-(*focalX), 0.f);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000342
343 // If the focal point is touching the edge of the circle it will
344 // cause a degenerate case that must be handled separately
egdaniel8405ef92014-06-09 11:57:28 -0700345 // kEdgeErrorTol = 5 * kErrorTol was picked after manual testing the
346 // stability trade off versus the linear approx used in the Edge Shader
347 if (SkScalarAbs(1.f - (*focalX)) < kEdgeErrorTol) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000348 return kEdge_ConicalType;
349 }
350
351 // Scale factor 1 / (1 - focalX * focalX)
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000352 SkScalar oneMinusF2 = 1.f - SkScalarMul(*focalX, *focalX);
reed80ea19c2015-05-12 10:37:34 -0700353 SkScalar s = SkScalarInvert(oneMinusF2);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000354
355
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000356 if (s >= 0.f) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000357 conicalType = kInside_ConicalType;
358 matrix.postScale(s, s * SkScalarSqrt(oneMinusF2));
359 } else {
360 conicalType = kOutside_ConicalType;
361 matrix.postScale(s, s);
362 }
363
364 invLMatrix->postConcat(matrix);
365
366 return conicalType;
367}
368
369//////////////////////////////////////////////////////////////////////////////
370
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000371class FocalOutside2PtConicalEffect : public GrGradientEffect {
372public:
fmenozzi55d318d2016-08-09 08:05:57 -0700373 class GLSLFocalOutside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000374
brianosman9557c272016-09-15 06:59:15 -0700375 static sk_sp<GrFragmentProcessor> Make(const CreateArgs& args, SkScalar focalX) {
bungeman06ca8ec2016-06-09 08:01:03 -0700376 return sk_sp<GrFragmentProcessor>(
brianosman9557c272016-09-15 06:59:15 -0700377 new FocalOutside2PtConicalEffect(args, focalX));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000378 }
379
380 virtual ~FocalOutside2PtConicalEffect() { }
381
mtklein36352bf2015-03-25 18:17:31 -0700382 const char* name() const override {
joshualitteb2a6762014-12-04 11:35:33 -0800383 return "Two-Point Conical Gradient Focal Outside";
384 }
385
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000386 bool isFlipped() const { return fIsFlipped; }
387 SkScalar focal() const { return fFocalX; }
388
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000389private:
egdaniel57d3b032015-11-13 11:57:27 -0800390 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -0700391
Brian Salomon94efbf52016-11-29 13:43:05 -0500392 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -0700393
mtklein36352bf2015-03-25 18:17:31 -0700394 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -0700395 const FocalOutside2PtConicalEffect& s = sBase.cast<FocalOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000396 return (INHERITED::onIsEqual(sBase) &&
397 this->fFocalX == s.fFocalX &&
398 this->fIsFlipped == s.fIsFlipped);
399 }
400
brianosman9557c272016-09-15 06:59:15 -0700401 FocalOutside2PtConicalEffect(const CreateArgs& args, SkScalar focalX)
402 : INHERITED(args)
joshualittb2456052015-07-08 09:36:59 -0700403 , fFocalX(focalX)
brianosman9557c272016-09-15 06:59:15 -0700404 , fIsFlipped(static_cast<const SkTwoPointConicalGradient*>(args.fShader)->isFlippedGrad()) {
joshualitteb2a6762014-12-04 11:35:33 -0800405 this->initClassID<FocalOutside2PtConicalEffect>();
406 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000407
joshualittb0a8a372014-09-23 09:50:21 -0700408 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000409
410 SkScalar fFocalX;
411 bool fIsFlipped;
412
413 typedef GrGradientEffect INHERITED;
414};
415
fmenozzi55d318d2016-08-09 08:05:57 -0700416class FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor
417 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000418public:
fmenozzi55d318d2016-08-09 08:05:57 -0700419 GLSLFocalOutside2PtConicalProcessor(const GrProcessor&);
420 virtual ~GLSLFocalOutside2PtConicalProcessor() { }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000421
wangyix7c157a92015-07-22 15:08:53 -0700422 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000423
Brian Salomon94efbf52016-11-29 13:43:05 -0500424 static void GenKey(const GrProcessor&, const GrShaderCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000425
426protected:
egdaniel018fb622015-10-28 07:26:40 -0700427 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -0700428
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000429 UniformHandle fParamUni;
430
431 const char* fVSVaryingName;
432 const char* fFSVaryingName;
433
434 bool fIsFlipped;
435
436 // @{
437 /// Values last uploaded as uniforms
438
439 SkScalar fCachedFocal;
440
441 // @}
442
443private:
fmenozzi55d318d2016-08-09 08:05:57 -0700444 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000445
446};
447
Brian Salomon94efbf52016-11-29 13:43:05 -0500448void FocalOutside2PtConicalEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800449 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -0700450 FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800451}
452
egdaniel57d3b032015-11-13 11:57:27 -0800453GrGLSLFragmentProcessor* FocalOutside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -0700454 return new FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000455}
456
joshualittb0a8a372014-09-23 09:50:21 -0700457GR_DEFINE_FRAGMENT_PROCESSOR_TEST(FocalOutside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000458
joshualitt01258472014-09-22 10:29:30 -0700459/*
460 * All Two point conical gradient test create functions may occasionally create edge case shaders
461 */
bungeman06ca8ec2016-06-09 08:01:03 -0700462sk_sp<GrFragmentProcessor> FocalOutside2PtConicalEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700463 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000464 SkScalar radius1 = 0.f;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000465 SkPoint center2;
466 SkScalar radius2;
467 do {
joshualitt0067ff52015-07-08 14:26:19 -0700468 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +0000469 // 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 +0000470 } while (center1 == center2);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000471
Brian Osman3f748602016-10-03 18:29:03 -0400472 SkPoint diff = center2 - center1;
473 SkScalar diffLen = diff.length();
474 // Below makes sure that the focal point is not contained within circle two
475 radius2 = d->fRandom->nextRangeF(0.f, diffLen);
476
477 RandomGradientParams params(d->fRandom);
Brian Osmana2196532016-10-17 12:48:13 -0400478 auto shader = params.fUseColors4f ?
479 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
480 params.fColors4f, params.fColorSpace, params.fStops,
481 params.fColorCount, params.fTileMode) :
482 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
483 params.fColors, params.fStops,
484 params.fColorCount, params.fTileMode);
Brian Osman9f532a32016-10-19 11:12:09 -0400485 GrTest::TestAsFPArgs asFPArgs(d);
486 sk_sp<GrFragmentProcessor> fp = shader->asFragmentProcessor(asFPArgs.args());
bsalomonc21b09e2015-08-28 18:46:56 -0700487 GrAlwaysAssert(fp);
488 return fp;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000489}
490
fmenozzi55d318d2016-08-09 08:05:57 -0700491FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor
492 ::GLSLFocalOutside2PtConicalProcessor(const GrProcessor& processor)
halcanary96fcdcc2015-08-27 07:41:13 -0700493 : fVSVaryingName(nullptr)
494 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000495 , fCachedFocal(SK_ScalarMax) {
joshualittb0a8a372014-09-23 09:50:21 -0700496 const FocalOutside2PtConicalEffect& data = processor.cast<FocalOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000497 fIsFlipped = data.isFlipped();
498}
499
fmenozzi55d318d2016-08-09 08:05:57 -0700500void FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -0700501 const FocalOutside2PtConicalEffect& ge = args.fFp.cast<FocalOutside2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -0800502 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
503 this->emitUniforms(uniformHandler, ge);
jvanverthde11ee42016-02-26 13:58:40 -0800504 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
505 kVec2f_GrSLType, kDefault_GrSLPrecision,
506 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000507 SkString tName("t");
508 SkString p0; // focalX
509 SkString p1; // 1 - focalX * focalX
510
jvanverthde11ee42016-02-26 13:58:40 -0800511 p0.appendf("%s.x", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
512 p1.appendf("%s.y", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000513
514 // if we have a vec3 from being in perspective, convert it to a vec2 first
cdalton85285412016-02-18 12:37:07 -0800515 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -0700516 SkString coords2DString = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +0000517 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000518
519 // t = p.x * focal.x +/- sqrt(p.x^2 + (1 - focal.x^2) * p.y^2)
520
521 // output will default to transparent black (we simply won't write anything
522 // else to it if invalid, instead of discarding or returning prematurely)
egdaniel4ca2e602015-11-18 08:01:26 -0800523 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 +0000524
egdaniel4ca2e602015-11-18 08:01:26 -0800525 fragBuilder->codeAppendf("\tfloat xs = %s.x * %s.x;\n", coords2D, coords2D);
526 fragBuilder->codeAppendf("\tfloat ys = %s.y * %s.y;\n", coords2D, coords2D);
527 fragBuilder->codeAppendf("\tfloat d = xs + %s * ys;\n", p1.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000528
529 // Must check to see if we flipped the circle order (to make sure start radius < end radius)
530 // If so we must also flip sign on sqrt
531 if (!fIsFlipped) {
egdaniel4ca2e602015-11-18 08:01:26 -0800532 fragBuilder->codeAppendf("\tfloat %s = %s.x * %s + sqrt(d);\n", tName.c_str(),
533 coords2D, p0.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000534 } else {
egdaniel4ca2e602015-11-18 08:01:26 -0800535 fragBuilder->codeAppendf("\tfloat %s = %s.x * %s - sqrt(d);\n", tName.c_str(),
536 coords2D, p0.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000537 }
538
egdaniel4ca2e602015-11-18 08:01:26 -0800539 fragBuilder->codeAppendf("\tif (%s >= 0.0 && d >= 0.0) {\n", tName.c_str());
540 fragBuilder->codeAppend("\t\t");
egdaniel7ea439b2015-12-03 09:20:44 -0800541 this->emitColor(fragBuilder,
542 uniformHandler,
egdaniela2e3e0f2015-11-19 07:23:45 -0800543 args.fGLSLCaps,
egdaniel4ca2e602015-11-18 08:01:26 -0800544 ge,
545 tName.c_str(),
546 args.fOutputColor,
547 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -0700548 args.fTexSamplers);
egdaniel4ca2e602015-11-18 08:01:26 -0800549 fragBuilder->codeAppend("\t}\n");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000550}
551
fmenozzi55d318d2016-08-09 08:05:57 -0700552void FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::onSetData(
553 const GrGLSLProgramDataManager& pdman,
554 const GrProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -0700555 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -0700556 const FocalOutside2PtConicalEffect& data = processor.cast<FocalOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000557 SkASSERT(data.isFlipped() == fIsFlipped);
558 SkScalar focal = data.focal();
559
560 if (fCachedFocal != focal) {
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000561 SkScalar oneMinus2F = 1.f - SkScalarMul(focal, focal);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000562
jvanverthde11ee42016-02-26 13:58:40 -0800563 pdman.set2f(fParamUni, SkScalarToFloat(focal), SkScalarToFloat(oneMinus2F));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000564 fCachedFocal = focal;
565 }
566}
567
fmenozzi55d318d2016-08-09 08:05:57 -0700568void FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::GenKey(
569 const GrProcessor& processor,
Brian Salomon94efbf52016-11-29 13:43:05 -0500570 const GrShaderCaps&, GrProcessorKeyBuilder* b) {
bsalomon63e99f72014-07-21 08:03:14 -0700571 uint32_t* key = b->add32n(2);
joshualittb0a8a372014-09-23 09:50:21 -0700572 key[0] = GenBaseGradientKey(processor);
573 key[1] = processor.cast<FocalOutside2PtConicalEffect>().isFlipped();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000574}
575
576//////////////////////////////////////////////////////////////////////////////
577
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000578class FocalInside2PtConicalEffect : public GrGradientEffect {
579public:
fmenozzi55d318d2016-08-09 08:05:57 -0700580 class GLSLFocalInside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000581
brianosman9557c272016-09-15 06:59:15 -0700582 static sk_sp<GrFragmentProcessor> Make(const CreateArgs& args, SkScalar focalX) {
bungeman06ca8ec2016-06-09 08:01:03 -0700583 return sk_sp<GrFragmentProcessor>(
brianosman9557c272016-09-15 06:59:15 -0700584 new FocalInside2PtConicalEffect(args, focalX));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000585 }
586
587 virtual ~FocalInside2PtConicalEffect() {}
588
mtklein36352bf2015-03-25 18:17:31 -0700589 const char* name() const override {
joshualitteb2a6762014-12-04 11:35:33 -0800590 return "Two-Point Conical Gradient Focal Inside";
591 }
592
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000593 SkScalar focal() const { return fFocalX; }
594
fmenozzi55d318d2016-08-09 08:05:57 -0700595 typedef FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor GLSLProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000596
597private:
egdaniel57d3b032015-11-13 11:57:27 -0800598 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -0700599
Brian Salomon94efbf52016-11-29 13:43:05 -0500600 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -0700601
mtklein36352bf2015-03-25 18:17:31 -0700602 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -0700603 const FocalInside2PtConicalEffect& s = sBase.cast<FocalInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000604 return (INHERITED::onIsEqual(sBase) &&
605 this->fFocalX == s.fFocalX);
606 }
607
brianosman9557c272016-09-15 06:59:15 -0700608 FocalInside2PtConicalEffect(const CreateArgs& args, SkScalar focalX)
609 : INHERITED(args), fFocalX(focalX) {
joshualitteb2a6762014-12-04 11:35:33 -0800610 this->initClassID<FocalInside2PtConicalEffect>();
611 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000612
joshualittb0a8a372014-09-23 09:50:21 -0700613 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000614
615 SkScalar fFocalX;
616
617 typedef GrGradientEffect INHERITED;
618};
619
fmenozzi55d318d2016-08-09 08:05:57 -0700620class FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor
621 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000622public:
fmenozzi55d318d2016-08-09 08:05:57 -0700623 GLSLFocalInside2PtConicalProcessor(const GrProcessor&);
624 virtual ~GLSLFocalInside2PtConicalProcessor() {}
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000625
wangyix7c157a92015-07-22 15:08:53 -0700626 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000627
Brian Salomon94efbf52016-11-29 13:43:05 -0500628 static void GenKey(const GrProcessor&, const GrShaderCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000629
630protected:
egdaniel018fb622015-10-28 07:26:40 -0700631 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -0700632
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000633 UniformHandle fFocalUni;
634
635 const char* fVSVaryingName;
636 const char* fFSVaryingName;
637
638 // @{
639 /// Values last uploaded as uniforms
640
641 SkScalar fCachedFocal;
642
643 // @}
644
645private:
fmenozzi55d318d2016-08-09 08:05:57 -0700646 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000647
648};
649
Brian Salomon94efbf52016-11-29 13:43:05 -0500650void FocalInside2PtConicalEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800651 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -0700652 FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800653}
654
egdaniel57d3b032015-11-13 11:57:27 -0800655GrGLSLFragmentProcessor* FocalInside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -0700656 return new FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000657}
658
joshualittb0a8a372014-09-23 09:50:21 -0700659GR_DEFINE_FRAGMENT_PROCESSOR_TEST(FocalInside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000660
joshualitt01258472014-09-22 10:29:30 -0700661/*
662 * All Two point conical gradient test create functions may occasionally create edge case shaders
663 */
bungeman06ca8ec2016-06-09 08:01:03 -0700664sk_sp<GrFragmentProcessor> FocalInside2PtConicalEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700665 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000666 SkScalar radius1 = 0.f;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000667 SkPoint center2;
668 SkScalar radius2;
669 do {
joshualitt0067ff52015-07-08 14:26:19 -0700670 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000671 // Below makes sure radius2 is larger enouch such that the focal point
672 // is inside the end circle
joshualitt0067ff52015-07-08 14:26:19 -0700673 SkScalar increase = d->fRandom->nextUScalar1();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000674 SkPoint diff = center2 - center1;
675 SkScalar diffLen = diff.length();
676 radius2 = diffLen + increase;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000677 // If the circles are identical the factory will give us an empty shader.
678 } while (radius1 == radius2 && center1 == center2);
679
Brian Osman3f748602016-10-03 18:29:03 -0400680 RandomGradientParams params(d->fRandom);
Brian Osmana2196532016-10-17 12:48:13 -0400681 auto shader = params.fUseColors4f ?
682 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
683 params.fColors4f, params.fColorSpace, params.fStops,
684 params.fColorCount, params.fTileMode) :
685 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
686 params.fColors, params.fStops,
687 params.fColorCount, params.fTileMode);
Brian Osman9f532a32016-10-19 11:12:09 -0400688 GrTest::TestAsFPArgs asFPArgs(d);
689 sk_sp<GrFragmentProcessor> fp = shader->asFragmentProcessor(asFPArgs.args());
bsalomonc21b09e2015-08-28 18:46:56 -0700690 GrAlwaysAssert(fp);
joshualittb0a8a372014-09-23 09:50:21 -0700691 return fp;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000692}
693
fmenozzi55d318d2016-08-09 08:05:57 -0700694FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor
695 ::GLSLFocalInside2PtConicalProcessor(const GrProcessor&)
halcanary96fcdcc2015-08-27 07:41:13 -0700696 : fVSVaryingName(nullptr)
697 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000698 , fCachedFocal(SK_ScalarMax) {}
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000699
fmenozzi55d318d2016-08-09 08:05:57 -0700700void FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -0700701 const FocalInside2PtConicalEffect& ge = args.fFp.cast<FocalInside2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -0800702 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
703 this->emitUniforms(uniformHandler, ge);
cdalton5e58cee2016-02-11 12:49:47 -0800704 fFocalUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800705 kFloat_GrSLType, kDefault_GrSLPrecision,
706 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000707 SkString tName("t");
708
709 // this is the distance along x-axis from the end center to focal point in
710 // transformed coordinates
Brian Salomon99938a82016-11-21 13:41:08 -0500711 GrShaderVar focal = uniformHandler->getUniformVariable(fFocalUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000712
713 // if we have a vec3 from being in perspective, convert it to a vec2 first
cdalton85285412016-02-18 12:37:07 -0800714 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -0700715 SkString coords2DString = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +0000716 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000717
718 // t = p.x * focalX + length(p)
egdaniel4ca2e602015-11-18 08:01:26 -0800719 fragBuilder->codeAppendf("\tfloat %s = %s.x * %s + length(%s);\n", tName.c_str(),
egdaniel7ea439b2015-12-03 09:20:44 -0800720 coords2D, focal.c_str(), coords2D);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000721
egdaniel7ea439b2015-12-03 09:20:44 -0800722 this->emitColor(fragBuilder,
723 uniformHandler,
egdaniela2e3e0f2015-11-19 07:23:45 -0800724 args.fGLSLCaps,
egdaniel4ca2e602015-11-18 08:01:26 -0800725 ge,
726 tName.c_str(),
727 args.fOutputColor,
728 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -0700729 args.fTexSamplers);
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000730}
731
fmenozzi55d318d2016-08-09 08:05:57 -0700732void FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::onSetData(
733 const GrGLSLProgramDataManager& pdman,
734 const GrProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -0700735 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -0700736 const FocalInside2PtConicalEffect& data = processor.cast<FocalInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000737 SkScalar focal = data.focal();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000738
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000739 if (fCachedFocal != focal) {
kkinnunen7510b222014-07-30 00:04:16 -0700740 pdman.set1f(fFocalUni, SkScalarToFloat(focal));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000741 fCachedFocal = focal;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000742 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000743}
744
fmenozzi55d318d2016-08-09 08:05:57 -0700745void FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::GenKey(
746 const GrProcessor& processor,
Brian Salomon94efbf52016-11-29 13:43:05 -0500747 const GrShaderCaps&, GrProcessorKeyBuilder* b) {
joshualittb0a8a372014-09-23 09:50:21 -0700748 b->add32(GenBaseGradientKey(processor));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000749}
750
751//////////////////////////////////////////////////////////////////////////////
752// Circle Conical Gradients
753//////////////////////////////////////////////////////////////////////////////
754
755struct CircleConicalInfo {
756 SkPoint fCenterEnd;
757 SkScalar fA;
758 SkScalar fB;
759 SkScalar fC;
760};
761
762// Returns focal distance along x-axis in transformed coords
763static ConicalType set_matrix_circle_conical(const SkTwoPointConicalGradient& shader,
764 SkMatrix* invLMatrix, CircleConicalInfo* info) {
765 // Inverse of the current local matrix is passed in then,
766 // translate and scale such that start circle is on the origin and has radius 1
767 const SkPoint& centerStart = shader.getStartCenter();
768 const SkPoint& centerEnd = shader.getEndCenter();
769 SkScalar radiusStart = shader.getStartRadius();
770 SkScalar radiusEnd = shader.getEndRadius();
771
772 SkMatrix matrix;
773
774 matrix.setTranslate(-centerStart.fX, -centerStart.fY);
775
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000776 SkScalar invStartRad = 1.f / radiusStart;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000777 matrix.postScale(invStartRad, invStartRad);
778
779 radiusEnd /= radiusStart;
780
781 SkPoint centerEndTrans;
782 matrix.mapPoints(&centerEndTrans, &centerEnd, 1);
783
784 SkScalar A = centerEndTrans.fX * centerEndTrans.fX + centerEndTrans.fY * centerEndTrans.fY
785 - radiusEnd * radiusEnd + 2 * radiusEnd - 1;
786
787 // Check to see if start circle is inside end circle with edges touching.
788 // If touching we return that it is of kEdge_ConicalType, and leave the matrix setting
egdaniel8405ef92014-06-09 11:57:28 -0700789 // to the edge shader. kEdgeErrorTol = 5 * kErrorTol was picked after manual testing
790 // so that C = 1 / A is stable, and the linear approximation used in the Edge shader is
791 // still accurate.
792 if (SkScalarAbs(A) < kEdgeErrorTol) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000793 return kEdge_ConicalType;
794 }
795
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000796 SkScalar C = 1.f / A;
797 SkScalar B = (radiusEnd - 1.f) * C;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000798
799 matrix.postScale(C, C);
800
801 invLMatrix->postConcat(matrix);
802
803 info->fCenterEnd = centerEndTrans;
804 info->fA = A;
805 info->fB = B;
806 info->fC = C;
807
808 // 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 +0000809 if (A < 0.f) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000810 return kInside_ConicalType;
811 }
812 return kOutside_ConicalType;
813}
814
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000815class CircleInside2PtConicalEffect : public GrGradientEffect {
816public:
fmenozzi55d318d2016-08-09 08:05:57 -0700817 class GLSLCircleInside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000818
brianosman9557c272016-09-15 06:59:15 -0700819 static sk_sp<GrFragmentProcessor> Make(const CreateArgs& args, const CircleConicalInfo& info) {
bungeman06ca8ec2016-06-09 08:01:03 -0700820 return sk_sp<GrFragmentProcessor>(
brianosman9557c272016-09-15 06:59:15 -0700821 new CircleInside2PtConicalEffect(args, info));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000822 }
823
824 virtual ~CircleInside2PtConicalEffect() {}
825
mtklein36352bf2015-03-25 18:17:31 -0700826 const char* name() const override { return "Two-Point Conical Gradient Inside"; }
joshualitteb2a6762014-12-04 11:35:33 -0800827
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000828 SkScalar centerX() const { return fInfo.fCenterEnd.fX; }
829 SkScalar centerY() const { return fInfo.fCenterEnd.fY; }
830 SkScalar A() const { return fInfo.fA; }
831 SkScalar B() const { return fInfo.fB; }
832 SkScalar C() const { return fInfo.fC; }
833
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000834private:
egdaniel57d3b032015-11-13 11:57:27 -0800835 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -0700836
Brian Salomon94efbf52016-11-29 13:43:05 -0500837 virtual void onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800838 GrProcessorKeyBuilder* b) const override;
wangyix4b3050b2015-08-04 07:59:37 -0700839
mtklein36352bf2015-03-25 18:17:31 -0700840 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -0700841 const CircleInside2PtConicalEffect& s = sBase.cast<CircleInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000842 return (INHERITED::onIsEqual(sBase) &&
843 this->fInfo.fCenterEnd == s.fInfo.fCenterEnd &&
844 this->fInfo.fA == s.fInfo.fA &&
845 this->fInfo.fB == s.fInfo.fB &&
846 this->fInfo.fC == s.fInfo.fC);
847 }
848
brianosman9557c272016-09-15 06:59:15 -0700849 CircleInside2PtConicalEffect(const CreateArgs& args, const CircleConicalInfo& info)
850 : INHERITED(args), fInfo(info) {
joshualitteb2a6762014-12-04 11:35:33 -0800851 this->initClassID<CircleInside2PtConicalEffect>();
852 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000853
joshualittb0a8a372014-09-23 09:50:21 -0700854 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000855
856 const CircleConicalInfo fInfo;
857
858 typedef GrGradientEffect INHERITED;
859};
860
fmenozzi55d318d2016-08-09 08:05:57 -0700861class CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor
862 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000863public:
fmenozzi55d318d2016-08-09 08:05:57 -0700864 GLSLCircleInside2PtConicalProcessor(const GrProcessor&);
865 virtual ~GLSLCircleInside2PtConicalProcessor() {}
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000866
wangyix7c157a92015-07-22 15:08:53 -0700867 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000868
Brian Salomon94efbf52016-11-29 13:43:05 -0500869 static void GenKey(const GrProcessor&, const GrShaderCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000870
871protected:
egdaniel018fb622015-10-28 07:26:40 -0700872 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -0700873
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000874 UniformHandle fCenterUni;
875 UniformHandle fParamUni;
876
877 const char* fVSVaryingName;
878 const char* fFSVaryingName;
879
880 // @{
881 /// Values last uploaded as uniforms
882
883 SkScalar fCachedCenterX;
884 SkScalar fCachedCenterY;
885 SkScalar fCachedA;
886 SkScalar fCachedB;
887 SkScalar fCachedC;
888
889 // @}
890
891private:
fmenozzi55d318d2016-08-09 08:05:57 -0700892 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000893
894};
895
Brian Salomon94efbf52016-11-29 13:43:05 -0500896void CircleInside2PtConicalEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800897 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -0700898 CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800899}
900
egdaniel57d3b032015-11-13 11:57:27 -0800901GrGLSLFragmentProcessor* CircleInside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -0700902 return new CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000903}
904
joshualittb0a8a372014-09-23 09:50:21 -0700905GR_DEFINE_FRAGMENT_PROCESSOR_TEST(CircleInside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000906
joshualitt01258472014-09-22 10:29:30 -0700907/*
908 * All Two point conical gradient test create functions may occasionally create edge case shaders
909 */
bungeman06ca8ec2016-06-09 08:01:03 -0700910sk_sp<GrFragmentProcessor> CircleInside2PtConicalEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700911 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
912 SkScalar radius1 = d->fRandom->nextUScalar1() + 0.0001f; // make sure radius1 != 0
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000913 SkPoint center2;
914 SkScalar radius2;
915 do {
joshualitt0067ff52015-07-08 14:26:19 -0700916 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000917 // Below makes sure that circle one is contained within circle two
joshualitt0067ff52015-07-08 14:26:19 -0700918 SkScalar increase = d->fRandom->nextUScalar1();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000919 SkPoint diff = center2 - center1;
920 SkScalar diffLen = diff.length();
921 radius2 = radius1 + diffLen + increase;
922 // If the circles are identical the factory will give us an empty shader.
923 } while (radius1 == radius2 && center1 == center2);
924
Brian Osman3f748602016-10-03 18:29:03 -0400925 RandomGradientParams params(d->fRandom);
Brian Osmana2196532016-10-17 12:48:13 -0400926 auto shader = params.fUseColors4f ?
927 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
928 params.fColors4f, params.fColorSpace, params.fStops,
929 params.fColorCount, params.fTileMode) :
930 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
931 params.fColors, params.fStops,
932 params.fColorCount, params.fTileMode);
Brian Osman9f532a32016-10-19 11:12:09 -0400933 GrTest::TestAsFPArgs asFPArgs(d);
934 sk_sp<GrFragmentProcessor> fp = shader->asFragmentProcessor(asFPArgs.args());
bsalomonc21b09e2015-08-28 18:46:56 -0700935 GrAlwaysAssert(fp);
joshualitt8ca93e72015-07-08 06:51:43 -0700936 return fp;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000937}
938
fmenozzi55d318d2016-08-09 08:05:57 -0700939CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor
940 ::GLSLCircleInside2PtConicalProcessor(const GrProcessor& processor)
halcanary96fcdcc2015-08-27 07:41:13 -0700941 : fVSVaryingName(nullptr)
942 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000943 , fCachedCenterX(SK_ScalarMax)
944 , fCachedCenterY(SK_ScalarMax)
945 , fCachedA(SK_ScalarMax)
946 , fCachedB(SK_ScalarMax)
947 , fCachedC(SK_ScalarMax) {}
948
fmenozzi55d318d2016-08-09 08:05:57 -0700949void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -0700950 const CircleInside2PtConicalEffect& ge = args.fFp.cast<CircleInside2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -0800951 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
952 this->emitUniforms(uniformHandler, ge);
cdalton5e58cee2016-02-11 12:49:47 -0800953 fCenterUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800954 kVec2f_GrSLType, kDefault_GrSLPrecision,
955 "Conical2FSCenter");
cdalton5e58cee2016-02-11 12:49:47 -0800956 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800957 kVec3f_GrSLType, kDefault_GrSLPrecision,
958 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000959 SkString tName("t");
960
Brian Salomon99938a82016-11-21 13:41:08 -0500961 GrShaderVar center = uniformHandler->getUniformVariable(fCenterUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000962 // params.x = A
963 // params.y = B
964 // params.z = C
Brian Salomon99938a82016-11-21 13:41:08 -0500965 GrShaderVar params = uniformHandler->getUniformVariable(fParamUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000966
967 // if we have a vec3 from being in perspective, convert it to a vec2 first
cdalton85285412016-02-18 12:37:07 -0800968 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -0700969 SkString coords2DString = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +0000970 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000971
972 // p = coords2D
973 // e = center end
974 // r = radius end
975 // A = dot(e, e) - r^2 + 2 * r - 1
976 // B = (r -1) / A
977 // C = 1 / A
978 // d = dot(e, p) + B
979 // t = d +/- sqrt(d^2 - A * dot(p, p) + C)
egdaniel4ca2e602015-11-18 08:01:26 -0800980 fragBuilder->codeAppendf("\tfloat pDotp = dot(%s, %s);\n", coords2D, coords2D);
981 fragBuilder->codeAppendf("\tfloat d = dot(%s, %s) + %s.y;\n", coords2D, center.c_str(),
982 params.c_str());
983 fragBuilder->codeAppendf("\tfloat %s = d + sqrt(d * d - %s.x * pDotp + %s.z);\n",
984 tName.c_str(), params.c_str(), params.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000985
egdaniel7ea439b2015-12-03 09:20:44 -0800986 this->emitColor(fragBuilder,
987 uniformHandler,
egdaniela2e3e0f2015-11-19 07:23:45 -0800988 args.fGLSLCaps,
egdaniel4ca2e602015-11-18 08:01:26 -0800989 ge,
990 tName.c_str(),
991 args.fOutputColor,
992 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -0700993 args.fTexSamplers);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000994}
995
fmenozzi55d318d2016-08-09 08:05:57 -0700996void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::onSetData(
997 const GrGLSLProgramDataManager& pdman,
998 const GrProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -0700999 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -07001000 const CircleInside2PtConicalEffect& data = processor.cast<CircleInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001001 SkScalar centerX = data.centerX();
1002 SkScalar centerY = data.centerY();
1003 SkScalar A = data.A();
1004 SkScalar B = data.B();
1005 SkScalar C = data.C();
1006
1007 if (fCachedCenterX != centerX || fCachedCenterY != centerY ||
1008 fCachedA != A || fCachedB != B || fCachedC != C) {
1009
kkinnunen7510b222014-07-30 00:04:16 -07001010 pdman.set2f(fCenterUni, SkScalarToFloat(centerX), SkScalarToFloat(centerY));
1011 pdman.set3f(fParamUni, SkScalarToFloat(A), SkScalarToFloat(B), SkScalarToFloat(C));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001012
1013 fCachedCenterX = centerX;
1014 fCachedCenterY = centerY;
1015 fCachedA = A;
1016 fCachedB = B;
1017 fCachedC = C;
1018 }
1019}
1020
fmenozzi55d318d2016-08-09 08:05:57 -07001021void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::GenKey(
1022 const GrProcessor& processor,
Brian Salomon94efbf52016-11-29 13:43:05 -05001023 const GrShaderCaps&, GrProcessorKeyBuilder* b) {
joshualittb0a8a372014-09-23 09:50:21 -07001024 b->add32(GenBaseGradientKey(processor));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001025}
1026
1027//////////////////////////////////////////////////////////////////////////////
1028
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001029class CircleOutside2PtConicalEffect : public GrGradientEffect {
1030public:
fmenozzi55d318d2016-08-09 08:05:57 -07001031 class GLSLCircleOutside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001032
brianosman9557c272016-09-15 06:59:15 -07001033 static sk_sp<GrFragmentProcessor> Make(const CreateArgs& args, const CircleConicalInfo& info) {
bungeman06ca8ec2016-06-09 08:01:03 -07001034 return sk_sp<GrFragmentProcessor>(
brianosman9557c272016-09-15 06:59:15 -07001035 new CircleOutside2PtConicalEffect(args, info));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001036 }
1037
1038 virtual ~CircleOutside2PtConicalEffect() {}
1039
mtklein36352bf2015-03-25 18:17:31 -07001040 const char* name() const override { return "Two-Point Conical Gradient Outside"; }
joshualitteb2a6762014-12-04 11:35:33 -08001041
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001042 SkScalar centerX() const { return fInfo.fCenterEnd.fX; }
1043 SkScalar centerY() const { return fInfo.fCenterEnd.fY; }
1044 SkScalar A() const { return fInfo.fA; }
1045 SkScalar B() const { return fInfo.fB; }
1046 SkScalar C() const { return fInfo.fC; }
1047 SkScalar tLimit() const { return fTLimit; }
1048 bool isFlipped() const { return fIsFlipped; }
1049
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001050private:
egdaniel57d3b032015-11-13 11:57:27 -08001051 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -07001052
Brian Salomon94efbf52016-11-29 13:43:05 -05001053 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -07001054
mtklein36352bf2015-03-25 18:17:31 -07001055 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -07001056 const CircleOutside2PtConicalEffect& s = sBase.cast<CircleOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001057 return (INHERITED::onIsEqual(sBase) &&
1058 this->fInfo.fCenterEnd == s.fInfo.fCenterEnd &&
1059 this->fInfo.fA == s.fInfo.fA &&
1060 this->fInfo.fB == s.fInfo.fB &&
1061 this->fInfo.fC == s.fInfo.fC &&
1062 this->fTLimit == s.fTLimit &&
1063 this->fIsFlipped == s.fIsFlipped);
1064 }
1065
brianosman9557c272016-09-15 06:59:15 -07001066 CircleOutside2PtConicalEffect(const CreateArgs& args, const CircleConicalInfo& info)
1067 : INHERITED(args), fInfo(info) {
joshualitteb2a6762014-12-04 11:35:33 -08001068 this->initClassID<CircleOutside2PtConicalEffect>();
brianosman9557c272016-09-15 06:59:15 -07001069 const SkTwoPointConicalGradient& shader =
1070 *static_cast<const SkTwoPointConicalGradient*>(args.fShader);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001071 if (shader.getStartRadius() != shader.getEndRadius()) {
reed80ea19c2015-05-12 10:37:34 -07001072 fTLimit = shader.getStartRadius() / (shader.getStartRadius() - shader.getEndRadius());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001073 } else {
1074 fTLimit = SK_ScalarMin;
1075 }
1076
1077 fIsFlipped = shader.isFlippedGrad();
1078 }
1079
joshualittb0a8a372014-09-23 09:50:21 -07001080 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001081
1082 const CircleConicalInfo fInfo;
1083 SkScalar fTLimit;
1084 bool fIsFlipped;
1085
1086 typedef GrGradientEffect INHERITED;
1087};
1088
fmenozzi55d318d2016-08-09 08:05:57 -07001089class CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor
1090 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001091public:
fmenozzi55d318d2016-08-09 08:05:57 -07001092 GLSLCircleOutside2PtConicalProcessor(const GrProcessor&);
1093 virtual ~GLSLCircleOutside2PtConicalProcessor() {}
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001094
wangyix7c157a92015-07-22 15:08:53 -07001095 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001096
Brian Salomon94efbf52016-11-29 13:43:05 -05001097 static void GenKey(const GrProcessor&, const GrShaderCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001098
1099protected:
egdaniel018fb622015-10-28 07:26:40 -07001100 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -07001101
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001102 UniformHandle fCenterUni;
1103 UniformHandle fParamUni;
1104
1105 const char* fVSVaryingName;
1106 const char* fFSVaryingName;
1107
1108 bool fIsFlipped;
1109
1110 // @{
1111 /// Values last uploaded as uniforms
1112
1113 SkScalar fCachedCenterX;
1114 SkScalar fCachedCenterY;
1115 SkScalar fCachedA;
1116 SkScalar fCachedB;
1117 SkScalar fCachedC;
1118 SkScalar fCachedTLimit;
1119
1120 // @}
1121
1122private:
fmenozzi55d318d2016-08-09 08:05:57 -07001123 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001124
1125};
1126
Brian Salomon94efbf52016-11-29 13:43:05 -05001127void CircleOutside2PtConicalEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -08001128 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -07001129 CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -08001130}
1131
egdaniel57d3b032015-11-13 11:57:27 -08001132GrGLSLFragmentProcessor* CircleOutside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -07001133 return new CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001134}
1135
joshualittb0a8a372014-09-23 09:50:21 -07001136GR_DEFINE_FRAGMENT_PROCESSOR_TEST(CircleOutside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001137
joshualitt01258472014-09-22 10:29:30 -07001138/*
1139 * All Two point conical gradient test create functions may occasionally create edge case shaders
1140 */
bungeman06ca8ec2016-06-09 08:01:03 -07001141sk_sp<GrFragmentProcessor> CircleOutside2PtConicalEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -07001142 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
1143 SkScalar radius1 = d->fRandom->nextUScalar1() + 0.0001f; // make sure radius1 != 0
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001144 SkPoint center2;
1145 SkScalar radius2;
1146 SkScalar diffLen;
1147 do {
joshualitt0067ff52015-07-08 14:26:19 -07001148 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001149 // If the circles share a center than we can't be in the outside case
1150 } while (center1 == center2);
joshualitt01258472014-09-22 10:29:30 -07001151 SkPoint diff = center2 - center1;
1152 diffLen = diff.length();
1153 // Below makes sure that circle one is not contained within circle two
1154 // and have radius2 >= radius to match sorting on cpu side
joshualitt0067ff52015-07-08 14:26:19 -07001155 radius2 = radius1 + d->fRandom->nextRangeF(0.f, diffLen);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001156
Brian Osman3f748602016-10-03 18:29:03 -04001157 RandomGradientParams params(d->fRandom);
Brian Osmana2196532016-10-17 12:48:13 -04001158 auto shader = params.fUseColors4f ?
1159 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
1160 params.fColors4f, params.fColorSpace, params.fStops,
1161 params.fColorCount, params.fTileMode) :
1162 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
1163 params.fColors, params.fStops,
1164 params.fColorCount, params.fTileMode);
Brian Osman9f532a32016-10-19 11:12:09 -04001165 GrTest::TestAsFPArgs asFPArgs(d);
1166 sk_sp<GrFragmentProcessor> fp = shader->asFragmentProcessor(asFPArgs.args());
bsalomonc21b09e2015-08-28 18:46:56 -07001167 GrAlwaysAssert(fp);
joshualitt8ca93e72015-07-08 06:51:43 -07001168 return fp;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001169}
1170
fmenozzi55d318d2016-08-09 08:05:57 -07001171CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor
1172 ::GLSLCircleOutside2PtConicalProcessor(const GrProcessor& processor)
halcanary96fcdcc2015-08-27 07:41:13 -07001173 : fVSVaryingName(nullptr)
1174 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001175 , fCachedCenterX(SK_ScalarMax)
1176 , fCachedCenterY(SK_ScalarMax)
1177 , fCachedA(SK_ScalarMax)
1178 , fCachedB(SK_ScalarMax)
1179 , fCachedC(SK_ScalarMax)
1180 , fCachedTLimit(SK_ScalarMax) {
joshualittb0a8a372014-09-23 09:50:21 -07001181 const CircleOutside2PtConicalEffect& data = processor.cast<CircleOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001182 fIsFlipped = data.isFlipped();
1183 }
1184
fmenozzi55d318d2016-08-09 08:05:57 -07001185void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -07001186 const CircleOutside2PtConicalEffect& ge = args.fFp.cast<CircleOutside2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -08001187 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
1188 this->emitUniforms(uniformHandler, ge);
cdalton5e58cee2016-02-11 12:49:47 -08001189 fCenterUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001190 kVec2f_GrSLType, kDefault_GrSLPrecision,
1191 "Conical2FSCenter");
cdalton5e58cee2016-02-11 12:49:47 -08001192 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001193 kVec4f_GrSLType, kDefault_GrSLPrecision,
1194 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001195 SkString tName("t");
1196
Brian Salomon99938a82016-11-21 13:41:08 -05001197 GrShaderVar center = uniformHandler->getUniformVariable(fCenterUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001198 // params.x = A
1199 // params.y = B
1200 // params.z = C
Brian Salomon99938a82016-11-21 13:41:08 -05001201 GrShaderVar params = uniformHandler->getUniformVariable(fParamUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001202
1203 // if we have a vec3 from being in perspective, convert it to a vec2 first
cdalton85285412016-02-18 12:37:07 -08001204 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -07001205 SkString coords2DString = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +00001206 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001207
1208 // output will default to transparent black (we simply won't write anything
1209 // else to it if invalid, instead of discarding or returning prematurely)
egdaniel4ca2e602015-11-18 08:01:26 -08001210 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 +00001211
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001212 // p = coords2D
1213 // e = center end
1214 // r = radius end
1215 // A = dot(e, e) - r^2 + 2 * r - 1
1216 // B = (r -1) / A
1217 // C = 1 / A
1218 // d = dot(e, p) + B
1219 // t = d +/- sqrt(d^2 - A * dot(p, p) + C)
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001220
egdaniel4ca2e602015-11-18 08:01:26 -08001221 fragBuilder->codeAppendf("\tfloat pDotp = dot(%s, %s);\n", coords2D, coords2D);
1222 fragBuilder->codeAppendf("\tfloat d = dot(%s, %s) + %s.y;\n", coords2D, center.c_str(),
1223 params.c_str());
1224 fragBuilder->codeAppendf("\tfloat deter = d * d - %s.x * pDotp + %s.z;\n", params.c_str(),
1225 params.c_str());
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001226
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001227 // Must check to see if we flipped the circle order (to make sure start radius < end radius)
1228 // If so we must also flip sign on sqrt
1229 if (!fIsFlipped) {
egdaniel4ca2e602015-11-18 08:01:26 -08001230 fragBuilder->codeAppendf("\tfloat %s = d + sqrt(deter);\n", tName.c_str());
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001231 } else {
egdaniel4ca2e602015-11-18 08:01:26 -08001232 fragBuilder->codeAppendf("\tfloat %s = d - sqrt(deter);\n", tName.c_str());
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001233 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001234
egdaniel7ea439b2015-12-03 09:20:44 -08001235 fragBuilder->codeAppendf("\tif (%s >= %s.w && deter >= 0.0) {\n",
1236 tName.c_str(), params.c_str());
egdaniel4ca2e602015-11-18 08:01:26 -08001237 fragBuilder->codeAppend("\t\t");
egdaniel7ea439b2015-12-03 09:20:44 -08001238 this->emitColor(fragBuilder,
1239 uniformHandler,
egdaniela2e3e0f2015-11-19 07:23:45 -08001240 args.fGLSLCaps,
egdaniel4ca2e602015-11-18 08:01:26 -08001241 ge,
1242 tName.c_str(),
1243 args.fOutputColor,
1244 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -07001245 args.fTexSamplers);
egdaniel4ca2e602015-11-18 08:01:26 -08001246 fragBuilder->codeAppend("\t}\n");
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001247}
1248
fmenozzi55d318d2016-08-09 08:05:57 -07001249void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::onSetData(
1250 const GrGLSLProgramDataManager& pdman,
egdaniel018fb622015-10-28 07:26:40 -07001251 const GrProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -07001252 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -07001253 const CircleOutside2PtConicalEffect& data = processor.cast<CircleOutside2PtConicalEffect>();
commit-bot@chromium.org44d83c12014-04-21 13:10:25 +00001254 SkASSERT(data.isFlipped() == fIsFlipped);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001255 SkScalar centerX = data.centerX();
1256 SkScalar centerY = data.centerY();
1257 SkScalar A = data.A();
1258 SkScalar B = data.B();
1259 SkScalar C = data.C();
1260 SkScalar tLimit = data.tLimit();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001261
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001262 if (fCachedCenterX != centerX || fCachedCenterY != centerY ||
1263 fCachedA != A || fCachedB != B || fCachedC != C || fCachedTLimit != tLimit) {
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001264
kkinnunen7510b222014-07-30 00:04:16 -07001265 pdman.set2f(fCenterUni, SkScalarToFloat(centerX), SkScalarToFloat(centerY));
1266 pdman.set4f(fParamUni, SkScalarToFloat(A), SkScalarToFloat(B), SkScalarToFloat(C),
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001267 SkScalarToFloat(tLimit));
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001268
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001269 fCachedCenterX = centerX;
1270 fCachedCenterY = centerY;
1271 fCachedA = A;
1272 fCachedB = B;
1273 fCachedC = C;
1274 fCachedTLimit = tLimit;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001275 }
1276}
1277
fmenozzi55d318d2016-08-09 08:05:57 -07001278void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::GenKey(
1279 const GrProcessor& processor,
Brian Salomon94efbf52016-11-29 13:43:05 -05001280 const GrShaderCaps&, GrProcessorKeyBuilder* b) {
bsalomon63e99f72014-07-21 08:03:14 -07001281 uint32_t* key = b->add32n(2);
joshualittb0a8a372014-09-23 09:50:21 -07001282 key[0] = GenBaseGradientKey(processor);
1283 key[1] = processor.cast<CircleOutside2PtConicalEffect>().isFlipped();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001284}
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001285
1286//////////////////////////////////////////////////////////////////////////////
1287
brianosman9557c272016-09-15 06:59:15 -07001288sk_sp<GrFragmentProcessor> Gr2PtConicalGradientEffect::Make(
1289 const GrGradientEffect::CreateArgs& args) {
1290 const SkTwoPointConicalGradient& shader =
1291 *static_cast<const SkTwoPointConicalGradient*>(args.fShader);
1292
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001293 SkMatrix matrix;
1294 if (!shader.getLocalMatrix().invert(&matrix)) {
halcanary96fcdcc2015-08-27 07:41:13 -07001295 return nullptr;
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001296 }
brianosman9557c272016-09-15 06:59:15 -07001297 if (args.fMatrix) {
commit-bot@chromium.org96fb7482014-05-09 20:28:11 +00001298 SkMatrix inv;
brianosman9557c272016-09-15 06:59:15 -07001299 if (!args.fMatrix->invert(&inv)) {
halcanary96fcdcc2015-08-27 07:41:13 -07001300 return nullptr;
commit-bot@chromium.org96fb7482014-05-09 20:28:11 +00001301 }
1302 matrix.postConcat(inv);
1303 }
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001304
brianosmanb9c51372016-09-15 11:09:45 -07001305 GrGradientEffect::CreateArgs newArgs(args.fContext, args.fShader, &matrix, args.fTileMode,
1306 std::move(args.fColorSpaceXform), args.fGammaCorrect);
brianosman9557c272016-09-15 06:59:15 -07001307
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001308 if (shader.getStartRadius() < kErrorTol) {
1309 SkScalar focalX;
1310 ConicalType type = set_matrix_focal_conical(shader, &matrix, &focalX);
1311 if (type == kInside_ConicalType) {
brianosman9557c272016-09-15 06:59:15 -07001312 return FocalInside2PtConicalEffect::Make(newArgs, focalX);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001313 } else if(type == kEdge_ConicalType) {
1314 set_matrix_edge_conical(shader, &matrix);
brianosman9557c272016-09-15 06:59:15 -07001315 return Edge2PtConicalEffect::Make(newArgs);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001316 } else {
brianosman9557c272016-09-15 06:59:15 -07001317 return FocalOutside2PtConicalEffect::Make(newArgs, focalX);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001318 }
1319 }
1320
1321 CircleConicalInfo info;
1322 ConicalType type = set_matrix_circle_conical(shader, &matrix, &info);
1323
1324 if (type == kInside_ConicalType) {
brianosman9557c272016-09-15 06:59:15 -07001325 return CircleInside2PtConicalEffect::Make(newArgs, info);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001326 } else if (type == kEdge_ConicalType) {
1327 set_matrix_edge_conical(shader, &matrix);
brianosman9557c272016-09-15 06:59:15 -07001328 return Edge2PtConicalEffect::Make(newArgs);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001329 } else {
brianosman9557c272016-09-15 06:59:15 -07001330 return CircleOutside2PtConicalEffect::Make(newArgs, info);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001331 }
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001332}
1333
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001334#endif