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