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