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