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