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; }
621
622 protected:
623 class ImplBase;
624
625 LightingEffect(ClassID classID,
626 GrSurfaceProxyView,
627 sk_sp<const SkImageFilterLight> light,
628 SkScalar surfaceScale,
629 const SkMatrix& matrix,
630 BoundaryMode boundaryMode,
631 const SkIRect* srcBounds,
632 const GrCaps& caps);
633
634 explicit LightingEffect(const LightingEffect& that);
635
636 bool onIsEqual(const GrFragmentProcessor&) const override;
637
638 private:
onAddToKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const639 void onAddToKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override {
640 b->add32(fBoundaryMode << 2 | fLight->type());
641 }
642
643 sk_sp<const SkImageFilterLight> fLight;
644 SkScalar fSurfaceScale;
645 SkMatrix fFilterMatrix;
646 BoundaryMode fBoundaryMode;
647
648 using INHERITED = GrFragmentProcessor;
649 };
650
651 class DiffuseLightingEffect : public LightingEffect {
652 public:
Make(GrSurfaceProxyView view,sk_sp<const SkImageFilterLight> light,SkScalar surfaceScale,const SkMatrix & matrix,SkScalar kd,BoundaryMode boundaryMode,const SkIRect * srcBounds,const GrCaps & caps)653 static std::unique_ptr<GrFragmentProcessor> Make(GrSurfaceProxyView view,
654 sk_sp<const SkImageFilterLight> light,
655 SkScalar surfaceScale,
656 const SkMatrix& matrix,
657 SkScalar kd,
658 BoundaryMode boundaryMode,
659 const SkIRect* srcBounds,
660 const GrCaps& caps) {
661 return std::unique_ptr<GrFragmentProcessor>(new DiffuseLightingEffect(std::move(view),
662 std::move(light),
663 surfaceScale,
664 matrix,
665 kd,
666 boundaryMode,
667 srcBounds,
668 caps));
669 }
670
name() const671 const char* name() const override { return "DiffuseLighting"; }
672
clone() const673 std::unique_ptr<GrFragmentProcessor> clone() const override {
674 return std::unique_ptr<GrFragmentProcessor>(new DiffuseLightingEffect(*this));
675 }
676
677 private:
678 class Impl;
679
680 std::unique_ptr<ProgramImpl> onMakeProgramImpl() const override;
681
682 bool onIsEqual(const GrFragmentProcessor&) const override;
683
684 DiffuseLightingEffect(GrSurfaceProxyView view,
685 sk_sp<const SkImageFilterLight> light,
686 SkScalar surfaceScale,
687 const SkMatrix& matrix,
688 SkScalar kd,
689 BoundaryMode boundaryMode,
690 const SkIRect* srcBounds,
691 const GrCaps& caps);
692
693 explicit DiffuseLightingEffect(const DiffuseLightingEffect& that);
694
695 GR_DECLARE_FRAGMENT_PROCESSOR_TEST
696 SkScalar fKD;
697
698 using INHERITED = LightingEffect;
699 };
700
701 class SpecularLightingEffect : public LightingEffect {
702 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)703 static std::unique_ptr<GrFragmentProcessor> Make(GrSurfaceProxyView view,
704 sk_sp<const SkImageFilterLight> light,
705 SkScalar surfaceScale,
706 const SkMatrix& matrix,
707 SkScalar ks,
708 SkScalar shininess,
709 BoundaryMode boundaryMode,
710 const SkIRect* srcBounds,
711 const GrCaps& caps) {
712 return std::unique_ptr<GrFragmentProcessor>(new SpecularLightingEffect(std::move(view),
713 std::move(light),
714 surfaceScale,
715 matrix,
716 ks,
717 shininess,
718 boundaryMode,
719 srcBounds,
720 caps));
721 }
722
name() const723 const char* name() const override { return "SpecularLighting"; }
724
clone() const725 std::unique_ptr<GrFragmentProcessor> clone() const override {
726 return std::unique_ptr<GrFragmentProcessor>(new SpecularLightingEffect(*this));
727 }
728
729 std::unique_ptr<ProgramImpl> onMakeProgramImpl() const override;
730
731 private:
732 class Impl;
733
734 bool onIsEqual(const GrFragmentProcessor&) const override;
735
736 SpecularLightingEffect(GrSurfaceProxyView,
737 sk_sp<const SkImageFilterLight> light,
738 SkScalar surfaceScale,
739 const SkMatrix& matrix,
740 SkScalar ks,
741 SkScalar shininess,
742 BoundaryMode boundaryMode,
743 const SkIRect* srcBounds,
744 const GrCaps&);
745
746 explicit SpecularLightingEffect(const SpecularLightingEffect&);
747
748 GR_DECLARE_FRAGMENT_PROCESSOR_TEST
749 SkScalar fKS;
750 SkScalar fShininess;
751
752 using INHERITED = LightingEffect;
753 };
754
755 ///////////////////////////////////////////////////////////////////////////////
756
757 class GpuLight {
758 public:
759 virtual ~GpuLight() = default;
760
761 /**
762 * This is called by GrGLLightingEffect::emitCode() before either of the two virtual functions
763 * below. It adds a half3 uniform visible in the FS that represents the constant light color.
764 */
765 void emitLightColorUniform(const GrFragmentProcessor*, GrGLSLUniformHandler*);
766
767 /**
768 * These two functions are called from GrGLLightingEffect's emitCode() function.
769 * emitSurfaceToLight places an expression in param out that is the vector from the surface to
770 * the light. The expression will be used in the FS. emitLightColor writes an expression into
771 * the FS that is the color of the light. Either function may add functions and/or uniforms to
772 * the FS. The default of emitLightColor appends the name of the constant light color uniform
773 * and so this function only needs to be overridden if the light color varies spatially.
774 */
775 virtual void emitSurfaceToLight(const GrFragmentProcessor*,
776 GrGLSLUniformHandler*,
777 GrGLSLFPFragmentBuilder*,
778 const char* z) = 0;
779 virtual void emitLightColor(const GrFragmentProcessor*,
780 GrGLSLUniformHandler*,
781 GrGLSLFPFragmentBuilder*,
782 const char *surfaceToLight);
783
784 // This is called from GrGLLightingEffect's setData(). Subclasses of GrGLLight must call
785 // INHERITED::setData().
786 virtual void setData(const GrGLSLProgramDataManager&, const SkImageFilterLight* light) const;
787
788 protected:
789 /**
790 * Gets the constant light color uniform. Subclasses can use this in their emitLightColor
791 * function.
792 */
lightColorUni() const793 UniformHandle lightColorUni() const { return fColorUni; }
794
795 private:
796 UniformHandle fColorUni;
797
798 using INHERITED = SkRefCnt;
799 };
800
801 ///////////////////////////////////////////////////////////////////////////////
802
803 class GpuDistantLight : public GpuLight {
804 public:
805 void setData(const GrGLSLProgramDataManager&, const SkImageFilterLight* light) const override;
806 void emitSurfaceToLight(const GrFragmentProcessor*, GrGLSLUniformHandler*,
807 GrGLSLFPFragmentBuilder*, const char* z) override;
808
809 private:
810 using INHERITED = GpuLight;
811 UniformHandle fDirectionUni;
812 };
813
814 ///////////////////////////////////////////////////////////////////////////////
815
816 class GpuPointLight : public GpuLight {
817 public:
818 void setData(const GrGLSLProgramDataManager&, const SkImageFilterLight* light) const override;
819 void emitSurfaceToLight(const GrFragmentProcessor*, GrGLSLUniformHandler*,
820 GrGLSLFPFragmentBuilder*, const char* z) override;
821
822 private:
823 using INHERITED = GpuLight;
824 UniformHandle fLocationUni;
825 };
826
827 ///////////////////////////////////////////////////////////////////////////////
828
829 class GpuSpotLight : public GpuLight {
830 public:
831 void setData(const GrGLSLProgramDataManager&, const SkImageFilterLight* light) const override;
832 void emitSurfaceToLight(const GrFragmentProcessor*, GrGLSLUniformHandler*,
833 GrGLSLFPFragmentBuilder*, const char* z) override;
834 void emitLightColor(const GrFragmentProcessor*,
835 GrGLSLUniformHandler*,
836 GrGLSLFPFragmentBuilder*,
837 const char *surfaceToLight) override;
838
839 private:
840 using INHERITED = GpuLight;
841
842 SkString fLightColorFunc;
843 UniformHandle fLocationUni;
844 UniformHandle fExponentUni;
845 UniformHandle fCosOuterConeAngleUni;
846 UniformHandle fCosInnerConeAngleUni;
847 UniformHandle fConeScaleUni;
848 UniformHandle fSUni;
849 };
850
851 #else
852
853 class GpuLight {};
854
855 #endif
856
857 ///////////////////////////////////////////////////////////////////////////////
858
859 class SkDistantLight : public SkImageFilterLight {
860 public:
SkDistantLight(const SkPoint3 & direction,SkColor color)861 SkDistantLight(const SkPoint3& direction, SkColor color)
862 : INHERITED(color), fDirection(direction) {
863 }
864
surfaceToLight(int x,int y,int z,SkScalar surfaceScale) const865 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const override {
866 return fDirection;
867 }
lightColor(const SkPoint3 &) const868 SkPoint3 lightColor(const SkPoint3&) const override { return this->color(); }
type() const869 LightType type() const override { return kDistant_LightType; }
direction() const870 const SkPoint3& direction() const { return fDirection; }
createGpuLight() const871 std::unique_ptr<GpuLight> createGpuLight() const override {
872 #if SK_SUPPORT_GPU
873 return std::make_unique<GpuDistantLight>();
874 #else
875 SkDEBUGFAIL("Should not call in GPU-less build");
876 return nullptr;
877 #endif
878 }
879
isEqual(const SkImageFilterLight & other) const880 bool isEqual(const SkImageFilterLight& other) const override {
881 if (other.type() != kDistant_LightType) {
882 return false;
883 }
884
885 const SkDistantLight& o = static_cast<const SkDistantLight&>(other);
886 return INHERITED::isEqual(other) &&
887 fDirection == o.fDirection;
888 }
889
SkDistantLight(SkReadBuffer & buffer)890 SkDistantLight(SkReadBuffer& buffer) : INHERITED(buffer) {
891 fDirection = read_point3(buffer);
892 }
893
894 protected:
SkDistantLight(const SkPoint3 & direction,const SkPoint3 & color)895 SkDistantLight(const SkPoint3& direction, const SkPoint3& color)
896 : INHERITED(color), fDirection(direction) {
897 }
transform(const SkMatrix & matrix) const898 SkImageFilterLight* transform(const SkMatrix& matrix) const override {
899 return new SkDistantLight(direction(), color());
900 }
onFlattenLight(SkWriteBuffer & buffer) const901 void onFlattenLight(SkWriteBuffer& buffer) const override {
902 write_point3(fDirection, buffer);
903 }
904
905 private:
906 SkPoint3 fDirection;
907
908 using INHERITED = SkImageFilterLight;
909 };
910
911 ///////////////////////////////////////////////////////////////////////////////
912
913 class SkPointLight : public SkImageFilterLight {
914 public:
SkPointLight(const SkPoint3 & location,SkColor color)915 SkPointLight(const SkPoint3& location, SkColor color)
916 : INHERITED(color), fLocation(location) {}
917
surfaceToLight(int x,int y,int z,SkScalar surfaceScale) const918 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const override {
919 SkPoint3 direction = SkPoint3::Make(fLocation.fX - SkIntToScalar(x),
920 fLocation.fY - SkIntToScalar(y),
921 fLocation.fZ - SkIntToScalar(z) * surfaceScale);
922 fast_normalize(&direction);
923 return direction;
924 }
lightColor(const SkPoint3 &) const925 SkPoint3 lightColor(const SkPoint3&) const override { return this->color(); }
type() const926 LightType type() const override { return kPoint_LightType; }
location() const927 const SkPoint3& location() const { return fLocation; }
createGpuLight() const928 std::unique_ptr<GpuLight> createGpuLight() const override {
929 #if SK_SUPPORT_GPU
930 return std::make_unique<GpuPointLight>();
931 #else
932 SkDEBUGFAIL("Should not call in GPU-less build");
933 return nullptr;
934 #endif
935 }
936
isEqual(const SkImageFilterLight & other) const937 bool isEqual(const SkImageFilterLight& other) const override {
938 if (other.type() != kPoint_LightType) {
939 return false;
940 }
941 const SkPointLight& o = static_cast<const SkPointLight&>(other);
942 return INHERITED::isEqual(other) &&
943 fLocation == o.fLocation;
944 }
transform(const SkMatrix & matrix) const945 SkImageFilterLight* transform(const SkMatrix& matrix) const override {
946 SkPoint location2 = SkPoint::Make(fLocation.fX, fLocation.fY);
947 matrix.mapPoints(&location2, 1);
948 // Use X scale and Y scale on Z and average the result
949 SkPoint locationZ = SkPoint::Make(fLocation.fZ, fLocation.fZ);
950 matrix.mapVectors(&locationZ, 1);
951 SkPoint3 location = SkPoint3::Make(location2.fX,
952 location2.fY,
953 SkScalarAve(locationZ.fX, locationZ.fY));
954 return new SkPointLight(location, color());
955 }
956
SkPointLight(SkReadBuffer & buffer)957 SkPointLight(SkReadBuffer& buffer) : INHERITED(buffer) {
958 fLocation = read_point3(buffer);
959 }
960
961 protected:
SkPointLight(const SkPoint3 & location,const SkPoint3 & color)962 SkPointLight(const SkPoint3& location, const SkPoint3& color)
963 : INHERITED(color), fLocation(location) {}
onFlattenLight(SkWriteBuffer & buffer) const964 void onFlattenLight(SkWriteBuffer& buffer) const override {
965 write_point3(fLocation, buffer);
966 }
967
968 private:
969 SkPoint3 fLocation;
970
971 using INHERITED = SkImageFilterLight;
972 };
973
974 ///////////////////////////////////////////////////////////////////////////////
975
976 class SkSpotLight : public SkImageFilterLight {
977 public:
SkSpotLight(const SkPoint3 & location,const SkPoint3 & target,SkScalar specularExponent,SkScalar cutoffAngle,SkColor color)978 SkSpotLight(const SkPoint3& location,
979 const SkPoint3& target,
980 SkScalar specularExponent,
981 SkScalar cutoffAngle,
982 SkColor color)
983 : INHERITED(color),
984 fLocation(location),
985 fTarget(target),
986 fSpecularExponent(specularExponent)
987 {
988 fS = target - location;
989 fast_normalize(&fS);
990 fCosOuterConeAngle = SkScalarCos(SkDegreesToRadians(cutoffAngle));
991 const SkScalar antiAliasThreshold = 0.016f;
992 fCosInnerConeAngle = fCosOuterConeAngle + antiAliasThreshold;
993 fConeScale = SkScalarInvert(antiAliasThreshold);
994 }
995
transform(const SkMatrix & matrix) const996 SkImageFilterLight* transform(const SkMatrix& matrix) const override {
997 SkPoint location2 = SkPoint::Make(fLocation.fX, fLocation.fY);
998 matrix.mapPoints(&location2, 1);
999 // Use X scale and Y scale on Z and average the result
1000 SkPoint locationZ = SkPoint::Make(fLocation.fZ, fLocation.fZ);
1001 matrix.mapVectors(&locationZ, 1);
1002 SkPoint3 location = SkPoint3::Make(location2.fX, location2.fY,
1003 SkScalarAve(locationZ.fX, locationZ.fY));
1004 SkPoint target2 = SkPoint::Make(fTarget.fX, fTarget.fY);
1005 matrix.mapPoints(&target2, 1);
1006 SkPoint targetZ = SkPoint::Make(fTarget.fZ, fTarget.fZ);
1007 matrix.mapVectors(&targetZ, 1);
1008 SkPoint3 target = SkPoint3::Make(target2.fX, target2.fY,
1009 SkScalarAve(targetZ.fX, targetZ.fY));
1010 SkPoint3 s = target - location;
1011 fast_normalize(&s);
1012 return new SkSpotLight(location,
1013 target,
1014 fSpecularExponent,
1015 fCosOuterConeAngle,
1016 fCosInnerConeAngle,
1017 fConeScale,
1018 s,
1019 color());
1020 }
1021
surfaceToLight(int x,int y,int z,SkScalar surfaceScale) const1022 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const override {
1023 SkPoint3 direction = SkPoint3::Make(fLocation.fX - SkIntToScalar(x),
1024 fLocation.fY - SkIntToScalar(y),
1025 fLocation.fZ - SkIntToScalar(z) * surfaceScale);
1026 fast_normalize(&direction);
1027 return direction;
1028 }
lightColor(const SkPoint3 & surfaceToLight) const1029 SkPoint3 lightColor(const SkPoint3& surfaceToLight) const override {
1030 SkScalar cosAngle = -surfaceToLight.dot(fS);
1031 SkScalar scale = 0;
1032 if (cosAngle >= fCosOuterConeAngle) {
1033 scale = SkScalarPow(cosAngle, fSpecularExponent);
1034 if (cosAngle < fCosInnerConeAngle) {
1035 scale *= (cosAngle - fCosOuterConeAngle) * fConeScale;
1036 }
1037 }
1038 return this->color().makeScale(scale);
1039 }
createGpuLight() const1040 std::unique_ptr<GpuLight> createGpuLight() const override {
1041 #if SK_SUPPORT_GPU
1042 return std::make_unique<GpuSpotLight>();
1043 #else
1044 SkDEBUGFAIL("Should not call in GPU-less build");
1045 return nullptr;
1046 #endif
1047 }
type() const1048 LightType type() const override { return kSpot_LightType; }
location() const1049 const SkPoint3& location() const { return fLocation; }
target() const1050 const SkPoint3& target() const { return fTarget; }
specularExponent() const1051 SkScalar specularExponent() const { return fSpecularExponent; }
cosInnerConeAngle() const1052 SkScalar cosInnerConeAngle() const { return fCosInnerConeAngle; }
cosOuterConeAngle() const1053 SkScalar cosOuterConeAngle() const { return fCosOuterConeAngle; }
coneScale() const1054 SkScalar coneScale() const { return fConeScale; }
s() const1055 const SkPoint3& s() const { return fS; }
1056
SkSpotLight(SkReadBuffer & buffer)1057 SkSpotLight(SkReadBuffer& buffer) : INHERITED(buffer) {
1058 fLocation = read_point3(buffer);
1059 fTarget = read_point3(buffer);
1060 fSpecularExponent = buffer.readScalar();
1061 fCosOuterConeAngle = buffer.readScalar();
1062 fCosInnerConeAngle = buffer.readScalar();
1063 fConeScale = buffer.readScalar();
1064 fS = read_point3(buffer);
1065 buffer.validate(SkScalarIsFinite(fSpecularExponent) &&
1066 SkScalarIsFinite(fCosOuterConeAngle) &&
1067 SkScalarIsFinite(fCosInnerConeAngle) &&
1068 SkScalarIsFinite(fConeScale));
1069 }
1070 protected:
SkSpotLight(const SkPoint3 & location,const SkPoint3 & target,SkScalar specularExponent,SkScalar cosOuterConeAngle,SkScalar cosInnerConeAngle,SkScalar coneScale,const SkPoint3 & s,const SkPoint3 & color)1071 SkSpotLight(const SkPoint3& location,
1072 const SkPoint3& target,
1073 SkScalar specularExponent,
1074 SkScalar cosOuterConeAngle,
1075 SkScalar cosInnerConeAngle,
1076 SkScalar coneScale,
1077 const SkPoint3& s,
1078 const SkPoint3& color)
1079 : INHERITED(color),
1080 fLocation(location),
1081 fTarget(target),
1082 fSpecularExponent(specularExponent),
1083 fCosOuterConeAngle(cosOuterConeAngle),
1084 fCosInnerConeAngle(cosInnerConeAngle),
1085 fConeScale(coneScale),
1086 fS(s)
1087 {
1088 }
onFlattenLight(SkWriteBuffer & buffer) const1089 void onFlattenLight(SkWriteBuffer& buffer) const override {
1090 write_point3(fLocation, buffer);
1091 write_point3(fTarget, buffer);
1092 buffer.writeScalar(fSpecularExponent);
1093 buffer.writeScalar(fCosOuterConeAngle);
1094 buffer.writeScalar(fCosInnerConeAngle);
1095 buffer.writeScalar(fConeScale);
1096 write_point3(fS, buffer);
1097 }
1098
isEqual(const SkImageFilterLight & other) const1099 bool isEqual(const SkImageFilterLight& other) const override {
1100 if (other.type() != kSpot_LightType) {
1101 return false;
1102 }
1103
1104 const SkSpotLight& o = static_cast<const SkSpotLight&>(other);
1105 return INHERITED::isEqual(other) &&
1106 fLocation == o.fLocation &&
1107 fTarget == o.fTarget &&
1108 fSpecularExponent == o.fSpecularExponent &&
1109 fCosOuterConeAngle == o.fCosOuterConeAngle;
1110 }
1111
1112 private:
1113 SkPoint3 fLocation;
1114 SkPoint3 fTarget;
1115 SkScalar fSpecularExponent;
1116 SkScalar fCosOuterConeAngle;
1117 SkScalar fCosInnerConeAngle;
1118 SkScalar fConeScale;
1119 SkPoint3 fS;
1120
1121 using INHERITED = SkImageFilterLight;
1122 };
1123 } // anonymous namespace
1124
1125 ///////////////////////////////////////////////////////////////////////////////
1126
flattenLight(SkWriteBuffer & buffer) const1127 void SkImageFilterLight::flattenLight(SkWriteBuffer& buffer) const {
1128 // Write type first, then baseclass, then subclass.
1129 buffer.writeInt(this->type());
1130 write_point3(fColor, buffer);
1131 this->onFlattenLight(buffer);
1132 }
1133
UnflattenLight(SkReadBuffer & buffer)1134 /*static*/ SkImageFilterLight* SkImageFilterLight::UnflattenLight(SkReadBuffer& buffer) {
1135 SkImageFilterLight::LightType type = buffer.read32LE(SkImageFilterLight::kLast_LightType);
1136
1137 switch (type) {
1138 // Each of these constructors must first call SkLight's, so we'll read the baseclass
1139 // then subclass, same order as flattenLight.
1140 case SkImageFilterLight::kDistant_LightType:
1141 return new SkDistantLight(buffer);
1142 case SkImageFilterLight::kPoint_LightType:
1143 return new SkPointLight(buffer);
1144 case SkImageFilterLight::kSpot_LightType:
1145 return new SkSpotLight(buffer);
1146 default:
1147 // Should never get here due to prior check of SkSafeRange
1148 SkDEBUGFAIL("Unknown LightType.");
1149 return nullptr;
1150 }
1151 }
1152 ///////////////////////////////////////////////////////////////////////////////
1153
DistantLitDiffuse(const SkPoint3 & direction,SkColor lightColor,SkScalar surfaceScale,SkScalar kd,sk_sp<SkImageFilter> input,const CropRect & cropRect)1154 sk_sp<SkImageFilter> SkImageFilters::DistantLitDiffuse(
1155 const SkPoint3& direction, SkColor lightColor, SkScalar surfaceScale, SkScalar kd,
1156 sk_sp<SkImageFilter> input, const CropRect& cropRect) {
1157 sk_sp<SkImageFilterLight> light(new SkDistantLight(direction, lightColor));
1158 return SkDiffuseLightingImageFilter::Make(std::move(light), surfaceScale, kd,
1159 std::move(input), cropRect);
1160 }
1161
PointLitDiffuse(const SkPoint3 & location,SkColor lightColor,SkScalar surfaceScale,SkScalar kd,sk_sp<SkImageFilter> input,const CropRect & cropRect)1162 sk_sp<SkImageFilter> SkImageFilters::PointLitDiffuse(
1163 const SkPoint3& location, SkColor lightColor, SkScalar surfaceScale, SkScalar kd,
1164 sk_sp<SkImageFilter> input, const CropRect& cropRect) {
1165 sk_sp<SkImageFilterLight> light(new SkPointLight(location, lightColor));
1166 return SkDiffuseLightingImageFilter::Make(std::move(light), surfaceScale, kd,
1167 std::move(input), cropRect);
1168 }
1169
SpotLitDiffuse(const SkPoint3 & location,const SkPoint3 & target,SkScalar falloffExponent,SkScalar cutoffAngle,SkColor lightColor,SkScalar surfaceScale,SkScalar kd,sk_sp<SkImageFilter> input,const CropRect & cropRect)1170 sk_sp<SkImageFilter> SkImageFilters::SpotLitDiffuse(
1171 const SkPoint3& location, const SkPoint3& target, SkScalar falloffExponent,
1172 SkScalar cutoffAngle, SkColor lightColor, SkScalar surfaceScale, SkScalar kd,
1173 sk_sp<SkImageFilter> input, const CropRect& cropRect) {
1174 sk_sp<SkImageFilterLight> light(new SkSpotLight(location, target, falloffExponent,
1175 cutoffAngle, lightColor));
1176 return SkDiffuseLightingImageFilter::Make(std::move(light), surfaceScale, kd,
1177 std::move(input), cropRect);
1178 }
1179
DistantLitSpecular(const SkPoint3 & direction,SkColor lightColor,SkScalar surfaceScale,SkScalar ks,SkScalar shininess,sk_sp<SkImageFilter> input,const CropRect & cropRect)1180 sk_sp<SkImageFilter> SkImageFilters::DistantLitSpecular(
1181 const SkPoint3& direction, SkColor lightColor, SkScalar surfaceScale, SkScalar ks,
1182 SkScalar shininess, sk_sp<SkImageFilter> input, const CropRect& cropRect) {
1183 sk_sp<SkImageFilterLight> light(new SkDistantLight(direction, lightColor));
1184 return SkSpecularLightingImageFilter::Make(std::move(light), surfaceScale, ks, shininess,
1185 std::move(input), cropRect);
1186 }
1187
PointLitSpecular(const SkPoint3 & location,SkColor lightColor,SkScalar surfaceScale,SkScalar ks,SkScalar shininess,sk_sp<SkImageFilter> input,const CropRect & cropRect)1188 sk_sp<SkImageFilter> SkImageFilters::PointLitSpecular(
1189 const SkPoint3& location, SkColor lightColor, SkScalar surfaceScale, SkScalar ks,
1190 SkScalar shininess, sk_sp<SkImageFilter> input, const CropRect& cropRect) {
1191 sk_sp<SkImageFilterLight> light(new SkPointLight(location, lightColor));
1192 return SkSpecularLightingImageFilter::Make(std::move(light), surfaceScale, ks, shininess,
1193 std::move(input), cropRect);
1194 }
1195
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)1196 sk_sp<SkImageFilter> SkImageFilters::SpotLitSpecular(
1197 const SkPoint3& location, const SkPoint3& target, SkScalar falloffExponent,
1198 SkScalar cutoffAngle, SkColor lightColor, SkScalar surfaceScale, SkScalar ks,
1199 SkScalar shininess, sk_sp<SkImageFilter> input, const CropRect& cropRect) {
1200 sk_sp<SkImageFilterLight> light(new SkSpotLight(location, target, falloffExponent,
1201 cutoffAngle, lightColor));
1202 return SkSpecularLightingImageFilter::Make(std::move(light), surfaceScale, ks, shininess,
1203 std::move(input), cropRect);
1204 }
1205
SkRegisterLightingImageFilterFlattenables()1206 void SkRegisterLightingImageFilterFlattenables() {
1207 SK_REGISTER_FLATTENABLE(SkDiffuseLightingImageFilter);
1208 SK_REGISTER_FLATTENABLE(SkSpecularLightingImageFilter);
1209 }
1210
1211 ///////////////////////////////////////////////////////////////////////////////
1212
Make(sk_sp<SkImageFilterLight> light,SkScalar surfaceScale,SkScalar kd,sk_sp<SkImageFilter> input,const SkRect * cropRect)1213 sk_sp<SkImageFilter> SkDiffuseLightingImageFilter::Make(sk_sp<SkImageFilterLight> light,
1214 SkScalar surfaceScale,
1215 SkScalar kd,
1216 sk_sp<SkImageFilter> input,
1217 const SkRect* cropRect) {
1218 if (!light) {
1219 return nullptr;
1220 }
1221 if (!SkScalarIsFinite(surfaceScale) || !SkScalarIsFinite(kd)) {
1222 return nullptr;
1223 }
1224 // According to the spec, kd can be any non-negative number :
1225 // http://www.w3.org/TR/SVG/filters.html#feDiffuseLightingElement
1226 if (kd < 0) {
1227 return nullptr;
1228 }
1229 return sk_sp<SkImageFilter>(new SkDiffuseLightingImageFilter(std::move(light), surfaceScale,
1230 kd, std::move(input), cropRect));
1231 }
1232
SkDiffuseLightingImageFilter(sk_sp<SkImageFilterLight> light,SkScalar surfaceScale,SkScalar kd,sk_sp<SkImageFilter> input,const SkRect * cropRect)1233 SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(sk_sp<SkImageFilterLight> light,
1234 SkScalar surfaceScale,
1235 SkScalar kd,
1236 sk_sp<SkImageFilter> input,
1237 const SkRect* cropRect)
1238 : INHERITED(std::move(light), surfaceScale, std::move(input), cropRect)
1239 , fKD(kd) {
1240 }
1241
CreateProc(SkReadBuffer & buffer)1242 sk_sp<SkFlattenable> SkDiffuseLightingImageFilter::CreateProc(SkReadBuffer& buffer) {
1243 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
1244
1245 sk_sp<SkImageFilterLight> light(SkImageFilterLight::UnflattenLight(buffer));
1246 SkScalar surfaceScale = buffer.readScalar();
1247 SkScalar kd = buffer.readScalar();
1248
1249 return Make(std::move(light), surfaceScale, kd, common.getInput(0), common.cropRect());
1250 }
1251
flatten(SkWriteBuffer & buffer) const1252 void SkDiffuseLightingImageFilter::flatten(SkWriteBuffer& buffer) const {
1253 this->INHERITED::flatten(buffer);
1254 buffer.writeScalar(fKD);
1255 }
1256
onFilterImage(const Context & ctx,SkIPoint * offset) const1257 sk_sp<SkSpecialImage> SkDiffuseLightingImageFilter::onFilterImage(const Context& ctx,
1258 SkIPoint* offset) const {
1259 SkIPoint inputOffset = SkIPoint::Make(0, 0);
1260 sk_sp<SkSpecialImage> input(this->filterInput(0, ctx, &inputOffset));
1261 if (!input) {
1262 return nullptr;
1263 }
1264
1265 const SkIRect inputBounds = SkIRect::MakeXYWH(inputOffset.x(), inputOffset.y(),
1266 input->width(), input->height());
1267 SkIRect bounds;
1268 if (!this->applyCropRect(ctx, inputBounds, &bounds)) {
1269 return nullptr;
1270 }
1271
1272 offset->fX = bounds.left();
1273 offset->fY = bounds.top();
1274 bounds.offset(-inputOffset);
1275
1276 #if SK_SUPPORT_GPU
1277 if (ctx.gpuBacked()) {
1278 SkMatrix matrix(ctx.ctm());
1279 matrix.postTranslate(SkIntToScalar(-offset->fX), SkIntToScalar(-offset->fY));
1280
1281 return this->filterImageGPU(ctx, input.get(), bounds, matrix);
1282 }
1283 #endif
1284
1285 if (bounds.width() < 2 || bounds.height() < 2) {
1286 return nullptr;
1287 }
1288
1289 SkBitmap inputBM;
1290
1291 if (!input->getROPixels(&inputBM)) {
1292 return nullptr;
1293 }
1294
1295 if (inputBM.colorType() != kN32_SkColorType) {
1296 return nullptr;
1297 }
1298
1299 if (!inputBM.getPixels()) {
1300 return nullptr;
1301 }
1302
1303 const SkImageInfo info = SkImageInfo::MakeN32Premul(bounds.width(), bounds.height());
1304
1305 SkBitmap dst;
1306 if (!dst.tryAllocPixels(info)) {
1307 return nullptr;
1308 }
1309
1310 SkMatrix matrix(ctx.ctm());
1311 matrix.postTranslate(SkIntToScalar(-inputOffset.x()), SkIntToScalar(-inputOffset.y()));
1312
1313 sk_sp<SkImageFilterLight> transformedLight(light()->transform(matrix));
1314
1315 DiffuseLightingType lightingType(fKD);
1316 lightBitmap(lightingType,
1317 transformedLight.get(),
1318 inputBM,
1319 &dst,
1320 surfaceScale(),
1321 bounds);
1322
1323 return SkSpecialImage::MakeFromRaster(SkIRect::MakeWH(bounds.width(), bounds.height()),
1324 dst, ctx.surfaceProps());
1325 }
1326
1327 #if SK_SUPPORT_GPU
makeFragmentProcessor(GrSurfaceProxyView view,const SkMatrix & matrix,const SkIRect * srcBounds,BoundaryMode boundaryMode,const GrCaps & caps) const1328 std::unique_ptr<GrFragmentProcessor> SkDiffuseLightingImageFilter::makeFragmentProcessor(
1329 GrSurfaceProxyView view,
1330 const SkMatrix& matrix,
1331 const SkIRect* srcBounds,
1332 BoundaryMode boundaryMode,
1333 const GrCaps& caps) const {
1334 SkScalar scale = this->surfaceScale() * 255;
1335 return DiffuseLightingEffect::Make(std::move(view),
1336 this->refLight(),
1337 scale,
1338 matrix,
1339 this->kd(),
1340 boundaryMode,
1341 srcBounds,
1342 caps);
1343 }
1344 #endif
1345
1346 ///////////////////////////////////////////////////////////////////////////////
1347
Make(sk_sp<SkImageFilterLight> light,SkScalar surfaceScale,SkScalar ks,SkScalar shininess,sk_sp<SkImageFilter> input,const SkRect * cropRect)1348 sk_sp<SkImageFilter> SkSpecularLightingImageFilter::Make(sk_sp<SkImageFilterLight> light,
1349 SkScalar surfaceScale,
1350 SkScalar ks,
1351 SkScalar shininess,
1352 sk_sp<SkImageFilter> input,
1353 const SkRect* cropRect) {
1354 if (!light) {
1355 return nullptr;
1356 }
1357 if (!SkScalarIsFinite(surfaceScale) || !SkScalarIsFinite(ks) || !SkScalarIsFinite(shininess)) {
1358 return nullptr;
1359 }
1360 // According to the spec, ks can be any non-negative number :
1361 // http://www.w3.org/TR/SVG/filters.html#feSpecularLightingElement
1362 if (ks < 0) {
1363 return nullptr;
1364 }
1365 return sk_sp<SkImageFilter>(new SkSpecularLightingImageFilter(std::move(light), surfaceScale,
1366 ks, shininess,
1367 std::move(input), cropRect));
1368 }
1369
SkSpecularLightingImageFilter(sk_sp<SkImageFilterLight> light,SkScalar surfaceScale,SkScalar ks,SkScalar shininess,sk_sp<SkImageFilter> input,const SkRect * cropRect)1370 SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(sk_sp<SkImageFilterLight> light,
1371 SkScalar surfaceScale,
1372 SkScalar ks,
1373 SkScalar shininess,
1374 sk_sp<SkImageFilter> input,
1375 const SkRect* cropRect)
1376 : INHERITED(std::move(light), surfaceScale, std::move(input), cropRect)
1377 , fKS(ks)
1378 , fShininess(shininess) {
1379 }
1380
CreateProc(SkReadBuffer & buffer)1381 sk_sp<SkFlattenable> SkSpecularLightingImageFilter::CreateProc(SkReadBuffer& buffer) {
1382 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
1383 sk_sp<SkImageFilterLight> light(SkImageFilterLight::UnflattenLight(buffer));
1384 SkScalar surfaceScale = buffer.readScalar();
1385 SkScalar ks = buffer.readScalar();
1386 SkScalar shine = buffer.readScalar();
1387
1388 return Make(std::move(light), surfaceScale, ks, shine, common.getInput(0),
1389 common.cropRect());
1390 }
1391
flatten(SkWriteBuffer & buffer) const1392 void SkSpecularLightingImageFilter::flatten(SkWriteBuffer& buffer) const {
1393 this->INHERITED::flatten(buffer);
1394 buffer.writeScalar(fKS);
1395 buffer.writeScalar(fShininess);
1396 }
1397
onFilterImage(const Context & ctx,SkIPoint * offset) const1398 sk_sp<SkSpecialImage> SkSpecularLightingImageFilter::onFilterImage(const Context& ctx,
1399 SkIPoint* offset) const {
1400 SkIPoint inputOffset = SkIPoint::Make(0, 0);
1401 sk_sp<SkSpecialImage> input(this->filterInput(0, ctx, &inputOffset));
1402 if (!input) {
1403 return nullptr;
1404 }
1405
1406 const SkIRect inputBounds = SkIRect::MakeXYWH(inputOffset.x(), inputOffset.y(),
1407 input->width(), input->height());
1408 SkIRect bounds;
1409 if (!this->applyCropRect(ctx, inputBounds, &bounds)) {
1410 return nullptr;
1411 }
1412
1413 offset->fX = bounds.left();
1414 offset->fY = bounds.top();
1415 bounds.offset(-inputOffset);
1416
1417 #if SK_SUPPORT_GPU
1418 if (ctx.gpuBacked()) {
1419 SkMatrix matrix(ctx.ctm());
1420 matrix.postTranslate(SkIntToScalar(-offset->fX), SkIntToScalar(-offset->fY));
1421
1422 return this->filterImageGPU(ctx, input.get(), bounds, matrix);
1423 }
1424 #endif
1425
1426 if (bounds.width() < 2 || bounds.height() < 2) {
1427 return nullptr;
1428 }
1429
1430 SkBitmap inputBM;
1431
1432 if (!input->getROPixels(&inputBM)) {
1433 return nullptr;
1434 }
1435
1436 if (inputBM.colorType() != kN32_SkColorType) {
1437 return nullptr;
1438 }
1439
1440 if (!inputBM.getPixels()) {
1441 return nullptr;
1442 }
1443
1444 const SkImageInfo info = SkImageInfo::MakeN32Premul(bounds.width(), bounds.height());
1445
1446 SkBitmap dst;
1447 if (!dst.tryAllocPixels(info)) {
1448 return nullptr;
1449 }
1450
1451 SpecularLightingType lightingType(fKS, fShininess);
1452
1453 SkMatrix matrix(ctx.ctm());
1454 matrix.postTranslate(SkIntToScalar(-inputOffset.x()), SkIntToScalar(-inputOffset.y()));
1455
1456 sk_sp<SkImageFilterLight> transformedLight(light()->transform(matrix));
1457
1458 lightBitmap(lightingType,
1459 transformedLight.get(),
1460 inputBM,
1461 &dst,
1462 surfaceScale(),
1463 bounds);
1464
1465 return SkSpecialImage::MakeFromRaster(SkIRect::MakeWH(bounds.width(), bounds.height()), dst,
1466 ctx.surfaceProps());
1467 }
1468
1469 #if SK_SUPPORT_GPU
makeFragmentProcessor(GrSurfaceProxyView view,const SkMatrix & matrix,const SkIRect * srcBounds,BoundaryMode boundaryMode,const GrCaps & caps) const1470 std::unique_ptr<GrFragmentProcessor> SkSpecularLightingImageFilter::makeFragmentProcessor(
1471 GrSurfaceProxyView view,
1472 const SkMatrix& matrix,
1473 const SkIRect* srcBounds,
1474 BoundaryMode boundaryMode,
1475 const GrCaps& caps) const {
1476 SkScalar scale = this->surfaceScale() * 255;
1477 return SpecularLightingEffect::Make(std::move(view),
1478 this->refLight(),
1479 scale,
1480 matrix,
1481 this->ks(),
1482 this->shininess(),
1483 boundaryMode,
1484 srcBounds,
1485 caps);
1486 }
1487 #endif
1488
1489 ///////////////////////////////////////////////////////////////////////////////
1490
1491 #if SK_SUPPORT_GPU
1492
emitNormalFunc(BoundaryMode mode,const char * pointToNormalName,const char * sobelFuncName)1493 static SkString emitNormalFunc(BoundaryMode mode,
1494 const char* pointToNormalName,
1495 const char* sobelFuncName) {
1496 SkString result;
1497 switch (mode) {
1498 case kTopLeft_BoundaryMode:
1499 result.printf("return %s(%s(0.0, 0.0, m[4], m[5], m[7], m[8], %g),"
1500 " %s(0.0, 0.0, m[4], m[7], m[5], m[8], %g),"
1501 " surfaceScale);",
1502 pointToNormalName, sobelFuncName, gTwoThirds,
1503 sobelFuncName, gTwoThirds);
1504 break;
1505 case kTop_BoundaryMode:
1506 result.printf("return %s(%s(0.0, 0.0, m[3], m[5], m[6], m[8], %g),"
1507 " %s(0.0, 0.0, m[4], m[7], m[5], m[8], %g),"
1508 " surfaceScale);",
1509 pointToNormalName, sobelFuncName, gOneThird,
1510 sobelFuncName, gOneHalf);
1511 break;
1512 case kTopRight_BoundaryMode:
1513 result.printf("return %s(%s( 0.0, 0.0, m[3], m[4], m[6], m[7], %g),"
1514 " %s(m[3], m[6], m[4], m[7], 0.0, 0.0, %g),"
1515 " surfaceScale);",
1516 pointToNormalName, sobelFuncName, gTwoThirds,
1517 sobelFuncName, gTwoThirds);
1518 break;
1519 case kLeft_BoundaryMode:
1520 result.printf("return %s(%s(m[1], m[2], m[4], m[5], m[7], m[8], %g),"
1521 " %s( 0.0, 0.0, m[1], m[7], m[2], m[8], %g),"
1522 " surfaceScale);",
1523 pointToNormalName, sobelFuncName, gOneHalf,
1524 sobelFuncName, gOneThird);
1525 break;
1526 case kInterior_BoundaryMode:
1527 result.printf("return %s(%s(m[0], m[2], m[3], m[5], m[6], m[8], %g),"
1528 " %s(m[0], m[6], m[1], m[7], m[2], m[8], %g),"
1529 " surfaceScale);",
1530 pointToNormalName, sobelFuncName, gOneQuarter,
1531 sobelFuncName, gOneQuarter);
1532 break;
1533 case kRight_BoundaryMode:
1534 result.printf("return %s(%s(m[0], m[1], m[3], m[4], m[6], m[7], %g),"
1535 " %s(m[0], m[6], m[1], m[7], 0.0, 0.0, %g),"
1536 " surfaceScale);",
1537 pointToNormalName, sobelFuncName, gOneHalf,
1538 sobelFuncName, gOneThird);
1539 break;
1540 case kBottomLeft_BoundaryMode:
1541 result.printf("return %s(%s(m[1], m[2], m[4], m[5], 0.0, 0.0, %g),"
1542 " %s( 0.0, 0.0, m[1], m[4], m[2], m[5], %g),"
1543 " surfaceScale);",
1544 pointToNormalName, sobelFuncName, gTwoThirds,
1545 sobelFuncName, gTwoThirds);
1546 break;
1547 case kBottom_BoundaryMode:
1548 result.printf("return %s(%s(m[0], m[2], m[3], m[5], 0.0, 0.0, %g),"
1549 " %s(m[0], m[3], m[1], m[4], m[2], m[5], %g),"
1550 " surfaceScale);",
1551 pointToNormalName, sobelFuncName, gOneThird,
1552 sobelFuncName, gOneHalf);
1553 break;
1554 case kBottomRight_BoundaryMode:
1555 result.printf("return %s(%s(m[0], m[1], m[3], m[4], 0.0, 0.0, %g),"
1556 " %s(m[0], m[3], m[1], m[4], 0.0, 0.0, %g),"
1557 " surfaceScale);",
1558 pointToNormalName, sobelFuncName, gTwoThirds,
1559 sobelFuncName, gTwoThirds);
1560 break;
1561 default:
1562 SkASSERT(false);
1563 break;
1564 }
1565 return result;
1566 }
1567
1568 namespace {
1569 class LightingEffect::ImplBase : public ProgramImpl {
1570 public:
1571 void emitCode(EmitArgs&) override;
1572
1573 protected:
1574 /**
1575 * Subclasses of LightingImpl must call INHERITED::onSetData();
1576 */
1577 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
1578
1579 virtual void emitLightFunc(const GrFragmentProcessor*,
1580 GrGLSLUniformHandler*,
1581 GrGLSLFPFragmentBuilder*,
1582 SkString* funcName) = 0;
1583
1584 private:
1585 UniformHandle fSurfaceScaleUni;
1586 std::unique_ptr<GpuLight> fLight;
1587 };
1588
1589 ///////////////////////////////////////////////////////////////////////////////
1590
1591 class DiffuseLightingEffect::Impl : public ImplBase {
1592 public:
1593 void emitLightFunc(const GrFragmentProcessor*,
1594 GrGLSLUniformHandler*,
1595 GrGLSLFPFragmentBuilder*,
1596 SkString* funcName) override;
1597
1598 private:
1599 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
1600
1601 using INHERITED = ImplBase;
1602
1603 UniformHandle fKDUni;
1604 };
1605
1606 ///////////////////////////////////////////////////////////////////////////////
1607
1608 class SpecularLightingEffect::Impl : public ImplBase {
1609 public:
1610 void emitLightFunc(const GrFragmentProcessor*,
1611 GrGLSLUniformHandler*,
1612 GrGLSLFPFragmentBuilder*,
1613 SkString* funcName) override;
1614
1615 private:
1616 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
1617
1618 using INHERITED = ImplBase;
1619
1620 UniformHandle fKSUni;
1621 UniformHandle fShininessUni;
1622 };
1623 } // anonymous namespace
1624
1625 ///////////////////////////////////////////////////////////////////////////////
1626
LightingEffect(ClassID classID,GrSurfaceProxyView view,sk_sp<const SkImageFilterLight> light,SkScalar surfaceScale,const SkMatrix & matrix,BoundaryMode boundaryMode,const SkIRect * srcBounds,const GrCaps & caps)1627 LightingEffect::LightingEffect(ClassID classID,
1628 GrSurfaceProxyView view,
1629 sk_sp<const SkImageFilterLight> light,
1630 SkScalar surfaceScale,
1631 const SkMatrix& matrix,
1632 BoundaryMode boundaryMode,
1633 const SkIRect* srcBounds,
1634 const GrCaps& caps)
1635 // Perhaps this could advertise the opaque or coverage-as-alpha optimizations?
1636 : INHERITED(classID, kNone_OptimizationFlags)
1637 , fLight(std::move(light))
1638 , fSurfaceScale(surfaceScale)
1639 , fFilterMatrix(matrix)
1640 , fBoundaryMode(boundaryMode) {
1641 static constexpr GrSamplerState kSampler(GrSamplerState::WrapMode::kClampToBorder,
1642 GrSamplerState::Filter::kNearest);
1643 std::unique_ptr<GrFragmentProcessor> child;
1644 if (srcBounds) {
1645 child = GrTextureEffect::MakeSubset(std::move(view), kPremul_SkAlphaType, SkMatrix::I(),
1646 kSampler, SkRect::Make(*srcBounds), caps);
1647 } else {
1648 child = GrTextureEffect::Make(std::move(view), kPremul_SkAlphaType, SkMatrix::I(), kSampler,
1649 caps);
1650 }
1651 this->registerChild(std::move(child), SkSL::SampleUsage::Explicit());
1652 this->setUsesSampleCoordsDirectly();
1653 }
1654
LightingEffect(const LightingEffect & that)1655 LightingEffect::LightingEffect(const LightingEffect& that)
1656 : INHERITED(that)
1657 , fLight(that.fLight)
1658 , fSurfaceScale(that.fSurfaceScale)
1659 , fFilterMatrix(that.fFilterMatrix)
1660 , fBoundaryMode(that.fBoundaryMode) {}
1661
onIsEqual(const GrFragmentProcessor & sBase) const1662 bool LightingEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
1663 const LightingEffect& s = sBase.cast<LightingEffect>();
1664 return fLight->isEqual(*s.fLight) &&
1665 fSurfaceScale == s.fSurfaceScale &&
1666 fBoundaryMode == s.fBoundaryMode;
1667 }
1668
1669 ///////////////////////////////////////////////////////////////////////////////
1670
DiffuseLightingEffect(GrSurfaceProxyView view,sk_sp<const SkImageFilterLight> light,SkScalar surfaceScale,const SkMatrix & matrix,SkScalar kd,BoundaryMode boundaryMode,const SkIRect * srcBounds,const GrCaps & caps)1671 DiffuseLightingEffect::DiffuseLightingEffect(GrSurfaceProxyView view,
1672 sk_sp<const SkImageFilterLight> light,
1673 SkScalar surfaceScale,
1674 const SkMatrix& matrix,
1675 SkScalar kd,
1676 BoundaryMode boundaryMode,
1677 const SkIRect* srcBounds,
1678 const GrCaps& caps)
1679 : INHERITED(kGrDiffuseLightingEffect_ClassID,
1680 std::move(view),
1681 std::move(light),
1682 surfaceScale,
1683 matrix,
1684 boundaryMode,
1685 srcBounds,
1686 caps)
1687 , fKD(kd) {}
1688
DiffuseLightingEffect(const DiffuseLightingEffect & that)1689 DiffuseLightingEffect::DiffuseLightingEffect(const DiffuseLightingEffect& that)
1690 : INHERITED(that), fKD(that.fKD) {}
1691
onIsEqual(const GrFragmentProcessor & sBase) const1692 bool DiffuseLightingEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
1693 const DiffuseLightingEffect& s = sBase.cast<DiffuseLightingEffect>();
1694 return INHERITED::onIsEqual(sBase) && fKD == s.fKD;
1695 }
1696
onMakeProgramImpl() const1697 std::unique_ptr<GrFragmentProcessor::ProgramImpl> DiffuseLightingEffect::onMakeProgramImpl() const {
1698 return std::make_unique<Impl>();
1699 }
1700
1701 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(DiffuseLightingEffect);
1702
1703 #if GR_TEST_UTILS
1704
random_point3(SkRandom * random)1705 static SkPoint3 random_point3(SkRandom* random) {
1706 return SkPoint3::Make(SkScalarToFloat(random->nextSScalar1()),
1707 SkScalarToFloat(random->nextSScalar1()),
1708 SkScalarToFloat(random->nextSScalar1()));
1709 }
1710
create_random_light(SkRandom * random)1711 static SkImageFilterLight* create_random_light(SkRandom* random) {
1712 int type = random->nextULessThan(3);
1713 switch (type) {
1714 case 0: {
1715 return new SkDistantLight(random_point3(random), random->nextU());
1716 }
1717 case 1: {
1718 return new SkPointLight(random_point3(random), random->nextU());
1719 }
1720 case 2: {
1721 return new SkSpotLight(random_point3(random), random_point3(random),
1722 random->nextUScalar1(), random->nextUScalar1(), random->nextU());
1723 }
1724 default:
1725 SK_ABORT("Unexpected value.");
1726 }
1727 }
1728
TestCreate(GrProcessorTestData * d)1729 std::unique_ptr<GrFragmentProcessor> DiffuseLightingEffect::TestCreate(GrProcessorTestData* d) {
1730 auto [view, ct, at] = d->randomView();
1731 SkScalar surfaceScale = d->fRandom->nextSScalar1();
1732 SkScalar kd = d->fRandom->nextUScalar1();
1733 sk_sp<SkImageFilterLight> light(create_random_light(d->fRandom));
1734 SkMatrix matrix;
1735 for (int i = 0; i < 9; i++) {
1736 matrix[i] = d->fRandom->nextUScalar1();
1737 }
1738
1739 uint32_t boundsX = d->fRandom->nextRangeU(0, view.width());
1740 uint32_t boundsY = d->fRandom->nextRangeU(0, view.height());
1741 uint32_t boundsW = d->fRandom->nextRangeU(0, view.width());
1742 uint32_t boundsH = d->fRandom->nextRangeU(0, view.height());
1743 SkIRect srcBounds = SkIRect::MakeXYWH(boundsX, boundsY, boundsW, boundsH);
1744 BoundaryMode mode = static_cast<BoundaryMode>(d->fRandom->nextU() % kBoundaryModeCount);
1745
1746 return DiffuseLightingEffect::Make(std::move(view),
1747 std::move(light),
1748 surfaceScale,
1749 matrix,
1750 kd,
1751 mode,
1752 &srcBounds,
1753 *d->caps());
1754 }
1755 #endif
1756
1757
1758 ///////////////////////////////////////////////////////////////////////////////
1759
emitCode(EmitArgs & args)1760 void LightingEffect::ImplBase::emitCode(EmitArgs& args) {
1761 const LightingEffect& le = args.fFp.cast<LightingEffect>();
1762 if (!fLight) {
1763 fLight = le.light()->createGpuLight();
1764 }
1765
1766 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
1767 fSurfaceScaleUni = uniformHandler->addUniform(&le,
1768 kFragment_GrShaderFlag,
1769 kHalf_GrSLType, "SurfaceScale");
1770 fLight->emitLightColorUniform(&le, uniformHandler);
1771 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
1772 SkString lightFunc;
1773 this->emitLightFunc(&le, uniformHandler, fragBuilder, &lightFunc);
1774 const GrShaderVar gSobelArgs[] = {
1775 GrShaderVar("a", kHalf_GrSLType),
1776 GrShaderVar("b", kHalf_GrSLType),
1777 GrShaderVar("c", kHalf_GrSLType),
1778 GrShaderVar("d", kHalf_GrSLType),
1779 GrShaderVar("e", kHalf_GrSLType),
1780 GrShaderVar("f", kHalf_GrSLType),
1781 GrShaderVar("scale", kHalf_GrSLType),
1782 };
1783
1784 SkString sobelFuncName = fragBuilder->getMangledFunctionName("sobel");
1785 fragBuilder->emitFunction(kHalf_GrSLType,
1786 sobelFuncName.c_str(),
1787 {gSobelArgs, SK_ARRAY_COUNT(gSobelArgs)},
1788 "return (-a + b - 2.0 * c + 2.0 * d -e + f) * scale;");
1789 const GrShaderVar gPointToNormalArgs[] = {
1790 GrShaderVar("x", kHalf_GrSLType),
1791 GrShaderVar("y", kHalf_GrSLType),
1792 GrShaderVar("scale", kHalf_GrSLType),
1793 };
1794 SkString pointToNormalName = fragBuilder->getMangledFunctionName("pointToNormal");
1795 fragBuilder->emitFunction(kHalf3_GrSLType,
1796 pointToNormalName.c_str(),
1797 {gPointToNormalArgs, SK_ARRAY_COUNT(gPointToNormalArgs)},
1798 "return normalize(half3(-x * scale, -y * scale, 1));");
1799
1800 const GrShaderVar gInteriorNormalArgs[] = {
1801 GrShaderVar("m", kHalf_GrSLType, 9),
1802 GrShaderVar("surfaceScale", kHalf_GrSLType),
1803 };
1804 SkString normalBody = emitNormalFunc(le.boundaryMode(),
1805 pointToNormalName.c_str(),
1806 sobelFuncName.c_str());
1807 SkString normalName = fragBuilder->getMangledFunctionName("normal");
1808 fragBuilder->emitFunction(kHalf3_GrSLType,
1809 normalName.c_str(),
1810 {gInteriorNormalArgs, SK_ARRAY_COUNT(gInteriorNormalArgs)},
1811 normalBody.c_str());
1812
1813 fragBuilder->codeAppendf("float2 coord = %s;", args.fSampleCoord);
1814 fragBuilder->codeAppend("half m[9];");
1815
1816 const char* surfScale = uniformHandler->getUniformCStr(fSurfaceScaleUni);
1817
1818 int index = 0;
1819 for (int dy = -1; dy <= 1; ++dy) {
1820 for (int dx = -1; dx <= 1; ++dx) {
1821 SkString texCoords;
1822 texCoords.appendf("coord + half2(%d, %d)", dx, dy);
1823 auto sample = this->invokeChild(0, args, texCoords.c_str());
1824 fragBuilder->codeAppendf("m[%d] = %s.a;", index, sample.c_str());
1825 index++;
1826 }
1827 }
1828 fragBuilder->codeAppend("half3 surfaceToLight = ");
1829 SkString arg;
1830 arg.appendf("%s * m[4]", surfScale);
1831 fLight->emitSurfaceToLight(&le, uniformHandler, fragBuilder, arg.c_str());
1832 fragBuilder->codeAppend(";");
1833 fragBuilder->codeAppendf("return %s(%s(m, %s), surfaceToLight, ",
1834 lightFunc.c_str(), normalName.c_str(), surfScale);
1835 fLight->emitLightColor(&le, uniformHandler, fragBuilder, "surfaceToLight");
1836 fragBuilder->codeAppend(");");
1837 }
1838
onSetData(const GrGLSLProgramDataManager & pdman,const GrFragmentProcessor & proc)1839 void LightingEffect::ImplBase::onSetData(const GrGLSLProgramDataManager& pdman,
1840 const GrFragmentProcessor& proc) {
1841 const LightingEffect& lighting = proc.cast<LightingEffect>();
1842 if (!fLight) {
1843 fLight = lighting.light()->createGpuLight();
1844 }
1845
1846 pdman.set1f(fSurfaceScaleUni, lighting.surfaceScale());
1847 sk_sp<SkImageFilterLight> transformedLight(
1848 lighting.light()->transform(lighting.filterMatrix()));
1849 fLight->setData(pdman, transformedLight.get());
1850 }
1851
1852 ///////////////////////////////////////////////////////////////////////////////
1853
1854 ///////////////////////////////////////////////////////////////////////////////
1855
emitLightFunc(const GrFragmentProcessor * owner,GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,SkString * funcName)1856 void DiffuseLightingEffect::Impl::emitLightFunc(const GrFragmentProcessor* owner,
1857 GrGLSLUniformHandler* uniformHandler,
1858 GrGLSLFPFragmentBuilder* fragBuilder,
1859 SkString* funcName) {
1860 const char* kd;
1861 fKDUni = uniformHandler->addUniform(owner, kFragment_GrShaderFlag, kHalf_GrSLType, "KD", &kd);
1862
1863 const GrShaderVar gLightArgs[] = {
1864 GrShaderVar("normal", kHalf3_GrSLType),
1865 GrShaderVar("surfaceToLight", kHalf3_GrSLType),
1866 GrShaderVar("lightColor", kHalf3_GrSLType)
1867 };
1868 SkString lightBody;
1869 lightBody.appendf("half colorScale = %s * dot(normal, surfaceToLight);", kd);
1870 lightBody.appendf("return half4(saturate(lightColor * colorScale), 1.0);");
1871 *funcName = fragBuilder->getMangledFunctionName("light");
1872 fragBuilder->emitFunction(kHalf4_GrSLType,
1873 funcName->c_str(),
1874 {gLightArgs, SK_ARRAY_COUNT(gLightArgs)},
1875 lightBody.c_str());
1876 }
1877
onSetData(const GrGLSLProgramDataManager & pdman,const GrFragmentProcessor & proc)1878 void DiffuseLightingEffect::Impl::onSetData(const GrGLSLProgramDataManager& pdman,
1879 const GrFragmentProcessor& proc) {
1880 INHERITED::onSetData(pdman, proc);
1881 const DiffuseLightingEffect& diffuse = proc.cast<DiffuseLightingEffect>();
1882 pdman.set1f(fKDUni, diffuse.fKD);
1883 }
1884
1885 ///////////////////////////////////////////////////////////////////////////////
1886
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)1887 SpecularLightingEffect::SpecularLightingEffect(GrSurfaceProxyView view,
1888 sk_sp<const SkImageFilterLight> light,
1889 SkScalar surfaceScale,
1890 const SkMatrix& matrix,
1891 SkScalar ks,
1892 SkScalar shininess,
1893 BoundaryMode boundaryMode,
1894 const SkIRect* srcBounds,
1895 const GrCaps& caps)
1896 : INHERITED(kGrSpecularLightingEffect_ClassID,
1897 std::move(view),
1898 std::move(light),
1899 surfaceScale,
1900 matrix,
1901 boundaryMode,
1902 srcBounds,
1903 caps)
1904 , fKS(ks)
1905 , fShininess(shininess) {}
1906
SpecularLightingEffect(const SpecularLightingEffect & that)1907 SpecularLightingEffect::SpecularLightingEffect(const SpecularLightingEffect& that)
1908 : INHERITED(that), fKS(that.fKS), fShininess(that.fShininess) {}
1909
onIsEqual(const GrFragmentProcessor & sBase) const1910 bool SpecularLightingEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
1911 const SpecularLightingEffect& s = sBase.cast<SpecularLightingEffect>();
1912 return INHERITED::onIsEqual(sBase) && this->fKS == s.fKS && this->fShininess == s.fShininess;
1913 }
1914
1915 std::unique_ptr<GrFragmentProcessor::ProgramImpl>
onMakeProgramImpl() const1916 SpecularLightingEffect::onMakeProgramImpl() const { return std::make_unique<Impl>(); }
1917
1918 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(SpecularLightingEffect);
1919
1920 #if GR_TEST_UTILS
TestCreate(GrProcessorTestData * d)1921 std::unique_ptr<GrFragmentProcessor> SpecularLightingEffect::TestCreate(GrProcessorTestData* d) {
1922 auto [view, ct, at] = d->randomView();
1923 SkScalar surfaceScale = d->fRandom->nextSScalar1();
1924 SkScalar ks = d->fRandom->nextUScalar1();
1925 SkScalar shininess = d->fRandom->nextUScalar1();
1926 sk_sp<SkImageFilterLight> light(create_random_light(d->fRandom));
1927 SkMatrix matrix;
1928 for (int i = 0; i < 9; i++) {
1929 matrix[i] = d->fRandom->nextUScalar1();
1930 }
1931 BoundaryMode mode = static_cast<BoundaryMode>(d->fRandom->nextU() % kBoundaryModeCount);
1932
1933 uint32_t boundsX = d->fRandom->nextRangeU(0, view.width());
1934 uint32_t boundsY = d->fRandom->nextRangeU(0, view.height());
1935 uint32_t boundsW = d->fRandom->nextRangeU(0, view.width());
1936 uint32_t boundsH = d->fRandom->nextRangeU(0, view.height());
1937 SkIRect srcBounds = SkIRect::MakeXYWH(boundsX, boundsY, boundsW, boundsH);
1938
1939 return SpecularLightingEffect::Make(std::move(view),
1940 std::move(light),
1941 surfaceScale,
1942 matrix,
1943 ks,
1944 shininess,
1945 mode,
1946 &srcBounds,
1947 *d->caps());
1948 }
1949 #endif
1950
1951 ///////////////////////////////////////////////////////////////////////////////
1952
emitLightFunc(const GrFragmentProcessor * owner,GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,SkString * funcName)1953 void SpecularLightingEffect::Impl::emitLightFunc(const GrFragmentProcessor* owner,
1954 GrGLSLUniformHandler* uniformHandler,
1955 GrGLSLFPFragmentBuilder* fragBuilder,
1956 SkString* funcName) {
1957 const char* ks;
1958 const char* shininess;
1959
1960 fKSUni = uniformHandler->addUniform(owner, kFragment_GrShaderFlag, kHalf_GrSLType, "KS", &ks);
1961 fShininessUni = uniformHandler->addUniform(owner,
1962 kFragment_GrShaderFlag,
1963 kHalf_GrSLType,
1964 "Shininess",
1965 &shininess);
1966
1967 const GrShaderVar gLightArgs[] = {
1968 GrShaderVar("normal", kHalf3_GrSLType),
1969 GrShaderVar("surfaceToLight", kHalf3_GrSLType),
1970 GrShaderVar("lightColor", kHalf3_GrSLType)
1971 };
1972 SkString lightBody;
1973 lightBody.appendf("half3 halfDir = half3(normalize(surfaceToLight + half3(0, 0, 1)));");
1974 lightBody.appendf("half colorScale = half(%s * pow(dot(normal, halfDir), %s));",
1975 ks, shininess);
1976 lightBody.appendf("half3 color = saturate(lightColor * colorScale);");
1977 lightBody.appendf("return half4(color, max(max(color.r, color.g), color.b));");
1978 *funcName = fragBuilder->getMangledFunctionName("light");
1979 fragBuilder->emitFunction(kHalf4_GrSLType,
1980 funcName->c_str(),
1981 {gLightArgs, SK_ARRAY_COUNT(gLightArgs)},
1982 lightBody.c_str());
1983 }
1984
onSetData(const GrGLSLProgramDataManager & pdman,const GrFragmentProcessor & effect)1985 void SpecularLightingEffect::Impl::onSetData(const GrGLSLProgramDataManager& pdman,
1986 const GrFragmentProcessor& effect) {
1987 INHERITED::onSetData(pdman, effect);
1988 const SpecularLightingEffect& spec = effect.cast<SpecularLightingEffect>();
1989 pdman.set1f(fKSUni, spec.fKS);
1990 pdman.set1f(fShininessUni, spec.fShininess);
1991 }
1992
1993 ///////////////////////////////////////////////////////////////////////////////
emitLightColorUniform(const GrFragmentProcessor * owner,GrGLSLUniformHandler * uniformHandler)1994 void GpuLight::emitLightColorUniform(const GrFragmentProcessor* owner,
1995 GrGLSLUniformHandler* uniformHandler) {
1996 fColorUni = uniformHandler->addUniform(owner, kFragment_GrShaderFlag, kHalf3_GrSLType,
1997 "LightColor");
1998 }
1999
emitLightColor(const GrFragmentProcessor * owner,GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,const char * surfaceToLight)2000 void GpuLight::emitLightColor(const GrFragmentProcessor* owner,
2001 GrGLSLUniformHandler* uniformHandler,
2002 GrGLSLFPFragmentBuilder* fragBuilder,
2003 const char* surfaceToLight) {
2004 fragBuilder->codeAppend(uniformHandler->getUniformCStr(this->lightColorUni()));
2005 }
2006
setData(const GrGLSLProgramDataManager & pdman,const SkImageFilterLight * light) const2007 void GpuLight::setData(const GrGLSLProgramDataManager& pdman,
2008 const SkImageFilterLight* light) const {
2009 setUniformPoint3(pdman, fColorUni,
2010 light->color().makeScale(SkScalarInvert(SkIntToScalar(255))));
2011 }
2012
2013 ///////////////////////////////////////////////////////////////////////////////
2014
setData(const GrGLSLProgramDataManager & pdman,const SkImageFilterLight * light) const2015 void GpuDistantLight::setData(const GrGLSLProgramDataManager& pdman,
2016 const SkImageFilterLight* light) const {
2017 INHERITED::setData(pdman, light);
2018 SkASSERT(light->type() == SkImageFilterLight::kDistant_LightType);
2019 const SkDistantLight* distantLight = static_cast<const SkDistantLight*>(light);
2020 setUniformNormal3(pdman, fDirectionUni, distantLight->direction());
2021 }
2022
emitSurfaceToLight(const GrFragmentProcessor * owner,GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,const char * z)2023 void GpuDistantLight::emitSurfaceToLight(const GrFragmentProcessor* owner,
2024 GrGLSLUniformHandler* uniformHandler,
2025 GrGLSLFPFragmentBuilder* fragBuilder,
2026 const char* z) {
2027 const char* dir;
2028 fDirectionUni = uniformHandler->addUniform(owner, kFragment_GrShaderFlag, kHalf3_GrSLType,
2029 "LightDirection", &dir);
2030 fragBuilder->codeAppend(dir);
2031 }
2032
2033 ///////////////////////////////////////////////////////////////////////////////
2034
setData(const GrGLSLProgramDataManager & pdman,const SkImageFilterLight * light) const2035 void GpuPointLight::setData(const GrGLSLProgramDataManager& pdman,
2036 const SkImageFilterLight* light) const {
2037 INHERITED::setData(pdman, light);
2038 SkASSERT(light->type() == SkImageFilterLight::kPoint_LightType);
2039 const SkPointLight* pointLight = static_cast<const SkPointLight*>(light);
2040 setUniformPoint3(pdman, fLocationUni, pointLight->location());
2041 }
2042
emitSurfaceToLight(const GrFragmentProcessor * owner,GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,const char * z)2043 void GpuPointLight::emitSurfaceToLight(const GrFragmentProcessor* owner,
2044 GrGLSLUniformHandler* uniformHandler,
2045 GrGLSLFPFragmentBuilder* fragBuilder,
2046 const char* z) {
2047 const char* loc;
2048 fLocationUni = uniformHandler->addUniform(owner, kFragment_GrShaderFlag, kHalf3_GrSLType,
2049 "LightLocation", &loc);
2050 fragBuilder->codeAppendf("normalize(%s - half3(sk_FragCoord.xy, %s))",
2051 loc, z);
2052 }
2053
2054 ///////////////////////////////////////////////////////////////////////////////
2055
setData(const GrGLSLProgramDataManager & pdman,const SkImageFilterLight * light) const2056 void GpuSpotLight::setData(const GrGLSLProgramDataManager& pdman,
2057 const SkImageFilterLight* light) const {
2058 INHERITED::setData(pdman, light);
2059 SkASSERT(light->type() == SkImageFilterLight::kSpot_LightType);
2060 const SkSpotLight* spotLight = static_cast<const SkSpotLight *>(light);
2061 setUniformPoint3(pdman, fLocationUni, spotLight->location());
2062 pdman.set1f(fExponentUni, spotLight->specularExponent());
2063 pdman.set1f(fCosInnerConeAngleUni, spotLight->cosInnerConeAngle());
2064 pdman.set1f(fCosOuterConeAngleUni, spotLight->cosOuterConeAngle());
2065 pdman.set1f(fConeScaleUni, spotLight->coneScale());
2066 setUniformNormal3(pdman, fSUni, spotLight->s());
2067 }
2068
emitSurfaceToLight(const GrFragmentProcessor * owner,GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,const char * z)2069 void GpuSpotLight::emitSurfaceToLight(const GrFragmentProcessor* owner,
2070 GrGLSLUniformHandler* uniformHandler,
2071 GrGLSLFPFragmentBuilder* fragBuilder,
2072 const char* z) {
2073 const char* location;
2074 fLocationUni = uniformHandler->addUniform(owner, kFragment_GrShaderFlag, kHalf3_GrSLType,
2075 "LightLocation", &location);
2076
2077 fragBuilder->codeAppendf("normalize(%s - half3(sk_FragCoord.xy, %s))",
2078 location, z);
2079 }
2080
emitLightColor(const GrFragmentProcessor * owner,GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,const char * surfaceToLight)2081 void GpuSpotLight::emitLightColor(const GrFragmentProcessor* owner,
2082 GrGLSLUniformHandler* uniformHandler,
2083 GrGLSLFPFragmentBuilder* fragBuilder,
2084 const char* surfaceToLight) {
2085 const char* color = uniformHandler->getUniformCStr(this->lightColorUni()); // created by parent class.
2086
2087 const char* exponent;
2088 const char* cosInner;
2089 const char* cosOuter;
2090 const char* coneScale;
2091 const char* s;
2092 fExponentUni = uniformHandler->addUniform(owner, kFragment_GrShaderFlag, kHalf_GrSLType,
2093 "Exponent", &exponent);
2094 fCosInnerConeAngleUni = uniformHandler->addUniform(owner, kFragment_GrShaderFlag,
2095 kHalf_GrSLType, "CosInnerConeAngle",
2096 &cosInner);
2097 fCosOuterConeAngleUni = uniformHandler->addUniform(owner, kFragment_GrShaderFlag,
2098 kHalf_GrSLType, "CosOuterConeAngle",
2099 &cosOuter);
2100 fConeScaleUni = uniformHandler->addUniform(owner, kFragment_GrShaderFlag, kHalf_GrSLType,
2101 "ConeScale", &coneScale);
2102 fSUni = uniformHandler->addUniform(owner, kFragment_GrShaderFlag, kHalf3_GrSLType, "S", &s);
2103
2104 const GrShaderVar gLightColorArgs[] = {
2105 GrShaderVar("surfaceToLight", kHalf3_GrSLType)
2106 };
2107 SkString lightColorBody;
2108 lightColorBody.appendf("half cosAngle = -dot(surfaceToLight, %s);", s);
2109 lightColorBody.appendf("if (cosAngle < %s) {", cosOuter);
2110 lightColorBody.appendf("return half3(0);");
2111 lightColorBody.appendf("}");
2112 lightColorBody.appendf("half scale = pow(cosAngle, %s);", exponent);
2113 lightColorBody.appendf("if (cosAngle < %s) {", cosInner);
2114 lightColorBody.appendf("return %s * scale * (cosAngle - %s) * %s;",
2115 color, cosOuter, coneScale);
2116 lightColorBody.appendf("}");
2117 lightColorBody.appendf("return %s * scale;", color);
2118 fLightColorFunc = fragBuilder->getMangledFunctionName("lightColor");
2119 fragBuilder->emitFunction(kHalf3_GrSLType,
2120 fLightColorFunc.c_str(),
2121 {gLightColorArgs, SK_ARRAY_COUNT(gLightColorArgs)},
2122 lightColorBody.c_str());
2123
2124 fragBuilder->codeAppendf("%s(%s)", fLightColorFunc.c_str(), surfaceToLight);
2125 }
2126
2127 #endif
2128