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