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