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