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