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