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