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