• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2012 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "SkLightingImageFilter.h"
9 #include "SkBitmap.h"
10 #include "SkColorData.h"
11 #include "SkColorSpaceXformer.h"
12 #include "SkImageFilterPriv.h"
13 #include "SkPoint3.h"
14 #include "SkReadBuffer.h"
15 #include "SkSpecialImage.h"
16 #include "SkTypes.h"
17 #include "SkWriteBuffer.h"
18 
19 #if SK_SUPPORT_GPU
20 #include "GrContext.h"
21 #include "GrFixedClip.h"
22 #include "GrFragmentProcessor.h"
23 #include "GrPaint.h"
24 #include "GrRenderTargetContext.h"
25 #include "GrTexture.h"
26 #include "GrTextureProxy.h"
27 
28 #include "SkGr.h"
29 #include "effects/GrTextureDomain.h"
30 #include "glsl/GrGLSLFragmentProcessor.h"
31 #include "glsl/GrGLSLFragmentShaderBuilder.h"
32 #include "glsl/GrGLSLProgramDataManager.h"
33 #include "glsl/GrGLSLUniformHandler.h"
34 
35 class GrGLDiffuseLightingEffect;
36 class GrGLSpecularLightingEffect;
37 
38 // For brevity
39 typedef GrGLSLProgramDataManager::UniformHandle UniformHandle;
40 #endif
41 
42 const SkScalar gOneThird = SkIntToScalar(1) / 3;
43 const SkScalar gTwoThirds = SkIntToScalar(2) / 3;
44 const SkScalar gOneHalf = 0.5f;
45 const SkScalar gOneQuarter = 0.25f;
46 
47 #if SK_SUPPORT_GPU
setUniformPoint3(const GrGLSLProgramDataManager & pdman,UniformHandle uni,const SkPoint3 & point)48 static void setUniformPoint3(const GrGLSLProgramDataManager& pdman, UniformHandle uni,
49                              const SkPoint3& point) {
50     GR_STATIC_ASSERT(sizeof(SkPoint3) == 3 * sizeof(float));
51     pdman.set3fv(uni, 1, &point.fX);
52 }
53 
setUniformNormal3(const GrGLSLProgramDataManager & pdman,UniformHandle uni,const SkPoint3 & point)54 static void setUniformNormal3(const GrGLSLProgramDataManager& pdman, UniformHandle uni,
55                               const SkPoint3& point) {
56     setUniformPoint3(pdman, uni, point);
57 }
58 #endif
59 
60 // Shift matrix components to the left, as we advance pixels to the right.
shiftMatrixLeft(int m[9])61 static inline void shiftMatrixLeft(int m[9]) {
62     m[0] = m[1];
63     m[3] = m[4];
64     m[6] = m[7];
65     m[1] = m[2];
66     m[4] = m[5];
67     m[7] = m[8];
68 }
69 
fast_normalize(SkPoint3 * vector)70 static inline void fast_normalize(SkPoint3* vector) {
71     // add a tiny bit so we don't have to worry about divide-by-zero
72     SkScalar magSq = vector->dot(*vector) + SK_ScalarNearlyZero;
73     SkScalar scale = sk_float_rsqrt(magSq);
74     vector->fX *= scale;
75     vector->fY *= scale;
76     vector->fZ *= scale;
77 }
78 
read_point3(SkReadBuffer & buffer)79 static SkPoint3 read_point3(SkReadBuffer& buffer) {
80     SkPoint3 point;
81     point.fX = buffer.readScalar();
82     point.fY = buffer.readScalar();
83     point.fZ = buffer.readScalar();
84     buffer.validate(SkScalarIsFinite(point.fX) &&
85                     SkScalarIsFinite(point.fY) &&
86                     SkScalarIsFinite(point.fZ));
87     return point;
88 };
89 
write_point3(const SkPoint3 & point,SkWriteBuffer & buffer)90 static void write_point3(const SkPoint3& point, SkWriteBuffer& buffer) {
91     buffer.writeScalar(point.fX);
92     buffer.writeScalar(point.fY);
93     buffer.writeScalar(point.fZ);
94 };
95 
96 class GrGLLight;
97 class SkImageFilterLight : public SkRefCnt {
98 public:
99     enum LightType {
100         kDistant_LightType,
101         kPoint_LightType,
102         kSpot_LightType,
103 
104         kLast_LightType = kSpot_LightType
105     };
106     virtual LightType type() const = 0;
color() const107     const SkPoint3& color() const { return fColor; }
108     virtual GrGLLight* createGLLight() const = 0;
isEqual(const SkImageFilterLight & other) const109     virtual bool isEqual(const SkImageFilterLight& other) const {
110         return fColor == other.fColor;
111     }
112     virtual SkImageFilterLight* transform(const SkMatrix& matrix) const = 0;
113 
114     virtual sk_sp<SkImageFilterLight> makeColorSpace(SkColorSpaceXformer*) 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 SkLightingImageFilter {
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(std::move(light), surfaceScale, std::move(input), cropRect) {
408     }
409 
410 #if SK_SUPPORT_GPU
411     sk_sp<SkSpecialImage> filterImageGPU(SkSpecialImage* source,
412                                          SkSpecialImage* input,
413                                          const SkIRect& bounds,
414                                          const SkMatrix& matrix,
415                                          const OutputProperties& outputProperties) const;
416     virtual std::unique_ptr<GrFragmentProcessor> makeFragmentProcessor(
417             sk_sp<GrTextureProxy>,
418             const SkMatrix&,
419             const SkIRect* srcBounds,
420             BoundaryMode boundaryMode) const = 0;
421 #endif
422 private:
423 #if SK_SUPPORT_GPU
424     void drawRect(GrRenderTargetContext*,
425                   sk_sp<GrTextureProxy> srcProxy,
426                   const SkMatrix& matrix,
427                   const GrClip& clip,
428                   const SkRect& dstRect,
429                   BoundaryMode boundaryMode,
430                   const SkIRect* srcBounds,
431                   const SkIRect& bounds) const;
432 #endif
433     typedef SkLightingImageFilter INHERITED;
434 };
435 
436 #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) const437 void SkLightingImageFilterInternal::drawRect(GrRenderTargetContext* renderTargetContext,
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     SkRect srcRect = dstRect.makeOffset(SkIntToScalar(bounds.x()), SkIntToScalar(bounds.y()));
446     GrPaint paint;
447     auto fp = this->makeFragmentProcessor(std::move(srcProxy), matrix, srcBounds, boundaryMode);
448     paint.addColorFragmentProcessor(std::move(fp));
449     paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
450     renderTargetContext->fillRectToRect(clip, std::move(paint), GrAA::kNo, SkMatrix::I(), dstRect,
451                                         srcRect);
452 }
453 
filterImageGPU(SkSpecialImage * source,SkSpecialImage * input,const SkIRect & offsetBounds,const SkMatrix & matrix,const OutputProperties & outputProperties) const454 sk_sp<SkSpecialImage> SkLightingImageFilterInternal::filterImageGPU(
455                                                    SkSpecialImage* source,
456                                                    SkSpecialImage* input,
457                                                    const SkIRect& offsetBounds,
458                                                    const SkMatrix& matrix,
459                                                    const OutputProperties& outputProperties) const {
460     SkASSERT(source->isTextureBacked());
461 
462     GrContext* context = source->getContext();
463 
464     sk_sp<GrTextureProxy> inputProxy(input->asTextureProxyRef(context));
465     SkASSERT(inputProxy);
466 
467     SkColorType colorType = outputProperties.colorType();
468     GrBackendFormat format =
469             context->contextPriv().caps()->getBackendFormatFromColorType(colorType);
470 
471     sk_sp<GrRenderTargetContext> renderTargetContext(
472         context->contextPriv().makeDeferredRenderTargetContext(
473                                 format, SkBackingFit::kApprox, offsetBounds.width(),
474                                 offsetBounds.height(), SkColorType2GrPixelConfig(colorType),
475                                 sk_ref_sp(outputProperties.colorSpace())));
476     if (!renderTargetContext) {
477         return nullptr;
478     }
479 
480     SkIRect dstIRect = SkIRect::MakeWH(offsetBounds.width(), offsetBounds.height());
481     SkRect dstRect = SkRect::Make(dstIRect);
482 
483     // setup new clip
484     GrFixedClip clip(dstIRect);
485 
486     const SkIRect inputBounds = SkIRect::MakeWH(input->width(), input->height());
487     SkRect topLeft = SkRect::MakeXYWH(0, 0, 1, 1);
488     SkRect top = SkRect::MakeXYWH(1, 0, dstRect.width() - 2, 1);
489     SkRect topRight = SkRect::MakeXYWH(dstRect.width() - 1, 0, 1, 1);
490     SkRect left = SkRect::MakeXYWH(0, 1, 1, dstRect.height() - 2);
491     SkRect interior = dstRect.makeInset(1, 1);
492     SkRect right = SkRect::MakeXYWH(dstRect.width() - 1, 1, 1, dstRect.height() - 2);
493     SkRect bottomLeft = SkRect::MakeXYWH(0, dstRect.height() - 1, 1, 1);
494     SkRect bottom = SkRect::MakeXYWH(1, dstRect.height() - 1, dstRect.width() - 2, 1);
495     SkRect bottomRight = SkRect::MakeXYWH(dstRect.width() - 1, dstRect.height() - 1, 1, 1);
496 
497     const SkIRect* pSrcBounds = inputBounds.contains(offsetBounds) ? nullptr : &inputBounds;
498     this->drawRect(renderTargetContext.get(), inputProxy, matrix, clip, topLeft,
499                    kTopLeft_BoundaryMode, pSrcBounds, offsetBounds);
500     this->drawRect(renderTargetContext.get(), inputProxy, matrix, clip, top,
501                    kTop_BoundaryMode, pSrcBounds, offsetBounds);
502     this->drawRect(renderTargetContext.get(), inputProxy, matrix, clip, topRight,
503                    kTopRight_BoundaryMode, pSrcBounds, offsetBounds);
504     this->drawRect(renderTargetContext.get(), inputProxy, matrix, clip, left,
505                    kLeft_BoundaryMode, pSrcBounds, offsetBounds);
506     this->drawRect(renderTargetContext.get(), inputProxy, matrix, clip, interior,
507                    kInterior_BoundaryMode, pSrcBounds, offsetBounds);
508     this->drawRect(renderTargetContext.get(), inputProxy, matrix, clip, right,
509                    kRight_BoundaryMode, pSrcBounds, offsetBounds);
510     this->drawRect(renderTargetContext.get(), inputProxy, matrix, clip, bottomLeft,
511                    kBottomLeft_BoundaryMode, pSrcBounds, offsetBounds);
512     this->drawRect(renderTargetContext.get(), inputProxy, matrix, clip, bottom,
513                    kBottom_BoundaryMode, pSrcBounds, offsetBounds);
514     this->drawRect(renderTargetContext.get(), inputProxy, matrix, clip, bottomRight,
515                    kBottomRight_BoundaryMode, pSrcBounds, offsetBounds);
516 
517     return SkSpecialImage::MakeDeferredFromGpu(
518             context,
519             SkIRect::MakeWH(offsetBounds.width(), offsetBounds.height()),
520             kNeedNewImageUniqueID_SpecialImage,
521             renderTargetContext->asTextureProxyRef(),
522             renderTargetContext->colorSpaceInfo().refColorSpace());
523 }
524 #endif
525 
526 class SkDiffuseLightingImageFilter : public SkLightingImageFilterInternal {
527 public:
528     static sk_sp<SkImageFilter> Make(sk_sp<SkImageFilterLight> light,
529                                      SkScalar surfaceScale,
530                                      SkScalar kd,
531                                      sk_sp<SkImageFilter>,
532                                      const CropRect*);
533 
kd() const534     SkScalar kd() const { return fKD; }
535 
536 protected:
537     SkDiffuseLightingImageFilter(sk_sp<SkImageFilterLight> light, SkScalar surfaceScale,
538                                  SkScalar kd,
539                                  sk_sp<SkImageFilter> input, const CropRect* cropRect);
540     void flatten(SkWriteBuffer& buffer) const override;
541 
542     sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
543                                         SkIPoint* offset) const override;
544     sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;
545 
546 #if SK_SUPPORT_GPU
547     std::unique_ptr<GrFragmentProcessor> makeFragmentProcessor(sk_sp<GrTextureProxy>,
548                                                                const SkMatrix&,
549                                                                const SkIRect* bounds,
550                                                                BoundaryMode) const override;
551 #endif
552 
553 private:
554     SK_FLATTENABLE_HOOKS(SkDiffuseLightingImageFilter)
555     friend class SkLightingImageFilter;
556     SkScalar fKD;
557 
558     typedef SkLightingImageFilterInternal INHERITED;
559 };
560 
561 class SkSpecularLightingImageFilter : public SkLightingImageFilterInternal {
562 public:
563     static sk_sp<SkImageFilter> Make(sk_sp<SkImageFilterLight> light,
564                                      SkScalar surfaceScale,
565                                      SkScalar ks, SkScalar shininess,
566                                      sk_sp<SkImageFilter>, const CropRect*);
567 
ks() const568     SkScalar ks() const { return fKS; }
shininess() const569     SkScalar shininess() const { return fShininess; }
570 
571 protected:
572     SkSpecularLightingImageFilter(sk_sp<SkImageFilterLight> light,
573                                   SkScalar surfaceScale, SkScalar ks,
574                                   SkScalar shininess,
575                                   sk_sp<SkImageFilter> input, const CropRect*);
576     void flatten(SkWriteBuffer& buffer) const override;
577 
578     sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
579                                         SkIPoint* offset) const override;
580     sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;
581 
582 #if SK_SUPPORT_GPU
583     std::unique_ptr<GrFragmentProcessor> makeFragmentProcessor(sk_sp<GrTextureProxy>,
584                                                                const SkMatrix&,
585                                                                const SkIRect* bounds,
586                                                                BoundaryMode) const override;
587 #endif
588 
589 private:
590     SK_FLATTENABLE_HOOKS(SkSpecularLightingImageFilter)
591 
592     SkScalar fKS;
593     SkScalar fShininess;
594     friend class SkLightingImageFilter;
595     typedef SkLightingImageFilterInternal INHERITED;
596 };
597 
598 #if SK_SUPPORT_GPU
599 
600 class GrLightingEffect : public GrFragmentProcessor {
601 public:
light() const602     const SkImageFilterLight* light() const { return fLight.get(); }
surfaceScale() const603     SkScalar surfaceScale() const { return fSurfaceScale; }
filterMatrix() const604     const SkMatrix& filterMatrix() const { return fFilterMatrix; }
boundaryMode() const605     BoundaryMode boundaryMode() const { return fBoundaryMode; }
domain() const606     const GrTextureDomain& domain() const { return fDomain; }
607 
608 protected:
609     GrLightingEffect(ClassID classID, sk_sp<GrTextureProxy>, sk_sp<const SkImageFilterLight> light,
610                      SkScalar surfaceScale, const SkMatrix& matrix, BoundaryMode boundaryMode,
611                      const SkIRect* srcBounds);
612 
613     GrLightingEffect(const GrLightingEffect& that);
614 
615     bool onIsEqual(const GrFragmentProcessor&) const override;
616 
617 private:
onTextureSampler(int) const618     const TextureSampler& onTextureSampler(int) const override { return fTextureSampler; }
619 
620     GrCoordTransform fCoordTransform;
621     GrTextureDomain fDomain;
622     TextureSampler fTextureSampler;
623     sk_sp<const SkImageFilterLight> fLight;
624     SkScalar fSurfaceScale;
625     SkMatrix fFilterMatrix;
626     BoundaryMode fBoundaryMode;
627 
628     typedef GrFragmentProcessor INHERITED;
629 };
630 
631 class GrDiffuseLightingEffect : public GrLightingEffect {
632 public:
Make(sk_sp<GrTextureProxy> proxy,sk_sp<const SkImageFilterLight> light,SkScalar surfaceScale,const SkMatrix & matrix,SkScalar kd,BoundaryMode boundaryMode,const SkIRect * srcBounds)633     static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy,
634                                                      sk_sp<const SkImageFilterLight> light,
635                                                      SkScalar surfaceScale,
636                                                      const SkMatrix& matrix,
637                                                      SkScalar kd,
638                                                      BoundaryMode boundaryMode,
639                                                      const SkIRect* srcBounds) {
640         return std::unique_ptr<GrFragmentProcessor>(
641                 new GrDiffuseLightingEffect(std::move(proxy), std::move(light), surfaceScale,
642                                             matrix, kd, boundaryMode, srcBounds));
643     }
644 
name() const645     const char* name() const override { return "DiffuseLighting"; }
646 
clone() const647     std::unique_ptr<GrFragmentProcessor> clone() const override {
648         return std::unique_ptr<GrFragmentProcessor>(new GrDiffuseLightingEffect(*this));
649     }
650 
kd() const651     SkScalar kd() const { return fKD; }
652 
653 private:
654     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
655 
656     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
657 
658     bool onIsEqual(const GrFragmentProcessor&) const override;
659 
660     GrDiffuseLightingEffect(sk_sp<GrTextureProxy>,
661                             sk_sp<const SkImageFilterLight> light,
662                             SkScalar surfaceScale,
663                             const SkMatrix& matrix,
664                             SkScalar kd,
665                             BoundaryMode boundaryMode,
666                             const SkIRect* srcBounds);
667 
668     explicit GrDiffuseLightingEffect(const GrDiffuseLightingEffect& that);
669 
670     GR_DECLARE_FRAGMENT_PROCESSOR_TEST
671     SkScalar fKD;
672 
673     typedef GrLightingEffect INHERITED;
674 };
675 
676 class GrSpecularLightingEffect : public GrLightingEffect {
677 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)678     static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy,
679                                                      sk_sp<const SkImageFilterLight> light,
680                                                      SkScalar surfaceScale,
681                                                      const SkMatrix& matrix,
682                                                      SkScalar ks,
683                                                      SkScalar shininess,
684                                                      BoundaryMode boundaryMode,
685                                                      const SkIRect* srcBounds) {
686         return std::unique_ptr<GrFragmentProcessor>(
687                 new GrSpecularLightingEffect(std::move(proxy), std::move(light), surfaceScale,
688                                              matrix, ks, shininess, boundaryMode, srcBounds));
689     }
690 
name() const691     const char* name() const override { return "SpecularLighting"; }
692 
clone() const693     std::unique_ptr<GrFragmentProcessor> clone() const override {
694         return std::unique_ptr<GrFragmentProcessor>(new GrSpecularLightingEffect(*this));
695     }
696 
697     GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
698 
ks() const699     SkScalar ks() const { return fKS; }
shininess() const700     SkScalar shininess() const { return fShininess; }
701 
702 private:
703     void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
704 
705     bool onIsEqual(const GrFragmentProcessor&) const override;
706 
707     GrSpecularLightingEffect(sk_sp<GrTextureProxy>,
708                              sk_sp<const SkImageFilterLight> light,
709                              SkScalar surfaceScale,
710                              const SkMatrix& matrix,
711                              SkScalar ks,
712                              SkScalar shininess,
713                              BoundaryMode boundaryMode,
714                              const SkIRect* srcBounds);
715 
716     explicit GrSpecularLightingEffect(const GrSpecularLightingEffect&);
717 
718     GR_DECLARE_FRAGMENT_PROCESSOR_TEST
719     SkScalar fKS;
720     SkScalar fShininess;
721 
722     typedef GrLightingEffect INHERITED;
723 };
724 
725 ///////////////////////////////////////////////////////////////////////////////
726 
727 class GrGLLight {
728 public:
~GrGLLight()729     virtual ~GrGLLight() {}
730 
731     /**
732      * This is called by GrGLLightingEffect::emitCode() before either of the two virtual functions
733      * below. It adds a half3 uniform visible in the FS that represents the constant light color.
734      */
735     void emitLightColorUniform(GrGLSLUniformHandler*);
736 
737     /**
738      * These two functions are called from GrGLLightingEffect's emitCode() function.
739      * emitSurfaceToLight places an expression in param out that is the vector from the surface to
740      * the light. The expression will be used in the FS. emitLightColor writes an expression into
741      * the FS that is the color of the light. Either function may add functions and/or uniforms to
742      * the FS. The default of emitLightColor appends the name of the constant light color uniform
743      * and so this function only needs to be overridden if the light color varies spatially.
744      */
745     virtual void emitSurfaceToLight(GrGLSLUniformHandler*,
746                                     GrGLSLFPFragmentBuilder*,
747                                     const char* z) = 0;
748     virtual void emitLightColor(GrGLSLUniformHandler*,
749                                 GrGLSLFPFragmentBuilder*,
750                                 const char *surfaceToLight);
751 
752     // This is called from GrGLLightingEffect's setData(). Subclasses of GrGLLight must call
753     // INHERITED::setData().
754     virtual void setData(const GrGLSLProgramDataManager&, const SkImageFilterLight* light) const;
755 
756 protected:
757     /**
758      * Gets the constant light color uniform. Subclasses can use this in their emitLightColor
759      * function.
760      */
lightColorUni() const761     UniformHandle lightColorUni() const { return fColorUni; }
762 
763 private:
764     UniformHandle fColorUni;
765 
766     typedef SkRefCnt INHERITED;
767 };
768 
769 ///////////////////////////////////////////////////////////////////////////////
770 
771 class GrGLDistantLight : public GrGLLight {
772 public:
~GrGLDistantLight()773     ~GrGLDistantLight() override {}
774     void setData(const GrGLSLProgramDataManager&, const SkImageFilterLight* light) const override;
775     void emitSurfaceToLight(GrGLSLUniformHandler*, GrGLSLFPFragmentBuilder*, const char* z) override;
776 
777 private:
778     typedef GrGLLight INHERITED;
779     UniformHandle fDirectionUni;
780 };
781 
782 ///////////////////////////////////////////////////////////////////////////////
783 
784 class GrGLPointLight : public GrGLLight {
785 public:
~GrGLPointLight()786     ~GrGLPointLight() override {}
787     void setData(const GrGLSLProgramDataManager&, const SkImageFilterLight* light) const override;
788     void emitSurfaceToLight(GrGLSLUniformHandler*, GrGLSLFPFragmentBuilder*, const char* z) override;
789 
790 private:
791     typedef GrGLLight INHERITED;
792     UniformHandle fLocationUni;
793 };
794 
795 ///////////////////////////////////////////////////////////////////////////////
796 
797 class GrGLSpotLight : public GrGLLight {
798 public:
~GrGLSpotLight()799     ~GrGLSpotLight() override {}
800     void setData(const GrGLSLProgramDataManager&, const SkImageFilterLight* light) const override;
801     void emitSurfaceToLight(GrGLSLUniformHandler*, GrGLSLFPFragmentBuilder*, const char* z) override;
802     void emitLightColor(GrGLSLUniformHandler*,
803                         GrGLSLFPFragmentBuilder*,
804                         const char *surfaceToLight) override;
805 
806 private:
807     typedef GrGLLight INHERITED;
808 
809     SkString        fLightColorFunc;
810     UniformHandle   fLocationUni;
811     UniformHandle   fExponentUni;
812     UniformHandle   fCosOuterConeAngleUni;
813     UniformHandle   fCosInnerConeAngleUni;
814     UniformHandle   fConeScaleUni;
815     UniformHandle   fSUni;
816 };
817 #else
818 
819 class GrGLLight;
820 
821 #endif
822 
823 ///////////////////////////////////////////////////////////////////////////////
824 
825 ///////////////////////////////////////////////////////////////////////////////
826 
xform_color(const SkPoint3 & color,SkColorSpaceXformer * xformer)827 static SkColor xform_color(const SkPoint3& color, SkColorSpaceXformer* xformer) {
828     SkColor origColor = SkColorSetRGB(SkScalarRoundToInt(color.fX),
829                                       SkScalarRoundToInt(color.fY),
830                                       SkScalarRoundToInt(color.fZ));
831     return xformer->apply(origColor);
832 }
833 
834 class SkDistantLight : public SkImageFilterLight {
835 public:
SkDistantLight(const SkPoint3 & direction,SkColor color)836     SkDistantLight(const SkPoint3& direction, SkColor color)
837       : INHERITED(color), fDirection(direction) {
838     }
839 
surfaceToLight(int x,int y,int z,SkScalar surfaceScale) const840     SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const override {
841         return fDirection;
842     }
lightColor(const SkPoint3 &) const843     SkPoint3 lightColor(const SkPoint3&) const override { return this->color(); }
type() const844     LightType type() const override { return kDistant_LightType; }
direction() const845     const SkPoint3& direction() const { return fDirection; }
createGLLight() const846     GrGLLight* createGLLight() const override {
847 #if SK_SUPPORT_GPU
848         return new GrGLDistantLight;
849 #else
850         SkDEBUGFAIL("Should not call in GPU-less build");
851         return nullptr;
852 #endif
853     }
854 
makeColorSpace(SkColorSpaceXformer * xformer) const855     sk_sp<SkImageFilterLight> makeColorSpace(SkColorSpaceXformer* xformer) const override {
856         return sk_make_sp<SkDistantLight>(fDirection, xform_color(this->color(), xformer));
857     }
858 
isEqual(const SkImageFilterLight & other) const859     bool isEqual(const SkImageFilterLight& other) const override {
860         if (other.type() != kDistant_LightType) {
861             return false;
862         }
863 
864         const SkDistantLight& o = static_cast<const SkDistantLight&>(other);
865         return INHERITED::isEqual(other) &&
866                fDirection == o.fDirection;
867     }
868 
SkDistantLight(SkReadBuffer & buffer)869     SkDistantLight(SkReadBuffer& buffer) : INHERITED(buffer) {
870         fDirection = read_point3(buffer);
871     }
872 
873 protected:
SkDistantLight(const SkPoint3 & direction,const SkPoint3 & color)874     SkDistantLight(const SkPoint3& direction, const SkPoint3& color)
875       : INHERITED(color), fDirection(direction) {
876     }
transform(const SkMatrix & matrix) const877     SkImageFilterLight* transform(const SkMatrix& matrix) const override {
878         return new SkDistantLight(direction(), color());
879     }
onFlattenLight(SkWriteBuffer & buffer) const880     void onFlattenLight(SkWriteBuffer& buffer) const override {
881         write_point3(fDirection, buffer);
882     }
883 
884 private:
885     SkPoint3 fDirection;
886 
887     typedef SkImageFilterLight INHERITED;
888 };
889 
890 ///////////////////////////////////////////////////////////////////////////////
891 
892 class SkPointLight : public SkImageFilterLight {
893 public:
SkPointLight(const SkPoint3 & location,SkColor color)894     SkPointLight(const SkPoint3& location, SkColor color)
895      : INHERITED(color), fLocation(location) {}
896 
surfaceToLight(int x,int y,int z,SkScalar surfaceScale) const897     SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const override {
898         SkPoint3 direction = SkPoint3::Make(fLocation.fX - SkIntToScalar(x),
899                                             fLocation.fY - SkIntToScalar(y),
900                                             fLocation.fZ - SkIntToScalar(z) * surfaceScale);
901         fast_normalize(&direction);
902         return direction;
903     }
lightColor(const SkPoint3 &) const904     SkPoint3 lightColor(const SkPoint3&) const override { return this->color(); }
type() const905     LightType type() const override { return kPoint_LightType; }
location() const906     const SkPoint3& location() const { return fLocation; }
createGLLight() const907     GrGLLight* createGLLight() const override {
908 #if SK_SUPPORT_GPU
909         return new GrGLPointLight;
910 #else
911         SkDEBUGFAIL("Should not call in GPU-less build");
912         return nullptr;
913 #endif
914     }
915 
makeColorSpace(SkColorSpaceXformer * xformer) const916     sk_sp<SkImageFilterLight> makeColorSpace(SkColorSpaceXformer* xformer) const override {
917         return sk_make_sp<SkPointLight>(fLocation, xform_color(this->color(), xformer));
918     }
919 
isEqual(const SkImageFilterLight & other) const920     bool isEqual(const SkImageFilterLight& other) const override {
921         if (other.type() != kPoint_LightType) {
922             return false;
923         }
924         const SkPointLight& o = static_cast<const SkPointLight&>(other);
925         return INHERITED::isEqual(other) &&
926                fLocation == o.fLocation;
927     }
transform(const SkMatrix & matrix) const928     SkImageFilterLight* transform(const SkMatrix& matrix) const override {
929         SkPoint location2 = SkPoint::Make(fLocation.fX, fLocation.fY);
930         matrix.mapPoints(&location2, 1);
931         // Use X scale and Y scale on Z and average the result
932         SkPoint locationZ = SkPoint::Make(fLocation.fZ, fLocation.fZ);
933         matrix.mapVectors(&locationZ, 1);
934         SkPoint3 location = SkPoint3::Make(location2.fX,
935                                            location2.fY,
936                                            SkScalarAve(locationZ.fX, locationZ.fY));
937         return new SkPointLight(location, color());
938     }
939 
SkPointLight(SkReadBuffer & buffer)940     SkPointLight(SkReadBuffer& buffer) : INHERITED(buffer) {
941         fLocation = read_point3(buffer);
942     }
943 
944 protected:
SkPointLight(const SkPoint3 & location,const SkPoint3 & color)945     SkPointLight(const SkPoint3& location, const SkPoint3& color)
946      : INHERITED(color), fLocation(location) {}
onFlattenLight(SkWriteBuffer & buffer) const947     void onFlattenLight(SkWriteBuffer& buffer) const override {
948         write_point3(fLocation, buffer);
949     }
950 
951 private:
952     SkPoint3 fLocation;
953 
954     typedef SkImageFilterLight INHERITED;
955 };
956 
957 ///////////////////////////////////////////////////////////////////////////////
958 
959 class SkSpotLight : public SkImageFilterLight {
960 public:
SkSpotLight(const SkPoint3 & location,const SkPoint3 & target,SkScalar specularExponent,SkScalar cutoffAngle,SkColor color)961     SkSpotLight(const SkPoint3& location,
962                 const SkPoint3& target,
963                 SkScalar specularExponent,
964                 SkScalar cutoffAngle,
965                 SkColor color)
966      : INHERITED(color),
967        fLocation(location),
968        fTarget(target),
969        fSpecularExponent(SkScalarPin(specularExponent, kSpecularExponentMin, kSpecularExponentMax)),
970        fCutoffAngle(cutoffAngle)
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 
makeColorSpace(SkColorSpaceXformer * xformer) const980     sk_sp<SkImageFilterLight> makeColorSpace(SkColorSpaceXformer* xformer) const override {
981         return sk_make_sp<SkSpotLight>(fLocation, fTarget, fSpecularExponent, fCutoffAngle,
982                                        xform_color(this->color(), xformer));
983     }
984 
transform(const SkMatrix & matrix) const985     SkImageFilterLight* transform(const SkMatrix& matrix) const override {
986         SkPoint location2 = SkPoint::Make(fLocation.fX, fLocation.fY);
987         matrix.mapPoints(&location2, 1);
988         // Use X scale and Y scale on Z and average the result
989         SkPoint locationZ = SkPoint::Make(fLocation.fZ, fLocation.fZ);
990         matrix.mapVectors(&locationZ, 1);
991         SkPoint3 location = SkPoint3::Make(location2.fX, location2.fY,
992                                            SkScalarAve(locationZ.fX, locationZ.fY));
993         SkPoint target2 = SkPoint::Make(fTarget.fX, fTarget.fY);
994         matrix.mapPoints(&target2, 1);
995         SkPoint targetZ = SkPoint::Make(fTarget.fZ, fTarget.fZ);
996         matrix.mapVectors(&targetZ, 1);
997         SkPoint3 target = SkPoint3::Make(target2.fX, target2.fY,
998                                          SkScalarAve(targetZ.fX, targetZ.fY));
999         SkPoint3 s = target - location;
1000         fast_normalize(&s);
1001         return new SkSpotLight(location,
1002                                target,
1003                                fSpecularExponent,
1004                                fCosOuterConeAngle,
1005                                fCosInnerConeAngle,
1006                                fConeScale,
1007                                s,
1008                                color());
1009     }
1010 
surfaceToLight(int x,int y,int z,SkScalar surfaceScale) const1011     SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const override {
1012         SkPoint3 direction = SkPoint3::Make(fLocation.fX - SkIntToScalar(x),
1013                                             fLocation.fY - SkIntToScalar(y),
1014                                             fLocation.fZ - SkIntToScalar(z) * surfaceScale);
1015         fast_normalize(&direction);
1016         return direction;
1017     }
lightColor(const SkPoint3 & surfaceToLight) const1018     SkPoint3 lightColor(const SkPoint3& surfaceToLight) const override {
1019         SkScalar cosAngle = -surfaceToLight.dot(fS);
1020         SkScalar scale = 0;
1021         if (cosAngle >= fCosOuterConeAngle) {
1022             scale = SkScalarPow(cosAngle, fSpecularExponent);
1023             if (cosAngle < fCosInnerConeAngle) {
1024                 scale *= (cosAngle - fCosOuterConeAngle) * fConeScale;
1025             }
1026         }
1027         return this->color().makeScale(scale);
1028     }
createGLLight() const1029     GrGLLight* createGLLight() const override {
1030 #if SK_SUPPORT_GPU
1031         return new GrGLSpotLight;
1032 #else
1033         SkDEBUGFAIL("Should not call in GPU-less build");
1034         return nullptr;
1035 #endif
1036     }
type() const1037     LightType type() const override { return kSpot_LightType; }
location() const1038     const SkPoint3& location() const { return fLocation; }
target() const1039     const SkPoint3& target() const { return fTarget; }
specularExponent() const1040     SkScalar specularExponent() const { return fSpecularExponent; }
cosInnerConeAngle() const1041     SkScalar cosInnerConeAngle() const { return fCosInnerConeAngle; }
cosOuterConeAngle() const1042     SkScalar cosOuterConeAngle() const { return fCosOuterConeAngle; }
coneScale() const1043     SkScalar coneScale() const { return fConeScale; }
s() const1044     const SkPoint3& s() const { return fS; }
1045 
SkSpotLight(SkReadBuffer & buffer)1046     SkSpotLight(SkReadBuffer& buffer) : INHERITED(buffer) {
1047         fLocation = read_point3(buffer);
1048         fTarget = read_point3(buffer);
1049         fSpecularExponent = buffer.readScalar();
1050         fCosOuterConeAngle = buffer.readScalar();
1051         fCosInnerConeAngle = buffer.readScalar();
1052         fConeScale = buffer.readScalar();
1053         fS = read_point3(buffer);
1054         buffer.validate(SkScalarIsFinite(fSpecularExponent) &&
1055                         SkScalarIsFinite(fCosOuterConeAngle) &&
1056                         SkScalarIsFinite(fCosInnerConeAngle) &&
1057                         SkScalarIsFinite(fConeScale));
1058     }
1059 protected:
SkSpotLight(const SkPoint3 & location,const SkPoint3 & target,SkScalar specularExponent,SkScalar cosOuterConeAngle,SkScalar cosInnerConeAngle,SkScalar coneScale,const SkPoint3 & s,const SkPoint3 & color)1060     SkSpotLight(const SkPoint3& location,
1061                 const SkPoint3& target,
1062                 SkScalar specularExponent,
1063                 SkScalar cosOuterConeAngle,
1064                 SkScalar cosInnerConeAngle,
1065                 SkScalar coneScale,
1066                 const SkPoint3& s,
1067                 const SkPoint3& color)
1068      : INHERITED(color),
1069        fLocation(location),
1070        fTarget(target),
1071        fSpecularExponent(specularExponent),
1072        fCosOuterConeAngle(cosOuterConeAngle),
1073        fCosInnerConeAngle(cosInnerConeAngle),
1074        fConeScale(coneScale),
1075        fS(s)
1076     {
1077     }
onFlattenLight(SkWriteBuffer & buffer) const1078     void onFlattenLight(SkWriteBuffer& buffer) const override {
1079         write_point3(fLocation, buffer);
1080         write_point3(fTarget, buffer);
1081         buffer.writeScalar(fSpecularExponent);
1082         buffer.writeScalar(fCosOuterConeAngle);
1083         buffer.writeScalar(fCosInnerConeAngle);
1084         buffer.writeScalar(fConeScale);
1085         write_point3(fS, buffer);
1086     }
1087 
isEqual(const SkImageFilterLight & other) const1088     bool isEqual(const SkImageFilterLight& other) const override {
1089         if (other.type() != kSpot_LightType) {
1090             return false;
1091         }
1092 
1093         const SkSpotLight& o = static_cast<const SkSpotLight&>(other);
1094         return INHERITED::isEqual(other) &&
1095                fLocation == o.fLocation &&
1096                fTarget == o.fTarget &&
1097                fSpecularExponent == o.fSpecularExponent &&
1098                fCosOuterConeAngle == o.fCosOuterConeAngle;
1099     }
1100 
1101 private:
1102     static const SkScalar kSpecularExponentMin;
1103     static const SkScalar kSpecularExponentMax;
1104 
1105     SkPoint3 fLocation;
1106     SkPoint3 fTarget;
1107     SkScalar fSpecularExponent;
1108     SkScalar fCutoffAngle;
1109     SkScalar fCosOuterConeAngle;
1110     SkScalar fCosInnerConeAngle;
1111     SkScalar fConeScale;
1112     SkPoint3 fS;
1113 
1114     typedef SkImageFilterLight INHERITED;
1115 };
1116 
1117 // According to the spec, the specular term should be in the range [1, 128] :
1118 // http://www.w3.org/TR/SVG/filters.html#feSpecularLightingSpecularExponentAttribute
1119 const SkScalar SkSpotLight::kSpecularExponentMin = 1.0f;
1120 const SkScalar SkSpotLight::kSpecularExponentMax = 128.0f;
1121 
1122 ///////////////////////////////////////////////////////////////////////////////
1123 
flattenLight(SkWriteBuffer & buffer) const1124 void SkImageFilterLight::flattenLight(SkWriteBuffer& buffer) const {
1125     // Write type first, then baseclass, then subclass.
1126     buffer.writeInt(this->type());
1127     write_point3(fColor, buffer);
1128     this->onFlattenLight(buffer);
1129 }
1130 
UnflattenLight(SkReadBuffer & buffer)1131 /*static*/ SkImageFilterLight* SkImageFilterLight::UnflattenLight(SkReadBuffer& buffer) {
1132     SkImageFilterLight::LightType type = buffer.read32LE(SkImageFilterLight::kLast_LightType);
1133 
1134     switch (type) {
1135         // Each of these constructors must first call SkLight's, so we'll read the baseclass
1136         // then subclass, same order as flattenLight.
1137         case SkImageFilterLight::kDistant_LightType:
1138             return new SkDistantLight(buffer);
1139         case SkImageFilterLight::kPoint_LightType:
1140             return new SkPointLight(buffer);
1141         case SkImageFilterLight::kSpot_LightType:
1142             return new SkSpotLight(buffer);
1143         default:
1144             // Should never get here due to prior check of SkSafeRange
1145             SkDEBUGFAIL("Unknown LightType.");
1146             return nullptr;
1147     }
1148 }
1149 ///////////////////////////////////////////////////////////////////////////////
1150 
SkLightingImageFilter(sk_sp<SkImageFilterLight> light,SkScalar surfaceScale,sk_sp<SkImageFilter> input,const CropRect * cropRect)1151 SkLightingImageFilter::SkLightingImageFilter(sk_sp<SkImageFilterLight> light,
1152                                              SkScalar surfaceScale,
1153                                              sk_sp<SkImageFilter> input, const CropRect* cropRect)
1154     : INHERITED(&input, 1, cropRect)
1155     , fLight(std::move(light))
1156     , fSurfaceScale(surfaceScale / 255) {
1157 }
1158 
~SkLightingImageFilter()1159 SkLightingImageFilter::~SkLightingImageFilter() {}
1160 
MakeDistantLitDiffuse(const SkPoint3 & direction,SkColor lightColor,SkScalar surfaceScale,SkScalar kd,sk_sp<SkImageFilter> input,const CropRect * cropRect)1161 sk_sp<SkImageFilter> SkLightingImageFilter::MakeDistantLitDiffuse(const SkPoint3& direction,
1162                                                                   SkColor lightColor,
1163                                                                   SkScalar surfaceScale,
1164                                                                   SkScalar kd,
1165                                                                   sk_sp<SkImageFilter> input,
1166                                                                   const CropRect* cropRect) {
1167     sk_sp<SkImageFilterLight> light(new SkDistantLight(direction, lightColor));
1168     return SkDiffuseLightingImageFilter::Make(std::move(light), surfaceScale, kd,
1169                                               std::move(input), cropRect);
1170 }
1171 
MakePointLitDiffuse(const SkPoint3 & location,SkColor lightColor,SkScalar surfaceScale,SkScalar kd,sk_sp<SkImageFilter> input,const CropRect * cropRect)1172 sk_sp<SkImageFilter> SkLightingImageFilter::MakePointLitDiffuse(const SkPoint3& location,
1173                                                                 SkColor lightColor,
1174                                                                 SkScalar surfaceScale,
1175                                                                 SkScalar kd,
1176                                                                 sk_sp<SkImageFilter> input,
1177                                                                 const CropRect* cropRect) {
1178     sk_sp<SkImageFilterLight> light(new SkPointLight(location, lightColor));
1179     return SkDiffuseLightingImageFilter::Make(std::move(light), surfaceScale, kd,
1180                                               std::move(input), cropRect);
1181 }
1182 
MakeSpotLitDiffuse(const SkPoint3 & location,const SkPoint3 & target,SkScalar specularExponent,SkScalar cutoffAngle,SkColor lightColor,SkScalar surfaceScale,SkScalar kd,sk_sp<SkImageFilter> input,const CropRect * cropRect)1183 sk_sp<SkImageFilter> SkLightingImageFilter::MakeSpotLitDiffuse(const SkPoint3& location,
1184                                                                const SkPoint3& target,
1185                                                                SkScalar specularExponent,
1186                                                                SkScalar cutoffAngle,
1187                                                                SkColor lightColor,
1188                                                                SkScalar surfaceScale,
1189                                                                SkScalar kd,
1190                                                                sk_sp<SkImageFilter> input,
1191                                                                const CropRect* cropRect) {
1192     sk_sp<SkImageFilterLight> light(
1193             new SkSpotLight(location, target, specularExponent, cutoffAngle, lightColor));
1194     return SkDiffuseLightingImageFilter::Make(std::move(light), surfaceScale, kd,
1195                                               std::move(input), cropRect);
1196 }
1197 
MakeDistantLitSpecular(const SkPoint3 & direction,SkColor lightColor,SkScalar surfaceScale,SkScalar ks,SkScalar shine,sk_sp<SkImageFilter> input,const CropRect * cropRect)1198 sk_sp<SkImageFilter> SkLightingImageFilter::MakeDistantLitSpecular(const SkPoint3& direction,
1199                                                                    SkColor lightColor,
1200                                                                    SkScalar surfaceScale,
1201                                                                    SkScalar ks,
1202                                                                    SkScalar shine,
1203                                                                    sk_sp<SkImageFilter> input,
1204                                                                    const CropRect* cropRect) {
1205     sk_sp<SkImageFilterLight> light(new SkDistantLight(direction, lightColor));
1206     return SkSpecularLightingImageFilter::Make(std::move(light), surfaceScale, ks, shine,
1207                                                std::move(input), cropRect);
1208 }
1209 
MakePointLitSpecular(const SkPoint3 & location,SkColor lightColor,SkScalar surfaceScale,SkScalar ks,SkScalar shine,sk_sp<SkImageFilter> input,const CropRect * cropRect)1210 sk_sp<SkImageFilter> SkLightingImageFilter::MakePointLitSpecular(const SkPoint3& location,
1211                                                                  SkColor lightColor,
1212                                                                  SkScalar surfaceScale,
1213                                                                  SkScalar ks,
1214                                                                  SkScalar shine,
1215                                                                  sk_sp<SkImageFilter> input,
1216                                                                  const CropRect* cropRect) {
1217     sk_sp<SkImageFilterLight> light(new SkPointLight(location, lightColor));
1218     return SkSpecularLightingImageFilter::Make(std::move(light), surfaceScale, ks, shine,
1219                                                std::move(input), cropRect);
1220 }
1221 
MakeSpotLitSpecular(const SkPoint3 & location,const SkPoint3 & target,SkScalar specularExponent,SkScalar cutoffAngle,SkColor lightColor,SkScalar surfaceScale,SkScalar ks,SkScalar shine,sk_sp<SkImageFilter> input,const CropRect * cropRect)1222 sk_sp<SkImageFilter> SkLightingImageFilter::MakeSpotLitSpecular(const SkPoint3& location,
1223                                                                 const SkPoint3& target,
1224                                                                 SkScalar specularExponent,
1225                                                                 SkScalar cutoffAngle,
1226                                                                 SkColor lightColor,
1227                                                                 SkScalar surfaceScale,
1228                                                                 SkScalar ks,
1229                                                                 SkScalar shine,
1230                                                                 sk_sp<SkImageFilter> input,
1231                                                                 const CropRect* cropRect) {
1232     sk_sp<SkImageFilterLight> light(
1233             new SkSpotLight(location, target, specularExponent, cutoffAngle, lightColor));
1234     return SkSpecularLightingImageFilter::Make(std::move(light), surfaceScale, ks, shine,
1235                                                std::move(input), cropRect);
1236 }
1237 
flatten(SkWriteBuffer & buffer) const1238 void SkLightingImageFilter::flatten(SkWriteBuffer& buffer) const {
1239     this->INHERITED::flatten(buffer);
1240     fLight->flattenLight(buffer);
1241     buffer.writeScalar(fSurfaceScale * 255);
1242 }
1243 
refLight() const1244 sk_sp<const SkImageFilterLight> SkLightingImageFilter::refLight() const { return fLight; }
1245 
1246 ///////////////////////////////////////////////////////////////////////////////
1247 
Make(sk_sp<SkImageFilterLight> light,SkScalar surfaceScale,SkScalar kd,sk_sp<SkImageFilter> input,const CropRect * cropRect)1248 sk_sp<SkImageFilter> SkDiffuseLightingImageFilter::Make(sk_sp<SkImageFilterLight> light,
1249                                                         SkScalar surfaceScale,
1250                                                         SkScalar kd,
1251                                                         sk_sp<SkImageFilter> input,
1252                                                         const CropRect* cropRect) {
1253     if (!light) {
1254         return nullptr;
1255     }
1256     if (!SkScalarIsFinite(surfaceScale) || !SkScalarIsFinite(kd)) {
1257         return nullptr;
1258     }
1259     // According to the spec, kd can be any non-negative number :
1260     // http://www.w3.org/TR/SVG/filters.html#feDiffuseLightingElement
1261     if (kd < 0) {
1262         return nullptr;
1263     }
1264     return sk_sp<SkImageFilter>(new SkDiffuseLightingImageFilter(std::move(light), surfaceScale,
1265                                                                  kd, std::move(input), cropRect));
1266 }
1267 
SkDiffuseLightingImageFilter(sk_sp<SkImageFilterLight> light,SkScalar surfaceScale,SkScalar kd,sk_sp<SkImageFilter> input,const CropRect * cropRect)1268 SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(sk_sp<SkImageFilterLight> light,
1269                                                            SkScalar surfaceScale,
1270                                                            SkScalar kd,
1271                                                            sk_sp<SkImageFilter> input,
1272                                                            const CropRect* cropRect)
1273     : INHERITED(std::move(light), surfaceScale, std::move(input), cropRect)
1274     , fKD(kd) {
1275 }
1276 
CreateProc(SkReadBuffer & buffer)1277 sk_sp<SkFlattenable> SkDiffuseLightingImageFilter::CreateProc(SkReadBuffer& buffer) {
1278     SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
1279 
1280     sk_sp<SkImageFilterLight> light(SkImageFilterLight::UnflattenLight(buffer));
1281     SkScalar surfaceScale = buffer.readScalar();
1282     SkScalar kd = buffer.readScalar();
1283 
1284     return Make(std::move(light), surfaceScale, kd, common.getInput(0), &common.cropRect());
1285 }
1286 
flatten(SkWriteBuffer & buffer) const1287 void SkDiffuseLightingImageFilter::flatten(SkWriteBuffer& buffer) const {
1288     this->INHERITED::flatten(buffer);
1289     buffer.writeScalar(fKD);
1290 }
1291 
onFilterImage(SkSpecialImage * source,const Context & ctx,SkIPoint * offset) const1292 sk_sp<SkSpecialImage> SkDiffuseLightingImageFilter::onFilterImage(SkSpecialImage* source,
1293                                                                   const Context& ctx,
1294                                                                   SkIPoint* offset) const {
1295     SkIPoint inputOffset = SkIPoint::Make(0, 0);
1296     sk_sp<SkSpecialImage> input(this->filterInput(0, source, ctx, &inputOffset));
1297     if (!input) {
1298         return nullptr;
1299     }
1300 
1301     const SkIRect inputBounds = SkIRect::MakeXYWH(inputOffset.x(), inputOffset.y(),
1302                                                   input->width(), input->height());
1303     SkIRect bounds;
1304     if (!this->applyCropRect(ctx, inputBounds, &bounds)) {
1305         return nullptr;
1306     }
1307 
1308     offset->fX = bounds.left();
1309     offset->fY = bounds.top();
1310     bounds.offset(-inputOffset);
1311 
1312 #if SK_SUPPORT_GPU
1313     if (source->isTextureBacked()) {
1314         SkMatrix matrix(ctx.ctm());
1315         matrix.postTranslate(SkIntToScalar(-offset->fX), SkIntToScalar(-offset->fY));
1316 
1317         return this->filterImageGPU(source, input.get(), bounds, matrix, ctx.outputProperties());
1318     }
1319 #endif
1320 
1321     if (bounds.width() < 2 || bounds.height() < 2) {
1322         return nullptr;
1323     }
1324 
1325     SkBitmap inputBM;
1326 
1327     if (!input->getROPixels(&inputBM)) {
1328         return nullptr;
1329     }
1330 
1331     if (inputBM.colorType() != kN32_SkColorType) {
1332         return nullptr;
1333     }
1334 
1335     if (!inputBM.getPixels()) {
1336         return nullptr;
1337     }
1338 
1339     const SkImageInfo info = SkImageInfo::MakeN32Premul(bounds.width(), bounds.height());
1340 
1341     SkBitmap dst;
1342     if (!dst.tryAllocPixels(info)) {
1343         return nullptr;
1344     }
1345 
1346     SkMatrix matrix(ctx.ctm());
1347     matrix.postTranslate(SkIntToScalar(-inputOffset.x()), SkIntToScalar(-inputOffset.y()));
1348 
1349     sk_sp<SkImageFilterLight> transformedLight(light()->transform(matrix));
1350 
1351     DiffuseLightingType lightingType(fKD);
1352     lightBitmap(lightingType,
1353                                                              transformedLight.get(),
1354                                                              inputBM,
1355                                                              &dst,
1356                                                              surfaceScale(),
1357                                                              bounds);
1358 
1359     return SkSpecialImage::MakeFromRaster(SkIRect::MakeWH(bounds.width(), bounds.height()),
1360                                           dst);
1361 }
1362 
onMakeColorSpace(SkColorSpaceXformer * xformer) const1363 sk_sp<SkImageFilter> SkDiffuseLightingImageFilter::onMakeColorSpace(SkColorSpaceXformer* xformer)
1364 const {
1365     SkASSERT(1 == this->countInputs());
1366     auto input = xformer->apply(this->getInput(0));
1367     auto light = this->light()->makeColorSpace(xformer);
1368     if (input.get() != this->getInput(0) || light.get() != this->light()) {
1369         return SkDiffuseLightingImageFilter::Make(std::move(light), 255.0f * this->surfaceScale(),
1370                                                   fKD, std::move(input), this->getCropRectIfSet());
1371     }
1372     return this->refMe();
1373 }
1374 
1375 #if SK_SUPPORT_GPU
makeFragmentProcessor(sk_sp<GrTextureProxy> proxy,const SkMatrix & matrix,const SkIRect * srcBounds,BoundaryMode boundaryMode) const1376 std::unique_ptr<GrFragmentProcessor> SkDiffuseLightingImageFilter::makeFragmentProcessor(
1377         sk_sp<GrTextureProxy> proxy,
1378         const SkMatrix& matrix,
1379         const SkIRect* srcBounds,
1380         BoundaryMode boundaryMode) const {
1381     SkScalar scale = this->surfaceScale() * 255;
1382     return GrDiffuseLightingEffect::Make(std::move(proxy), this->refLight(), scale, matrix,
1383                                          this->kd(), boundaryMode, srcBounds);
1384 }
1385 #endif
1386 
1387 ///////////////////////////////////////////////////////////////////////////////
1388 
Make(sk_sp<SkImageFilterLight> light,SkScalar surfaceScale,SkScalar ks,SkScalar shininess,sk_sp<SkImageFilter> input,const CropRect * cropRect)1389 sk_sp<SkImageFilter> SkSpecularLightingImageFilter::Make(sk_sp<SkImageFilterLight> light,
1390                                                          SkScalar surfaceScale,
1391                                                          SkScalar ks,
1392                                                          SkScalar shininess,
1393                                                          sk_sp<SkImageFilter> input,
1394                                                          const CropRect* cropRect) {
1395     if (!light) {
1396         return nullptr;
1397     }
1398     if (!SkScalarIsFinite(surfaceScale) || !SkScalarIsFinite(ks) || !SkScalarIsFinite(shininess)) {
1399         return nullptr;
1400     }
1401     // According to the spec, ks can be any non-negative number :
1402     // http://www.w3.org/TR/SVG/filters.html#feSpecularLightingElement
1403     if (ks < 0) {
1404         return nullptr;
1405     }
1406     return sk_sp<SkImageFilter>(new SkSpecularLightingImageFilter(std::move(light), surfaceScale,
1407                                                                   ks, shininess,
1408                                                                   std::move(input), cropRect));
1409 }
1410 
SkSpecularLightingImageFilter(sk_sp<SkImageFilterLight> light,SkScalar surfaceScale,SkScalar ks,SkScalar shininess,sk_sp<SkImageFilter> input,const CropRect * cropRect)1411 SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(sk_sp<SkImageFilterLight> light,
1412                                                              SkScalar surfaceScale,
1413                                                              SkScalar ks,
1414                                                              SkScalar shininess,
1415                                                              sk_sp<SkImageFilter> input,
1416                                                              const CropRect* cropRect)
1417     : INHERITED(std::move(light), surfaceScale, std::move(input), cropRect)
1418     , fKS(ks)
1419     , fShininess(shininess) {
1420 }
1421 
CreateProc(SkReadBuffer & buffer)1422 sk_sp<SkFlattenable> SkSpecularLightingImageFilter::CreateProc(SkReadBuffer& buffer) {
1423     SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
1424     sk_sp<SkImageFilterLight> light(SkImageFilterLight::UnflattenLight(buffer));
1425     SkScalar surfaceScale = buffer.readScalar();
1426     SkScalar ks = buffer.readScalar();
1427     SkScalar shine = buffer.readScalar();
1428 
1429     return Make(std::move(light), surfaceScale, ks, shine, common.getInput(0),
1430                 &common.cropRect());
1431 }
1432 
flatten(SkWriteBuffer & buffer) const1433 void SkSpecularLightingImageFilter::flatten(SkWriteBuffer& buffer) const {
1434     this->INHERITED::flatten(buffer);
1435     buffer.writeScalar(fKS);
1436     buffer.writeScalar(fShininess);
1437 }
1438 
onFilterImage(SkSpecialImage * source,const Context & ctx,SkIPoint * offset) const1439 sk_sp<SkSpecialImage> SkSpecularLightingImageFilter::onFilterImage(SkSpecialImage* source,
1440                                                                    const Context& ctx,
1441                                                                    SkIPoint* offset) const {
1442     SkIPoint inputOffset = SkIPoint::Make(0, 0);
1443     sk_sp<SkSpecialImage> input(this->filterInput(0, source, ctx, &inputOffset));
1444     if (!input) {
1445         return nullptr;
1446     }
1447 
1448     const SkIRect inputBounds = SkIRect::MakeXYWH(inputOffset.x(), inputOffset.y(),
1449                                                   input->width(), input->height());
1450     SkIRect bounds;
1451     if (!this->applyCropRect(ctx, inputBounds, &bounds)) {
1452         return nullptr;
1453     }
1454 
1455     offset->fX = bounds.left();
1456     offset->fY = bounds.top();
1457     bounds.offset(-inputOffset);
1458 
1459 #if SK_SUPPORT_GPU
1460     if (source->isTextureBacked()) {
1461         SkMatrix matrix(ctx.ctm());
1462         matrix.postTranslate(SkIntToScalar(-offset->fX), SkIntToScalar(-offset->fY));
1463 
1464         return this->filterImageGPU(source, input.get(), bounds, matrix, ctx.outputProperties());
1465     }
1466 #endif
1467 
1468     if (bounds.width() < 2 || bounds.height() < 2) {
1469         return nullptr;
1470     }
1471 
1472     SkBitmap inputBM;
1473 
1474     if (!input->getROPixels(&inputBM)) {
1475         return nullptr;
1476     }
1477 
1478     if (inputBM.colorType() != kN32_SkColorType) {
1479         return nullptr;
1480     }
1481 
1482     if (!inputBM.getPixels()) {
1483         return nullptr;
1484     }
1485 
1486     const SkImageInfo info = SkImageInfo::MakeN32Premul(bounds.width(), bounds.height());
1487 
1488     SkBitmap dst;
1489     if (!dst.tryAllocPixels(info)) {
1490         return nullptr;
1491     }
1492 
1493     SpecularLightingType lightingType(fKS, fShininess);
1494 
1495     SkMatrix matrix(ctx.ctm());
1496     matrix.postTranslate(SkIntToScalar(-inputOffset.x()), SkIntToScalar(-inputOffset.y()));
1497 
1498     sk_sp<SkImageFilterLight> transformedLight(light()->transform(matrix));
1499 
1500     lightBitmap(lightingType,
1501                                                               transformedLight.get(),
1502                                                               inputBM,
1503                                                               &dst,
1504                                                               surfaceScale(),
1505                                                               bounds);
1506 
1507     return SkSpecialImage::MakeFromRaster(SkIRect::MakeWH(bounds.width(), bounds.height()), dst);
1508 }
1509 
onMakeColorSpace(SkColorSpaceXformer * xformer) const1510 sk_sp<SkImageFilter> SkSpecularLightingImageFilter::onMakeColorSpace(SkColorSpaceXformer* xformer)
1511 const {
1512     SkASSERT(1 == this->countInputs());
1513 
1514     auto input = xformer->apply(this->getInput(0));
1515     auto light = this->light()->makeColorSpace(xformer);
1516     if (input.get() != this->getInput(0) || light.get() != this->light()) {
1517         return SkSpecularLightingImageFilter::Make(std::move(light),
1518                                                    255.0f * this->surfaceScale(), fKS, fShininess,
1519                                                    std::move(input), this->getCropRectIfSet());
1520     }
1521     return this->refMe();
1522 }
1523 
1524 #if SK_SUPPORT_GPU
makeFragmentProcessor(sk_sp<GrTextureProxy> proxy,const SkMatrix & matrix,const SkIRect * srcBounds,BoundaryMode boundaryMode) const1525 std::unique_ptr<GrFragmentProcessor> SkSpecularLightingImageFilter::makeFragmentProcessor(
1526         sk_sp<GrTextureProxy> proxy,
1527         const SkMatrix& matrix,
1528         const SkIRect* srcBounds,
1529         BoundaryMode boundaryMode) const {
1530     SkScalar scale = this->surfaceScale() * 255;
1531     return GrSpecularLightingEffect::Make(std::move(proxy), this->refLight(), scale, matrix,
1532                                           this->ks(), this->shininess(), boundaryMode, srcBounds);
1533 }
1534 #endif
1535 
1536 ///////////////////////////////////////////////////////////////////////////////
1537 
1538 #if SK_SUPPORT_GPU
1539 
emitNormalFunc(BoundaryMode mode,const char * pointToNormalName,const char * sobelFuncName)1540 static SkString emitNormalFunc(BoundaryMode mode,
1541                                const char* pointToNormalName,
1542                                const char* sobelFuncName) {
1543     SkString result;
1544     switch (mode) {
1545     case kTopLeft_BoundaryMode:
1546         result.printf("\treturn %s(%s(0.0, 0.0, m[4], m[5], m[7], m[8], %g),\n"
1547                       "\t          %s(0.0, 0.0, m[4], m[7], m[5], m[8], %g),\n"
1548                       "\t          surfaceScale);\n",
1549                       pointToNormalName, sobelFuncName, gTwoThirds,
1550                                          sobelFuncName, gTwoThirds);
1551         break;
1552     case kTop_BoundaryMode:
1553         result.printf("\treturn %s(%s(0.0, 0.0, m[3], m[5], m[6], m[8], %g),\n"
1554                       "\t          %s(0.0, 0.0, m[4], m[7], m[5], m[8], %g),\n"
1555                       "\t          surfaceScale);\n",
1556                       pointToNormalName, sobelFuncName, gOneThird,
1557                                          sobelFuncName, gOneHalf);
1558         break;
1559     case kTopRight_BoundaryMode:
1560         result.printf("\treturn %s(%s( 0.0,  0.0, m[3], m[4], m[6], m[7], %g),\n"
1561                       "\t          %s(m[3], m[6], m[4], m[7],  0.0,  0.0, %g),\n"
1562                       "\t          surfaceScale);\n",
1563                       pointToNormalName, sobelFuncName, gTwoThirds,
1564                                          sobelFuncName, gTwoThirds);
1565         break;
1566     case kLeft_BoundaryMode:
1567         result.printf("\treturn %s(%s(m[1], m[2], m[4], m[5], m[7], m[8], %g),\n"
1568                       "\t          %s( 0.0,  0.0, m[1], m[7], m[2], m[8], %g),\n"
1569                       "\t          surfaceScale);\n",
1570                       pointToNormalName, sobelFuncName, gOneHalf,
1571                                          sobelFuncName, gOneThird);
1572         break;
1573     case kInterior_BoundaryMode:
1574         result.printf("\treturn %s(%s(m[0], m[2], m[3], m[5], m[6], m[8], %g),\n"
1575                       "\t          %s(m[0], m[6], m[1], m[7], m[2], m[8], %g),\n"
1576                       "\t          surfaceScale);\n",
1577                       pointToNormalName, sobelFuncName, gOneQuarter,
1578                                          sobelFuncName, gOneQuarter);
1579         break;
1580     case kRight_BoundaryMode:
1581         result.printf("\treturn %s(%s(m[0], m[1], m[3], m[4], m[6], m[7], %g),\n"
1582                       "\t          %s(m[0], m[6], m[1], m[7],  0.0,  0.0, %g),\n"
1583                       "\t          surfaceScale);\n",
1584                       pointToNormalName, sobelFuncName, gOneHalf,
1585                                          sobelFuncName, gOneThird);
1586         break;
1587     case kBottomLeft_BoundaryMode:
1588         result.printf("\treturn %s(%s(m[1], m[2], m[4], m[5],  0.0,  0.0, %g),\n"
1589                       "\t          %s( 0.0,  0.0, m[1], m[4], m[2], m[5], %g),\n"
1590                       "\t          surfaceScale);\n",
1591                       pointToNormalName, sobelFuncName, gTwoThirds,
1592                                          sobelFuncName, gTwoThirds);
1593         break;
1594     case kBottom_BoundaryMode:
1595         result.printf("\treturn %s(%s(m[0], m[2], m[3], m[5],  0.0,  0.0, %g),\n"
1596                       "\t          %s(m[0], m[3], m[1], m[4], m[2], m[5], %g),\n"
1597                       "\t          surfaceScale);\n",
1598                       pointToNormalName, sobelFuncName, gOneThird,
1599                                          sobelFuncName, gOneHalf);
1600         break;
1601     case kBottomRight_BoundaryMode:
1602         result.printf("\treturn %s(%s(m[0], m[1], m[3], m[4],  0.0,  0.0, %g),\n"
1603                       "\t          %s(m[0], m[3], m[1], m[4],  0.0,  0.0, %g),\n"
1604                       "\t          surfaceScale);\n",
1605                       pointToNormalName, sobelFuncName, gTwoThirds,
1606                                          sobelFuncName, gTwoThirds);
1607         break;
1608     default:
1609         SkASSERT(false);
1610         break;
1611     }
1612     return result;
1613 }
1614 
1615 class GrGLLightingEffect : public GrGLSLFragmentProcessor {
1616 public:
GrGLLightingEffect()1617     GrGLLightingEffect() : fLight(nullptr) { }
~GrGLLightingEffect()1618     ~GrGLLightingEffect() override { delete fLight; }
1619 
1620     void emitCode(EmitArgs&) override;
1621 
1622     static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder* b);
1623 
1624 protected:
1625     /**
1626      * Subclasses of GrGLLightingEffect must call INHERITED::onSetData();
1627      */
1628     void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
1629 
1630     virtual void emitLightFunc(GrGLSLUniformHandler*,
1631                                GrGLSLFPFragmentBuilder*,
1632                                SkString* funcName) = 0;
1633 
1634 private:
1635     typedef GrGLSLFragmentProcessor INHERITED;
1636 
1637     UniformHandle              fImageIncrementUni;
1638     UniformHandle              fSurfaceScaleUni;
1639     GrTextureDomain::GLDomain  fDomain;
1640     GrGLLight*                 fLight;
1641 };
1642 
1643 ///////////////////////////////////////////////////////////////////////////////
1644 
1645 class GrGLDiffuseLightingEffect  : public GrGLLightingEffect {
1646 public:
1647     void emitLightFunc(GrGLSLUniformHandler*, GrGLSLFPFragmentBuilder*, SkString* funcName) override;
1648 
1649 protected:
1650     void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
1651 
1652 private:
1653     typedef GrGLLightingEffect INHERITED;
1654 
1655     UniformHandle   fKDUni;
1656 };
1657 
1658 ///////////////////////////////////////////////////////////////////////////////
1659 
1660 class GrGLSpecularLightingEffect  : public GrGLLightingEffect {
1661 public:
1662     void emitLightFunc(GrGLSLUniformHandler*, GrGLSLFPFragmentBuilder*, SkString* funcName) override;
1663 
1664 protected:
1665     void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
1666 
1667 private:
1668     typedef GrGLLightingEffect INHERITED;
1669 
1670     UniformHandle   fKSUni;
1671     UniformHandle   fShininessUni;
1672 };
1673 
1674 ///////////////////////////////////////////////////////////////////////////////
1675 
create_domain(GrTextureProxy * proxy,const SkIRect * srcBounds,GrTextureDomain::Mode mode)1676 static GrTextureDomain create_domain(GrTextureProxy* proxy, const SkIRect* srcBounds,
1677                                      GrTextureDomain::Mode mode) {
1678     if (srcBounds) {
1679         SkRect texelDomain = GrTextureDomain::MakeTexelDomain(*srcBounds, mode);
1680         return GrTextureDomain(proxy, texelDomain, mode, mode);
1681     } else {
1682         return GrTextureDomain::IgnoredDomain();
1683     }
1684 }
1685 
GrLightingEffect(ClassID classID,sk_sp<GrTextureProxy> proxy,sk_sp<const SkImageFilterLight> light,SkScalar surfaceScale,const SkMatrix & matrix,BoundaryMode boundaryMode,const SkIRect * srcBounds)1686 GrLightingEffect::GrLightingEffect(ClassID classID,
1687                                    sk_sp<GrTextureProxy> proxy,
1688                                    sk_sp<const SkImageFilterLight> light,
1689                                    SkScalar surfaceScale,
1690                                    const SkMatrix& matrix,
1691                                    BoundaryMode boundaryMode,
1692                                    const SkIRect* srcBounds)
1693         // Perhaps this could advertise the opaque or coverage-as-alpha optimizations?
1694         : INHERITED(classID, kNone_OptimizationFlags)
1695         , fCoordTransform(proxy.get())
1696         , fDomain(create_domain(proxy.get(), srcBounds, GrTextureDomain::kDecal_Mode))
1697         , fTextureSampler(std::move(proxy))
1698         , fLight(std::move(light))
1699         , fSurfaceScale(surfaceScale)
1700         , fFilterMatrix(matrix)
1701         , fBoundaryMode(boundaryMode) {
1702     this->addCoordTransform(&fCoordTransform);
1703     this->setTextureSamplerCnt(1);
1704 }
1705 
GrLightingEffect(const GrLightingEffect & that)1706 GrLightingEffect::GrLightingEffect(const GrLightingEffect& that)
1707         : INHERITED(that.classID(), that.optimizationFlags())
1708         , fCoordTransform(that.fCoordTransform)
1709         , fDomain(that.fDomain)
1710         , fTextureSampler(that.fTextureSampler)
1711         , fLight(that.fLight)
1712         , fSurfaceScale(that.fSurfaceScale)
1713         , fFilterMatrix(that.fFilterMatrix)
1714         , fBoundaryMode(that.fBoundaryMode) {
1715     this->addCoordTransform(&fCoordTransform);
1716     this->setTextureSamplerCnt(1);
1717 }
1718 
onIsEqual(const GrFragmentProcessor & sBase) const1719 bool GrLightingEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
1720     const GrLightingEffect& s = sBase.cast<GrLightingEffect>();
1721     return fLight->isEqual(*s.fLight) &&
1722            fSurfaceScale == s.fSurfaceScale &&
1723            fBoundaryMode == s.fBoundaryMode;
1724 }
1725 
1726 ///////////////////////////////////////////////////////////////////////////////
1727 
GrDiffuseLightingEffect(sk_sp<GrTextureProxy> proxy,sk_sp<const SkImageFilterLight> light,SkScalar surfaceScale,const SkMatrix & matrix,SkScalar kd,BoundaryMode boundaryMode,const SkIRect * srcBounds)1728 GrDiffuseLightingEffect::GrDiffuseLightingEffect(sk_sp<GrTextureProxy> proxy,
1729                                                  sk_sp<const SkImageFilterLight>light,
1730                                                  SkScalar surfaceScale,
1731                                                  const SkMatrix& matrix,
1732                                                  SkScalar kd,
1733                                                  BoundaryMode boundaryMode,
1734                                                  const SkIRect* srcBounds)
1735         : INHERITED(kGrDiffuseLightingEffect_ClassID, std::move(proxy), std::move(light),
1736                     surfaceScale, matrix, boundaryMode, srcBounds)
1737         , fKD(kd) {}
1738 
GrDiffuseLightingEffect(const GrDiffuseLightingEffect & that)1739 GrDiffuseLightingEffect::GrDiffuseLightingEffect(const GrDiffuseLightingEffect& that)
1740         : INHERITED(that), fKD(that.fKD) {}
1741 
onIsEqual(const GrFragmentProcessor & sBase) const1742 bool GrDiffuseLightingEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
1743     const GrDiffuseLightingEffect& s = sBase.cast<GrDiffuseLightingEffect>();
1744     return INHERITED::onIsEqual(sBase) && this->kd() == s.kd();
1745 }
1746 
onGetGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const1747 void GrDiffuseLightingEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
1748                                                     GrProcessorKeyBuilder* b) const {
1749     GrGLDiffuseLightingEffect::GenKey(*this, caps, b);
1750 }
1751 
onCreateGLSLInstance() const1752 GrGLSLFragmentProcessor* GrDiffuseLightingEffect::onCreateGLSLInstance() const {
1753     return new GrGLDiffuseLightingEffect;
1754 }
1755 
1756 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDiffuseLightingEffect);
1757 
1758 #if GR_TEST_UTILS
1759 
random_point3(SkRandom * random)1760 static SkPoint3 random_point3(SkRandom* random) {
1761     return SkPoint3::Make(SkScalarToFloat(random->nextSScalar1()),
1762                           SkScalarToFloat(random->nextSScalar1()),
1763                           SkScalarToFloat(random->nextSScalar1()));
1764 }
1765 
create_random_light(SkRandom * random)1766 static SkImageFilterLight* create_random_light(SkRandom* random) {
1767     int type = random->nextULessThan(3);
1768     switch (type) {
1769         case 0: {
1770             return new SkDistantLight(random_point3(random), random->nextU());
1771         }
1772         case 1: {
1773             return new SkPointLight(random_point3(random), random->nextU());
1774         }
1775         case 2: {
1776             return new SkSpotLight(random_point3(random), random_point3(random),
1777                                    random->nextUScalar1(), random->nextUScalar1(), random->nextU());
1778         }
1779         default:
1780             SK_ABORT("Unexpected value.");
1781             return nullptr;
1782     }
1783 }
1784 
TestCreate(GrProcessorTestData * d)1785 std::unique_ptr<GrFragmentProcessor> GrDiffuseLightingEffect::TestCreate(GrProcessorTestData* d) {
1786     int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
1787                                         : GrProcessorUnitTest::kAlphaTextureIdx;
1788     sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
1789     SkScalar surfaceScale = d->fRandom->nextSScalar1();
1790     SkScalar kd = d->fRandom->nextUScalar1();
1791     sk_sp<SkImageFilterLight> light(create_random_light(d->fRandom));
1792     SkMatrix matrix;
1793     for (int i = 0; i < 9; i++) {
1794         matrix[i] = d->fRandom->nextUScalar1();
1795     }
1796     SkIRect srcBounds = SkIRect::MakeXYWH(d->fRandom->nextRangeU(0, proxy->width()),
1797                                           d->fRandom->nextRangeU(0, proxy->height()),
1798                                           d->fRandom->nextRangeU(0, proxy->width()),
1799                                           d->fRandom->nextRangeU(0, proxy->height()));
1800     BoundaryMode mode = static_cast<BoundaryMode>(d->fRandom->nextU() % kBoundaryModeCount);
1801     return GrDiffuseLightingEffect::Make(std::move(proxy), std::move(light), surfaceScale, matrix,
1802                                          kd, mode, &srcBounds);
1803 }
1804 #endif
1805 
1806 
1807 ///////////////////////////////////////////////////////////////////////////////
1808 
emitCode(EmitArgs & args)1809 void GrGLLightingEffect::emitCode(EmitArgs& args) {
1810     const GrLightingEffect& le = args.fFp.cast<GrLightingEffect>();
1811     if (!fLight) {
1812         fLight = le.light()->createGLLight();
1813     }
1814 
1815     GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
1816     fImageIncrementUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
1817                                                     kHalf2_GrSLType, "ImageIncrement");
1818     fSurfaceScaleUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
1819                                                   kHalf_GrSLType, "SurfaceScale");
1820     fLight->emitLightColorUniform(uniformHandler);
1821     GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
1822     SkString lightFunc;
1823     this->emitLightFunc(uniformHandler, fragBuilder, &lightFunc);
1824     const GrShaderVar gSobelArgs[] =  {
1825         GrShaderVar("a", kHalf_GrSLType),
1826         GrShaderVar("b", kHalf_GrSLType),
1827         GrShaderVar("c", kHalf_GrSLType),
1828         GrShaderVar("d", kHalf_GrSLType),
1829         GrShaderVar("e", kHalf_GrSLType),
1830         GrShaderVar("f", kHalf_GrSLType),
1831         GrShaderVar("scale", kHalf_GrSLType),
1832     };
1833     SkString sobelFuncName;
1834     SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
1835 
1836     fragBuilder->emitFunction(kHalf_GrSLType,
1837                               "sobel",
1838                               SK_ARRAY_COUNT(gSobelArgs),
1839                               gSobelArgs,
1840                               "\treturn (-a + b - 2.0 * c + 2.0 * d -e + f) * scale;\n",
1841                               &sobelFuncName);
1842     const GrShaderVar gPointToNormalArgs[] =  {
1843         GrShaderVar("x", kHalf_GrSLType),
1844         GrShaderVar("y", kHalf_GrSLType),
1845         GrShaderVar("scale", kHalf_GrSLType),
1846     };
1847     SkString pointToNormalName;
1848     fragBuilder->emitFunction(kHalf3_GrSLType,
1849                               "pointToNormal",
1850                               SK_ARRAY_COUNT(gPointToNormalArgs),
1851                               gPointToNormalArgs,
1852                               "\treturn normalize(half3(-x * scale, -y * scale, 1));\n",
1853                               &pointToNormalName);
1854 
1855     const GrShaderVar gInteriorNormalArgs[] =  {
1856         GrShaderVar("m", kHalf_GrSLType, 9),
1857         GrShaderVar("surfaceScale", kHalf_GrSLType),
1858     };
1859     SkString normalBody = emitNormalFunc(le.boundaryMode(),
1860                                          pointToNormalName.c_str(),
1861                                          sobelFuncName.c_str());
1862     SkString normalName;
1863     fragBuilder->emitFunction(kHalf3_GrSLType,
1864                               "normal",
1865                               SK_ARRAY_COUNT(gInteriorNormalArgs),
1866                               gInteriorNormalArgs,
1867                               normalBody.c_str(),
1868                               &normalName);
1869 
1870     fragBuilder->codeAppendf("\t\tfloat2 coord = %s;\n", coords2D.c_str());
1871     fragBuilder->codeAppend("\t\thalf m[9];\n");
1872 
1873     const char* imgInc = uniformHandler->getUniformCStr(fImageIncrementUni);
1874     const char* surfScale = uniformHandler->getUniformCStr(fSurfaceScaleUni);
1875 
1876     int index = 0;
1877     for (int dy = 1; dy >= -1; dy--) {
1878         for (int dx = -1; dx <= 1; dx++) {
1879             SkString texCoords;
1880             texCoords.appendf("coord + half2(%d, %d) * %s", dx, dy, imgInc);
1881             SkString temp;
1882             temp.appendf("temp%d", index);
1883             fragBuilder->codeAppendf("half4 %s;", temp.c_str());
1884             fDomain.sampleTexture(fragBuilder,
1885                                   args.fUniformHandler,
1886                                   args.fShaderCaps,
1887                                   le.domain(),
1888                                   temp.c_str(),
1889                                   texCoords,
1890                                   args.fTexSamplers[0]);
1891             fragBuilder->codeAppendf("m[%d] = %s.a;", index, temp.c_str());
1892             index++;
1893         }
1894     }
1895     fragBuilder->codeAppend("\t\thalf3 surfaceToLight = ");
1896     SkString arg;
1897     arg.appendf("%s * m[4]", surfScale);
1898     fLight->emitSurfaceToLight(uniformHandler, fragBuilder, arg.c_str());
1899     fragBuilder->codeAppend(";\n");
1900     fragBuilder->codeAppendf("\t\t%s = %s(%s(m, %s), surfaceToLight, ",
1901                              args.fOutputColor, lightFunc.c_str(), normalName.c_str(), surfScale);
1902     fLight->emitLightColor(uniformHandler, fragBuilder, "surfaceToLight");
1903     fragBuilder->codeAppend(");\n");
1904     fragBuilder->codeAppendf("%s *= %s;\n", args.fOutputColor, args.fInputColor);
1905 }
1906 
GenKey(const GrProcessor & proc,const GrShaderCaps & caps,GrProcessorKeyBuilder * b)1907 void GrGLLightingEffect::GenKey(const GrProcessor& proc,
1908                                 const GrShaderCaps& caps, GrProcessorKeyBuilder* b) {
1909     const GrLightingEffect& lighting = proc.cast<GrLightingEffect>();
1910     b->add32(lighting.boundaryMode() << 2 | lighting.light()->type());
1911     b->add32(GrTextureDomain::GLDomain::DomainKey(lighting.domain()));
1912 }
1913 
onSetData(const GrGLSLProgramDataManager & pdman,const GrFragmentProcessor & proc)1914 void GrGLLightingEffect::onSetData(const GrGLSLProgramDataManager& pdman,
1915                                    const GrFragmentProcessor& proc) {
1916     const GrLightingEffect& lighting = proc.cast<GrLightingEffect>();
1917     if (!fLight) {
1918         fLight = lighting.light()->createGLLight();
1919     }
1920 
1921     GrTextureProxy* proxy = lighting.textureSampler(0).proxy();
1922     GrTexture* texture = proxy->peekTexture();
1923 
1924     float ySign = proxy->origin() == kTopLeft_GrSurfaceOrigin ? -1.0f : 1.0f;
1925     pdman.set2f(fImageIncrementUni, 1.0f / texture->width(), ySign / texture->height());
1926     pdman.set1f(fSurfaceScaleUni, lighting.surfaceScale());
1927     sk_sp<SkImageFilterLight> transformedLight(
1928             lighting.light()->transform(lighting.filterMatrix()));
1929     fDomain.setData(pdman, lighting.domain(), proxy, lighting.textureSampler(0).samplerState());
1930     fLight->setData(pdman, transformedLight.get());
1931 }
1932 
1933 ///////////////////////////////////////////////////////////////////////////////
1934 
1935 ///////////////////////////////////////////////////////////////////////////////
1936 
emitLightFunc(GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,SkString * funcName)1937 void GrGLDiffuseLightingEffect::emitLightFunc(GrGLSLUniformHandler* uniformHandler,
1938                                               GrGLSLFPFragmentBuilder* fragBuilder,
1939                                               SkString* funcName) {
1940     const char* kd;
1941     fKDUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "KD", &kd);
1942 
1943     const GrShaderVar gLightArgs[] = {
1944         GrShaderVar("normal", kHalf3_GrSLType),
1945         GrShaderVar("surfaceToLight", kHalf3_GrSLType),
1946         GrShaderVar("lightColor", kHalf3_GrSLType)
1947     };
1948     SkString lightBody;
1949     lightBody.appendf("\thalf colorScale = %s * dot(normal, surfaceToLight);\n", kd);
1950     lightBody.appendf("\treturn half4(lightColor * saturate(colorScale), 1.0);\n");
1951     fragBuilder->emitFunction(kHalf4_GrSLType,
1952                               "light",
1953                               SK_ARRAY_COUNT(gLightArgs),
1954                               gLightArgs,
1955                               lightBody.c_str(),
1956                               funcName);
1957 }
1958 
onSetData(const GrGLSLProgramDataManager & pdman,const GrFragmentProcessor & proc)1959 void GrGLDiffuseLightingEffect::onSetData(const GrGLSLProgramDataManager& pdman,
1960                                           const GrFragmentProcessor& proc) {
1961     INHERITED::onSetData(pdman, proc);
1962     const GrDiffuseLightingEffect& diffuse = proc.cast<GrDiffuseLightingEffect>();
1963     pdman.set1f(fKDUni, diffuse.kd());
1964 }
1965 
1966 ///////////////////////////////////////////////////////////////////////////////
1967 
GrSpecularLightingEffect(sk_sp<GrTextureProxy> proxy,sk_sp<const SkImageFilterLight> light,SkScalar surfaceScale,const SkMatrix & matrix,SkScalar ks,SkScalar shininess,BoundaryMode boundaryMode,const SkIRect * srcBounds)1968 GrSpecularLightingEffect::GrSpecularLightingEffect(sk_sp<GrTextureProxy> proxy,
1969                                                    sk_sp<const SkImageFilterLight> light,
1970                                                    SkScalar surfaceScale,
1971                                                    const SkMatrix& matrix,
1972                                                    SkScalar ks,
1973                                                    SkScalar shininess,
1974                                                    BoundaryMode boundaryMode,
1975                                                    const SkIRect* srcBounds)
1976         : INHERITED(kGrSpecularLightingEffect_ClassID, std::move(proxy), std::move(light),
1977                     surfaceScale, matrix, boundaryMode, srcBounds)
1978         , fKS(ks)
1979         , fShininess(shininess) {}
1980 
GrSpecularLightingEffect(const GrSpecularLightingEffect & that)1981 GrSpecularLightingEffect::GrSpecularLightingEffect(const GrSpecularLightingEffect& that)
1982         : INHERITED(that), fKS(that.fKS), fShininess(that.fShininess) {}
1983 
onIsEqual(const GrFragmentProcessor & sBase) const1984 bool GrSpecularLightingEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
1985     const GrSpecularLightingEffect& s = sBase.cast<GrSpecularLightingEffect>();
1986     return INHERITED::onIsEqual(sBase) &&
1987            this->ks() == s.ks() &&
1988            this->shininess() == s.shininess();
1989 }
1990 
onGetGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const1991 void GrSpecularLightingEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
1992                                                      GrProcessorKeyBuilder* b) const {
1993     GrGLSpecularLightingEffect::GenKey(*this, caps, b);
1994 }
1995 
onCreateGLSLInstance() const1996 GrGLSLFragmentProcessor* GrSpecularLightingEffect::onCreateGLSLInstance() const {
1997     return new GrGLSpecularLightingEffect;
1998 }
1999 
2000 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrSpecularLightingEffect);
2001 
2002 #if GR_TEST_UTILS
TestCreate(GrProcessorTestData * d)2003 std::unique_ptr<GrFragmentProcessor> GrSpecularLightingEffect::TestCreate(GrProcessorTestData* d) {
2004     int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
2005                                         : GrProcessorUnitTest::kAlphaTextureIdx;
2006     sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
2007     SkScalar surfaceScale = d->fRandom->nextSScalar1();
2008     SkScalar ks = d->fRandom->nextUScalar1();
2009     SkScalar shininess = d->fRandom->nextUScalar1();
2010     sk_sp<SkImageFilterLight> light(create_random_light(d->fRandom));
2011     SkMatrix matrix;
2012     for (int i = 0; i < 9; i++) {
2013         matrix[i] = d->fRandom->nextUScalar1();
2014     }
2015     BoundaryMode mode = static_cast<BoundaryMode>(d->fRandom->nextU() % kBoundaryModeCount);
2016     SkIRect srcBounds = SkIRect::MakeXYWH(d->fRandom->nextRangeU(0, proxy->width()),
2017                                           d->fRandom->nextRangeU(0, proxy->height()),
2018                                           d->fRandom->nextRangeU(0, proxy->width()),
2019                                           d->fRandom->nextRangeU(0, proxy->height()));
2020     return GrSpecularLightingEffect::Make(std::move(proxy), std::move(light), surfaceScale, matrix,
2021                                           ks, shininess, mode, &srcBounds);
2022 }
2023 #endif
2024 
2025 ///////////////////////////////////////////////////////////////////////////////
2026 
emitLightFunc(GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,SkString * funcName)2027 void GrGLSpecularLightingEffect::emitLightFunc(GrGLSLUniformHandler* uniformHandler,
2028                                                GrGLSLFPFragmentBuilder* fragBuilder,
2029                                                SkString* funcName) {
2030     const char* ks;
2031     const char* shininess;
2032 
2033     fKSUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "KS", &ks);
2034     fShininessUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
2035                                                kHalf_GrSLType,
2036                                                "Shininess",
2037                                                &shininess);
2038 
2039     const GrShaderVar gLightArgs[] = {
2040         GrShaderVar("normal", kHalf3_GrSLType),
2041         GrShaderVar("surfaceToLight", kHalf3_GrSLType),
2042         GrShaderVar("lightColor", kHalf3_GrSLType)
2043     };
2044     SkString lightBody;
2045     lightBody.appendf("\thalf3 halfDir = half3(normalize(surfaceToLight + half3(0, 0, 1)));\n");
2046     lightBody.appendf("\tfloat colorScale = %s * pow(dot(normal, halfDir), %s);\n",
2047                       ks, shininess);
2048     lightBody.appendf("\thalf3 color = lightColor * saturate(colorScale);\n");
2049     lightBody.appendf("\treturn half4(color, max(max(color.r, color.g), color.b));\n");
2050     fragBuilder->emitFunction(kHalf4_GrSLType,
2051                               "light",
2052                               SK_ARRAY_COUNT(gLightArgs),
2053                               gLightArgs,
2054                               lightBody.c_str(),
2055                               funcName);
2056 }
2057 
onSetData(const GrGLSLProgramDataManager & pdman,const GrFragmentProcessor & effect)2058 void GrGLSpecularLightingEffect::onSetData(const GrGLSLProgramDataManager& pdman,
2059                                            const GrFragmentProcessor& effect) {
2060     INHERITED::onSetData(pdman, effect);
2061     const GrSpecularLightingEffect& spec = effect.cast<GrSpecularLightingEffect>();
2062     pdman.set1f(fKSUni, spec.ks());
2063     pdman.set1f(fShininessUni, spec.shininess());
2064 }
2065 
2066 ///////////////////////////////////////////////////////////////////////////////
emitLightColorUniform(GrGLSLUniformHandler * uniformHandler)2067 void GrGLLight::emitLightColorUniform(GrGLSLUniformHandler* uniformHandler) {
2068     fColorUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType, "LightColor");
2069 }
2070 
emitLightColor(GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,const char * surfaceToLight)2071 void GrGLLight::emitLightColor(GrGLSLUniformHandler* uniformHandler,
2072                                GrGLSLFPFragmentBuilder* fragBuilder,
2073                                const char *surfaceToLight) {
2074     fragBuilder->codeAppend(uniformHandler->getUniformCStr(this->lightColorUni()));
2075 }
2076 
setData(const GrGLSLProgramDataManager & pdman,const SkImageFilterLight * light) const2077 void GrGLLight::setData(const GrGLSLProgramDataManager& pdman,
2078                         const SkImageFilterLight* light) const {
2079     setUniformPoint3(pdman, fColorUni,
2080                      light->color().makeScale(SkScalarInvert(SkIntToScalar(255))));
2081 }
2082 
2083 ///////////////////////////////////////////////////////////////////////////////
2084 
setData(const GrGLSLProgramDataManager & pdman,const SkImageFilterLight * light) const2085 void GrGLDistantLight::setData(const GrGLSLProgramDataManager& pdman,
2086                                const SkImageFilterLight* light) const {
2087     INHERITED::setData(pdman, light);
2088     SkASSERT(light->type() == SkImageFilterLight::kDistant_LightType);
2089     const SkDistantLight* distantLight = static_cast<const SkDistantLight*>(light);
2090     setUniformNormal3(pdman, fDirectionUni, distantLight->direction());
2091 }
2092 
emitSurfaceToLight(GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,const char * z)2093 void GrGLDistantLight::emitSurfaceToLight(GrGLSLUniformHandler* uniformHandler,
2094                                           GrGLSLFPFragmentBuilder* fragBuilder,
2095                                           const char* z) {
2096     const char* dir;
2097     fDirectionUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType,
2098                                                "LightDirection", &dir);
2099     fragBuilder->codeAppend(dir);
2100 }
2101 
2102 ///////////////////////////////////////////////////////////////////////////////
2103 
setData(const GrGLSLProgramDataManager & pdman,const SkImageFilterLight * light) const2104 void GrGLPointLight::setData(const GrGLSLProgramDataManager& pdman,
2105                              const SkImageFilterLight* light) const {
2106     INHERITED::setData(pdman, light);
2107     SkASSERT(light->type() == SkImageFilterLight::kPoint_LightType);
2108     const SkPointLight* pointLight = static_cast<const SkPointLight*>(light);
2109     setUniformPoint3(pdman, fLocationUni, pointLight->location());
2110 }
2111 
emitSurfaceToLight(GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,const char * z)2112 void GrGLPointLight::emitSurfaceToLight(GrGLSLUniformHandler* uniformHandler,
2113                                         GrGLSLFPFragmentBuilder* fragBuilder,
2114                                         const char* z) {
2115     const char* loc;
2116     fLocationUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType,
2117                                               "LightLocation", &loc);
2118     fragBuilder->codeAppendf("normalize(%s - half3(sk_FragCoord.xy, %s))",
2119                              loc, z);
2120 }
2121 
2122 ///////////////////////////////////////////////////////////////////////////////
2123 
setData(const GrGLSLProgramDataManager & pdman,const SkImageFilterLight * light) const2124 void GrGLSpotLight::setData(const GrGLSLProgramDataManager& pdman,
2125                             const SkImageFilterLight* light) const {
2126     INHERITED::setData(pdman, light);
2127     SkASSERT(light->type() == SkImageFilterLight::kSpot_LightType);
2128     const SkSpotLight* spotLight = static_cast<const SkSpotLight *>(light);
2129     setUniformPoint3(pdman, fLocationUni, spotLight->location());
2130     pdman.set1f(fExponentUni, spotLight->specularExponent());
2131     pdman.set1f(fCosInnerConeAngleUni, spotLight->cosInnerConeAngle());
2132     pdman.set1f(fCosOuterConeAngleUni, spotLight->cosOuterConeAngle());
2133     pdman.set1f(fConeScaleUni, spotLight->coneScale());
2134     setUniformNormal3(pdman, fSUni, spotLight->s());
2135 }
2136 
emitSurfaceToLight(GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,const char * z)2137 void GrGLSpotLight::emitSurfaceToLight(GrGLSLUniformHandler* uniformHandler,
2138                                        GrGLSLFPFragmentBuilder* fragBuilder,
2139                                        const char* z) {
2140     const char* location;
2141     fLocationUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType,
2142                                               "LightLocation", &location);
2143 
2144     fragBuilder->codeAppendf("normalize(%s - half3(sk_FragCoord.xy, %s))",
2145                              location, z);
2146 }
2147 
emitLightColor(GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,const char * surfaceToLight)2148 void GrGLSpotLight::emitLightColor(GrGLSLUniformHandler* uniformHandler,
2149                                    GrGLSLFPFragmentBuilder* fragBuilder,
2150                                    const char *surfaceToLight) {
2151 
2152     const char* color = uniformHandler->getUniformCStr(this->lightColorUni()); // created by parent class.
2153 
2154     const char* exponent;
2155     const char* cosInner;
2156     const char* cosOuter;
2157     const char* coneScale;
2158     const char* s;
2159     fExponentUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
2160                                               "Exponent", &exponent);
2161     fCosInnerConeAngleUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
2162                                                        "CosInnerConeAngle", &cosInner);
2163     fCosOuterConeAngleUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
2164                                                        "CosOuterConeAngle", &cosOuter);
2165     fConeScaleUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
2166                                                "ConeScale", &coneScale);
2167     fSUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType, "S", &s);
2168 
2169     const GrShaderVar gLightColorArgs[] = {
2170         GrShaderVar("surfaceToLight", kHalf3_GrSLType)
2171     };
2172     SkString lightColorBody;
2173     lightColorBody.appendf("\thalf cosAngle = -dot(surfaceToLight, %s);\n", s);
2174     lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosOuter);
2175     lightColorBody.appendf("\t\treturn half3(0);\n");
2176     lightColorBody.appendf("\t}\n");
2177     lightColorBody.appendf("\thalf scale = pow(cosAngle, %s);\n", exponent);
2178     lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosInner);
2179     lightColorBody.appendf("\t\treturn %s * scale * (cosAngle - %s) * %s;\n",
2180                            color, cosOuter, coneScale);
2181     lightColorBody.appendf("\t}\n");
2182     lightColorBody.appendf("\treturn %s;\n", color);
2183     fragBuilder->emitFunction(kHalf3_GrSLType,
2184                               "lightColor",
2185                               SK_ARRAY_COUNT(gLightColorArgs),
2186                               gLightColorArgs,
2187                               lightColorBody.c_str(),
2188                               &fLightColorFunc);
2189 
2190     fragBuilder->codeAppendf("%s(%s)", fLightColorFunc.c_str(), surfaceToLight);
2191 }
2192 
2193 #endif
2194 
RegisterFlattenables()2195 void SkLightingImageFilter::RegisterFlattenables() {
2196     SK_REGISTER_FLATTENABLE(SkDiffuseLightingImageFilter);
2197     SK_REGISTER_FLATTENABLE(SkSpecularLightingImageFilter);
2198 }
2199