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