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