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