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