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