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