blob: fedb4459043e8f68fbe7201ccef73791081ed6c1 [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"
joshualitt8ca93e72015-07-08 06:51:43 -070013#include "GrPaint.h"
egdaniel2d721d32015-11-11 13:06:05 -080014#include "glsl/GrGLSLFragmentShaderBuilder.h"
egdaniel018fb622015-10-28 07:26:40 -070015#include "glsl/GrGLSLProgramDataManager.h"
egdaniel7ea439b2015-12-03 09:20:44 -080016#include "glsl/GrGLSLUniformHandler.h"
brianosman9557c272016-09-15 06:59:15 -070017#include "SkTwoPointConicalGradient_gpu.h"
18
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +000019// For brevity
egdaniel018fb622015-10-28 07:26:40 -070020typedef GrGLSLProgramDataManager::UniformHandle UniformHandle;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +000021
commit-bot@chromium.org80894672014-04-22 21:24:22 +000022static const SkScalar kErrorTol = 0.00001f;
egdaniel8405ef92014-06-09 11:57:28 -070023static const SkScalar kEdgeErrorTol = 5.f * kErrorTol;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +000024
25/**
26 * We have three general cases for 2pt conical gradients. First we always assume that
27 * the start radius <= end radius. Our first case (kInside_) is when the start circle
28 * is completely enclosed by the end circle. The second case (kOutside_) is the case
29 * when the start circle is either completely outside the end circle or the circles
30 * overlap. The final case (kEdge_) is when the start circle is inside the end one,
31 * but the two are just barely touching at 1 point along their edges.
32 */
33enum ConicalType {
34 kInside_ConicalType,
35 kOutside_ConicalType,
36 kEdge_ConicalType,
37};
38
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000039//////////////////////////////////////////////////////////////////////////////
40
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +000041static void set_matrix_edge_conical(const SkTwoPointConicalGradient& shader,
42 SkMatrix* invLMatrix) {
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000043 // Inverse of the current local matrix is passed in then,
44 // translate to center1, rotate so center2 is on x axis.
45 const SkPoint& center1 = shader.getStartCenter();
46 const SkPoint& center2 = shader.getEndCenter();
47
48 invLMatrix->postTranslate(-center1.fX, -center1.fY);
49
50 SkPoint diff = center2 - center1;
51 SkScalar diffLen = diff.length();
52 if (0 != diffLen) {
53 SkScalar invDiffLen = SkScalarInvert(diffLen);
54 SkMatrix rot;
Mike Reed8be952a2017-02-13 20:44:33 -050055 rot.setSinCos(-invDiffLen * diff.fY, invDiffLen * diff.fX);
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000056 invLMatrix->postConcat(rot);
57 }
58}
59
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +000060class Edge2PtConicalEffect : public GrGradientEffect {
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +000061public:
fmenozzi55d318d2016-08-09 08:05:57 -070062 class GLSLEdge2PtConicalProcessor;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +000063
brianosman9557c272016-09-15 06:59:15 -070064 static sk_sp<GrFragmentProcessor> Make(const CreateArgs& args) {
65 return sk_sp<GrFragmentProcessor>(new Edge2PtConicalEffect(args));
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000066 }
67
Brian Salomond3b65972017-03-22 12:05:03 -040068 ~Edge2PtConicalEffect() override {}
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000069
mtklein36352bf2015-03-25 18:17:31 -070070 const char* name() const override {
joshualitteb2a6762014-12-04 11:35:33 -080071 return "Two-Point Conical Gradient Edge Touching";
72 }
73
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000074 // The radial gradient parameters can collapse to a linear (instead of quadratic) equation.
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000075 SkScalar center() const { return fCenterX1; }
76 SkScalar diffRadius() const { return fDiffRadius; }
77 SkScalar radius() const { return fRadius0; }
78
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000079private:
egdaniel57d3b032015-11-13 11:57:27 -080080 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -070081
Brian Salomon94efbf52016-11-29 13:43:05 -050082 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -070083
mtklein36352bf2015-03-25 18:17:31 -070084 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -070085 const Edge2PtConicalEffect& s = sBase.cast<Edge2PtConicalEffect>();
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000086 return (INHERITED::onIsEqual(sBase) &&
87 this->fCenterX1 == s.fCenterX1 &&
88 this->fRadius0 == s.fRadius0 &&
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +000089 this->fDiffRadius == s.fDiffRadius);
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000090 }
91
brianosman9557c272016-09-15 06:59:15 -070092 Edge2PtConicalEffect(const CreateArgs& args)
Brian Salomon587e08f2017-01-27 10:59:27 -050093 : INHERITED(args, false /* opaque: draws transparent black outside of the cone. */) {
brianosman9557c272016-09-15 06:59:15 -070094 const SkTwoPointConicalGradient& shader =
95 *static_cast<const SkTwoPointConicalGradient*>(args.fShader);
96 fCenterX1 = shader.getCenterX1();
97 fRadius0 = shader.getStartRadius();
98 fDiffRadius = shader.getDiffRadius();
joshualitteb2a6762014-12-04 11:35:33 -080099 this->initClassID<Edge2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000100 // We should only be calling this shader if we are degenerate case with touching circles
egdaniel8405ef92014-06-09 11:57:28 -0700101 // When deciding if we are in edge case, we scaled by the end radius for cases when the
joshualitt01258472014-09-22 10:29:30 -0700102 // start radius was close to zero, otherwise we scaled by the start radius. In addition
103 // Our test for the edge case in set_matrix_circle_conical has a higher tolerance so we
104 // need the sqrt value below
105 SkASSERT(SkScalarAbs(SkScalarAbs(fDiffRadius) - fCenterX1) <
106 (fRadius0 < kErrorTol ? shader.getEndRadius() * kEdgeErrorTol :
107 fRadius0 * sqrt(kEdgeErrorTol)));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000108
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +0000109 // We pass the linear part of the quadratic as a varying.
110 // float b = -2.0 * (fCenterX1 * x + fRadius0 * fDiffRadius * z)
111 fBTransform = this->getCoordTransform();
112 SkMatrix& bMatrix = *fBTransform.accessMatrix();
Mike Reed8be952a2017-02-13 20:44:33 -0500113 SkScalar r0dr = fRadius0 * fDiffRadius;
114 bMatrix[SkMatrix::kMScaleX] = -2 * (fCenterX1 * bMatrix[SkMatrix::kMScaleX] +
115 r0dr * bMatrix[SkMatrix::kMPersp0]);
116 bMatrix[SkMatrix::kMSkewX] = -2 * (fCenterX1 * bMatrix[SkMatrix::kMSkewX] +
117 r0dr * bMatrix[SkMatrix::kMPersp1]);
118 bMatrix[SkMatrix::kMTransX] = -2 * (fCenterX1 * bMatrix[SkMatrix::kMTransX] +
119 r0dr * bMatrix[SkMatrix::kMPersp2]);
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +0000120 this->addCoordTransform(&fBTransform);
121 }
122
joshualittb0a8a372014-09-23 09:50:21 -0700123 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +0000124
125 // @{
126 // Cache of values - these can change arbitrarily, EXCEPT
127 // we shouldn't change between degenerate and non-degenerate?!
128
129 GrCoordTransform fBTransform;
130 SkScalar fCenterX1;
131 SkScalar fRadius0;
132 SkScalar fDiffRadius;
133
134 // @}
135
136 typedef GrGradientEffect INHERITED;
137};
138
fmenozzi55d318d2016-08-09 08:05:57 -0700139class Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +0000140public:
fmenozzi55d318d2016-08-09 08:05:57 -0700141 GLSLEdge2PtConicalProcessor(const GrProcessor&);
Brian Salomond3b65972017-03-22 12:05:03 -0400142 ~GLSLEdge2PtConicalProcessor() override {}
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000143
wangyix7c157a92015-07-22 15:08:53 -0700144 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000145
Brian Salomon94efbf52016-11-29 13:43:05 -0500146 static void GenKey(const GrProcessor&, const GrShaderCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000147
148protected:
Brian Salomonab015ef2017-04-04 10:15:51 -0400149 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -0700150
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000151 UniformHandle fParamUni;
152
153 const char* fVSVaryingName;
154 const char* fFSVaryingName;
155
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000156 // @{
157 /// Values last uploaded as uniforms
158
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000159 SkScalar fCachedRadius;
160 SkScalar fCachedDiffRadius;
161
162 // @}
163
164private:
fmenozzi55d318d2016-08-09 08:05:57 -0700165 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000166
167};
168
Brian Salomon94efbf52016-11-29 13:43:05 -0500169void Edge2PtConicalEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800170 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -0700171 Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800172}
173
egdaniel57d3b032015-11-13 11:57:27 -0800174GrGLSLFragmentProcessor* Edge2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -0700175 return new Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor(*this);
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000176}
skia.committer@gmail.com221b9112014-04-04 03:04:32 +0000177
joshualittb0a8a372014-09-23 09:50:21 -0700178GR_DEFINE_FRAGMENT_PROCESSOR_TEST(Edge2PtConicalEffect);
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000179
joshualitt01258472014-09-22 10:29:30 -0700180/*
181 * All Two point conical gradient test create functions may occasionally create edge case shaders
182 */
Hal Canary6f6961e2017-01-31 13:50:44 -0500183#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -0700184sk_sp<GrFragmentProcessor> Edge2PtConicalEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700185 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
186 SkScalar radius1 = d->fRandom->nextUScalar1();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000187 SkPoint center2;
188 SkScalar radius2;
189 do {
joshualitt0067ff52015-07-08 14:26:19 -0700190 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000191 // If the circles are identical the factory will give us an empty shader.
192 // This will happen if we pick identical centers
193 } while (center1 == center2);
194
195 // Below makes sure that circle one is contained within circle two
196 // and both circles are touching on an edge
197 SkPoint diff = center2 - center1;
198 SkScalar diffLen = diff.length();
199 radius2 = radius1 + diffLen;
200
Brian Osman3f748602016-10-03 18:29:03 -0400201 RandomGradientParams params(d->fRandom);
Brian Osmana2196532016-10-17 12:48:13 -0400202 auto shader = params.fUseColors4f ?
203 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
204 params.fColors4f, params.fColorSpace, params.fStops,
205 params.fColorCount, params.fTileMode) :
206 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
207 params.fColors, params.fStops,
208 params.fColorCount, params.fTileMode);
Brian Osman9f532a32016-10-19 11:12:09 -0400209 GrTest::TestAsFPArgs asFPArgs(d);
210 sk_sp<GrFragmentProcessor> fp = shader->asFragmentProcessor(asFPArgs.args());
bsalomonc21b09e2015-08-28 18:46:56 -0700211 GrAlwaysAssert(fp);
joshualittb0a8a372014-09-23 09:50:21 -0700212 return fp;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000213}
Hal Canary6f6961e2017-01-31 13:50:44 -0500214#endif
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000215
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,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500277 args.fShaderCaps,
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(
Brian Salomonab015ef2017-04-04 10:15:51 -0400287 const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -0700288 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -0700289 const Edge2PtConicalEffect& data = processor.cast<Edge2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000290 SkScalar radius0 = data.radius();
291 SkScalar diffRadius = data.diffRadius();
292
293 if (fCachedRadius != radius0 ||
294 fCachedDiffRadius != diffRadius) {
295
Mike Reed8be952a2017-02-13 20:44:33 -0500296 pdman.set3f(fParamUni, radius0, radius0 * radius0, diffRadius);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000297 fCachedRadius = radius0;
298 fCachedDiffRadius = diffRadius;
299 }
300}
301
fmenozzi55d318d2016-08-09 08:05:57 -0700302void Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::GenKey(const GrProcessor& processor,
Brian Salomon94efbf52016-11-29 13:43:05 -0500303 const GrShaderCaps&, GrProcessorKeyBuilder* b) {
joshualittb0a8a372014-09-23 09:50:21 -0700304 b->add32(GenBaseGradientKey(processor));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000305}
306
307//////////////////////////////////////////////////////////////////////////////
308// Focal Conical Gradients
309//////////////////////////////////////////////////////////////////////////////
310
311static ConicalType set_matrix_focal_conical(const SkTwoPointConicalGradient& shader,
312 SkMatrix* invLMatrix, SkScalar* focalX) {
313 // Inverse of the current local matrix is passed in then,
314 // translate, scale, and rotate such that endCircle is unit circle on x-axis,
315 // and focal point is at the origin.
316 ConicalType conicalType;
317 const SkPoint& focal = shader.getStartCenter();
318 const SkPoint& centerEnd = shader.getEndCenter();
319 SkScalar radius = shader.getEndRadius();
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000320 SkScalar invRadius = 1.f / radius;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000321
322 SkMatrix matrix;
323
324 matrix.setTranslate(-centerEnd.fX, -centerEnd.fY);
325 matrix.postScale(invRadius, invRadius);
326
327 SkPoint focalTrans;
328 matrix.mapPoints(&focalTrans, &focal, 1);
329 *focalX = focalTrans.length();
330
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000331 if (0.f != *focalX) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000332 SkScalar invFocalX = SkScalarInvert(*focalX);
333 SkMatrix rot;
Mike Reed8be952a2017-02-13 20:44:33 -0500334 rot.setSinCos(-invFocalX * focalTrans.fY, invFocalX * focalTrans.fX);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000335 matrix.postConcat(rot);
336 }
337
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000338 matrix.postTranslate(-(*focalX), 0.f);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000339
340 // If the focal point is touching the edge of the circle it will
341 // cause a degenerate case that must be handled separately
egdaniel8405ef92014-06-09 11:57:28 -0700342 // kEdgeErrorTol = 5 * kErrorTol was picked after manual testing the
343 // stability trade off versus the linear approx used in the Edge Shader
344 if (SkScalarAbs(1.f - (*focalX)) < kEdgeErrorTol) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000345 return kEdge_ConicalType;
346 }
347
348 // Scale factor 1 / (1 - focalX * focalX)
Mike Reed8be952a2017-02-13 20:44:33 -0500349 SkScalar oneMinusF2 = 1.f - *focalX * *focalX;
reed80ea19c2015-05-12 10:37:34 -0700350 SkScalar s = SkScalarInvert(oneMinusF2);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000351
352
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000353 if (s >= 0.f) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000354 conicalType = kInside_ConicalType;
355 matrix.postScale(s, s * SkScalarSqrt(oneMinusF2));
356 } else {
357 conicalType = kOutside_ConicalType;
358 matrix.postScale(s, s);
359 }
360
361 invLMatrix->postConcat(matrix);
362
363 return conicalType;
364}
365
366//////////////////////////////////////////////////////////////////////////////
367
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000368class FocalOutside2PtConicalEffect : public GrGradientEffect {
369public:
fmenozzi55d318d2016-08-09 08:05:57 -0700370 class GLSLFocalOutside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000371
brianosman9557c272016-09-15 06:59:15 -0700372 static sk_sp<GrFragmentProcessor> Make(const CreateArgs& args, SkScalar focalX) {
bungeman06ca8ec2016-06-09 08:01:03 -0700373 return sk_sp<GrFragmentProcessor>(
brianosman9557c272016-09-15 06:59:15 -0700374 new FocalOutside2PtConicalEffect(args, focalX));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000375 }
376
Brian Salomond3b65972017-03-22 12:05:03 -0400377 ~FocalOutside2PtConicalEffect() override {}
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000378
mtklein36352bf2015-03-25 18:17:31 -0700379 const char* name() const override {
joshualitteb2a6762014-12-04 11:35:33 -0800380 return "Two-Point Conical Gradient Focal Outside";
381 }
382
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000383 bool isFlipped() const { return fIsFlipped; }
384 SkScalar focal() const { return fFocalX; }
385
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000386private:
egdaniel57d3b032015-11-13 11:57:27 -0800387 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -0700388
Brian Salomon94efbf52016-11-29 13:43:05 -0500389 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -0700390
mtklein36352bf2015-03-25 18:17:31 -0700391 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -0700392 const FocalOutside2PtConicalEffect& s = sBase.cast<FocalOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000393 return (INHERITED::onIsEqual(sBase) &&
394 this->fFocalX == s.fFocalX &&
395 this->fIsFlipped == s.fIsFlipped);
396 }
397
Brian Salomon587e08f2017-01-27 10:59:27 -0500398 static bool IsFlipped(const CreateArgs& args) {
399 // eww.
400 return static_cast<const SkTwoPointConicalGradient*>(args.fShader)->isFlippedGrad();
401 }
402
brianosman9557c272016-09-15 06:59:15 -0700403 FocalOutside2PtConicalEffect(const CreateArgs& args, SkScalar focalX)
Brian Salomon587e08f2017-01-27 10:59:27 -0500404 : INHERITED(args, false /* opaque: draws transparent black outside of the cone. */)
405 , fFocalX(focalX)
406 , fIsFlipped(IsFlipped(args)) {
joshualitteb2a6762014-12-04 11:35:33 -0800407 this->initClassID<FocalOutside2PtConicalEffect>();
408 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000409
joshualittb0a8a372014-09-23 09:50:21 -0700410 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000411
412 SkScalar fFocalX;
413 bool fIsFlipped;
414
415 typedef GrGradientEffect INHERITED;
416};
417
Brian Salomon587e08f2017-01-27 10:59:27 -0500418class FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor
fmenozzi55d318d2016-08-09 08:05:57 -0700419 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000420public:
fmenozzi55d318d2016-08-09 08:05:57 -0700421 GLSLFocalOutside2PtConicalProcessor(const GrProcessor&);
Brian Salomond3b65972017-03-22 12:05:03 -0400422 ~GLSLFocalOutside2PtConicalProcessor() override {}
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000423
wangyix7c157a92015-07-22 15:08:53 -0700424 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000425
Brian Salomon94efbf52016-11-29 13:43:05 -0500426 static void GenKey(const GrProcessor&, const GrShaderCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000427
428protected:
Brian Salomonab015ef2017-04-04 10:15:51 -0400429 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -0700430
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000431 UniformHandle fParamUni;
432
433 const char* fVSVaryingName;
434 const char* fFSVaryingName;
435
436 bool fIsFlipped;
437
438 // @{
439 /// Values last uploaded as uniforms
440
441 SkScalar fCachedFocal;
442
443 // @}
444
445private:
fmenozzi55d318d2016-08-09 08:05:57 -0700446 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000447
448};
449
Brian Salomon94efbf52016-11-29 13:43:05 -0500450void FocalOutside2PtConicalEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800451 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -0700452 FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800453}
454
egdaniel57d3b032015-11-13 11:57:27 -0800455GrGLSLFragmentProcessor* FocalOutside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -0700456 return new FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000457}
458
joshualittb0a8a372014-09-23 09:50:21 -0700459GR_DEFINE_FRAGMENT_PROCESSOR_TEST(FocalOutside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000460
joshualitt01258472014-09-22 10:29:30 -0700461/*
462 * All Two point conical gradient test create functions may occasionally create edge case shaders
463 */
Hal Canary6f6961e2017-01-31 13:50:44 -0500464#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -0700465sk_sp<GrFragmentProcessor> FocalOutside2PtConicalEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700466 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000467 SkScalar radius1 = 0.f;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000468 SkPoint center2;
469 SkScalar radius2;
470 do {
joshualitt0067ff52015-07-08 14:26:19 -0700471 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +0000472 // 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 +0000473 } while (center1 == center2);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000474
Brian Osman3f748602016-10-03 18:29:03 -0400475 SkPoint diff = center2 - center1;
476 SkScalar diffLen = diff.length();
477 // Below makes sure that the focal point is not contained within circle two
478 radius2 = d->fRandom->nextRangeF(0.f, diffLen);
479
480 RandomGradientParams params(d->fRandom);
Brian Osmana2196532016-10-17 12:48:13 -0400481 auto shader = params.fUseColors4f ?
482 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
483 params.fColors4f, params.fColorSpace, params.fStops,
484 params.fColorCount, params.fTileMode) :
485 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
486 params.fColors, params.fStops,
487 params.fColorCount, params.fTileMode);
Brian Osman9f532a32016-10-19 11:12:09 -0400488 GrTest::TestAsFPArgs asFPArgs(d);
489 sk_sp<GrFragmentProcessor> fp = shader->asFragmentProcessor(asFPArgs.args());
bsalomonc21b09e2015-08-28 18:46:56 -0700490 GrAlwaysAssert(fp);
491 return fp;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000492}
Hal Canary6f6961e2017-01-31 13:50:44 -0500493#endif
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000494
fmenozzi55d318d2016-08-09 08:05:57 -0700495FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor
496 ::GLSLFocalOutside2PtConicalProcessor(const GrProcessor& processor)
halcanary96fcdcc2015-08-27 07:41:13 -0700497 : fVSVaryingName(nullptr)
498 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000499 , fCachedFocal(SK_ScalarMax) {
joshualittb0a8a372014-09-23 09:50:21 -0700500 const FocalOutside2PtConicalEffect& data = processor.cast<FocalOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000501 fIsFlipped = data.isFlipped();
502}
503
fmenozzi55d318d2016-08-09 08:05:57 -0700504void FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -0700505 const FocalOutside2PtConicalEffect& ge = args.fFp.cast<FocalOutside2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -0800506 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
507 this->emitUniforms(uniformHandler, ge);
jvanverthde11ee42016-02-26 13:58:40 -0800508 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
509 kVec2f_GrSLType, kDefault_GrSLPrecision,
510 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000511 SkString tName("t");
512 SkString p0; // focalX
513 SkString p1; // 1 - focalX * focalX
514
jvanverthde11ee42016-02-26 13:58:40 -0800515 p0.appendf("%s.x", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
516 p1.appendf("%s.y", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000517
518 // if we have a vec3 from being in perspective, convert it to a vec2 first
cdalton85285412016-02-18 12:37:07 -0800519 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -0700520 SkString coords2DString = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +0000521 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000522
523 // t = p.x * focal.x +/- sqrt(p.x^2 + (1 - focal.x^2) * p.y^2)
524
525 // output will default to transparent black (we simply won't write anything
526 // else to it if invalid, instead of discarding or returning prematurely)
egdaniel4ca2e602015-11-18 08:01:26 -0800527 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 +0000528
egdaniel4ca2e602015-11-18 08:01:26 -0800529 fragBuilder->codeAppendf("\tfloat xs = %s.x * %s.x;\n", coords2D, coords2D);
530 fragBuilder->codeAppendf("\tfloat ys = %s.y * %s.y;\n", coords2D, coords2D);
531 fragBuilder->codeAppendf("\tfloat d = xs + %s * ys;\n", p1.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000532
533 // Must check to see if we flipped the circle order (to make sure start radius < end radius)
534 // If so we must also flip sign on sqrt
535 if (!fIsFlipped) {
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 } else {
egdaniel4ca2e602015-11-18 08:01:26 -0800539 fragBuilder->codeAppendf("\tfloat %s = %s.x * %s - sqrt(d);\n", tName.c_str(),
540 coords2D, p0.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000541 }
542
egdaniel4ca2e602015-11-18 08:01:26 -0800543 fragBuilder->codeAppendf("\tif (%s >= 0.0 && d >= 0.0) {\n", tName.c_str());
544 fragBuilder->codeAppend("\t\t");
egdaniel7ea439b2015-12-03 09:20:44 -0800545 this->emitColor(fragBuilder,
546 uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500547 args.fShaderCaps,
egdaniel4ca2e602015-11-18 08:01:26 -0800548 ge,
549 tName.c_str(),
550 args.fOutputColor,
551 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -0700552 args.fTexSamplers);
egdaniel4ca2e602015-11-18 08:01:26 -0800553 fragBuilder->codeAppend("\t}\n");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000554}
555
fmenozzi55d318d2016-08-09 08:05:57 -0700556void FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::onSetData(
Brian Salomonab015ef2017-04-04 10:15:51 -0400557 const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -0700558 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -0700559 const FocalOutside2PtConicalEffect& data = processor.cast<FocalOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000560 SkASSERT(data.isFlipped() == fIsFlipped);
561 SkScalar focal = data.focal();
562
563 if (fCachedFocal != focal) {
Mike Reed8be952a2017-02-13 20:44:33 -0500564 SkScalar oneMinus2F = 1.f - focal * focal;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000565
jvanverthde11ee42016-02-26 13:58:40 -0800566 pdman.set2f(fParamUni, SkScalarToFloat(focal), SkScalarToFloat(oneMinus2F));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000567 fCachedFocal = focal;
568 }
569}
570
fmenozzi55d318d2016-08-09 08:05:57 -0700571void FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::GenKey(
572 const GrProcessor& processor,
Brian Salomon94efbf52016-11-29 13:43:05 -0500573 const GrShaderCaps&, GrProcessorKeyBuilder* b) {
bsalomon63e99f72014-07-21 08:03:14 -0700574 uint32_t* key = b->add32n(2);
joshualittb0a8a372014-09-23 09:50:21 -0700575 key[0] = GenBaseGradientKey(processor);
576 key[1] = processor.cast<FocalOutside2PtConicalEffect>().isFlipped();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000577}
578
579//////////////////////////////////////////////////////////////////////////////
580
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000581class FocalInside2PtConicalEffect : public GrGradientEffect {
582public:
fmenozzi55d318d2016-08-09 08:05:57 -0700583 class GLSLFocalInside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000584
brianosman9557c272016-09-15 06:59:15 -0700585 static sk_sp<GrFragmentProcessor> Make(const CreateArgs& args, SkScalar focalX) {
bungeman06ca8ec2016-06-09 08:01:03 -0700586 return sk_sp<GrFragmentProcessor>(
brianosman9557c272016-09-15 06:59:15 -0700587 new FocalInside2PtConicalEffect(args, focalX));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000588 }
589
Brian Salomond3b65972017-03-22 12:05:03 -0400590 ~FocalInside2PtConicalEffect() override {}
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000591
mtklein36352bf2015-03-25 18:17:31 -0700592 const char* name() const override {
joshualitteb2a6762014-12-04 11:35:33 -0800593 return "Two-Point Conical Gradient Focal Inside";
594 }
595
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000596 SkScalar focal() const { return fFocalX; }
597
fmenozzi55d318d2016-08-09 08:05:57 -0700598 typedef FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor GLSLProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000599
600private:
egdaniel57d3b032015-11-13 11:57:27 -0800601 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -0700602
Brian Salomon94efbf52016-11-29 13:43:05 -0500603 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -0700604
mtklein36352bf2015-03-25 18:17:31 -0700605 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -0700606 const FocalInside2PtConicalEffect& s = sBase.cast<FocalInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000607 return (INHERITED::onIsEqual(sBase) &&
608 this->fFocalX == s.fFocalX);
609 }
610
brianosman9557c272016-09-15 06:59:15 -0700611 FocalInside2PtConicalEffect(const CreateArgs& args, SkScalar focalX)
Brian Salomon587e08f2017-01-27 10:59:27 -0500612 : INHERITED(args, args.fShader->colorsAreOpaque()), fFocalX(focalX) {
joshualitteb2a6762014-12-04 11:35:33 -0800613 this->initClassID<FocalInside2PtConicalEffect>();
614 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000615
joshualittb0a8a372014-09-23 09:50:21 -0700616 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000617
618 SkScalar fFocalX;
619
620 typedef GrGradientEffect INHERITED;
621};
622
fmenozzi55d318d2016-08-09 08:05:57 -0700623class FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor
624 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000625public:
fmenozzi55d318d2016-08-09 08:05:57 -0700626 GLSLFocalInside2PtConicalProcessor(const GrProcessor&);
Brian Salomond3b65972017-03-22 12:05:03 -0400627 ~GLSLFocalInside2PtConicalProcessor() override {}
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000628
wangyix7c157a92015-07-22 15:08:53 -0700629 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000630
Brian Salomon94efbf52016-11-29 13:43:05 -0500631 static void GenKey(const GrProcessor&, const GrShaderCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000632
633protected:
Brian Salomonab015ef2017-04-04 10:15:51 -0400634 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -0700635
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000636 UniformHandle fFocalUni;
637
638 const char* fVSVaryingName;
639 const char* fFSVaryingName;
640
641 // @{
642 /// Values last uploaded as uniforms
643
644 SkScalar fCachedFocal;
645
646 // @}
647
648private:
fmenozzi55d318d2016-08-09 08:05:57 -0700649 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000650
651};
652
Brian Salomon94efbf52016-11-29 13:43:05 -0500653void FocalInside2PtConicalEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800654 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -0700655 FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800656}
657
egdaniel57d3b032015-11-13 11:57:27 -0800658GrGLSLFragmentProcessor* FocalInside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -0700659 return new FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000660}
661
joshualittb0a8a372014-09-23 09:50:21 -0700662GR_DEFINE_FRAGMENT_PROCESSOR_TEST(FocalInside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000663
joshualitt01258472014-09-22 10:29:30 -0700664/*
665 * All Two point conical gradient test create functions may occasionally create edge case shaders
666 */
Hal Canary6f6961e2017-01-31 13:50:44 -0500667#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -0700668sk_sp<GrFragmentProcessor> FocalInside2PtConicalEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700669 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000670 SkScalar radius1 = 0.f;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000671 SkPoint center2;
672 SkScalar radius2;
673 do {
joshualitt0067ff52015-07-08 14:26:19 -0700674 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000675 // Below makes sure radius2 is larger enouch such that the focal point
676 // is inside the end circle
joshualitt0067ff52015-07-08 14:26:19 -0700677 SkScalar increase = d->fRandom->nextUScalar1();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000678 SkPoint diff = center2 - center1;
679 SkScalar diffLen = diff.length();
680 radius2 = diffLen + increase;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000681 // If the circles are identical the factory will give us an empty shader.
682 } while (radius1 == radius2 && center1 == center2);
683
Brian Osman3f748602016-10-03 18:29:03 -0400684 RandomGradientParams params(d->fRandom);
Brian Osmana2196532016-10-17 12:48:13 -0400685 auto shader = params.fUseColors4f ?
686 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
687 params.fColors4f, params.fColorSpace, params.fStops,
688 params.fColorCount, params.fTileMode) :
689 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
690 params.fColors, params.fStops,
691 params.fColorCount, params.fTileMode);
Brian Osman9f532a32016-10-19 11:12:09 -0400692 GrTest::TestAsFPArgs asFPArgs(d);
693 sk_sp<GrFragmentProcessor> fp = shader->asFragmentProcessor(asFPArgs.args());
bsalomonc21b09e2015-08-28 18:46:56 -0700694 GrAlwaysAssert(fp);
joshualittb0a8a372014-09-23 09:50:21 -0700695 return fp;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000696}
Hal Canary6f6961e2017-01-31 13:50:44 -0500697#endif
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000698
fmenozzi55d318d2016-08-09 08:05:57 -0700699FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor
700 ::GLSLFocalInside2PtConicalProcessor(const GrProcessor&)
halcanary96fcdcc2015-08-27 07:41:13 -0700701 : fVSVaryingName(nullptr)
702 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000703 , fCachedFocal(SK_ScalarMax) {}
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000704
fmenozzi55d318d2016-08-09 08:05:57 -0700705void FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -0700706 const FocalInside2PtConicalEffect& ge = args.fFp.cast<FocalInside2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -0800707 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
708 this->emitUniforms(uniformHandler, ge);
cdalton5e58cee2016-02-11 12:49:47 -0800709 fFocalUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800710 kFloat_GrSLType, kDefault_GrSLPrecision,
711 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000712 SkString tName("t");
713
714 // this is the distance along x-axis from the end center to focal point in
715 // transformed coordinates
Brian Salomon99938a82016-11-21 13:41:08 -0500716 GrShaderVar focal = uniformHandler->getUniformVariable(fFocalUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000717
718 // if we have a vec3 from being in perspective, convert it to a vec2 first
cdalton85285412016-02-18 12:37:07 -0800719 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -0700720 SkString coords2DString = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +0000721 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000722
723 // t = p.x * focalX + length(p)
egdaniel4ca2e602015-11-18 08:01:26 -0800724 fragBuilder->codeAppendf("\tfloat %s = %s.x * %s + length(%s);\n", tName.c_str(),
egdaniel7ea439b2015-12-03 09:20:44 -0800725 coords2D, focal.c_str(), coords2D);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000726
egdaniel7ea439b2015-12-03 09:20:44 -0800727 this->emitColor(fragBuilder,
728 uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500729 args.fShaderCaps,
egdaniel4ca2e602015-11-18 08:01:26 -0800730 ge,
731 tName.c_str(),
732 args.fOutputColor,
733 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -0700734 args.fTexSamplers);
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000735}
736
fmenozzi55d318d2016-08-09 08:05:57 -0700737void FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::onSetData(
Brian Salomonab015ef2017-04-04 10:15:51 -0400738 const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -0700739 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -0700740 const FocalInside2PtConicalEffect& data = processor.cast<FocalInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000741 SkScalar focal = data.focal();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000742
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000743 if (fCachedFocal != focal) {
kkinnunen7510b222014-07-30 00:04:16 -0700744 pdman.set1f(fFocalUni, SkScalarToFloat(focal));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000745 fCachedFocal = focal;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000746 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000747}
748
fmenozzi55d318d2016-08-09 08:05:57 -0700749void FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::GenKey(
750 const GrProcessor& processor,
Brian Salomon94efbf52016-11-29 13:43:05 -0500751 const GrShaderCaps&, GrProcessorKeyBuilder* b) {
joshualittb0a8a372014-09-23 09:50:21 -0700752 b->add32(GenBaseGradientKey(processor));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000753}
754
755//////////////////////////////////////////////////////////////////////////////
756// Circle Conical Gradients
757//////////////////////////////////////////////////////////////////////////////
758
759struct CircleConicalInfo {
760 SkPoint fCenterEnd;
761 SkScalar fA;
762 SkScalar fB;
763 SkScalar fC;
764};
765
766// Returns focal distance along x-axis in transformed coords
767static ConicalType set_matrix_circle_conical(const SkTwoPointConicalGradient& shader,
768 SkMatrix* invLMatrix, CircleConicalInfo* info) {
769 // Inverse of the current local matrix is passed in then,
770 // translate and scale such that start circle is on the origin and has radius 1
771 const SkPoint& centerStart = shader.getStartCenter();
772 const SkPoint& centerEnd = shader.getEndCenter();
773 SkScalar radiusStart = shader.getStartRadius();
774 SkScalar radiusEnd = shader.getEndRadius();
775
776 SkMatrix matrix;
777
778 matrix.setTranslate(-centerStart.fX, -centerStart.fY);
779
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000780 SkScalar invStartRad = 1.f / radiusStart;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000781 matrix.postScale(invStartRad, invStartRad);
782
783 radiusEnd /= radiusStart;
784
785 SkPoint centerEndTrans;
786 matrix.mapPoints(&centerEndTrans, &centerEnd, 1);
787
788 SkScalar A = centerEndTrans.fX * centerEndTrans.fX + centerEndTrans.fY * centerEndTrans.fY
789 - radiusEnd * radiusEnd + 2 * radiusEnd - 1;
790
791 // Check to see if start circle is inside end circle with edges touching.
792 // If touching we return that it is of kEdge_ConicalType, and leave the matrix setting
egdaniel8405ef92014-06-09 11:57:28 -0700793 // to the edge shader. kEdgeErrorTol = 5 * kErrorTol was picked after manual testing
794 // so that C = 1 / A is stable, and the linear approximation used in the Edge shader is
795 // still accurate.
796 if (SkScalarAbs(A) < kEdgeErrorTol) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000797 return kEdge_ConicalType;
798 }
799
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000800 SkScalar C = 1.f / A;
801 SkScalar B = (radiusEnd - 1.f) * C;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000802
803 matrix.postScale(C, C);
804
805 invLMatrix->postConcat(matrix);
806
807 info->fCenterEnd = centerEndTrans;
808 info->fA = A;
809 info->fB = B;
810 info->fC = C;
811
812 // 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 +0000813 if (A < 0.f) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000814 return kInside_ConicalType;
815 }
816 return kOutside_ConicalType;
817}
818
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000819class CircleInside2PtConicalEffect : public GrGradientEffect {
820public:
fmenozzi55d318d2016-08-09 08:05:57 -0700821 class GLSLCircleInside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000822
brianosman9557c272016-09-15 06:59:15 -0700823 static sk_sp<GrFragmentProcessor> Make(const CreateArgs& args, const CircleConicalInfo& info) {
bungeman06ca8ec2016-06-09 08:01:03 -0700824 return sk_sp<GrFragmentProcessor>(
brianosman9557c272016-09-15 06:59:15 -0700825 new CircleInside2PtConicalEffect(args, info));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000826 }
827
Brian Salomond3b65972017-03-22 12:05:03 -0400828 ~CircleInside2PtConicalEffect() override {}
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000829
mtklein36352bf2015-03-25 18:17:31 -0700830 const char* name() const override { return "Two-Point Conical Gradient Inside"; }
joshualitteb2a6762014-12-04 11:35:33 -0800831
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000832 SkScalar centerX() const { return fInfo.fCenterEnd.fX; }
833 SkScalar centerY() const { return fInfo.fCenterEnd.fY; }
834 SkScalar A() const { return fInfo.fA; }
835 SkScalar B() const { return fInfo.fB; }
836 SkScalar C() const { return fInfo.fC; }
837
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000838private:
egdaniel57d3b032015-11-13 11:57:27 -0800839 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -0700840
Brian Salomon94efbf52016-11-29 13:43:05 -0500841 virtual void onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800842 GrProcessorKeyBuilder* b) const override;
wangyix4b3050b2015-08-04 07:59:37 -0700843
mtklein36352bf2015-03-25 18:17:31 -0700844 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -0700845 const CircleInside2PtConicalEffect& s = sBase.cast<CircleInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000846 return (INHERITED::onIsEqual(sBase) &&
847 this->fInfo.fCenterEnd == s.fInfo.fCenterEnd &&
848 this->fInfo.fA == s.fInfo.fA &&
849 this->fInfo.fB == s.fInfo.fB &&
850 this->fInfo.fC == s.fInfo.fC);
851 }
852
brianosman9557c272016-09-15 06:59:15 -0700853 CircleInside2PtConicalEffect(const CreateArgs& args, const CircleConicalInfo& info)
Brian Salomon587e08f2017-01-27 10:59:27 -0500854 : INHERITED(args, args.fShader->colorsAreOpaque()), fInfo(info) {
joshualitteb2a6762014-12-04 11:35:33 -0800855 this->initClassID<CircleInside2PtConicalEffect>();
856 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000857
joshualittb0a8a372014-09-23 09:50:21 -0700858 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000859
860 const CircleConicalInfo fInfo;
861
862 typedef GrGradientEffect INHERITED;
863};
864
fmenozzi55d318d2016-08-09 08:05:57 -0700865class CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor
866 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000867public:
fmenozzi55d318d2016-08-09 08:05:57 -0700868 GLSLCircleInside2PtConicalProcessor(const GrProcessor&);
Brian Salomond3b65972017-03-22 12:05:03 -0400869 ~GLSLCircleInside2PtConicalProcessor() override {}
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000870
wangyix7c157a92015-07-22 15:08:53 -0700871 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000872
Brian Salomon94efbf52016-11-29 13:43:05 -0500873 static void GenKey(const GrProcessor&, const GrShaderCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000874
875protected:
Brian Salomonab015ef2017-04-04 10:15:51 -0400876 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -0700877
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000878 UniformHandle fCenterUni;
879 UniformHandle fParamUni;
880
881 const char* fVSVaryingName;
882 const char* fFSVaryingName;
883
884 // @{
885 /// Values last uploaded as uniforms
886
887 SkScalar fCachedCenterX;
888 SkScalar fCachedCenterY;
889 SkScalar fCachedA;
890 SkScalar fCachedB;
891 SkScalar fCachedC;
892
893 // @}
894
895private:
fmenozzi55d318d2016-08-09 08:05:57 -0700896 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000897
898};
899
Brian Salomon94efbf52016-11-29 13:43:05 -0500900void CircleInside2PtConicalEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -0800901 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -0700902 CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800903}
904
egdaniel57d3b032015-11-13 11:57:27 -0800905GrGLSLFragmentProcessor* CircleInside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -0700906 return new CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000907}
908
joshualittb0a8a372014-09-23 09:50:21 -0700909GR_DEFINE_FRAGMENT_PROCESSOR_TEST(CircleInside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000910
joshualitt01258472014-09-22 10:29:30 -0700911/*
912 * All Two point conical gradient test create functions may occasionally create edge case shaders
913 */
Hal Canary6f6961e2017-01-31 13:50:44 -0500914#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -0700915sk_sp<GrFragmentProcessor> CircleInside2PtConicalEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700916 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
917 SkScalar radius1 = d->fRandom->nextUScalar1() + 0.0001f; // make sure radius1 != 0
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000918 SkPoint center2;
919 SkScalar radius2;
920 do {
joshualitt0067ff52015-07-08 14:26:19 -0700921 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000922 // Below makes sure that circle one is contained within circle two
joshualitt0067ff52015-07-08 14:26:19 -0700923 SkScalar increase = d->fRandom->nextUScalar1();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000924 SkPoint diff = center2 - center1;
925 SkScalar diffLen = diff.length();
926 radius2 = radius1 + diffLen + increase;
927 // If the circles are identical the factory will give us an empty shader.
928 } while (radius1 == radius2 && center1 == center2);
929
Brian Osman3f748602016-10-03 18:29:03 -0400930 RandomGradientParams params(d->fRandom);
Brian Osmana2196532016-10-17 12:48:13 -0400931 auto shader = params.fUseColors4f ?
932 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
933 params.fColors4f, params.fColorSpace, params.fStops,
934 params.fColorCount, params.fTileMode) :
935 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
936 params.fColors, params.fStops,
937 params.fColorCount, params.fTileMode);
Brian Osman9f532a32016-10-19 11:12:09 -0400938 GrTest::TestAsFPArgs asFPArgs(d);
939 sk_sp<GrFragmentProcessor> fp = shader->asFragmentProcessor(asFPArgs.args());
bsalomonc21b09e2015-08-28 18:46:56 -0700940 GrAlwaysAssert(fp);
joshualitt8ca93e72015-07-08 06:51:43 -0700941 return fp;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000942}
Hal Canary6f6961e2017-01-31 13:50:44 -0500943#endif
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000944
fmenozzi55d318d2016-08-09 08:05:57 -0700945CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor
946 ::GLSLCircleInside2PtConicalProcessor(const GrProcessor& processor)
halcanary96fcdcc2015-08-27 07:41:13 -0700947 : fVSVaryingName(nullptr)
948 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000949 , fCachedCenterX(SK_ScalarMax)
950 , fCachedCenterY(SK_ScalarMax)
951 , fCachedA(SK_ScalarMax)
952 , fCachedB(SK_ScalarMax)
953 , fCachedC(SK_ScalarMax) {}
954
fmenozzi55d318d2016-08-09 08:05:57 -0700955void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -0700956 const CircleInside2PtConicalEffect& ge = args.fFp.cast<CircleInside2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -0800957 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
958 this->emitUniforms(uniformHandler, ge);
cdalton5e58cee2016-02-11 12:49:47 -0800959 fCenterUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800960 kVec2f_GrSLType, kDefault_GrSLPrecision,
961 "Conical2FSCenter");
cdalton5e58cee2016-02-11 12:49:47 -0800962 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800963 kVec3f_GrSLType, kDefault_GrSLPrecision,
964 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000965 SkString tName("t");
966
Brian Salomon99938a82016-11-21 13:41:08 -0500967 GrShaderVar center = uniformHandler->getUniformVariable(fCenterUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000968 // params.x = A
969 // params.y = B
970 // params.z = C
Brian Salomon99938a82016-11-21 13:41:08 -0500971 GrShaderVar params = uniformHandler->getUniformVariable(fParamUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000972
973 // if we have a vec3 from being in perspective, convert it to a vec2 first
cdalton85285412016-02-18 12:37:07 -0800974 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -0700975 SkString coords2DString = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +0000976 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000977
978 // p = coords2D
979 // e = center end
980 // r = radius end
981 // A = dot(e, e) - r^2 + 2 * r - 1
982 // B = (r -1) / A
983 // C = 1 / A
984 // d = dot(e, p) + B
985 // t = d +/- sqrt(d^2 - A * dot(p, p) + C)
egdaniel4ca2e602015-11-18 08:01:26 -0800986 fragBuilder->codeAppendf("\tfloat pDotp = dot(%s, %s);\n", coords2D, coords2D);
987 fragBuilder->codeAppendf("\tfloat d = dot(%s, %s) + %s.y;\n", coords2D, center.c_str(),
988 params.c_str());
989 fragBuilder->codeAppendf("\tfloat %s = d + sqrt(d * d - %s.x * pDotp + %s.z);\n",
990 tName.c_str(), params.c_str(), params.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000991
egdaniel7ea439b2015-12-03 09:20:44 -0800992 this->emitColor(fragBuilder,
993 uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -0500994 args.fShaderCaps,
egdaniel4ca2e602015-11-18 08:01:26 -0800995 ge,
996 tName.c_str(),
997 args.fOutputColor,
998 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -0700999 args.fTexSamplers);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001000}
1001
fmenozzi55d318d2016-08-09 08:05:57 -07001002void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::onSetData(
Brian Salomonab015ef2017-04-04 10:15:51 -04001003 const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -07001004 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -07001005 const CircleInside2PtConicalEffect& data = processor.cast<CircleInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001006 SkScalar centerX = data.centerX();
1007 SkScalar centerY = data.centerY();
1008 SkScalar A = data.A();
1009 SkScalar B = data.B();
1010 SkScalar C = data.C();
1011
1012 if (fCachedCenterX != centerX || fCachedCenterY != centerY ||
1013 fCachedA != A || fCachedB != B || fCachedC != C) {
1014
kkinnunen7510b222014-07-30 00:04:16 -07001015 pdman.set2f(fCenterUni, SkScalarToFloat(centerX), SkScalarToFloat(centerY));
1016 pdman.set3f(fParamUni, SkScalarToFloat(A), SkScalarToFloat(B), SkScalarToFloat(C));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001017
1018 fCachedCenterX = centerX;
1019 fCachedCenterY = centerY;
1020 fCachedA = A;
1021 fCachedB = B;
1022 fCachedC = C;
1023 }
1024}
1025
fmenozzi55d318d2016-08-09 08:05:57 -07001026void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::GenKey(
1027 const GrProcessor& processor,
Brian Salomon94efbf52016-11-29 13:43:05 -05001028 const GrShaderCaps&, GrProcessorKeyBuilder* b) {
joshualittb0a8a372014-09-23 09:50:21 -07001029 b->add32(GenBaseGradientKey(processor));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001030}
1031
1032//////////////////////////////////////////////////////////////////////////////
1033
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001034class CircleOutside2PtConicalEffect : public GrGradientEffect {
1035public:
fmenozzi55d318d2016-08-09 08:05:57 -07001036 class GLSLCircleOutside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001037
brianosman9557c272016-09-15 06:59:15 -07001038 static sk_sp<GrFragmentProcessor> Make(const CreateArgs& args, const CircleConicalInfo& info) {
bungeman06ca8ec2016-06-09 08:01:03 -07001039 return sk_sp<GrFragmentProcessor>(
brianosman9557c272016-09-15 06:59:15 -07001040 new CircleOutside2PtConicalEffect(args, info));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001041 }
1042
Brian Salomond3b65972017-03-22 12:05:03 -04001043 ~CircleOutside2PtConicalEffect() override {}
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001044
mtklein36352bf2015-03-25 18:17:31 -07001045 const char* name() const override { return "Two-Point Conical Gradient Outside"; }
joshualitteb2a6762014-12-04 11:35:33 -08001046
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001047 SkScalar centerX() const { return fInfo.fCenterEnd.fX; }
1048 SkScalar centerY() const { return fInfo.fCenterEnd.fY; }
1049 SkScalar A() const { return fInfo.fA; }
1050 SkScalar B() const { return fInfo.fB; }
1051 SkScalar C() const { return fInfo.fC; }
1052 SkScalar tLimit() const { return fTLimit; }
1053 bool isFlipped() const { return fIsFlipped; }
1054
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001055private:
egdaniel57d3b032015-11-13 11:57:27 -08001056 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -07001057
Brian Salomon94efbf52016-11-29 13:43:05 -05001058 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -07001059
mtklein36352bf2015-03-25 18:17:31 -07001060 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -07001061 const CircleOutside2PtConicalEffect& s = sBase.cast<CircleOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001062 return (INHERITED::onIsEqual(sBase) &&
1063 this->fInfo.fCenterEnd == s.fInfo.fCenterEnd &&
1064 this->fInfo.fA == s.fInfo.fA &&
1065 this->fInfo.fB == s.fInfo.fB &&
1066 this->fInfo.fC == s.fInfo.fC &&
1067 this->fTLimit == s.fTLimit &&
1068 this->fIsFlipped == s.fIsFlipped);
1069 }
1070
brianosman9557c272016-09-15 06:59:15 -07001071 CircleOutside2PtConicalEffect(const CreateArgs& args, const CircleConicalInfo& info)
Brian Salomon587e08f2017-01-27 10:59:27 -05001072 : INHERITED(args, false /* opaque: draws transparent black outside of the cone. */)
1073 , fInfo(info) {
joshualitteb2a6762014-12-04 11:35:33 -08001074 this->initClassID<CircleOutside2PtConicalEffect>();
brianosman9557c272016-09-15 06:59:15 -07001075 const SkTwoPointConicalGradient& shader =
1076 *static_cast<const SkTwoPointConicalGradient*>(args.fShader);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001077 if (shader.getStartRadius() != shader.getEndRadius()) {
reed80ea19c2015-05-12 10:37:34 -07001078 fTLimit = shader.getStartRadius() / (shader.getStartRadius() - shader.getEndRadius());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001079 } else {
1080 fTLimit = SK_ScalarMin;
1081 }
1082
1083 fIsFlipped = shader.isFlippedGrad();
1084 }
1085
joshualittb0a8a372014-09-23 09:50:21 -07001086 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001087
1088 const CircleConicalInfo fInfo;
1089 SkScalar fTLimit;
1090 bool fIsFlipped;
1091
1092 typedef GrGradientEffect INHERITED;
1093};
1094
fmenozzi55d318d2016-08-09 08:05:57 -07001095class CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor
1096 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001097public:
fmenozzi55d318d2016-08-09 08:05:57 -07001098 GLSLCircleOutside2PtConicalProcessor(const GrProcessor&);
Brian Salomond3b65972017-03-22 12:05:03 -04001099 ~GLSLCircleOutside2PtConicalProcessor() override {}
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001100
wangyix7c157a92015-07-22 15:08:53 -07001101 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001102
Brian Salomon94efbf52016-11-29 13:43:05 -05001103 static void GenKey(const GrProcessor&, const GrShaderCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001104
1105protected:
Brian Salomonab015ef2017-04-04 10:15:51 -04001106 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -07001107
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001108 UniformHandle fCenterUni;
1109 UniformHandle fParamUni;
1110
1111 const char* fVSVaryingName;
1112 const char* fFSVaryingName;
1113
1114 bool fIsFlipped;
1115
1116 // @{
1117 /// Values last uploaded as uniforms
1118
1119 SkScalar fCachedCenterX;
1120 SkScalar fCachedCenterY;
1121 SkScalar fCachedA;
1122 SkScalar fCachedB;
1123 SkScalar fCachedC;
1124 SkScalar fCachedTLimit;
1125
1126 // @}
1127
1128private:
fmenozzi55d318d2016-08-09 08:05:57 -07001129 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001130
1131};
1132
Brian Salomon94efbf52016-11-29 13:43:05 -05001133void CircleOutside2PtConicalEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
egdaniel57d3b032015-11-13 11:57:27 -08001134 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -07001135 CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -08001136}
1137
egdaniel57d3b032015-11-13 11:57:27 -08001138GrGLSLFragmentProcessor* CircleOutside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -07001139 return new CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001140}
1141
joshualittb0a8a372014-09-23 09:50:21 -07001142GR_DEFINE_FRAGMENT_PROCESSOR_TEST(CircleOutside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001143
joshualitt01258472014-09-22 10:29:30 -07001144/*
1145 * All Two point conical gradient test create functions may occasionally create edge case shaders
1146 */
Hal Canary6f6961e2017-01-31 13:50:44 -05001147#if GR_TEST_UTILS
bungeman06ca8ec2016-06-09 08:01:03 -07001148sk_sp<GrFragmentProcessor> CircleOutside2PtConicalEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -07001149 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
1150 SkScalar radius1 = d->fRandom->nextUScalar1() + 0.0001f; // make sure radius1 != 0
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001151 SkPoint center2;
1152 SkScalar radius2;
1153 SkScalar diffLen;
1154 do {
joshualitt0067ff52015-07-08 14:26:19 -07001155 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001156 // If the circles share a center than we can't be in the outside case
1157 } while (center1 == center2);
joshualitt01258472014-09-22 10:29:30 -07001158 SkPoint diff = center2 - center1;
1159 diffLen = diff.length();
1160 // Below makes sure that circle one is not contained within circle two
1161 // and have radius2 >= radius to match sorting on cpu side
joshualitt0067ff52015-07-08 14:26:19 -07001162 radius2 = radius1 + d->fRandom->nextRangeF(0.f, diffLen);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001163
Brian Osman3f748602016-10-03 18:29:03 -04001164 RandomGradientParams params(d->fRandom);
Brian Osmana2196532016-10-17 12:48:13 -04001165 auto shader = params.fUseColors4f ?
1166 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
1167 params.fColors4f, params.fColorSpace, params.fStops,
1168 params.fColorCount, params.fTileMode) :
1169 SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
1170 params.fColors, params.fStops,
1171 params.fColorCount, params.fTileMode);
Brian Osman9f532a32016-10-19 11:12:09 -04001172 GrTest::TestAsFPArgs asFPArgs(d);
1173 sk_sp<GrFragmentProcessor> fp = shader->asFragmentProcessor(asFPArgs.args());
bsalomonc21b09e2015-08-28 18:46:56 -07001174 GrAlwaysAssert(fp);
joshualitt8ca93e72015-07-08 06:51:43 -07001175 return fp;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001176}
Hal Canary6f6961e2017-01-31 13:50:44 -05001177#endif
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001178
fmenozzi55d318d2016-08-09 08:05:57 -07001179CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor
1180 ::GLSLCircleOutside2PtConicalProcessor(const GrProcessor& processor)
halcanary96fcdcc2015-08-27 07:41:13 -07001181 : fVSVaryingName(nullptr)
1182 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001183 , fCachedCenterX(SK_ScalarMax)
1184 , fCachedCenterY(SK_ScalarMax)
1185 , fCachedA(SK_ScalarMax)
1186 , fCachedB(SK_ScalarMax)
1187 , fCachedC(SK_ScalarMax)
1188 , fCachedTLimit(SK_ScalarMax) {
joshualittb0a8a372014-09-23 09:50:21 -07001189 const CircleOutside2PtConicalEffect& data = processor.cast<CircleOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001190 fIsFlipped = data.isFlipped();
1191 }
1192
fmenozzi55d318d2016-08-09 08:05:57 -07001193void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -07001194 const CircleOutside2PtConicalEffect& ge = args.fFp.cast<CircleOutside2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -08001195 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
1196 this->emitUniforms(uniformHandler, ge);
cdalton5e58cee2016-02-11 12:49:47 -08001197 fCenterUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001198 kVec2f_GrSLType, kDefault_GrSLPrecision,
1199 "Conical2FSCenter");
cdalton5e58cee2016-02-11 12:49:47 -08001200 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001201 kVec4f_GrSLType, kDefault_GrSLPrecision,
1202 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001203 SkString tName("t");
1204
Brian Salomon99938a82016-11-21 13:41:08 -05001205 GrShaderVar center = uniformHandler->getUniformVariable(fCenterUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001206 // params.x = A
1207 // params.y = B
1208 // params.z = C
Brian Salomon99938a82016-11-21 13:41:08 -05001209 GrShaderVar params = uniformHandler->getUniformVariable(fParamUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001210
1211 // if we have a vec3 from being in perspective, convert it to a vec2 first
cdalton85285412016-02-18 12:37:07 -08001212 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -07001213 SkString coords2DString = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +00001214 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001215
1216 // output will default to transparent black (we simply won't write anything
1217 // else to it if invalid, instead of discarding or returning prematurely)
egdaniel4ca2e602015-11-18 08:01:26 -08001218 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 +00001219
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001220 // p = coords2D
1221 // e = center end
1222 // r = radius end
1223 // A = dot(e, e) - r^2 + 2 * r - 1
1224 // B = (r -1) / A
1225 // C = 1 / A
1226 // d = dot(e, p) + B
1227 // t = d +/- sqrt(d^2 - A * dot(p, p) + C)
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001228
egdaniel4ca2e602015-11-18 08:01:26 -08001229 fragBuilder->codeAppendf("\tfloat pDotp = dot(%s, %s);\n", coords2D, coords2D);
1230 fragBuilder->codeAppendf("\tfloat d = dot(%s, %s) + %s.y;\n", coords2D, center.c_str(),
1231 params.c_str());
1232 fragBuilder->codeAppendf("\tfloat deter = d * d - %s.x * pDotp + %s.z;\n", params.c_str(),
1233 params.c_str());
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001234
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001235 // Must check to see if we flipped the circle order (to make sure start radius < end radius)
1236 // If so we must also flip sign on sqrt
1237 if (!fIsFlipped) {
egdaniel4ca2e602015-11-18 08:01:26 -08001238 fragBuilder->codeAppendf("\tfloat %s = d + sqrt(deter);\n", tName.c_str());
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001239 } else {
egdaniel4ca2e602015-11-18 08:01:26 -08001240 fragBuilder->codeAppendf("\tfloat %s = d - sqrt(deter);\n", tName.c_str());
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001241 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001242
egdaniel7ea439b2015-12-03 09:20:44 -08001243 fragBuilder->codeAppendf("\tif (%s >= %s.w && deter >= 0.0) {\n",
1244 tName.c_str(), params.c_str());
egdaniel4ca2e602015-11-18 08:01:26 -08001245 fragBuilder->codeAppend("\t\t");
egdaniel7ea439b2015-12-03 09:20:44 -08001246 this->emitColor(fragBuilder,
1247 uniformHandler,
Brian Salomon1edc5b92016-11-29 13:43:46 -05001248 args.fShaderCaps,
egdaniel4ca2e602015-11-18 08:01:26 -08001249 ge,
1250 tName.c_str(),
1251 args.fOutputColor,
1252 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -07001253 args.fTexSamplers);
egdaniel4ca2e602015-11-18 08:01:26 -08001254 fragBuilder->codeAppend("\t}\n");
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001255}
1256
fmenozzi55d318d2016-08-09 08:05:57 -07001257void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::onSetData(
Brian Salomonab015ef2017-04-04 10:15:51 -04001258 const GrGLSLProgramDataManager& pdman, const GrFragmentProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -07001259 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -07001260 const CircleOutside2PtConicalEffect& data = processor.cast<CircleOutside2PtConicalEffect>();
commit-bot@chromium.org44d83c12014-04-21 13:10:25 +00001261 SkASSERT(data.isFlipped() == fIsFlipped);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001262 SkScalar centerX = data.centerX();
1263 SkScalar centerY = data.centerY();
1264 SkScalar A = data.A();
1265 SkScalar B = data.B();
1266 SkScalar C = data.C();
1267 SkScalar tLimit = data.tLimit();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001268
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001269 if (fCachedCenterX != centerX || fCachedCenterY != centerY ||
1270 fCachedA != A || fCachedB != B || fCachedC != C || fCachedTLimit != tLimit) {
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001271
kkinnunen7510b222014-07-30 00:04:16 -07001272 pdman.set2f(fCenterUni, SkScalarToFloat(centerX), SkScalarToFloat(centerY));
1273 pdman.set4f(fParamUni, SkScalarToFloat(A), SkScalarToFloat(B), SkScalarToFloat(C),
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001274 SkScalarToFloat(tLimit));
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001275
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001276 fCachedCenterX = centerX;
1277 fCachedCenterY = centerY;
1278 fCachedA = A;
1279 fCachedB = B;
1280 fCachedC = C;
1281 fCachedTLimit = tLimit;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001282 }
1283}
1284
fmenozzi55d318d2016-08-09 08:05:57 -07001285void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::GenKey(
1286 const GrProcessor& processor,
Brian Salomon94efbf52016-11-29 13:43:05 -05001287 const GrShaderCaps&, GrProcessorKeyBuilder* b) {
bsalomon63e99f72014-07-21 08:03:14 -07001288 uint32_t* key = b->add32n(2);
joshualittb0a8a372014-09-23 09:50:21 -07001289 key[0] = GenBaseGradientKey(processor);
1290 key[1] = processor.cast<CircleOutside2PtConicalEffect>().isFlipped();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001291}
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001292
1293//////////////////////////////////////////////////////////////////////////////
1294
brianosman9557c272016-09-15 06:59:15 -07001295sk_sp<GrFragmentProcessor> Gr2PtConicalGradientEffect::Make(
1296 const GrGradientEffect::CreateArgs& args) {
1297 const SkTwoPointConicalGradient& shader =
1298 *static_cast<const SkTwoPointConicalGradient*>(args.fShader);
1299
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001300 SkMatrix matrix;
1301 if (!shader.getLocalMatrix().invert(&matrix)) {
halcanary96fcdcc2015-08-27 07:41:13 -07001302 return nullptr;
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001303 }
brianosman9557c272016-09-15 06:59:15 -07001304 if (args.fMatrix) {
commit-bot@chromium.org96fb7482014-05-09 20:28:11 +00001305 SkMatrix inv;
brianosman9557c272016-09-15 06:59:15 -07001306 if (!args.fMatrix->invert(&inv)) {
halcanary96fcdcc2015-08-27 07:41:13 -07001307 return nullptr;
commit-bot@chromium.org96fb7482014-05-09 20:28:11 +00001308 }
1309 matrix.postConcat(inv);
1310 }
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001311
brianosmanb9c51372016-09-15 11:09:45 -07001312 GrGradientEffect::CreateArgs newArgs(args.fContext, args.fShader, &matrix, args.fTileMode,
1313 std::move(args.fColorSpaceXform), args.fGammaCorrect);
brianosman9557c272016-09-15 06:59:15 -07001314
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001315 if (shader.getStartRadius() < kErrorTol) {
1316 SkScalar focalX;
1317 ConicalType type = set_matrix_focal_conical(shader, &matrix, &focalX);
1318 if (type == kInside_ConicalType) {
brianosman9557c272016-09-15 06:59:15 -07001319 return FocalInside2PtConicalEffect::Make(newArgs, focalX);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001320 } else if(type == kEdge_ConicalType) {
1321 set_matrix_edge_conical(shader, &matrix);
brianosman9557c272016-09-15 06:59:15 -07001322 return Edge2PtConicalEffect::Make(newArgs);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001323 } else {
brianosman9557c272016-09-15 06:59:15 -07001324 return FocalOutside2PtConicalEffect::Make(newArgs, focalX);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001325 }
1326 }
1327
1328 CircleConicalInfo info;
1329 ConicalType type = set_matrix_circle_conical(shader, &matrix, &info);
1330
1331 if (type == kInside_ConicalType) {
brianosman9557c272016-09-15 06:59:15 -07001332 return CircleInside2PtConicalEffect::Make(newArgs, info);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001333 } else if (type == kEdge_ConicalType) {
1334 set_matrix_edge_conical(shader, &matrix);
brianosman9557c272016-09-15 06:59:15 -07001335 return Edge2PtConicalEffect::Make(newArgs);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001336 } else {
brianosman9557c272016-09-15 06:59:15 -07001337 return CircleOutside2PtConicalEffect::Make(newArgs, info);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001338 }
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001339}
1340
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001341#endif