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