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
24class GrGLDiffuseLightingEffect;
25class GrGLSpecularLightingEffect;
26
27// For brevity
28typedef GrGLProgramDataManager::UniformHandle UniformHandle;
29#endif
30
31namespace {
32
33const SkScalar gOneThird = SkScalarInvert(SkIntToScalar(3));
34const SkScalar gTwoThirds = SkScalarDiv(SkIntToScalar(2), SkIntToScalar(3));
35const SkScalar gOneHalf = 0.5f;
36const SkScalar gOneQuarter = 0.25f;
37
38#if SK_SUPPORT_GPU
39void 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
45void 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.
52inline 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
61class DiffuseLightingType {
62public:
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    }
75private:
76    SkScalar fKD;
77};
78
79class SpecularLightingType {
80public:
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    }
97private:
98    SkScalar fKS;
99    SkScalar fShininess;
100};
101
102inline 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
106inline 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
114inline 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
120inline 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
126inline 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
132inline 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
139inline 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
145inline 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
151inline 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
157inline 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
163inline 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
169template <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
263SkPoint3 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
274void writePoint3(const SkPoint3& point, SkWriteBuffer& buffer) {
275    buffer.writeScalar(point.fX);
276    buffer.writeScalar(point.fY);
277    buffer.writeScalar(point.fZ);
278};
279
280class SkDiffuseLightingImageFilter : public SkLightingImageFilter {
281public:
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
288protected:
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
303private:
304    friend class SkLightingImageFilter;
305    typedef SkLightingImageFilter INHERITED;
306    SkScalar fKD;
307};
308
309class SkSpecularLightingImageFilter : public SkLightingImageFilter {
310public:
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
320protected:
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
335private:
336    SkScalar fKS;
337    SkScalar fShininess;
338    friend class SkLightingImageFilter;
339    typedef SkLightingImageFilter INHERITED;
340};
341
342#if SK_SUPPORT_GPU
343
344class GrLightingEffect : public GrSingleTextureEffect {
345public:
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
359protected:
360    virtual bool onIsEqual(const GrProcessor&) const SK_OVERRIDE;
361
362private:
363    typedef GrSingleTextureEffect INHERITED;
364    const SkLight* fLight;
365    SkScalar fSurfaceScale;
366    SkMatrix fFilterMatrix;
367};
368
369class GrDiffuseLightingEffect : public GrLightingEffect {
370public:
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
390private:
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
404class GrSpecularLightingEffect : public GrLightingEffect {
405public:
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
427private:
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
445class GrGLLight {
446public:
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
471protected:
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
478private:
479    UniformHandle fColorUni;
480
481    typedef SkRefCnt INHERITED;
482};
483
484///////////////////////////////////////////////////////////////////////////////
485
486class GrGLDistantLight : public GrGLLight {
487public:
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
493private:
494    typedef GrGLLight INHERITED;
495    UniformHandle fDirectionUni;
496};
497
498///////////////////////////////////////////////////////////////////////////////
499
500class GrGLPointLight : public GrGLLight {
501public:
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
507private:
508    typedef GrGLLight INHERITED;
509    UniformHandle fLocationUni;
510};
511
512///////////////////////////////////////////////////////////////////////////////
513
514class GrGLSpotLight : public GrGLLight {
515public:
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
522private:
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
535class GrGLLight;
536
537#endif
538
539};
540
541///////////////////////////////////////////////////////////////////////////////
542
543class SkLight : public SkRefCnt {
544public:
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
566protected:
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
580private:
581    typedef SkRefCnt INHERITED;
582    SkPoint3 fColor;
583};
584
585///////////////////////////////////////////////////////////////////////////////
586
587class SkDistantLight : public SkLight {
588public:
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
623protected:
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
634private:
635    typedef SkLight INHERITED;
636    SkPoint3 fDirection;
637};
638
639///////////////////////////////////////////////////////////////////////////////
640
641class SkPointLight : public SkLight {
642public:
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
687protected:
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
694private:
695    typedef SkLight INHERITED;
696    SkPoint3 fLocation;
697};
698
699///////////////////////////////////////////////////////////////////////////////
700
701class SkSpotLight : public SkLight {
702public:
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    }
784protected:
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
819private:
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
835const SkScalar SkSpotLight::kSpecularExponentMin = 1.0f;
836const SkScalar SkSpotLight::kSpecularExponentMax = 128.0f;
837
838///////////////////////////////////////////////////////////////////////////////
839
840void 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
864SkLightingImageFilter::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
872SkImageFilter* 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
882SkImageFilter* 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
892SkImageFilter* 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
906SkImageFilter* 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
917SkImageFilter* 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
928SkImageFilter* 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
943SkLightingImageFilter::~SkLightingImageFilter() {}
944
945#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
946SkLightingImageFilter::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
954void SkLightingImageFilter::flatten(SkWriteBuffer& buffer) const {
955    this->INHERITED::flatten(buffer);
956    fLight->flattenLight(buffer);
957    buffer.writeScalar(fSurfaceScale * 255);
958}
959
960///////////////////////////////////////////////////////////////////////////////
961
962SkImageFilter* 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
978SkDiffuseLightingImageFilter::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
985SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkReadBuffer& buffer)
986  : INHERITED(buffer)
987{
988    fKD = buffer.readScalar();
989    buffer.validate(SkScalarIsFinite(fKD) && (fKD >= 0));
990}
991#endif
992
993SkFlattenable* 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
1001void SkDiffuseLightingImageFilter::flatten(SkWriteBuffer& buffer) const {
1002    this->INHERITED::flatten(buffer);
1003    buffer.writeScalar(fKD);
1004}
1005
1006bool 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
1061bool 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
1075SkImageFilter* 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
1092SkSpecularLightingImageFilter::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
1100SkSpecularLightingImageFilter::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
1110SkFlattenable* 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
1119void SkSpecularLightingImageFilter::flatten(SkWriteBuffer& buffer) const {
1120    this->INHERITED::flatten(buffer);
1121    buffer.writeScalar(fKS);
1122    buffer.writeScalar(fShininess);
1123}
1124
1125bool 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
1179bool 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
1195namespace {
1196SkPoint3 random_point3(SkRandom* random) {
1197    return SkPoint3(SkScalarToFloat(random->nextSScalar1()),
1198                    SkScalarToFloat(random->nextSScalar1()),
1199                    SkScalarToFloat(random->nextSScalar1()));
1200}
1201
1202SkLight* 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
1226class GrGLLightingEffect  : public GrGLFragmentProcessor {
1227public:
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
1246protected:
1247    virtual void emitLightFunc(GrGLProgramBuilder*, SkString* funcName) = 0;
1248
1249private:
1250    typedef GrGLFragmentProcessor INHERITED;
1251
1252    UniformHandle       fImageIncrementUni;
1253    UniformHandle       fSurfaceScaleUni;
1254    GrGLLight*          fLight;
1255};
1256
1257///////////////////////////////////////////////////////////////////////////////
1258
1259class GrGLDiffuseLightingEffect  : public GrGLLightingEffect {
1260public:
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
1265private:
1266    typedef GrGLLightingEffect INHERITED;
1267
1268    UniformHandle   fKDUni;
1269};
1270
1271///////////////////////////////////////////////////////////////////////////////
1272
1273class GrGLSpecularLightingEffect  : public GrGLLightingEffect {
1274public:
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
1279private:
1280    typedef GrGLLightingEffect INHERITED;
1281
1282    UniformHandle   fKSUni;
1283    UniformHandle   fShininessUni;
1284};
1285
1286///////////////////////////////////////////////////////////////////////////////
1287
1288GrLightingEffect::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
1302GrLightingEffect::~GrLightingEffect() {
1303    fLight->unref();
1304}
1305
1306bool 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
1315GrDiffuseLightingEffect::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
1323const GrBackendFragmentProcessorFactory& GrDiffuseLightingEffect::getFactory() const {
1324    return GrTBackendFragmentProcessorFactory<GrDiffuseLightingEffect>::getInstance();
1325}
1326
1327bool 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
1333GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDiffuseLightingEffect);
1334
1335GrFragmentProcessor* 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
1353GrGLLightingEffect::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
1360GrGLLightingEffect::~GrGLLightingEffect() {
1361    delete fLight;
1362}
1363
1364void 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
1461void GrGLLightingEffect::GenKey(const GrProcessor& proc,
1462                                const GrGLCaps& caps, GrProcessorKeyBuilder* b) {
1463    b->add32(proc.cast<GrLightingEffect>().light()->type());
1464}
1465
1466void 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
1481GrGLDiffuseLightingEffect::GrGLDiffuseLightingEffect(const GrBackendProcessorFactory& factory,
1482                                                     const GrProcessor& proc)
1483    : INHERITED(factory, proc) {
1484}
1485
1486void 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
1509void 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
1518GrSpecularLightingEffect::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
1529const GrBackendFragmentProcessorFactory& GrSpecularLightingEffect::getFactory() const {
1530    return GrTBackendFragmentProcessorFactory<GrSpecularLightingEffect>::getInstance();
1531}
1532
1533bool 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
1540GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrSpecularLightingEffect);
1541
1542GrFragmentProcessor* 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
1560GrGLSpecularLightingEffect::GrGLSpecularLightingEffect(const GrBackendProcessorFactory& factory,
1561                                                       const GrProcessor& proc)
1562    : INHERITED(factory, proc) {
1563}
1564
1565void 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
1592void 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///////////////////////////////////////////////////////////////////////////////
1601void GrGLLight::emitLightColorUniform(GrGLProgramBuilder* builder) {
1602    fColorUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
1603                                    kVec3f_GrSLType, "LightColor");
1604}
1605
1606void GrGLLight::emitLightColor(GrGLProgramBuilder* builder,
1607                               const char *surfaceToLight) {
1608    builder->getFragmentShaderBuilder()->codeAppend(builder->getUniformCStr(this->lightColorUni()));
1609}
1610
1611void GrGLLight::setData(const GrGLProgramDataManager& pdman,
1612                        const SkLight* light) const {
1613    setUniformPoint3(pdman, fColorUni, light->color() * SkScalarInvert(SkIntToScalar(255)));
1614}
1615
1616///////////////////////////////////////////////////////////////////////////////
1617
1618void 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
1626void 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
1635void 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
1643void 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
1654void 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
1667void 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
1677void 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
1725SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingImageFilter)
1726    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDiffuseLightingImageFilter)
1727    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSpecularLightingImageFilter)
1728SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
1729