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