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