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