blob: e89193ff550974069c2f79fecdd4615f3346b5b1 [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#include "SkTwoPointConicalGradient_gpu.h"
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00009
10#include "SkTwoPointConicalGradient.h"
11
commit-bot@chromium.orgef93d292014-04-10 15:37:52 +000012#if SK_SUPPORT_GPU
egdaniel7ea439b2015-12-03 09:20:44 -080013#include "GrCoordTransform.h"
14#include "GrInvariantOutput.h"
joshualitt8ca93e72015-07-08 06:51:43 -070015#include "GrPaint.h"
egdaniel2d721d32015-11-11 13:06:05 -080016#include "glsl/GrGLSLFragmentShaderBuilder.h"
egdaniel018fb622015-10-28 07:26:40 -070017#include "glsl/GrGLSLProgramDataManager.h"
egdaniel7ea439b2015-12-03 09:20:44 -080018#include "glsl/GrGLSLUniformHandler.h"
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;
55 rot.setSinCos(-SkScalarMul(invDiffLen, diff.fY),
56 SkScalarMul(invDiffLen, diff.fX));
57 invLMatrix->postConcat(rot);
58 }
59}
60
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +000061class Edge2PtConicalEffect : public GrGradientEffect {
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +000062public:
fmenozzi55d318d2016-08-09 08:05:57 -070063 class GLSLEdge2PtConicalProcessor;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +000064
bungeman06ca8ec2016-06-09 08:01:03 -070065 static sk_sp<GrFragmentProcessor> Make(GrContext* ctx,
66 const SkTwoPointConicalGradient& shader,
67 const SkMatrix& matrix,
68 SkShader::TileMode tm) {
69 return sk_sp<GrFragmentProcessor>(new Edge2PtConicalEffect(ctx, shader, matrix, tm));
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000070 }
71
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +000072 virtual ~Edge2PtConicalEffect() {}
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000073
mtklein36352bf2015-03-25 18:17:31 -070074 const char* name() const override {
joshualitteb2a6762014-12-04 11:35:33 -080075 return "Two-Point Conical Gradient Edge Touching";
76 }
77
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000078 // The radial gradient parameters can collapse to a linear (instead of quadratic) equation.
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000079 SkScalar center() const { return fCenterX1; }
80 SkScalar diffRadius() const { return fDiffRadius; }
81 SkScalar radius() const { return fRadius0; }
82
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000083private:
egdaniel57d3b032015-11-13 11:57:27 -080084 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -070085
egdaniel57d3b032015-11-13 11:57:27 -080086 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -070087
mtklein36352bf2015-03-25 18:17:31 -070088 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -070089 const Edge2PtConicalEffect& s = sBase.cast<Edge2PtConicalEffect>();
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000090 return (INHERITED::onIsEqual(sBase) &&
91 this->fCenterX1 == s.fCenterX1 &&
92 this->fRadius0 == s.fRadius0 &&
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +000093 this->fDiffRadius == s.fDiffRadius);
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +000094 }
95
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +000096 Edge2PtConicalEffect(GrContext* ctx,
97 const SkTwoPointConicalGradient& shader,
98 const SkMatrix& matrix,
99 SkShader::TileMode tm)
bsalomon4a339522015-10-06 08:40:50 -0700100 : INHERITED(ctx, shader, matrix, tm),
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +0000101 fCenterX1(shader.getCenterX1()),
102 fRadius0(shader.getStartRadius()),
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000103 fDiffRadius(shader.getDiffRadius()){
joshualitteb2a6762014-12-04 11:35:33 -0800104 this->initClassID<Edge2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000105 // We should only be calling this shader if we are degenerate case with touching circles
egdaniel8405ef92014-06-09 11:57:28 -0700106 // When deciding if we are in edge case, we scaled by the end radius for cases when the
joshualitt01258472014-09-22 10:29:30 -0700107 // start radius was close to zero, otherwise we scaled by the start radius. In addition
108 // Our test for the edge case in set_matrix_circle_conical has a higher tolerance so we
109 // need the sqrt value below
110 SkASSERT(SkScalarAbs(SkScalarAbs(fDiffRadius) - fCenterX1) <
111 (fRadius0 < kErrorTol ? shader.getEndRadius() * kEdgeErrorTol :
112 fRadius0 * sqrt(kEdgeErrorTol)));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000113
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +0000114 // We pass the linear part of the quadratic as a varying.
115 // float b = -2.0 * (fCenterX1 * x + fRadius0 * fDiffRadius * z)
116 fBTransform = this->getCoordTransform();
117 SkMatrix& bMatrix = *fBTransform.accessMatrix();
118 SkScalar r0dr = SkScalarMul(fRadius0, fDiffRadius);
119 bMatrix[SkMatrix::kMScaleX] = -2 * (SkScalarMul(fCenterX1, bMatrix[SkMatrix::kMScaleX]) +
120 SkScalarMul(r0dr, bMatrix[SkMatrix::kMPersp0]));
121 bMatrix[SkMatrix::kMSkewX] = -2 * (SkScalarMul(fCenterX1, bMatrix[SkMatrix::kMSkewX]) +
122 SkScalarMul(r0dr, bMatrix[SkMatrix::kMPersp1]));
123 bMatrix[SkMatrix::kMTransX] = -2 * (SkScalarMul(fCenterX1, bMatrix[SkMatrix::kMTransX]) +
124 SkScalarMul(r0dr, bMatrix[SkMatrix::kMPersp2]));
125 this->addCoordTransform(&fBTransform);
126 }
127
joshualittb0a8a372014-09-23 09:50:21 -0700128 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +0000129
130 // @{
131 // Cache of values - these can change arbitrarily, EXCEPT
132 // we shouldn't change between degenerate and non-degenerate?!
133
134 GrCoordTransform fBTransform;
135 SkScalar fCenterX1;
136 SkScalar fRadius0;
137 SkScalar fDiffRadius;
138
139 // @}
140
141 typedef GrGradientEffect INHERITED;
142};
143
fmenozzi55d318d2016-08-09 08:05:57 -0700144class Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +0000145public:
fmenozzi55d318d2016-08-09 08:05:57 -0700146 GLSLEdge2PtConicalProcessor(const GrProcessor&);
147 virtual ~GLSLEdge2PtConicalProcessor() { }
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000148
wangyix7c157a92015-07-22 15:08:53 -0700149 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000150
jvanverthcfc18862015-04-28 08:48:20 -0700151 static void GenKey(const GrProcessor&, const GrGLSLCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000152
153protected:
egdaniel018fb622015-10-28 07:26:40 -0700154 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -0700155
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000156 UniformHandle fParamUni;
157
158 const char* fVSVaryingName;
159 const char* fFSVaryingName;
160
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000161 // @{
162 /// Values last uploaded as uniforms
163
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000164 SkScalar fCachedRadius;
165 SkScalar fCachedDiffRadius;
166
167 // @}
168
169private:
fmenozzi55d318d2016-08-09 08:05:57 -0700170 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000171
172};
173
egdaniel57d3b032015-11-13 11:57:27 -0800174void Edge2PtConicalEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
175 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -0700176 Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800177}
178
egdaniel57d3b032015-11-13 11:57:27 -0800179GrGLSLFragmentProcessor* Edge2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -0700180 return new Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor(*this);
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000181}
skia.committer@gmail.com221b9112014-04-04 03:04:32 +0000182
joshualittb0a8a372014-09-23 09:50:21 -0700183GR_DEFINE_FRAGMENT_PROCESSOR_TEST(Edge2PtConicalEffect);
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000184
joshualitt01258472014-09-22 10:29:30 -0700185/*
186 * All Two point conical gradient test create functions may occasionally create edge case shaders
187 */
bungeman06ca8ec2016-06-09 08:01:03 -0700188sk_sp<GrFragmentProcessor> Edge2PtConicalEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700189 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
190 SkScalar radius1 = d->fRandom->nextUScalar1();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000191 SkPoint center2;
192 SkScalar radius2;
193 do {
joshualitt0067ff52015-07-08 14:26:19 -0700194 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000195 // If the circles are identical the factory will give us an empty shader.
196 // This will happen if we pick identical centers
197 } while (center1 == center2);
198
199 // Below makes sure that circle one is contained within circle two
200 // and both circles are touching on an edge
201 SkPoint diff = center2 - center1;
202 SkScalar diffLen = diff.length();
203 radius2 = radius1 + diffLen;
204
205 SkColor colors[kMaxRandomGradientColors];
206 SkScalar stopsArray[kMaxRandomGradientColors];
207 SkScalar* stops = stopsArray;
208 SkShader::TileMode tm;
joshualitt0067ff52015-07-08 14:26:19 -0700209 int colorCount = RandomGradientParams(d->fRandom, colors, &stops, &tm);
reed8a21c9f2016-03-08 18:50:00 -0800210 auto shader = SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
211 colors, stops, colorCount, tm);
brianosman839345d2016-07-22 11:04:53 -0700212 SkMatrix viewMatrix = GrTest::TestMatrix(d->fRandom);
213 sk_sp<GrFragmentProcessor> fp = shader->asFragmentProcessor(SkShader::AsFPArgs(
brianosman1638c0d2016-07-25 05:12:53 -0700214 d->fContext, &viewMatrix, NULL, kNone_SkFilterQuality, nullptr,
215 SkSourceGammaTreatment::kRespect));
bsalomonc21b09e2015-08-28 18:46:56 -0700216 GrAlwaysAssert(fp);
joshualittb0a8a372014-09-23 09:50:21 -0700217 return fp;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000218}
219
fmenozzi55d318d2016-08-09 08:05:57 -0700220Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::GLSLEdge2PtConicalProcessor(const GrProcessor&)
halcanary96fcdcc2015-08-27 07:41:13 -0700221 : fVSVaryingName(nullptr)
222 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000223 , fCachedRadius(-SK_ScalarMax)
224 , fCachedDiffRadius(-SK_ScalarMax) {}
225
fmenozzi55d318d2016-08-09 08:05:57 -0700226void Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -0700227 const Edge2PtConicalEffect& ge = args.fFp.cast<Edge2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -0800228 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
229 this->emitUniforms(uniformHandler, ge);
jvanverthde11ee42016-02-26 13:58:40 -0800230 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
231 kVec3f_GrSLType, kDefault_GrSLPrecision,
232 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000233
234 SkString cName("c");
235 SkString tName("t");
236 SkString p0; // start radius
237 SkString p1; // start radius squared
238 SkString p2; // difference in radii (r1 - r0)
239
jvanverthde11ee42016-02-26 13:58:40 -0800240
241 p0.appendf("%s.x", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
242 p1.appendf("%s.y", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
243 p2.appendf("%s.z", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000244
245 // We interpolate the linear component in coords[1].
bsalomon1a1aa932016-09-12 09:30:36 -0700246 SkASSERT(args.fTransformedCoords[0].getType() == args.fTransformedCoords[1].getType());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000247 const char* coords2D;
248 SkString bVar;
cdalton85285412016-02-18 12:37:07 -0800249 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -0700250 if (kVec3f_GrSLType == args.fTransformedCoords[0].getType()) {
egdaniel4ca2e602015-11-18 08:01:26 -0800251 fragBuilder->codeAppendf("\tvec3 interpolants = vec3(%s.xy / %s.z, %s.x / %s.z);\n",
bsalomon1a1aa932016-09-12 09:30:36 -0700252 args.fTransformedCoords[0].c_str(),
253 args.fTransformedCoords[0].c_str(),
254 args.fTransformedCoords[1].c_str(),
255 args.fTransformedCoords[1].c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000256 coords2D = "interpolants.xy";
257 bVar = "interpolants.z";
258 } else {
bsalomon1a1aa932016-09-12 09:30:36 -0700259 coords2D = args.fTransformedCoords[0].c_str();
260 bVar.printf("%s.x", args.fTransformedCoords[1].c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000261 }
262
263 // output will default to transparent black (we simply won't write anything
264 // else to it if invalid, instead of discarding or returning prematurely)
egdaniel4ca2e602015-11-18 08:01:26 -0800265 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 +0000266
267 // c = (x^2)+(y^2) - params[1]
egdaniel4ca2e602015-11-18 08:01:26 -0800268 fragBuilder->codeAppendf("\tfloat %s = dot(%s, %s) - %s;\n",
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000269 cName.c_str(), coords2D, coords2D, p1.c_str());
270
271 // linear case: t = -c/b
egdaniel4ca2e602015-11-18 08:01:26 -0800272 fragBuilder->codeAppendf("\tfloat %s = -(%s / %s);\n", tName.c_str(),
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000273 cName.c_str(), bVar.c_str());
274
275 // if r(t) > 0, then t will be the x coordinate
egdaniel4ca2e602015-11-18 08:01:26 -0800276 fragBuilder->codeAppendf("\tif (%s * %s + %s > 0.0) {\n", tName.c_str(),
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000277 p2.c_str(), p0.c_str());
egdaniel4ca2e602015-11-18 08:01:26 -0800278 fragBuilder->codeAppend("\t");
egdaniel7ea439b2015-12-03 09:20:44 -0800279 this->emitColor(fragBuilder,
280 uniformHandler,
egdaniela2e3e0f2015-11-19 07:23:45 -0800281 args.fGLSLCaps,
egdaniel4ca2e602015-11-18 08:01:26 -0800282 ge,
283 tName.c_str(),
284 args.fOutputColor,
285 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -0700286 args.fTexSamplers);
egdaniel4ca2e602015-11-18 08:01:26 -0800287 fragBuilder->codeAppend("\t}\n");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000288}
289
fmenozzi55d318d2016-08-09 08:05:57 -0700290void Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::onSetData(
291 const GrGLSLProgramDataManager& pdman,
292 const GrProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -0700293 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -0700294 const Edge2PtConicalEffect& data = processor.cast<Edge2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000295 SkScalar radius0 = data.radius();
296 SkScalar diffRadius = data.diffRadius();
297
298 if (fCachedRadius != radius0 ||
299 fCachedDiffRadius != diffRadius) {
300
halcanary9d524f22016-03-29 09:03:52 -0700301 pdman.set3f(fParamUni, SkScalarToFloat(radius0),
jvanverthde11ee42016-02-26 13:58:40 -0800302 SkScalarToFloat(SkScalarMul(radius0, radius0)), SkScalarToFloat(diffRadius));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000303 fCachedRadius = radius0;
304 fCachedDiffRadius = diffRadius;
305 }
306}
307
fmenozzi55d318d2016-08-09 08:05:57 -0700308void Edge2PtConicalEffect::GLSLEdge2PtConicalProcessor::GenKey(const GrProcessor& processor,
jvanverthcfc18862015-04-28 08:48:20 -0700309 const GrGLSLCaps&, GrProcessorKeyBuilder* b) {
joshualittb0a8a372014-09-23 09:50:21 -0700310 b->add32(GenBaseGradientKey(processor));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000311}
312
313//////////////////////////////////////////////////////////////////////////////
314// Focal Conical Gradients
315//////////////////////////////////////////////////////////////////////////////
316
317static ConicalType set_matrix_focal_conical(const SkTwoPointConicalGradient& shader,
318 SkMatrix* invLMatrix, SkScalar* focalX) {
319 // Inverse of the current local matrix is passed in then,
320 // translate, scale, and rotate such that endCircle is unit circle on x-axis,
321 // and focal point is at the origin.
322 ConicalType conicalType;
323 const SkPoint& focal = shader.getStartCenter();
324 const SkPoint& centerEnd = shader.getEndCenter();
325 SkScalar radius = shader.getEndRadius();
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000326 SkScalar invRadius = 1.f / radius;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000327
328 SkMatrix matrix;
329
330 matrix.setTranslate(-centerEnd.fX, -centerEnd.fY);
331 matrix.postScale(invRadius, invRadius);
332
333 SkPoint focalTrans;
334 matrix.mapPoints(&focalTrans, &focal, 1);
335 *focalX = focalTrans.length();
336
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000337 if (0.f != *focalX) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000338 SkScalar invFocalX = SkScalarInvert(*focalX);
339 SkMatrix rot;
340 rot.setSinCos(-SkScalarMul(invFocalX, focalTrans.fY),
341 SkScalarMul(invFocalX, focalTrans.fX));
342 matrix.postConcat(rot);
343 }
344
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000345 matrix.postTranslate(-(*focalX), 0.f);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000346
347 // If the focal point is touching the edge of the circle it will
348 // cause a degenerate case that must be handled separately
egdaniel8405ef92014-06-09 11:57:28 -0700349 // kEdgeErrorTol = 5 * kErrorTol was picked after manual testing the
350 // stability trade off versus the linear approx used in the Edge Shader
351 if (SkScalarAbs(1.f - (*focalX)) < kEdgeErrorTol) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000352 return kEdge_ConicalType;
353 }
354
355 // Scale factor 1 / (1 - focalX * focalX)
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000356 SkScalar oneMinusF2 = 1.f - SkScalarMul(*focalX, *focalX);
reed80ea19c2015-05-12 10:37:34 -0700357 SkScalar s = SkScalarInvert(oneMinusF2);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000358
359
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000360 if (s >= 0.f) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000361 conicalType = kInside_ConicalType;
362 matrix.postScale(s, s * SkScalarSqrt(oneMinusF2));
363 } else {
364 conicalType = kOutside_ConicalType;
365 matrix.postScale(s, s);
366 }
367
368 invLMatrix->postConcat(matrix);
369
370 return conicalType;
371}
372
373//////////////////////////////////////////////////////////////////////////////
374
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000375class FocalOutside2PtConicalEffect : public GrGradientEffect {
376public:
fmenozzi55d318d2016-08-09 08:05:57 -0700377 class GLSLFocalOutside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000378
bungeman06ca8ec2016-06-09 08:01:03 -0700379 static sk_sp<GrFragmentProcessor> Make(GrContext* ctx,
380 const SkTwoPointConicalGradient& shader,
381 const SkMatrix& matrix,
382 SkShader::TileMode tm,
383 SkScalar focalX) {
384 return sk_sp<GrFragmentProcessor>(
385 new FocalOutside2PtConicalEffect(ctx, shader, matrix, tm, focalX));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000386 }
387
388 virtual ~FocalOutside2PtConicalEffect() { }
389
mtklein36352bf2015-03-25 18:17:31 -0700390 const char* name() const override {
joshualitteb2a6762014-12-04 11:35:33 -0800391 return "Two-Point Conical Gradient Focal Outside";
392 }
393
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000394 bool isFlipped() const { return fIsFlipped; }
395 SkScalar focal() const { return fFocalX; }
396
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000397private:
egdaniel57d3b032015-11-13 11:57:27 -0800398 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -0700399
egdaniel57d3b032015-11-13 11:57:27 -0800400 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -0700401
mtklein36352bf2015-03-25 18:17:31 -0700402 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -0700403 const FocalOutside2PtConicalEffect& s = sBase.cast<FocalOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000404 return (INHERITED::onIsEqual(sBase) &&
405 this->fFocalX == s.fFocalX &&
406 this->fIsFlipped == s.fIsFlipped);
407 }
408
409 FocalOutside2PtConicalEffect(GrContext* ctx,
410 const SkTwoPointConicalGradient& shader,
411 const SkMatrix& matrix,
412 SkShader::TileMode tm,
413 SkScalar focalX)
bsalomon4a339522015-10-06 08:40:50 -0700414 : INHERITED(ctx, shader, matrix, tm)
joshualittb2456052015-07-08 09:36:59 -0700415 , fFocalX(focalX)
416 , fIsFlipped(shader.isFlippedGrad()) {
joshualitteb2a6762014-12-04 11:35:33 -0800417 this->initClassID<FocalOutside2PtConicalEffect>();
418 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000419
joshualittb0a8a372014-09-23 09:50:21 -0700420 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000421
422 SkScalar fFocalX;
423 bool fIsFlipped;
424
425 typedef GrGradientEffect INHERITED;
426};
427
fmenozzi55d318d2016-08-09 08:05:57 -0700428class FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor
429 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000430public:
fmenozzi55d318d2016-08-09 08:05:57 -0700431 GLSLFocalOutside2PtConicalProcessor(const GrProcessor&);
432 virtual ~GLSLFocalOutside2PtConicalProcessor() { }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000433
wangyix7c157a92015-07-22 15:08:53 -0700434 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000435
jvanverthcfc18862015-04-28 08:48:20 -0700436 static void GenKey(const GrProcessor&, const GrGLSLCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000437
438protected:
egdaniel018fb622015-10-28 07:26:40 -0700439 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -0700440
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000441 UniformHandle fParamUni;
442
443 const char* fVSVaryingName;
444 const char* fFSVaryingName;
445
446 bool fIsFlipped;
447
448 // @{
449 /// Values last uploaded as uniforms
450
451 SkScalar fCachedFocal;
452
453 // @}
454
455private:
fmenozzi55d318d2016-08-09 08:05:57 -0700456 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000457
458};
459
egdaniel57d3b032015-11-13 11:57:27 -0800460void FocalOutside2PtConicalEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
461 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -0700462 FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800463}
464
egdaniel57d3b032015-11-13 11:57:27 -0800465GrGLSLFragmentProcessor* FocalOutside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -0700466 return new FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000467}
468
joshualittb0a8a372014-09-23 09:50:21 -0700469GR_DEFINE_FRAGMENT_PROCESSOR_TEST(FocalOutside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000470
joshualitt01258472014-09-22 10:29:30 -0700471/*
472 * All Two point conical gradient test create functions may occasionally create edge case shaders
473 */
bungeman06ca8ec2016-06-09 08:01:03 -0700474sk_sp<GrFragmentProcessor> FocalOutside2PtConicalEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700475 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000476 SkScalar radius1 = 0.f;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000477 SkPoint center2;
478 SkScalar radius2;
479 do {
joshualitt0067ff52015-07-08 14:26:19 -0700480 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +0000481 // 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 +0000482 } while (center1 == center2);
483 SkPoint diff = center2 - center1;
484 SkScalar diffLen = diff.length();
485 // Below makes sure that the focal point is not contained within circle two
joshualitt0067ff52015-07-08 14:26:19 -0700486 radius2 = d->fRandom->nextRangeF(0.f, diffLen);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000487
488 SkColor colors[kMaxRandomGradientColors];
489 SkScalar stopsArray[kMaxRandomGradientColors];
490 SkScalar* stops = stopsArray;
491 SkShader::TileMode tm;
joshualitt0067ff52015-07-08 14:26:19 -0700492 int colorCount = RandomGradientParams(d->fRandom, colors, &stops, &tm);
reed8a21c9f2016-03-08 18:50:00 -0800493 auto shader = SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
494 colors, stops, colorCount, tm);
brianosman839345d2016-07-22 11:04:53 -0700495 SkMatrix viewMatrix = GrTest::TestMatrix(d->fRandom);
496 sk_sp<GrFragmentProcessor> fp = shader->asFragmentProcessor(SkShader::AsFPArgs(
brianosman1638c0d2016-07-25 05:12:53 -0700497 d->fContext, &viewMatrix, NULL, kNone_SkFilterQuality, nullptr,
498 SkSourceGammaTreatment::kRespect));
bsalomonc21b09e2015-08-28 18:46:56 -0700499 GrAlwaysAssert(fp);
500 return fp;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000501}
502
fmenozzi55d318d2016-08-09 08:05:57 -0700503FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor
504 ::GLSLFocalOutside2PtConicalProcessor(const GrProcessor& processor)
halcanary96fcdcc2015-08-27 07:41:13 -0700505 : fVSVaryingName(nullptr)
506 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000507 , fCachedFocal(SK_ScalarMax) {
joshualittb0a8a372014-09-23 09:50:21 -0700508 const FocalOutside2PtConicalEffect& data = processor.cast<FocalOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000509 fIsFlipped = data.isFlipped();
510}
511
fmenozzi55d318d2016-08-09 08:05:57 -0700512void FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -0700513 const FocalOutside2PtConicalEffect& ge = args.fFp.cast<FocalOutside2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -0800514 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
515 this->emitUniforms(uniformHandler, ge);
jvanverthde11ee42016-02-26 13:58:40 -0800516 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
517 kVec2f_GrSLType, kDefault_GrSLPrecision,
518 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000519 SkString tName("t");
520 SkString p0; // focalX
521 SkString p1; // 1 - focalX * focalX
522
jvanverthde11ee42016-02-26 13:58:40 -0800523 p0.appendf("%s.x", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
524 p1.appendf("%s.y", uniformHandler->getUniformVariable(fParamUni).getName().c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000525
526 // if we have a vec3 from being in perspective, convert it to a vec2 first
cdalton85285412016-02-18 12:37:07 -0800527 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -0700528 SkString coords2DString = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +0000529 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000530
531 // t = p.x * focal.x +/- sqrt(p.x^2 + (1 - focal.x^2) * p.y^2)
532
533 // output will default to transparent black (we simply won't write anything
534 // else to it if invalid, instead of discarding or returning prematurely)
egdaniel4ca2e602015-11-18 08:01:26 -0800535 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 +0000536
egdaniel4ca2e602015-11-18 08:01:26 -0800537 fragBuilder->codeAppendf("\tfloat xs = %s.x * %s.x;\n", coords2D, coords2D);
538 fragBuilder->codeAppendf("\tfloat ys = %s.y * %s.y;\n", coords2D, coords2D);
539 fragBuilder->codeAppendf("\tfloat d = xs + %s * ys;\n", p1.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000540
541 // Must check to see if we flipped the circle order (to make sure start radius < end radius)
542 // If so we must also flip sign on sqrt
543 if (!fIsFlipped) {
egdaniel4ca2e602015-11-18 08:01:26 -0800544 fragBuilder->codeAppendf("\tfloat %s = %s.x * %s + sqrt(d);\n", tName.c_str(),
545 coords2D, p0.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000546 } else {
egdaniel4ca2e602015-11-18 08:01:26 -0800547 fragBuilder->codeAppendf("\tfloat %s = %s.x * %s - sqrt(d);\n", tName.c_str(),
548 coords2D, p0.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000549 }
550
egdaniel4ca2e602015-11-18 08:01:26 -0800551 fragBuilder->codeAppendf("\tif (%s >= 0.0 && d >= 0.0) {\n", tName.c_str());
552 fragBuilder->codeAppend("\t\t");
egdaniel7ea439b2015-12-03 09:20:44 -0800553 this->emitColor(fragBuilder,
554 uniformHandler,
egdaniela2e3e0f2015-11-19 07:23:45 -0800555 args.fGLSLCaps,
egdaniel4ca2e602015-11-18 08:01:26 -0800556 ge,
557 tName.c_str(),
558 args.fOutputColor,
559 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -0700560 args.fTexSamplers);
egdaniel4ca2e602015-11-18 08:01:26 -0800561 fragBuilder->codeAppend("\t}\n");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000562}
563
fmenozzi55d318d2016-08-09 08:05:57 -0700564void FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::onSetData(
565 const GrGLSLProgramDataManager& pdman,
566 const GrProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -0700567 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -0700568 const FocalOutside2PtConicalEffect& data = processor.cast<FocalOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000569 SkASSERT(data.isFlipped() == fIsFlipped);
570 SkScalar focal = data.focal();
571
572 if (fCachedFocal != focal) {
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000573 SkScalar oneMinus2F = 1.f - SkScalarMul(focal, focal);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000574
jvanverthde11ee42016-02-26 13:58:40 -0800575 pdman.set2f(fParamUni, SkScalarToFloat(focal), SkScalarToFloat(oneMinus2F));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000576 fCachedFocal = focal;
577 }
578}
579
fmenozzi55d318d2016-08-09 08:05:57 -0700580void FocalOutside2PtConicalEffect::GLSLFocalOutside2PtConicalProcessor::GenKey(
581 const GrProcessor& processor,
jvanverthcfc18862015-04-28 08:48:20 -0700582 const GrGLSLCaps&, GrProcessorKeyBuilder* b) {
bsalomon63e99f72014-07-21 08:03:14 -0700583 uint32_t* key = b->add32n(2);
joshualittb0a8a372014-09-23 09:50:21 -0700584 key[0] = GenBaseGradientKey(processor);
585 key[1] = processor.cast<FocalOutside2PtConicalEffect>().isFlipped();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000586}
587
588//////////////////////////////////////////////////////////////////////////////
589
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000590class FocalInside2PtConicalEffect : public GrGradientEffect {
591public:
fmenozzi55d318d2016-08-09 08:05:57 -0700592 class GLSLFocalInside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000593
bungeman06ca8ec2016-06-09 08:01:03 -0700594 static sk_sp<GrFragmentProcessor> Make(GrContext* ctx,
595 const SkTwoPointConicalGradient& shader,
596 const SkMatrix& matrix,
597 SkShader::TileMode tm,
598 SkScalar focalX) {
599 return sk_sp<GrFragmentProcessor>(
600 new FocalInside2PtConicalEffect(ctx, shader, matrix, tm, focalX));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000601 }
602
603 virtual ~FocalInside2PtConicalEffect() {}
604
mtklein36352bf2015-03-25 18:17:31 -0700605 const char* name() const override {
joshualitteb2a6762014-12-04 11:35:33 -0800606 return "Two-Point Conical Gradient Focal Inside";
607 }
608
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000609 SkScalar focal() const { return fFocalX; }
610
fmenozzi55d318d2016-08-09 08:05:57 -0700611 typedef FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor GLSLProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000612
613private:
egdaniel57d3b032015-11-13 11:57:27 -0800614 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -0700615
egdaniel57d3b032015-11-13 11:57:27 -0800616 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -0700617
mtklein36352bf2015-03-25 18:17:31 -0700618 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -0700619 const FocalInside2PtConicalEffect& s = sBase.cast<FocalInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000620 return (INHERITED::onIsEqual(sBase) &&
621 this->fFocalX == s.fFocalX);
622 }
623
624 FocalInside2PtConicalEffect(GrContext* ctx,
625 const SkTwoPointConicalGradient& shader,
626 const SkMatrix& matrix,
627 SkShader::TileMode tm,
628 SkScalar focalX)
bsalomon4a339522015-10-06 08:40:50 -0700629 : INHERITED(ctx, shader, matrix, tm), fFocalX(focalX) {
joshualitteb2a6762014-12-04 11:35:33 -0800630 this->initClassID<FocalInside2PtConicalEffect>();
631 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000632
joshualittb0a8a372014-09-23 09:50:21 -0700633 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000634
635 SkScalar fFocalX;
636
637 typedef GrGradientEffect INHERITED;
638};
639
fmenozzi55d318d2016-08-09 08:05:57 -0700640class FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor
641 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000642public:
fmenozzi55d318d2016-08-09 08:05:57 -0700643 GLSLFocalInside2PtConicalProcessor(const GrProcessor&);
644 virtual ~GLSLFocalInside2PtConicalProcessor() {}
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000645
wangyix7c157a92015-07-22 15:08:53 -0700646 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000647
jvanverthcfc18862015-04-28 08:48:20 -0700648 static void GenKey(const GrProcessor&, const GrGLSLCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000649
650protected:
egdaniel018fb622015-10-28 07:26:40 -0700651 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -0700652
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000653 UniformHandle fFocalUni;
654
655 const char* fVSVaryingName;
656 const char* fFSVaryingName;
657
658 // @{
659 /// Values last uploaded as uniforms
660
661 SkScalar fCachedFocal;
662
663 // @}
664
665private:
fmenozzi55d318d2016-08-09 08:05:57 -0700666 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000667
668};
669
egdaniel57d3b032015-11-13 11:57:27 -0800670void FocalInside2PtConicalEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
671 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -0700672 FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800673}
674
egdaniel57d3b032015-11-13 11:57:27 -0800675GrGLSLFragmentProcessor* FocalInside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -0700676 return new FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000677}
678
joshualittb0a8a372014-09-23 09:50:21 -0700679GR_DEFINE_FRAGMENT_PROCESSOR_TEST(FocalInside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000680
joshualitt01258472014-09-22 10:29:30 -0700681/*
682 * All Two point conical gradient test create functions may occasionally create edge case shaders
683 */
bungeman06ca8ec2016-06-09 08:01:03 -0700684sk_sp<GrFragmentProcessor> FocalInside2PtConicalEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700685 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000686 SkScalar radius1 = 0.f;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000687 SkPoint center2;
688 SkScalar radius2;
689 do {
joshualitt0067ff52015-07-08 14:26:19 -0700690 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000691 // Below makes sure radius2 is larger enouch such that the focal point
692 // is inside the end circle
joshualitt0067ff52015-07-08 14:26:19 -0700693 SkScalar increase = d->fRandom->nextUScalar1();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000694 SkPoint diff = center2 - center1;
695 SkScalar diffLen = diff.length();
696 radius2 = diffLen + increase;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000697 // If the circles are identical the factory will give us an empty shader.
698 } while (radius1 == radius2 && center1 == center2);
699
700 SkColor colors[kMaxRandomGradientColors];
701 SkScalar stopsArray[kMaxRandomGradientColors];
702 SkScalar* stops = stopsArray;
703 SkShader::TileMode tm;
joshualitt0067ff52015-07-08 14:26:19 -0700704 int colorCount = RandomGradientParams(d->fRandom, colors, &stops, &tm);
reed8a21c9f2016-03-08 18:50:00 -0800705 auto shader = SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
706 colors, stops, colorCount, tm);
brianosman839345d2016-07-22 11:04:53 -0700707 SkMatrix viewMatrix = GrTest::TestMatrix(d->fRandom);
708 sk_sp<GrFragmentProcessor> fp = shader->asFragmentProcessor(SkShader::AsFPArgs(
brianosman1638c0d2016-07-25 05:12:53 -0700709 d->fContext, &viewMatrix, NULL, kNone_SkFilterQuality, nullptr,
710 SkSourceGammaTreatment::kRespect));
bsalomonc21b09e2015-08-28 18:46:56 -0700711 GrAlwaysAssert(fp);
joshualittb0a8a372014-09-23 09:50:21 -0700712 return fp;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000713}
714
fmenozzi55d318d2016-08-09 08:05:57 -0700715FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor
716 ::GLSLFocalInside2PtConicalProcessor(const GrProcessor&)
halcanary96fcdcc2015-08-27 07:41:13 -0700717 : fVSVaryingName(nullptr)
718 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000719 , fCachedFocal(SK_ScalarMax) {}
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000720
fmenozzi55d318d2016-08-09 08:05:57 -0700721void FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -0700722 const FocalInside2PtConicalEffect& ge = args.fFp.cast<FocalInside2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -0800723 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
724 this->emitUniforms(uniformHandler, ge);
cdalton5e58cee2016-02-11 12:49:47 -0800725 fFocalUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800726 kFloat_GrSLType, kDefault_GrSLPrecision,
727 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000728 SkString tName("t");
729
730 // this is the distance along x-axis from the end center to focal point in
731 // transformed coordinates
egdaniel7ea439b2015-12-03 09:20:44 -0800732 GrGLSLShaderVar focal = uniformHandler->getUniformVariable(fFocalUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000733
734 // if we have a vec3 from being in perspective, convert it to a vec2 first
cdalton85285412016-02-18 12:37:07 -0800735 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -0700736 SkString coords2DString = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +0000737 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000738
739 // t = p.x * focalX + length(p)
egdaniel4ca2e602015-11-18 08:01:26 -0800740 fragBuilder->codeAppendf("\tfloat %s = %s.x * %s + length(%s);\n", tName.c_str(),
egdaniel7ea439b2015-12-03 09:20:44 -0800741 coords2D, focal.c_str(), coords2D);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000742
egdaniel7ea439b2015-12-03 09:20:44 -0800743 this->emitColor(fragBuilder,
744 uniformHandler,
egdaniela2e3e0f2015-11-19 07:23:45 -0800745 args.fGLSLCaps,
egdaniel4ca2e602015-11-18 08:01:26 -0800746 ge,
747 tName.c_str(),
748 args.fOutputColor,
749 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -0700750 args.fTexSamplers);
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000751}
752
fmenozzi55d318d2016-08-09 08:05:57 -0700753void FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::onSetData(
754 const GrGLSLProgramDataManager& pdman,
755 const GrProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -0700756 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -0700757 const FocalInside2PtConicalEffect& data = processor.cast<FocalInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000758 SkScalar focal = data.focal();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000759
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000760 if (fCachedFocal != focal) {
kkinnunen7510b222014-07-30 00:04:16 -0700761 pdman.set1f(fFocalUni, SkScalarToFloat(focal));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000762 fCachedFocal = focal;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +0000763 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000764}
765
fmenozzi55d318d2016-08-09 08:05:57 -0700766void FocalInside2PtConicalEffect::GLSLFocalInside2PtConicalProcessor::GenKey(
767 const GrProcessor& processor,
768 const GrGLSLCaps&, GrProcessorKeyBuilder* b) {
joshualittb0a8a372014-09-23 09:50:21 -0700769 b->add32(GenBaseGradientKey(processor));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000770}
771
772//////////////////////////////////////////////////////////////////////////////
773// Circle Conical Gradients
774//////////////////////////////////////////////////////////////////////////////
775
776struct CircleConicalInfo {
777 SkPoint fCenterEnd;
778 SkScalar fA;
779 SkScalar fB;
780 SkScalar fC;
781};
782
783// Returns focal distance along x-axis in transformed coords
784static ConicalType set_matrix_circle_conical(const SkTwoPointConicalGradient& shader,
785 SkMatrix* invLMatrix, CircleConicalInfo* info) {
786 // Inverse of the current local matrix is passed in then,
787 // translate and scale such that start circle is on the origin and has radius 1
788 const SkPoint& centerStart = shader.getStartCenter();
789 const SkPoint& centerEnd = shader.getEndCenter();
790 SkScalar radiusStart = shader.getStartRadius();
791 SkScalar radiusEnd = shader.getEndRadius();
792
793 SkMatrix matrix;
794
795 matrix.setTranslate(-centerStart.fX, -centerStart.fY);
796
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000797 SkScalar invStartRad = 1.f / radiusStart;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000798 matrix.postScale(invStartRad, invStartRad);
799
800 radiusEnd /= radiusStart;
801
802 SkPoint centerEndTrans;
803 matrix.mapPoints(&centerEndTrans, &centerEnd, 1);
804
805 SkScalar A = centerEndTrans.fX * centerEndTrans.fX + centerEndTrans.fY * centerEndTrans.fY
806 - radiusEnd * radiusEnd + 2 * radiusEnd - 1;
807
808 // Check to see if start circle is inside end circle with edges touching.
809 // If touching we return that it is of kEdge_ConicalType, and leave the matrix setting
egdaniel8405ef92014-06-09 11:57:28 -0700810 // to the edge shader. kEdgeErrorTol = 5 * kErrorTol was picked after manual testing
811 // so that C = 1 / A is stable, and the linear approximation used in the Edge shader is
812 // still accurate.
813 if (SkScalarAbs(A) < kEdgeErrorTol) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000814 return kEdge_ConicalType;
815 }
816
commit-bot@chromium.org80894672014-04-22 21:24:22 +0000817 SkScalar C = 1.f / A;
818 SkScalar B = (radiusEnd - 1.f) * C;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000819
820 matrix.postScale(C, C);
821
822 invLMatrix->postConcat(matrix);
823
824 info->fCenterEnd = centerEndTrans;
825 info->fA = A;
826 info->fB = B;
827 info->fC = C;
828
829 // 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 +0000830 if (A < 0.f) {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000831 return kInside_ConicalType;
832 }
833 return kOutside_ConicalType;
834}
835
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000836class CircleInside2PtConicalEffect : public GrGradientEffect {
837public:
fmenozzi55d318d2016-08-09 08:05:57 -0700838 class GLSLCircleInside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000839
bungeman06ca8ec2016-06-09 08:01:03 -0700840 static sk_sp<GrFragmentProcessor> Make(GrContext* ctx,
841 const SkTwoPointConicalGradient& shader,
842 const SkMatrix& matrix,
843 SkShader::TileMode tm,
844 const CircleConicalInfo& info) {
845 return sk_sp<GrFragmentProcessor>(
846 new CircleInside2PtConicalEffect(ctx, shader, matrix, tm, info));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000847 }
848
849 virtual ~CircleInside2PtConicalEffect() {}
850
mtklein36352bf2015-03-25 18:17:31 -0700851 const char* name() const override { return "Two-Point Conical Gradient Inside"; }
joshualitteb2a6762014-12-04 11:35:33 -0800852
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000853 SkScalar centerX() const { return fInfo.fCenterEnd.fX; }
854 SkScalar centerY() const { return fInfo.fCenterEnd.fY; }
855 SkScalar A() const { return fInfo.fA; }
856 SkScalar B() const { return fInfo.fB; }
857 SkScalar C() const { return fInfo.fC; }
858
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000859private:
egdaniel57d3b032015-11-13 11:57:27 -0800860 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -0700861
egdaniel57d3b032015-11-13 11:57:27 -0800862 virtual void onGetGLSLProcessorKey(const GrGLSLCaps& caps,
863 GrProcessorKeyBuilder* b) const override;
wangyix4b3050b2015-08-04 07:59:37 -0700864
mtklein36352bf2015-03-25 18:17:31 -0700865 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -0700866 const CircleInside2PtConicalEffect& s = sBase.cast<CircleInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000867 return (INHERITED::onIsEqual(sBase) &&
868 this->fInfo.fCenterEnd == s.fInfo.fCenterEnd &&
869 this->fInfo.fA == s.fInfo.fA &&
870 this->fInfo.fB == s.fInfo.fB &&
871 this->fInfo.fC == s.fInfo.fC);
872 }
873
874 CircleInside2PtConicalEffect(GrContext* ctx,
875 const SkTwoPointConicalGradient& shader,
876 const SkMatrix& matrix,
877 SkShader::TileMode tm,
878 const CircleConicalInfo& info)
bsalomon4a339522015-10-06 08:40:50 -0700879 : INHERITED(ctx, shader, matrix, tm), fInfo(info) {
joshualitteb2a6762014-12-04 11:35:33 -0800880 this->initClassID<CircleInside2PtConicalEffect>();
881 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000882
joshualittb0a8a372014-09-23 09:50:21 -0700883 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000884
885 const CircleConicalInfo fInfo;
886
887 typedef GrGradientEffect INHERITED;
888};
889
fmenozzi55d318d2016-08-09 08:05:57 -0700890class CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor
891 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000892public:
fmenozzi55d318d2016-08-09 08:05:57 -0700893 GLSLCircleInside2PtConicalProcessor(const GrProcessor&);
894 virtual ~GLSLCircleInside2PtConicalProcessor() {}
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000895
wangyix7c157a92015-07-22 15:08:53 -0700896 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000897
jvanverthcfc18862015-04-28 08:48:20 -0700898 static void GenKey(const GrProcessor&, const GrGLSLCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000899
900protected:
egdaniel018fb622015-10-28 07:26:40 -0700901 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -0700902
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000903 UniformHandle fCenterUni;
904 UniformHandle fParamUni;
905
906 const char* fVSVaryingName;
907 const char* fFSVaryingName;
908
909 // @{
910 /// Values last uploaded as uniforms
911
912 SkScalar fCachedCenterX;
913 SkScalar fCachedCenterY;
914 SkScalar fCachedA;
915 SkScalar fCachedB;
916 SkScalar fCachedC;
917
918 // @}
919
920private:
fmenozzi55d318d2016-08-09 08:05:57 -0700921 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000922
923};
924
egdaniel57d3b032015-11-13 11:57:27 -0800925void CircleInside2PtConicalEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
926 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -0700927 CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -0800928}
929
egdaniel57d3b032015-11-13 11:57:27 -0800930GrGLSLFragmentProcessor* CircleInside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -0700931 return new CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000932}
933
joshualittb0a8a372014-09-23 09:50:21 -0700934GR_DEFINE_FRAGMENT_PROCESSOR_TEST(CircleInside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000935
joshualitt01258472014-09-22 10:29:30 -0700936/*
937 * All Two point conical gradient test create functions may occasionally create edge case shaders
938 */
bungeman06ca8ec2016-06-09 08:01:03 -0700939sk_sp<GrFragmentProcessor> CircleInside2PtConicalEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -0700940 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
941 SkScalar radius1 = d->fRandom->nextUScalar1() + 0.0001f; // make sure radius1 != 0
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000942 SkPoint center2;
943 SkScalar radius2;
944 do {
joshualitt0067ff52015-07-08 14:26:19 -0700945 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000946 // Below makes sure that circle one is contained within circle two
joshualitt0067ff52015-07-08 14:26:19 -0700947 SkScalar increase = d->fRandom->nextUScalar1();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000948 SkPoint diff = center2 - center1;
949 SkScalar diffLen = diff.length();
950 radius2 = radius1 + diffLen + increase;
951 // If the circles are identical the factory will give us an empty shader.
952 } while (radius1 == radius2 && center1 == center2);
953
954 SkColor colors[kMaxRandomGradientColors];
955 SkScalar stopsArray[kMaxRandomGradientColors];
956 SkScalar* stops = stopsArray;
957 SkShader::TileMode tm;
joshualitt0067ff52015-07-08 14:26:19 -0700958 int colorCount = RandomGradientParams(d->fRandom, colors, &stops, &tm);
reed8a21c9f2016-03-08 18:50:00 -0800959 auto shader = SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
960 colors, stops, colorCount, tm);
brianosman839345d2016-07-22 11:04:53 -0700961 SkMatrix viewMatrix = GrTest::TestMatrix(d->fRandom);
962 sk_sp<GrFragmentProcessor> fp = shader->asFragmentProcessor(SkShader::AsFPArgs(
brianosman1638c0d2016-07-25 05:12:53 -0700963 d->fContext, &viewMatrix, NULL, kNone_SkFilterQuality, nullptr,
964 SkSourceGammaTreatment::kRespect));
bsalomonc21b09e2015-08-28 18:46:56 -0700965 GrAlwaysAssert(fp);
joshualitt8ca93e72015-07-08 06:51:43 -0700966 return fp;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000967}
968
fmenozzi55d318d2016-08-09 08:05:57 -0700969CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor
970 ::GLSLCircleInside2PtConicalProcessor(const GrProcessor& processor)
halcanary96fcdcc2015-08-27 07:41:13 -0700971 : fVSVaryingName(nullptr)
972 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000973 , fCachedCenterX(SK_ScalarMax)
974 , fCachedCenterY(SK_ScalarMax)
975 , fCachedA(SK_ScalarMax)
976 , fCachedB(SK_ScalarMax)
977 , fCachedC(SK_ScalarMax) {}
978
fmenozzi55d318d2016-08-09 08:05:57 -0700979void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -0700980 const CircleInside2PtConicalEffect& ge = args.fFp.cast<CircleInside2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -0800981 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
982 this->emitUniforms(uniformHandler, ge);
cdalton5e58cee2016-02-11 12:49:47 -0800983 fCenterUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800984 kVec2f_GrSLType, kDefault_GrSLPrecision,
985 "Conical2FSCenter");
cdalton5e58cee2016-02-11 12:49:47 -0800986 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -0800987 kVec3f_GrSLType, kDefault_GrSLPrecision,
988 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000989 SkString tName("t");
990
egdaniel7ea439b2015-12-03 09:20:44 -0800991 GrGLSLShaderVar center = uniformHandler->getUniformVariable(fCenterUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000992 // params.x = A
993 // params.y = B
994 // params.z = C
egdaniel7ea439b2015-12-03 09:20:44 -0800995 GrGLSLShaderVar params = uniformHandler->getUniformVariable(fParamUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +0000996
997 // if we have a vec3 from being in perspective, convert it to a vec2 first
cdalton85285412016-02-18 12:37:07 -0800998 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -0700999 SkString coords2DString = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +00001000 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001001
1002 // p = coords2D
1003 // e = center end
1004 // r = radius end
1005 // A = dot(e, e) - r^2 + 2 * r - 1
1006 // B = (r -1) / A
1007 // C = 1 / A
1008 // d = dot(e, p) + B
1009 // t = d +/- sqrt(d^2 - A * dot(p, p) + C)
egdaniel4ca2e602015-11-18 08:01:26 -08001010 fragBuilder->codeAppendf("\tfloat pDotp = dot(%s, %s);\n", coords2D, coords2D);
1011 fragBuilder->codeAppendf("\tfloat d = dot(%s, %s) + %s.y;\n", coords2D, center.c_str(),
1012 params.c_str());
1013 fragBuilder->codeAppendf("\tfloat %s = d + sqrt(d * d - %s.x * pDotp + %s.z);\n",
1014 tName.c_str(), params.c_str(), params.c_str());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001015
egdaniel7ea439b2015-12-03 09:20:44 -08001016 this->emitColor(fragBuilder,
1017 uniformHandler,
egdaniela2e3e0f2015-11-19 07:23:45 -08001018 args.fGLSLCaps,
egdaniel4ca2e602015-11-18 08:01:26 -08001019 ge,
1020 tName.c_str(),
1021 args.fOutputColor,
1022 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -07001023 args.fTexSamplers);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001024}
1025
fmenozzi55d318d2016-08-09 08:05:57 -07001026void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::onSetData(
1027 const GrGLSLProgramDataManager& pdman,
1028 const GrProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -07001029 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -07001030 const CircleInside2PtConicalEffect& data = processor.cast<CircleInside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001031 SkScalar centerX = data.centerX();
1032 SkScalar centerY = data.centerY();
1033 SkScalar A = data.A();
1034 SkScalar B = data.B();
1035 SkScalar C = data.C();
1036
1037 if (fCachedCenterX != centerX || fCachedCenterY != centerY ||
1038 fCachedA != A || fCachedB != B || fCachedC != C) {
1039
kkinnunen7510b222014-07-30 00:04:16 -07001040 pdman.set2f(fCenterUni, SkScalarToFloat(centerX), SkScalarToFloat(centerY));
1041 pdman.set3f(fParamUni, SkScalarToFloat(A), SkScalarToFloat(B), SkScalarToFloat(C));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001042
1043 fCachedCenterX = centerX;
1044 fCachedCenterY = centerY;
1045 fCachedA = A;
1046 fCachedB = B;
1047 fCachedC = C;
1048 }
1049}
1050
fmenozzi55d318d2016-08-09 08:05:57 -07001051void CircleInside2PtConicalEffect::GLSLCircleInside2PtConicalProcessor::GenKey(
1052 const GrProcessor& processor,
jvanverthcfc18862015-04-28 08:48:20 -07001053 const GrGLSLCaps&, GrProcessorKeyBuilder* b) {
joshualittb0a8a372014-09-23 09:50:21 -07001054 b->add32(GenBaseGradientKey(processor));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001055}
1056
1057//////////////////////////////////////////////////////////////////////////////
1058
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001059class CircleOutside2PtConicalEffect : public GrGradientEffect {
1060public:
fmenozzi55d318d2016-08-09 08:05:57 -07001061 class GLSLCircleOutside2PtConicalProcessor;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001062
bungeman06ca8ec2016-06-09 08:01:03 -07001063 static sk_sp<GrFragmentProcessor> Make(GrContext* ctx,
1064 const SkTwoPointConicalGradient& shader,
1065 const SkMatrix& matrix,
1066 SkShader::TileMode tm,
1067 const CircleConicalInfo& info) {
1068 return sk_sp<GrFragmentProcessor>(
1069 new CircleOutside2PtConicalEffect(ctx, shader, matrix, tm, info));
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001070 }
1071
1072 virtual ~CircleOutside2PtConicalEffect() {}
1073
mtklein36352bf2015-03-25 18:17:31 -07001074 const char* name() const override { return "Two-Point Conical Gradient Outside"; }
joshualitteb2a6762014-12-04 11:35:33 -08001075
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001076 SkScalar centerX() const { return fInfo.fCenterEnd.fX; }
1077 SkScalar centerY() const { return fInfo.fCenterEnd.fY; }
1078 SkScalar A() const { return fInfo.fA; }
1079 SkScalar B() const { return fInfo.fB; }
1080 SkScalar C() const { return fInfo.fC; }
1081 SkScalar tLimit() const { return fTLimit; }
1082 bool isFlipped() const { return fIsFlipped; }
1083
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001084private:
egdaniel57d3b032015-11-13 11:57:27 -08001085 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
wangyixb1daa862015-08-18 11:29:31 -07001086
egdaniel57d3b032015-11-13 11:57:27 -08001087 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
wangyix4b3050b2015-08-04 07:59:37 -07001088
mtklein36352bf2015-03-25 18:17:31 -07001089 bool onIsEqual(const GrFragmentProcessor& sBase) const override {
joshualitt49586be2014-09-16 08:21:41 -07001090 const CircleOutside2PtConicalEffect& s = sBase.cast<CircleOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001091 return (INHERITED::onIsEqual(sBase) &&
1092 this->fInfo.fCenterEnd == s.fInfo.fCenterEnd &&
1093 this->fInfo.fA == s.fInfo.fA &&
1094 this->fInfo.fB == s.fInfo.fB &&
1095 this->fInfo.fC == s.fInfo.fC &&
1096 this->fTLimit == s.fTLimit &&
1097 this->fIsFlipped == s.fIsFlipped);
1098 }
1099
1100 CircleOutside2PtConicalEffect(GrContext* ctx,
1101 const SkTwoPointConicalGradient& shader,
1102 const SkMatrix& matrix,
1103 SkShader::TileMode tm,
1104 const CircleConicalInfo& info)
bsalomon4a339522015-10-06 08:40:50 -07001105 : INHERITED(ctx, shader, matrix, tm), fInfo(info) {
joshualitteb2a6762014-12-04 11:35:33 -08001106 this->initClassID<CircleOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001107 if (shader.getStartRadius() != shader.getEndRadius()) {
reed80ea19c2015-05-12 10:37:34 -07001108 fTLimit = shader.getStartRadius() / (shader.getStartRadius() - shader.getEndRadius());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001109 } else {
1110 fTLimit = SK_ScalarMin;
1111 }
1112
1113 fIsFlipped = shader.isFlippedGrad();
1114 }
1115
joshualittb0a8a372014-09-23 09:50:21 -07001116 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001117
1118 const CircleConicalInfo fInfo;
1119 SkScalar fTLimit;
1120 bool fIsFlipped;
1121
1122 typedef GrGradientEffect INHERITED;
1123};
1124
fmenozzi55d318d2016-08-09 08:05:57 -07001125class CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor
1126 : public GrGradientEffect::GLSLProcessor {
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001127public:
fmenozzi55d318d2016-08-09 08:05:57 -07001128 GLSLCircleOutside2PtConicalProcessor(const GrProcessor&);
1129 virtual ~GLSLCircleOutside2PtConicalProcessor() {}
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001130
wangyix7c157a92015-07-22 15:08:53 -07001131 virtual void emitCode(EmitArgs&) override;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001132
jvanverthcfc18862015-04-28 08:48:20 -07001133 static void GenKey(const GrProcessor&, const GrGLSLCaps& caps, GrProcessorKeyBuilder* b);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001134
1135protected:
egdaniel018fb622015-10-28 07:26:40 -07001136 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
wangyixb1daa862015-08-18 11:29:31 -07001137
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001138 UniformHandle fCenterUni;
1139 UniformHandle fParamUni;
1140
1141 const char* fVSVaryingName;
1142 const char* fFSVaryingName;
1143
1144 bool fIsFlipped;
1145
1146 // @{
1147 /// Values last uploaded as uniforms
1148
1149 SkScalar fCachedCenterX;
1150 SkScalar fCachedCenterY;
1151 SkScalar fCachedA;
1152 SkScalar fCachedB;
1153 SkScalar fCachedC;
1154 SkScalar fCachedTLimit;
1155
1156 // @}
1157
1158private:
fmenozzi55d318d2016-08-09 08:05:57 -07001159 typedef GrGradientEffect::GLSLProcessor INHERITED;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001160
1161};
1162
egdaniel57d3b032015-11-13 11:57:27 -08001163void CircleOutside2PtConicalEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
1164 GrProcessorKeyBuilder* b) const {
fmenozzi55d318d2016-08-09 08:05:57 -07001165 CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::GenKey(*this, caps, b);
joshualitteb2a6762014-12-04 11:35:33 -08001166}
1167
egdaniel57d3b032015-11-13 11:57:27 -08001168GrGLSLFragmentProcessor* CircleOutside2PtConicalEffect::onCreateGLSLInstance() const {
fmenozzi55d318d2016-08-09 08:05:57 -07001169 return new CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor(*this);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001170}
1171
joshualittb0a8a372014-09-23 09:50:21 -07001172GR_DEFINE_FRAGMENT_PROCESSOR_TEST(CircleOutside2PtConicalEffect);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001173
joshualitt01258472014-09-22 10:29:30 -07001174/*
1175 * All Two point conical gradient test create functions may occasionally create edge case shaders
1176 */
bungeman06ca8ec2016-06-09 08:01:03 -07001177sk_sp<GrFragmentProcessor> CircleOutside2PtConicalEffect::TestCreate(GrProcessorTestData* d) {
joshualitt0067ff52015-07-08 14:26:19 -07001178 SkPoint center1 = {d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1()};
1179 SkScalar radius1 = d->fRandom->nextUScalar1() + 0.0001f; // make sure radius1 != 0
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001180 SkPoint center2;
1181 SkScalar radius2;
1182 SkScalar diffLen;
1183 do {
joshualitt0067ff52015-07-08 14:26:19 -07001184 center2.set(d->fRandom->nextUScalar1(), d->fRandom->nextUScalar1());
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001185 // If the circles share a center than we can't be in the outside case
1186 } while (center1 == center2);
joshualitt01258472014-09-22 10:29:30 -07001187 SkPoint diff = center2 - center1;
1188 diffLen = diff.length();
1189 // Below makes sure that circle one is not contained within circle two
1190 // and have radius2 >= radius to match sorting on cpu side
joshualitt0067ff52015-07-08 14:26:19 -07001191 radius2 = radius1 + d->fRandom->nextRangeF(0.f, diffLen);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001192
1193 SkColor colors[kMaxRandomGradientColors];
1194 SkScalar stopsArray[kMaxRandomGradientColors];
1195 SkScalar* stops = stopsArray;
1196 SkShader::TileMode tm;
joshualitt0067ff52015-07-08 14:26:19 -07001197 int colorCount = RandomGradientParams(d->fRandom, colors, &stops, &tm);
reed8a21c9f2016-03-08 18:50:00 -08001198 auto shader = SkGradientShader::MakeTwoPointConical(center1, radius1, center2, radius2,
1199 colors, stops, colorCount, tm);
brianosman839345d2016-07-22 11:04:53 -07001200 SkMatrix viewMatrix = GrTest::TestMatrix(d->fRandom);
1201 sk_sp<GrFragmentProcessor> fp = shader->asFragmentProcessor(SkShader::AsFPArgs(
brianosman1638c0d2016-07-25 05:12:53 -07001202 d->fContext, &viewMatrix, NULL, kNone_SkFilterQuality, nullptr,
1203 SkSourceGammaTreatment::kRespect));
bsalomonc21b09e2015-08-28 18:46:56 -07001204 GrAlwaysAssert(fp);
joshualitt8ca93e72015-07-08 06:51:43 -07001205 return fp;
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001206}
1207
fmenozzi55d318d2016-08-09 08:05:57 -07001208CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor
1209 ::GLSLCircleOutside2PtConicalProcessor(const GrProcessor& processor)
halcanary96fcdcc2015-08-27 07:41:13 -07001210 : fVSVaryingName(nullptr)
1211 , fFSVaryingName(nullptr)
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001212 , fCachedCenterX(SK_ScalarMax)
1213 , fCachedCenterY(SK_ScalarMax)
1214 , fCachedA(SK_ScalarMax)
1215 , fCachedB(SK_ScalarMax)
1216 , fCachedC(SK_ScalarMax)
1217 , fCachedTLimit(SK_ScalarMax) {
joshualittb0a8a372014-09-23 09:50:21 -07001218 const CircleOutside2PtConicalEffect& data = processor.cast<CircleOutside2PtConicalEffect>();
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001219 fIsFlipped = data.isFlipped();
1220 }
1221
fmenozzi55d318d2016-08-09 08:05:57 -07001222void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::emitCode(EmitArgs& args) {
wangyix7c157a92015-07-22 15:08:53 -07001223 const CircleOutside2PtConicalEffect& ge = args.fFp.cast<CircleOutside2PtConicalEffect>();
egdaniel7ea439b2015-12-03 09:20:44 -08001224 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
1225 this->emitUniforms(uniformHandler, ge);
cdalton5e58cee2016-02-11 12:49:47 -08001226 fCenterUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001227 kVec2f_GrSLType, kDefault_GrSLPrecision,
1228 "Conical2FSCenter");
cdalton5e58cee2016-02-11 12:49:47 -08001229 fParamUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
egdaniel7ea439b2015-12-03 09:20:44 -08001230 kVec4f_GrSLType, kDefault_GrSLPrecision,
1231 "Conical2FSParams");
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001232 SkString tName("t");
1233
egdaniel7ea439b2015-12-03 09:20:44 -08001234 GrGLSLShaderVar center = uniformHandler->getUniformVariable(fCenterUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001235 // params.x = A
1236 // params.y = B
1237 // params.z = C
egdaniel7ea439b2015-12-03 09:20:44 -08001238 GrGLSLShaderVar params = uniformHandler->getUniformVariable(fParamUni);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001239
1240 // if we have a vec3 from being in perspective, convert it to a vec2 first
cdalton85285412016-02-18 12:37:07 -08001241 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
bsalomon1a1aa932016-09-12 09:30:36 -07001242 SkString coords2DString = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
skia.committer@gmail.comede0c5c2014-04-23 03:04:11 +00001243 const char* coords2D = coords2DString.c_str();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001244
1245 // output will default to transparent black (we simply won't write anything
1246 // else to it if invalid, instead of discarding or returning prematurely)
egdaniel4ca2e602015-11-18 08:01:26 -08001247 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 +00001248
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001249 // p = coords2D
1250 // e = center end
1251 // r = radius end
1252 // A = dot(e, e) - r^2 + 2 * r - 1
1253 // B = (r -1) / A
1254 // C = 1 / A
1255 // d = dot(e, p) + B
1256 // t = d +/- sqrt(d^2 - A * dot(p, p) + C)
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001257
egdaniel4ca2e602015-11-18 08:01:26 -08001258 fragBuilder->codeAppendf("\tfloat pDotp = dot(%s, %s);\n", coords2D, coords2D);
1259 fragBuilder->codeAppendf("\tfloat d = dot(%s, %s) + %s.y;\n", coords2D, center.c_str(),
1260 params.c_str());
1261 fragBuilder->codeAppendf("\tfloat deter = d * d - %s.x * pDotp + %s.z;\n", params.c_str(),
1262 params.c_str());
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001263
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001264 // Must check to see if we flipped the circle order (to make sure start radius < end radius)
1265 // If so we must also flip sign on sqrt
1266 if (!fIsFlipped) {
egdaniel4ca2e602015-11-18 08:01:26 -08001267 fragBuilder->codeAppendf("\tfloat %s = d + sqrt(deter);\n", tName.c_str());
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001268 } else {
egdaniel4ca2e602015-11-18 08:01:26 -08001269 fragBuilder->codeAppendf("\tfloat %s = d - sqrt(deter);\n", tName.c_str());
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001270 }
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001271
egdaniel7ea439b2015-12-03 09:20:44 -08001272 fragBuilder->codeAppendf("\tif (%s >= %s.w && deter >= 0.0) {\n",
1273 tName.c_str(), params.c_str());
egdaniel4ca2e602015-11-18 08:01:26 -08001274 fragBuilder->codeAppend("\t\t");
egdaniel7ea439b2015-12-03 09:20:44 -08001275 this->emitColor(fragBuilder,
1276 uniformHandler,
egdaniela2e3e0f2015-11-19 07:23:45 -08001277 args.fGLSLCaps,
egdaniel4ca2e602015-11-18 08:01:26 -08001278 ge,
1279 tName.c_str(),
1280 args.fOutputColor,
1281 args.fInputColor,
cdalton3f6f76f2016-04-11 12:18:09 -07001282 args.fTexSamplers);
egdaniel4ca2e602015-11-18 08:01:26 -08001283 fragBuilder->codeAppend("\t}\n");
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001284}
1285
fmenozzi55d318d2016-08-09 08:05:57 -07001286void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::onSetData(
1287 const GrGLSLProgramDataManager& pdman,
egdaniel018fb622015-10-28 07:26:40 -07001288 const GrProcessor& processor) {
wangyixb1daa862015-08-18 11:29:31 -07001289 INHERITED::onSetData(pdman, processor);
joshualittb0a8a372014-09-23 09:50:21 -07001290 const CircleOutside2PtConicalEffect& data = processor.cast<CircleOutside2PtConicalEffect>();
commit-bot@chromium.org44d83c12014-04-21 13:10:25 +00001291 SkASSERT(data.isFlipped() == fIsFlipped);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001292 SkScalar centerX = data.centerX();
1293 SkScalar centerY = data.centerY();
1294 SkScalar A = data.A();
1295 SkScalar B = data.B();
1296 SkScalar C = data.C();
1297 SkScalar tLimit = data.tLimit();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001298
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001299 if (fCachedCenterX != centerX || fCachedCenterY != centerY ||
1300 fCachedA != A || fCachedB != B || fCachedC != C || fCachedTLimit != tLimit) {
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001301
kkinnunen7510b222014-07-30 00:04:16 -07001302 pdman.set2f(fCenterUni, SkScalarToFloat(centerX), SkScalarToFloat(centerY));
1303 pdman.set4f(fParamUni, SkScalarToFloat(A), SkScalarToFloat(B), SkScalarToFloat(C),
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001304 SkScalarToFloat(tLimit));
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001305
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001306 fCachedCenterX = centerX;
1307 fCachedCenterY = centerY;
1308 fCachedA = A;
1309 fCachedB = B;
1310 fCachedC = C;
1311 fCachedTLimit = tLimit;
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001312 }
1313}
1314
fmenozzi55d318d2016-08-09 08:05:57 -07001315void CircleOutside2PtConicalEffect::GLSLCircleOutside2PtConicalProcessor::GenKey(
1316 const GrProcessor& processor,
1317 const GrGLSLCaps&, GrProcessorKeyBuilder* b) {
bsalomon63e99f72014-07-21 08:03:14 -07001318 uint32_t* key = b->add32n(2);
joshualittb0a8a372014-09-23 09:50:21 -07001319 key[0] = GenBaseGradientKey(processor);
1320 key[1] = processor.cast<CircleOutside2PtConicalEffect>().isFlipped();
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001321}
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001322
1323//////////////////////////////////////////////////////////////////////////////
1324
bungeman06ca8ec2016-06-09 08:01:03 -07001325sk_sp<GrFragmentProcessor> Gr2PtConicalGradientEffect::Make(GrContext* ctx,
1326 const SkTwoPointConicalGradient& shader,
1327 SkShader::TileMode tm,
1328 const SkMatrix* localMatrix) {
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001329 SkMatrix matrix;
1330 if (!shader.getLocalMatrix().invert(&matrix)) {
halcanary96fcdcc2015-08-27 07:41:13 -07001331 return nullptr;
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001332 }
commit-bot@chromium.org96fb7482014-05-09 20:28:11 +00001333 if (localMatrix) {
1334 SkMatrix inv;
1335 if (!localMatrix->invert(&inv)) {
halcanary96fcdcc2015-08-27 07:41:13 -07001336 return nullptr;
commit-bot@chromium.org96fb7482014-05-09 20:28:11 +00001337 }
1338 matrix.postConcat(inv);
1339 }
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001340
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001341 if (shader.getStartRadius() < kErrorTol) {
1342 SkScalar focalX;
1343 ConicalType type = set_matrix_focal_conical(shader, &matrix, &focalX);
1344 if (type == kInside_ConicalType) {
bungeman06ca8ec2016-06-09 08:01:03 -07001345 return FocalInside2PtConicalEffect::Make(ctx, shader, matrix, tm, focalX);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001346 } else if(type == kEdge_ConicalType) {
1347 set_matrix_edge_conical(shader, &matrix);
bungeman06ca8ec2016-06-09 08:01:03 -07001348 return Edge2PtConicalEffect::Make(ctx, shader, matrix, tm);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001349 } else {
bungeman06ca8ec2016-06-09 08:01:03 -07001350 return FocalOutside2PtConicalEffect::Make(ctx, shader, matrix, tm, focalX);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001351 }
1352 }
1353
1354 CircleConicalInfo info;
1355 ConicalType type = set_matrix_circle_conical(shader, &matrix, &info);
1356
1357 if (type == kInside_ConicalType) {
bungeman06ca8ec2016-06-09 08:01:03 -07001358 return CircleInside2PtConicalEffect::Make(ctx, shader, matrix, tm, info);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001359 } else if (type == kEdge_ConicalType) {
1360 set_matrix_edge_conical(shader, &matrix);
bungeman06ca8ec2016-06-09 08:01:03 -07001361 return Edge2PtConicalEffect::Make(ctx, shader, matrix, tm);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001362 } else {
bungeman06ca8ec2016-06-09 08:01:03 -07001363 return CircleOutside2PtConicalEffect::Make(ctx, shader, matrix, tm, info);
commit-bot@chromium.orgc8379d72014-04-22 20:56:37 +00001364 }
commit-bot@chromium.org2af1a2d2014-04-04 13:50:50 +00001365}
1366
commit-bot@chromium.orgaa64fbf2014-04-03 14:59:19 +00001367#endif