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