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