• 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; }
621 
622 protected:
623     class ImplBase;
624 
625     LightingEffect(ClassID classID,
626                    GrSurfaceProxyView,
627                    sk_sp<const SkImageFilterLight> light,
628                    SkScalar surfaceScale,
629                    const SkMatrix& matrix,
630                    BoundaryMode boundaryMode,
631                    const SkIRect* srcBounds,
632                    const GrCaps& caps);
633 
634     explicit LightingEffect(const LightingEffect& that);
635 
636     bool onIsEqual(const GrFragmentProcessor&) const override;
637 
638 private:
onAddToKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const639     void onAddToKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
640         b->add32(fBoundaryMode << 2 | fLight->type());
641     }
642 
643     sk_sp<const SkImageFilterLight> fLight;
644     SkScalar fSurfaceScale;
645     SkMatrix fFilterMatrix;
646     BoundaryMode fBoundaryMode;
647 
648     using INHERITED = GrFragmentProcessor;
649 };
650 
651 class DiffuseLightingEffect : public LightingEffect {
652 public:
Make(GrSurfaceProxyView view,sk_sp<const SkImageFilterLight> light,SkScalar surfaceScale,const SkMatrix & matrix,SkScalar kd,BoundaryMode boundaryMode,const SkIRect * srcBounds,const GrCaps & caps)653     static std::unique_ptr<GrFragmentProcessor> Make(GrSurfaceProxyView view,
654                                                      sk_sp<const SkImageFilterLight> light,
655                                                      SkScalar surfaceScale,
656                                                      const SkMatrix& matrix,
657                                                      SkScalar kd,
658                                                      BoundaryMode boundaryMode,
659                                                      const SkIRect* srcBounds,
660                                                      const GrCaps& caps) {
661         return std::unique_ptr<GrFragmentProcessor>(new DiffuseLightingEffect(std::move(view),
662                                                                               std::move(light),
663                                                                               surfaceScale,
664                                                                               matrix,
665                                                                               kd,
666                                                                               boundaryMode,
667                                                                               srcBounds,
668                                                                               caps));
669     }
670 
name() const671     const char* name() const override { return "DiffuseLighting"; }
672 
clone() const673     std::unique_ptr<GrFragmentProcessor> clone() const override {
674         return std::unique_ptr<GrFragmentProcessor>(new DiffuseLightingEffect(*this));
675     }
676 
677 private:
678     class Impl;
679 
680     std::unique_ptr<ProgramImpl> onMakeProgramImpl() const override;
681 
682     bool onIsEqual(const GrFragmentProcessor&) const override;
683 
684     DiffuseLightingEffect(GrSurfaceProxyView view,
685                           sk_sp<const SkImageFilterLight> light,
686                           SkScalar surfaceScale,
687                           const SkMatrix& matrix,
688                           SkScalar kd,
689                           BoundaryMode boundaryMode,
690                           const SkIRect* srcBounds,
691                           const GrCaps& caps);
692 
693     explicit DiffuseLightingEffect(const DiffuseLightingEffect& that);
694 
695     GR_DECLARE_FRAGMENT_PROCESSOR_TEST
696     SkScalar fKD;
697 
698     using INHERITED = LightingEffect;
699 };
700 
701 class SpecularLightingEffect : public LightingEffect {
702 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)703     static std::unique_ptr<GrFragmentProcessor> Make(GrSurfaceProxyView view,
704                                                      sk_sp<const SkImageFilterLight> light,
705                                                      SkScalar surfaceScale,
706                                                      const SkMatrix& matrix,
707                                                      SkScalar ks,
708                                                      SkScalar shininess,
709                                                      BoundaryMode boundaryMode,
710                                                      const SkIRect* srcBounds,
711                                                      const GrCaps& caps) {
712         return std::unique_ptr<GrFragmentProcessor>(new SpecularLightingEffect(std::move(view),
713                                                                                std::move(light),
714                                                                                surfaceScale,
715                                                                                matrix,
716                                                                                ks,
717                                                                                shininess,
718                                                                                boundaryMode,
719                                                                                srcBounds,
720                                                                                caps));
721     }
722 
name() const723     const char* name() const override { return "SpecularLighting"; }
724 
clone() const725     std::unique_ptr<GrFragmentProcessor> clone() const override {
726         return std::unique_ptr<GrFragmentProcessor>(new SpecularLightingEffect(*this));
727     }
728 
729     std::unique_ptr<ProgramImpl> onMakeProgramImpl() const override;
730 
731 private:
732     class Impl;
733 
734     bool onIsEqual(const GrFragmentProcessor&) const override;
735 
736     SpecularLightingEffect(GrSurfaceProxyView,
737                            sk_sp<const SkImageFilterLight> light,
738                            SkScalar surfaceScale,
739                            const SkMatrix& matrix,
740                            SkScalar ks,
741                            SkScalar shininess,
742                            BoundaryMode boundaryMode,
743                            const SkIRect* srcBounds,
744                            const GrCaps&);
745 
746     explicit SpecularLightingEffect(const SpecularLightingEffect&);
747 
748     GR_DECLARE_FRAGMENT_PROCESSOR_TEST
749     SkScalar fKS;
750     SkScalar fShininess;
751 
752     using INHERITED = LightingEffect;
753 };
754 
755 ///////////////////////////////////////////////////////////////////////////////
756 
757 class GpuLight {
758 public:
759     virtual ~GpuLight() = default;
760 
761     /**
762      * This is called by GrGLLightingEffect::emitCode() before either of the two virtual functions
763      * below. It adds a half3 uniform visible in the FS that represents the constant light color.
764      */
765     void emitLightColorUniform(const GrFragmentProcessor*, GrGLSLUniformHandler*);
766 
767     /**
768      * These two functions are called from GrGLLightingEffect's emitCode() function.
769      * emitSurfaceToLight places an expression in param out that is the vector from the surface to
770      * the light. The expression will be used in the FS. emitLightColor writes an expression into
771      * the FS that is the color of the light. Either function may add functions and/or uniforms to
772      * the FS. The default of emitLightColor appends the name of the constant light color uniform
773      * and so this function only needs to be overridden if the light color varies spatially.
774      */
775     virtual void emitSurfaceToLight(const GrFragmentProcessor*,
776                                     GrGLSLUniformHandler*,
777                                     GrGLSLFPFragmentBuilder*,
778                                     const char* z) = 0;
779     virtual void emitLightColor(const GrFragmentProcessor*,
780                                 GrGLSLUniformHandler*,
781                                 GrGLSLFPFragmentBuilder*,
782                                 const char *surfaceToLight);
783 
784     // This is called from GrGLLightingEffect's setData(). Subclasses of GrGLLight must call
785     // INHERITED::setData().
786     virtual void setData(const GrGLSLProgramDataManager&, const SkImageFilterLight* light) const;
787 
788 protected:
789     /**
790      * Gets the constant light color uniform. Subclasses can use this in their emitLightColor
791      * function.
792      */
lightColorUni() const793     UniformHandle lightColorUni() const { return fColorUni; }
794 
795 private:
796     UniformHandle fColorUni;
797 
798     using INHERITED = SkRefCnt;
799 };
800 
801 ///////////////////////////////////////////////////////////////////////////////
802 
803 class GpuDistantLight : public GpuLight {
804 public:
805     void setData(const GrGLSLProgramDataManager&, const SkImageFilterLight* light) const override;
806     void emitSurfaceToLight(const GrFragmentProcessor*, GrGLSLUniformHandler*,
807                             GrGLSLFPFragmentBuilder*, const char* z) override;
808 
809 private:
810     using INHERITED = GpuLight;
811     UniformHandle fDirectionUni;
812 };
813 
814 ///////////////////////////////////////////////////////////////////////////////
815 
816 class GpuPointLight : public GpuLight {
817 public:
818     void setData(const GrGLSLProgramDataManager&, const SkImageFilterLight* light) const override;
819     void emitSurfaceToLight(const GrFragmentProcessor*, GrGLSLUniformHandler*,
820                             GrGLSLFPFragmentBuilder*, const char* z) override;
821 
822 private:
823     using INHERITED = GpuLight;
824     UniformHandle fLocationUni;
825 };
826 
827 ///////////////////////////////////////////////////////////////////////////////
828 
829 class GpuSpotLight : public GpuLight {
830 public:
831     void setData(const GrGLSLProgramDataManager&, const SkImageFilterLight* light) const override;
832     void emitSurfaceToLight(const GrFragmentProcessor*, GrGLSLUniformHandler*,
833                             GrGLSLFPFragmentBuilder*, const char* z) override;
834     void emitLightColor(const GrFragmentProcessor*,
835                         GrGLSLUniformHandler*,
836                         GrGLSLFPFragmentBuilder*,
837                         const char *surfaceToLight) override;
838 
839 private:
840     using INHERITED = GpuLight;
841 
842     SkString        fLightColorFunc;
843     UniformHandle   fLocationUni;
844     UniformHandle   fExponentUni;
845     UniformHandle   fCosOuterConeAngleUni;
846     UniformHandle   fCosInnerConeAngleUni;
847     UniformHandle   fConeScaleUni;
848     UniformHandle   fSUni;
849 };
850 
851 #else
852 
853 class GpuLight {};
854 
855 #endif
856 
857 ///////////////////////////////////////////////////////////////////////////////
858 
859 class SkDistantLight : public SkImageFilterLight {
860 public:
SkDistantLight(const SkPoint3 & direction,SkColor color)861     SkDistantLight(const SkPoint3& direction, SkColor color)
862       : INHERITED(color), fDirection(direction) {
863     }
864 
surfaceToLight(int x,int y,int z,SkScalar surfaceScale) const865     SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const override {
866         return fDirection;
867     }
lightColor(const SkPoint3 &) const868     SkPoint3 lightColor(const SkPoint3&) const override { return this->color(); }
type() const869     LightType type() const override { return kDistant_LightType; }
direction() const870     const SkPoint3& direction() const { return fDirection; }
createGpuLight() const871     std::unique_ptr<GpuLight> createGpuLight() const override {
872 #if SK_SUPPORT_GPU
873         return std::make_unique<GpuDistantLight>();
874 #else
875         SkDEBUGFAIL("Should not call in GPU-less build");
876         return nullptr;
877 #endif
878     }
879 
isEqual(const SkImageFilterLight & other) const880     bool isEqual(const SkImageFilterLight& other) const override {
881         if (other.type() != kDistant_LightType) {
882             return false;
883         }
884 
885         const SkDistantLight& o = static_cast<const SkDistantLight&>(other);
886         return INHERITED::isEqual(other) &&
887                fDirection == o.fDirection;
888     }
889 
SkDistantLight(SkReadBuffer & buffer)890     SkDistantLight(SkReadBuffer& buffer) : INHERITED(buffer) {
891         fDirection = read_point3(buffer);
892     }
893 
894 protected:
SkDistantLight(const SkPoint3 & direction,const SkPoint3 & color)895     SkDistantLight(const SkPoint3& direction, const SkPoint3& color)
896       : INHERITED(color), fDirection(direction) {
897     }
transform(const SkMatrix & matrix) const898     SkImageFilterLight* transform(const SkMatrix& matrix) const override {
899         return new SkDistantLight(direction(), color());
900     }
onFlattenLight(SkWriteBuffer & buffer) const901     void onFlattenLight(SkWriteBuffer& buffer) const override {
902         write_point3(fDirection, buffer);
903     }
904 
905 private:
906     SkPoint3 fDirection;
907 
908     using INHERITED = SkImageFilterLight;
909 };
910 
911 ///////////////////////////////////////////////////////////////////////////////
912 
913 class SkPointLight : public SkImageFilterLight {
914 public:
SkPointLight(const SkPoint3 & location,SkColor color)915     SkPointLight(const SkPoint3& location, SkColor color)
916      : INHERITED(color), fLocation(location) {}
917 
surfaceToLight(int x,int y,int z,SkScalar surfaceScale) const918     SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const override {
919         SkPoint3 direction = SkPoint3::Make(fLocation.fX - SkIntToScalar(x),
920                                             fLocation.fY - SkIntToScalar(y),
921                                             fLocation.fZ - SkIntToScalar(z) * surfaceScale);
922         fast_normalize(&direction);
923         return direction;
924     }
lightColor(const SkPoint3 &) const925     SkPoint3 lightColor(const SkPoint3&) const override { return this->color(); }
type() const926     LightType type() const override { return kPoint_LightType; }
location() const927     const SkPoint3& location() const { return fLocation; }
createGpuLight() const928     std::unique_ptr<GpuLight> createGpuLight() const override {
929 #if SK_SUPPORT_GPU
930         return std::make_unique<GpuPointLight>();
931 #else
932         SkDEBUGFAIL("Should not call in GPU-less build");
933         return nullptr;
934 #endif
935     }
936 
isEqual(const SkImageFilterLight & other) const937     bool isEqual(const SkImageFilterLight& other) const override {
938         if (other.type() != kPoint_LightType) {
939             return false;
940         }
941         const SkPointLight& o = static_cast<const SkPointLight&>(other);
942         return INHERITED::isEqual(other) &&
943                fLocation == o.fLocation;
944     }
transform(const SkMatrix & matrix) const945     SkImageFilterLight* transform(const SkMatrix& matrix) const override {
946         SkPoint location2 = SkPoint::Make(fLocation.fX, fLocation.fY);
947         matrix.mapPoints(&location2, 1);
948         // Use X scale and Y scale on Z and average the result
949         SkPoint locationZ = SkPoint::Make(fLocation.fZ, fLocation.fZ);
950         matrix.mapVectors(&locationZ, 1);
951         SkPoint3 location = SkPoint3::Make(location2.fX,
952                                            location2.fY,
953                                            SkScalarAve(locationZ.fX, locationZ.fY));
954         return new SkPointLight(location, color());
955     }
956 
SkPointLight(SkReadBuffer & buffer)957     SkPointLight(SkReadBuffer& buffer) : INHERITED(buffer) {
958         fLocation = read_point3(buffer);
959     }
960 
961 protected:
SkPointLight(const SkPoint3 & location,const SkPoint3 & color)962     SkPointLight(const SkPoint3& location, const SkPoint3& color)
963      : INHERITED(color), fLocation(location) {}
onFlattenLight(SkWriteBuffer & buffer) const964     void onFlattenLight(SkWriteBuffer& buffer) const override {
965         write_point3(fLocation, buffer);
966     }
967 
968 private:
969     SkPoint3 fLocation;
970 
971     using INHERITED = SkImageFilterLight;
972 };
973 
974 ///////////////////////////////////////////////////////////////////////////////
975 
976 class SkSpotLight : public SkImageFilterLight {
977 public:
SkSpotLight(const SkPoint3 & location,const SkPoint3 & target,SkScalar specularExponent,SkScalar cutoffAngle,SkColor color)978     SkSpotLight(const SkPoint3& location,
979                 const SkPoint3& target,
980                 SkScalar specularExponent,
981                 SkScalar cutoffAngle,
982                 SkColor color)
983      : INHERITED(color),
984        fLocation(location),
985        fTarget(target),
986        fSpecularExponent(specularExponent)
987     {
988        fS = target - location;
989        fast_normalize(&fS);
990        fCosOuterConeAngle = SkScalarCos(SkDegreesToRadians(cutoffAngle));
991        const SkScalar antiAliasThreshold = 0.016f;
992        fCosInnerConeAngle = fCosOuterConeAngle + antiAliasThreshold;
993        fConeScale = SkScalarInvert(antiAliasThreshold);
994     }
995 
transform(const SkMatrix & matrix) const996     SkImageFilterLight* transform(const SkMatrix& matrix) const override {
997         SkPoint location2 = SkPoint::Make(fLocation.fX, fLocation.fY);
998         matrix.mapPoints(&location2, 1);
999         // Use X scale and Y scale on Z and average the result
1000         SkPoint locationZ = SkPoint::Make(fLocation.fZ, fLocation.fZ);
1001         matrix.mapVectors(&locationZ, 1);
1002         SkPoint3 location = SkPoint3::Make(location2.fX, location2.fY,
1003                                            SkScalarAve(locationZ.fX, locationZ.fY));
1004         SkPoint target2 = SkPoint::Make(fTarget.fX, fTarget.fY);
1005         matrix.mapPoints(&target2, 1);
1006         SkPoint targetZ = SkPoint::Make(fTarget.fZ, fTarget.fZ);
1007         matrix.mapVectors(&targetZ, 1);
1008         SkPoint3 target = SkPoint3::Make(target2.fX, target2.fY,
1009                                          SkScalarAve(targetZ.fX, targetZ.fY));
1010         SkPoint3 s = target - location;
1011         fast_normalize(&s);
1012         return new SkSpotLight(location,
1013                                target,
1014                                fSpecularExponent,
1015                                fCosOuterConeAngle,
1016                                fCosInnerConeAngle,
1017                                fConeScale,
1018                                s,
1019                                color());
1020     }
1021 
surfaceToLight(int x,int y,int z,SkScalar surfaceScale) const1022     SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const override {
1023         SkPoint3 direction = SkPoint3::Make(fLocation.fX - SkIntToScalar(x),
1024                                             fLocation.fY - SkIntToScalar(y),
1025                                             fLocation.fZ - SkIntToScalar(z) * surfaceScale);
1026         fast_normalize(&direction);
1027         return direction;
1028     }
lightColor(const SkPoint3 & surfaceToLight) const1029     SkPoint3 lightColor(const SkPoint3& surfaceToLight) const override {
1030         SkScalar cosAngle = -surfaceToLight.dot(fS);
1031         SkScalar scale = 0;
1032         if (cosAngle >= fCosOuterConeAngle) {
1033             scale = SkScalarPow(cosAngle, fSpecularExponent);
1034             if (cosAngle < fCosInnerConeAngle) {
1035                 scale *= (cosAngle - fCosOuterConeAngle) * fConeScale;
1036             }
1037         }
1038         return this->color().makeScale(scale);
1039     }
createGpuLight() const1040     std::unique_ptr<GpuLight> createGpuLight() const override {
1041 #if SK_SUPPORT_GPU
1042         return std::make_unique<GpuSpotLight>();
1043 #else
1044         SkDEBUGFAIL("Should not call in GPU-less build");
1045         return nullptr;
1046 #endif
1047     }
type() const1048     LightType type() const override { return kSpot_LightType; }
location() const1049     const SkPoint3& location() const { return fLocation; }
target() const1050     const SkPoint3& target() const { return fTarget; }
specularExponent() const1051     SkScalar specularExponent() const { return fSpecularExponent; }
cosInnerConeAngle() const1052     SkScalar cosInnerConeAngle() const { return fCosInnerConeAngle; }
cosOuterConeAngle() const1053     SkScalar cosOuterConeAngle() const { return fCosOuterConeAngle; }
coneScale() const1054     SkScalar coneScale() const { return fConeScale; }
s() const1055     const SkPoint3& s() const { return fS; }
1056 
SkSpotLight(SkReadBuffer & buffer)1057     SkSpotLight(SkReadBuffer& buffer) : INHERITED(buffer) {
1058         fLocation = read_point3(buffer);
1059         fTarget = read_point3(buffer);
1060         fSpecularExponent = buffer.readScalar();
1061         fCosOuterConeAngle = buffer.readScalar();
1062         fCosInnerConeAngle = buffer.readScalar();
1063         fConeScale = buffer.readScalar();
1064         fS = read_point3(buffer);
1065         buffer.validate(SkScalarIsFinite(fSpecularExponent) &&
1066                         SkScalarIsFinite(fCosOuterConeAngle) &&
1067                         SkScalarIsFinite(fCosInnerConeAngle) &&
1068                         SkScalarIsFinite(fConeScale));
1069     }
1070 protected:
SkSpotLight(const SkPoint3 & location,const SkPoint3 & target,SkScalar specularExponent,SkScalar cosOuterConeAngle,SkScalar cosInnerConeAngle,SkScalar coneScale,const SkPoint3 & s,const SkPoint3 & color)1071     SkSpotLight(const SkPoint3& location,
1072                 const SkPoint3& target,
1073                 SkScalar specularExponent,
1074                 SkScalar cosOuterConeAngle,
1075                 SkScalar cosInnerConeAngle,
1076                 SkScalar coneScale,
1077                 const SkPoint3& s,
1078                 const SkPoint3& color)
1079      : INHERITED(color),
1080        fLocation(location),
1081        fTarget(target),
1082        fSpecularExponent(specularExponent),
1083        fCosOuterConeAngle(cosOuterConeAngle),
1084        fCosInnerConeAngle(cosInnerConeAngle),
1085        fConeScale(coneScale),
1086        fS(s)
1087     {
1088     }
onFlattenLight(SkWriteBuffer & buffer) const1089     void onFlattenLight(SkWriteBuffer& buffer) const override {
1090         write_point3(fLocation, buffer);
1091         write_point3(fTarget, buffer);
1092         buffer.writeScalar(fSpecularExponent);
1093         buffer.writeScalar(fCosOuterConeAngle);
1094         buffer.writeScalar(fCosInnerConeAngle);
1095         buffer.writeScalar(fConeScale);
1096         write_point3(fS, buffer);
1097     }
1098 
isEqual(const SkImageFilterLight & other) const1099     bool isEqual(const SkImageFilterLight& other) const override {
1100         if (other.type() != kSpot_LightType) {
1101             return false;
1102         }
1103 
1104         const SkSpotLight& o = static_cast<const SkSpotLight&>(other);
1105         return INHERITED::isEqual(other) &&
1106                fLocation == o.fLocation &&
1107                fTarget == o.fTarget &&
1108                fSpecularExponent == o.fSpecularExponent &&
1109                fCosOuterConeAngle == o.fCosOuterConeAngle;
1110     }
1111 
1112 private:
1113     SkPoint3 fLocation;
1114     SkPoint3 fTarget;
1115     SkScalar fSpecularExponent;
1116     SkScalar fCosOuterConeAngle;
1117     SkScalar fCosInnerConeAngle;
1118     SkScalar fConeScale;
1119     SkPoint3 fS;
1120 
1121     using INHERITED = SkImageFilterLight;
1122 };
1123 }  // anonymous namespace
1124 
1125 ///////////////////////////////////////////////////////////////////////////////
1126 
flattenLight(SkWriteBuffer & buffer) const1127 void SkImageFilterLight::flattenLight(SkWriteBuffer& buffer) const {
1128     // Write type first, then baseclass, then subclass.
1129     buffer.writeInt(this->type());
1130     write_point3(fColor, buffer);
1131     this->onFlattenLight(buffer);
1132 }
1133 
UnflattenLight(SkReadBuffer & buffer)1134 /*static*/ SkImageFilterLight* SkImageFilterLight::UnflattenLight(SkReadBuffer& buffer) {
1135     SkImageFilterLight::LightType type = buffer.read32LE(SkImageFilterLight::kLast_LightType);
1136 
1137     switch (type) {
1138         // Each of these constructors must first call SkLight's, so we'll read the baseclass
1139         // then subclass, same order as flattenLight.
1140         case SkImageFilterLight::kDistant_LightType:
1141             return new SkDistantLight(buffer);
1142         case SkImageFilterLight::kPoint_LightType:
1143             return new SkPointLight(buffer);
1144         case SkImageFilterLight::kSpot_LightType:
1145             return new SkSpotLight(buffer);
1146         default:
1147             // Should never get here due to prior check of SkSafeRange
1148             SkDEBUGFAIL("Unknown LightType.");
1149             return nullptr;
1150     }
1151 }
1152 ///////////////////////////////////////////////////////////////////////////////
1153 
DistantLitDiffuse(const SkPoint3 & direction,SkColor lightColor,SkScalar surfaceScale,SkScalar kd,sk_sp<SkImageFilter> input,const CropRect & cropRect)1154 sk_sp<SkImageFilter> SkImageFilters::DistantLitDiffuse(
1155         const SkPoint3& direction, SkColor lightColor, SkScalar surfaceScale, SkScalar kd,
1156         sk_sp<SkImageFilter> input, const CropRect& cropRect) {
1157     sk_sp<SkImageFilterLight> light(new SkDistantLight(direction, lightColor));
1158     return SkDiffuseLightingImageFilter::Make(std::move(light), surfaceScale, kd,
1159                                               std::move(input), cropRect);
1160 }
1161 
PointLitDiffuse(const SkPoint3 & location,SkColor lightColor,SkScalar surfaceScale,SkScalar kd,sk_sp<SkImageFilter> input,const CropRect & cropRect)1162 sk_sp<SkImageFilter> SkImageFilters::PointLitDiffuse(
1163         const SkPoint3& location, SkColor lightColor, SkScalar surfaceScale, SkScalar kd,
1164         sk_sp<SkImageFilter> input, const CropRect& cropRect) {
1165     sk_sp<SkImageFilterLight> light(new SkPointLight(location, lightColor));
1166     return SkDiffuseLightingImageFilter::Make(std::move(light), surfaceScale, kd,
1167                                               std::move(input), cropRect);
1168 }
1169 
SpotLitDiffuse(const SkPoint3 & location,const SkPoint3 & target,SkScalar falloffExponent,SkScalar cutoffAngle,SkColor lightColor,SkScalar surfaceScale,SkScalar kd,sk_sp<SkImageFilter> input,const CropRect & cropRect)1170 sk_sp<SkImageFilter> SkImageFilters::SpotLitDiffuse(
1171         const SkPoint3& location, const SkPoint3& target, SkScalar falloffExponent,
1172         SkScalar cutoffAngle, SkColor lightColor, SkScalar surfaceScale, SkScalar kd,
1173         sk_sp<SkImageFilter> input, const CropRect& cropRect) {
1174     sk_sp<SkImageFilterLight> light(new SkSpotLight(location, target, falloffExponent,
1175                                                     cutoffAngle, lightColor));
1176     return SkDiffuseLightingImageFilter::Make(std::move(light), surfaceScale, kd,
1177                                               std::move(input), cropRect);
1178 }
1179 
DistantLitSpecular(const SkPoint3 & direction,SkColor lightColor,SkScalar surfaceScale,SkScalar ks,SkScalar shininess,sk_sp<SkImageFilter> input,const CropRect & cropRect)1180 sk_sp<SkImageFilter> SkImageFilters::DistantLitSpecular(
1181         const SkPoint3& direction, SkColor lightColor, SkScalar surfaceScale, SkScalar ks,
1182         SkScalar shininess, sk_sp<SkImageFilter> input, const CropRect& cropRect) {
1183     sk_sp<SkImageFilterLight> light(new SkDistantLight(direction, lightColor));
1184     return SkSpecularLightingImageFilter::Make(std::move(light), surfaceScale, ks, shininess,
1185                                                std::move(input), cropRect);
1186 }
1187 
PointLitSpecular(const SkPoint3 & location,SkColor lightColor,SkScalar surfaceScale,SkScalar ks,SkScalar shininess,sk_sp<SkImageFilter> input,const CropRect & cropRect)1188 sk_sp<SkImageFilter> SkImageFilters::PointLitSpecular(
1189         const SkPoint3& location, SkColor lightColor, SkScalar surfaceScale, SkScalar ks,
1190         SkScalar shininess, sk_sp<SkImageFilter> input, const CropRect& cropRect) {
1191     sk_sp<SkImageFilterLight> light(new SkPointLight(location, lightColor));
1192     return SkSpecularLightingImageFilter::Make(std::move(light), surfaceScale, ks, shininess,
1193                                                std::move(input), cropRect);
1194 }
1195 
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)1196 sk_sp<SkImageFilter> SkImageFilters::SpotLitSpecular(
1197         const SkPoint3& location, const SkPoint3& target, SkScalar falloffExponent,
1198         SkScalar cutoffAngle, SkColor lightColor, SkScalar surfaceScale, SkScalar ks,
1199         SkScalar shininess, sk_sp<SkImageFilter> input, const CropRect& cropRect) {
1200     sk_sp<SkImageFilterLight> light(new SkSpotLight(location, target, falloffExponent,
1201                                                     cutoffAngle, lightColor));
1202     return SkSpecularLightingImageFilter::Make(std::move(light), surfaceScale, ks, shininess,
1203                                                std::move(input), cropRect);
1204 }
1205 
SkRegisterLightingImageFilterFlattenables()1206 void SkRegisterLightingImageFilterFlattenables() {
1207     SK_REGISTER_FLATTENABLE(SkDiffuseLightingImageFilter);
1208     SK_REGISTER_FLATTENABLE(SkSpecularLightingImageFilter);
1209 }
1210 
1211 ///////////////////////////////////////////////////////////////////////////////
1212 
Make(sk_sp<SkImageFilterLight> light,SkScalar surfaceScale,SkScalar kd,sk_sp<SkImageFilter> input,const SkRect * cropRect)1213 sk_sp<SkImageFilter> SkDiffuseLightingImageFilter::Make(sk_sp<SkImageFilterLight> light,
1214                                                         SkScalar surfaceScale,
1215                                                         SkScalar kd,
1216                                                         sk_sp<SkImageFilter> input,
1217                                                         const SkRect* cropRect) {
1218     if (!light) {
1219         return nullptr;
1220     }
1221     if (!SkScalarIsFinite(surfaceScale) || !SkScalarIsFinite(kd)) {
1222         return nullptr;
1223     }
1224     // According to the spec, kd can be any non-negative number :
1225     // http://www.w3.org/TR/SVG/filters.html#feDiffuseLightingElement
1226     if (kd < 0) {
1227         return nullptr;
1228     }
1229     return sk_sp<SkImageFilter>(new SkDiffuseLightingImageFilter(std::move(light), surfaceScale,
1230                                                                  kd, std::move(input), cropRect));
1231 }
1232 
SkDiffuseLightingImageFilter(sk_sp<SkImageFilterLight> light,SkScalar surfaceScale,SkScalar kd,sk_sp<SkImageFilter> input,const SkRect * cropRect)1233 SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(sk_sp<SkImageFilterLight> light,
1234                                                            SkScalar surfaceScale,
1235                                                            SkScalar kd,
1236                                                            sk_sp<SkImageFilter> input,
1237                                                            const SkRect* cropRect)
1238     : INHERITED(std::move(light), surfaceScale, std::move(input), cropRect)
1239     , fKD(kd) {
1240 }
1241 
CreateProc(SkReadBuffer & buffer)1242 sk_sp<SkFlattenable> SkDiffuseLightingImageFilter::CreateProc(SkReadBuffer& buffer) {
1243     SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
1244 
1245     sk_sp<SkImageFilterLight> light(SkImageFilterLight::UnflattenLight(buffer));
1246     SkScalar surfaceScale = buffer.readScalar();
1247     SkScalar kd = buffer.readScalar();
1248 
1249     return Make(std::move(light), surfaceScale, kd, common.getInput(0), common.cropRect());
1250 }
1251 
flatten(SkWriteBuffer & buffer) const1252 void SkDiffuseLightingImageFilter::flatten(SkWriteBuffer& buffer) const {
1253     this->INHERITED::flatten(buffer);
1254     buffer.writeScalar(fKD);
1255 }
1256 
onFilterImage(const Context & ctx,SkIPoint * offset) const1257 sk_sp<SkSpecialImage> SkDiffuseLightingImageFilter::onFilterImage(const Context& ctx,
1258                                                                   SkIPoint* offset) const {
1259     SkIPoint inputOffset = SkIPoint::Make(0, 0);
1260     sk_sp<SkSpecialImage> input(this->filterInput(0, ctx, &inputOffset));
1261     if (!input) {
1262         return nullptr;
1263     }
1264 
1265     const SkIRect inputBounds = SkIRect::MakeXYWH(inputOffset.x(), inputOffset.y(),
1266                                                   input->width(), input->height());
1267     SkIRect bounds;
1268     if (!this->applyCropRect(ctx, inputBounds, &bounds)) {
1269         return nullptr;
1270     }
1271 
1272     offset->fX = bounds.left();
1273     offset->fY = bounds.top();
1274     bounds.offset(-inputOffset);
1275 
1276 #if SK_SUPPORT_GPU
1277     if (ctx.gpuBacked()) {
1278         SkMatrix matrix(ctx.ctm());
1279         matrix.postTranslate(SkIntToScalar(-offset->fX), SkIntToScalar(-offset->fY));
1280 
1281         return this->filterImageGPU(ctx, input.get(), bounds, matrix);
1282     }
1283 #endif
1284 
1285     if (bounds.width() < 2 || bounds.height() < 2) {
1286         return nullptr;
1287     }
1288 
1289     SkBitmap inputBM;
1290 
1291     if (!input->getROPixels(&inputBM)) {
1292         return nullptr;
1293     }
1294 
1295     if (inputBM.colorType() != kN32_SkColorType) {
1296         return nullptr;
1297     }
1298 
1299     if (!inputBM.getPixels()) {
1300         return nullptr;
1301     }
1302 
1303     const SkImageInfo info = SkImageInfo::MakeN32Premul(bounds.width(), bounds.height());
1304 
1305     SkBitmap dst;
1306     if (!dst.tryAllocPixels(info)) {
1307         return nullptr;
1308     }
1309 
1310     SkMatrix matrix(ctx.ctm());
1311     matrix.postTranslate(SkIntToScalar(-inputOffset.x()), SkIntToScalar(-inputOffset.y()));
1312 
1313     sk_sp<SkImageFilterLight> transformedLight(light()->transform(matrix));
1314 
1315     DiffuseLightingType lightingType(fKD);
1316     lightBitmap(lightingType,
1317                                                              transformedLight.get(),
1318                                                              inputBM,
1319                                                              &dst,
1320                                                              surfaceScale(),
1321                                                              bounds);
1322 
1323     return SkSpecialImage::MakeFromRaster(SkIRect::MakeWH(bounds.width(), bounds.height()),
1324                                           dst, ctx.surfaceProps());
1325 }
1326 
1327 #if SK_SUPPORT_GPU
makeFragmentProcessor(GrSurfaceProxyView view,const SkMatrix & matrix,const SkIRect * srcBounds,BoundaryMode boundaryMode,const GrCaps & caps) const1328 std::unique_ptr<GrFragmentProcessor> SkDiffuseLightingImageFilter::makeFragmentProcessor(
1329         GrSurfaceProxyView view,
1330         const SkMatrix& matrix,
1331         const SkIRect* srcBounds,
1332         BoundaryMode boundaryMode,
1333         const GrCaps& caps) const {
1334     SkScalar scale = this->surfaceScale() * 255;
1335     return DiffuseLightingEffect::Make(std::move(view),
1336                                        this->refLight(),
1337                                        scale,
1338                                        matrix,
1339                                        this->kd(),
1340                                        boundaryMode,
1341                                        srcBounds,
1342                                        caps);
1343 }
1344 #endif
1345 
1346 ///////////////////////////////////////////////////////////////////////////////
1347 
Make(sk_sp<SkImageFilterLight> light,SkScalar surfaceScale,SkScalar ks,SkScalar shininess,sk_sp<SkImageFilter> input,const SkRect * cropRect)1348 sk_sp<SkImageFilter> SkSpecularLightingImageFilter::Make(sk_sp<SkImageFilterLight> light,
1349                                                          SkScalar surfaceScale,
1350                                                          SkScalar ks,
1351                                                          SkScalar shininess,
1352                                                          sk_sp<SkImageFilter> input,
1353                                                          const SkRect* cropRect) {
1354     if (!light) {
1355         return nullptr;
1356     }
1357     if (!SkScalarIsFinite(surfaceScale) || !SkScalarIsFinite(ks) || !SkScalarIsFinite(shininess)) {
1358         return nullptr;
1359     }
1360     // According to the spec, ks can be any non-negative number :
1361     // http://www.w3.org/TR/SVG/filters.html#feSpecularLightingElement
1362     if (ks < 0) {
1363         return nullptr;
1364     }
1365     return sk_sp<SkImageFilter>(new SkSpecularLightingImageFilter(std::move(light), surfaceScale,
1366                                                                   ks, shininess,
1367                                                                   std::move(input), cropRect));
1368 }
1369 
SkSpecularLightingImageFilter(sk_sp<SkImageFilterLight> light,SkScalar surfaceScale,SkScalar ks,SkScalar shininess,sk_sp<SkImageFilter> input,const SkRect * cropRect)1370 SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(sk_sp<SkImageFilterLight> light,
1371                                                              SkScalar surfaceScale,
1372                                                              SkScalar ks,
1373                                                              SkScalar shininess,
1374                                                              sk_sp<SkImageFilter> input,
1375                                                              const SkRect* cropRect)
1376     : INHERITED(std::move(light), surfaceScale, std::move(input), cropRect)
1377     , fKS(ks)
1378     , fShininess(shininess) {
1379 }
1380 
CreateProc(SkReadBuffer & buffer)1381 sk_sp<SkFlattenable> SkSpecularLightingImageFilter::CreateProc(SkReadBuffer& buffer) {
1382     SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
1383     sk_sp<SkImageFilterLight> light(SkImageFilterLight::UnflattenLight(buffer));
1384     SkScalar surfaceScale = buffer.readScalar();
1385     SkScalar ks = buffer.readScalar();
1386     SkScalar shine = buffer.readScalar();
1387 
1388     return Make(std::move(light), surfaceScale, ks, shine, common.getInput(0),
1389                 common.cropRect());
1390 }
1391 
flatten(SkWriteBuffer & buffer) const1392 void SkSpecularLightingImageFilter::flatten(SkWriteBuffer& buffer) const {
1393     this->INHERITED::flatten(buffer);
1394     buffer.writeScalar(fKS);
1395     buffer.writeScalar(fShininess);
1396 }
1397 
onFilterImage(const Context & ctx,SkIPoint * offset) const1398 sk_sp<SkSpecialImage> SkSpecularLightingImageFilter::onFilterImage(const Context& ctx,
1399                                                                    SkIPoint* offset) const {
1400     SkIPoint inputOffset = SkIPoint::Make(0, 0);
1401     sk_sp<SkSpecialImage> input(this->filterInput(0, ctx, &inputOffset));
1402     if (!input) {
1403         return nullptr;
1404     }
1405 
1406     const SkIRect inputBounds = SkIRect::MakeXYWH(inputOffset.x(), inputOffset.y(),
1407                                                   input->width(), input->height());
1408     SkIRect bounds;
1409     if (!this->applyCropRect(ctx, inputBounds, &bounds)) {
1410         return nullptr;
1411     }
1412 
1413     offset->fX = bounds.left();
1414     offset->fY = bounds.top();
1415     bounds.offset(-inputOffset);
1416 
1417 #if SK_SUPPORT_GPU
1418     if (ctx.gpuBacked()) {
1419         SkMatrix matrix(ctx.ctm());
1420         matrix.postTranslate(SkIntToScalar(-offset->fX), SkIntToScalar(-offset->fY));
1421 
1422         return this->filterImageGPU(ctx, input.get(), bounds, matrix);
1423     }
1424 #endif
1425 
1426     if (bounds.width() < 2 || bounds.height() < 2) {
1427         return nullptr;
1428     }
1429 
1430     SkBitmap inputBM;
1431 
1432     if (!input->getROPixels(&inputBM)) {
1433         return nullptr;
1434     }
1435 
1436     if (inputBM.colorType() != kN32_SkColorType) {
1437         return nullptr;
1438     }
1439 
1440     if (!inputBM.getPixels()) {
1441         return nullptr;
1442     }
1443 
1444     const SkImageInfo info = SkImageInfo::MakeN32Premul(bounds.width(), bounds.height());
1445 
1446     SkBitmap dst;
1447     if (!dst.tryAllocPixels(info)) {
1448         return nullptr;
1449     }
1450 
1451     SpecularLightingType lightingType(fKS, fShininess);
1452 
1453     SkMatrix matrix(ctx.ctm());
1454     matrix.postTranslate(SkIntToScalar(-inputOffset.x()), SkIntToScalar(-inputOffset.y()));
1455 
1456     sk_sp<SkImageFilterLight> transformedLight(light()->transform(matrix));
1457 
1458     lightBitmap(lightingType,
1459                                                               transformedLight.get(),
1460                                                               inputBM,
1461                                                               &dst,
1462                                                               surfaceScale(),
1463                                                               bounds);
1464 
1465     return SkSpecialImage::MakeFromRaster(SkIRect::MakeWH(bounds.width(), bounds.height()), dst,
1466                                           ctx.surfaceProps());
1467 }
1468 
1469 #if SK_SUPPORT_GPU
makeFragmentProcessor(GrSurfaceProxyView view,const SkMatrix & matrix,const SkIRect * srcBounds,BoundaryMode boundaryMode,const GrCaps & caps) const1470 std::unique_ptr<GrFragmentProcessor> SkSpecularLightingImageFilter::makeFragmentProcessor(
1471         GrSurfaceProxyView view,
1472         const SkMatrix& matrix,
1473         const SkIRect* srcBounds,
1474         BoundaryMode boundaryMode,
1475         const GrCaps& caps) const {
1476     SkScalar scale = this->surfaceScale() * 255;
1477     return SpecularLightingEffect::Make(std::move(view),
1478                                         this->refLight(),
1479                                         scale,
1480                                         matrix,
1481                                         this->ks(),
1482                                         this->shininess(),
1483                                         boundaryMode,
1484                                         srcBounds,
1485                                         caps);
1486 }
1487 #endif
1488 
1489 ///////////////////////////////////////////////////////////////////////////////
1490 
1491 #if SK_SUPPORT_GPU
1492 
emitNormalFunc(BoundaryMode mode,const char * pointToNormalName,const char * sobelFuncName)1493 static SkString emitNormalFunc(BoundaryMode mode,
1494                                const char* pointToNormalName,
1495                                const char* sobelFuncName) {
1496     SkString result;
1497     switch (mode) {
1498     case kTopLeft_BoundaryMode:
1499         result.printf("return %s(%s(0.0, 0.0, m[4], m[5], m[7], m[8], %g),"
1500                       "          %s(0.0, 0.0, m[4], m[7], m[5], m[8], %g),"
1501                       "          surfaceScale);",
1502                       pointToNormalName, sobelFuncName, gTwoThirds,
1503                                          sobelFuncName, gTwoThirds);
1504         break;
1505     case kTop_BoundaryMode:
1506         result.printf("return %s(%s(0.0, 0.0, m[3], m[5], m[6], m[8], %g),"
1507                       "          %s(0.0, 0.0, m[4], m[7], m[5], m[8], %g),"
1508                       "          surfaceScale);",
1509                       pointToNormalName, sobelFuncName, gOneThird,
1510                                          sobelFuncName, gOneHalf);
1511         break;
1512     case kTopRight_BoundaryMode:
1513         result.printf("return %s(%s( 0.0,  0.0, m[3], m[4], m[6], m[7], %g),"
1514                       "          %s(m[3], m[6], m[4], m[7],  0.0,  0.0, %g),"
1515                       "          surfaceScale);",
1516                       pointToNormalName, sobelFuncName, gTwoThirds,
1517                                          sobelFuncName, gTwoThirds);
1518         break;
1519     case kLeft_BoundaryMode:
1520         result.printf("return %s(%s(m[1], m[2], m[4], m[5], m[7], m[8], %g),"
1521                       "          %s( 0.0,  0.0, m[1], m[7], m[2], m[8], %g),"
1522                       "          surfaceScale);",
1523                       pointToNormalName, sobelFuncName, gOneHalf,
1524                                          sobelFuncName, gOneThird);
1525         break;
1526     case kInterior_BoundaryMode:
1527         result.printf("return %s(%s(m[0], m[2], m[3], m[5], m[6], m[8], %g),"
1528                       "          %s(m[0], m[6], m[1], m[7], m[2], m[8], %g),"
1529                       "          surfaceScale);",
1530                       pointToNormalName, sobelFuncName, gOneQuarter,
1531                                          sobelFuncName, gOneQuarter);
1532         break;
1533     case kRight_BoundaryMode:
1534         result.printf("return %s(%s(m[0], m[1], m[3], m[4], m[6], m[7], %g),"
1535                       "          %s(m[0], m[6], m[1], m[7],  0.0,  0.0, %g),"
1536                       "          surfaceScale);",
1537                       pointToNormalName, sobelFuncName, gOneHalf,
1538                                          sobelFuncName, gOneThird);
1539         break;
1540     case kBottomLeft_BoundaryMode:
1541         result.printf("return %s(%s(m[1], m[2], m[4], m[5],  0.0,  0.0, %g),"
1542                       "          %s( 0.0,  0.0, m[1], m[4], m[2], m[5], %g),"
1543                       "          surfaceScale);",
1544                       pointToNormalName, sobelFuncName, gTwoThirds,
1545                                          sobelFuncName, gTwoThirds);
1546         break;
1547     case kBottom_BoundaryMode:
1548         result.printf("return %s(%s(m[0], m[2], m[3], m[5],  0.0,  0.0, %g),"
1549                       "          %s(m[0], m[3], m[1], m[4], m[2], m[5], %g),"
1550                       "          surfaceScale);",
1551                       pointToNormalName, sobelFuncName, gOneThird,
1552                                          sobelFuncName, gOneHalf);
1553         break;
1554     case kBottomRight_BoundaryMode:
1555         result.printf("return %s(%s(m[0], m[1], m[3], m[4],  0.0,  0.0, %g),"
1556                       "          %s(m[0], m[3], m[1], m[4],  0.0,  0.0, %g),"
1557                       "          surfaceScale);",
1558                       pointToNormalName, sobelFuncName, gTwoThirds,
1559                                          sobelFuncName, gTwoThirds);
1560         break;
1561     default:
1562         SkASSERT(false);
1563         break;
1564     }
1565     return result;
1566 }
1567 
1568 namespace {
1569 class LightingEffect::ImplBase : public ProgramImpl {
1570 public:
1571     void emitCode(EmitArgs&) override;
1572 
1573 protected:
1574     /**
1575      * Subclasses of LightingImpl must call INHERITED::onSetData();
1576      */
1577     void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
1578 
1579     virtual void emitLightFunc(const GrFragmentProcessor*,
1580                                GrGLSLUniformHandler*,
1581                                GrGLSLFPFragmentBuilder*,
1582                                SkString* funcName) = 0;
1583 
1584 private:
1585     UniformHandle             fSurfaceScaleUni;
1586     std::unique_ptr<GpuLight> fLight;
1587 };
1588 
1589 ///////////////////////////////////////////////////////////////////////////////
1590 
1591 class DiffuseLightingEffect::Impl : public ImplBase {
1592 public:
1593     void emitLightFunc(const GrFragmentProcessor*,
1594                        GrGLSLUniformHandler*,
1595                        GrGLSLFPFragmentBuilder*,
1596                        SkString* funcName) override;
1597 
1598 private:
1599     void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
1600 
1601     using INHERITED = ImplBase;
1602 
1603     UniformHandle   fKDUni;
1604 };
1605 
1606 ///////////////////////////////////////////////////////////////////////////////
1607 
1608 class SpecularLightingEffect::Impl : public ImplBase {
1609 public:
1610     void emitLightFunc(const GrFragmentProcessor*,
1611                        GrGLSLUniformHandler*,
1612                        GrGLSLFPFragmentBuilder*,
1613                        SkString* funcName) override;
1614 
1615 private:
1616     void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
1617 
1618     using INHERITED = ImplBase;
1619 
1620     UniformHandle   fKSUni;
1621     UniformHandle   fShininessUni;
1622 };
1623 }  // anonymous namespace
1624 
1625 ///////////////////////////////////////////////////////////////////////////////
1626 
LightingEffect(ClassID classID,GrSurfaceProxyView view,sk_sp<const SkImageFilterLight> light,SkScalar surfaceScale,const SkMatrix & matrix,BoundaryMode boundaryMode,const SkIRect * srcBounds,const GrCaps & caps)1627 LightingEffect::LightingEffect(ClassID classID,
1628                                GrSurfaceProxyView view,
1629                                sk_sp<const SkImageFilterLight> light,
1630                                SkScalar surfaceScale,
1631                                const SkMatrix& matrix,
1632                                BoundaryMode boundaryMode,
1633                                const SkIRect* srcBounds,
1634                                const GrCaps& caps)
1635         // Perhaps this could advertise the opaque or coverage-as-alpha optimizations?
1636         : INHERITED(classID, kNone_OptimizationFlags)
1637         , fLight(std::move(light))
1638         , fSurfaceScale(surfaceScale)
1639         , fFilterMatrix(matrix)
1640         , fBoundaryMode(boundaryMode) {
1641     static constexpr GrSamplerState kSampler(GrSamplerState::WrapMode::kClampToBorder,
1642                                              GrSamplerState::Filter::kNearest);
1643     std::unique_ptr<GrFragmentProcessor> child;
1644     if (srcBounds) {
1645         child = GrTextureEffect::MakeSubset(std::move(view), kPremul_SkAlphaType, SkMatrix::I(),
1646                                             kSampler, SkRect::Make(*srcBounds), caps);
1647     } else {
1648         child = GrTextureEffect::Make(std::move(view), kPremul_SkAlphaType, SkMatrix::I(), kSampler,
1649                                       caps);
1650     }
1651     this->registerChild(std::move(child), SkSL::SampleUsage::Explicit());
1652     this->setUsesSampleCoordsDirectly();
1653 }
1654 
LightingEffect(const LightingEffect & that)1655 LightingEffect::LightingEffect(const LightingEffect& that)
1656         : INHERITED(that)
1657         , fLight(that.fLight)
1658         , fSurfaceScale(that.fSurfaceScale)
1659         , fFilterMatrix(that.fFilterMatrix)
1660         , fBoundaryMode(that.fBoundaryMode) {}
1661 
onIsEqual(const GrFragmentProcessor & sBase) const1662 bool LightingEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
1663     const LightingEffect& s = sBase.cast<LightingEffect>();
1664     return fLight->isEqual(*s.fLight) &&
1665            fSurfaceScale == s.fSurfaceScale &&
1666            fBoundaryMode == s.fBoundaryMode;
1667 }
1668 
1669 ///////////////////////////////////////////////////////////////////////////////
1670 
DiffuseLightingEffect(GrSurfaceProxyView view,sk_sp<const SkImageFilterLight> light,SkScalar surfaceScale,const SkMatrix & matrix,SkScalar kd,BoundaryMode boundaryMode,const SkIRect * srcBounds,const GrCaps & caps)1671 DiffuseLightingEffect::DiffuseLightingEffect(GrSurfaceProxyView view,
1672                                              sk_sp<const SkImageFilterLight> light,
1673                                              SkScalar surfaceScale,
1674                                              const SkMatrix& matrix,
1675                                              SkScalar kd,
1676                                              BoundaryMode boundaryMode,
1677                                              const SkIRect* srcBounds,
1678                                              const GrCaps& caps)
1679         : INHERITED(kGrDiffuseLightingEffect_ClassID,
1680                     std::move(view),
1681                     std::move(light),
1682                     surfaceScale,
1683                     matrix,
1684                     boundaryMode,
1685                     srcBounds,
1686                     caps)
1687         , fKD(kd) {}
1688 
DiffuseLightingEffect(const DiffuseLightingEffect & that)1689 DiffuseLightingEffect::DiffuseLightingEffect(const DiffuseLightingEffect& that)
1690         : INHERITED(that), fKD(that.fKD) {}
1691 
onIsEqual(const GrFragmentProcessor & sBase) const1692 bool DiffuseLightingEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
1693     const DiffuseLightingEffect& s = sBase.cast<DiffuseLightingEffect>();
1694     return INHERITED::onIsEqual(sBase) && fKD == s.fKD;
1695 }
1696 
onMakeProgramImpl() const1697 std::unique_ptr<GrFragmentProcessor::ProgramImpl> DiffuseLightingEffect::onMakeProgramImpl() const {
1698     return std::make_unique<Impl>();
1699 }
1700 
1701 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(DiffuseLightingEffect);
1702 
1703 #if GR_TEST_UTILS
1704 
random_point3(SkRandom * random)1705 static SkPoint3 random_point3(SkRandom* random) {
1706     return SkPoint3::Make(SkScalarToFloat(random->nextSScalar1()),
1707                           SkScalarToFloat(random->nextSScalar1()),
1708                           SkScalarToFloat(random->nextSScalar1()));
1709 }
1710 
create_random_light(SkRandom * random)1711 static SkImageFilterLight* create_random_light(SkRandom* random) {
1712     int type = random->nextULessThan(3);
1713     switch (type) {
1714         case 0: {
1715             return new SkDistantLight(random_point3(random), random->nextU());
1716         }
1717         case 1: {
1718             return new SkPointLight(random_point3(random), random->nextU());
1719         }
1720         case 2: {
1721             return new SkSpotLight(random_point3(random), random_point3(random),
1722                                    random->nextUScalar1(), random->nextUScalar1(), random->nextU());
1723         }
1724         default:
1725             SK_ABORT("Unexpected value.");
1726     }
1727 }
1728 
TestCreate(GrProcessorTestData * d)1729 std::unique_ptr<GrFragmentProcessor> DiffuseLightingEffect::TestCreate(GrProcessorTestData* d) {
1730     auto [view, ct, at] = d->randomView();
1731     SkScalar surfaceScale = d->fRandom->nextSScalar1();
1732     SkScalar kd = d->fRandom->nextUScalar1();
1733     sk_sp<SkImageFilterLight> light(create_random_light(d->fRandom));
1734     SkMatrix matrix;
1735     for (int i = 0; i < 9; i++) {
1736         matrix[i] = d->fRandom->nextUScalar1();
1737     }
1738 
1739     uint32_t boundsX = d->fRandom->nextRangeU(0, view.width());
1740     uint32_t boundsY = d->fRandom->nextRangeU(0, view.height());
1741     uint32_t boundsW = d->fRandom->nextRangeU(0, view.width());
1742     uint32_t boundsH = d->fRandom->nextRangeU(0, view.height());
1743     SkIRect srcBounds = SkIRect::MakeXYWH(boundsX, boundsY, boundsW, boundsH);
1744     BoundaryMode mode = static_cast<BoundaryMode>(d->fRandom->nextU() % kBoundaryModeCount);
1745 
1746     return DiffuseLightingEffect::Make(std::move(view),
1747                                        std::move(light),
1748                                        surfaceScale,
1749                                        matrix,
1750                                        kd,
1751                                        mode,
1752                                        &srcBounds,
1753                                        *d->caps());
1754 }
1755 #endif
1756 
1757 
1758 ///////////////////////////////////////////////////////////////////////////////
1759 
emitCode(EmitArgs & args)1760 void LightingEffect::ImplBase::emitCode(EmitArgs& args) {
1761     const LightingEffect& le = args.fFp.cast<LightingEffect>();
1762     if (!fLight) {
1763         fLight = le.light()->createGpuLight();
1764     }
1765 
1766     GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
1767     fSurfaceScaleUni = uniformHandler->addUniform(&le,
1768                                                   kFragment_GrShaderFlag,
1769                                                   kHalf_GrSLType, "SurfaceScale");
1770     fLight->emitLightColorUniform(&le, uniformHandler);
1771     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
1772     SkString lightFunc;
1773     this->emitLightFunc(&le, uniformHandler, fragBuilder, &lightFunc);
1774     const GrShaderVar gSobelArgs[] = {
1775         GrShaderVar("a", kHalf_GrSLType),
1776         GrShaderVar("b", kHalf_GrSLType),
1777         GrShaderVar("c", kHalf_GrSLType),
1778         GrShaderVar("d", kHalf_GrSLType),
1779         GrShaderVar("e", kHalf_GrSLType),
1780         GrShaderVar("f", kHalf_GrSLType),
1781         GrShaderVar("scale", kHalf_GrSLType),
1782     };
1783 
1784     SkString sobelFuncName = fragBuilder->getMangledFunctionName("sobel");
1785     fragBuilder->emitFunction(kHalf_GrSLType,
1786                               sobelFuncName.c_str(),
1787                               {gSobelArgs, SK_ARRAY_COUNT(gSobelArgs)},
1788                               "return (-a + b - 2.0 * c + 2.0 * d -e + f) * scale;");
1789     const GrShaderVar gPointToNormalArgs[] = {
1790         GrShaderVar("x", kHalf_GrSLType),
1791         GrShaderVar("y", kHalf_GrSLType),
1792         GrShaderVar("scale", kHalf_GrSLType),
1793     };
1794     SkString pointToNormalName = fragBuilder->getMangledFunctionName("pointToNormal");
1795     fragBuilder->emitFunction(kHalf3_GrSLType,
1796                               pointToNormalName.c_str(),
1797                               {gPointToNormalArgs, SK_ARRAY_COUNT(gPointToNormalArgs)},
1798                               "return normalize(half3(-x * scale, -y * scale, 1));");
1799 
1800     const GrShaderVar gInteriorNormalArgs[] = {
1801         GrShaderVar("m", kHalf_GrSLType, 9),
1802         GrShaderVar("surfaceScale", kHalf_GrSLType),
1803     };
1804     SkString normalBody = emitNormalFunc(le.boundaryMode(),
1805                                          pointToNormalName.c_str(),
1806                                          sobelFuncName.c_str());
1807     SkString normalName = fragBuilder->getMangledFunctionName("normal");
1808     fragBuilder->emitFunction(kHalf3_GrSLType,
1809                               normalName.c_str(),
1810                               {gInteriorNormalArgs, SK_ARRAY_COUNT(gInteriorNormalArgs)},
1811                               normalBody.c_str());
1812 
1813     fragBuilder->codeAppendf("float2 coord = %s;", args.fSampleCoord);
1814     fragBuilder->codeAppend("half m[9];");
1815 
1816     const char* surfScale = uniformHandler->getUniformCStr(fSurfaceScaleUni);
1817 
1818     int index = 0;
1819     for (int dy = -1; dy <= 1; ++dy) {
1820         for (int dx = -1; dx <= 1; ++dx) {
1821             SkString texCoords;
1822             texCoords.appendf("coord + half2(%d, %d)", dx, dy);
1823             auto sample = this->invokeChild(0, args, texCoords.c_str());
1824             fragBuilder->codeAppendf("m[%d] = %s.a;", index, sample.c_str());
1825             index++;
1826         }
1827     }
1828     fragBuilder->codeAppend("half3 surfaceToLight = ");
1829     SkString arg;
1830     arg.appendf("%s * m[4]", surfScale);
1831     fLight->emitSurfaceToLight(&le, uniformHandler, fragBuilder, arg.c_str());
1832     fragBuilder->codeAppend(";");
1833     fragBuilder->codeAppendf("return %s(%s(m, %s), surfaceToLight, ",
1834                              lightFunc.c_str(), normalName.c_str(), surfScale);
1835     fLight->emitLightColor(&le, uniformHandler, fragBuilder, "surfaceToLight");
1836     fragBuilder->codeAppend(");");
1837 }
1838 
onSetData(const GrGLSLProgramDataManager & pdman,const GrFragmentProcessor & proc)1839 void LightingEffect::ImplBase::onSetData(const GrGLSLProgramDataManager& pdman,
1840                                          const GrFragmentProcessor& proc) {
1841     const LightingEffect& lighting = proc.cast<LightingEffect>();
1842     if (!fLight) {
1843         fLight = lighting.light()->createGpuLight();
1844     }
1845 
1846     pdman.set1f(fSurfaceScaleUni, lighting.surfaceScale());
1847     sk_sp<SkImageFilterLight> transformedLight(
1848             lighting.light()->transform(lighting.filterMatrix()));
1849     fLight->setData(pdman, transformedLight.get());
1850 }
1851 
1852 ///////////////////////////////////////////////////////////////////////////////
1853 
1854 ///////////////////////////////////////////////////////////////////////////////
1855 
emitLightFunc(const GrFragmentProcessor * owner,GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,SkString * funcName)1856 void DiffuseLightingEffect::Impl::emitLightFunc(const GrFragmentProcessor* owner,
1857                                                 GrGLSLUniformHandler* uniformHandler,
1858                                                 GrGLSLFPFragmentBuilder* fragBuilder,
1859                                                 SkString* funcName) {
1860     const char* kd;
1861     fKDUni = uniformHandler->addUniform(owner, kFragment_GrShaderFlag, kHalf_GrSLType, "KD", &kd);
1862 
1863     const GrShaderVar gLightArgs[] = {
1864         GrShaderVar("normal", kHalf3_GrSLType),
1865         GrShaderVar("surfaceToLight", kHalf3_GrSLType),
1866         GrShaderVar("lightColor", kHalf3_GrSLType)
1867     };
1868     SkString lightBody;
1869     lightBody.appendf("half colorScale = %s * dot(normal, surfaceToLight);", kd);
1870     lightBody.appendf("return half4(saturate(lightColor * colorScale), 1.0);");
1871     *funcName = fragBuilder->getMangledFunctionName("light");
1872     fragBuilder->emitFunction(kHalf4_GrSLType,
1873                               funcName->c_str(),
1874                               {gLightArgs, SK_ARRAY_COUNT(gLightArgs)},
1875                               lightBody.c_str());
1876 }
1877 
onSetData(const GrGLSLProgramDataManager & pdman,const GrFragmentProcessor & proc)1878 void DiffuseLightingEffect::Impl::onSetData(const GrGLSLProgramDataManager& pdman,
1879                                             const GrFragmentProcessor& proc) {
1880     INHERITED::onSetData(pdman, proc);
1881     const DiffuseLightingEffect& diffuse = proc.cast<DiffuseLightingEffect>();
1882     pdman.set1f(fKDUni, diffuse.fKD);
1883 }
1884 
1885 ///////////////////////////////////////////////////////////////////////////////
1886 
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)1887 SpecularLightingEffect::SpecularLightingEffect(GrSurfaceProxyView view,
1888                                                sk_sp<const SkImageFilterLight> light,
1889                                                SkScalar surfaceScale,
1890                                                const SkMatrix& matrix,
1891                                                SkScalar ks,
1892                                                SkScalar shininess,
1893                                                BoundaryMode boundaryMode,
1894                                                const SkIRect* srcBounds,
1895                                                const GrCaps& caps)
1896         : INHERITED(kGrSpecularLightingEffect_ClassID,
1897                     std::move(view),
1898                     std::move(light),
1899                     surfaceScale,
1900                     matrix,
1901                     boundaryMode,
1902                     srcBounds,
1903                     caps)
1904         , fKS(ks)
1905         , fShininess(shininess) {}
1906 
SpecularLightingEffect(const SpecularLightingEffect & that)1907 SpecularLightingEffect::SpecularLightingEffect(const SpecularLightingEffect& that)
1908         : INHERITED(that), fKS(that.fKS), fShininess(that.fShininess) {}
1909 
onIsEqual(const GrFragmentProcessor & sBase) const1910 bool SpecularLightingEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
1911     const SpecularLightingEffect& s = sBase.cast<SpecularLightingEffect>();
1912     return INHERITED::onIsEqual(sBase) && this->fKS == s.fKS && this->fShininess == s.fShininess;
1913 }
1914 
1915 std::unique_ptr<GrFragmentProcessor::ProgramImpl>
onMakeProgramImpl() const1916 SpecularLightingEffect::onMakeProgramImpl() const { return std::make_unique<Impl>(); }
1917 
1918 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(SpecularLightingEffect);
1919 
1920 #if GR_TEST_UTILS
TestCreate(GrProcessorTestData * d)1921 std::unique_ptr<GrFragmentProcessor> SpecularLightingEffect::TestCreate(GrProcessorTestData* d) {
1922     auto [view, ct, at] = d->randomView();
1923     SkScalar surfaceScale = d->fRandom->nextSScalar1();
1924     SkScalar ks = d->fRandom->nextUScalar1();
1925     SkScalar shininess = d->fRandom->nextUScalar1();
1926     sk_sp<SkImageFilterLight> light(create_random_light(d->fRandom));
1927     SkMatrix matrix;
1928     for (int i = 0; i < 9; i++) {
1929         matrix[i] = d->fRandom->nextUScalar1();
1930     }
1931     BoundaryMode mode = static_cast<BoundaryMode>(d->fRandom->nextU() % kBoundaryModeCount);
1932 
1933     uint32_t boundsX = d->fRandom->nextRangeU(0, view.width());
1934     uint32_t boundsY = d->fRandom->nextRangeU(0, view.height());
1935     uint32_t boundsW = d->fRandom->nextRangeU(0, view.width());
1936     uint32_t boundsH = d->fRandom->nextRangeU(0, view.height());
1937     SkIRect srcBounds = SkIRect::MakeXYWH(boundsX, boundsY, boundsW, boundsH);
1938 
1939     return SpecularLightingEffect::Make(std::move(view),
1940                                         std::move(light),
1941                                         surfaceScale,
1942                                         matrix,
1943                                         ks,
1944                                         shininess,
1945                                         mode,
1946                                         &srcBounds,
1947                                         *d->caps());
1948 }
1949 #endif
1950 
1951 ///////////////////////////////////////////////////////////////////////////////
1952 
emitLightFunc(const GrFragmentProcessor * owner,GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,SkString * funcName)1953 void SpecularLightingEffect::Impl::emitLightFunc(const GrFragmentProcessor* owner,
1954                                                  GrGLSLUniformHandler* uniformHandler,
1955                                                  GrGLSLFPFragmentBuilder* fragBuilder,
1956                                                  SkString* funcName) {
1957     const char* ks;
1958     const char* shininess;
1959 
1960     fKSUni = uniformHandler->addUniform(owner, kFragment_GrShaderFlag, kHalf_GrSLType, "KS", &ks);
1961     fShininessUni = uniformHandler->addUniform(owner,
1962                                                kFragment_GrShaderFlag,
1963                                                kHalf_GrSLType,
1964                                                "Shininess",
1965                                                &shininess);
1966 
1967     const GrShaderVar gLightArgs[] = {
1968         GrShaderVar("normal", kHalf3_GrSLType),
1969         GrShaderVar("surfaceToLight", kHalf3_GrSLType),
1970         GrShaderVar("lightColor", kHalf3_GrSLType)
1971     };
1972     SkString lightBody;
1973     lightBody.appendf("half3 halfDir = half3(normalize(surfaceToLight + half3(0, 0, 1)));");
1974     lightBody.appendf("half colorScale = half(%s * pow(dot(normal, halfDir), %s));",
1975                       ks, shininess);
1976     lightBody.appendf("half3 color = saturate(lightColor * colorScale);");
1977     lightBody.appendf("return half4(color, max(max(color.r, color.g), color.b));");
1978     *funcName = fragBuilder->getMangledFunctionName("light");
1979     fragBuilder->emitFunction(kHalf4_GrSLType,
1980                               funcName->c_str(),
1981                               {gLightArgs, SK_ARRAY_COUNT(gLightArgs)},
1982                               lightBody.c_str());
1983 }
1984 
onSetData(const GrGLSLProgramDataManager & pdman,const GrFragmentProcessor & effect)1985 void SpecularLightingEffect::Impl::onSetData(const GrGLSLProgramDataManager& pdman,
1986                                              const GrFragmentProcessor& effect) {
1987     INHERITED::onSetData(pdman, effect);
1988     const SpecularLightingEffect& spec = effect.cast<SpecularLightingEffect>();
1989     pdman.set1f(fKSUni, spec.fKS);
1990     pdman.set1f(fShininessUni, spec.fShininess);
1991 }
1992 
1993 ///////////////////////////////////////////////////////////////////////////////
emitLightColorUniform(const GrFragmentProcessor * owner,GrGLSLUniformHandler * uniformHandler)1994 void GpuLight::emitLightColorUniform(const GrFragmentProcessor* owner,
1995                                      GrGLSLUniformHandler* uniformHandler) {
1996     fColorUni = uniformHandler->addUniform(owner, kFragment_GrShaderFlag, kHalf3_GrSLType,
1997                                            "LightColor");
1998 }
1999 
emitLightColor(const GrFragmentProcessor * owner,GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,const char * surfaceToLight)2000 void GpuLight::emitLightColor(const GrFragmentProcessor* owner,
2001                               GrGLSLUniformHandler* uniformHandler,
2002                               GrGLSLFPFragmentBuilder* fragBuilder,
2003                               const char* surfaceToLight) {
2004     fragBuilder->codeAppend(uniformHandler->getUniformCStr(this->lightColorUni()));
2005 }
2006 
setData(const GrGLSLProgramDataManager & pdman,const SkImageFilterLight * light) const2007 void GpuLight::setData(const GrGLSLProgramDataManager& pdman,
2008                        const SkImageFilterLight* light) const {
2009     setUniformPoint3(pdman, fColorUni,
2010                      light->color().makeScale(SkScalarInvert(SkIntToScalar(255))));
2011 }
2012 
2013 ///////////////////////////////////////////////////////////////////////////////
2014 
setData(const GrGLSLProgramDataManager & pdman,const SkImageFilterLight * light) const2015 void GpuDistantLight::setData(const GrGLSLProgramDataManager& pdman,
2016                               const SkImageFilterLight* light) const {
2017     INHERITED::setData(pdman, light);
2018     SkASSERT(light->type() == SkImageFilterLight::kDistant_LightType);
2019     const SkDistantLight* distantLight = static_cast<const SkDistantLight*>(light);
2020     setUniformNormal3(pdman, fDirectionUni, distantLight->direction());
2021 }
2022 
emitSurfaceToLight(const GrFragmentProcessor * owner,GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,const char * z)2023 void GpuDistantLight::emitSurfaceToLight(const GrFragmentProcessor* owner,
2024                                          GrGLSLUniformHandler* uniformHandler,
2025                                          GrGLSLFPFragmentBuilder* fragBuilder,
2026                                          const char* z) {
2027     const char* dir;
2028     fDirectionUni = uniformHandler->addUniform(owner, kFragment_GrShaderFlag, kHalf3_GrSLType,
2029                                                "LightDirection", &dir);
2030     fragBuilder->codeAppend(dir);
2031 }
2032 
2033 ///////////////////////////////////////////////////////////////////////////////
2034 
setData(const GrGLSLProgramDataManager & pdman,const SkImageFilterLight * light) const2035 void GpuPointLight::setData(const GrGLSLProgramDataManager& pdman,
2036                             const SkImageFilterLight* light) const {
2037     INHERITED::setData(pdman, light);
2038     SkASSERT(light->type() == SkImageFilterLight::kPoint_LightType);
2039     const SkPointLight* pointLight = static_cast<const SkPointLight*>(light);
2040     setUniformPoint3(pdman, fLocationUni, pointLight->location());
2041 }
2042 
emitSurfaceToLight(const GrFragmentProcessor * owner,GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,const char * z)2043 void GpuPointLight::emitSurfaceToLight(const GrFragmentProcessor* owner,
2044                                        GrGLSLUniformHandler* uniformHandler,
2045                                        GrGLSLFPFragmentBuilder* fragBuilder,
2046                                        const char* z) {
2047     const char* loc;
2048     fLocationUni = uniformHandler->addUniform(owner, kFragment_GrShaderFlag, kHalf3_GrSLType,
2049                                               "LightLocation", &loc);
2050     fragBuilder->codeAppendf("normalize(%s - half3(sk_FragCoord.xy, %s))",
2051                              loc, z);
2052 }
2053 
2054 ///////////////////////////////////////////////////////////////////////////////
2055 
setData(const GrGLSLProgramDataManager & pdman,const SkImageFilterLight * light) const2056 void GpuSpotLight::setData(const GrGLSLProgramDataManager& pdman,
2057                            const SkImageFilterLight* light) const {
2058     INHERITED::setData(pdman, light);
2059     SkASSERT(light->type() == SkImageFilterLight::kSpot_LightType);
2060     const SkSpotLight* spotLight = static_cast<const SkSpotLight *>(light);
2061     setUniformPoint3(pdman, fLocationUni, spotLight->location());
2062     pdman.set1f(fExponentUni, spotLight->specularExponent());
2063     pdman.set1f(fCosInnerConeAngleUni, spotLight->cosInnerConeAngle());
2064     pdman.set1f(fCosOuterConeAngleUni, spotLight->cosOuterConeAngle());
2065     pdman.set1f(fConeScaleUni, spotLight->coneScale());
2066     setUniformNormal3(pdman, fSUni, spotLight->s());
2067 }
2068 
emitSurfaceToLight(const GrFragmentProcessor * owner,GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,const char * z)2069 void GpuSpotLight::emitSurfaceToLight(const GrFragmentProcessor* owner,
2070                                       GrGLSLUniformHandler* uniformHandler,
2071                                       GrGLSLFPFragmentBuilder* fragBuilder,
2072                                       const char* z) {
2073     const char* location;
2074     fLocationUni = uniformHandler->addUniform(owner, kFragment_GrShaderFlag, kHalf3_GrSLType,
2075                                               "LightLocation", &location);
2076 
2077     fragBuilder->codeAppendf("normalize(%s - half3(sk_FragCoord.xy, %s))",
2078                              location, z);
2079 }
2080 
emitLightColor(const GrFragmentProcessor * owner,GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,const char * surfaceToLight)2081 void GpuSpotLight::emitLightColor(const GrFragmentProcessor* owner,
2082                                   GrGLSLUniformHandler* uniformHandler,
2083                                   GrGLSLFPFragmentBuilder* fragBuilder,
2084                                   const char* surfaceToLight) {
2085     const char* color = uniformHandler->getUniformCStr(this->lightColorUni()); // created by parent class.
2086 
2087     const char* exponent;
2088     const char* cosInner;
2089     const char* cosOuter;
2090     const char* coneScale;
2091     const char* s;
2092     fExponentUni = uniformHandler->addUniform(owner, kFragment_GrShaderFlag, kHalf_GrSLType,
2093                                               "Exponent", &exponent);
2094     fCosInnerConeAngleUni = uniformHandler->addUniform(owner, kFragment_GrShaderFlag,
2095                                                        kHalf_GrSLType, "CosInnerConeAngle",
2096                                                        &cosInner);
2097     fCosOuterConeAngleUni = uniformHandler->addUniform(owner, kFragment_GrShaderFlag,
2098                                                        kHalf_GrSLType, "CosOuterConeAngle",
2099                                                        &cosOuter);
2100     fConeScaleUni = uniformHandler->addUniform(owner, kFragment_GrShaderFlag, kHalf_GrSLType,
2101                                                "ConeScale", &coneScale);
2102     fSUni = uniformHandler->addUniform(owner, kFragment_GrShaderFlag, kHalf3_GrSLType, "S", &s);
2103 
2104     const GrShaderVar gLightColorArgs[] = {
2105         GrShaderVar("surfaceToLight", kHalf3_GrSLType)
2106     };
2107     SkString lightColorBody;
2108     lightColorBody.appendf("half cosAngle = -dot(surfaceToLight, %s);", s);
2109     lightColorBody.appendf("if (cosAngle < %s) {", cosOuter);
2110     lightColorBody.appendf("return half3(0);");
2111     lightColorBody.appendf("}");
2112     lightColorBody.appendf("half scale = pow(cosAngle, %s);", exponent);
2113     lightColorBody.appendf("if (cosAngle < %s) {", cosInner);
2114     lightColorBody.appendf("return %s * scale * (cosAngle - %s) * %s;",
2115                            color, cosOuter, coneScale);
2116     lightColorBody.appendf("}");
2117     lightColorBody.appendf("return %s * scale;", color);
2118     fLightColorFunc = fragBuilder->getMangledFunctionName("lightColor");
2119     fragBuilder->emitFunction(kHalf3_GrSLType,
2120                               fLightColorFunc.c_str(),
2121                               {gLightColorArgs, SK_ARRAY_COUNT(gLightColorArgs)},
2122                               lightColorBody.c_str());
2123 
2124     fragBuilder->codeAppendf("%s(%s)", fLightColorFunc.c_str(), surfaceToLight);
2125 }
2126 
2127 #endif
2128