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