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