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