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 "SkLightingImageFilter.h"
9 #include "SkBitmap.h"
10 #include "SkColorData.h"
11 #include "SkColorSpaceXformer.h"
12 #include "SkImageFilterPriv.h"
13 #include "SkPoint3.h"
14 #include "SkReadBuffer.h"
15 #include "SkSpecialImage.h"
16 #include "SkTypes.h"
17 #include "SkWriteBuffer.h"
18
19 #if SK_SUPPORT_GPU
20 #include "GrContext.h"
21 #include "GrFixedClip.h"
22 #include "GrFragmentProcessor.h"
23 #include "GrPaint.h"
24 #include "GrRenderTargetContext.h"
25 #include "GrTexture.h"
26 #include "GrTextureProxy.h"
27
28 #include "SkGr.h"
29 #include "effects/GrTextureDomain.h"
30 #include "glsl/GrGLSLFragmentProcessor.h"
31 #include "glsl/GrGLSLFragmentShaderBuilder.h"
32 #include "glsl/GrGLSLProgramDataManager.h"
33 #include "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 GR_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 SkScalar scale = sk_float_rsqrt(magSq);
74 vector->fX *= scale;
75 vector->fY *= scale;
76 vector->fZ *= scale;
77 }
78
read_point3(SkReadBuffer & buffer)79 static SkPoint3 read_point3(SkReadBuffer& buffer) {
80 SkPoint3 point;
81 point.fX = buffer.readScalar();
82 point.fY = buffer.readScalar();
83 point.fZ = buffer.readScalar();
84 buffer.validate(SkScalarIsFinite(point.fX) &&
85 SkScalarIsFinite(point.fY) &&
86 SkScalarIsFinite(point.fZ));
87 return point;
88 };
89
write_point3(const SkPoint3 & point,SkWriteBuffer & buffer)90 static void write_point3(const SkPoint3& point, SkWriteBuffer& buffer) {
91 buffer.writeScalar(point.fX);
92 buffer.writeScalar(point.fY);
93 buffer.writeScalar(point.fZ);
94 };
95
96 class GrGLLight;
97 class SkImageFilterLight : public SkRefCnt {
98 public:
99 enum LightType {
100 kDistant_LightType,
101 kPoint_LightType,
102 kSpot_LightType,
103
104 kLast_LightType = kSpot_LightType
105 };
106 virtual LightType type() const = 0;
color() const107 const SkPoint3& color() const { return fColor; }
108 virtual GrGLLight* createGLLight() const = 0;
isEqual(const SkImageFilterLight & other) const109 virtual bool isEqual(const SkImageFilterLight& other) const {
110 return fColor == other.fColor;
111 }
112 virtual SkImageFilterLight* transform(const SkMatrix& matrix) const = 0;
113
114 virtual sk_sp<SkImageFilterLight> makeColorSpace(SkColorSpaceXformer*) 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 SkLightingImageFilter {
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(std::move(light), surfaceScale, std::move(input), cropRect) {
408 }
409
410 #if SK_SUPPORT_GPU
411 sk_sp<SkSpecialImage> filterImageGPU(SkSpecialImage* source,
412 SkSpecialImage* input,
413 const SkIRect& bounds,
414 const SkMatrix& matrix,
415 const OutputProperties& outputProperties) const;
416 virtual std::unique_ptr<GrFragmentProcessor> makeFragmentProcessor(
417 sk_sp<GrTextureProxy>,
418 const SkMatrix&,
419 const SkIRect* srcBounds,
420 BoundaryMode boundaryMode) const = 0;
421 #endif
422 private:
423 #if SK_SUPPORT_GPU
424 void drawRect(GrRenderTargetContext*,
425 sk_sp<GrTextureProxy> srcProxy,
426 const SkMatrix& matrix,
427 const GrClip& clip,
428 const SkRect& dstRect,
429 BoundaryMode boundaryMode,
430 const SkIRect* srcBounds,
431 const SkIRect& bounds) const;
432 #endif
433 typedef SkLightingImageFilter INHERITED;
434 };
435
436 #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) const437 void SkLightingImageFilterInternal::drawRect(GrRenderTargetContext* renderTargetContext,
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 SkRect srcRect = dstRect.makeOffset(SkIntToScalar(bounds.x()), SkIntToScalar(bounds.y()));
446 GrPaint paint;
447 auto fp = this->makeFragmentProcessor(std::move(srcProxy), matrix, srcBounds, boundaryMode);
448 paint.addColorFragmentProcessor(std::move(fp));
449 paint.setPorterDuffXPFactory(SkBlendMode::kSrc);
450 renderTargetContext->fillRectToRect(clip, std::move(paint), GrAA::kNo, SkMatrix::I(), dstRect,
451 srcRect);
452 }
453
filterImageGPU(SkSpecialImage * source,SkSpecialImage * input,const SkIRect & offsetBounds,const SkMatrix & matrix,const OutputProperties & outputProperties) const454 sk_sp<SkSpecialImage> SkLightingImageFilterInternal::filterImageGPU(
455 SkSpecialImage* source,
456 SkSpecialImage* input,
457 const SkIRect& offsetBounds,
458 const SkMatrix& matrix,
459 const OutputProperties& outputProperties) const {
460 SkASSERT(source->isTextureBacked());
461
462 GrContext* context = source->getContext();
463
464 sk_sp<GrTextureProxy> inputProxy(input->asTextureProxyRef(context));
465 SkASSERT(inputProxy);
466
467 SkColorType colorType = outputProperties.colorType();
468 GrBackendFormat format =
469 context->contextPriv().caps()->getBackendFormatFromColorType(colorType);
470
471 sk_sp<GrRenderTargetContext> renderTargetContext(
472 context->contextPriv().makeDeferredRenderTargetContext(
473 format, SkBackingFit::kApprox, offsetBounds.width(),
474 offsetBounds.height(), SkColorType2GrPixelConfig(colorType),
475 sk_ref_sp(outputProperties.colorSpace())));
476 if (!renderTargetContext) {
477 return nullptr;
478 }
479
480 SkIRect dstIRect = SkIRect::MakeWH(offsetBounds.width(), offsetBounds.height());
481 SkRect dstRect = SkRect::Make(dstIRect);
482
483 // setup new clip
484 GrFixedClip clip(dstIRect);
485
486 const SkIRect inputBounds = SkIRect::MakeWH(input->width(), input->height());
487 SkRect topLeft = SkRect::MakeXYWH(0, 0, 1, 1);
488 SkRect top = SkRect::MakeXYWH(1, 0, dstRect.width() - 2, 1);
489 SkRect topRight = SkRect::MakeXYWH(dstRect.width() - 1, 0, 1, 1);
490 SkRect left = SkRect::MakeXYWH(0, 1, 1, dstRect.height() - 2);
491 SkRect interior = dstRect.makeInset(1, 1);
492 SkRect right = SkRect::MakeXYWH(dstRect.width() - 1, 1, 1, dstRect.height() - 2);
493 SkRect bottomLeft = SkRect::MakeXYWH(0, dstRect.height() - 1, 1, 1);
494 SkRect bottom = SkRect::MakeXYWH(1, dstRect.height() - 1, dstRect.width() - 2, 1);
495 SkRect bottomRight = SkRect::MakeXYWH(dstRect.width() - 1, dstRect.height() - 1, 1, 1);
496
497 const SkIRect* pSrcBounds = inputBounds.contains(offsetBounds) ? nullptr : &inputBounds;
498 this->drawRect(renderTargetContext.get(), inputProxy, matrix, clip, topLeft,
499 kTopLeft_BoundaryMode, pSrcBounds, offsetBounds);
500 this->drawRect(renderTargetContext.get(), inputProxy, matrix, clip, top,
501 kTop_BoundaryMode, pSrcBounds, offsetBounds);
502 this->drawRect(renderTargetContext.get(), inputProxy, matrix, clip, topRight,
503 kTopRight_BoundaryMode, pSrcBounds, offsetBounds);
504 this->drawRect(renderTargetContext.get(), inputProxy, matrix, clip, left,
505 kLeft_BoundaryMode, pSrcBounds, offsetBounds);
506 this->drawRect(renderTargetContext.get(), inputProxy, matrix, clip, interior,
507 kInterior_BoundaryMode, pSrcBounds, offsetBounds);
508 this->drawRect(renderTargetContext.get(), inputProxy, matrix, clip, right,
509 kRight_BoundaryMode, pSrcBounds, offsetBounds);
510 this->drawRect(renderTargetContext.get(), inputProxy, matrix, clip, bottomLeft,
511 kBottomLeft_BoundaryMode, pSrcBounds, offsetBounds);
512 this->drawRect(renderTargetContext.get(), inputProxy, matrix, clip, bottom,
513 kBottom_BoundaryMode, pSrcBounds, offsetBounds);
514 this->drawRect(renderTargetContext.get(), inputProxy, matrix, clip, bottomRight,
515 kBottomRight_BoundaryMode, pSrcBounds, offsetBounds);
516
517 return SkSpecialImage::MakeDeferredFromGpu(
518 context,
519 SkIRect::MakeWH(offsetBounds.width(), offsetBounds.height()),
520 kNeedNewImageUniqueID_SpecialImage,
521 renderTargetContext->asTextureProxyRef(),
522 renderTargetContext->colorSpaceInfo().refColorSpace());
523 }
524 #endif
525
526 class SkDiffuseLightingImageFilter : public SkLightingImageFilterInternal {
527 public:
528 static sk_sp<SkImageFilter> Make(sk_sp<SkImageFilterLight> light,
529 SkScalar surfaceScale,
530 SkScalar kd,
531 sk_sp<SkImageFilter>,
532 const CropRect*);
533
kd() const534 SkScalar kd() const { return fKD; }
535
536 protected:
537 SkDiffuseLightingImageFilter(sk_sp<SkImageFilterLight> light, SkScalar surfaceScale,
538 SkScalar kd,
539 sk_sp<SkImageFilter> input, const CropRect* cropRect);
540 void flatten(SkWriteBuffer& buffer) const override;
541
542 sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
543 SkIPoint* offset) const override;
544 sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;
545
546 #if SK_SUPPORT_GPU
547 std::unique_ptr<GrFragmentProcessor> makeFragmentProcessor(sk_sp<GrTextureProxy>,
548 const SkMatrix&,
549 const SkIRect* bounds,
550 BoundaryMode) const override;
551 #endif
552
553 private:
554 SK_FLATTENABLE_HOOKS(SkDiffuseLightingImageFilter)
555 friend class SkLightingImageFilter;
556 SkScalar fKD;
557
558 typedef SkLightingImageFilterInternal INHERITED;
559 };
560
561 class SkSpecularLightingImageFilter : public SkLightingImageFilterInternal {
562 public:
563 static sk_sp<SkImageFilter> Make(sk_sp<SkImageFilterLight> light,
564 SkScalar surfaceScale,
565 SkScalar ks, SkScalar shininess,
566 sk_sp<SkImageFilter>, const CropRect*);
567
ks() const568 SkScalar ks() const { return fKS; }
shininess() const569 SkScalar shininess() const { return fShininess; }
570
571 protected:
572 SkSpecularLightingImageFilter(sk_sp<SkImageFilterLight> light,
573 SkScalar surfaceScale, SkScalar ks,
574 SkScalar shininess,
575 sk_sp<SkImageFilter> input, const CropRect*);
576 void flatten(SkWriteBuffer& buffer) const override;
577
578 sk_sp<SkSpecialImage> onFilterImage(SkSpecialImage* source, const Context&,
579 SkIPoint* offset) const override;
580 sk_sp<SkImageFilter> onMakeColorSpace(SkColorSpaceXformer*) const override;
581
582 #if SK_SUPPORT_GPU
583 std::unique_ptr<GrFragmentProcessor> makeFragmentProcessor(sk_sp<GrTextureProxy>,
584 const SkMatrix&,
585 const SkIRect* bounds,
586 BoundaryMode) const override;
587 #endif
588
589 private:
590 SK_FLATTENABLE_HOOKS(SkSpecularLightingImageFilter)
591
592 SkScalar fKS;
593 SkScalar fShininess;
594 friend class SkLightingImageFilter;
595 typedef SkLightingImageFilterInternal INHERITED;
596 };
597
598 #if SK_SUPPORT_GPU
599
600 class GrLightingEffect : public GrFragmentProcessor {
601 public:
light() const602 const SkImageFilterLight* light() const { return fLight.get(); }
surfaceScale() const603 SkScalar surfaceScale() const { return fSurfaceScale; }
filterMatrix() const604 const SkMatrix& filterMatrix() const { return fFilterMatrix; }
boundaryMode() const605 BoundaryMode boundaryMode() const { return fBoundaryMode; }
domain() const606 const GrTextureDomain& domain() const { return fDomain; }
607
608 protected:
609 GrLightingEffect(ClassID classID, sk_sp<GrTextureProxy>, sk_sp<const SkImageFilterLight> light,
610 SkScalar surfaceScale, const SkMatrix& matrix, BoundaryMode boundaryMode,
611 const SkIRect* srcBounds);
612
613 GrLightingEffect(const GrLightingEffect& that);
614
615 bool onIsEqual(const GrFragmentProcessor&) const override;
616
617 private:
onTextureSampler(int) const618 const TextureSampler& onTextureSampler(int) const override { return fTextureSampler; }
619
620 GrCoordTransform fCoordTransform;
621 GrTextureDomain fDomain;
622 TextureSampler fTextureSampler;
623 sk_sp<const SkImageFilterLight> fLight;
624 SkScalar fSurfaceScale;
625 SkMatrix fFilterMatrix;
626 BoundaryMode fBoundaryMode;
627
628 typedef GrFragmentProcessor INHERITED;
629 };
630
631 class GrDiffuseLightingEffect : public GrLightingEffect {
632 public:
Make(sk_sp<GrTextureProxy> proxy,sk_sp<const SkImageFilterLight> light,SkScalar surfaceScale,const SkMatrix & matrix,SkScalar kd,BoundaryMode boundaryMode,const SkIRect * srcBounds)633 static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy,
634 sk_sp<const SkImageFilterLight> light,
635 SkScalar surfaceScale,
636 const SkMatrix& matrix,
637 SkScalar kd,
638 BoundaryMode boundaryMode,
639 const SkIRect* srcBounds) {
640 return std::unique_ptr<GrFragmentProcessor>(
641 new GrDiffuseLightingEffect(std::move(proxy), std::move(light), surfaceScale,
642 matrix, kd, boundaryMode, srcBounds));
643 }
644
name() const645 const char* name() const override { return "DiffuseLighting"; }
646
clone() const647 std::unique_ptr<GrFragmentProcessor> clone() const override {
648 return std::unique_ptr<GrFragmentProcessor>(new GrDiffuseLightingEffect(*this));
649 }
650
kd() const651 SkScalar kd() const { return fKD; }
652
653 private:
654 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
655
656 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
657
658 bool onIsEqual(const GrFragmentProcessor&) const override;
659
660 GrDiffuseLightingEffect(sk_sp<GrTextureProxy>,
661 sk_sp<const SkImageFilterLight> light,
662 SkScalar surfaceScale,
663 const SkMatrix& matrix,
664 SkScalar kd,
665 BoundaryMode boundaryMode,
666 const SkIRect* srcBounds);
667
668 explicit GrDiffuseLightingEffect(const GrDiffuseLightingEffect& that);
669
670 GR_DECLARE_FRAGMENT_PROCESSOR_TEST
671 SkScalar fKD;
672
673 typedef GrLightingEffect INHERITED;
674 };
675
676 class GrSpecularLightingEffect : public GrLightingEffect {
677 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)678 static std::unique_ptr<GrFragmentProcessor> Make(sk_sp<GrTextureProxy> proxy,
679 sk_sp<const SkImageFilterLight> light,
680 SkScalar surfaceScale,
681 const SkMatrix& matrix,
682 SkScalar ks,
683 SkScalar shininess,
684 BoundaryMode boundaryMode,
685 const SkIRect* srcBounds) {
686 return std::unique_ptr<GrFragmentProcessor>(
687 new GrSpecularLightingEffect(std::move(proxy), std::move(light), surfaceScale,
688 matrix, ks, shininess, boundaryMode, srcBounds));
689 }
690
name() const691 const char* name() const override { return "SpecularLighting"; }
692
clone() const693 std::unique_ptr<GrFragmentProcessor> clone() const override {
694 return std::unique_ptr<GrFragmentProcessor>(new GrSpecularLightingEffect(*this));
695 }
696
697 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
698
ks() const699 SkScalar ks() const { return fKS; }
shininess() const700 SkScalar shininess() const { return fShininess; }
701
702 private:
703 void onGetGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder*) const override;
704
705 bool onIsEqual(const GrFragmentProcessor&) const override;
706
707 GrSpecularLightingEffect(sk_sp<GrTextureProxy>,
708 sk_sp<const SkImageFilterLight> light,
709 SkScalar surfaceScale,
710 const SkMatrix& matrix,
711 SkScalar ks,
712 SkScalar shininess,
713 BoundaryMode boundaryMode,
714 const SkIRect* srcBounds);
715
716 explicit GrSpecularLightingEffect(const GrSpecularLightingEffect&);
717
718 GR_DECLARE_FRAGMENT_PROCESSOR_TEST
719 SkScalar fKS;
720 SkScalar fShininess;
721
722 typedef GrLightingEffect INHERITED;
723 };
724
725 ///////////////////////////////////////////////////////////////////////////////
726
727 class GrGLLight {
728 public:
~GrGLLight()729 virtual ~GrGLLight() {}
730
731 /**
732 * This is called by GrGLLightingEffect::emitCode() before either of the two virtual functions
733 * below. It adds a half3 uniform visible in the FS that represents the constant light color.
734 */
735 void emitLightColorUniform(GrGLSLUniformHandler*);
736
737 /**
738 * These two functions are called from GrGLLightingEffect's emitCode() function.
739 * emitSurfaceToLight places an expression in param out that is the vector from the surface to
740 * the light. The expression will be used in the FS. emitLightColor writes an expression into
741 * the FS that is the color of the light. Either function may add functions and/or uniforms to
742 * the FS. The default of emitLightColor appends the name of the constant light color uniform
743 * and so this function only needs to be overridden if the light color varies spatially.
744 */
745 virtual void emitSurfaceToLight(GrGLSLUniformHandler*,
746 GrGLSLFPFragmentBuilder*,
747 const char* z) = 0;
748 virtual void emitLightColor(GrGLSLUniformHandler*,
749 GrGLSLFPFragmentBuilder*,
750 const char *surfaceToLight);
751
752 // This is called from GrGLLightingEffect's setData(). Subclasses of GrGLLight must call
753 // INHERITED::setData().
754 virtual void setData(const GrGLSLProgramDataManager&, const SkImageFilterLight* light) const;
755
756 protected:
757 /**
758 * Gets the constant light color uniform. Subclasses can use this in their emitLightColor
759 * function.
760 */
lightColorUni() const761 UniformHandle lightColorUni() const { return fColorUni; }
762
763 private:
764 UniformHandle fColorUni;
765
766 typedef SkRefCnt INHERITED;
767 };
768
769 ///////////////////////////////////////////////////////////////////////////////
770
771 class GrGLDistantLight : public GrGLLight {
772 public:
~GrGLDistantLight()773 ~GrGLDistantLight() override {}
774 void setData(const GrGLSLProgramDataManager&, const SkImageFilterLight* light) const override;
775 void emitSurfaceToLight(GrGLSLUniformHandler*, GrGLSLFPFragmentBuilder*, const char* z) override;
776
777 private:
778 typedef GrGLLight INHERITED;
779 UniformHandle fDirectionUni;
780 };
781
782 ///////////////////////////////////////////////////////////////////////////////
783
784 class GrGLPointLight : public GrGLLight {
785 public:
~GrGLPointLight()786 ~GrGLPointLight() override {}
787 void setData(const GrGLSLProgramDataManager&, const SkImageFilterLight* light) const override;
788 void emitSurfaceToLight(GrGLSLUniformHandler*, GrGLSLFPFragmentBuilder*, const char* z) override;
789
790 private:
791 typedef GrGLLight INHERITED;
792 UniformHandle fLocationUni;
793 };
794
795 ///////////////////////////////////////////////////////////////////////////////
796
797 class GrGLSpotLight : public GrGLLight {
798 public:
~GrGLSpotLight()799 ~GrGLSpotLight() override {}
800 void setData(const GrGLSLProgramDataManager&, const SkImageFilterLight* light) const override;
801 void emitSurfaceToLight(GrGLSLUniformHandler*, GrGLSLFPFragmentBuilder*, const char* z) override;
802 void emitLightColor(GrGLSLUniformHandler*,
803 GrGLSLFPFragmentBuilder*,
804 const char *surfaceToLight) override;
805
806 private:
807 typedef GrGLLight INHERITED;
808
809 SkString fLightColorFunc;
810 UniformHandle fLocationUni;
811 UniformHandle fExponentUni;
812 UniformHandle fCosOuterConeAngleUni;
813 UniformHandle fCosInnerConeAngleUni;
814 UniformHandle fConeScaleUni;
815 UniformHandle fSUni;
816 };
817 #else
818
819 class GrGLLight;
820
821 #endif
822
823 ///////////////////////////////////////////////////////////////////////////////
824
825 ///////////////////////////////////////////////////////////////////////////////
826
xform_color(const SkPoint3 & color,SkColorSpaceXformer * xformer)827 static SkColor xform_color(const SkPoint3& color, SkColorSpaceXformer* xformer) {
828 SkColor origColor = SkColorSetRGB(SkScalarRoundToInt(color.fX),
829 SkScalarRoundToInt(color.fY),
830 SkScalarRoundToInt(color.fZ));
831 return xformer->apply(origColor);
832 }
833
834 class SkDistantLight : public SkImageFilterLight {
835 public:
SkDistantLight(const SkPoint3 & direction,SkColor color)836 SkDistantLight(const SkPoint3& direction, SkColor color)
837 : INHERITED(color), fDirection(direction) {
838 }
839
surfaceToLight(int x,int y,int z,SkScalar surfaceScale) const840 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const override {
841 return fDirection;
842 }
lightColor(const SkPoint3 &) const843 SkPoint3 lightColor(const SkPoint3&) const override { return this->color(); }
type() const844 LightType type() const override { return kDistant_LightType; }
direction() const845 const SkPoint3& direction() const { return fDirection; }
createGLLight() const846 GrGLLight* createGLLight() const override {
847 #if SK_SUPPORT_GPU
848 return new GrGLDistantLight;
849 #else
850 SkDEBUGFAIL("Should not call in GPU-less build");
851 return nullptr;
852 #endif
853 }
854
makeColorSpace(SkColorSpaceXformer * xformer) const855 sk_sp<SkImageFilterLight> makeColorSpace(SkColorSpaceXformer* xformer) const override {
856 return sk_make_sp<SkDistantLight>(fDirection, xform_color(this->color(), xformer));
857 }
858
isEqual(const SkImageFilterLight & other) const859 bool isEqual(const SkImageFilterLight& other) const override {
860 if (other.type() != kDistant_LightType) {
861 return false;
862 }
863
864 const SkDistantLight& o = static_cast<const SkDistantLight&>(other);
865 return INHERITED::isEqual(other) &&
866 fDirection == o.fDirection;
867 }
868
SkDistantLight(SkReadBuffer & buffer)869 SkDistantLight(SkReadBuffer& buffer) : INHERITED(buffer) {
870 fDirection = read_point3(buffer);
871 }
872
873 protected:
SkDistantLight(const SkPoint3 & direction,const SkPoint3 & color)874 SkDistantLight(const SkPoint3& direction, const SkPoint3& color)
875 : INHERITED(color), fDirection(direction) {
876 }
transform(const SkMatrix & matrix) const877 SkImageFilterLight* transform(const SkMatrix& matrix) const override {
878 return new SkDistantLight(direction(), color());
879 }
onFlattenLight(SkWriteBuffer & buffer) const880 void onFlattenLight(SkWriteBuffer& buffer) const override {
881 write_point3(fDirection, buffer);
882 }
883
884 private:
885 SkPoint3 fDirection;
886
887 typedef SkImageFilterLight INHERITED;
888 };
889
890 ///////////////////////////////////////////////////////////////////////////////
891
892 class SkPointLight : public SkImageFilterLight {
893 public:
SkPointLight(const SkPoint3 & location,SkColor color)894 SkPointLight(const SkPoint3& location, SkColor color)
895 : INHERITED(color), fLocation(location) {}
896
surfaceToLight(int x,int y,int z,SkScalar surfaceScale) const897 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const override {
898 SkPoint3 direction = SkPoint3::Make(fLocation.fX - SkIntToScalar(x),
899 fLocation.fY - SkIntToScalar(y),
900 fLocation.fZ - SkIntToScalar(z) * surfaceScale);
901 fast_normalize(&direction);
902 return direction;
903 }
lightColor(const SkPoint3 &) const904 SkPoint3 lightColor(const SkPoint3&) const override { return this->color(); }
type() const905 LightType type() const override { return kPoint_LightType; }
location() const906 const SkPoint3& location() const { return fLocation; }
createGLLight() const907 GrGLLight* createGLLight() const override {
908 #if SK_SUPPORT_GPU
909 return new GrGLPointLight;
910 #else
911 SkDEBUGFAIL("Should not call in GPU-less build");
912 return nullptr;
913 #endif
914 }
915
makeColorSpace(SkColorSpaceXformer * xformer) const916 sk_sp<SkImageFilterLight> makeColorSpace(SkColorSpaceXformer* xformer) const override {
917 return sk_make_sp<SkPointLight>(fLocation, xform_color(this->color(), xformer));
918 }
919
isEqual(const SkImageFilterLight & other) const920 bool isEqual(const SkImageFilterLight& other) const override {
921 if (other.type() != kPoint_LightType) {
922 return false;
923 }
924 const SkPointLight& o = static_cast<const SkPointLight&>(other);
925 return INHERITED::isEqual(other) &&
926 fLocation == o.fLocation;
927 }
transform(const SkMatrix & matrix) const928 SkImageFilterLight* transform(const SkMatrix& matrix) const override {
929 SkPoint location2 = SkPoint::Make(fLocation.fX, fLocation.fY);
930 matrix.mapPoints(&location2, 1);
931 // Use X scale and Y scale on Z and average the result
932 SkPoint locationZ = SkPoint::Make(fLocation.fZ, fLocation.fZ);
933 matrix.mapVectors(&locationZ, 1);
934 SkPoint3 location = SkPoint3::Make(location2.fX,
935 location2.fY,
936 SkScalarAve(locationZ.fX, locationZ.fY));
937 return new SkPointLight(location, color());
938 }
939
SkPointLight(SkReadBuffer & buffer)940 SkPointLight(SkReadBuffer& buffer) : INHERITED(buffer) {
941 fLocation = read_point3(buffer);
942 }
943
944 protected:
SkPointLight(const SkPoint3 & location,const SkPoint3 & color)945 SkPointLight(const SkPoint3& location, const SkPoint3& color)
946 : INHERITED(color), fLocation(location) {}
onFlattenLight(SkWriteBuffer & buffer) const947 void onFlattenLight(SkWriteBuffer& buffer) const override {
948 write_point3(fLocation, buffer);
949 }
950
951 private:
952 SkPoint3 fLocation;
953
954 typedef SkImageFilterLight INHERITED;
955 };
956
957 ///////////////////////////////////////////////////////////////////////////////
958
959 class SkSpotLight : public SkImageFilterLight {
960 public:
SkSpotLight(const SkPoint3 & location,const SkPoint3 & target,SkScalar specularExponent,SkScalar cutoffAngle,SkColor color)961 SkSpotLight(const SkPoint3& location,
962 const SkPoint3& target,
963 SkScalar specularExponent,
964 SkScalar cutoffAngle,
965 SkColor color)
966 : INHERITED(color),
967 fLocation(location),
968 fTarget(target),
969 fSpecularExponent(SkScalarPin(specularExponent, kSpecularExponentMin, kSpecularExponentMax)),
970 fCutoffAngle(cutoffAngle)
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
makeColorSpace(SkColorSpaceXformer * xformer) const980 sk_sp<SkImageFilterLight> makeColorSpace(SkColorSpaceXformer* xformer) const override {
981 return sk_make_sp<SkSpotLight>(fLocation, fTarget, fSpecularExponent, fCutoffAngle,
982 xform_color(this->color(), xformer));
983 }
984
transform(const SkMatrix & matrix) const985 SkImageFilterLight* transform(const SkMatrix& matrix) const override {
986 SkPoint location2 = SkPoint::Make(fLocation.fX, fLocation.fY);
987 matrix.mapPoints(&location2, 1);
988 // Use X scale and Y scale on Z and average the result
989 SkPoint locationZ = SkPoint::Make(fLocation.fZ, fLocation.fZ);
990 matrix.mapVectors(&locationZ, 1);
991 SkPoint3 location = SkPoint3::Make(location2.fX, location2.fY,
992 SkScalarAve(locationZ.fX, locationZ.fY));
993 SkPoint target2 = SkPoint::Make(fTarget.fX, fTarget.fY);
994 matrix.mapPoints(&target2, 1);
995 SkPoint targetZ = SkPoint::Make(fTarget.fZ, fTarget.fZ);
996 matrix.mapVectors(&targetZ, 1);
997 SkPoint3 target = SkPoint3::Make(target2.fX, target2.fY,
998 SkScalarAve(targetZ.fX, targetZ.fY));
999 SkPoint3 s = target - location;
1000 fast_normalize(&s);
1001 return new SkSpotLight(location,
1002 target,
1003 fSpecularExponent,
1004 fCosOuterConeAngle,
1005 fCosInnerConeAngle,
1006 fConeScale,
1007 s,
1008 color());
1009 }
1010
surfaceToLight(int x,int y,int z,SkScalar surfaceScale) const1011 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const override {
1012 SkPoint3 direction = SkPoint3::Make(fLocation.fX - SkIntToScalar(x),
1013 fLocation.fY - SkIntToScalar(y),
1014 fLocation.fZ - SkIntToScalar(z) * surfaceScale);
1015 fast_normalize(&direction);
1016 return direction;
1017 }
lightColor(const SkPoint3 & surfaceToLight) const1018 SkPoint3 lightColor(const SkPoint3& surfaceToLight) const override {
1019 SkScalar cosAngle = -surfaceToLight.dot(fS);
1020 SkScalar scale = 0;
1021 if (cosAngle >= fCosOuterConeAngle) {
1022 scale = SkScalarPow(cosAngle, fSpecularExponent);
1023 if (cosAngle < fCosInnerConeAngle) {
1024 scale *= (cosAngle - fCosOuterConeAngle) * fConeScale;
1025 }
1026 }
1027 return this->color().makeScale(scale);
1028 }
createGLLight() const1029 GrGLLight* createGLLight() const override {
1030 #if SK_SUPPORT_GPU
1031 return new GrGLSpotLight;
1032 #else
1033 SkDEBUGFAIL("Should not call in GPU-less build");
1034 return nullptr;
1035 #endif
1036 }
type() const1037 LightType type() const override { return kSpot_LightType; }
location() const1038 const SkPoint3& location() const { return fLocation; }
target() const1039 const SkPoint3& target() const { return fTarget; }
specularExponent() const1040 SkScalar specularExponent() const { return fSpecularExponent; }
cosInnerConeAngle() const1041 SkScalar cosInnerConeAngle() const { return fCosInnerConeAngle; }
cosOuterConeAngle() const1042 SkScalar cosOuterConeAngle() const { return fCosOuterConeAngle; }
coneScale() const1043 SkScalar coneScale() const { return fConeScale; }
s() const1044 const SkPoint3& s() const { return fS; }
1045
SkSpotLight(SkReadBuffer & buffer)1046 SkSpotLight(SkReadBuffer& buffer) : INHERITED(buffer) {
1047 fLocation = read_point3(buffer);
1048 fTarget = read_point3(buffer);
1049 fSpecularExponent = buffer.readScalar();
1050 fCosOuterConeAngle = buffer.readScalar();
1051 fCosInnerConeAngle = buffer.readScalar();
1052 fConeScale = buffer.readScalar();
1053 fS = read_point3(buffer);
1054 buffer.validate(SkScalarIsFinite(fSpecularExponent) &&
1055 SkScalarIsFinite(fCosOuterConeAngle) &&
1056 SkScalarIsFinite(fCosInnerConeAngle) &&
1057 SkScalarIsFinite(fConeScale));
1058 }
1059 protected:
SkSpotLight(const SkPoint3 & location,const SkPoint3 & target,SkScalar specularExponent,SkScalar cosOuterConeAngle,SkScalar cosInnerConeAngle,SkScalar coneScale,const SkPoint3 & s,const SkPoint3 & color)1060 SkSpotLight(const SkPoint3& location,
1061 const SkPoint3& target,
1062 SkScalar specularExponent,
1063 SkScalar cosOuterConeAngle,
1064 SkScalar cosInnerConeAngle,
1065 SkScalar coneScale,
1066 const SkPoint3& s,
1067 const SkPoint3& color)
1068 : INHERITED(color),
1069 fLocation(location),
1070 fTarget(target),
1071 fSpecularExponent(specularExponent),
1072 fCosOuterConeAngle(cosOuterConeAngle),
1073 fCosInnerConeAngle(cosInnerConeAngle),
1074 fConeScale(coneScale),
1075 fS(s)
1076 {
1077 }
onFlattenLight(SkWriteBuffer & buffer) const1078 void onFlattenLight(SkWriteBuffer& buffer) const override {
1079 write_point3(fLocation, buffer);
1080 write_point3(fTarget, buffer);
1081 buffer.writeScalar(fSpecularExponent);
1082 buffer.writeScalar(fCosOuterConeAngle);
1083 buffer.writeScalar(fCosInnerConeAngle);
1084 buffer.writeScalar(fConeScale);
1085 write_point3(fS, buffer);
1086 }
1087
isEqual(const SkImageFilterLight & other) const1088 bool isEqual(const SkImageFilterLight& other) const override {
1089 if (other.type() != kSpot_LightType) {
1090 return false;
1091 }
1092
1093 const SkSpotLight& o = static_cast<const SkSpotLight&>(other);
1094 return INHERITED::isEqual(other) &&
1095 fLocation == o.fLocation &&
1096 fTarget == o.fTarget &&
1097 fSpecularExponent == o.fSpecularExponent &&
1098 fCosOuterConeAngle == o.fCosOuterConeAngle;
1099 }
1100
1101 private:
1102 static const SkScalar kSpecularExponentMin;
1103 static const SkScalar kSpecularExponentMax;
1104
1105 SkPoint3 fLocation;
1106 SkPoint3 fTarget;
1107 SkScalar fSpecularExponent;
1108 SkScalar fCutoffAngle;
1109 SkScalar fCosOuterConeAngle;
1110 SkScalar fCosInnerConeAngle;
1111 SkScalar fConeScale;
1112 SkPoint3 fS;
1113
1114 typedef SkImageFilterLight INHERITED;
1115 };
1116
1117 // According to the spec, the specular term should be in the range [1, 128] :
1118 // http://www.w3.org/TR/SVG/filters.html#feSpecularLightingSpecularExponentAttribute
1119 const SkScalar SkSpotLight::kSpecularExponentMin = 1.0f;
1120 const SkScalar SkSpotLight::kSpecularExponentMax = 128.0f;
1121
1122 ///////////////////////////////////////////////////////////////////////////////
1123
flattenLight(SkWriteBuffer & buffer) const1124 void SkImageFilterLight::flattenLight(SkWriteBuffer& buffer) const {
1125 // Write type first, then baseclass, then subclass.
1126 buffer.writeInt(this->type());
1127 write_point3(fColor, buffer);
1128 this->onFlattenLight(buffer);
1129 }
1130
UnflattenLight(SkReadBuffer & buffer)1131 /*static*/ SkImageFilterLight* SkImageFilterLight::UnflattenLight(SkReadBuffer& buffer) {
1132 SkImageFilterLight::LightType type = buffer.read32LE(SkImageFilterLight::kLast_LightType);
1133
1134 switch (type) {
1135 // Each of these constructors must first call SkLight's, so we'll read the baseclass
1136 // then subclass, same order as flattenLight.
1137 case SkImageFilterLight::kDistant_LightType:
1138 return new SkDistantLight(buffer);
1139 case SkImageFilterLight::kPoint_LightType:
1140 return new SkPointLight(buffer);
1141 case SkImageFilterLight::kSpot_LightType:
1142 return new SkSpotLight(buffer);
1143 default:
1144 // Should never get here due to prior check of SkSafeRange
1145 SkDEBUGFAIL("Unknown LightType.");
1146 return nullptr;
1147 }
1148 }
1149 ///////////////////////////////////////////////////////////////////////////////
1150
SkLightingImageFilter(sk_sp<SkImageFilterLight> light,SkScalar surfaceScale,sk_sp<SkImageFilter> input,const CropRect * cropRect)1151 SkLightingImageFilter::SkLightingImageFilter(sk_sp<SkImageFilterLight> light,
1152 SkScalar surfaceScale,
1153 sk_sp<SkImageFilter> input, const CropRect* cropRect)
1154 : INHERITED(&input, 1, cropRect)
1155 , fLight(std::move(light))
1156 , fSurfaceScale(surfaceScale / 255) {
1157 }
1158
~SkLightingImageFilter()1159 SkLightingImageFilter::~SkLightingImageFilter() {}
1160
MakeDistantLitDiffuse(const SkPoint3 & direction,SkColor lightColor,SkScalar surfaceScale,SkScalar kd,sk_sp<SkImageFilter> input,const CropRect * cropRect)1161 sk_sp<SkImageFilter> SkLightingImageFilter::MakeDistantLitDiffuse(const SkPoint3& direction,
1162 SkColor lightColor,
1163 SkScalar surfaceScale,
1164 SkScalar kd,
1165 sk_sp<SkImageFilter> input,
1166 const CropRect* cropRect) {
1167 sk_sp<SkImageFilterLight> light(new SkDistantLight(direction, lightColor));
1168 return SkDiffuseLightingImageFilter::Make(std::move(light), surfaceScale, kd,
1169 std::move(input), cropRect);
1170 }
1171
MakePointLitDiffuse(const SkPoint3 & location,SkColor lightColor,SkScalar surfaceScale,SkScalar kd,sk_sp<SkImageFilter> input,const CropRect * cropRect)1172 sk_sp<SkImageFilter> SkLightingImageFilter::MakePointLitDiffuse(const SkPoint3& location,
1173 SkColor lightColor,
1174 SkScalar surfaceScale,
1175 SkScalar kd,
1176 sk_sp<SkImageFilter> input,
1177 const CropRect* cropRect) {
1178 sk_sp<SkImageFilterLight> light(new SkPointLight(location, lightColor));
1179 return SkDiffuseLightingImageFilter::Make(std::move(light), surfaceScale, kd,
1180 std::move(input), cropRect);
1181 }
1182
MakeSpotLitDiffuse(const SkPoint3 & location,const SkPoint3 & target,SkScalar specularExponent,SkScalar cutoffAngle,SkColor lightColor,SkScalar surfaceScale,SkScalar kd,sk_sp<SkImageFilter> input,const CropRect * cropRect)1183 sk_sp<SkImageFilter> SkLightingImageFilter::MakeSpotLitDiffuse(const SkPoint3& location,
1184 const SkPoint3& target,
1185 SkScalar specularExponent,
1186 SkScalar cutoffAngle,
1187 SkColor lightColor,
1188 SkScalar surfaceScale,
1189 SkScalar kd,
1190 sk_sp<SkImageFilter> input,
1191 const CropRect* cropRect) {
1192 sk_sp<SkImageFilterLight> light(
1193 new SkSpotLight(location, target, specularExponent, cutoffAngle, lightColor));
1194 return SkDiffuseLightingImageFilter::Make(std::move(light), surfaceScale, kd,
1195 std::move(input), cropRect);
1196 }
1197
MakeDistantLitSpecular(const SkPoint3 & direction,SkColor lightColor,SkScalar surfaceScale,SkScalar ks,SkScalar shine,sk_sp<SkImageFilter> input,const CropRect * cropRect)1198 sk_sp<SkImageFilter> SkLightingImageFilter::MakeDistantLitSpecular(const SkPoint3& direction,
1199 SkColor lightColor,
1200 SkScalar surfaceScale,
1201 SkScalar ks,
1202 SkScalar shine,
1203 sk_sp<SkImageFilter> input,
1204 const CropRect* cropRect) {
1205 sk_sp<SkImageFilterLight> light(new SkDistantLight(direction, lightColor));
1206 return SkSpecularLightingImageFilter::Make(std::move(light), surfaceScale, ks, shine,
1207 std::move(input), cropRect);
1208 }
1209
MakePointLitSpecular(const SkPoint3 & location,SkColor lightColor,SkScalar surfaceScale,SkScalar ks,SkScalar shine,sk_sp<SkImageFilter> input,const CropRect * cropRect)1210 sk_sp<SkImageFilter> SkLightingImageFilter::MakePointLitSpecular(const SkPoint3& location,
1211 SkColor lightColor,
1212 SkScalar surfaceScale,
1213 SkScalar ks,
1214 SkScalar shine,
1215 sk_sp<SkImageFilter> input,
1216 const CropRect* cropRect) {
1217 sk_sp<SkImageFilterLight> light(new SkPointLight(location, lightColor));
1218 return SkSpecularLightingImageFilter::Make(std::move(light), surfaceScale, ks, shine,
1219 std::move(input), cropRect);
1220 }
1221
MakeSpotLitSpecular(const SkPoint3 & location,const SkPoint3 & target,SkScalar specularExponent,SkScalar cutoffAngle,SkColor lightColor,SkScalar surfaceScale,SkScalar ks,SkScalar shine,sk_sp<SkImageFilter> input,const CropRect * cropRect)1222 sk_sp<SkImageFilter> SkLightingImageFilter::MakeSpotLitSpecular(const SkPoint3& location,
1223 const SkPoint3& target,
1224 SkScalar specularExponent,
1225 SkScalar cutoffAngle,
1226 SkColor lightColor,
1227 SkScalar surfaceScale,
1228 SkScalar ks,
1229 SkScalar shine,
1230 sk_sp<SkImageFilter> input,
1231 const CropRect* cropRect) {
1232 sk_sp<SkImageFilterLight> light(
1233 new SkSpotLight(location, target, specularExponent, cutoffAngle, lightColor));
1234 return SkSpecularLightingImageFilter::Make(std::move(light), surfaceScale, ks, shine,
1235 std::move(input), cropRect);
1236 }
1237
flatten(SkWriteBuffer & buffer) const1238 void SkLightingImageFilter::flatten(SkWriteBuffer& buffer) const {
1239 this->INHERITED::flatten(buffer);
1240 fLight->flattenLight(buffer);
1241 buffer.writeScalar(fSurfaceScale * 255);
1242 }
1243
refLight() const1244 sk_sp<const SkImageFilterLight> SkLightingImageFilter::refLight() const { return fLight; }
1245
1246 ///////////////////////////////////////////////////////////////////////////////
1247
Make(sk_sp<SkImageFilterLight> light,SkScalar surfaceScale,SkScalar kd,sk_sp<SkImageFilter> input,const CropRect * cropRect)1248 sk_sp<SkImageFilter> SkDiffuseLightingImageFilter::Make(sk_sp<SkImageFilterLight> light,
1249 SkScalar surfaceScale,
1250 SkScalar kd,
1251 sk_sp<SkImageFilter> input,
1252 const CropRect* cropRect) {
1253 if (!light) {
1254 return nullptr;
1255 }
1256 if (!SkScalarIsFinite(surfaceScale) || !SkScalarIsFinite(kd)) {
1257 return nullptr;
1258 }
1259 // According to the spec, kd can be any non-negative number :
1260 // http://www.w3.org/TR/SVG/filters.html#feDiffuseLightingElement
1261 if (kd < 0) {
1262 return nullptr;
1263 }
1264 return sk_sp<SkImageFilter>(new SkDiffuseLightingImageFilter(std::move(light), surfaceScale,
1265 kd, std::move(input), cropRect));
1266 }
1267
SkDiffuseLightingImageFilter(sk_sp<SkImageFilterLight> light,SkScalar surfaceScale,SkScalar kd,sk_sp<SkImageFilter> input,const CropRect * cropRect)1268 SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(sk_sp<SkImageFilterLight> light,
1269 SkScalar surfaceScale,
1270 SkScalar kd,
1271 sk_sp<SkImageFilter> input,
1272 const CropRect* cropRect)
1273 : INHERITED(std::move(light), surfaceScale, std::move(input), cropRect)
1274 , fKD(kd) {
1275 }
1276
CreateProc(SkReadBuffer & buffer)1277 sk_sp<SkFlattenable> SkDiffuseLightingImageFilter::CreateProc(SkReadBuffer& buffer) {
1278 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
1279
1280 sk_sp<SkImageFilterLight> light(SkImageFilterLight::UnflattenLight(buffer));
1281 SkScalar surfaceScale = buffer.readScalar();
1282 SkScalar kd = buffer.readScalar();
1283
1284 return Make(std::move(light), surfaceScale, kd, common.getInput(0), &common.cropRect());
1285 }
1286
flatten(SkWriteBuffer & buffer) const1287 void SkDiffuseLightingImageFilter::flatten(SkWriteBuffer& buffer) const {
1288 this->INHERITED::flatten(buffer);
1289 buffer.writeScalar(fKD);
1290 }
1291
onFilterImage(SkSpecialImage * source,const Context & ctx,SkIPoint * offset) const1292 sk_sp<SkSpecialImage> SkDiffuseLightingImageFilter::onFilterImage(SkSpecialImage* source,
1293 const Context& ctx,
1294 SkIPoint* offset) const {
1295 SkIPoint inputOffset = SkIPoint::Make(0, 0);
1296 sk_sp<SkSpecialImage> input(this->filterInput(0, source, ctx, &inputOffset));
1297 if (!input) {
1298 return nullptr;
1299 }
1300
1301 const SkIRect inputBounds = SkIRect::MakeXYWH(inputOffset.x(), inputOffset.y(),
1302 input->width(), input->height());
1303 SkIRect bounds;
1304 if (!this->applyCropRect(ctx, inputBounds, &bounds)) {
1305 return nullptr;
1306 }
1307
1308 offset->fX = bounds.left();
1309 offset->fY = bounds.top();
1310 bounds.offset(-inputOffset);
1311
1312 #if SK_SUPPORT_GPU
1313 if (source->isTextureBacked()) {
1314 SkMatrix matrix(ctx.ctm());
1315 matrix.postTranslate(SkIntToScalar(-offset->fX), SkIntToScalar(-offset->fY));
1316
1317 return this->filterImageGPU(source, input.get(), bounds, matrix, ctx.outputProperties());
1318 }
1319 #endif
1320
1321 if (bounds.width() < 2 || bounds.height() < 2) {
1322 return nullptr;
1323 }
1324
1325 SkBitmap inputBM;
1326
1327 if (!input->getROPixels(&inputBM)) {
1328 return nullptr;
1329 }
1330
1331 if (inputBM.colorType() != kN32_SkColorType) {
1332 return nullptr;
1333 }
1334
1335 if (!inputBM.getPixels()) {
1336 return nullptr;
1337 }
1338
1339 const SkImageInfo info = SkImageInfo::MakeN32Premul(bounds.width(), bounds.height());
1340
1341 SkBitmap dst;
1342 if (!dst.tryAllocPixels(info)) {
1343 return nullptr;
1344 }
1345
1346 SkMatrix matrix(ctx.ctm());
1347 matrix.postTranslate(SkIntToScalar(-inputOffset.x()), SkIntToScalar(-inputOffset.y()));
1348
1349 sk_sp<SkImageFilterLight> transformedLight(light()->transform(matrix));
1350
1351 DiffuseLightingType lightingType(fKD);
1352 lightBitmap(lightingType,
1353 transformedLight.get(),
1354 inputBM,
1355 &dst,
1356 surfaceScale(),
1357 bounds);
1358
1359 return SkSpecialImage::MakeFromRaster(SkIRect::MakeWH(bounds.width(), bounds.height()),
1360 dst);
1361 }
1362
onMakeColorSpace(SkColorSpaceXformer * xformer) const1363 sk_sp<SkImageFilter> SkDiffuseLightingImageFilter::onMakeColorSpace(SkColorSpaceXformer* xformer)
1364 const {
1365 SkASSERT(1 == this->countInputs());
1366 auto input = xformer->apply(this->getInput(0));
1367 auto light = this->light()->makeColorSpace(xformer);
1368 if (input.get() != this->getInput(0) || light.get() != this->light()) {
1369 return SkDiffuseLightingImageFilter::Make(std::move(light), 255.0f * this->surfaceScale(),
1370 fKD, std::move(input), this->getCropRectIfSet());
1371 }
1372 return this->refMe();
1373 }
1374
1375 #if SK_SUPPORT_GPU
makeFragmentProcessor(sk_sp<GrTextureProxy> proxy,const SkMatrix & matrix,const SkIRect * srcBounds,BoundaryMode boundaryMode) const1376 std::unique_ptr<GrFragmentProcessor> SkDiffuseLightingImageFilter::makeFragmentProcessor(
1377 sk_sp<GrTextureProxy> proxy,
1378 const SkMatrix& matrix,
1379 const SkIRect* srcBounds,
1380 BoundaryMode boundaryMode) const {
1381 SkScalar scale = this->surfaceScale() * 255;
1382 return GrDiffuseLightingEffect::Make(std::move(proxy), this->refLight(), scale, matrix,
1383 this->kd(), boundaryMode, srcBounds);
1384 }
1385 #endif
1386
1387 ///////////////////////////////////////////////////////////////////////////////
1388
Make(sk_sp<SkImageFilterLight> light,SkScalar surfaceScale,SkScalar ks,SkScalar shininess,sk_sp<SkImageFilter> input,const CropRect * cropRect)1389 sk_sp<SkImageFilter> SkSpecularLightingImageFilter::Make(sk_sp<SkImageFilterLight> light,
1390 SkScalar surfaceScale,
1391 SkScalar ks,
1392 SkScalar shininess,
1393 sk_sp<SkImageFilter> input,
1394 const CropRect* cropRect) {
1395 if (!light) {
1396 return nullptr;
1397 }
1398 if (!SkScalarIsFinite(surfaceScale) || !SkScalarIsFinite(ks) || !SkScalarIsFinite(shininess)) {
1399 return nullptr;
1400 }
1401 // According to the spec, ks can be any non-negative number :
1402 // http://www.w3.org/TR/SVG/filters.html#feSpecularLightingElement
1403 if (ks < 0) {
1404 return nullptr;
1405 }
1406 return sk_sp<SkImageFilter>(new SkSpecularLightingImageFilter(std::move(light), surfaceScale,
1407 ks, shininess,
1408 std::move(input), cropRect));
1409 }
1410
SkSpecularLightingImageFilter(sk_sp<SkImageFilterLight> light,SkScalar surfaceScale,SkScalar ks,SkScalar shininess,sk_sp<SkImageFilter> input,const CropRect * cropRect)1411 SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(sk_sp<SkImageFilterLight> light,
1412 SkScalar surfaceScale,
1413 SkScalar ks,
1414 SkScalar shininess,
1415 sk_sp<SkImageFilter> input,
1416 const CropRect* cropRect)
1417 : INHERITED(std::move(light), surfaceScale, std::move(input), cropRect)
1418 , fKS(ks)
1419 , fShininess(shininess) {
1420 }
1421
CreateProc(SkReadBuffer & buffer)1422 sk_sp<SkFlattenable> SkSpecularLightingImageFilter::CreateProc(SkReadBuffer& buffer) {
1423 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
1424 sk_sp<SkImageFilterLight> light(SkImageFilterLight::UnflattenLight(buffer));
1425 SkScalar surfaceScale = buffer.readScalar();
1426 SkScalar ks = buffer.readScalar();
1427 SkScalar shine = buffer.readScalar();
1428
1429 return Make(std::move(light), surfaceScale, ks, shine, common.getInput(0),
1430 &common.cropRect());
1431 }
1432
flatten(SkWriteBuffer & buffer) const1433 void SkSpecularLightingImageFilter::flatten(SkWriteBuffer& buffer) const {
1434 this->INHERITED::flatten(buffer);
1435 buffer.writeScalar(fKS);
1436 buffer.writeScalar(fShininess);
1437 }
1438
onFilterImage(SkSpecialImage * source,const Context & ctx,SkIPoint * offset) const1439 sk_sp<SkSpecialImage> SkSpecularLightingImageFilter::onFilterImage(SkSpecialImage* source,
1440 const Context& ctx,
1441 SkIPoint* offset) const {
1442 SkIPoint inputOffset = SkIPoint::Make(0, 0);
1443 sk_sp<SkSpecialImage> input(this->filterInput(0, source, ctx, &inputOffset));
1444 if (!input) {
1445 return nullptr;
1446 }
1447
1448 const SkIRect inputBounds = SkIRect::MakeXYWH(inputOffset.x(), inputOffset.y(),
1449 input->width(), input->height());
1450 SkIRect bounds;
1451 if (!this->applyCropRect(ctx, inputBounds, &bounds)) {
1452 return nullptr;
1453 }
1454
1455 offset->fX = bounds.left();
1456 offset->fY = bounds.top();
1457 bounds.offset(-inputOffset);
1458
1459 #if SK_SUPPORT_GPU
1460 if (source->isTextureBacked()) {
1461 SkMatrix matrix(ctx.ctm());
1462 matrix.postTranslate(SkIntToScalar(-offset->fX), SkIntToScalar(-offset->fY));
1463
1464 return this->filterImageGPU(source, input.get(), bounds, matrix, ctx.outputProperties());
1465 }
1466 #endif
1467
1468 if (bounds.width() < 2 || bounds.height() < 2) {
1469 return nullptr;
1470 }
1471
1472 SkBitmap inputBM;
1473
1474 if (!input->getROPixels(&inputBM)) {
1475 return nullptr;
1476 }
1477
1478 if (inputBM.colorType() != kN32_SkColorType) {
1479 return nullptr;
1480 }
1481
1482 if (!inputBM.getPixels()) {
1483 return nullptr;
1484 }
1485
1486 const SkImageInfo info = SkImageInfo::MakeN32Premul(bounds.width(), bounds.height());
1487
1488 SkBitmap dst;
1489 if (!dst.tryAllocPixels(info)) {
1490 return nullptr;
1491 }
1492
1493 SpecularLightingType lightingType(fKS, fShininess);
1494
1495 SkMatrix matrix(ctx.ctm());
1496 matrix.postTranslate(SkIntToScalar(-inputOffset.x()), SkIntToScalar(-inputOffset.y()));
1497
1498 sk_sp<SkImageFilterLight> transformedLight(light()->transform(matrix));
1499
1500 lightBitmap(lightingType,
1501 transformedLight.get(),
1502 inputBM,
1503 &dst,
1504 surfaceScale(),
1505 bounds);
1506
1507 return SkSpecialImage::MakeFromRaster(SkIRect::MakeWH(bounds.width(), bounds.height()), dst);
1508 }
1509
onMakeColorSpace(SkColorSpaceXformer * xformer) const1510 sk_sp<SkImageFilter> SkSpecularLightingImageFilter::onMakeColorSpace(SkColorSpaceXformer* xformer)
1511 const {
1512 SkASSERT(1 == this->countInputs());
1513
1514 auto input = xformer->apply(this->getInput(0));
1515 auto light = this->light()->makeColorSpace(xformer);
1516 if (input.get() != this->getInput(0) || light.get() != this->light()) {
1517 return SkSpecularLightingImageFilter::Make(std::move(light),
1518 255.0f * this->surfaceScale(), fKS, fShininess,
1519 std::move(input), this->getCropRectIfSet());
1520 }
1521 return this->refMe();
1522 }
1523
1524 #if SK_SUPPORT_GPU
makeFragmentProcessor(sk_sp<GrTextureProxy> proxy,const SkMatrix & matrix,const SkIRect * srcBounds,BoundaryMode boundaryMode) const1525 std::unique_ptr<GrFragmentProcessor> SkSpecularLightingImageFilter::makeFragmentProcessor(
1526 sk_sp<GrTextureProxy> proxy,
1527 const SkMatrix& matrix,
1528 const SkIRect* srcBounds,
1529 BoundaryMode boundaryMode) const {
1530 SkScalar scale = this->surfaceScale() * 255;
1531 return GrSpecularLightingEffect::Make(std::move(proxy), this->refLight(), scale, matrix,
1532 this->ks(), this->shininess(), boundaryMode, srcBounds);
1533 }
1534 #endif
1535
1536 ///////////////////////////////////////////////////////////////////////////////
1537
1538 #if SK_SUPPORT_GPU
1539
emitNormalFunc(BoundaryMode mode,const char * pointToNormalName,const char * sobelFuncName)1540 static SkString emitNormalFunc(BoundaryMode mode,
1541 const char* pointToNormalName,
1542 const char* sobelFuncName) {
1543 SkString result;
1544 switch (mode) {
1545 case kTopLeft_BoundaryMode:
1546 result.printf("\treturn %s(%s(0.0, 0.0, m[4], m[5], m[7], m[8], %g),\n"
1547 "\t %s(0.0, 0.0, m[4], m[7], m[5], m[8], %g),\n"
1548 "\t surfaceScale);\n",
1549 pointToNormalName, sobelFuncName, gTwoThirds,
1550 sobelFuncName, gTwoThirds);
1551 break;
1552 case kTop_BoundaryMode:
1553 result.printf("\treturn %s(%s(0.0, 0.0, m[3], m[5], m[6], m[8], %g),\n"
1554 "\t %s(0.0, 0.0, m[4], m[7], m[5], m[8], %g),\n"
1555 "\t surfaceScale);\n",
1556 pointToNormalName, sobelFuncName, gOneThird,
1557 sobelFuncName, gOneHalf);
1558 break;
1559 case kTopRight_BoundaryMode:
1560 result.printf("\treturn %s(%s( 0.0, 0.0, m[3], m[4], m[6], m[7], %g),\n"
1561 "\t %s(m[3], m[6], m[4], m[7], 0.0, 0.0, %g),\n"
1562 "\t surfaceScale);\n",
1563 pointToNormalName, sobelFuncName, gTwoThirds,
1564 sobelFuncName, gTwoThirds);
1565 break;
1566 case kLeft_BoundaryMode:
1567 result.printf("\treturn %s(%s(m[1], m[2], m[4], m[5], m[7], m[8], %g),\n"
1568 "\t %s( 0.0, 0.0, m[1], m[7], m[2], m[8], %g),\n"
1569 "\t surfaceScale);\n",
1570 pointToNormalName, sobelFuncName, gOneHalf,
1571 sobelFuncName, gOneThird);
1572 break;
1573 case kInterior_BoundaryMode:
1574 result.printf("\treturn %s(%s(m[0], m[2], m[3], m[5], m[6], m[8], %g),\n"
1575 "\t %s(m[0], m[6], m[1], m[7], m[2], m[8], %g),\n"
1576 "\t surfaceScale);\n",
1577 pointToNormalName, sobelFuncName, gOneQuarter,
1578 sobelFuncName, gOneQuarter);
1579 break;
1580 case kRight_BoundaryMode:
1581 result.printf("\treturn %s(%s(m[0], m[1], m[3], m[4], m[6], m[7], %g),\n"
1582 "\t %s(m[0], m[6], m[1], m[7], 0.0, 0.0, %g),\n"
1583 "\t surfaceScale);\n",
1584 pointToNormalName, sobelFuncName, gOneHalf,
1585 sobelFuncName, gOneThird);
1586 break;
1587 case kBottomLeft_BoundaryMode:
1588 result.printf("\treturn %s(%s(m[1], m[2], m[4], m[5], 0.0, 0.0, %g),\n"
1589 "\t %s( 0.0, 0.0, m[1], m[4], m[2], m[5], %g),\n"
1590 "\t surfaceScale);\n",
1591 pointToNormalName, sobelFuncName, gTwoThirds,
1592 sobelFuncName, gTwoThirds);
1593 break;
1594 case kBottom_BoundaryMode:
1595 result.printf("\treturn %s(%s(m[0], m[2], m[3], m[5], 0.0, 0.0, %g),\n"
1596 "\t %s(m[0], m[3], m[1], m[4], m[2], m[5], %g),\n"
1597 "\t surfaceScale);\n",
1598 pointToNormalName, sobelFuncName, gOneThird,
1599 sobelFuncName, gOneHalf);
1600 break;
1601 case kBottomRight_BoundaryMode:
1602 result.printf("\treturn %s(%s(m[0], m[1], m[3], m[4], 0.0, 0.0, %g),\n"
1603 "\t %s(m[0], m[3], m[1], m[4], 0.0, 0.0, %g),\n"
1604 "\t surfaceScale);\n",
1605 pointToNormalName, sobelFuncName, gTwoThirds,
1606 sobelFuncName, gTwoThirds);
1607 break;
1608 default:
1609 SkASSERT(false);
1610 break;
1611 }
1612 return result;
1613 }
1614
1615 class GrGLLightingEffect : public GrGLSLFragmentProcessor {
1616 public:
GrGLLightingEffect()1617 GrGLLightingEffect() : fLight(nullptr) { }
~GrGLLightingEffect()1618 ~GrGLLightingEffect() override { delete fLight; }
1619
1620 void emitCode(EmitArgs&) override;
1621
1622 static inline void GenKey(const GrProcessor&, const GrShaderCaps&, GrProcessorKeyBuilder* b);
1623
1624 protected:
1625 /**
1626 * Subclasses of GrGLLightingEffect must call INHERITED::onSetData();
1627 */
1628 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
1629
1630 virtual void emitLightFunc(GrGLSLUniformHandler*,
1631 GrGLSLFPFragmentBuilder*,
1632 SkString* funcName) = 0;
1633
1634 private:
1635 typedef GrGLSLFragmentProcessor INHERITED;
1636
1637 UniformHandle fImageIncrementUni;
1638 UniformHandle fSurfaceScaleUni;
1639 GrTextureDomain::GLDomain fDomain;
1640 GrGLLight* fLight;
1641 };
1642
1643 ///////////////////////////////////////////////////////////////////////////////
1644
1645 class GrGLDiffuseLightingEffect : public GrGLLightingEffect {
1646 public:
1647 void emitLightFunc(GrGLSLUniformHandler*, GrGLSLFPFragmentBuilder*, SkString* funcName) override;
1648
1649 protected:
1650 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
1651
1652 private:
1653 typedef GrGLLightingEffect INHERITED;
1654
1655 UniformHandle fKDUni;
1656 };
1657
1658 ///////////////////////////////////////////////////////////////////////////////
1659
1660 class GrGLSpecularLightingEffect : public GrGLLightingEffect {
1661 public:
1662 void emitLightFunc(GrGLSLUniformHandler*, GrGLSLFPFragmentBuilder*, SkString* funcName) override;
1663
1664 protected:
1665 void onSetData(const GrGLSLProgramDataManager&, const GrFragmentProcessor&) override;
1666
1667 private:
1668 typedef GrGLLightingEffect INHERITED;
1669
1670 UniformHandle fKSUni;
1671 UniformHandle fShininessUni;
1672 };
1673
1674 ///////////////////////////////////////////////////////////////////////////////
1675
create_domain(GrTextureProxy * proxy,const SkIRect * srcBounds,GrTextureDomain::Mode mode)1676 static GrTextureDomain create_domain(GrTextureProxy* proxy, const SkIRect* srcBounds,
1677 GrTextureDomain::Mode mode) {
1678 if (srcBounds) {
1679 SkRect texelDomain = GrTextureDomain::MakeTexelDomain(*srcBounds, mode);
1680 return GrTextureDomain(proxy, texelDomain, mode, mode);
1681 } else {
1682 return GrTextureDomain::IgnoredDomain();
1683 }
1684 }
1685
GrLightingEffect(ClassID classID,sk_sp<GrTextureProxy> proxy,sk_sp<const SkImageFilterLight> light,SkScalar surfaceScale,const SkMatrix & matrix,BoundaryMode boundaryMode,const SkIRect * srcBounds)1686 GrLightingEffect::GrLightingEffect(ClassID classID,
1687 sk_sp<GrTextureProxy> proxy,
1688 sk_sp<const SkImageFilterLight> light,
1689 SkScalar surfaceScale,
1690 const SkMatrix& matrix,
1691 BoundaryMode boundaryMode,
1692 const SkIRect* srcBounds)
1693 // Perhaps this could advertise the opaque or coverage-as-alpha optimizations?
1694 : INHERITED(classID, kNone_OptimizationFlags)
1695 , fCoordTransform(proxy.get())
1696 , fDomain(create_domain(proxy.get(), srcBounds, GrTextureDomain::kDecal_Mode))
1697 , fTextureSampler(std::move(proxy))
1698 , fLight(std::move(light))
1699 , fSurfaceScale(surfaceScale)
1700 , fFilterMatrix(matrix)
1701 , fBoundaryMode(boundaryMode) {
1702 this->addCoordTransform(&fCoordTransform);
1703 this->setTextureSamplerCnt(1);
1704 }
1705
GrLightingEffect(const GrLightingEffect & that)1706 GrLightingEffect::GrLightingEffect(const GrLightingEffect& that)
1707 : INHERITED(that.classID(), that.optimizationFlags())
1708 , fCoordTransform(that.fCoordTransform)
1709 , fDomain(that.fDomain)
1710 , fTextureSampler(that.fTextureSampler)
1711 , fLight(that.fLight)
1712 , fSurfaceScale(that.fSurfaceScale)
1713 , fFilterMatrix(that.fFilterMatrix)
1714 , fBoundaryMode(that.fBoundaryMode) {
1715 this->addCoordTransform(&fCoordTransform);
1716 this->setTextureSamplerCnt(1);
1717 }
1718
onIsEqual(const GrFragmentProcessor & sBase) const1719 bool GrLightingEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
1720 const GrLightingEffect& s = sBase.cast<GrLightingEffect>();
1721 return fLight->isEqual(*s.fLight) &&
1722 fSurfaceScale == s.fSurfaceScale &&
1723 fBoundaryMode == s.fBoundaryMode;
1724 }
1725
1726 ///////////////////////////////////////////////////////////////////////////////
1727
GrDiffuseLightingEffect(sk_sp<GrTextureProxy> proxy,sk_sp<const SkImageFilterLight> light,SkScalar surfaceScale,const SkMatrix & matrix,SkScalar kd,BoundaryMode boundaryMode,const SkIRect * srcBounds)1728 GrDiffuseLightingEffect::GrDiffuseLightingEffect(sk_sp<GrTextureProxy> proxy,
1729 sk_sp<const SkImageFilterLight>light,
1730 SkScalar surfaceScale,
1731 const SkMatrix& matrix,
1732 SkScalar kd,
1733 BoundaryMode boundaryMode,
1734 const SkIRect* srcBounds)
1735 : INHERITED(kGrDiffuseLightingEffect_ClassID, std::move(proxy), std::move(light),
1736 surfaceScale, matrix, boundaryMode, srcBounds)
1737 , fKD(kd) {}
1738
GrDiffuseLightingEffect(const GrDiffuseLightingEffect & that)1739 GrDiffuseLightingEffect::GrDiffuseLightingEffect(const GrDiffuseLightingEffect& that)
1740 : INHERITED(that), fKD(that.fKD) {}
1741
onIsEqual(const GrFragmentProcessor & sBase) const1742 bool GrDiffuseLightingEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
1743 const GrDiffuseLightingEffect& s = sBase.cast<GrDiffuseLightingEffect>();
1744 return INHERITED::onIsEqual(sBase) && this->kd() == s.kd();
1745 }
1746
onGetGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const1747 void GrDiffuseLightingEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
1748 GrProcessorKeyBuilder* b) const {
1749 GrGLDiffuseLightingEffect::GenKey(*this, caps, b);
1750 }
1751
onCreateGLSLInstance() const1752 GrGLSLFragmentProcessor* GrDiffuseLightingEffect::onCreateGLSLInstance() const {
1753 return new GrGLDiffuseLightingEffect;
1754 }
1755
1756 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDiffuseLightingEffect);
1757
1758 #if GR_TEST_UTILS
1759
random_point3(SkRandom * random)1760 static SkPoint3 random_point3(SkRandom* random) {
1761 return SkPoint3::Make(SkScalarToFloat(random->nextSScalar1()),
1762 SkScalarToFloat(random->nextSScalar1()),
1763 SkScalarToFloat(random->nextSScalar1()));
1764 }
1765
create_random_light(SkRandom * random)1766 static SkImageFilterLight* create_random_light(SkRandom* random) {
1767 int type = random->nextULessThan(3);
1768 switch (type) {
1769 case 0: {
1770 return new SkDistantLight(random_point3(random), random->nextU());
1771 }
1772 case 1: {
1773 return new SkPointLight(random_point3(random), random->nextU());
1774 }
1775 case 2: {
1776 return new SkSpotLight(random_point3(random), random_point3(random),
1777 random->nextUScalar1(), random->nextUScalar1(), random->nextU());
1778 }
1779 default:
1780 SK_ABORT("Unexpected value.");
1781 return nullptr;
1782 }
1783 }
1784
TestCreate(GrProcessorTestData * d)1785 std::unique_ptr<GrFragmentProcessor> GrDiffuseLightingEffect::TestCreate(GrProcessorTestData* d) {
1786 int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
1787 : GrProcessorUnitTest::kAlphaTextureIdx;
1788 sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
1789 SkScalar surfaceScale = d->fRandom->nextSScalar1();
1790 SkScalar kd = d->fRandom->nextUScalar1();
1791 sk_sp<SkImageFilterLight> light(create_random_light(d->fRandom));
1792 SkMatrix matrix;
1793 for (int i = 0; i < 9; i++) {
1794 matrix[i] = d->fRandom->nextUScalar1();
1795 }
1796 SkIRect srcBounds = SkIRect::MakeXYWH(d->fRandom->nextRangeU(0, proxy->width()),
1797 d->fRandom->nextRangeU(0, proxy->height()),
1798 d->fRandom->nextRangeU(0, proxy->width()),
1799 d->fRandom->nextRangeU(0, proxy->height()));
1800 BoundaryMode mode = static_cast<BoundaryMode>(d->fRandom->nextU() % kBoundaryModeCount);
1801 return GrDiffuseLightingEffect::Make(std::move(proxy), std::move(light), surfaceScale, matrix,
1802 kd, mode, &srcBounds);
1803 }
1804 #endif
1805
1806
1807 ///////////////////////////////////////////////////////////////////////////////
1808
emitCode(EmitArgs & args)1809 void GrGLLightingEffect::emitCode(EmitArgs& args) {
1810 const GrLightingEffect& le = args.fFp.cast<GrLightingEffect>();
1811 if (!fLight) {
1812 fLight = le.light()->createGLLight();
1813 }
1814
1815 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
1816 fImageIncrementUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
1817 kHalf2_GrSLType, "ImageIncrement");
1818 fSurfaceScaleUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
1819 kHalf_GrSLType, "SurfaceScale");
1820 fLight->emitLightColorUniform(uniformHandler);
1821 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
1822 SkString lightFunc;
1823 this->emitLightFunc(uniformHandler, fragBuilder, &lightFunc);
1824 const GrShaderVar gSobelArgs[] = {
1825 GrShaderVar("a", kHalf_GrSLType),
1826 GrShaderVar("b", kHalf_GrSLType),
1827 GrShaderVar("c", kHalf_GrSLType),
1828 GrShaderVar("d", kHalf_GrSLType),
1829 GrShaderVar("e", kHalf_GrSLType),
1830 GrShaderVar("f", kHalf_GrSLType),
1831 GrShaderVar("scale", kHalf_GrSLType),
1832 };
1833 SkString sobelFuncName;
1834 SkString coords2D = fragBuilder->ensureCoords2D(args.fTransformedCoords[0]);
1835
1836 fragBuilder->emitFunction(kHalf_GrSLType,
1837 "sobel",
1838 SK_ARRAY_COUNT(gSobelArgs),
1839 gSobelArgs,
1840 "\treturn (-a + b - 2.0 * c + 2.0 * d -e + f) * scale;\n",
1841 &sobelFuncName);
1842 const GrShaderVar gPointToNormalArgs[] = {
1843 GrShaderVar("x", kHalf_GrSLType),
1844 GrShaderVar("y", kHalf_GrSLType),
1845 GrShaderVar("scale", kHalf_GrSLType),
1846 };
1847 SkString pointToNormalName;
1848 fragBuilder->emitFunction(kHalf3_GrSLType,
1849 "pointToNormal",
1850 SK_ARRAY_COUNT(gPointToNormalArgs),
1851 gPointToNormalArgs,
1852 "\treturn normalize(half3(-x * scale, -y * scale, 1));\n",
1853 &pointToNormalName);
1854
1855 const GrShaderVar gInteriorNormalArgs[] = {
1856 GrShaderVar("m", kHalf_GrSLType, 9),
1857 GrShaderVar("surfaceScale", kHalf_GrSLType),
1858 };
1859 SkString normalBody = emitNormalFunc(le.boundaryMode(),
1860 pointToNormalName.c_str(),
1861 sobelFuncName.c_str());
1862 SkString normalName;
1863 fragBuilder->emitFunction(kHalf3_GrSLType,
1864 "normal",
1865 SK_ARRAY_COUNT(gInteriorNormalArgs),
1866 gInteriorNormalArgs,
1867 normalBody.c_str(),
1868 &normalName);
1869
1870 fragBuilder->codeAppendf("\t\tfloat2 coord = %s;\n", coords2D.c_str());
1871 fragBuilder->codeAppend("\t\thalf m[9];\n");
1872
1873 const char* imgInc = uniformHandler->getUniformCStr(fImageIncrementUni);
1874 const char* surfScale = uniformHandler->getUniformCStr(fSurfaceScaleUni);
1875
1876 int index = 0;
1877 for (int dy = 1; dy >= -1; dy--) {
1878 for (int dx = -1; dx <= 1; dx++) {
1879 SkString texCoords;
1880 texCoords.appendf("coord + half2(%d, %d) * %s", dx, dy, imgInc);
1881 SkString temp;
1882 temp.appendf("temp%d", index);
1883 fragBuilder->codeAppendf("half4 %s;", temp.c_str());
1884 fDomain.sampleTexture(fragBuilder,
1885 args.fUniformHandler,
1886 args.fShaderCaps,
1887 le.domain(),
1888 temp.c_str(),
1889 texCoords,
1890 args.fTexSamplers[0]);
1891 fragBuilder->codeAppendf("m[%d] = %s.a;", index, temp.c_str());
1892 index++;
1893 }
1894 }
1895 fragBuilder->codeAppend("\t\thalf3 surfaceToLight = ");
1896 SkString arg;
1897 arg.appendf("%s * m[4]", surfScale);
1898 fLight->emitSurfaceToLight(uniformHandler, fragBuilder, arg.c_str());
1899 fragBuilder->codeAppend(";\n");
1900 fragBuilder->codeAppendf("\t\t%s = %s(%s(m, %s), surfaceToLight, ",
1901 args.fOutputColor, lightFunc.c_str(), normalName.c_str(), surfScale);
1902 fLight->emitLightColor(uniformHandler, fragBuilder, "surfaceToLight");
1903 fragBuilder->codeAppend(");\n");
1904 fragBuilder->codeAppendf("%s *= %s;\n", args.fOutputColor, args.fInputColor);
1905 }
1906
GenKey(const GrProcessor & proc,const GrShaderCaps & caps,GrProcessorKeyBuilder * b)1907 void GrGLLightingEffect::GenKey(const GrProcessor& proc,
1908 const GrShaderCaps& caps, GrProcessorKeyBuilder* b) {
1909 const GrLightingEffect& lighting = proc.cast<GrLightingEffect>();
1910 b->add32(lighting.boundaryMode() << 2 | lighting.light()->type());
1911 b->add32(GrTextureDomain::GLDomain::DomainKey(lighting.domain()));
1912 }
1913
onSetData(const GrGLSLProgramDataManager & pdman,const GrFragmentProcessor & proc)1914 void GrGLLightingEffect::onSetData(const GrGLSLProgramDataManager& pdman,
1915 const GrFragmentProcessor& proc) {
1916 const GrLightingEffect& lighting = proc.cast<GrLightingEffect>();
1917 if (!fLight) {
1918 fLight = lighting.light()->createGLLight();
1919 }
1920
1921 GrTextureProxy* proxy = lighting.textureSampler(0).proxy();
1922 GrTexture* texture = proxy->peekTexture();
1923
1924 float ySign = proxy->origin() == kTopLeft_GrSurfaceOrigin ? -1.0f : 1.0f;
1925 pdman.set2f(fImageIncrementUni, 1.0f / texture->width(), ySign / texture->height());
1926 pdman.set1f(fSurfaceScaleUni, lighting.surfaceScale());
1927 sk_sp<SkImageFilterLight> transformedLight(
1928 lighting.light()->transform(lighting.filterMatrix()));
1929 fDomain.setData(pdman, lighting.domain(), proxy, lighting.textureSampler(0).samplerState());
1930 fLight->setData(pdman, transformedLight.get());
1931 }
1932
1933 ///////////////////////////////////////////////////////////////////////////////
1934
1935 ///////////////////////////////////////////////////////////////////////////////
1936
emitLightFunc(GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,SkString * funcName)1937 void GrGLDiffuseLightingEffect::emitLightFunc(GrGLSLUniformHandler* uniformHandler,
1938 GrGLSLFPFragmentBuilder* fragBuilder,
1939 SkString* funcName) {
1940 const char* kd;
1941 fKDUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "KD", &kd);
1942
1943 const GrShaderVar gLightArgs[] = {
1944 GrShaderVar("normal", kHalf3_GrSLType),
1945 GrShaderVar("surfaceToLight", kHalf3_GrSLType),
1946 GrShaderVar("lightColor", kHalf3_GrSLType)
1947 };
1948 SkString lightBody;
1949 lightBody.appendf("\thalf colorScale = %s * dot(normal, surfaceToLight);\n", kd);
1950 lightBody.appendf("\treturn half4(lightColor * saturate(colorScale), 1.0);\n");
1951 fragBuilder->emitFunction(kHalf4_GrSLType,
1952 "light",
1953 SK_ARRAY_COUNT(gLightArgs),
1954 gLightArgs,
1955 lightBody.c_str(),
1956 funcName);
1957 }
1958
onSetData(const GrGLSLProgramDataManager & pdman,const GrFragmentProcessor & proc)1959 void GrGLDiffuseLightingEffect::onSetData(const GrGLSLProgramDataManager& pdman,
1960 const GrFragmentProcessor& proc) {
1961 INHERITED::onSetData(pdman, proc);
1962 const GrDiffuseLightingEffect& diffuse = proc.cast<GrDiffuseLightingEffect>();
1963 pdman.set1f(fKDUni, diffuse.kd());
1964 }
1965
1966 ///////////////////////////////////////////////////////////////////////////////
1967
GrSpecularLightingEffect(sk_sp<GrTextureProxy> proxy,sk_sp<const SkImageFilterLight> light,SkScalar surfaceScale,const SkMatrix & matrix,SkScalar ks,SkScalar shininess,BoundaryMode boundaryMode,const SkIRect * srcBounds)1968 GrSpecularLightingEffect::GrSpecularLightingEffect(sk_sp<GrTextureProxy> proxy,
1969 sk_sp<const SkImageFilterLight> light,
1970 SkScalar surfaceScale,
1971 const SkMatrix& matrix,
1972 SkScalar ks,
1973 SkScalar shininess,
1974 BoundaryMode boundaryMode,
1975 const SkIRect* srcBounds)
1976 : INHERITED(kGrSpecularLightingEffect_ClassID, std::move(proxy), std::move(light),
1977 surfaceScale, matrix, boundaryMode, srcBounds)
1978 , fKS(ks)
1979 , fShininess(shininess) {}
1980
GrSpecularLightingEffect(const GrSpecularLightingEffect & that)1981 GrSpecularLightingEffect::GrSpecularLightingEffect(const GrSpecularLightingEffect& that)
1982 : INHERITED(that), fKS(that.fKS), fShininess(that.fShininess) {}
1983
onIsEqual(const GrFragmentProcessor & sBase) const1984 bool GrSpecularLightingEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
1985 const GrSpecularLightingEffect& s = sBase.cast<GrSpecularLightingEffect>();
1986 return INHERITED::onIsEqual(sBase) &&
1987 this->ks() == s.ks() &&
1988 this->shininess() == s.shininess();
1989 }
1990
onGetGLSLProcessorKey(const GrShaderCaps & caps,GrProcessorKeyBuilder * b) const1991 void GrSpecularLightingEffect::onGetGLSLProcessorKey(const GrShaderCaps& caps,
1992 GrProcessorKeyBuilder* b) const {
1993 GrGLSpecularLightingEffect::GenKey(*this, caps, b);
1994 }
1995
onCreateGLSLInstance() const1996 GrGLSLFragmentProcessor* GrSpecularLightingEffect::onCreateGLSLInstance() const {
1997 return new GrGLSpecularLightingEffect;
1998 }
1999
2000 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrSpecularLightingEffect);
2001
2002 #if GR_TEST_UTILS
TestCreate(GrProcessorTestData * d)2003 std::unique_ptr<GrFragmentProcessor> GrSpecularLightingEffect::TestCreate(GrProcessorTestData* d) {
2004 int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx
2005 : GrProcessorUnitTest::kAlphaTextureIdx;
2006 sk_sp<GrTextureProxy> proxy = d->textureProxy(texIdx);
2007 SkScalar surfaceScale = d->fRandom->nextSScalar1();
2008 SkScalar ks = d->fRandom->nextUScalar1();
2009 SkScalar shininess = d->fRandom->nextUScalar1();
2010 sk_sp<SkImageFilterLight> light(create_random_light(d->fRandom));
2011 SkMatrix matrix;
2012 for (int i = 0; i < 9; i++) {
2013 matrix[i] = d->fRandom->nextUScalar1();
2014 }
2015 BoundaryMode mode = static_cast<BoundaryMode>(d->fRandom->nextU() % kBoundaryModeCount);
2016 SkIRect srcBounds = SkIRect::MakeXYWH(d->fRandom->nextRangeU(0, proxy->width()),
2017 d->fRandom->nextRangeU(0, proxy->height()),
2018 d->fRandom->nextRangeU(0, proxy->width()),
2019 d->fRandom->nextRangeU(0, proxy->height()));
2020 return GrSpecularLightingEffect::Make(std::move(proxy), std::move(light), surfaceScale, matrix,
2021 ks, shininess, mode, &srcBounds);
2022 }
2023 #endif
2024
2025 ///////////////////////////////////////////////////////////////////////////////
2026
emitLightFunc(GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,SkString * funcName)2027 void GrGLSpecularLightingEffect::emitLightFunc(GrGLSLUniformHandler* uniformHandler,
2028 GrGLSLFPFragmentBuilder* fragBuilder,
2029 SkString* funcName) {
2030 const char* ks;
2031 const char* shininess;
2032
2033 fKSUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType, "KS", &ks);
2034 fShininessUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
2035 kHalf_GrSLType,
2036 "Shininess",
2037 &shininess);
2038
2039 const GrShaderVar gLightArgs[] = {
2040 GrShaderVar("normal", kHalf3_GrSLType),
2041 GrShaderVar("surfaceToLight", kHalf3_GrSLType),
2042 GrShaderVar("lightColor", kHalf3_GrSLType)
2043 };
2044 SkString lightBody;
2045 lightBody.appendf("\thalf3 halfDir = half3(normalize(surfaceToLight + half3(0, 0, 1)));\n");
2046 lightBody.appendf("\tfloat colorScale = %s * pow(dot(normal, halfDir), %s);\n",
2047 ks, shininess);
2048 lightBody.appendf("\thalf3 color = lightColor * saturate(colorScale);\n");
2049 lightBody.appendf("\treturn half4(color, max(max(color.r, color.g), color.b));\n");
2050 fragBuilder->emitFunction(kHalf4_GrSLType,
2051 "light",
2052 SK_ARRAY_COUNT(gLightArgs),
2053 gLightArgs,
2054 lightBody.c_str(),
2055 funcName);
2056 }
2057
onSetData(const GrGLSLProgramDataManager & pdman,const GrFragmentProcessor & effect)2058 void GrGLSpecularLightingEffect::onSetData(const GrGLSLProgramDataManager& pdman,
2059 const GrFragmentProcessor& effect) {
2060 INHERITED::onSetData(pdman, effect);
2061 const GrSpecularLightingEffect& spec = effect.cast<GrSpecularLightingEffect>();
2062 pdman.set1f(fKSUni, spec.ks());
2063 pdman.set1f(fShininessUni, spec.shininess());
2064 }
2065
2066 ///////////////////////////////////////////////////////////////////////////////
emitLightColorUniform(GrGLSLUniformHandler * uniformHandler)2067 void GrGLLight::emitLightColorUniform(GrGLSLUniformHandler* uniformHandler) {
2068 fColorUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType, "LightColor");
2069 }
2070
emitLightColor(GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,const char * surfaceToLight)2071 void GrGLLight::emitLightColor(GrGLSLUniformHandler* uniformHandler,
2072 GrGLSLFPFragmentBuilder* fragBuilder,
2073 const char *surfaceToLight) {
2074 fragBuilder->codeAppend(uniformHandler->getUniformCStr(this->lightColorUni()));
2075 }
2076
setData(const GrGLSLProgramDataManager & pdman,const SkImageFilterLight * light) const2077 void GrGLLight::setData(const GrGLSLProgramDataManager& pdman,
2078 const SkImageFilterLight* light) const {
2079 setUniformPoint3(pdman, fColorUni,
2080 light->color().makeScale(SkScalarInvert(SkIntToScalar(255))));
2081 }
2082
2083 ///////////////////////////////////////////////////////////////////////////////
2084
setData(const GrGLSLProgramDataManager & pdman,const SkImageFilterLight * light) const2085 void GrGLDistantLight::setData(const GrGLSLProgramDataManager& pdman,
2086 const SkImageFilterLight* light) const {
2087 INHERITED::setData(pdman, light);
2088 SkASSERT(light->type() == SkImageFilterLight::kDistant_LightType);
2089 const SkDistantLight* distantLight = static_cast<const SkDistantLight*>(light);
2090 setUniformNormal3(pdman, fDirectionUni, distantLight->direction());
2091 }
2092
emitSurfaceToLight(GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,const char * z)2093 void GrGLDistantLight::emitSurfaceToLight(GrGLSLUniformHandler* uniformHandler,
2094 GrGLSLFPFragmentBuilder* fragBuilder,
2095 const char* z) {
2096 const char* dir;
2097 fDirectionUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType,
2098 "LightDirection", &dir);
2099 fragBuilder->codeAppend(dir);
2100 }
2101
2102 ///////////////////////////////////////////////////////////////////////////////
2103
setData(const GrGLSLProgramDataManager & pdman,const SkImageFilterLight * light) const2104 void GrGLPointLight::setData(const GrGLSLProgramDataManager& pdman,
2105 const SkImageFilterLight* light) const {
2106 INHERITED::setData(pdman, light);
2107 SkASSERT(light->type() == SkImageFilterLight::kPoint_LightType);
2108 const SkPointLight* pointLight = static_cast<const SkPointLight*>(light);
2109 setUniformPoint3(pdman, fLocationUni, pointLight->location());
2110 }
2111
emitSurfaceToLight(GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,const char * z)2112 void GrGLPointLight::emitSurfaceToLight(GrGLSLUniformHandler* uniformHandler,
2113 GrGLSLFPFragmentBuilder* fragBuilder,
2114 const char* z) {
2115 const char* loc;
2116 fLocationUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType,
2117 "LightLocation", &loc);
2118 fragBuilder->codeAppendf("normalize(%s - half3(sk_FragCoord.xy, %s))",
2119 loc, z);
2120 }
2121
2122 ///////////////////////////////////////////////////////////////////////////////
2123
setData(const GrGLSLProgramDataManager & pdman,const SkImageFilterLight * light) const2124 void GrGLSpotLight::setData(const GrGLSLProgramDataManager& pdman,
2125 const SkImageFilterLight* light) const {
2126 INHERITED::setData(pdman, light);
2127 SkASSERT(light->type() == SkImageFilterLight::kSpot_LightType);
2128 const SkSpotLight* spotLight = static_cast<const SkSpotLight *>(light);
2129 setUniformPoint3(pdman, fLocationUni, spotLight->location());
2130 pdman.set1f(fExponentUni, spotLight->specularExponent());
2131 pdman.set1f(fCosInnerConeAngleUni, spotLight->cosInnerConeAngle());
2132 pdman.set1f(fCosOuterConeAngleUni, spotLight->cosOuterConeAngle());
2133 pdman.set1f(fConeScaleUni, spotLight->coneScale());
2134 setUniformNormal3(pdman, fSUni, spotLight->s());
2135 }
2136
emitSurfaceToLight(GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,const char * z)2137 void GrGLSpotLight::emitSurfaceToLight(GrGLSLUniformHandler* uniformHandler,
2138 GrGLSLFPFragmentBuilder* fragBuilder,
2139 const char* z) {
2140 const char* location;
2141 fLocationUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType,
2142 "LightLocation", &location);
2143
2144 fragBuilder->codeAppendf("normalize(%s - half3(sk_FragCoord.xy, %s))",
2145 location, z);
2146 }
2147
emitLightColor(GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,const char * surfaceToLight)2148 void GrGLSpotLight::emitLightColor(GrGLSLUniformHandler* uniformHandler,
2149 GrGLSLFPFragmentBuilder* fragBuilder,
2150 const char *surfaceToLight) {
2151
2152 const char* color = uniformHandler->getUniformCStr(this->lightColorUni()); // created by parent class.
2153
2154 const char* exponent;
2155 const char* cosInner;
2156 const char* cosOuter;
2157 const char* coneScale;
2158 const char* s;
2159 fExponentUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
2160 "Exponent", &exponent);
2161 fCosInnerConeAngleUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
2162 "CosInnerConeAngle", &cosInner);
2163 fCosOuterConeAngleUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
2164 "CosOuterConeAngle", &cosOuter);
2165 fConeScaleUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf_GrSLType,
2166 "ConeScale", &coneScale);
2167 fSUni = uniformHandler->addUniform(kFragment_GrShaderFlag, kHalf3_GrSLType, "S", &s);
2168
2169 const GrShaderVar gLightColorArgs[] = {
2170 GrShaderVar("surfaceToLight", kHalf3_GrSLType)
2171 };
2172 SkString lightColorBody;
2173 lightColorBody.appendf("\thalf cosAngle = -dot(surfaceToLight, %s);\n", s);
2174 lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosOuter);
2175 lightColorBody.appendf("\t\treturn half3(0);\n");
2176 lightColorBody.appendf("\t}\n");
2177 lightColorBody.appendf("\thalf scale = pow(cosAngle, %s);\n", exponent);
2178 lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosInner);
2179 lightColorBody.appendf("\t\treturn %s * scale * (cosAngle - %s) * %s;\n",
2180 color, cosOuter, coneScale);
2181 lightColorBody.appendf("\t}\n");
2182 lightColorBody.appendf("\treturn %s;\n", color);
2183 fragBuilder->emitFunction(kHalf3_GrSLType,
2184 "lightColor",
2185 SK_ARRAY_COUNT(gLightColorArgs),
2186 gLightColorArgs,
2187 lightColorBody.c_str(),
2188 &fLightColorFunc);
2189
2190 fragBuilder->codeAppendf("%s(%s)", fLightColorFunc.c_str(), surfaceToLight);
2191 }
2192
2193 #endif
2194
RegisterFlattenables()2195 void SkLightingImageFilter::RegisterFlattenables() {
2196 SK_REGISTER_FLATTENABLE(SkDiffuseLightingImageFilter);
2197 SK_REGISTER_FLATTENABLE(SkSpecularLightingImageFilter);
2198 }
2199