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