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