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