Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / effects / SkLightingImageFilter.cpp
1 /*
2  * Copyright 2012 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7
8 #include "SkLightingImageFilter.h"
9 #include "SkBitmap.h"
10 #include "SkColorPriv.h"
11 #include "SkReadBuffer.h"
12 #include "SkWriteBuffer.h"
13 #include "SkReadBuffer.h"
14 #include "SkWriteBuffer.h"
15 #include "SkTypes.h"
16
17 #if SK_SUPPORT_GPU
18 #include "effects/GrSingleTextureEffect.h"
19 #include "gl/GrGLEffect.h"
20 #include "gl/GrGLShaderBuilder.h"
21 #include "GrEffect.h"
22 #include "GrTBackendEffectFactory.h"
23
24 class GrGLDiffuseLightingEffect;
25 class GrGLSpecularLightingEffect;
26
27 // For brevity
28 typedef GrGLProgramDataManager::UniformHandle UniformHandle;
29 #endif
30
31 namespace {
32
33 const SkScalar gOneThird = SkScalarInvert(SkIntToScalar(3));
34 const SkScalar gTwoThirds = SkScalarDiv(SkIntToScalar(2), SkIntToScalar(3));
35 const SkScalar gOneHalf = 0.5f;
36 const SkScalar gOneQuarter = 0.25f;
37
38 #if SK_SUPPORT_GPU
39 void setUniformPoint3(const GrGLProgramDataManager& pdman, UniformHandle uni, const SkPoint3& point) {
40     GR_STATIC_ASSERT(sizeof(SkPoint3) == 3 * sizeof(GrGLfloat));
41     pdman.set3fv(uni, 1, &point.fX);
42 }
43
44 void setUniformNormal3(const GrGLProgramDataManager& pdman, UniformHandle uni, const SkPoint3& point) {
45     setUniformPoint3(pdman, uni, SkPoint3(point.fX, point.fY, point.fZ));
46 }
47 #endif
48
49 // Shift matrix components to the left, as we advance pixels to the right.
50 inline void shiftMatrixLeft(int m[9]) {
51     m[0] = m[1];
52     m[3] = m[4];
53     m[6] = m[7];
54     m[1] = m[2];
55     m[4] = m[5];
56     m[7] = m[8];
57 }
58
59 class DiffuseLightingType {
60 public:
61     DiffuseLightingType(SkScalar kd)
62         : fKD(kd) {}
63     SkPMColor light(const SkPoint3& normal, const SkPoint3& surfaceTolight, const SkPoint3& lightColor) const {
64         SkScalar colorScale = SkScalarMul(fKD, normal.dot(surfaceTolight));
65         colorScale = SkScalarClampMax(colorScale, SK_Scalar1);
66         SkPoint3 color(lightColor * colorScale);
67         return SkPackARGB32(255,
68                             SkClampMax(SkScalarRoundToInt(color.fX), 255),
69                             SkClampMax(SkScalarRoundToInt(color.fY), 255),
70                             SkClampMax(SkScalarRoundToInt(color.fZ), 255));
71     }
72 private:
73     SkScalar fKD;
74 };
75
76 class SpecularLightingType {
77 public:
78     SpecularLightingType(SkScalar ks, SkScalar shininess)
79         : fKS(ks), fShininess(shininess) {}
80     SkPMColor light(const SkPoint3& normal, const SkPoint3& surfaceTolight, const SkPoint3& lightColor) const {
81         SkPoint3 halfDir(surfaceTolight);
82         halfDir.fZ += SK_Scalar1;        // eye position is always (0, 0, 1)
83         halfDir.normalize();
84         SkScalar colorScale = SkScalarMul(fKS,
85             SkScalarPow(normal.dot(halfDir), fShininess));
86         colorScale = SkScalarClampMax(colorScale, SK_Scalar1);
87         SkPoint3 color(lightColor * colorScale);
88         return SkPackARGB32(SkClampMax(SkScalarRoundToInt(color.maxComponent()), 255),
89                             SkClampMax(SkScalarRoundToInt(color.fX), 255),
90                             SkClampMax(SkScalarRoundToInt(color.fY), 255),
91                             SkClampMax(SkScalarRoundToInt(color.fZ), 255));
92     }
93 private:
94     SkScalar fKS;
95     SkScalar fShininess;
96 };
97
98 inline SkScalar sobel(int a, int b, int c, int d, int e, int f, SkScalar scale) {
99     return SkScalarMul(SkIntToScalar(-a + b - 2 * c + 2 * d -e + f), scale);
100 }
101
102 inline SkPoint3 pointToNormal(SkScalar x, SkScalar y, SkScalar surfaceScale) {
103     SkPoint3 vector(SkScalarMul(-x, surfaceScale),
104                     SkScalarMul(-y, surfaceScale),
105                     SK_Scalar1);
106     vector.normalize();
107     return vector;
108 }
109
110 inline SkPoint3 topLeftNormal(int m[9], SkScalar surfaceScale) {
111     return pointToNormal(sobel(0, 0, m[4], m[5], m[7], m[8], gTwoThirds),
112                          sobel(0, 0, m[4], m[7], m[5], m[8], gTwoThirds),
113                          surfaceScale);
114 }
115
116 inline SkPoint3 topNormal(int m[9], SkScalar surfaceScale) {
117     return pointToNormal(sobel(   0,    0, m[3], m[5], m[6], m[8], gOneThird),
118                          sobel(m[3], m[6], m[4], m[7], m[5], m[8], gOneHalf),
119                          surfaceScale);
120 }
121
122 inline SkPoint3 topRightNormal(int m[9], SkScalar surfaceScale) {
123     return pointToNormal(sobel(   0,    0, m[3], m[4], m[6], m[7], gTwoThirds),
124                          sobel(m[3], m[6], m[4], m[7],    0,    0, gTwoThirds),
125                          surfaceScale);
126 }
127
128 inline SkPoint3 leftNormal(int m[9], SkScalar surfaceScale) {
129     return pointToNormal(sobel(m[1], m[2], m[4], m[5], m[7], m[8], gOneHalf),
130                          sobel(   0,    0, m[1], m[7], m[2], m[8], gOneThird),
131                          surfaceScale);
132 }
133
134
135 inline SkPoint3 interiorNormal(int m[9], SkScalar surfaceScale) {
136     return pointToNormal(sobel(m[0], m[2], m[3], m[5], m[6], m[8], gOneQuarter),
137                          sobel(m[0], m[6], m[1], m[7], m[2], m[8], gOneQuarter),
138                          surfaceScale);
139 }
140
141 inline SkPoint3 rightNormal(int m[9], SkScalar surfaceScale) {
142     return pointToNormal(sobel(m[0], m[1], m[3], m[4], m[6], m[7], gOneHalf),
143                          sobel(m[0], m[6], m[1], m[7],    0,    0, gOneThird),
144                          surfaceScale);
145 }
146
147 inline SkPoint3 bottomLeftNormal(int m[9], SkScalar surfaceScale) {
148     return pointToNormal(sobel(m[1], m[2], m[4], m[5],    0,    0, gTwoThirds),
149                          sobel(   0,    0, m[1], m[4], m[2], m[5], gTwoThirds),
150                          surfaceScale);
151 }
152
153 inline SkPoint3 bottomNormal(int m[9], SkScalar surfaceScale) {
154     return pointToNormal(sobel(m[0], m[2], m[3], m[5],    0,    0, gOneThird),
155                          sobel(m[0], m[3], m[1], m[4], m[2], m[5], gOneHalf),
156                          surfaceScale);
157 }
158
159 inline SkPoint3 bottomRightNormal(int m[9], SkScalar surfaceScale) {
160     return pointToNormal(sobel(m[0], m[1], m[3], m[4], 0,  0, gTwoThirds),
161                          sobel(m[0], m[3], m[1], m[4], 0,  0, gTwoThirds),
162                          surfaceScale);
163 }
164
165 template <class LightingType, class LightType> void lightBitmap(const LightingType& lightingType, const SkLight* light, const SkBitmap& src, SkBitmap* dst, SkScalar surfaceScale, const SkIRect& bounds) {
166     SkASSERT(dst->width() == bounds.width() && dst->height() == bounds.height());
167     const LightType* l = static_cast<const LightType*>(light);
168     int left = bounds.left(), right = bounds.right();
169     int bottom = bounds.bottom();
170     int y = bounds.top();
171     SkPMColor* dptr = dst->getAddr32(0, 0);
172     {
173         int x = left;
174         const SkPMColor* row1 = src.getAddr32(x, y);
175         const SkPMColor* row2 = src.getAddr32(x, y + 1);
176         int m[9];
177         m[4] = SkGetPackedA32(*row1++);
178         m[5] = SkGetPackedA32(*row1++);
179         m[7] = SkGetPackedA32(*row2++);
180         m[8] = SkGetPackedA32(*row2++);
181         SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
182         *dptr++ = lightingType.light(topLeftNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
183         for (++x; x < right - 1; ++x)
184         {
185             shiftMatrixLeft(m);
186             m[5] = SkGetPackedA32(*row1++);
187             m[8] = SkGetPackedA32(*row2++);
188             surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
189             *dptr++ = lightingType.light(topNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
190         }
191         shiftMatrixLeft(m);
192         surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
193         *dptr++ = lightingType.light(topRightNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
194     }
195
196     for (++y; y < bottom - 1; ++y) {
197         int x = left;
198         const SkPMColor* row0 = src.getAddr32(x, y - 1);
199         const SkPMColor* row1 = src.getAddr32(x, y);
200         const SkPMColor* row2 = src.getAddr32(x, y + 1);
201         int m[9];
202         m[1] = SkGetPackedA32(*row0++);
203         m[2] = SkGetPackedA32(*row0++);
204         m[4] = SkGetPackedA32(*row1++);
205         m[5] = SkGetPackedA32(*row1++);
206         m[7] = SkGetPackedA32(*row2++);
207         m[8] = SkGetPackedA32(*row2++);
208         SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
209         *dptr++ = lightingType.light(leftNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
210         for (++x; x < right - 1; ++x) {
211             shiftMatrixLeft(m);
212             m[2] = SkGetPackedA32(*row0++);
213             m[5] = SkGetPackedA32(*row1++);
214             m[8] = SkGetPackedA32(*row2++);
215             surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
216             *dptr++ = lightingType.light(interiorNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
217         }
218         shiftMatrixLeft(m);
219         surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
220         *dptr++ = lightingType.light(rightNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
221     }
222
223     {
224         int x = left;
225         const SkPMColor* row0 = src.getAddr32(x, bottom - 2);
226         const SkPMColor* row1 = src.getAddr32(x, bottom - 1);
227         int m[9];
228         m[1] = SkGetPackedA32(*row0++);
229         m[2] = SkGetPackedA32(*row0++);
230         m[4] = SkGetPackedA32(*row1++);
231         m[5] = SkGetPackedA32(*row1++);
232         SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
233         *dptr++ = lightingType.light(bottomLeftNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
234         for (++x; x < right - 1; ++x)
235         {
236             shiftMatrixLeft(m);
237             m[2] = SkGetPackedA32(*row0++);
238             m[5] = SkGetPackedA32(*row1++);
239             surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
240             *dptr++ = lightingType.light(bottomNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
241         }
242         shiftMatrixLeft(m);
243         surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale);
244         *dptr++ = lightingType.light(bottomRightNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight));
245     }
246 }
247
248 SkPoint3 readPoint3(SkReadBuffer& buffer) {
249     SkPoint3 point;
250     point.fX = buffer.readScalar();
251     point.fY = buffer.readScalar();
252     point.fZ = buffer.readScalar();
253     buffer.validate(SkScalarIsFinite(point.fX) &&
254                     SkScalarIsFinite(point.fY) &&
255                     SkScalarIsFinite(point.fZ));
256     return point;
257 };
258
259 void writePoint3(const SkPoint3& point, SkWriteBuffer& buffer) {
260     buffer.writeScalar(point.fX);
261     buffer.writeScalar(point.fY);
262     buffer.writeScalar(point.fZ);
263 };
264
265 class SkDiffuseLightingImageFilter : public SkLightingImageFilter {
266 public:
267     SkDiffuseLightingImageFilter(SkLight* light, SkScalar surfaceScale,
268                                  SkScalar kd, SkImageFilter* input, const CropRect* cropRect);
269     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDiffuseLightingImageFilter)
270     SkScalar kd() const { return fKD; }
271
272 protected:
273     explicit SkDiffuseLightingImageFilter(SkReadBuffer& buffer);
274     virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE;
275     virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context&,
276                                SkBitmap* result, SkIPoint* offset) const SK_OVERRIDE;
277 #if SK_SUPPORT_GPU
278     virtual bool asNewEffect(GrEffect** effect, GrTexture*, const SkMatrix& matrix,
279                              const SkIRect& bounds) const SK_OVERRIDE;
280 #endif
281
282 private:
283     typedef SkLightingImageFilter INHERITED;
284     SkScalar fKD;
285 };
286
287 class SkSpecularLightingImageFilter : public SkLightingImageFilter {
288 public:
289     SkSpecularLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess, SkImageFilter* input, const CropRect* cropRect);
290     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSpecularLightingImageFilter)
291
292     SkScalar ks() const { return fKS; }
293     SkScalar shininess() const { return fShininess; }
294
295 protected:
296     explicit SkSpecularLightingImageFilter(SkReadBuffer& buffer);
297     virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE;
298     virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context&,
299                                SkBitmap* result, SkIPoint* offset) const SK_OVERRIDE;
300 #if SK_SUPPORT_GPU
301     virtual bool asNewEffect(GrEffect** effect, GrTexture*, const SkMatrix& matrix,
302                              const SkIRect& bounds) const SK_OVERRIDE;
303 #endif
304
305 private:
306     typedef SkLightingImageFilter INHERITED;
307     SkScalar fKS;
308     SkScalar fShininess;
309 };
310
311 #if SK_SUPPORT_GPU
312
313 class GrLightingEffect : public GrSingleTextureEffect {
314 public:
315     GrLightingEffect(GrTexture* texture, const SkLight* light, SkScalar surfaceScale, const SkMatrix& matrix);
316     virtual ~GrLightingEffect();
317
318     const SkLight* light() const { return fLight; }
319     SkScalar surfaceScale() const { return fSurfaceScale; }
320     const SkMatrix& filterMatrix() const { return fFilterMatrix; }
321
322     virtual void getConstantColorComponents(GrColor* color,
323                                             uint32_t* validFlags) const SK_OVERRIDE {
324         // lighting shaders are complicated. We just throw up our hands.
325         *validFlags = 0;
326     }
327
328 protected:
329     virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
330
331 private:
332     typedef GrSingleTextureEffect INHERITED;
333     const SkLight* fLight;
334     SkScalar fSurfaceScale;
335     SkMatrix fFilterMatrix;
336 };
337
338 class GrDiffuseLightingEffect : public GrLightingEffect {
339 public:
340     static GrEffect* Create(GrTexture* texture,
341                             const SkLight* light,
342                             SkScalar surfaceScale,
343                             const SkMatrix& matrix,
344                             SkScalar kd) {
345         return SkNEW_ARGS(GrDiffuseLightingEffect, (texture,
346                                                     light,
347                                                     surfaceScale,
348                                                     matrix,
349                                                     kd));
350     }
351
352     static const char* Name() { return "DiffuseLighting"; }
353
354     typedef GrGLDiffuseLightingEffect GLEffect;
355
356     virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
357     SkScalar kd() const { return fKD; }
358
359 private:
360     virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
361
362     GrDiffuseLightingEffect(GrTexture* texture,
363                             const SkLight* light,
364                             SkScalar surfaceScale,
365                             const SkMatrix& matrix,
366                             SkScalar kd);
367
368     GR_DECLARE_EFFECT_TEST;
369     typedef GrLightingEffect INHERITED;
370     SkScalar fKD;
371 };
372
373 class GrSpecularLightingEffect : public GrLightingEffect {
374 public:
375     static GrEffect* Create(GrTexture* texture,
376                             const SkLight* light,
377                             SkScalar surfaceScale,
378                             const SkMatrix& matrix,
379                             SkScalar ks,
380                             SkScalar shininess) {
381         return SkNEW_ARGS(GrSpecularLightingEffect, (texture,
382                                                      light,
383                                                      surfaceScale,
384                                                      matrix,
385                                                      ks,
386                                                      shininess));
387     }
388     static const char* Name() { return "SpecularLighting"; }
389
390     typedef GrGLSpecularLightingEffect GLEffect;
391
392     virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE;
393     SkScalar ks() const { return fKS; }
394     SkScalar shininess() const { return fShininess; }
395
396 private:
397     virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
398
399     GrSpecularLightingEffect(GrTexture* texture,
400                              const SkLight* light,
401                              SkScalar surfaceScale,
402                              const SkMatrix& matrix,
403                              SkScalar ks,
404                              SkScalar shininess);
405
406     GR_DECLARE_EFFECT_TEST;
407     typedef GrLightingEffect INHERITED;
408     SkScalar fKS;
409     SkScalar fShininess;
410 };
411
412 ///////////////////////////////////////////////////////////////////////////////
413
414 class GrGLLight {
415 public:
416     virtual ~GrGLLight() {}
417
418     /**
419      * This is called by GrGLLightingEffect::emitCode() before either of the two virtual functions
420      * below. It adds a vec3f uniform visible in the FS that represents the constant light color.
421      */
422     void emitLightColorUniform(GrGLShaderBuilder*);
423
424     /**
425      * These two functions are called from GrGLLightingEffect's emitCode() function.
426      * emitSurfaceToLight places an expression in param out that is the vector from the surface to
427      * the light. The expression will be used in the FS. emitLightColor writes an expression into
428      * the FS that is the color of the light. Either function may add functions and/or uniforms to
429      * the FS. The default of emitLightColor appends the name of the constant light color uniform
430      * and so this function only needs to be overridden if the light color varies spatially.
431      */
432     virtual void emitSurfaceToLight(GrGLShaderBuilder*, const char* z) = 0;
433     virtual void emitLightColor(GrGLShaderBuilder*, const char *surfaceToLight);
434
435     // This is called from GrGLLightingEffect's setData(). Subclasses of GrGLLight must call
436     // INHERITED::setData().
437     virtual void setData(const GrGLProgramDataManager&,
438                          const SkLight* light) const;
439
440 protected:
441     /**
442      * Gets the constant light color uniform. Subclasses can use this in their emitLightColor
443      * function.
444      */
445     UniformHandle lightColorUni() const { return fColorUni; }
446
447 private:
448     UniformHandle fColorUni;
449
450     typedef SkRefCnt INHERITED;
451 };
452
453 ///////////////////////////////////////////////////////////////////////////////
454
455 class GrGLDistantLight : public GrGLLight {
456 public:
457     virtual ~GrGLDistantLight() {}
458     virtual void setData(const GrGLProgramDataManager&,
459                          const SkLight* light) const SK_OVERRIDE;
460     virtual void emitSurfaceToLight(GrGLShaderBuilder*, const char* z) SK_OVERRIDE;
461
462 private:
463     typedef GrGLLight INHERITED;
464     UniformHandle fDirectionUni;
465 };
466
467 ///////////////////////////////////////////////////////////////////////////////
468
469 class GrGLPointLight : public GrGLLight {
470 public:
471     virtual ~GrGLPointLight() {}
472     virtual void setData(const GrGLProgramDataManager&,
473                          const SkLight* light) const SK_OVERRIDE;
474     virtual void emitSurfaceToLight(GrGLShaderBuilder*, const char* z) SK_OVERRIDE;
475
476 private:
477     typedef GrGLLight INHERITED;
478     UniformHandle fLocationUni;
479 };
480
481 ///////////////////////////////////////////////////////////////////////////////
482
483 class GrGLSpotLight : public GrGLLight {
484 public:
485     virtual ~GrGLSpotLight() {}
486     virtual void setData(const GrGLProgramDataManager&,
487                          const SkLight* light) const SK_OVERRIDE;
488     virtual void emitSurfaceToLight(GrGLShaderBuilder*, const char* z) SK_OVERRIDE;
489     virtual void emitLightColor(GrGLShaderBuilder*, const char *surfaceToLight) SK_OVERRIDE;
490
491 private:
492     typedef GrGLLight INHERITED;
493
494     SkString        fLightColorFunc;
495     UniformHandle   fLocationUni;
496     UniformHandle   fExponentUni;
497     UniformHandle   fCosOuterConeAngleUni;
498     UniformHandle   fCosInnerConeAngleUni;
499     UniformHandle   fConeScaleUni;
500     UniformHandle   fSUni;
501 };
502 #else
503
504 class GrGLLight;
505
506 #endif
507
508 };
509
510 ///////////////////////////////////////////////////////////////////////////////
511
512 class SkLight : public SkRefCnt {
513 public:
514     SK_DECLARE_INST_COUNT(SkLight)
515
516     enum LightType {
517         kDistant_LightType,
518         kPoint_LightType,
519         kSpot_LightType,
520     };
521     virtual LightType type() const = 0;
522     const SkPoint3& color() const { return fColor; }
523     virtual GrGLLight* createGLLight() const = 0;
524     virtual bool isEqual(const SkLight& other) const {
525         return fColor == other.fColor;
526     }
527     // Called to know whether the generated GrGLLight will require access to the fragment position.
528     virtual bool requiresFragmentPosition() const = 0;
529     virtual SkLight* transform(const SkMatrix& matrix) const = 0;
530
531     // Defined below SkLight's subclasses.
532     void flattenLight(SkWriteBuffer& buffer) const;
533     static SkLight* UnflattenLight(SkReadBuffer& buffer);
534
535 protected:
536     SkLight(SkColor color)
537       : fColor(SkIntToScalar(SkColorGetR(color)),
538                SkIntToScalar(SkColorGetG(color)),
539                SkIntToScalar(SkColorGetB(color))) {}
540     SkLight(const SkPoint3& color)
541       : fColor(color) {}
542     SkLight(SkReadBuffer& buffer) {
543         fColor = readPoint3(buffer);
544     }
545
546     virtual void onFlattenLight(SkWriteBuffer& buffer) const = 0;
547
548
549 private:
550     typedef SkRefCnt INHERITED;
551     SkPoint3 fColor;
552 };
553
554 ///////////////////////////////////////////////////////////////////////////////
555
556 class SkDistantLight : public SkLight {
557 public:
558     SkDistantLight(const SkPoint3& direction, SkColor color)
559       : INHERITED(color), fDirection(direction) {
560     }
561
562     SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
563         return fDirection;
564     };
565     SkPoint3 lightColor(const SkPoint3&) const { return color(); }
566     virtual LightType type() const { return kDistant_LightType; }
567     const SkPoint3& direction() const { return fDirection; }
568     virtual GrGLLight* createGLLight() const SK_OVERRIDE {
569 #if SK_SUPPORT_GPU
570         return SkNEW(GrGLDistantLight);
571 #else
572         SkDEBUGFAIL("Should not call in GPU-less build");
573         return NULL;
574 #endif
575     }
576     virtual bool requiresFragmentPosition() const SK_OVERRIDE { return false; }
577
578     virtual bool isEqual(const SkLight& other) const SK_OVERRIDE {
579         if (other.type() != kDistant_LightType) {
580             return false;
581         }
582
583         const SkDistantLight& o = static_cast<const SkDistantLight&>(other);
584         return INHERITED::isEqual(other) &&
585                fDirection == o.fDirection;
586     }
587
588     SkDistantLight(SkReadBuffer& buffer) : INHERITED(buffer) {
589         fDirection = readPoint3(buffer);
590     }
591
592 protected:
593     SkDistantLight(const SkPoint3& direction, const SkPoint3& color)
594       : INHERITED(color), fDirection(direction) {
595     }
596     virtual SkLight* transform(const SkMatrix& matrix) const {
597         return new SkDistantLight(direction(), color());
598     }
599     virtual void onFlattenLight(SkWriteBuffer& buffer) const SK_OVERRIDE {
600         writePoint3(fDirection, buffer);
601     }
602
603 private:
604     typedef SkLight INHERITED;
605     SkPoint3 fDirection;
606 };
607
608 ///////////////////////////////////////////////////////////////////////////////
609
610 class SkPointLight : public SkLight {
611 public:
612     SkPointLight(const SkPoint3& location, SkColor color)
613      : INHERITED(color), fLocation(location) {}
614
615     SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
616         SkPoint3 direction(fLocation.fX - SkIntToScalar(x),
617                            fLocation.fY - SkIntToScalar(y),
618                            fLocation.fZ - SkScalarMul(SkIntToScalar(z), surfaceScale));
619         direction.normalize();
620         return direction;
621     };
622     SkPoint3 lightColor(const SkPoint3&) const { return color(); }
623     virtual LightType type() const { return kPoint_LightType; }
624     const SkPoint3& location() const { return fLocation; }
625     virtual GrGLLight* createGLLight() const SK_OVERRIDE {
626 #if SK_SUPPORT_GPU
627         return SkNEW(GrGLPointLight);
628 #else
629         SkDEBUGFAIL("Should not call in GPU-less build");
630         return NULL;
631 #endif
632     }
633     virtual bool requiresFragmentPosition() const SK_OVERRIDE { return true; }
634     virtual bool isEqual(const SkLight& other) const SK_OVERRIDE {
635         if (other.type() != kPoint_LightType) {
636             return false;
637         }
638         const SkPointLight& o = static_cast<const SkPointLight&>(other);
639         return INHERITED::isEqual(other) &&
640                fLocation == o.fLocation;
641     }
642     virtual SkLight* transform(const SkMatrix& matrix) const {
643         SkPoint location2 = SkPoint::Make(fLocation.fX, fLocation.fY);
644         matrix.mapPoints(&location2, 1);
645         // Use X scale and Y scale on Z and average the result
646         SkPoint locationZ = SkPoint::Make(fLocation.fZ, fLocation.fZ);
647         matrix.mapVectors(&locationZ, 1);
648         SkPoint3 location(location2.fX, location2.fY, SkScalarAve(locationZ.fX, locationZ.fY));
649         return new SkPointLight(location, color());
650     }
651
652     SkPointLight(SkReadBuffer& buffer) : INHERITED(buffer) {
653         fLocation = readPoint3(buffer);
654     }
655
656 protected:
657     SkPointLight(const SkPoint3& location, const SkPoint3& color)
658      : INHERITED(color), fLocation(location) {}
659     virtual void onFlattenLight(SkWriteBuffer& buffer) const SK_OVERRIDE {
660         writePoint3(fLocation, buffer);
661     }
662
663 private:
664     typedef SkLight INHERITED;
665     SkPoint3 fLocation;
666 };
667
668 ///////////////////////////////////////////////////////////////////////////////
669
670 class SkSpotLight : public SkLight {
671 public:
672     SkSpotLight(const SkPoint3& location, const SkPoint3& target, SkScalar specularExponent, SkScalar cutoffAngle, SkColor color)
673      : INHERITED(color),
674        fLocation(location),
675        fTarget(target),
676        fSpecularExponent(SkScalarPin(specularExponent, kSpecularExponentMin, kSpecularExponentMax))
677     {
678        fS = target - location;
679        fS.normalize();
680        fCosOuterConeAngle = SkScalarCos(SkDegreesToRadians(cutoffAngle));
681        const SkScalar antiAliasThreshold = 0.016f;
682        fCosInnerConeAngle = fCosOuterConeAngle + antiAliasThreshold;
683        fConeScale = SkScalarInvert(antiAliasThreshold);
684     }
685
686     virtual SkLight* transform(const SkMatrix& matrix) const {
687         SkPoint location2 = SkPoint::Make(fLocation.fX, fLocation.fY);
688         matrix.mapPoints(&location2, 1);
689         // Use X scale and Y scale on Z and average the result
690         SkPoint locationZ = SkPoint::Make(fLocation.fZ, fLocation.fZ);
691         matrix.mapVectors(&locationZ, 1);
692         SkPoint3 location(location2.fX, location2.fY, SkScalarAve(locationZ.fX, locationZ.fY));
693         SkPoint target2 = SkPoint::Make(fTarget.fX, fTarget.fY);
694         matrix.mapPoints(&target2, 1);
695         SkPoint targetZ = SkPoint::Make(fTarget.fZ, fTarget.fZ);
696         matrix.mapVectors(&targetZ, 1);
697         SkPoint3 target(target2.fX, target2.fY, SkScalarAve(targetZ.fX, targetZ.fY));
698         SkPoint3 s = target - location;
699         s.normalize();
700         return new SkSpotLight(location, target, fSpecularExponent, fCosOuterConeAngle, fCosInnerConeAngle, fConeScale, s, color());
701     }
702
703     SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
704         SkPoint3 direction(fLocation.fX - SkIntToScalar(x),
705                            fLocation.fY - SkIntToScalar(y),
706                            fLocation.fZ - SkScalarMul(SkIntToScalar(z), surfaceScale));
707         direction.normalize();
708         return direction;
709     };
710     SkPoint3 lightColor(const SkPoint3& surfaceToLight) const {
711         SkScalar cosAngle = -surfaceToLight.dot(fS);
712         if (cosAngle < fCosOuterConeAngle) {
713             return SkPoint3(0, 0, 0);
714         }
715         SkScalar scale = SkScalarPow(cosAngle, fSpecularExponent);
716         if (cosAngle < fCosInnerConeAngle) {
717             scale = SkScalarMul(scale, cosAngle - fCosOuterConeAngle);
718             return color() * SkScalarMul(scale, fConeScale);
719         }
720         return color() * scale;
721     }
722     virtual GrGLLight* createGLLight() const SK_OVERRIDE {
723 #if SK_SUPPORT_GPU
724         return SkNEW(GrGLSpotLight);
725 #else
726         SkDEBUGFAIL("Should not call in GPU-less build");
727         return NULL;
728 #endif
729     }
730     virtual bool requiresFragmentPosition() const SK_OVERRIDE { return true; }
731     virtual LightType type() const { return kSpot_LightType; }
732     const SkPoint3& location() const { return fLocation; }
733     const SkPoint3& target() const { return fTarget; }
734     SkScalar specularExponent() const { return fSpecularExponent; }
735     SkScalar cosInnerConeAngle() const { return fCosInnerConeAngle; }
736     SkScalar cosOuterConeAngle() const { return fCosOuterConeAngle; }
737     SkScalar coneScale() const { return fConeScale; }
738     const SkPoint3& s() const { return fS; }
739
740     SkSpotLight(SkReadBuffer& buffer) : INHERITED(buffer) {
741         fLocation = readPoint3(buffer);
742         fTarget = readPoint3(buffer);
743         fSpecularExponent = buffer.readScalar();
744         fCosOuterConeAngle = buffer.readScalar();
745         fCosInnerConeAngle = buffer.readScalar();
746         fConeScale = buffer.readScalar();
747         fS = readPoint3(buffer);
748         buffer.validate(SkScalarIsFinite(fSpecularExponent) &&
749                         SkScalarIsFinite(fCosOuterConeAngle) &&
750                         SkScalarIsFinite(fCosInnerConeAngle) &&
751                         SkScalarIsFinite(fConeScale));
752     }
753 protected:
754     SkSpotLight(const SkPoint3& location, const SkPoint3& target, SkScalar specularExponent, SkScalar cosOuterConeAngle, SkScalar cosInnerConeAngle, SkScalar coneScale, const SkPoint3& s, const SkPoint3& color)
755      : INHERITED(color),
756        fLocation(location),
757        fTarget(target),
758        fSpecularExponent(specularExponent),
759        fCosOuterConeAngle(cosOuterConeAngle),
760        fCosInnerConeAngle(cosInnerConeAngle),
761        fConeScale(coneScale),
762        fS(s)
763     {
764     }
765     virtual void onFlattenLight(SkWriteBuffer& buffer) const SK_OVERRIDE {
766         writePoint3(fLocation, buffer);
767         writePoint3(fTarget, buffer);
768         buffer.writeScalar(fSpecularExponent);
769         buffer.writeScalar(fCosOuterConeAngle);
770         buffer.writeScalar(fCosInnerConeAngle);
771         buffer.writeScalar(fConeScale);
772         writePoint3(fS, buffer);
773     }
774
775     virtual bool isEqual(const SkLight& other) const SK_OVERRIDE {
776         if (other.type() != kSpot_LightType) {
777             return false;
778         }
779
780         const SkSpotLight& o = static_cast<const SkSpotLight&>(other);
781         return INHERITED::isEqual(other) &&
782                fLocation == o.fLocation &&
783                fTarget == o.fTarget &&
784                fSpecularExponent == o.fSpecularExponent &&
785                fCosOuterConeAngle == o.fCosOuterConeAngle;
786     }
787
788 private:
789     static const SkScalar kSpecularExponentMin;
790     static const SkScalar kSpecularExponentMax;
791
792     typedef SkLight INHERITED;
793     SkPoint3 fLocation;
794     SkPoint3 fTarget;
795     SkScalar fSpecularExponent;
796     SkScalar fCosOuterConeAngle;
797     SkScalar fCosInnerConeAngle;
798     SkScalar fConeScale;
799     SkPoint3 fS;
800 };
801
802 // According to the spec, the specular term should be in the range [1, 128] :
803 // http://www.w3.org/TR/SVG/filters.html#feSpecularLightingSpecularExponentAttribute
804 const SkScalar SkSpotLight::kSpecularExponentMin = 1.0f;
805 const SkScalar SkSpotLight::kSpecularExponentMax = 128.0f;
806
807 ///////////////////////////////////////////////////////////////////////////////
808
809 void SkLight::flattenLight(SkWriteBuffer& buffer) const {
810     // Write type first, then baseclass, then subclass.
811     buffer.writeInt(this->type());
812     writePoint3(fColor, buffer);
813     this->onFlattenLight(buffer);
814 }
815
816 /*static*/ SkLight* SkLight::UnflattenLight(SkReadBuffer& buffer) {
817     // Read type first.
818     const SkLight::LightType type = (SkLight::LightType)buffer.readInt();
819     switch (type) {
820         // Each of these constructors must first call SkLight's, so we'll read the baseclass
821         // then subclass, same order as flattenLight.
822         case SkLight::kDistant_LightType: return SkNEW_ARGS(SkDistantLight, (buffer));
823         case SkLight::kPoint_LightType:   return SkNEW_ARGS(SkPointLight, (buffer));
824         case SkLight::kSpot_LightType:    return SkNEW_ARGS(SkSpotLight, (buffer));
825         default:
826             SkDEBUGFAIL("Unknown LightType.");
827             buffer.validate(false);
828             return NULL;
829     }
830 }
831 ///////////////////////////////////////////////////////////////////////////////
832
833 SkLightingImageFilter::SkLightingImageFilter(SkLight* light, SkScalar surfaceScale,
834                                              SkImageFilter* input, const CropRect* cropRect)
835   : INHERITED(1, &input, cropRect),
836     fLight(light),
837     fSurfaceScale(SkScalarDiv(surfaceScale, SkIntToScalar(255)))
838 {
839     SkASSERT(fLight);
840     // our caller knows that we take ownership of the light, so we don't
841     // need to call ref() here.
842 }
843
844 SkImageFilter* SkLightingImageFilter::CreateDistantLitDiffuse(
845     const SkPoint3& direction, SkColor lightColor, SkScalar surfaceScale,
846     SkScalar kd, SkImageFilter* input, const CropRect* cropRect) {
847     return SkNEW_ARGS(SkDiffuseLightingImageFilter,
848         (SkNEW_ARGS(SkDistantLight, (direction, lightColor)), surfaceScale, kd,
849         input, cropRect));
850 }
851
852 SkImageFilter* SkLightingImageFilter::CreatePointLitDiffuse(
853     const SkPoint3& location, SkColor lightColor, SkScalar surfaceScale,
854     SkScalar kd, SkImageFilter* input, const CropRect* cropRect) {
855     return SkNEW_ARGS(SkDiffuseLightingImageFilter,
856         (SkNEW_ARGS(SkPointLight, (location, lightColor)), surfaceScale, kd,
857         input, cropRect));
858 }
859
860 SkImageFilter* SkLightingImageFilter::CreateSpotLitDiffuse(
861     const SkPoint3& location, const SkPoint3& target,
862     SkScalar specularExponent, SkScalar cutoffAngle,
863     SkColor lightColor, SkScalar surfaceScale, SkScalar kd,
864     SkImageFilter* input, const CropRect* cropRect) {
865     return SkNEW_ARGS(SkDiffuseLightingImageFilter,
866         (SkNEW_ARGS(SkSpotLight, (location, target, specularExponent,
867                                   cutoffAngle, lightColor)),
868                     surfaceScale, kd, input, cropRect));
869 }
870
871 SkImageFilter* SkLightingImageFilter::CreateDistantLitSpecular(
872     const SkPoint3& direction, SkColor lightColor, SkScalar surfaceScale,
873     SkScalar ks, SkScalar shininess, SkImageFilter* input, const CropRect* cropRect) {
874     return SkNEW_ARGS(SkSpecularLightingImageFilter,
875         (SkNEW_ARGS(SkDistantLight, (direction, lightColor)),
876         surfaceScale, ks, shininess, input, cropRect));
877 }
878
879 SkImageFilter* SkLightingImageFilter::CreatePointLitSpecular(
880     const SkPoint3& location, SkColor lightColor, SkScalar surfaceScale,
881     SkScalar ks, SkScalar shininess, SkImageFilter* input, const CropRect* cropRect) {
882     return SkNEW_ARGS(SkSpecularLightingImageFilter,
883         (SkNEW_ARGS(SkPointLight, (location, lightColor)),
884         surfaceScale, ks, shininess, input, cropRect));
885 }
886
887 SkImageFilter* SkLightingImageFilter::CreateSpotLitSpecular(
888     const SkPoint3& location, const SkPoint3& target,
889     SkScalar specularExponent, SkScalar cutoffAngle,
890     SkColor lightColor, SkScalar surfaceScale,
891     SkScalar ks, SkScalar shininess, SkImageFilter* input, const CropRect* cropRect) {
892     return SkNEW_ARGS(SkSpecularLightingImageFilter,
893         (SkNEW_ARGS(SkSpotLight, (location, target, specularExponent, cutoffAngle, lightColor)),
894         surfaceScale, ks, shininess, input, cropRect));
895 }
896
897 SkLightingImageFilter::~SkLightingImageFilter() {
898     SkSafeUnref(fLight);
899 }
900
901 SkLightingImageFilter::SkLightingImageFilter(SkReadBuffer& buffer)
902   : INHERITED(1, buffer) {
903     fLight = SkLight::UnflattenLight(buffer);
904     fSurfaceScale = buffer.readScalar();
905     buffer.validate(SkScalarIsFinite(fSurfaceScale));
906 }
907
908 void SkLightingImageFilter::flatten(SkWriteBuffer& buffer) const {
909     this->INHERITED::flatten(buffer);
910     fLight->flattenLight(buffer);
911     buffer.writeScalar(fSurfaceScale);
912 }
913
914 ///////////////////////////////////////////////////////////////////////////////
915
916 SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar kd, SkImageFilter* input, const CropRect* cropRect = NULL)
917   : SkLightingImageFilter(light, surfaceScale, input, cropRect),
918     // According to the spec, kd can be any non-negative number :
919     // http://www.w3.org/TR/SVG/filters.html#feDiffuseLightingElement
920     fKD(kd < 0 ? 0 : kd)
921 {
922 }
923
924 SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkReadBuffer& buffer)
925   : INHERITED(buffer)
926 {
927     fKD = buffer.readScalar();
928     buffer.validate(SkScalarIsFinite(fKD) && (fKD >= 0));
929 }
930
931 void SkDiffuseLightingImageFilter::flatten(SkWriteBuffer& buffer) const {
932     this->INHERITED::flatten(buffer);
933     buffer.writeScalar(fKD);
934 }
935
936 bool SkDiffuseLightingImageFilter::onFilterImage(Proxy* proxy,
937                                                  const SkBitmap& source,
938                                                  const Context& ctx,
939                                                  SkBitmap* dst,
940                                                  SkIPoint* offset) const {
941     SkImageFilter* input = getInput(0);
942     SkBitmap src = source;
943     SkIPoint srcOffset = SkIPoint::Make(0, 0);
944     if (input && !input->filterImage(proxy, source, ctx, &src, &srcOffset)) {
945         return false;
946     }
947
948     if (src.colorType() != kN32_SkColorType) {
949         return false;
950     }
951     SkIRect bounds;
952     if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &bounds, &src)) {
953         return false;
954     }
955
956     if (bounds.width() < 2 || bounds.height() < 2) {
957         return false;
958     }
959
960     SkAutoLockPixels alp(src);
961     if (!src.getPixels()) {
962         return false;
963     }
964
965     if (!dst->allocPixels(src.info().makeWH(bounds.width(), bounds.height()))) {
966         return false;
967     }
968
969     SkAutoTUnref<SkLight> transformedLight(light()->transform(ctx.ctm()));
970
971     DiffuseLightingType lightingType(fKD);
972     offset->fX = bounds.left();
973     offset->fY = bounds.top();
974     bounds.offset(-srcOffset);
975     switch (transformedLight->type()) {
976         case SkLight::kDistant_LightType:
977             lightBitmap<DiffuseLightingType, SkDistantLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
978             break;
979         case SkLight::kPoint_LightType:
980             lightBitmap<DiffuseLightingType, SkPointLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
981             break;
982         case SkLight::kSpot_LightType:
983             lightBitmap<DiffuseLightingType, SkSpotLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
984             break;
985     }
986
987     return true;
988 }
989
990 #if SK_SUPPORT_GPU
991 bool SkDiffuseLightingImageFilter::asNewEffect(GrEffect** effect, GrTexture* texture,
992                                                const SkMatrix& matrix, const SkIRect&) const {
993     if (effect) {
994         SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255));
995         *effect = GrDiffuseLightingEffect::Create(texture, light(), scale, matrix, kd());
996     }
997     return true;
998 }
999 #endif
1000
1001 ///////////////////////////////////////////////////////////////////////////////
1002
1003 SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess, SkImageFilter* input, const CropRect* cropRect)
1004   : SkLightingImageFilter(light, surfaceScale, input, cropRect),
1005     // According to the spec, ks can be any non-negative number :
1006     // http://www.w3.org/TR/SVG/filters.html#feSpecularLightingElement
1007     fKS(ks < 0 ? 0 : ks),
1008     fShininess(shininess)
1009 {
1010 }
1011
1012 SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkReadBuffer& buffer)
1013   : INHERITED(buffer)
1014 {
1015     fKS = buffer.readScalar();
1016     fShininess = buffer.readScalar();
1017     buffer.validate(SkScalarIsFinite(fKS) && (fKS >= 0) &&
1018                     SkScalarIsFinite(fShininess));
1019 }
1020
1021 void SkSpecularLightingImageFilter::flatten(SkWriteBuffer& buffer) const {
1022     this->INHERITED::flatten(buffer);
1023     buffer.writeScalar(fKS);
1024     buffer.writeScalar(fShininess);
1025 }
1026
1027 bool SkSpecularLightingImageFilter::onFilterImage(Proxy* proxy,
1028                                                   const SkBitmap& source,
1029                                                   const Context& ctx,
1030                                                   SkBitmap* dst,
1031                                                   SkIPoint* offset) const {
1032     SkImageFilter* input = getInput(0);
1033     SkBitmap src = source;
1034     SkIPoint srcOffset = SkIPoint::Make(0, 0);
1035     if (input && !input->filterImage(proxy, source, ctx, &src, &srcOffset)) {
1036         return false;
1037     }
1038
1039     if (src.colorType() != kN32_SkColorType) {
1040         return false;
1041     }
1042
1043     SkIRect bounds;
1044     if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &bounds, &src)) {
1045         return false;
1046     }
1047
1048     if (bounds.width() < 2 || bounds.height() < 2) {
1049         return false;
1050     }
1051
1052     SkAutoLockPixels alp(src);
1053     if (!src.getPixels()) {
1054         return false;
1055     }
1056
1057     if (!dst->allocPixels(src.info().makeWH(bounds.width(), bounds.height()))) {
1058         return false;
1059     }
1060
1061     SpecularLightingType lightingType(fKS, fShininess);
1062     offset->fX = bounds.left();
1063     offset->fY = bounds.top();
1064     bounds.offset(-srcOffset);
1065     SkAutoTUnref<SkLight> transformedLight(light()->transform(ctx.ctm()));
1066     switch (transformedLight->type()) {
1067         case SkLight::kDistant_LightType:
1068             lightBitmap<SpecularLightingType, SkDistantLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
1069             break;
1070         case SkLight::kPoint_LightType:
1071             lightBitmap<SpecularLightingType, SkPointLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
1072             break;
1073         case SkLight::kSpot_LightType:
1074             lightBitmap<SpecularLightingType, SkSpotLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds);
1075             break;
1076     }
1077     return true;
1078 }
1079
1080 #if SK_SUPPORT_GPU
1081 bool SkSpecularLightingImageFilter::asNewEffect(GrEffect** effect, GrTexture* texture,
1082                                                 const SkMatrix& matrix, const SkIRect&) const {
1083     if (effect) {
1084         SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255));
1085         *effect = GrSpecularLightingEffect::Create(texture, light(), scale, matrix, ks(), shininess());
1086     }
1087     return true;
1088 }
1089 #endif
1090
1091 ///////////////////////////////////////////////////////////////////////////////
1092
1093 #if SK_SUPPORT_GPU
1094
1095 namespace {
1096 SkPoint3 random_point3(SkRandom* random) {
1097     return SkPoint3(SkScalarToFloat(random->nextSScalar1()),
1098                     SkScalarToFloat(random->nextSScalar1()),
1099                     SkScalarToFloat(random->nextSScalar1()));
1100 }
1101
1102 SkLight* create_random_light(SkRandom* random) {
1103     int type = random->nextULessThan(3);
1104     switch (type) {
1105         case 0: {
1106             return SkNEW_ARGS(SkDistantLight, (random_point3(random), random->nextU()));
1107         }
1108         case 1: {
1109             return SkNEW_ARGS(SkPointLight, (random_point3(random), random->nextU()));
1110         }
1111         case 2: {
1112             return SkNEW_ARGS(SkSpotLight, (random_point3(random),
1113                                             random_point3(random),
1114                                             random->nextUScalar1(),
1115                                             random->nextUScalar1(),
1116                                             random->nextU()));
1117         }
1118         default:
1119             SkFAIL("Unexpected value.");
1120             return NULL;
1121     }
1122 }
1123
1124 }
1125
1126 class GrGLLightingEffect  : public GrGLEffect {
1127 public:
1128     GrGLLightingEffect(const GrBackendEffectFactory& factory,
1129                        const GrDrawEffect& effect);
1130     virtual ~GrGLLightingEffect();
1131
1132     virtual void emitCode(GrGLShaderBuilder*,
1133                           const GrDrawEffect&,
1134                           const GrEffectKey&,
1135                           const char* outputColor,
1136                           const char* inputColor,
1137                           const TransformedCoordsArray&,
1138                           const TextureSamplerArray&) SK_OVERRIDE;
1139
1140     static inline void GenKey(const GrDrawEffect&, const GrGLCaps&, GrEffectKeyBuilder* b);
1141
1142     /**
1143      * Subclasses of GrGLLightingEffect must call INHERITED::setData();
1144      */
1145     virtual void setData(const GrGLProgramDataManager&, const GrDrawEffect&) SK_OVERRIDE;
1146
1147 protected:
1148     virtual void emitLightFunc(GrGLShaderBuilder*, SkString* funcName) = 0;
1149
1150 private:
1151     typedef GrGLEffect INHERITED;
1152
1153     UniformHandle       fImageIncrementUni;
1154     UniformHandle       fSurfaceScaleUni;
1155     GrGLLight*          fLight;
1156 };
1157
1158 ///////////////////////////////////////////////////////////////////////////////
1159
1160 class GrGLDiffuseLightingEffect  : public GrGLLightingEffect {
1161 public:
1162     GrGLDiffuseLightingEffect(const GrBackendEffectFactory& factory,
1163                               const GrDrawEffect& drawEffect);
1164     virtual void emitLightFunc(GrGLShaderBuilder*, SkString* funcName) SK_OVERRIDE;
1165     virtual void setData(const GrGLProgramDataManager&, const GrDrawEffect&) SK_OVERRIDE;
1166
1167 private:
1168     typedef GrGLLightingEffect INHERITED;
1169
1170     UniformHandle   fKDUni;
1171 };
1172
1173 ///////////////////////////////////////////////////////////////////////////////
1174
1175 class GrGLSpecularLightingEffect  : public GrGLLightingEffect {
1176 public:
1177     GrGLSpecularLightingEffect(const GrBackendEffectFactory& factory,
1178                                const GrDrawEffect& effect);
1179     virtual void emitLightFunc(GrGLShaderBuilder*, SkString* funcName) SK_OVERRIDE;
1180     virtual void setData(const GrGLProgramDataManager&, const GrDrawEffect&) SK_OVERRIDE;
1181
1182 private:
1183     typedef GrGLLightingEffect INHERITED;
1184
1185     UniformHandle   fKSUni;
1186     UniformHandle   fShininessUni;
1187 };
1188
1189 ///////////////////////////////////////////////////////////////////////////////
1190
1191 GrLightingEffect::GrLightingEffect(GrTexture* texture,
1192                                    const SkLight* light,
1193                                    SkScalar surfaceScale,
1194                                    const SkMatrix& matrix)
1195     : INHERITED(texture, MakeDivByTextureWHMatrix(texture))
1196     , fLight(light)
1197     , fSurfaceScale(surfaceScale)
1198     , fFilterMatrix(matrix) {
1199     fLight->ref();
1200     if (light->requiresFragmentPosition()) {
1201         this->setWillReadFragmentPosition();
1202     }
1203 }
1204
1205 GrLightingEffect::~GrLightingEffect() {
1206     fLight->unref();
1207 }
1208
1209 bool GrLightingEffect::onIsEqual(const GrEffect& sBase) const {
1210     const GrLightingEffect& s = CastEffect<GrLightingEffect>(sBase);
1211     return this->texture(0) == s.texture(0) &&
1212            fLight->isEqual(*s.fLight) &&
1213            fSurfaceScale == s.fSurfaceScale;
1214 }
1215
1216 ///////////////////////////////////////////////////////////////////////////////
1217
1218 GrDiffuseLightingEffect::GrDiffuseLightingEffect(GrTexture* texture,
1219                                                  const SkLight* light,
1220                                                  SkScalar surfaceScale,
1221                                                  const SkMatrix& matrix,
1222                                                  SkScalar kd)
1223     : INHERITED(texture, light, surfaceScale, matrix), fKD(kd) {
1224 }
1225
1226 const GrBackendEffectFactory& GrDiffuseLightingEffect::getFactory() const {
1227     return GrTBackendEffectFactory<GrDiffuseLightingEffect>::getInstance();
1228 }
1229
1230 bool GrDiffuseLightingEffect::onIsEqual(const GrEffect& sBase) const {
1231     const GrDiffuseLightingEffect& s = CastEffect<GrDiffuseLightingEffect>(sBase);
1232     return INHERITED::onIsEqual(sBase) &&
1233             this->kd() == s.kd();
1234 }
1235
1236 GR_DEFINE_EFFECT_TEST(GrDiffuseLightingEffect);
1237
1238 GrEffect* GrDiffuseLightingEffect::TestCreate(SkRandom* random,
1239                                               GrContext* context,
1240                                               const GrDrawTargetCaps&,
1241                                               GrTexture* textures[]) {
1242     SkScalar surfaceScale = random->nextSScalar1();
1243     SkScalar kd = random->nextUScalar1();
1244     SkAutoTUnref<SkLight> light(create_random_light(random));
1245     SkMatrix matrix;
1246     for (int i = 0; i < 9; i++) {
1247         matrix[i] = random->nextUScalar1();
1248     }
1249     return GrDiffuseLightingEffect::Create(textures[GrEffectUnitTest::kAlphaTextureIdx],
1250                                            light, surfaceScale, matrix, kd);
1251 }
1252
1253
1254 ///////////////////////////////////////////////////////////////////////////////
1255
1256 GrGLLightingEffect::GrGLLightingEffect(const GrBackendEffectFactory& factory,
1257                                        const GrDrawEffect& drawEffect)
1258     : INHERITED(factory) {
1259     const GrLightingEffect& m = drawEffect.castEffect<GrLightingEffect>();
1260     fLight = m.light()->createGLLight();
1261 }
1262
1263 GrGLLightingEffect::~GrGLLightingEffect() {
1264     delete fLight;
1265 }
1266
1267 void GrGLLightingEffect::emitCode(GrGLShaderBuilder* builder,
1268                                   const GrDrawEffect&,
1269                                   const GrEffectKey& key,
1270                                   const char* outputColor,
1271                                   const char* inputColor,
1272                                   const TransformedCoordsArray& coords,
1273                                   const TextureSamplerArray& samplers) {
1274     SkString coords2D = builder->ensureFSCoords2D(coords, 0);
1275
1276     fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
1277                                               kVec2f_GrSLType,
1278                                              "ImageIncrement");
1279     fSurfaceScaleUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
1280                                            kFloat_GrSLType,
1281                                            "SurfaceScale");
1282     fLight->emitLightColorUniform(builder);
1283     SkString lightFunc;
1284     this->emitLightFunc(builder, &lightFunc);
1285     static const GrGLShaderVar gSobelArgs[] =  {
1286         GrGLShaderVar("a", kFloat_GrSLType),
1287         GrGLShaderVar("b", kFloat_GrSLType),
1288         GrGLShaderVar("c", kFloat_GrSLType),
1289         GrGLShaderVar("d", kFloat_GrSLType),
1290         GrGLShaderVar("e", kFloat_GrSLType),
1291         GrGLShaderVar("f", kFloat_GrSLType),
1292         GrGLShaderVar("scale", kFloat_GrSLType),
1293     };
1294     SkString sobelFuncName;
1295     builder->fsEmitFunction(kFloat_GrSLType,
1296                             "sobel",
1297                             SK_ARRAY_COUNT(gSobelArgs),
1298                             gSobelArgs,
1299                             "\treturn (-a + b - 2.0 * c + 2.0 * d -e + f) * scale;\n",
1300                             &sobelFuncName);
1301     static const GrGLShaderVar gPointToNormalArgs[] =  {
1302         GrGLShaderVar("x", kFloat_GrSLType),
1303         GrGLShaderVar("y", kFloat_GrSLType),
1304         GrGLShaderVar("scale", kFloat_GrSLType),
1305     };
1306     SkString pointToNormalName;
1307     builder->fsEmitFunction(kVec3f_GrSLType,
1308                             "pointToNormal",
1309                             SK_ARRAY_COUNT(gPointToNormalArgs),
1310                             gPointToNormalArgs,
1311                             "\treturn normalize(vec3(-x * scale, y * scale, 1));\n",
1312                             &pointToNormalName);
1313
1314     static const GrGLShaderVar gInteriorNormalArgs[] =  {
1315         GrGLShaderVar("m", kFloat_GrSLType, 9),
1316         GrGLShaderVar("surfaceScale", kFloat_GrSLType),
1317     };
1318     SkString interiorNormalBody;
1319     interiorNormalBody.appendf("\treturn %s(%s(m[0], m[2], m[3], m[5], m[6], m[8], 0.25),\n"
1320                                "\t       %s(m[0], m[6], m[1], m[7], m[2], m[8], 0.25),\n"
1321                                "\t       surfaceScale);\n",
1322                                 pointToNormalName.c_str(),
1323                                 sobelFuncName.c_str(),
1324                                 sobelFuncName.c_str());
1325     SkString interiorNormalName;
1326     builder->fsEmitFunction(kVec3f_GrSLType,
1327                             "interiorNormal",
1328                             SK_ARRAY_COUNT(gInteriorNormalArgs),
1329                             gInteriorNormalArgs,
1330                             interiorNormalBody.c_str(),
1331                             &interiorNormalName);
1332
1333     builder->fsCodeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str());
1334     builder->fsCodeAppend("\t\tfloat m[9];\n");
1335
1336     const char* imgInc = builder->getUniformCStr(fImageIncrementUni);
1337     const char* surfScale = builder->getUniformCStr(fSurfaceScaleUni);
1338
1339     int index = 0;
1340     for (int dy = -1; dy <= 1; dy++) {
1341         for (int dx = -1; dx <= 1; dx++) {
1342             SkString texCoords;
1343             texCoords.appendf("coord + vec2(%d, %d) * %s", dx, dy, imgInc);
1344             builder->fsCodeAppendf("\t\tm[%d] = ", index++);
1345             builder->fsAppendTextureLookup(samplers[0], texCoords.c_str());
1346             builder->fsCodeAppend(".a;\n");
1347         }
1348     }
1349     builder->fsCodeAppend("\t\tvec3 surfaceToLight = ");
1350     SkString arg;
1351     arg.appendf("%s * m[4]", surfScale);
1352     fLight->emitSurfaceToLight(builder, arg.c_str());
1353     builder->fsCodeAppend(";\n");
1354     builder->fsCodeAppendf("\t\t%s = %s(%s(m, %s), surfaceToLight, ",
1355                            outputColor, lightFunc.c_str(), interiorNormalName.c_str(), surfScale);
1356     fLight->emitLightColor(builder, "surfaceToLight");
1357     builder->fsCodeAppend(");\n");
1358     SkString modulate;
1359     GrGLSLMulVarBy4f(&modulate, 2, outputColor, inputColor);
1360     builder->fsCodeAppend(modulate.c_str());
1361 }
1362
1363 void GrGLLightingEffect::GenKey(const GrDrawEffect& drawEffect,
1364                                 const GrGLCaps& caps, GrEffectKeyBuilder* b) {
1365     b->add32(drawEffect.castEffect<GrLightingEffect>().light()->type());
1366 }
1367
1368 void GrGLLightingEffect::setData(const GrGLProgramDataManager& pdman,
1369                                  const GrDrawEffect& drawEffect) {
1370     const GrLightingEffect& lighting = drawEffect.castEffect<GrLightingEffect>();
1371     GrTexture* texture = lighting.texture(0);
1372     float ySign = texture->origin() == kTopLeft_GrSurfaceOrigin ? -1.0f : 1.0f;
1373     pdman.set2f(fImageIncrementUni, 1.0f / texture->width(), ySign / texture->height());
1374     pdman.set1f(fSurfaceScaleUni, lighting.surfaceScale());
1375     SkAutoTUnref<SkLight> transformedLight(lighting.light()->transform(lighting.filterMatrix()));
1376     fLight->setData(pdman, transformedLight);
1377 }
1378
1379 ///////////////////////////////////////////////////////////////////////////////
1380
1381 ///////////////////////////////////////////////////////////////////////////////
1382
1383 GrGLDiffuseLightingEffect::GrGLDiffuseLightingEffect(const GrBackendEffectFactory& factory,
1384                                                      const GrDrawEffect& drawEffect)
1385     : INHERITED(factory, drawEffect) {
1386 }
1387
1388 void GrGLDiffuseLightingEffect::emitLightFunc(GrGLShaderBuilder* builder, SkString* funcName) {
1389     const char* kd;
1390     fKDUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
1391                                  kFloat_GrSLType,
1392                                  "KD",
1393                                  &kd);
1394
1395     static const GrGLShaderVar gLightArgs[] = {
1396         GrGLShaderVar("normal", kVec3f_GrSLType),
1397         GrGLShaderVar("surfaceToLight", kVec3f_GrSLType),
1398         GrGLShaderVar("lightColor", kVec3f_GrSLType)
1399     };
1400     SkString lightBody;
1401     lightBody.appendf("\tfloat colorScale = %s * dot(normal, surfaceToLight);\n", kd);
1402     lightBody.appendf("\treturn vec4(lightColor * clamp(colorScale, 0.0, 1.0), 1.0);\n");
1403     builder->fsEmitFunction(kVec4f_GrSLType,
1404                             "light",
1405                             SK_ARRAY_COUNT(gLightArgs),
1406                             gLightArgs,
1407                             lightBody.c_str(),
1408                             funcName);
1409 }
1410
1411 void GrGLDiffuseLightingEffect::setData(const GrGLProgramDataManager& pdman,
1412                                         const GrDrawEffect& drawEffect) {
1413     INHERITED::setData(pdman, drawEffect);
1414     const GrDiffuseLightingEffect& diffuse = drawEffect.castEffect<GrDiffuseLightingEffect>();
1415     pdman.set1f(fKDUni, diffuse.kd());
1416 }
1417
1418 ///////////////////////////////////////////////////////////////////////////////
1419
1420 GrSpecularLightingEffect::GrSpecularLightingEffect(GrTexture* texture,
1421                                                    const SkLight* light,
1422                                                    SkScalar surfaceScale,
1423                                                    const SkMatrix& matrix,
1424                                                    SkScalar ks,
1425                                                    SkScalar shininess)
1426     : INHERITED(texture, light, surfaceScale, matrix),
1427       fKS(ks),
1428       fShininess(shininess) {
1429 }
1430
1431 const GrBackendEffectFactory& GrSpecularLightingEffect::getFactory() const {
1432     return GrTBackendEffectFactory<GrSpecularLightingEffect>::getInstance();
1433 }
1434
1435 bool GrSpecularLightingEffect::onIsEqual(const GrEffect& sBase) const {
1436     const GrSpecularLightingEffect& s = CastEffect<GrSpecularLightingEffect>(sBase);
1437     return INHERITED::onIsEqual(sBase) &&
1438            this->ks() == s.ks() &&
1439            this->shininess() == s.shininess();
1440 }
1441
1442 GR_DEFINE_EFFECT_TEST(GrSpecularLightingEffect);
1443
1444 GrEffect* GrSpecularLightingEffect::TestCreate(SkRandom* random,
1445                                                GrContext* context,
1446                                                const GrDrawTargetCaps&,
1447                                                GrTexture* textures[]) {
1448     SkScalar surfaceScale = random->nextSScalar1();
1449     SkScalar ks = random->nextUScalar1();
1450     SkScalar shininess = random->nextUScalar1();
1451     SkAutoTUnref<SkLight> light(create_random_light(random));
1452     SkMatrix matrix;
1453     for (int i = 0; i < 9; i++) {
1454         matrix[i] = random->nextUScalar1();
1455     }
1456     return GrSpecularLightingEffect::Create(textures[GrEffectUnitTest::kAlphaTextureIdx],
1457                                             light, surfaceScale, matrix, ks, shininess);
1458 }
1459
1460 ///////////////////////////////////////////////////////////////////////////////
1461
1462 GrGLSpecularLightingEffect::GrGLSpecularLightingEffect(const GrBackendEffectFactory& factory,
1463                                                        const GrDrawEffect& drawEffect)
1464     : INHERITED(factory, drawEffect) {
1465 }
1466
1467 void GrGLSpecularLightingEffect::emitLightFunc(GrGLShaderBuilder* builder, SkString* funcName) {
1468     const char* ks;
1469     const char* shininess;
1470
1471     fKSUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
1472                                  kFloat_GrSLType, "KS", &ks);
1473     fShininessUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
1474                                         kFloat_GrSLType, "Shininess", &shininess);
1475
1476     static const GrGLShaderVar gLightArgs[] = {
1477         GrGLShaderVar("normal", kVec3f_GrSLType),
1478         GrGLShaderVar("surfaceToLight", kVec3f_GrSLType),
1479         GrGLShaderVar("lightColor", kVec3f_GrSLType)
1480     };
1481     SkString lightBody;
1482     lightBody.appendf("\tvec3 halfDir = vec3(normalize(surfaceToLight + vec3(0, 0, 1)));\n");
1483     lightBody.appendf("\tfloat colorScale = %s * pow(dot(normal, halfDir), %s);\n", ks, shininess);
1484     lightBody.appendf("\tvec3 color = lightColor * clamp(colorScale, 0.0, 1.0);\n");
1485     lightBody.appendf("\treturn vec4(color, max(max(color.r, color.g), color.b));\n");
1486     builder->fsEmitFunction(kVec4f_GrSLType,
1487                             "light",
1488                             SK_ARRAY_COUNT(gLightArgs),
1489                             gLightArgs,
1490                             lightBody.c_str(),
1491                             funcName);
1492 }
1493
1494 void GrGLSpecularLightingEffect::setData(const GrGLProgramDataManager& pdman,
1495                                          const GrDrawEffect& drawEffect) {
1496     INHERITED::setData(pdman, drawEffect);
1497     const GrSpecularLightingEffect& spec = drawEffect.castEffect<GrSpecularLightingEffect>();
1498     pdman.set1f(fKSUni, spec.ks());
1499     pdman.set1f(fShininessUni, spec.shininess());
1500 }
1501
1502 ///////////////////////////////////////////////////////////////////////////////
1503 void GrGLLight::emitLightColorUniform(GrGLShaderBuilder* builder) {
1504     fColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
1505                                     kVec3f_GrSLType, "LightColor");
1506 }
1507
1508 void GrGLLight::emitLightColor(GrGLShaderBuilder* builder,
1509                                const char *surfaceToLight) {
1510     builder->fsCodeAppend(builder->getUniformCStr(this->lightColorUni()));
1511 }
1512
1513 void GrGLLight::setData(const GrGLProgramDataManager& pdman,
1514                         const SkLight* light) const {
1515     setUniformPoint3(pdman, fColorUni, light->color() * SkScalarInvert(SkIntToScalar(255)));
1516 }
1517
1518 ///////////////////////////////////////////////////////////////////////////////
1519
1520 void GrGLDistantLight::setData(const GrGLProgramDataManager& pdman,
1521                                const SkLight* light) const {
1522     INHERITED::setData(pdman, light);
1523     SkASSERT(light->type() == SkLight::kDistant_LightType);
1524     const SkDistantLight* distantLight = static_cast<const SkDistantLight*>(light);
1525     setUniformNormal3(pdman, fDirectionUni, distantLight->direction());
1526 }
1527
1528 void GrGLDistantLight::emitSurfaceToLight(GrGLShaderBuilder* builder, const char* z) {
1529     const char* dir;
1530     fDirectionUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, kVec3f_GrSLType,
1531                                         "LightDirection", &dir);
1532     builder->fsCodeAppend(dir);
1533 }
1534
1535 ///////////////////////////////////////////////////////////////////////////////
1536
1537 void GrGLPointLight::setData(const GrGLProgramDataManager& pdman,
1538                              const SkLight* light) const {
1539     INHERITED::setData(pdman, light);
1540     SkASSERT(light->type() == SkLight::kPoint_LightType);
1541     const SkPointLight* pointLight = static_cast<const SkPointLight*>(light);
1542     setUniformPoint3(pdman, fLocationUni, pointLight->location());
1543 }
1544
1545 void GrGLPointLight::emitSurfaceToLight(GrGLShaderBuilder* builder, const char* z) {
1546     const char* loc;
1547     fLocationUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, kVec3f_GrSLType,
1548                                        "LightLocation", &loc);
1549     builder->fsCodeAppendf("normalize(%s - vec3(%s.xy, %s))", loc, builder->fragmentPosition(), z);
1550 }
1551
1552 ///////////////////////////////////////////////////////////////////////////////
1553
1554 void GrGLSpotLight::setData(const GrGLProgramDataManager& pdman,
1555                             const SkLight* light) const {
1556     INHERITED::setData(pdman, light);
1557     SkASSERT(light->type() == SkLight::kSpot_LightType);
1558     const SkSpotLight* spotLight = static_cast<const SkSpotLight *>(light);
1559     setUniformPoint3(pdman, fLocationUni, spotLight->location());
1560     pdman.set1f(fExponentUni, spotLight->specularExponent());
1561     pdman.set1f(fCosInnerConeAngleUni, spotLight->cosInnerConeAngle());
1562     pdman.set1f(fCosOuterConeAngleUni, spotLight->cosOuterConeAngle());
1563     pdman.set1f(fConeScaleUni, spotLight->coneScale());
1564     setUniformNormal3(pdman, fSUni, spotLight->s());
1565 }
1566
1567 void GrGLSpotLight::emitSurfaceToLight(GrGLShaderBuilder* builder, const char* z) {
1568     const char* location;
1569     fLocationUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
1570                                        kVec3f_GrSLType, "LightLocation", &location);
1571     builder->fsCodeAppendf("normalize(%s - vec3(%s.xy, %s))",
1572                            location, builder->fragmentPosition(), z);
1573 }
1574
1575 void GrGLSpotLight::emitLightColor(GrGLShaderBuilder* builder,
1576                                    const char *surfaceToLight) {
1577
1578     const char* color = builder->getUniformCStr(this->lightColorUni()); // created by parent class.
1579
1580     const char* exponent;
1581     const char* cosInner;
1582     const char* cosOuter;
1583     const char* coneScale;
1584     const char* s;
1585     fExponentUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
1586                                        kFloat_GrSLType, "Exponent", &exponent);
1587     fCosInnerConeAngleUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
1588                                                 kFloat_GrSLType, "CosInnerConeAngle", &cosInner);
1589     fCosOuterConeAngleUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
1590                                                 kFloat_GrSLType, "CosOuterConeAngle", &cosOuter);
1591     fConeScaleUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
1592                                         kFloat_GrSLType, "ConeScale", &coneScale);
1593     fSUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
1594                                 kVec3f_GrSLType, "S", &s);
1595
1596     static const GrGLShaderVar gLightColorArgs[] = {
1597         GrGLShaderVar("surfaceToLight", kVec3f_GrSLType)
1598     };
1599     SkString lightColorBody;
1600     lightColorBody.appendf("\tfloat cosAngle = -dot(surfaceToLight, %s);\n", s);
1601     lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosOuter);
1602     lightColorBody.appendf("\t\treturn vec3(0);\n");
1603     lightColorBody.appendf("\t}\n");
1604     lightColorBody.appendf("\tfloat scale = pow(cosAngle, %s);\n", exponent);
1605     lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosInner);
1606     lightColorBody.appendf("\t\treturn %s * scale * (cosAngle - %s) * %s;\n",
1607                            color, cosOuter, coneScale);
1608     lightColorBody.appendf("\t}\n");
1609     lightColorBody.appendf("\treturn %s;\n", color);
1610     builder->fsEmitFunction(kVec3f_GrSLType,
1611                             "lightColor",
1612                             SK_ARRAY_COUNT(gLightColorArgs),
1613                             gLightColorArgs,
1614                             lightColorBody.c_str(),
1615                             &fLightColorFunc);
1616
1617     builder->fsCodeAppendf("%s(%s)", fLightColorFunc.c_str(), surfaceToLight);
1618 }
1619
1620 #endif
1621
1622 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingImageFilter)
1623     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDiffuseLightingImageFilter)
1624     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSpecularLightingImageFilter)
1625 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END