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