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 "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 
     22 class GrGLDiffuseLightingEffect;
     23 class GrGLSpecularLightingEffect;
     24 
     25 // For brevity
     26 typedef GrGLUniformManager::UniformHandle UniformHandle;
     27 #endif
     28 
     29 namespace {
     30 
     31 const SkScalar gOneThird = SkScalarInvert(SkIntToScalar(3));
     32 const SkScalar gTwoThirds = SkScalarDiv(SkIntToScalar(2), SkIntToScalar(3));
     33 const SkScalar gOneHalf = 0.5f;
     34 const SkScalar gOneQuarter = 0.25f;
     35 
     36 #if SK_SUPPORT_GPU
     37 void 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 
     42 void 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.
     48 inline 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 
     57 class DiffuseLightingType {
     58 public:
     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     }
     70 private:
     71     SkScalar fKD;
     72 };
     73 
     74 class SpecularLightingType {
     75 public:
     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     }
     91 private:
     92     SkScalar fKS;
     93     SkScalar fShininess;
     94 };
     95 
     96 inline 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 
    100 inline 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 
    108 inline 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 
    114 inline 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 
    120 inline 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 
    126 inline 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 
    133 inline 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 
    139 inline 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 
    145 inline 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 
    151 inline 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 
    157 inline 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 
    163 template <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 
    246 SkPoint3 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 
    257 void writePoint3(const SkPoint3& point, SkFlattenableWriteBuffer& buffer) {
    258     buffer.writeScalar(point.fX);
    259     buffer.writeScalar(point.fY);
    260     buffer.writeScalar(point.fZ);
    261 };
    262 
    263 class SkDiffuseLightingImageFilter : public SkLightingImageFilter {
    264 public:
    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 
    270 protected:
    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 
    279 private:
    280     typedef SkLightingImageFilter INHERITED;
    281     SkScalar fKD;
    282 };
    283 
    284 class SkSpecularLightingImageFilter : public SkLightingImageFilter {
    285 public:
    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 
    292 protected:
    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 
    301 private:
    302     typedef SkLightingImageFilter INHERITED;
    303     SkScalar fKS;
    304     SkScalar fShininess;
    305 };
    306 
    307 #if SK_SUPPORT_GPU
    308 
    309 class GrLightingEffect : public GrSingleTextureEffect {
    310 public:
    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 
    324 protected:
    325     virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
    326 
    327 private:
    328     typedef GrSingleTextureEffect INHERITED;
    329     const SkLight* fLight;
    330     SkScalar fSurfaceScale;
    331     SkMatrix fFilterMatrix;
    332 };
    333 
    334 class GrDiffuseLightingEffect : public GrLightingEffect {
    335 public:
    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 
    356 private:
    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 
    370 class GrSpecularLightingEffect : public GrLightingEffect {
    371 public:
    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 
    394 private:
    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 
    412 class GrGLLight {
    413 public:
    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 
    438 protected:
    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 
    445 private:
    446     UniformHandle fColorUni;
    447 
    448     typedef SkRefCnt INHERITED;
    449 };
    450 
    451 ///////////////////////////////////////////////////////////////////////////////
    452 
    453 class GrGLDistantLight : public GrGLLight {
    454 public:
    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 
    460 private:
    461     typedef GrGLLight INHERITED;
    462     UniformHandle fDirectionUni;
    463 };
    464 
    465 ///////////////////////////////////////////////////////////////////////////////
    466 
    467 class GrGLPointLight : public GrGLLight {
    468 public:
    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 
    474 private:
    475     typedef GrGLLight INHERITED;
    476     UniformHandle fLocationUni;
    477 };
    478 
    479 ///////////////////////////////////////////////////////////////////////////////
    480 
    481 class GrGLSpotLight : public GrGLLight {
    482 public:
    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 
    489 private:
    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 
    502 class GrGLLight;
    503 
    504 #endif
    505 
    506 };
    507 
    508 ///////////////////////////////////////////////////////////////////////////////
    509 
    510 class SkLight : public SkRefCnt {
    511 public:
    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 
    533 protected:
    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 
    547 private:
    548     typedef SkRefCnt INHERITED;
    549     SkPoint3 fColor;
    550 };
    551 
    552 ///////////////////////////////////////////////////////////////////////////////
    553 
    554 class SkDistantLight : public SkLight {
    555 public:
    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 
    590 protected:
    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 
    601 private:
    602     typedef SkLight INHERITED;
    603     SkPoint3 fDirection;
    604 };
    605 
    606 ///////////////////////////////////////////////////////////////////////////////
    607 
    608 class SkPointLight : public SkLight {
    609 public:
    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 
    651 protected:
    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 
    658 private:
    659     typedef SkLight INHERITED;
    660     SkPoint3 fLocation;
    661 };
    662 
    663 ///////////////////////////////////////////////////////////////////////////////
    664 
    665 class SkSpotLight : public SkLight {
    666 public:
    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     }
    741 protected:
    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 
    776 private:
    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
    792 const SkScalar SkSpotLight::kSpecularExponentMin = 1.0f;
    793 const SkScalar SkSpotLight::kSpecularExponentMax = 128.0f;
    794 
    795 ///////////////////////////////////////////////////////////////////////////////
    796 
    797 void 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 
    821 SkLightingImageFilter::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 
    831 SkImageFilter* 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 
    839 SkImageFilter* 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 
    847 SkImageFilter* 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 
    858 SkImageFilter* 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 
    866 SkImageFilter* 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 
    874 SkImageFilter* 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 
    884 SkLightingImageFilter::~SkLightingImageFilter() {
    885     SkSafeUnref(fLight);
    886 }
    887 
    888 SkLightingImageFilter::SkLightingImageFilter(SkFlattenableReadBuffer& buffer)
    889   : INHERITED(1, buffer) {
    890     fLight = SkLight::UnflattenLight(buffer);
    891     fSurfaceScale = buffer.readScalar();
    892     buffer.validate(SkScalarIsFinite(fSurfaceScale));
    893 }
    894 
    895 void SkLightingImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
    896     this->INHERITED::flatten(buffer);
    897     fLight->flattenLight(buffer);
    898     buffer.writeScalar(fSurfaceScale);
    899 }
    900 
    901 ///////////////////////////////////////////////////////////////////////////////
    902 
    903 SkDiffuseLightingImageFilter::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 
    911 SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkFlattenableReadBuffer& buffer)
    912   : INHERITED(buffer)
    913 {
    914     fKD = buffer.readScalar();
    915     buffer.validate(SkScalarIsFinite(fKD) && (fKD >= 0));
    916 }
    917 
    918 void SkDiffuseLightingImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
    919     this->INHERITED::flatten(buffer);
    920     buffer.writeScalar(fKD);
    921 }
    922 
    923 bool 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
    979 bool 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 
    990 SkSpecularLightingImageFilter::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 
    999 SkSpecularLightingImageFilter::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 
   1008 void SkSpecularLightingImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
   1009     this->INHERITED::flatten(buffer);
   1010     buffer.writeScalar(fKS);
   1011     buffer.writeScalar(fShininess);
   1012 }
   1013 
   1014 bool 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
   1068 bool 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 
   1081 namespace {
   1082 SkPoint3 random_point3(SkRandom* random) {
   1083     return SkPoint3(SkScalarToFloat(random->nextSScalar1()),
   1084                     SkScalarToFloat(random->nextSScalar1()),
   1085                     SkScalarToFloat(random->nextSScalar1()));
   1086 }
   1087 
   1088 SkLight* 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 
   1112 class GrGLLightingEffect  : public GrGLEffect {
   1113 public:
   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 
   1133 protected:
   1134     virtual void emitLightFunc(GrGLShaderBuilder*, SkString* funcName) = 0;
   1135 
   1136 private:
   1137     typedef GrGLEffect INHERITED;
   1138 
   1139     UniformHandle       fImageIncrementUni;
   1140     UniformHandle       fSurfaceScaleUni;
   1141     GrGLLight*          fLight;
   1142 };
   1143 
   1144 ///////////////////////////////////////////////////////////////////////////////
   1145 
   1146 class GrGLDiffuseLightingEffect  : public GrGLLightingEffect {
   1147 public:
   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 
   1153 private:
   1154     typedef GrGLLightingEffect INHERITED;
   1155 
   1156     UniformHandle   fKDUni;
   1157 };
   1158 
   1159 ///////////////////////////////////////////////////////////////////////////////
   1160 
   1161 class GrGLSpecularLightingEffect  : public GrGLLightingEffect {
   1162 public:
   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 
   1168 private:
   1169     typedef GrGLLightingEffect INHERITED;
   1170 
   1171     UniformHandle   fKSUni;
   1172     UniformHandle   fShininessUni;
   1173 };
   1174 
   1175 ///////////////////////////////////////////////////////////////////////////////
   1176 
   1177 GrLightingEffect::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 
   1191 GrLightingEffect::~GrLightingEffect() {
   1192     fLight->unref();
   1193 }
   1194 
   1195 bool 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 
   1204 GrDiffuseLightingEffect::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 
   1212 const GrBackendEffectFactory& GrDiffuseLightingEffect::getFactory() const {
   1213     return GrTBackendEffectFactory<GrDiffuseLightingEffect>::getInstance();
   1214 }
   1215 
   1216 bool 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 
   1222 GR_DEFINE_EFFECT_TEST(GrDiffuseLightingEffect);
   1223 
   1224 GrEffectRef* 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 
   1242 GrGLLightingEffect::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 
   1249 GrGLLightingEffect::~GrGLLightingEffect() {
   1250     delete fLight;
   1251 }
   1252 
   1253 void 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 
   1349 GrGLEffect::EffectKey GrGLLightingEffect::GenKey(const GrDrawEffect& drawEffect,
   1350                                                  const GrGLCaps& caps) {
   1351     return drawEffect.castEffect<GrLightingEffect>().light()->type();
   1352 }
   1353 
   1354 void 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 
   1369 GrGLDiffuseLightingEffect::GrGLDiffuseLightingEffect(const GrBackendEffectFactory& factory,
   1370                                                      const GrDrawEffect& drawEffect)
   1371     : INHERITED(factory, drawEffect) {
   1372 }
   1373 
   1374 void 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 
   1397 void 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 
   1406 GrSpecularLightingEffect::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 
   1417 const GrBackendEffectFactory& GrSpecularLightingEffect::getFactory() const {
   1418     return GrTBackendEffectFactory<GrSpecularLightingEffect>::getInstance();
   1419 }
   1420 
   1421 bool 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 
   1428 GR_DEFINE_EFFECT_TEST(GrSpecularLightingEffect);
   1429 
   1430 GrEffectRef* 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 
   1448 GrGLSpecularLightingEffect::GrGLSpecularLightingEffect(const GrBackendEffectFactory& factory,
   1449                                                        const GrDrawEffect& drawEffect)
   1450     : INHERITED(factory, drawEffect) {
   1451 }
   1452 
   1453 void 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 
   1480 void 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 ///////////////////////////////////////////////////////////////////////////////
   1489 void GrGLLight::emitLightColorUniform(GrGLShaderBuilder* builder) {
   1490     fColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility,
   1491                                     kVec3f_GrSLType, "LightColor");
   1492 }
   1493 
   1494 void GrGLLight::emitLightColor(GrGLShaderBuilder* builder,
   1495                                const char *surfaceToLight) {
   1496     builder->fsCodeAppend(builder->getUniformCStr(this->lightColorUni()));
   1497 }
   1498 
   1499 void GrGLLight::setData(const GrGLUniformManager& uman,
   1500                         const SkLight* light) const {
   1501     setUniformPoint3(uman, fColorUni, light->color() * SkScalarInvert(SkIntToScalar(255)));
   1502 }
   1503 
   1504 ///////////////////////////////////////////////////////////////////////////////
   1505 
   1506 void 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 
   1514 void 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 
   1523 void 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 
   1531 void 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 
   1540 void 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 
   1553 void 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 
   1561 void 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 
   1608 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingImageFilter)
   1609     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDiffuseLightingImageFilter)
   1610     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSpecularLightingImageFilter)
   1611 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
   1612