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