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