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