OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2014 Google Inc. | 2 * Copyright 2014 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkTwoPointConicalGradient_gpu.h" | 8 #include "SkTwoPointConicalGradient_gpu.h" |
9 | 9 |
10 #include "SkTwoPointConicalGradient.h" | 10 #include "SkTwoPointConicalGradient.h" |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
49 return CreateEffectRef(effect); | 49 return CreateEffectRef(effect); |
50 } | 50 } |
51 | 51 |
52 virtual ~Default2PtConicalEffect() { } | 52 virtual ~Default2PtConicalEffect() { } |
53 | 53 |
54 static const char* Name() { return "Two-Point Conical Gradient"; } | 54 static const char* Name() { return "Two-Point Conical Gradient"; } |
55 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; | 55 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; |
56 | 56 |
57 // The radial gradient parameters can collapse to a linear (instead of quadr
atic) equation. | 57 // The radial gradient parameters can collapse to a linear (instead of quadr
atic) equation. |
58 bool isDegenerate() const { return SkScalarAbs(fDiffRadius) == SkScalarAbs(f
CenterX1); } | 58 bool isDegenerate() const { return SkScalarAbs(fDiffRadius) == SkScalarAbs(f
CenterX1); } |
| 59 bool isFlipped() const { return fIsFlipped; } |
59 SkScalar center() const { return fCenterX1; } | 60 SkScalar center() const { return fCenterX1; } |
60 SkScalar diffRadius() const { return fDiffRadius; } | 61 SkScalar diffRadius() const { return fDiffRadius; } |
61 SkScalar radius() const { return fRadius0; } | 62 SkScalar radius() const { return fRadius0; } |
62 | 63 |
63 typedef GLDefault2PtConicalEffect GLEffect; | 64 typedef GLDefault2PtConicalEffect GLEffect; |
64 | 65 |
65 private: | 66 private: |
66 virtual bool onIsEqual(const GrEffect& sBase) const SK_OVERRIDE { | 67 virtual bool onIsEqual(const GrEffect& sBase) const SK_OVERRIDE { |
67 const Default2PtConicalEffect& s = CastEffect<Default2PtConicalEffect>(s
Base); | 68 const Default2PtConicalEffect& s = CastEffect<Default2PtConicalEffect>(s
Base); |
68 return (INHERITED::onIsEqual(sBase) && | 69 return (INHERITED::onIsEqual(sBase) && |
69 this->fCenterX1 == s.fCenterX1 && | 70 this->fCenterX1 == s.fCenterX1 && |
70 this->fRadius0 == s.fRadius0 && | 71 this->fRadius0 == s.fRadius0 && |
71 this->fDiffRadius == s.fDiffRadius); | 72 this->fDiffRadius == s.fDiffRadius && |
| 73 this->fIsFlipped == s.fIsFlipped); |
72 } | 74 } |
73 | 75 |
74 Default2PtConicalEffect(GrContext* ctx, | 76 Default2PtConicalEffect(GrContext* ctx, |
75 const SkTwoPointConicalGradient& shader, | 77 const SkTwoPointConicalGradient& shader, |
76 const SkMatrix& matrix, | 78 const SkMatrix& matrix, |
77 SkShader::TileMode tm) | 79 SkShader::TileMode tm) |
78 : INHERITED(ctx, shader, matrix, tm), | 80 : INHERITED(ctx, shader, matrix, tm), |
79 fCenterX1(shader.getCenterX1()), | 81 fCenterX1(shader.getCenterX1()), |
80 fRadius0(shader.getStartRadius()), | 82 fRadius0(shader.getStartRadius()), |
81 fDiffRadius(shader.getDiffRadius()) { | 83 fDiffRadius(shader.getDiffRadius()), |
| 84 fIsFlipped(shader.isFlippedGrad()) { |
82 // We pass the linear part of the quadratic as a varying. | 85 // We pass the linear part of the quadratic as a varying. |
83 // float b = -2.0 * (fCenterX1 * x + fRadius0 * fDiffRadius * z) | 86 // float b = -2.0 * (fCenterX1 * x + fRadius0 * fDiffRadius * z) |
84 fBTransform = this->getCoordTransform(); | 87 fBTransform = this->getCoordTransform(); |
85 SkMatrix& bMatrix = *fBTransform.accessMatrix(); | 88 SkMatrix& bMatrix = *fBTransform.accessMatrix(); |
86 SkScalar r0dr = SkScalarMul(fRadius0, fDiffRadius); | 89 SkScalar r0dr = SkScalarMul(fRadius0, fDiffRadius); |
87 bMatrix[SkMatrix::kMScaleX] = -2 * (SkScalarMul(fCenterX1, bMatrix[SkMat
rix::kMScaleX]) + | 90 bMatrix[SkMatrix::kMScaleX] = -2 * (SkScalarMul(fCenterX1, bMatrix[SkMat
rix::kMScaleX]) + |
88 SkScalarMul(r0dr, bMatrix[SkMatrix::
kMPersp0])); | 91 SkScalarMul(r0dr, bMatrix[SkMatrix::
kMPersp0])); |
89 bMatrix[SkMatrix::kMSkewX] = -2 * (SkScalarMul(fCenterX1, bMatrix[SkMatr
ix::kMSkewX]) + | 92 bMatrix[SkMatrix::kMSkewX] = -2 * (SkScalarMul(fCenterX1, bMatrix[SkMatr
ix::kMSkewX]) + |
90 SkScalarMul(r0dr, bMatrix[SkMatrix::k
MPersp1])); | 93 SkScalarMul(r0dr, bMatrix[SkMatrix::k
MPersp1])); |
91 bMatrix[SkMatrix::kMTransX] = -2 * (SkScalarMul(fCenterX1, bMatrix[SkMat
rix::kMTransX]) + | 94 bMatrix[SkMatrix::kMTransX] = -2 * (SkScalarMul(fCenterX1, bMatrix[SkMat
rix::kMTransX]) + |
92 SkScalarMul(r0dr, bMatrix[SkMatrix::
kMPersp2])); | 95 SkScalarMul(r0dr, bMatrix[SkMatrix::
kMPersp2])); |
93 this->addCoordTransform(&fBTransform); | 96 this->addCoordTransform(&fBTransform); |
94 } | 97 } |
95 | 98 |
96 GR_DECLARE_EFFECT_TEST; | 99 GR_DECLARE_EFFECT_TEST; |
97 | 100 |
98 // @{ | 101 // @{ |
99 // Cache of values - these can change arbitrarily, EXCEPT | 102 // Cache of values - these can change arbitrarily, EXCEPT |
100 // we shouldn't change between degenerate and non-degenerate?! | 103 // we shouldn't change between degenerate and non-degenerate?! |
101 | 104 |
102 GrCoordTransform fBTransform; | 105 GrCoordTransform fBTransform; |
103 SkScalar fCenterX1; | 106 SkScalar fCenterX1; |
104 SkScalar fRadius0; | 107 SkScalar fRadius0; |
105 SkScalar fDiffRadius; | 108 SkScalar fDiffRadius; |
| 109 bool fIsFlipped; |
106 | 110 |
107 // @} | 111 // @} |
108 | 112 |
109 typedef GrGradientEffect INHERITED; | 113 typedef GrGradientEffect INHERITED; |
110 }; | 114 }; |
111 | 115 |
112 class GLDefault2PtConicalEffect : public GrGLGradientEffect { | 116 class GLDefault2PtConicalEffect : public GrGLGradientEffect { |
113 public: | 117 public: |
114 GLDefault2PtConicalEffect(const GrBackendEffectFactory& factory, const GrDra
wEffect&); | 118 GLDefault2PtConicalEffect(const GrBackendEffectFactory& factory, const GrDra
wEffect&); |
115 virtual ~GLDefault2PtConicalEffect() { } | 119 virtual ~GLDefault2PtConicalEffect() { } |
116 | 120 |
117 virtual void emitCode(GrGLShaderBuilder*, | 121 virtual void emitCode(GrGLShaderBuilder*, |
118 const GrDrawEffect&, | 122 const GrDrawEffect&, |
119 EffectKey, | 123 EffectKey, |
120 const char* outputColor, | 124 const char* outputColor, |
121 const char* inputColor, | 125 const char* inputColor, |
122 const TransformedCoordsArray&, | 126 const TransformedCoordsArray&, |
123 const TextureSamplerArray&) SK_OVERRIDE; | 127 const TextureSamplerArray&) SK_OVERRIDE; |
124 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER
RIDE; | 128 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVER
RIDE; |
125 | 129 |
126 static EffectKey GenKey(const GrDrawEffect&, const GrGLCaps& caps); | 130 static EffectKey GenKey(const GrDrawEffect&, const GrGLCaps& caps); |
127 | 131 |
128 protected: | 132 protected: |
129 UniformHandle fParamUni; | 133 UniformHandle fParamUni; |
130 | 134 |
131 const char* fVSVaryingName; | 135 const char* fVSVaryingName; |
132 const char* fFSVaryingName; | 136 const char* fFSVaryingName; |
133 | 137 |
134 bool fIsDegenerate; | 138 bool fIsDegenerate; |
| 139 bool fIsFlipped; |
135 | 140 |
136 // @{ | 141 // @{ |
137 /// Values last uploaded as uniforms | 142 /// Values last uploaded as uniforms |
138 | 143 |
139 SkScalar fCachedCenter; | 144 SkScalar fCachedCenter; |
140 SkScalar fCachedRadius; | 145 SkScalar fCachedRadius; |
141 SkScalar fCachedDiffRadius; | 146 SkScalar fCachedDiffRadius; |
142 | 147 |
143 // @} | 148 // @} |
144 | 149 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
187 const GrDrawEffect& drawEffect) | 192 const GrDrawEffect& drawEffect) |
188 : INHERITED(factory) | 193 : INHERITED(factory) |
189 , fVSVaryingName(NULL) | 194 , fVSVaryingName(NULL) |
190 , fFSVaryingName(NULL) | 195 , fFSVaryingName(NULL) |
191 , fCachedCenter(SK_ScalarMax) | 196 , fCachedCenter(SK_ScalarMax) |
192 , fCachedRadius(-SK_ScalarMax) | 197 , fCachedRadius(-SK_ScalarMax) |
193 , fCachedDiffRadius(-SK_ScalarMax) { | 198 , fCachedDiffRadius(-SK_ScalarMax) { |
194 | 199 |
195 const Default2PtConicalEffect& data = drawEffect.castEffect<Default2PtConica
lEffect>(); | 200 const Default2PtConicalEffect& data = drawEffect.castEffect<Default2PtConica
lEffect>(); |
196 fIsDegenerate = data.isDegenerate(); | 201 fIsDegenerate = data.isDegenerate(); |
| 202 fIsFlipped = data.isFlipped(); |
197 } | 203 } |
198 | 204 |
199 void GLDefault2PtConicalEffect::emitCode(GrGLShaderBuilder* builder, | 205 void GLDefault2PtConicalEffect::emitCode(GrGLShaderBuilder* builder, |
200 const GrDrawEffect&, | 206 const GrDrawEffect&, |
201 EffectKey key, | 207 EffectKey key, |
202 const char* outputColor, | 208 const char* outputColor, |
203 const char* inputColor, | 209 const char* inputColor, |
204 const TransformedCoordsArray& coords, | 210 const TransformedCoordsArray& coords, |
205 const TextureSamplerArray& samplers) { | 211 const TextureSamplerArray& samplers) { |
206 this->emitUniforms(builder, key); | 212 this->emitUniforms(builder, key); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
274 // r0 = q * params[1] | 280 // r0 = q * params[1] |
275 builder->fsCodeAppendf("\t\tfloat %s = %s * %s;\n", r0Name.c_str(), | 281 builder->fsCodeAppendf("\t\tfloat %s = %s * %s;\n", r0Name.c_str(), |
276 qName.c_str(), p1.c_str()); | 282 qName.c_str(), p1.c_str()); |
277 // r1 = c / q | 283 // r1 = c / q |
278 builder->fsCodeAppendf("\t\tfloat %s = %s / %s;\n", r1Name.c_str(), | 284 builder->fsCodeAppendf("\t\tfloat %s = %s / %s;\n", r1Name.c_str(), |
279 cName.c_str(), qName.c_str()); | 285 cName.c_str(), qName.c_str()); |
280 | 286 |
281 // Note: If there are two roots that both generate radius(t) > 0, the | 287 // Note: If there are two roots that both generate radius(t) > 0, the |
282 // Canvas spec says to choose the larger t. | 288 // Canvas spec says to choose the larger t. |
283 | 289 |
284 // so we'll look at the larger one first: | 290 // so we'll look at the larger one first (or smaller if flipped): |
285 builder->fsCodeAppendf("\t\tfloat %s = max(%s, %s);\n", tName.c_str(), | 291 if (!fIsFlipped) { |
286 r0Name.c_str(), r1Name.c_str()); | 292 builder->fsCodeAppendf("\t\tfloat %s = max(%s, %s);\n", tName.c_str(
), |
| 293 r0Name.c_str(), r1Name.c_str()); |
| 294 } else { |
| 295 builder->fsCodeAppendf("\t\tfloat %s = min(%s, %s);\n", tName.c_str(
), |
| 296 r0Name.c_str(), r1Name.c_str()); |
| 297 } |
287 | 298 |
288 // if r(t) > 0, then we're done; t will be our x coordinate | 299 // if r(t) > 0, then we're done; t will be our x coordinate |
289 builder->fsCodeAppendf("\t\tif (%s * %s + %s > 0.0) {\n", tName.c_str(), | 300 builder->fsCodeAppendf("\t\tif (%s * %s + %s > 0.0) {\n", tName.c_str(), |
290 p5.c_str(), p3.c_str()); | 301 p5.c_str(), p3.c_str()); |
291 | 302 |
292 builder->fsCodeAppend("\t\t"); | 303 builder->fsCodeAppend("\t\t"); |
293 this->emitColor(builder, tName.c_str(), key, outputColor, inputColor, sa
mplers); | 304 this->emitColor(builder, tName.c_str(), key, outputColor, inputColor, sa
mplers); |
294 | 305 |
295 // otherwise, if r(t) for the larger root was <= 0, try the other root | 306 // otherwise, if r(t) for the larger root was <= 0, try the other root |
296 builder->fsCodeAppend("\t\t} else {\n"); | 307 builder->fsCodeAppend("\t\t} else {\n"); |
297 builder->fsCodeAppendf("\t\t\t%s = min(%s, %s);\n", tName.c_str(), | 308 if (!fIsFlipped) { |
298 r0Name.c_str(), r1Name.c_str()); | 309 builder->fsCodeAppendf("\t\t\t%s = min(%s, %s);\n", tName.c_str(), |
| 310 r0Name.c_str(), r1Name.c_str()); |
| 311 } else { |
| 312 builder->fsCodeAppendf("\t\t\t%s = max(%s, %s);\n", tName.c_str(), |
| 313 r0Name.c_str(), r1Name.c_str()); |
| 314 } |
299 | 315 |
300 // if r(t) > 0 for the smaller root, then t will be our x coordinate | 316 // if r(t) > 0 for the smaller root, then t will be our x coordinate |
301 builder->fsCodeAppendf("\t\t\tif (%s * %s + %s > 0.0) {\n", | 317 builder->fsCodeAppendf("\t\t\tif (%s * %s + %s > 0.0) {\n", |
302 tName.c_str(), p5.c_str(), p3.c_str()); | 318 tName.c_str(), p5.c_str(), p3.c_str()); |
303 | 319 |
304 builder->fsCodeAppend("\t\t\t"); | 320 builder->fsCodeAppend("\t\t\t"); |
305 this->emitColor(builder, tName.c_str(), key, outputColor, inputColor, sa
mplers); | 321 this->emitColor(builder, tName.c_str(), key, outputColor, inputColor, sa
mplers); |
306 | 322 |
307 // end if (r(t) > 0) for smaller root | 323 // end if (r(t) > 0) for smaller root |
308 builder->fsCodeAppend("\t\t\t}\n"); | 324 builder->fsCodeAppend("\t\t\t}\n"); |
(...skipping 14 matching lines...) Expand all Loading... |
323 this->emitColor(builder, tName.c_str(), key, outputColor, inputColor, sa
mplers); | 339 this->emitColor(builder, tName.c_str(), key, outputColor, inputColor, sa
mplers); |
324 builder->fsCodeAppend("\t}\n"); | 340 builder->fsCodeAppend("\t}\n"); |
325 } | 341 } |
326 } | 342 } |
327 | 343 |
328 void GLDefault2PtConicalEffect::setData(const GrGLUniformManager& uman, | 344 void GLDefault2PtConicalEffect::setData(const GrGLUniformManager& uman, |
329 const GrDrawEffect& drawEffect) { | 345 const GrDrawEffect& drawEffect) { |
330 INHERITED::setData(uman, drawEffect); | 346 INHERITED::setData(uman, drawEffect); |
331 const Default2PtConicalEffect& data = drawEffect.castEffect<Default2PtConica
lEffect>(); | 347 const Default2PtConicalEffect& data = drawEffect.castEffect<Default2PtConica
lEffect>(); |
332 SkASSERT(data.isDegenerate() == fIsDegenerate); | 348 SkASSERT(data.isDegenerate() == fIsDegenerate); |
| 349 SkASSERT(data.isFlipped() == fIsFlipped); |
333 SkScalar centerX1 = data.center(); | 350 SkScalar centerX1 = data.center(); |
334 SkScalar radius0 = data.radius(); | 351 SkScalar radius0 = data.radius(); |
335 SkScalar diffRadius = data.diffRadius(); | 352 SkScalar diffRadius = data.diffRadius(); |
336 | 353 |
337 if (fCachedCenter != centerX1 || | 354 if (fCachedCenter != centerX1 || |
338 fCachedRadius != radius0 || | 355 fCachedRadius != radius0 || |
339 fCachedDiffRadius != diffRadius) { | 356 fCachedDiffRadius != diffRadius) { |
340 | 357 |
341 SkScalar a = SkScalarMul(centerX1, centerX1) - diffRadius * diffRadius; | 358 SkScalar a = SkScalarMul(centerX1, centerX1) - diffRadius * diffRadius; |
342 | 359 |
(...skipping 15 matching lines...) Expand all Loading... |
358 fCachedCenter = centerX1; | 375 fCachedCenter = centerX1; |
359 fCachedRadius = radius0; | 376 fCachedRadius = radius0; |
360 fCachedDiffRadius = diffRadius; | 377 fCachedDiffRadius = diffRadius; |
361 } | 378 } |
362 } | 379 } |
363 | 380 |
364 GrGLEffect::EffectKey GLDefault2PtConicalEffect::GenKey(const GrDrawEffect& draw
Effect, | 381 GrGLEffect::EffectKey GLDefault2PtConicalEffect::GenKey(const GrDrawEffect& draw
Effect, |
365 const GrGLCaps&) { | 382 const GrGLCaps&) { |
366 enum { | 383 enum { |
367 kIsDegenerate = 1 << kBaseKeyBitCnt, | 384 kIsDegenerate = 1 << kBaseKeyBitCnt, |
| 385 kIsFlipped = 1 << (kBaseKeyBitCnt + 1), |
368 }; | 386 }; |
369 | 387 |
370 EffectKey key = GenBaseGradientKey(drawEffect); | 388 EffectKey key = GenBaseGradientKey(drawEffect); |
371 if (drawEffect.castEffect<Default2PtConicalEffect>().isDegenerate()) { | 389 if (drawEffect.castEffect<Default2PtConicalEffect>().isDegenerate()) { |
372 key |= kIsDegenerate; | 390 key |= kIsDegenerate; |
373 } | 391 } |
| 392 if (drawEffect.castEffect<Default2PtConicalEffect>().isFlipped()) { |
| 393 key |= kIsFlipped; |
| 394 } |
374 return key; | 395 return key; |
375 } | 396 } |
376 | 397 |
377 ////////////////////////////////////////////////////////////////////////////// | 398 ////////////////////////////////////////////////////////////////////////////// |
378 | 399 |
379 GrEffectRef* Gr2PtConicalGradientEffect::Create(GrContext* ctx, | 400 GrEffectRef* Gr2PtConicalGradientEffect::Create(GrContext* ctx, |
380 const SkTwoPointConicalGradient&
shader, | 401 const SkTwoPointConicalGradient&
shader, |
381 SkShader::TileMode tm) { | 402 SkShader::TileMode tm) { |
382 | 403 |
383 SkMatrix matrix; | 404 SkMatrix matrix; |
384 if (!shader.getLocalMatrix().invert(&matrix)) { | 405 if (!shader.getLocalMatrix().invert(&matrix)) { |
385 return NULL; | 406 return NULL; |
386 } | 407 } |
387 | 408 |
388 set_matrix_default_conical(shader, &matrix); | 409 set_matrix_default_conical(shader, &matrix); |
389 return Default2PtConicalEffect::Create(ctx, shader, matrix, tm); | 410 return Default2PtConicalEffect::Create(ctx, shader, matrix, tm); |
390 } | 411 } |
391 | 412 |
392 #endif | 413 #endif |
OLD | NEW |