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