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 "SkDevice.h"
12 #include "SkPoint3.h"
13 #include "SkReadBuffer.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 "GrFragmentProcessor.h"
21 #include "GrInvariantOutput.h"
22 #include "GrPaint.h"
23 #include "SkGr.h"
24 #include "effects/GrSingleTextureEffect.h"
25 #include "effects/GrTextureDomain.h"
26 #include "glsl/GrGLSLFragmentProcessor.h"
27 #include "glsl/GrGLSLFragmentShaderBuilder.h"
28 #include "glsl/GrGLSLProgramDataManager.h"
29 #include "glsl/GrGLSLUniformHandler.h"
30
31 class GrGLDiffuseLightingEffect;
32 class GrGLSpecularLightingEffect;
33
34 // For brevity
35 typedef GrGLSLProgramDataManager::UniformHandle UniformHandle;
36 #endif
37
38 namespace {
39
40 const SkScalar gOneThird = SkIntToScalar(1) / 3;
41 const SkScalar gTwoThirds = SkIntToScalar(2) / 3;
42 const SkScalar gOneHalf = 0.5f;
43 const SkScalar gOneQuarter = 0.25f;
44
45 #if SK_SUPPORT_GPU
setUniformPoint3(const GrGLSLProgramDataManager & pdman,UniformHandle uni,const SkPoint3 & point)46 void setUniformPoint3(const GrGLSLProgramDataManager& pdman, UniformHandle uni,
47 const SkPoint3& point) {
48 GR_STATIC_ASSERT(sizeof(SkPoint3) == 3 * sizeof(float));
49 pdman.set3fv(uni, 1, &point.fX);
50 }
51
setUniformNormal3(const GrGLSLProgramDataManager & pdman,UniformHandle uni,const SkPoint3 & point)52 void setUniformNormal3(const GrGLSLProgramDataManager& pdman, UniformHandle uni,
53 const SkPoint3& point) {
54 setUniformPoint3(pdman, uni, point);
55 }
56 #endif
57
58 // Shift matrix components to the left, as we advance pixels to the right.
shiftMatrixLeft(int m[9])59 inline void shiftMatrixLeft(int m[9]) {
60 m[0] = m[1];
61 m[3] = m[4];
62 m[6] = m[7];
63 m[1] = m[2];
64 m[4] = m[5];
65 m[7] = m[8];
66 }
67
fast_normalize(SkPoint3 * vector)68 static inline void fast_normalize(SkPoint3* vector) {
69 // add a tiny bit so we don't have to worry about divide-by-zero
70 SkScalar magSq = vector->dot(*vector) + SK_ScalarNearlyZero;
71 SkScalar scale = sk_float_rsqrt(magSq);
72 vector->fX *= scale;
73 vector->fY *= scale;
74 vector->fZ *= scale;
75 }
76
77 class DiffuseLightingType {
78 public:
DiffuseLightingType(SkScalar kd)79 DiffuseLightingType(SkScalar kd)
80 : fKD(kd) {}
light(const SkPoint3 & normal,const SkPoint3 & surfaceTolight,const SkPoint3 & lightColor) const81 SkPMColor light(const SkPoint3& normal, const SkPoint3& surfaceTolight,
82 const SkPoint3& lightColor) const {
83 SkScalar colorScale = SkScalarMul(fKD, normal.dot(surfaceTolight));
84 colorScale = SkScalarClampMax(colorScale, SK_Scalar1);
85 SkPoint3 color = lightColor.makeScale(colorScale);
86 return SkPackARGB32(255,
87 SkClampMax(SkScalarRoundToInt(color.fX), 255),
88 SkClampMax(SkScalarRoundToInt(color.fY), 255),
89 SkClampMax(SkScalarRoundToInt(color.fZ), 255));
90 }
91 private:
92 SkScalar fKD;
93 };
94
max_component(const SkPoint3 & p)95 static SkScalar max_component(const SkPoint3& p) {
96 return p.x() > p.y() ? (p.x() > p.z() ? p.x() : p.z()) : (p.y() > p.z() ? p.y() : p.z());
97 }
98
99 class SpecularLightingType {
100 public:
SpecularLightingType(SkScalar ks,SkScalar shininess)101 SpecularLightingType(SkScalar ks, SkScalar shininess)
102 : fKS(ks), fShininess(shininess) {}
light(const SkPoint3 & normal,const SkPoint3 & surfaceTolight,const SkPoint3 & lightColor) const103 SkPMColor light(const SkPoint3& normal, const SkPoint3& surfaceTolight,
104 const SkPoint3& lightColor) const {
105 SkPoint3 halfDir(surfaceTolight);
106 halfDir.fZ += SK_Scalar1; // eye position is always (0, 0, 1)
107 fast_normalize(&halfDir);
108 SkScalar colorScale = SkScalarMul(fKS,
109 SkScalarPow(normal.dot(halfDir), fShininess));
110 colorScale = SkScalarClampMax(colorScale, SK_Scalar1);
111 SkPoint3 color = lightColor.makeScale(colorScale);
112 return SkPackARGB32(SkClampMax(SkScalarRoundToInt(max_component(color)), 255),
113 SkClampMax(SkScalarRoundToInt(color.fX), 255),
114 SkClampMax(SkScalarRoundToInt(color.fY), 255),
115 SkClampMax(SkScalarRoundToInt(color.fZ), 255));
116 }
117 private:
118 SkScalar fKS;
119 SkScalar fShininess;
120 };
121
sobel(int a,int b,int c,int d,int e,int f,SkScalar scale)122 inline SkScalar sobel(int a, int b, int c, int d, int e, int f, SkScalar scale) {
123 return SkScalarMul(SkIntToScalar(-a + b - 2 * c + 2 * d -e + f), scale);
124 }
125
pointToNormal(SkScalar x,SkScalar y,SkScalar surfaceScale)126 inline SkPoint3 pointToNormal(SkScalar x, SkScalar y, SkScalar surfaceScale) {
127 SkPoint3 vector = SkPoint3::Make(SkScalarMul(-x, surfaceScale),
128 SkScalarMul(-y, surfaceScale),
129 SK_Scalar1);
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(SkImageFilterLight * light,SkScalar surfaceScale,SkImageFilter * input,const CropRect * cropRect)350 SkLightingImageFilterInternal(SkImageFilterLight* light,
351 SkScalar surfaceScale,
352 SkImageFilter* input,
353 const CropRect* cropRect)
354 : INHERITED(light, surfaceScale, input, cropRect) {}
355
356 #if SK_SUPPORT_GPU
canFilterImageGPU() const357 bool canFilterImageGPU() const override { return true; }
358 bool filterImageGPUDeprecated(Proxy*, const SkBitmap& src, const Context&,
359 SkBitmap* result, SkIPoint* offset) const override;
360 virtual GrFragmentProcessor* getFragmentProcessor(GrTexture*,
361 const SkMatrix&,
362 const SkIRect* srcBounds,
363 BoundaryMode boundaryMode) const = 0;
364 #endif
365 private:
366 #if SK_SUPPORT_GPU
367 void drawRect(GrDrawContext* drawContext,
368 GrTexture* src,
369 const SkMatrix& matrix,
370 const GrClip& clip,
371 const SkRect& dstRect,
372 BoundaryMode boundaryMode,
373 const SkIRect* srcBounds,
374 const SkIRect& bounds) const;
375 #endif
376 typedef SkLightingImageFilter INHERITED;
377 };
378
379 #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) const380 void SkLightingImageFilterInternal::drawRect(GrDrawContext* drawContext,
381 GrTexture* src,
382 const SkMatrix& matrix,
383 const GrClip& clip,
384 const SkRect& dstRect,
385 BoundaryMode boundaryMode,
386 const SkIRect* srcBounds,
387 const SkIRect& bounds) const {
388 SkRect srcRect = dstRect.makeOffset(SkIntToScalar(bounds.x()), SkIntToScalar(bounds.y()));
389 GrPaint paint;
390 GrFragmentProcessor* fp = this->getFragmentProcessor(src, matrix, srcBounds, boundaryMode);
391 paint.addColorFragmentProcessor(fp)->unref();
392 paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
393 drawContext->fillRectToRect(clip, paint, SkMatrix::I(), dstRect, srcRect);
394 }
395
filterImageGPUDeprecated(Proxy * proxy,const SkBitmap & src,const Context & ctx,SkBitmap * result,SkIPoint * offset) const396 bool SkLightingImageFilterInternal::filterImageGPUDeprecated(Proxy* proxy,
397 const SkBitmap& src,
398 const Context& ctx,
399 SkBitmap* result,
400 SkIPoint* offset) const {
401 SkBitmap input = src;
402 SkIPoint srcOffset = SkIPoint::Make(0, 0);
403 if (!this->filterInputGPUDeprecated(0, proxy, src, ctx, &input, &srcOffset)) {
404 return false;
405 }
406 SkIRect srcBounds = input.bounds();
407 srcBounds.offset(srcOffset);
408 SkIRect bounds;
409 if (!this->applyCropRect(ctx, srcBounds, &bounds)) {
410 return false;
411 }
412 SkRect dstRect = SkRect::MakeWH(SkIntToScalar(bounds.width()),
413 SkIntToScalar(bounds.height()));
414 GrTexture* srcTexture = input.getTexture();
415 GrContext* context = srcTexture->getContext();
416
417 GrSurfaceDesc desc;
418 desc.fFlags = kRenderTarget_GrSurfaceFlag,
419 desc.fWidth = bounds.width();
420 desc.fHeight = bounds.height();
421 desc.fConfig = kRGBA_8888_GrPixelConfig;
422
423 SkAutoTUnref<GrTexture> dst(context->textureProvider()->createApproxTexture(desc));
424 if (!dst) {
425 return false;
426 }
427
428 // setup new clip
429 GrClip clip(dstRect);
430
431 offset->fX = bounds.left();
432 offset->fY = bounds.top();
433 SkMatrix matrix(ctx.ctm());
434 matrix.postTranslate(SkIntToScalar(-bounds.left()), SkIntToScalar(-bounds.top()));
435 bounds.offset(-srcOffset);
436 srcBounds.offset(-srcOffset);
437 SkRect topLeft = SkRect::MakeXYWH(0, 0, 1, 1);
438 SkRect top = SkRect::MakeXYWH(1, 0, dstRect.width() - 2, 1);
439 SkRect topRight = SkRect::MakeXYWH(dstRect.width() - 1, 0, 1, 1);
440 SkRect left = SkRect::MakeXYWH(0, 1, 1, dstRect.height() - 2);
441 SkRect interior = dstRect.makeInset(1, 1);
442 SkRect right = SkRect::MakeXYWH(dstRect.width() - 1, 1, 1, dstRect.height() - 2);
443 SkRect bottomLeft = SkRect::MakeXYWH(0, dstRect.height() - 1, 1, 1);
444 SkRect bottom = SkRect::MakeXYWH(1, dstRect.height() - 1, dstRect.width() - 2, 1);
445 SkRect bottomRight = SkRect::MakeXYWH(dstRect.width() - 1, dstRect.height() - 1, 1, 1);
446
447 SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(dst->asRenderTarget()));
448 if (!drawContext) {
449 return false;
450 }
451
452 const SkIRect* pSrcBounds = srcBounds.contains(bounds) ? nullptr : &srcBounds;
453 this->drawRect(drawContext, srcTexture, matrix, clip, topLeft, kTopLeft_BoundaryMode,
454 pSrcBounds, bounds);
455 this->drawRect(drawContext, srcTexture, matrix, clip, top, kTop_BoundaryMode,
456 pSrcBounds, bounds);
457 this->drawRect(drawContext, srcTexture, matrix, clip, topRight, kTopRight_BoundaryMode,
458 pSrcBounds, bounds);
459 this->drawRect(drawContext, srcTexture, matrix, clip, left, kLeft_BoundaryMode,
460 pSrcBounds, bounds);
461 this->drawRect(drawContext, srcTexture, matrix, clip, interior, kInterior_BoundaryMode,
462 pSrcBounds, bounds);
463 this->drawRect(drawContext, srcTexture, matrix, clip, right, kRight_BoundaryMode,
464 pSrcBounds, bounds);
465 this->drawRect(drawContext, srcTexture, matrix, clip, bottomLeft, kBottomLeft_BoundaryMode,
466 pSrcBounds, bounds);
467 this->drawRect(drawContext, srcTexture, matrix, clip, bottom, kBottom_BoundaryMode,
468 pSrcBounds, bounds);
469 this->drawRect(drawContext, srcTexture, matrix, clip, bottomRight,
470 kBottomRight_BoundaryMode, pSrcBounds, bounds);
471 GrWrapTextureInBitmap(dst, bounds.width(), bounds.height(), false, result);
472 return true;
473 }
474 #endif
475
476 class SkDiffuseLightingImageFilter : public SkLightingImageFilterInternal {
477 public:
478 static SkImageFilter* Create(SkImageFilterLight* light, SkScalar surfaceScale,
479 SkScalar kd, SkImageFilter*,
480 const CropRect*);
481
482 SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDiffuseLightingImageFilter)483 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDiffuseLightingImageFilter)
484 SkScalar kd() const { return fKD; }
485
486 protected:
487 SkDiffuseLightingImageFilter(SkImageFilterLight* light, SkScalar surfaceScale,
488 SkScalar kd, SkImageFilter* input, const CropRect* cropRect);
489 void flatten(SkWriteBuffer& buffer) const override;
490 bool onFilterImageDeprecated(Proxy*, const SkBitmap& src, const Context&,
491 SkBitmap* result, SkIPoint* offset) const override;
492 #if SK_SUPPORT_GPU
493 GrFragmentProcessor* getFragmentProcessor(GrTexture*, const SkMatrix&, const SkIRect* bounds,
494 BoundaryMode) const override;
495 #endif
496
497 private:
498 friend class SkLightingImageFilter;
499 typedef SkLightingImageFilterInternal INHERITED;
500 SkScalar fKD;
501 };
502
503 class SkSpecularLightingImageFilter : public SkLightingImageFilterInternal {
504 public:
505 static SkImageFilter* Create(SkImageFilterLight* light, SkScalar surfaceScale,
506 SkScalar ks, SkScalar shininess, SkImageFilter*, const CropRect*);
507
508 SK_TO_STRING_OVERRIDE()
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSpecularLightingImageFilter)509 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSpecularLightingImageFilter)
510
511 SkScalar ks() const { return fKS; }
shininess() const512 SkScalar shininess() const { return fShininess; }
513
514 protected:
515 SkSpecularLightingImageFilter(SkImageFilterLight* light, SkScalar surfaceScale, SkScalar ks,
516 SkScalar shininess, SkImageFilter* input, const CropRect*);
517 void flatten(SkWriteBuffer& buffer) const override;
518 bool onFilterImageDeprecated(Proxy*, const SkBitmap& src, const Context&,
519 SkBitmap* result, SkIPoint* offset) const override;
520 #if SK_SUPPORT_GPU
521 GrFragmentProcessor* getFragmentProcessor(GrTexture*, const SkMatrix&, const SkIRect* bounds,
522 BoundaryMode) const override;
523 #endif
524
525 private:
526 SkScalar fKS;
527 SkScalar fShininess;
528 friend class SkLightingImageFilter;
529 typedef SkLightingImageFilterInternal INHERITED;
530 };
531
532 #if SK_SUPPORT_GPU
533
534 class GrLightingEffect : public GrSingleTextureEffect {
535 public:
536 GrLightingEffect(GrTexture* texture, const SkImageFilterLight* light, SkScalar surfaceScale,
537 const SkMatrix& matrix, BoundaryMode boundaryMode, const SkIRect* srcBounds);
538 ~GrLightingEffect() override;
539
light() const540 const SkImageFilterLight* light() const { return fLight; }
surfaceScale() const541 SkScalar surfaceScale() const { return fSurfaceScale; }
filterMatrix() const542 const SkMatrix& filterMatrix() const { return fFilterMatrix; }
boundaryMode() const543 BoundaryMode boundaryMode() const { return fBoundaryMode; }
domain() const544 const GrTextureDomain& domain() const { return fDomain; }
545
546 protected:
547 bool onIsEqual(const GrFragmentProcessor&) const override;
548
onComputeInvariantOutput(GrInvariantOutput * inout) const549 void onComputeInvariantOutput(GrInvariantOutput* inout) const override {
550 // lighting shaders are complicated. We just throw up our hands.
551 inout->mulByUnknownFourComponents();
552 }
553
554 private:
555 const SkImageFilterLight* fLight;
556 SkScalar fSurfaceScale;
557 SkMatrix fFilterMatrix;
558 BoundaryMode fBoundaryMode;
559 GrTextureDomain fDomain;
560
561 typedef GrSingleTextureEffect INHERITED;
562 };
563
564 class GrDiffuseLightingEffect : public GrLightingEffect {
565 public:
Create(GrTexture * texture,const SkImageFilterLight * light,SkScalar surfaceScale,const SkMatrix & matrix,SkScalar kd,BoundaryMode boundaryMode,const SkIRect * srcBounds)566 static GrFragmentProcessor* Create(GrTexture* texture,
567 const SkImageFilterLight* light,
568 SkScalar surfaceScale,
569 const SkMatrix& matrix,
570 SkScalar kd,
571 BoundaryMode boundaryMode,
572 const SkIRect* srcBounds) {
573 return new GrDiffuseLightingEffect(texture, light, surfaceScale, matrix, kd, boundaryMode,
574 srcBounds);
575 }
576
name() const577 const char* name() const override { return "DiffuseLighting"; }
578
kd() const579 SkScalar kd() const { return fKD; }
580
581 private:
582 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
583
584 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
585
586 bool onIsEqual(const GrFragmentProcessor&) const override;
587
588 GrDiffuseLightingEffect(GrTexture* texture,
589 const SkImageFilterLight* light,
590 SkScalar surfaceScale,
591 const SkMatrix& matrix,
592 SkScalar kd,
593 BoundaryMode boundaryMode,
594 const SkIRect* srcBounds);
595
596 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
597 typedef GrLightingEffect INHERITED;
598 SkScalar fKD;
599 };
600
601 class GrSpecularLightingEffect : public GrLightingEffect {
602 public:
Create(GrTexture * texture,const SkImageFilterLight * light,SkScalar surfaceScale,const SkMatrix & matrix,SkScalar ks,SkScalar shininess,BoundaryMode boundaryMode,const SkIRect * srcBounds)603 static GrFragmentProcessor* Create(GrTexture* texture,
604 const SkImageFilterLight* light,
605 SkScalar surfaceScale,
606 const SkMatrix& matrix,
607 SkScalar ks,
608 SkScalar shininess,
609 BoundaryMode boundaryMode,
610 const SkIRect* srcBounds) {
611 return new GrSpecularLightingEffect(texture, light, surfaceScale, matrix, ks, shininess,
612 boundaryMode, srcBounds);
613 }
614
name() const615 const char* name() const override { return "SpecularLighting"; }
616
617 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override;
618
ks() const619 SkScalar ks() const { return fKS; }
shininess() const620 SkScalar shininess() const { return fShininess; }
621
622 private:
623 void onGetGLSLProcessorKey(const GrGLSLCaps&, GrProcessorKeyBuilder*) const override;
624
625 bool onIsEqual(const GrFragmentProcessor&) const override;
626
627 GrSpecularLightingEffect(GrTexture* texture,
628 const SkImageFilterLight* light,
629 SkScalar surfaceScale,
630 const SkMatrix& matrix,
631 SkScalar ks,
632 SkScalar shininess,
633 BoundaryMode boundaryMode,
634 const SkIRect* srcBounds);
635
636 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
637 typedef GrLightingEffect INHERITED;
638 SkScalar fKS;
639 SkScalar fShininess;
640 };
641
642 ///////////////////////////////////////////////////////////////////////////////
643
644 class GrGLLight {
645 public:
~GrGLLight()646 virtual ~GrGLLight() {}
647
648 /**
649 * This is called by GrGLLightingEffect::emitCode() before either of the two virtual functions
650 * below. It adds a vec3f uniform visible in the FS that represents the constant light color.
651 */
652 void emitLightColorUniform(GrGLSLUniformHandler*);
653
654 /**
655 * These two functions are called from GrGLLightingEffect's emitCode() function.
656 * emitSurfaceToLight places an expression in param out that is the vector from the surface to
657 * the light. The expression will be used in the FS. emitLightColor writes an expression into
658 * the FS that is the color of the light. Either function may add functions and/or uniforms to
659 * the FS. The default of emitLightColor appends the name of the constant light color uniform
660 * and so this function only needs to be overridden if the light color varies spatially.
661 */
662 virtual void emitSurfaceToLight(GrGLSLUniformHandler*,
663 GrGLSLFPFragmentBuilder*,
664 const char* z) = 0;
665 virtual void emitLightColor(GrGLSLUniformHandler*,
666 GrGLSLFPFragmentBuilder*,
667 const char *surfaceToLight);
668
669 // This is called from GrGLLightingEffect's setData(). Subclasses of GrGLLight must call
670 // INHERITED::setData().
671 virtual void setData(const GrGLSLProgramDataManager&, const SkImageFilterLight* light) const;
672
673 protected:
674 /**
675 * Gets the constant light color uniform. Subclasses can use this in their emitLightColor
676 * function.
677 */
lightColorUni() const678 UniformHandle lightColorUni() const { return fColorUni; }
679
680 private:
681 UniformHandle fColorUni;
682
683 typedef SkRefCnt INHERITED;
684 };
685
686 ///////////////////////////////////////////////////////////////////////////////
687
688 class GrGLDistantLight : public GrGLLight {
689 public:
~GrGLDistantLight()690 virtual ~GrGLDistantLight() {}
691 void setData(const GrGLSLProgramDataManager&, const SkImageFilterLight* light) const override;
692 void emitSurfaceToLight(GrGLSLUniformHandler*, GrGLSLFPFragmentBuilder*, const char* z) override;
693
694 private:
695 typedef GrGLLight INHERITED;
696 UniformHandle fDirectionUni;
697 };
698
699 ///////////////////////////////////////////////////////////////////////////////
700
701 class GrGLPointLight : public GrGLLight {
702 public:
~GrGLPointLight()703 virtual ~GrGLPointLight() {}
704 void setData(const GrGLSLProgramDataManager&, const SkImageFilterLight* light) const override;
705 void emitSurfaceToLight(GrGLSLUniformHandler*, GrGLSLFPFragmentBuilder*, const char* z) override;
706
707 private:
708 typedef GrGLLight INHERITED;
709 UniformHandle fLocationUni;
710 };
711
712 ///////////////////////////////////////////////////////////////////////////////
713
714 class GrGLSpotLight : public GrGLLight {
715 public:
~GrGLSpotLight()716 virtual ~GrGLSpotLight() {}
717 void setData(const GrGLSLProgramDataManager&, const SkImageFilterLight* light) const override;
718 void emitSurfaceToLight(GrGLSLUniformHandler*, GrGLSLFPFragmentBuilder*, const char* z) override;
719 void emitLightColor(GrGLSLUniformHandler*,
720 GrGLSLFPFragmentBuilder*,
721 const char *surfaceToLight) override;
722
723 private:
724 typedef GrGLLight INHERITED;
725
726 SkString fLightColorFunc;
727 UniformHandle fLocationUni;
728 UniformHandle fExponentUni;
729 UniformHandle fCosOuterConeAngleUni;
730 UniformHandle fCosInnerConeAngleUni;
731 UniformHandle fConeScaleUni;
732 UniformHandle fSUni;
733 };
734 #else
735
736 class GrGLLight;
737
738 #endif
739
740 };
741
742 ///////////////////////////////////////////////////////////////////////////////
743
744 class SkImageFilterLight : public SkRefCnt {
745 public:
746
747
748 enum LightType {
749 kDistant_LightType,
750 kPoint_LightType,
751 kSpot_LightType,
752 };
753 virtual LightType type() const = 0;
color() const754 const SkPoint3& color() const { return fColor; }
755 virtual GrGLLight* createGLLight() const = 0;
isEqual(const SkImageFilterLight & other) const756 virtual bool isEqual(const SkImageFilterLight& other) const {
757 return fColor == other.fColor;
758 }
759 // Called to know whether the generated GrGLLight will require access to the fragment position.
760 virtual bool requiresFragmentPosition() const = 0;
761 virtual SkImageFilterLight* transform(const SkMatrix& matrix) const = 0;
762
763 // Defined below SkLight's subclasses.
764 void flattenLight(SkWriteBuffer& buffer) const;
765 static SkImageFilterLight* UnflattenLight(SkReadBuffer& buffer);
766
767 protected:
SkImageFilterLight(SkColor color)768 SkImageFilterLight(SkColor color) {
769 fColor = SkPoint3::Make(SkIntToScalar(SkColorGetR(color)),
770 SkIntToScalar(SkColorGetG(color)),
771 SkIntToScalar(SkColorGetB(color)));
772 }
SkImageFilterLight(const SkPoint3 & color)773 SkImageFilterLight(const SkPoint3& color)
774 : fColor(color) {}
SkImageFilterLight(SkReadBuffer & buffer)775 SkImageFilterLight(SkReadBuffer& buffer) {
776 fColor = readPoint3(buffer);
777 }
778
779 virtual void onFlattenLight(SkWriteBuffer& buffer) const = 0;
780
781
782 private:
783 typedef SkRefCnt INHERITED;
784 SkPoint3 fColor;
785 };
786
787 ///////////////////////////////////////////////////////////////////////////////
788
789 class SkDistantLight : public SkImageFilterLight {
790 public:
SkDistantLight(const SkPoint3 & direction,SkColor color)791 SkDistantLight(const SkPoint3& direction, SkColor color)
792 : INHERITED(color), fDirection(direction) {
793 }
794
surfaceToLight(int x,int y,int z,SkScalar surfaceScale) const795 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
796 return fDirection;
797 };
lightColor(const SkPoint3 &) const798 const SkPoint3& lightColor(const SkPoint3&) const { return this->color(); }
type() const799 LightType type() const override { return kDistant_LightType; }
direction() const800 const SkPoint3& direction() const { return fDirection; }
createGLLight() const801 GrGLLight* createGLLight() const override {
802 #if SK_SUPPORT_GPU
803 return new GrGLDistantLight;
804 #else
805 SkDEBUGFAIL("Should not call in GPU-less build");
806 return nullptr;
807 #endif
808 }
requiresFragmentPosition() const809 bool requiresFragmentPosition() const override { return false; }
810
isEqual(const SkImageFilterLight & other) const811 bool isEqual(const SkImageFilterLight& other) const override {
812 if (other.type() != kDistant_LightType) {
813 return false;
814 }
815
816 const SkDistantLight& o = static_cast<const SkDistantLight&>(other);
817 return INHERITED::isEqual(other) &&
818 fDirection == o.fDirection;
819 }
820
SkDistantLight(SkReadBuffer & buffer)821 SkDistantLight(SkReadBuffer& buffer) : INHERITED(buffer) {
822 fDirection = readPoint3(buffer);
823 }
824
825 protected:
SkDistantLight(const SkPoint3 & direction,const SkPoint3 & color)826 SkDistantLight(const SkPoint3& direction, const SkPoint3& color)
827 : INHERITED(color), fDirection(direction) {
828 }
transform(const SkMatrix & matrix) const829 SkImageFilterLight* transform(const SkMatrix& matrix) const override {
830 return new SkDistantLight(direction(), color());
831 }
onFlattenLight(SkWriteBuffer & buffer) const832 void onFlattenLight(SkWriteBuffer& buffer) const override {
833 writePoint3(fDirection, buffer);
834 }
835
836 private:
837 SkPoint3 fDirection;
838
839 typedef SkImageFilterLight INHERITED;
840 };
841
842 ///////////////////////////////////////////////////////////////////////////////
843
844 class SkPointLight : public SkImageFilterLight {
845 public:
SkPointLight(const SkPoint3 & location,SkColor color)846 SkPointLight(const SkPoint3& location, SkColor color)
847 : INHERITED(color), fLocation(location) {}
848
surfaceToLight(int x,int y,int z,SkScalar surfaceScale) const849 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
850 SkPoint3 direction = SkPoint3::Make(fLocation.fX - SkIntToScalar(x),
851 fLocation.fY - SkIntToScalar(y),
852 fLocation.fZ - SkScalarMul(SkIntToScalar(z),
853 surfaceScale));
854 fast_normalize(&direction);
855 return direction;
856 };
lightColor(const SkPoint3 &) const857 const SkPoint3& lightColor(const SkPoint3&) const { return this->color(); }
type() const858 LightType type() const override { return kPoint_LightType; }
location() const859 const SkPoint3& location() const { return fLocation; }
createGLLight() const860 GrGLLight* createGLLight() const override {
861 #if SK_SUPPORT_GPU
862 return new GrGLPointLight;
863 #else
864 SkDEBUGFAIL("Should not call in GPU-less build");
865 return nullptr;
866 #endif
867 }
requiresFragmentPosition() const868 bool requiresFragmentPosition() const override { return true; }
isEqual(const SkImageFilterLight & other) const869 bool isEqual(const SkImageFilterLight& other) const override {
870 if (other.type() != kPoint_LightType) {
871 return false;
872 }
873 const SkPointLight& o = static_cast<const SkPointLight&>(other);
874 return INHERITED::isEqual(other) &&
875 fLocation == o.fLocation;
876 }
transform(const SkMatrix & matrix) const877 SkImageFilterLight* transform(const SkMatrix& matrix) const override {
878 SkPoint location2 = SkPoint::Make(fLocation.fX, fLocation.fY);
879 matrix.mapPoints(&location2, 1);
880 // Use X scale and Y scale on Z and average the result
881 SkPoint locationZ = SkPoint::Make(fLocation.fZ, fLocation.fZ);
882 matrix.mapVectors(&locationZ, 1);
883 SkPoint3 location = SkPoint3::Make(location2.fX,
884 location2.fY,
885 SkScalarAve(locationZ.fX, locationZ.fY));
886 return new SkPointLight(location, color());
887 }
888
SkPointLight(SkReadBuffer & buffer)889 SkPointLight(SkReadBuffer& buffer) : INHERITED(buffer) {
890 fLocation = readPoint3(buffer);
891 }
892
893 protected:
SkPointLight(const SkPoint3 & location,const SkPoint3 & color)894 SkPointLight(const SkPoint3& location, const SkPoint3& color)
895 : INHERITED(color), fLocation(location) {}
onFlattenLight(SkWriteBuffer & buffer) const896 void onFlattenLight(SkWriteBuffer& buffer) const override {
897 writePoint3(fLocation, buffer);
898 }
899
900 private:
901 SkPoint3 fLocation;
902
903 typedef SkImageFilterLight INHERITED;
904 };
905
906 ///////////////////////////////////////////////////////////////////////////////
907
908 class SkSpotLight : public SkImageFilterLight {
909 public:
SkSpotLight(const SkPoint3 & location,const SkPoint3 & target,SkScalar specularExponent,SkScalar cutoffAngle,SkColor color)910 SkSpotLight(const SkPoint3& location,
911 const SkPoint3& target,
912 SkScalar specularExponent,
913 SkScalar cutoffAngle,
914 SkColor color)
915 : INHERITED(color),
916 fLocation(location),
917 fTarget(target),
918 fSpecularExponent(SkScalarPin(specularExponent, kSpecularExponentMin, kSpecularExponentMax))
919 {
920 fS = target - location;
921 fast_normalize(&fS);
922 fCosOuterConeAngle = SkScalarCos(SkDegreesToRadians(cutoffAngle));
923 const SkScalar antiAliasThreshold = 0.016f;
924 fCosInnerConeAngle = fCosOuterConeAngle + antiAliasThreshold;
925 fConeScale = SkScalarInvert(antiAliasThreshold);
926 }
927
transform(const SkMatrix & matrix) const928 SkImageFilterLight* transform(const SkMatrix& matrix) const override {
929 SkPoint location2 = SkPoint::Make(fLocation.fX, fLocation.fY);
930 matrix.mapPoints(&location2, 1);
931 // Use X scale and Y scale on Z and average the result
932 SkPoint locationZ = SkPoint::Make(fLocation.fZ, fLocation.fZ);
933 matrix.mapVectors(&locationZ, 1);
934 SkPoint3 location = SkPoint3::Make(location2.fX, location2.fY,
935 SkScalarAve(locationZ.fX, locationZ.fY));
936 SkPoint target2 = SkPoint::Make(fTarget.fX, fTarget.fY);
937 matrix.mapPoints(&target2, 1);
938 SkPoint targetZ = SkPoint::Make(fTarget.fZ, fTarget.fZ);
939 matrix.mapVectors(&targetZ, 1);
940 SkPoint3 target = SkPoint3::Make(target2.fX, target2.fY,
941 SkScalarAve(targetZ.fX, targetZ.fY));
942 SkPoint3 s = target - location;
943 fast_normalize(&s);
944 return new SkSpotLight(location,
945 target,
946 fSpecularExponent,
947 fCosOuterConeAngle,
948 fCosInnerConeAngle,
949 fConeScale,
950 s,
951 color());
952 }
953
surfaceToLight(int x,int y,int z,SkScalar surfaceScale) const954 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const {
955 SkPoint3 direction = SkPoint3::Make(fLocation.fX - SkIntToScalar(x),
956 fLocation.fY - SkIntToScalar(y),
957 fLocation.fZ - SkScalarMul(SkIntToScalar(z),
958 surfaceScale));
959 fast_normalize(&direction);
960 return direction;
961 };
lightColor(const SkPoint3 & surfaceToLight) const962 SkPoint3 lightColor(const SkPoint3& surfaceToLight) const {
963 SkScalar cosAngle = -surfaceToLight.dot(fS);
964 SkScalar scale = 0;
965 if (cosAngle >= fCosOuterConeAngle) {
966 scale = SkScalarPow(cosAngle, fSpecularExponent);
967 if (cosAngle < fCosInnerConeAngle) {
968 scale = SkScalarMul(scale, cosAngle - fCosOuterConeAngle);
969 scale *= fConeScale;
970 }
971 }
972 return this->color().makeScale(scale);
973 }
createGLLight() const974 GrGLLight* createGLLight() const override {
975 #if SK_SUPPORT_GPU
976 return new GrGLSpotLight;
977 #else
978 SkDEBUGFAIL("Should not call in GPU-less build");
979 return nullptr;
980 #endif
981 }
requiresFragmentPosition() const982 bool requiresFragmentPosition() const override { return true; }
type() const983 LightType type() const override { return kSpot_LightType; }
location() const984 const SkPoint3& location() const { return fLocation; }
target() const985 const SkPoint3& target() const { return fTarget; }
specularExponent() const986 SkScalar specularExponent() const { return fSpecularExponent; }
cosInnerConeAngle() const987 SkScalar cosInnerConeAngle() const { return fCosInnerConeAngle; }
cosOuterConeAngle() const988 SkScalar cosOuterConeAngle() const { return fCosOuterConeAngle; }
coneScale() const989 SkScalar coneScale() const { return fConeScale; }
s() const990 const SkPoint3& s() const { return fS; }
991
SkSpotLight(SkReadBuffer & buffer)992 SkSpotLight(SkReadBuffer& buffer) : INHERITED(buffer) {
993 fLocation = readPoint3(buffer);
994 fTarget = readPoint3(buffer);
995 fSpecularExponent = buffer.readScalar();
996 fCosOuterConeAngle = buffer.readScalar();
997 fCosInnerConeAngle = buffer.readScalar();
998 fConeScale = buffer.readScalar();
999 fS = readPoint3(buffer);
1000 buffer.validate(SkScalarIsFinite(fSpecularExponent) &&
1001 SkScalarIsFinite(fCosOuterConeAngle) &&
1002 SkScalarIsFinite(fCosInnerConeAngle) &&
1003 SkScalarIsFinite(fConeScale));
1004 }
1005 protected:
SkSpotLight(const SkPoint3 & location,const SkPoint3 & target,SkScalar specularExponent,SkScalar cosOuterConeAngle,SkScalar cosInnerConeAngle,SkScalar coneScale,const SkPoint3 & s,const SkPoint3 & color)1006 SkSpotLight(const SkPoint3& location,
1007 const SkPoint3& target,
1008 SkScalar specularExponent,
1009 SkScalar cosOuterConeAngle,
1010 SkScalar cosInnerConeAngle,
1011 SkScalar coneScale,
1012 const SkPoint3& s,
1013 const SkPoint3& color)
1014 : INHERITED(color),
1015 fLocation(location),
1016 fTarget(target),
1017 fSpecularExponent(specularExponent),
1018 fCosOuterConeAngle(cosOuterConeAngle),
1019 fCosInnerConeAngle(cosInnerConeAngle),
1020 fConeScale(coneScale),
1021 fS(s)
1022 {
1023 }
onFlattenLight(SkWriteBuffer & buffer) const1024 void onFlattenLight(SkWriteBuffer& buffer) const override {
1025 writePoint3(fLocation, buffer);
1026 writePoint3(fTarget, buffer);
1027 buffer.writeScalar(fSpecularExponent);
1028 buffer.writeScalar(fCosOuterConeAngle);
1029 buffer.writeScalar(fCosInnerConeAngle);
1030 buffer.writeScalar(fConeScale);
1031 writePoint3(fS, buffer);
1032 }
1033
isEqual(const SkImageFilterLight & other) const1034 bool isEqual(const SkImageFilterLight& other) const override {
1035 if (other.type() != kSpot_LightType) {
1036 return false;
1037 }
1038
1039 const SkSpotLight& o = static_cast<const SkSpotLight&>(other);
1040 return INHERITED::isEqual(other) &&
1041 fLocation == o.fLocation &&
1042 fTarget == o.fTarget &&
1043 fSpecularExponent == o.fSpecularExponent &&
1044 fCosOuterConeAngle == o.fCosOuterConeAngle;
1045 }
1046
1047 private:
1048 static const SkScalar kSpecularExponentMin;
1049 static const SkScalar kSpecularExponentMax;
1050
1051 SkPoint3 fLocation;
1052 SkPoint3 fTarget;
1053 SkScalar fSpecularExponent;
1054 SkScalar fCosOuterConeAngle;
1055 SkScalar fCosInnerConeAngle;
1056 SkScalar fConeScale;
1057 SkPoint3 fS;
1058
1059 typedef SkImageFilterLight INHERITED;
1060 };
1061
1062 // According to the spec, the specular term should be in the range [1, 128] :
1063 // http://www.w3.org/TR/SVG/filters.html#feSpecularLightingSpecularExponentAttribute
1064 const SkScalar SkSpotLight::kSpecularExponentMin = 1.0f;
1065 const SkScalar SkSpotLight::kSpecularExponentMax = 128.0f;
1066
1067 ///////////////////////////////////////////////////////////////////////////////
1068
flattenLight(SkWriteBuffer & buffer) const1069 void SkImageFilterLight::flattenLight(SkWriteBuffer& buffer) const {
1070 // Write type first, then baseclass, then subclass.
1071 buffer.writeInt(this->type());
1072 writePoint3(fColor, buffer);
1073 this->onFlattenLight(buffer);
1074 }
1075
UnflattenLight(SkReadBuffer & buffer)1076 /*static*/ SkImageFilterLight* SkImageFilterLight::UnflattenLight(SkReadBuffer& buffer) {
1077 // Read type first.
1078 const SkImageFilterLight::LightType type = (SkImageFilterLight::LightType)buffer.readInt();
1079 switch (type) {
1080 // Each of these constructors must first call SkLight's, so we'll read the baseclass
1081 // then subclass, same order as flattenLight.
1082 case SkImageFilterLight::kDistant_LightType:
1083 return new SkDistantLight(buffer);
1084 case SkImageFilterLight::kPoint_LightType:
1085 return new SkPointLight(buffer);
1086 case SkImageFilterLight::kSpot_LightType:
1087 return new SkSpotLight(buffer);
1088 default:
1089 SkDEBUGFAIL("Unknown LightType.");
1090 buffer.validate(false);
1091 return nullptr;
1092 }
1093 }
1094 ///////////////////////////////////////////////////////////////////////////////
1095
SkLightingImageFilter(SkImageFilterLight * light,SkScalar surfaceScale,SkImageFilter * input,const CropRect * cropRect)1096 SkLightingImageFilter::SkLightingImageFilter(SkImageFilterLight* light, SkScalar surfaceScale,
1097 SkImageFilter* input, const CropRect* cropRect)
1098 : INHERITED(1, &input, cropRect)
1099 , fLight(SkRef(light))
1100 , fSurfaceScale(surfaceScale / 255)
1101 {}
1102
CreateDistantLitDiffuse(const SkPoint3 & direction,SkColor lightColor,SkScalar surfaceScale,SkScalar kd,SkImageFilter * input,const CropRect * cropRect)1103 SkImageFilter* SkLightingImageFilter::CreateDistantLitDiffuse(const SkPoint3& direction,
1104 SkColor lightColor,
1105 SkScalar surfaceScale,
1106 SkScalar kd,
1107 SkImageFilter* input,
1108 const CropRect* cropRect) {
1109 SkAutoTUnref<SkImageFilterLight> light(new SkDistantLight(direction, lightColor));
1110 return SkDiffuseLightingImageFilter::Create(light, surfaceScale, kd, input, cropRect);
1111 }
1112
CreatePointLitDiffuse(const SkPoint3 & location,SkColor lightColor,SkScalar surfaceScale,SkScalar kd,SkImageFilter * input,const CropRect * cropRect)1113 SkImageFilter* SkLightingImageFilter::CreatePointLitDiffuse(const SkPoint3& location,
1114 SkColor lightColor,
1115 SkScalar surfaceScale,
1116 SkScalar kd,
1117 SkImageFilter* input,
1118 const CropRect* cropRect) {
1119 SkAutoTUnref<SkImageFilterLight> light(new SkPointLight(location, lightColor));
1120 return SkDiffuseLightingImageFilter::Create(light, surfaceScale, kd, input, cropRect);
1121 }
1122
CreateSpotLitDiffuse(const SkPoint3 & location,const SkPoint3 & target,SkScalar specularExponent,SkScalar cutoffAngle,SkColor lightColor,SkScalar surfaceScale,SkScalar kd,SkImageFilter * input,const CropRect * cropRect)1123 SkImageFilter* SkLightingImageFilter::CreateSpotLitDiffuse(const SkPoint3& location,
1124 const SkPoint3& target,
1125 SkScalar specularExponent,
1126 SkScalar cutoffAngle,
1127 SkColor lightColor,
1128 SkScalar surfaceScale,
1129 SkScalar kd,
1130 SkImageFilter* input,
1131 const CropRect* cropRect) {
1132 SkAutoTUnref<SkImageFilterLight> light(
1133 new SkSpotLight(location, target, specularExponent, cutoffAngle, lightColor));
1134 return SkDiffuseLightingImageFilter::Create(light, surfaceScale, kd, input, cropRect);
1135 }
1136
CreateDistantLitSpecular(const SkPoint3 & direction,SkColor lightColor,SkScalar surfaceScale,SkScalar ks,SkScalar shine,SkImageFilter * input,const CropRect * cropRect)1137 SkImageFilter* SkLightingImageFilter::CreateDistantLitSpecular(const SkPoint3& direction,
1138 SkColor lightColor,
1139 SkScalar surfaceScale,
1140 SkScalar ks,
1141 SkScalar shine,
1142 SkImageFilter* input,
1143 const CropRect* cropRect) {
1144 SkAutoTUnref<SkImageFilterLight> light(new SkDistantLight(direction, lightColor));
1145 return SkSpecularLightingImageFilter::Create(light, surfaceScale, ks, shine, input, cropRect);
1146 }
1147
CreatePointLitSpecular(const SkPoint3 & location,SkColor lightColor,SkScalar surfaceScale,SkScalar ks,SkScalar shine,SkImageFilter * input,const CropRect * cropRect)1148 SkImageFilter* SkLightingImageFilter::CreatePointLitSpecular(const SkPoint3& location,
1149 SkColor lightColor,
1150 SkScalar surfaceScale,
1151 SkScalar ks,
1152 SkScalar shine,
1153 SkImageFilter* input,
1154 const CropRect* cropRect) {
1155 SkAutoTUnref<SkImageFilterLight> light(new SkPointLight(location, lightColor));
1156 return SkSpecularLightingImageFilter::Create(light, surfaceScale, ks, shine, input, cropRect);
1157 }
1158
CreateSpotLitSpecular(const SkPoint3 & location,const SkPoint3 & target,SkScalar specularExponent,SkScalar cutoffAngle,SkColor lightColor,SkScalar surfaceScale,SkScalar ks,SkScalar shine,SkImageFilter * input,const CropRect * cropRect)1159 SkImageFilter* SkLightingImageFilter::CreateSpotLitSpecular(const SkPoint3& location,
1160 const SkPoint3& target,
1161 SkScalar specularExponent,
1162 SkScalar cutoffAngle,
1163 SkColor lightColor,
1164 SkScalar surfaceScale,
1165 SkScalar ks,
1166 SkScalar shine,
1167 SkImageFilter* input,
1168 const CropRect* cropRect) {
1169 SkAutoTUnref<SkImageFilterLight> light(
1170 new SkSpotLight(location, target, specularExponent, cutoffAngle, lightColor));
1171 return SkSpecularLightingImageFilter::Create(light, surfaceScale, ks, shine, input, cropRect);
1172 }
1173
~SkLightingImageFilter()1174 SkLightingImageFilter::~SkLightingImageFilter() {}
1175
flatten(SkWriteBuffer & buffer) const1176 void SkLightingImageFilter::flatten(SkWriteBuffer& buffer) const {
1177 this->INHERITED::flatten(buffer);
1178 fLight->flattenLight(buffer);
1179 buffer.writeScalar(fSurfaceScale * 255);
1180 }
1181
1182 ///////////////////////////////////////////////////////////////////////////////
1183
Create(SkImageFilterLight * light,SkScalar surfaceScale,SkScalar kd,SkImageFilter * input,const CropRect * cropRect)1184 SkImageFilter* SkDiffuseLightingImageFilter::Create(SkImageFilterLight* light,
1185 SkScalar surfaceScale,
1186 SkScalar kd,
1187 SkImageFilter* input,
1188 const CropRect* cropRect) {
1189 if (nullptr == light) {
1190 return nullptr;
1191 }
1192 if (!SkScalarIsFinite(surfaceScale) || !SkScalarIsFinite(kd)) {
1193 return nullptr;
1194 }
1195 // According to the spec, kd can be any non-negative number :
1196 // http://www.w3.org/TR/SVG/filters.html#feDiffuseLightingElement
1197 if (kd < 0) {
1198 return nullptr;
1199 }
1200 return new SkDiffuseLightingImageFilter(light, surfaceScale, kd, input, cropRect);
1201 }
1202
SkDiffuseLightingImageFilter(SkImageFilterLight * light,SkScalar surfaceScale,SkScalar kd,SkImageFilter * input,const CropRect * cropRect)1203 SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkImageFilterLight* light,
1204 SkScalar surfaceScale,
1205 SkScalar kd,
1206 SkImageFilter* input,
1207 const CropRect* cropRect)
1208 : INHERITED(light, surfaceScale, input, cropRect),
1209 fKD(kd)
1210 {
1211 }
1212
CreateProc(SkReadBuffer & buffer)1213 SkFlattenable* SkDiffuseLightingImageFilter::CreateProc(SkReadBuffer& buffer) {
1214 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
1215 SkAutoTUnref<SkImageFilterLight> light(SkImageFilterLight::UnflattenLight(buffer));
1216 SkScalar surfaceScale = buffer.readScalar();
1217 SkScalar kd = buffer.readScalar();
1218 return Create(light, surfaceScale, kd, common.getInput(0), &common.cropRect());
1219 }
1220
flatten(SkWriteBuffer & buffer) const1221 void SkDiffuseLightingImageFilter::flatten(SkWriteBuffer& buffer) const {
1222 this->INHERITED::flatten(buffer);
1223 buffer.writeScalar(fKD);
1224 }
1225
onFilterImageDeprecated(Proxy * proxy,const SkBitmap & source,const Context & ctx,SkBitmap * dst,SkIPoint * offset) const1226 bool SkDiffuseLightingImageFilter::onFilterImageDeprecated(Proxy* proxy,
1227 const SkBitmap& source,
1228 const Context& ctx,
1229 SkBitmap* dst,
1230 SkIPoint* offset) const {
1231 SkBitmap src = source;
1232 SkIPoint srcOffset = SkIPoint::Make(0, 0);
1233 if (!this->filterInputDeprecated(0, proxy, source, ctx, &src, &srcOffset)) {
1234 return false;
1235 }
1236
1237 if (src.colorType() != kN32_SkColorType) {
1238 return false;
1239 }
1240 SkIRect srcBounds = src.bounds();
1241 srcBounds.offset(srcOffset);
1242 SkIRect bounds;
1243 if (!this->applyCropRect(ctx, srcBounds, &bounds)) {
1244 return false;
1245 }
1246
1247 if (bounds.width() < 2 || bounds.height() < 2) {
1248 return false;
1249 }
1250
1251 SkAutoLockPixels alp(src);
1252 if (!src.getPixels()) {
1253 return false;
1254 }
1255
1256 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
1257 if (!device) {
1258 return false;
1259 }
1260 *dst = device->accessBitmap(false);
1261 SkAutoLockPixels alp_dst(*dst);
1262
1263 SkMatrix matrix(ctx.ctm());
1264 matrix.postTranslate(SkIntToScalar(-srcOffset.x()), SkIntToScalar(-srcOffset.y()));
1265 SkAutoTUnref<SkImageFilterLight> transformedLight(light()->transform(matrix));
1266
1267 DiffuseLightingType lightingType(fKD);
1268 offset->fX = bounds.left();
1269 offset->fY = bounds.top();
1270 bounds.offset(-srcOffset);
1271 switch (transformedLight->type()) {
1272 case SkImageFilterLight::kDistant_LightType:
1273 lightBitmap<DiffuseLightingType, SkDistantLight>(lightingType,
1274 transformedLight,
1275 src,
1276 dst,
1277 surfaceScale(),
1278 bounds);
1279 break;
1280 case SkImageFilterLight::kPoint_LightType:
1281 lightBitmap<DiffuseLightingType, SkPointLight>(lightingType,
1282 transformedLight,
1283 src,
1284 dst,
1285 surfaceScale(),
1286 bounds);
1287 break;
1288 case SkImageFilterLight::kSpot_LightType:
1289 lightBitmap<DiffuseLightingType, SkSpotLight>(lightingType,
1290 transformedLight,
1291 src,
1292 dst,
1293 surfaceScale(),
1294 bounds);
1295 break;
1296 }
1297
1298 return true;
1299 }
1300
1301 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const1302 void SkDiffuseLightingImageFilter::toString(SkString* str) const {
1303 str->appendf("SkDiffuseLightingImageFilter: (");
1304 str->appendf("kD: %f\n", fKD);
1305 str->append(")");
1306 }
1307 #endif
1308
1309 #if SK_SUPPORT_GPU
getFragmentProcessor(GrTexture * texture,const SkMatrix & matrix,const SkIRect * srcBounds,BoundaryMode boundaryMode) const1310 GrFragmentProcessor* SkDiffuseLightingImageFilter::getFragmentProcessor(
1311 GrTexture* texture,
1312 const SkMatrix& matrix,
1313 const SkIRect* srcBounds,
1314 BoundaryMode boundaryMode) const {
1315 SkScalar scale = SkScalarMul(this->surfaceScale(), SkIntToScalar(255));
1316 return GrDiffuseLightingEffect::Create(texture, this->light(), scale, matrix, this->kd(),
1317 boundaryMode, srcBounds);
1318 }
1319 #endif
1320
1321 ///////////////////////////////////////////////////////////////////////////////
1322
Create(SkImageFilterLight * light,SkScalar surfaceScale,SkScalar ks,SkScalar shininess,SkImageFilter * input,const CropRect * cropRect)1323 SkImageFilter* SkSpecularLightingImageFilter::Create(SkImageFilterLight* light,
1324 SkScalar surfaceScale,
1325 SkScalar ks,
1326 SkScalar shininess,
1327 SkImageFilter* input,
1328 const CropRect* cropRect) {
1329 if (nullptr == light) {
1330 return nullptr;
1331 }
1332 if (!SkScalarIsFinite(surfaceScale) || !SkScalarIsFinite(ks) || !SkScalarIsFinite(shininess)) {
1333 return nullptr;
1334 }
1335 // According to the spec, ks can be any non-negative number :
1336 // http://www.w3.org/TR/SVG/filters.html#feSpecularLightingElement
1337 if (ks < 0) {
1338 return nullptr;
1339 }
1340 return new SkSpecularLightingImageFilter(light, surfaceScale, ks, shininess, input, cropRect);
1341 }
1342
SkSpecularLightingImageFilter(SkImageFilterLight * light,SkScalar surfaceScale,SkScalar ks,SkScalar shininess,SkImageFilter * input,const CropRect * cropRect)1343 SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkImageFilterLight* light,
1344 SkScalar surfaceScale,
1345 SkScalar ks,
1346 SkScalar shininess,
1347 SkImageFilter* input,
1348 const CropRect* cropRect)
1349 : INHERITED(light, surfaceScale, input, cropRect),
1350 fKS(ks),
1351 fShininess(shininess)
1352 {
1353 }
1354
CreateProc(SkReadBuffer & buffer)1355 SkFlattenable* SkSpecularLightingImageFilter::CreateProc(SkReadBuffer& buffer) {
1356 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
1357 SkAutoTUnref<SkImageFilterLight> light(SkImageFilterLight::UnflattenLight(buffer));
1358 SkScalar surfaceScale = buffer.readScalar();
1359 SkScalar ks = buffer.readScalar();
1360 SkScalar shine = buffer.readScalar();
1361 return Create(light, surfaceScale, ks, shine, common.getInput(0), &common.cropRect());
1362 }
1363
flatten(SkWriteBuffer & buffer) const1364 void SkSpecularLightingImageFilter::flatten(SkWriteBuffer& buffer) const {
1365 this->INHERITED::flatten(buffer);
1366 buffer.writeScalar(fKS);
1367 buffer.writeScalar(fShininess);
1368 }
1369
onFilterImageDeprecated(Proxy * proxy,const SkBitmap & source,const Context & ctx,SkBitmap * dst,SkIPoint * offset) const1370 bool SkSpecularLightingImageFilter::onFilterImageDeprecated(Proxy* proxy,
1371 const SkBitmap& source,
1372 const Context& ctx,
1373 SkBitmap* dst,
1374 SkIPoint* offset) const {
1375 SkBitmap src = source;
1376 SkIPoint srcOffset = SkIPoint::Make(0, 0);
1377 if (!this->filterInputDeprecated(0, proxy, source, ctx, &src, &srcOffset)) {
1378 return false;
1379 }
1380
1381 if (src.colorType() != kN32_SkColorType) {
1382 return false;
1383 }
1384
1385 SkIRect srcBounds = src.bounds();
1386 srcBounds.offset(srcOffset);
1387 SkIRect bounds;
1388 if (!this->applyCropRect(ctx, srcBounds, &bounds)) {
1389 return false;
1390 }
1391
1392 if (bounds.width() < 2 || bounds.height() < 2) {
1393 return false;
1394 }
1395
1396 SkAutoLockPixels alp(src);
1397 if (!src.getPixels()) {
1398 return false;
1399 }
1400
1401 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
1402 if (!device) {
1403 return false;
1404 }
1405 *dst = device->accessBitmap(false);
1406 SkAutoLockPixels alp_dst(*dst);
1407
1408 SpecularLightingType lightingType(fKS, fShininess);
1409 offset->fX = bounds.left();
1410 offset->fY = bounds.top();
1411 SkMatrix matrix(ctx.ctm());
1412 matrix.postTranslate(SkIntToScalar(-srcOffset.x()), SkIntToScalar(-srcOffset.y()));
1413 SkAutoTUnref<SkImageFilterLight> transformedLight(light()->transform(matrix));
1414 bounds.offset(-srcOffset);
1415 switch (transformedLight->type()) {
1416 case SkImageFilterLight::kDistant_LightType:
1417 lightBitmap<SpecularLightingType, SkDistantLight>(lightingType,
1418 transformedLight,
1419 src,
1420 dst,
1421 surfaceScale(),
1422 bounds);
1423 break;
1424 case SkImageFilterLight::kPoint_LightType:
1425 lightBitmap<SpecularLightingType, SkPointLight>(lightingType,
1426 transformedLight,
1427 src,
1428 dst,
1429 surfaceScale(),
1430 bounds);
1431 break;
1432 case SkImageFilterLight::kSpot_LightType:
1433 lightBitmap<SpecularLightingType, SkSpotLight>(lightingType,
1434 transformedLight,
1435 src,
1436 dst,
1437 surfaceScale(),
1438 bounds);
1439 break;
1440 }
1441 return true;
1442 }
1443
1444 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const1445 void SkSpecularLightingImageFilter::toString(SkString* str) const {
1446 str->appendf("SkSpecularLightingImageFilter: (");
1447 str->appendf("kS: %f shininess: %f", fKS, fShininess);
1448 str->append(")");
1449 }
1450 #endif
1451
1452 #if SK_SUPPORT_GPU
getFragmentProcessor(GrTexture * texture,const SkMatrix & matrix,const SkIRect * srcBounds,BoundaryMode boundaryMode) const1453 GrFragmentProcessor* SkSpecularLightingImageFilter::getFragmentProcessor(
1454 GrTexture* texture,
1455 const SkMatrix& matrix,
1456 const SkIRect* srcBounds,
1457 BoundaryMode boundaryMode) const {
1458 SkScalar scale = SkScalarMul(this->surfaceScale(), SkIntToScalar(255));
1459 return GrSpecularLightingEffect::Create(texture, this->light(), scale, matrix, this->ks(),
1460 this->shininess(), boundaryMode, srcBounds);
1461 }
1462 #endif
1463
1464 ///////////////////////////////////////////////////////////////////////////////
1465
1466 #if SK_SUPPORT_GPU
1467
1468 namespace {
random_point3(SkRandom * random)1469 SkPoint3 random_point3(SkRandom* random) {
1470 return SkPoint3::Make(SkScalarToFloat(random->nextSScalar1()),
1471 SkScalarToFloat(random->nextSScalar1()),
1472 SkScalarToFloat(random->nextSScalar1()));
1473 }
1474
create_random_light(SkRandom * random)1475 SkImageFilterLight* create_random_light(SkRandom* random) {
1476 int type = random->nextULessThan(3);
1477 switch (type) {
1478 case 0: {
1479 return new SkDistantLight(random_point3(random), random->nextU());
1480 }
1481 case 1: {
1482 return new SkPointLight(random_point3(random), random->nextU());
1483 }
1484 case 2: {
1485 return new SkSpotLight(random_point3(random), random_point3(random),
1486 random->nextUScalar1(), random->nextUScalar1(), random->nextU());
1487 }
1488 default:
1489 SkFAIL("Unexpected value.");
1490 return nullptr;
1491 }
1492 }
1493
emitNormalFunc(BoundaryMode mode,const char * pointToNormalName,const char * sobelFuncName)1494 SkString emitNormalFunc(BoundaryMode mode,
1495 const char* pointToNormalName,
1496 const char* sobelFuncName) {
1497 SkString result;
1498 switch (mode) {
1499 case kTopLeft_BoundaryMode:
1500 result.printf("\treturn %s(%s(0.0, 0.0, m[4], m[5], m[7], m[8], %g),\n"
1501 "\t %s(0.0, 0.0, m[4], m[7], m[5], m[8], %g),\n"
1502 "\t surfaceScale);\n",
1503 pointToNormalName, sobelFuncName, gTwoThirds,
1504 sobelFuncName, gTwoThirds);
1505 break;
1506 case kTop_BoundaryMode:
1507 result.printf("\treturn %s(%s(0.0, 0.0, m[3], m[5], m[6], m[8], %g),\n"
1508 "\t %s(0.0, 0.0, m[4], m[7], m[5], m[8], %g),\n"
1509 "\t surfaceScale);\n",
1510 pointToNormalName, sobelFuncName, gOneThird,
1511 sobelFuncName, gOneHalf);
1512 break;
1513 case kTopRight_BoundaryMode:
1514 result.printf("\treturn %s(%s( 0.0, 0.0, m[3], m[4], m[6], m[7], %g),\n"
1515 "\t %s(m[3], m[6], m[4], m[7], 0.0, 0.0, %g),\n"
1516 "\t surfaceScale);\n",
1517 pointToNormalName, sobelFuncName, gTwoThirds,
1518 sobelFuncName, gTwoThirds);
1519 break;
1520 case kLeft_BoundaryMode:
1521 result.printf("\treturn %s(%s(m[1], m[2], m[4], m[5], m[7], m[8], %g),\n"
1522 "\t %s( 0.0, 0.0, m[1], m[7], m[2], m[8], %g),\n"
1523 "\t surfaceScale);\n",
1524 pointToNormalName, sobelFuncName, gOneHalf,
1525 sobelFuncName, gOneThird);
1526 break;
1527 case kInterior_BoundaryMode:
1528 result.printf("\treturn %s(%s(m[0], m[2], m[3], m[5], m[6], m[8], %g),\n"
1529 "\t %s(m[0], m[6], m[1], m[7], m[2], m[8], %g),\n"
1530 "\t surfaceScale);\n",
1531 pointToNormalName, sobelFuncName, gOneQuarter,
1532 sobelFuncName, gOneQuarter);
1533 break;
1534 case kRight_BoundaryMode:
1535 result.printf("\treturn %s(%s(m[0], m[1], m[3], m[4], m[6], m[7], %g),\n"
1536 "\t %s(m[0], m[6], m[1], m[7], 0.0, 0.0, %g),\n"
1537 "\t surfaceScale);\n",
1538 pointToNormalName, sobelFuncName, gOneHalf,
1539 sobelFuncName, gOneThird);
1540 break;
1541 case kBottomLeft_BoundaryMode:
1542 result.printf("\treturn %s(%s(m[1], m[2], m[4], m[5], 0.0, 0.0, %g),\n"
1543 "\t %s( 0.0, 0.0, m[1], m[4], m[2], m[5], %g),\n"
1544 "\t surfaceScale);\n",
1545 pointToNormalName, sobelFuncName, gTwoThirds,
1546 sobelFuncName, gTwoThirds);
1547 break;
1548 case kBottom_BoundaryMode:
1549 result.printf("\treturn %s(%s(m[0], m[2], m[3], m[5], 0.0, 0.0, %g),\n"
1550 "\t %s(m[0], m[3], m[1], m[4], m[2], m[5], %g),\n"
1551 "\t surfaceScale);\n",
1552 pointToNormalName, sobelFuncName, gOneThird,
1553 sobelFuncName, gOneHalf);
1554 break;
1555 case kBottomRight_BoundaryMode:
1556 result.printf("\treturn %s(%s(m[0], m[1], m[3], m[4], 0.0, 0.0, %g),\n"
1557 "\t %s(m[0], m[3], m[1], m[4], 0.0, 0.0, %g),\n"
1558 "\t surfaceScale);\n",
1559 pointToNormalName, sobelFuncName, gTwoThirds,
1560 sobelFuncName, gTwoThirds);
1561 break;
1562 default:
1563 SkASSERT(false);
1564 break;
1565 }
1566 return result;
1567 }
1568
1569 }
1570
1571 class GrGLLightingEffect : public GrGLSLFragmentProcessor {
1572 public:
GrGLLightingEffect()1573 GrGLLightingEffect() : fLight(nullptr) { }
~GrGLLightingEffect()1574 virtual ~GrGLLightingEffect() { delete fLight; }
1575
1576 void emitCode(EmitArgs&) override;
1577
1578 static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder* b);
1579
1580 protected:
1581 /**
1582 * Subclasses of GrGLLightingEffect must call INHERITED::onSetData();
1583 */
1584 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
1585
1586 virtual void emitLightFunc(GrGLSLUniformHandler*,
1587 GrGLSLFPFragmentBuilder*,
1588 SkString* funcName) = 0;
1589
1590 private:
1591 typedef GrGLSLFragmentProcessor INHERITED;
1592
1593 UniformHandle fImageIncrementUni;
1594 UniformHandle fSurfaceScaleUni;
1595 GrTextureDomain::GLDomain fDomain;
1596 GrGLLight* fLight;
1597 };
1598
1599 ///////////////////////////////////////////////////////////////////////////////
1600
1601 class GrGLDiffuseLightingEffect : public GrGLLightingEffect {
1602 public:
1603 void emitLightFunc(GrGLSLUniformHandler*, GrGLSLFPFragmentBuilder*, SkString* funcName) override;
1604
1605 protected:
1606 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
1607
1608 private:
1609 typedef GrGLLightingEffect INHERITED;
1610
1611 UniformHandle fKDUni;
1612 };
1613
1614 ///////////////////////////////////////////////////////////////////////////////
1615
1616 class GrGLSpecularLightingEffect : public GrGLLightingEffect {
1617 public:
1618 void emitLightFunc(GrGLSLUniformHandler*, GrGLSLFPFragmentBuilder*, SkString* funcName) override;
1619
1620 protected:
1621 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
1622
1623 private:
1624 typedef GrGLLightingEffect INHERITED;
1625
1626 UniformHandle fKSUni;
1627 UniformHandle fShininessUni;
1628 };
1629
1630 ///////////////////////////////////////////////////////////////////////////////
1631
1632 namespace {
1633
create_domain(GrTexture * texture,const SkIRect * srcBounds,GrTextureDomain::Mode mode)1634 GrTextureDomain create_domain(GrTexture* texture, const SkIRect* srcBounds,
1635 GrTextureDomain::Mode mode) {
1636 if (srcBounds) {
1637 SkRect texelDomain = GrTextureDomain::MakeTexelDomainForMode(texture, *srcBounds, mode);
1638 return GrTextureDomain(texelDomain, mode);
1639 } else {
1640 return GrTextureDomain(SkRect::MakeEmpty(), GrTextureDomain::kIgnore_Mode);
1641 }
1642 }
1643
1644 };
1645
GrLightingEffect(GrTexture * texture,const SkImageFilterLight * light,SkScalar surfaceScale,const SkMatrix & matrix,BoundaryMode boundaryMode,const SkIRect * srcBounds)1646 GrLightingEffect::GrLightingEffect(GrTexture* texture,
1647 const SkImageFilterLight* light,
1648 SkScalar surfaceScale,
1649 const SkMatrix& matrix,
1650 BoundaryMode boundaryMode,
1651 const SkIRect* srcBounds)
1652 : INHERITED(texture, GrCoordTransform::MakeDivByTextureWHMatrix(texture))
1653 , fLight(light)
1654 , fSurfaceScale(surfaceScale)
1655 , fFilterMatrix(matrix)
1656 , fBoundaryMode(boundaryMode)
1657 , fDomain(create_domain(texture, srcBounds, GrTextureDomain::kDecal_Mode)) {
1658 fLight->ref();
1659 if (light->requiresFragmentPosition()) {
1660 this->setWillReadFragmentPosition();
1661 }
1662 }
1663
~GrLightingEffect()1664 GrLightingEffect::~GrLightingEffect() {
1665 fLight->unref();
1666 }
1667
onIsEqual(const GrFragmentProcessor & sBase) const1668 bool GrLightingEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
1669 const GrLightingEffect& s = sBase.cast<GrLightingEffect>();
1670 return fLight->isEqual(*s.fLight) &&
1671 fSurfaceScale == s.fSurfaceScale &&
1672 fBoundaryMode == s.fBoundaryMode;
1673 }
1674
1675 ///////////////////////////////////////////////////////////////////////////////
1676
GrDiffuseLightingEffect(GrTexture * texture,const SkImageFilterLight * light,SkScalar surfaceScale,const SkMatrix & matrix,SkScalar kd,BoundaryMode boundaryMode,const SkIRect * srcBounds)1677 GrDiffuseLightingEffect::GrDiffuseLightingEffect(GrTexture* texture,
1678 const SkImageFilterLight* light,
1679 SkScalar surfaceScale,
1680 const SkMatrix& matrix,
1681 SkScalar kd,
1682 BoundaryMode boundaryMode,
1683 const SkIRect* srcBounds)
1684 : INHERITED(texture, light, surfaceScale, matrix, boundaryMode, srcBounds), fKD(kd) {
1685 this->initClassID<GrDiffuseLightingEffect>();
1686 }
1687
onIsEqual(const GrFragmentProcessor & sBase) const1688 bool GrDiffuseLightingEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
1689 const GrDiffuseLightingEffect& s = sBase.cast<GrDiffuseLightingEffect>();
1690 return INHERITED::onIsEqual(sBase) && this->kd() == s.kd();
1691 }
1692
onGetGLSLProcessorKey(const GrGLSLCaps & caps,GrProcessorKeyBuilder * b) const1693 void GrDiffuseLightingEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
1694 GrProcessorKeyBuilder* b) const {
1695 GrGLDiffuseLightingEffect::GenKey(*this, caps, b);
1696 }
1697
onCreateGLSLInstance() const1698 GrGLSLFragmentProcessor* GrDiffuseLightingEffect::onCreateGLSLInstance() const {
1699 return new GrGLDiffuseLightingEffect;
1700 }
1701
1702 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDiffuseLightingEffect);
1703
TestCreate(GrProcessorTestData * d)1704 const GrFragmentProcessor* GrDiffuseLightingEffect::TestCreate(GrProcessorTestData* d) {
1705 int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
1706 GrProcessorUnitTest::kAlphaTextureIdx;
1707 GrTexture* tex = d->fTextures[texIdx];
1708 SkScalar surfaceScale = d->fRandom->nextSScalar1();
1709 SkScalar kd = d->fRandom->nextUScalar1();
1710 SkAutoTUnref<SkImageFilterLight> light(create_random_light(d->fRandom));
1711 SkMatrix matrix;
1712 for (int i = 0; i < 9; i++) {
1713 matrix[i] = d->fRandom->nextUScalar1();
1714 }
1715 SkIRect srcBounds = SkIRect::MakeXYWH(d->fRandom->nextRangeU(0, tex->width()),
1716 d->fRandom->nextRangeU(0, tex->height()),
1717 d->fRandom->nextRangeU(0, tex->width()),
1718 d->fRandom->nextRangeU(0, tex->height()));
1719 BoundaryMode mode = static_cast<BoundaryMode>(d->fRandom->nextU() % kBoundaryModeCount);
1720 return GrDiffuseLightingEffect::Create(tex, light, surfaceScale, matrix, kd, mode, &srcBounds);
1721 }
1722
1723
1724 ///////////////////////////////////////////////////////////////////////////////
1725
emitCode(EmitArgs & args)1726 void GrGLLightingEffect::emitCode(EmitArgs& args) {
1727 const GrLightingEffect& le = args.fFp.cast<GrLightingEffect>();
1728 if (!fLight) {
1729 fLight = le.light()->createGLLight();
1730 }
1731
1732 GrGLSLUniformHandler* uniformHandler = args.fUniformHandler;
1733 fImageIncrementUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
1734 kVec2f_GrSLType, kDefault_GrSLPrecision,
1735 "ImageIncrement");
1736 fSurfaceScaleUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
1737 kFloat_GrSLType, kDefault_GrSLPrecision,
1738 "SurfaceScale");
1739 fLight->emitLightColorUniform(uniformHandler);
1740 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
1741 SkString lightFunc;
1742 this->emitLightFunc(uniformHandler, fragBuilder, &lightFunc);
1743 static const GrGLSLShaderVar gSobelArgs[] = {
1744 GrGLSLShaderVar("a", kFloat_GrSLType),
1745 GrGLSLShaderVar("b", kFloat_GrSLType),
1746 GrGLSLShaderVar("c", kFloat_GrSLType),
1747 GrGLSLShaderVar("d", kFloat_GrSLType),
1748 GrGLSLShaderVar("e", kFloat_GrSLType),
1749 GrGLSLShaderVar("f", kFloat_GrSLType),
1750 GrGLSLShaderVar("scale", kFloat_GrSLType),
1751 };
1752 SkString sobelFuncName;
1753 SkString coords2D = fragBuilder->ensureFSCoords2D(args.fCoords, 0);
1754
1755 fragBuilder->emitFunction(kFloat_GrSLType,
1756 "sobel",
1757 SK_ARRAY_COUNT(gSobelArgs),
1758 gSobelArgs,
1759 "\treturn (-a + b - 2.0 * c + 2.0 * d -e + f) * scale;\n",
1760 &sobelFuncName);
1761 static const GrGLSLShaderVar gPointToNormalArgs[] = {
1762 GrGLSLShaderVar("x", kFloat_GrSLType),
1763 GrGLSLShaderVar("y", kFloat_GrSLType),
1764 GrGLSLShaderVar("scale", kFloat_GrSLType),
1765 };
1766 SkString pointToNormalName;
1767 fragBuilder->emitFunction(kVec3f_GrSLType,
1768 "pointToNormal",
1769 SK_ARRAY_COUNT(gPointToNormalArgs),
1770 gPointToNormalArgs,
1771 "\treturn normalize(vec3(-x * scale, -y * scale, 1));\n",
1772 &pointToNormalName);
1773
1774 static const GrGLSLShaderVar gInteriorNormalArgs[] = {
1775 GrGLSLShaderVar("m", kFloat_GrSLType, 9),
1776 GrGLSLShaderVar("surfaceScale", kFloat_GrSLType),
1777 };
1778 SkString normalBody = emitNormalFunc(le.boundaryMode(),
1779 pointToNormalName.c_str(),
1780 sobelFuncName.c_str());
1781 SkString normalName;
1782 fragBuilder->emitFunction(kVec3f_GrSLType,
1783 "normal",
1784 SK_ARRAY_COUNT(gInteriorNormalArgs),
1785 gInteriorNormalArgs,
1786 normalBody.c_str(),
1787 &normalName);
1788
1789 fragBuilder->codeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str());
1790 fragBuilder->codeAppend("\t\tfloat m[9];\n");
1791
1792 const char* imgInc = uniformHandler->getUniformCStr(fImageIncrementUni);
1793 const char* surfScale = uniformHandler->getUniformCStr(fSurfaceScaleUni);
1794
1795 int index = 0;
1796 for (int dy = 1; dy >= -1; dy--) {
1797 for (int dx = -1; dx <= 1; dx++) {
1798 SkString texCoords;
1799 texCoords.appendf("coord + vec2(%d, %d) * %s", dx, dy, imgInc);
1800 SkString temp;
1801 temp.appendf("temp%d", index);
1802 fragBuilder->codeAppendf("vec4 %s;", temp.c_str());
1803 fDomain.sampleTexture(fragBuilder,
1804 args.fUniformHandler,
1805 args.fGLSLCaps,
1806 le.domain(),
1807 temp.c_str(),
1808 texCoords,
1809 args.fSamplers[0]);
1810 fragBuilder->codeAppendf("m[%d] = %s.a;", index, temp.c_str());
1811 index++;
1812 }
1813 }
1814 fragBuilder->codeAppend("\t\tvec3 surfaceToLight = ");
1815 SkString arg;
1816 arg.appendf("%s * m[4]", surfScale);
1817 fLight->emitSurfaceToLight(uniformHandler, fragBuilder, arg.c_str());
1818 fragBuilder->codeAppend(";\n");
1819 fragBuilder->codeAppendf("\t\t%s = %s(%s(m, %s), surfaceToLight, ",
1820 args.fOutputColor, lightFunc.c_str(), normalName.c_str(), surfScale);
1821 fLight->emitLightColor(uniformHandler, fragBuilder, "surfaceToLight");
1822 fragBuilder->codeAppend(");\n");
1823 SkString modulate;
1824 GrGLSLMulVarBy4f(&modulate, args.fOutputColor, args.fInputColor);
1825 fragBuilder->codeAppend(modulate.c_str());
1826 }
1827
GenKey(const GrProcessor & proc,const GrGLSLCaps & caps,GrProcessorKeyBuilder * b)1828 void GrGLLightingEffect::GenKey(const GrProcessor& proc,
1829 const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) {
1830 const GrLightingEffect& lighting = proc.cast<GrLightingEffect>();
1831 b->add32(lighting.boundaryMode() << 2 | lighting.light()->type());
1832 b->add32(GrTextureDomain::GLDomain::DomainKey(lighting.domain()));
1833 }
1834
onSetData(const GrGLSLProgramDataManager & pdman,const GrProcessor & proc)1835 void GrGLLightingEffect::onSetData(const GrGLSLProgramDataManager& pdman,
1836 const GrProcessor& proc) {
1837 const GrLightingEffect& lighting = proc.cast<GrLightingEffect>();
1838 if (!fLight) {
1839 fLight = lighting.light()->createGLLight();
1840 }
1841
1842 GrTexture* texture = lighting.texture(0);
1843 float ySign = texture->origin() == kTopLeft_GrSurfaceOrigin ? -1.0f : 1.0f;
1844 pdman.set2f(fImageIncrementUni, 1.0f / texture->width(), ySign / texture->height());
1845 pdman.set1f(fSurfaceScaleUni, lighting.surfaceScale());
1846 SkAutoTUnref<SkImageFilterLight> transformedLight(
1847 lighting.light()->transform(lighting.filterMatrix()));
1848 fDomain.setData(pdman, lighting.domain(), texture->origin());
1849 fLight->setData(pdman, transformedLight);
1850 }
1851
1852 ///////////////////////////////////////////////////////////////////////////////
1853
1854 ///////////////////////////////////////////////////////////////////////////////
1855
emitLightFunc(GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,SkString * funcName)1856 void GrGLDiffuseLightingEffect::emitLightFunc(GrGLSLUniformHandler* uniformHandler,
1857 GrGLSLFPFragmentBuilder* fragBuilder,
1858 SkString* funcName) {
1859 const char* kd;
1860 fKDUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
1861 kFloat_GrSLType, kDefault_GrSLPrecision,
1862 "KD", &kd);
1863
1864 static const GrGLSLShaderVar gLightArgs[] = {
1865 GrGLSLShaderVar("normal", kVec3f_GrSLType),
1866 GrGLSLShaderVar("surfaceToLight", kVec3f_GrSLType),
1867 GrGLSLShaderVar("lightColor", kVec3f_GrSLType)
1868 };
1869 SkString lightBody;
1870 lightBody.appendf("\tfloat colorScale = %s * dot(normal, surfaceToLight);\n", kd);
1871 lightBody.appendf("\treturn vec4(lightColor * clamp(colorScale, 0.0, 1.0), 1.0);\n");
1872 fragBuilder->emitFunction(kVec4f_GrSLType,
1873 "light",
1874 SK_ARRAY_COUNT(gLightArgs),
1875 gLightArgs,
1876 lightBody.c_str(),
1877 funcName);
1878 }
1879
onSetData(const GrGLSLProgramDataManager & pdman,const GrProcessor & proc)1880 void GrGLDiffuseLightingEffect::onSetData(const GrGLSLProgramDataManager& pdman,
1881 const GrProcessor& proc) {
1882 INHERITED::onSetData(pdman, proc);
1883 const GrDiffuseLightingEffect& diffuse = proc.cast<GrDiffuseLightingEffect>();
1884 pdman.set1f(fKDUni, diffuse.kd());
1885 }
1886
1887 ///////////////////////////////////////////////////////////////////////////////
1888
GrSpecularLightingEffect(GrTexture * texture,const SkImageFilterLight * light,SkScalar surfaceScale,const SkMatrix & matrix,SkScalar ks,SkScalar shininess,BoundaryMode boundaryMode,const SkIRect * srcBounds)1889 GrSpecularLightingEffect::GrSpecularLightingEffect(GrTexture* texture,
1890 const SkImageFilterLight* light,
1891 SkScalar surfaceScale,
1892 const SkMatrix& matrix,
1893 SkScalar ks,
1894 SkScalar shininess,
1895 BoundaryMode boundaryMode,
1896 const SkIRect* srcBounds)
1897 : INHERITED(texture, light, surfaceScale, matrix, boundaryMode, srcBounds)
1898 , fKS(ks)
1899 , fShininess(shininess) {
1900 this->initClassID<GrSpecularLightingEffect>();
1901 }
1902
onIsEqual(const GrFragmentProcessor & sBase) const1903 bool GrSpecularLightingEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
1904 const GrSpecularLightingEffect& s = sBase.cast<GrSpecularLightingEffect>();
1905 return INHERITED::onIsEqual(sBase) &&
1906 this->ks() == s.ks() &&
1907 this->shininess() == s.shininess();
1908 }
1909
onGetGLSLProcessorKey(const GrGLSLCaps & caps,GrProcessorKeyBuilder * b) const1910 void GrSpecularLightingEffect::onGetGLSLProcessorKey(const GrGLSLCaps& caps,
1911 GrProcessorKeyBuilder* b) const {
1912 GrGLSpecularLightingEffect::GenKey(*this, caps, b);
1913 }
1914
onCreateGLSLInstance() const1915 GrGLSLFragmentProcessor* GrSpecularLightingEffect::onCreateGLSLInstance() const {
1916 return new GrGLSpecularLightingEffect;
1917 }
1918
1919 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrSpecularLightingEffect);
1920
TestCreate(GrProcessorTestData * d)1921 const GrFragmentProcessor* GrSpecularLightingEffect::TestCreate(GrProcessorTestData* d) {
1922 int texIdx = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
1923 GrProcessorUnitTest::kAlphaTextureIdx;
1924 GrTexture* tex = d->fTextures[texIdx];
1925 SkScalar surfaceScale = d->fRandom->nextSScalar1();
1926 SkScalar ks = d->fRandom->nextUScalar1();
1927 SkScalar shininess = d->fRandom->nextUScalar1();
1928 SkAutoTUnref<SkImageFilterLight> light(create_random_light(d->fRandom));
1929 SkMatrix matrix;
1930 for (int i = 0; i < 9; i++) {
1931 matrix[i] = d->fRandom->nextUScalar1();
1932 }
1933 BoundaryMode mode = static_cast<BoundaryMode>(d->fRandom->nextU() % kBoundaryModeCount);
1934 SkIRect srcBounds = SkIRect::MakeXYWH(d->fRandom->nextRangeU(0, tex->width()),
1935 d->fRandom->nextRangeU(0, tex->height()),
1936 d->fRandom->nextRangeU(0, tex->width()),
1937 d->fRandom->nextRangeU(0, tex->height()));
1938 return GrSpecularLightingEffect::Create(d->fTextures[GrProcessorUnitTest::kAlphaTextureIdx],
1939 light, surfaceScale, matrix, ks, shininess, mode,
1940 &srcBounds);
1941 }
1942
1943 ///////////////////////////////////////////////////////////////////////////////
1944
emitLightFunc(GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,SkString * funcName)1945 void GrGLSpecularLightingEffect::emitLightFunc(GrGLSLUniformHandler* uniformHandler,
1946 GrGLSLFPFragmentBuilder* fragBuilder,
1947 SkString* funcName) {
1948 const char* ks;
1949 const char* shininess;
1950
1951 fKSUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
1952 kFloat_GrSLType, kDefault_GrSLPrecision, "KS", &ks);
1953 fShininessUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
1954 kFloat_GrSLType,
1955 kDefault_GrSLPrecision,
1956 "Shininess",
1957 &shininess);
1958
1959 static const GrGLSLShaderVar gLightArgs[] = {
1960 GrGLSLShaderVar("normal", kVec3f_GrSLType),
1961 GrGLSLShaderVar("surfaceToLight", kVec3f_GrSLType),
1962 GrGLSLShaderVar("lightColor", kVec3f_GrSLType)
1963 };
1964 SkString lightBody;
1965 lightBody.appendf("\tvec3 halfDir = vec3(normalize(surfaceToLight + vec3(0, 0, 1)));\n");
1966 lightBody.appendf("\tfloat colorScale = %s * pow(dot(normal, halfDir), %s);\n", ks, shininess);
1967 lightBody.appendf("\tvec3 color = lightColor * clamp(colorScale, 0.0, 1.0);\n");
1968 lightBody.appendf("\treturn vec4(color, max(max(color.r, color.g), color.b));\n");
1969 fragBuilder->emitFunction(kVec4f_GrSLType,
1970 "light",
1971 SK_ARRAY_COUNT(gLightArgs),
1972 gLightArgs,
1973 lightBody.c_str(),
1974 funcName);
1975 }
1976
onSetData(const GrGLSLProgramDataManager & pdman,const GrProcessor & effect)1977 void GrGLSpecularLightingEffect::onSetData(const GrGLSLProgramDataManager& pdman,
1978 const GrProcessor& effect) {
1979 INHERITED::onSetData(pdman, effect);
1980 const GrSpecularLightingEffect& spec = effect.cast<GrSpecularLightingEffect>();
1981 pdman.set1f(fKSUni, spec.ks());
1982 pdman.set1f(fShininessUni, spec.shininess());
1983 }
1984
1985 ///////////////////////////////////////////////////////////////////////////////
emitLightColorUniform(GrGLSLUniformHandler * uniformHandler)1986 void GrGLLight::emitLightColorUniform(GrGLSLUniformHandler* uniformHandler) {
1987 fColorUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
1988 kVec3f_GrSLType, kDefault_GrSLPrecision,
1989 "LightColor");
1990 }
1991
emitLightColor(GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,const char * surfaceToLight)1992 void GrGLLight::emitLightColor(GrGLSLUniformHandler* uniformHandler,
1993 GrGLSLFPFragmentBuilder* fragBuilder,
1994 const char *surfaceToLight) {
1995 fragBuilder->codeAppend(uniformHandler->getUniformCStr(this->lightColorUni()));
1996 }
1997
setData(const GrGLSLProgramDataManager & pdman,const SkImageFilterLight * light) const1998 void GrGLLight::setData(const GrGLSLProgramDataManager& pdman,
1999 const SkImageFilterLight* light) const {
2000 setUniformPoint3(pdman, fColorUni,
2001 light->color().makeScale(SkScalarInvert(SkIntToScalar(255))));
2002 }
2003
2004 ///////////////////////////////////////////////////////////////////////////////
2005
setData(const GrGLSLProgramDataManager & pdman,const SkImageFilterLight * light) const2006 void GrGLDistantLight::setData(const GrGLSLProgramDataManager& pdman,
2007 const SkImageFilterLight* light) const {
2008 INHERITED::setData(pdman, light);
2009 SkASSERT(light->type() == SkImageFilterLight::kDistant_LightType);
2010 const SkDistantLight* distantLight = static_cast<const SkDistantLight*>(light);
2011 setUniformNormal3(pdman, fDirectionUni, distantLight->direction());
2012 }
2013
emitSurfaceToLight(GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,const char * z)2014 void GrGLDistantLight::emitSurfaceToLight(GrGLSLUniformHandler* uniformHandler,
2015 GrGLSLFPFragmentBuilder* fragBuilder,
2016 const char* z) {
2017 const char* dir;
2018 fDirectionUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
2019 kVec3f_GrSLType, kDefault_GrSLPrecision,
2020 "LightDirection", &dir);
2021 fragBuilder->codeAppend(dir);
2022 }
2023
2024 ///////////////////////////////////////////////////////////////////////////////
2025
setData(const GrGLSLProgramDataManager & pdman,const SkImageFilterLight * light) const2026 void GrGLPointLight::setData(const GrGLSLProgramDataManager& pdman,
2027 const SkImageFilterLight* light) const {
2028 INHERITED::setData(pdman, light);
2029 SkASSERT(light->type() == SkImageFilterLight::kPoint_LightType);
2030 const SkPointLight* pointLight = static_cast<const SkPointLight*>(light);
2031 setUniformPoint3(pdman, fLocationUni, pointLight->location());
2032 }
2033
emitSurfaceToLight(GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,const char * z)2034 void GrGLPointLight::emitSurfaceToLight(GrGLSLUniformHandler* uniformHandler,
2035 GrGLSLFPFragmentBuilder* fragBuilder,
2036 const char* z) {
2037 const char* loc;
2038 fLocationUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
2039 kVec3f_GrSLType, kDefault_GrSLPrecision,
2040 "LightLocation", &loc);
2041 fragBuilder->codeAppendf("normalize(%s - vec3(%s.xy, %s))",
2042 loc, fragBuilder->fragmentPosition(), z);
2043 }
2044
2045 ///////////////////////////////////////////////////////////////////////////////
2046
setData(const GrGLSLProgramDataManager & pdman,const SkImageFilterLight * light) const2047 void GrGLSpotLight::setData(const GrGLSLProgramDataManager& pdman,
2048 const SkImageFilterLight* light) const {
2049 INHERITED::setData(pdman, light);
2050 SkASSERT(light->type() == SkImageFilterLight::kSpot_LightType);
2051 const SkSpotLight* spotLight = static_cast<const SkSpotLight *>(light);
2052 setUniformPoint3(pdman, fLocationUni, spotLight->location());
2053 pdman.set1f(fExponentUni, spotLight->specularExponent());
2054 pdman.set1f(fCosInnerConeAngleUni, spotLight->cosInnerConeAngle());
2055 pdman.set1f(fCosOuterConeAngleUni, spotLight->cosOuterConeAngle());
2056 pdman.set1f(fConeScaleUni, spotLight->coneScale());
2057 setUniformNormal3(pdman, fSUni, spotLight->s());
2058 }
2059
emitSurfaceToLight(GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,const char * z)2060 void GrGLSpotLight::emitSurfaceToLight(GrGLSLUniformHandler* uniformHandler,
2061 GrGLSLFPFragmentBuilder* fragBuilder,
2062 const char* z) {
2063 const char* location;
2064 fLocationUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
2065 kVec3f_GrSLType, kDefault_GrSLPrecision,
2066 "LightLocation", &location);
2067
2068 fragBuilder->codeAppendf("normalize(%s - vec3(%s.xy, %s))",
2069 location, fragBuilder->fragmentPosition(), z);
2070 }
2071
emitLightColor(GrGLSLUniformHandler * uniformHandler,GrGLSLFPFragmentBuilder * fragBuilder,const char * surfaceToLight)2072 void GrGLSpotLight::emitLightColor(GrGLSLUniformHandler* uniformHandler,
2073 GrGLSLFPFragmentBuilder* fragBuilder,
2074 const char *surfaceToLight) {
2075
2076 const char* color = uniformHandler->getUniformCStr(this->lightColorUni()); // created by parent class.
2077
2078 const char* exponent;
2079 const char* cosInner;
2080 const char* cosOuter;
2081 const char* coneScale;
2082 const char* s;
2083 fExponentUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
2084 kFloat_GrSLType, kDefault_GrSLPrecision,
2085 "Exponent", &exponent);
2086 fCosInnerConeAngleUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
2087 kFloat_GrSLType, kDefault_GrSLPrecision,
2088 "CosInnerConeAngle", &cosInner);
2089 fCosOuterConeAngleUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
2090 kFloat_GrSLType, kDefault_GrSLPrecision,
2091 "CosOuterConeAngle", &cosOuter);
2092 fConeScaleUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
2093 kFloat_GrSLType, kDefault_GrSLPrecision,
2094 "ConeScale", &coneScale);
2095 fSUni = uniformHandler->addUniform(kFragment_GrShaderFlag,
2096 kVec3f_GrSLType, kDefault_GrSLPrecision, "S", &s);
2097
2098 static const GrGLSLShaderVar gLightColorArgs[] = {
2099 GrGLSLShaderVar("surfaceToLight", kVec3f_GrSLType)
2100 };
2101 SkString lightColorBody;
2102 lightColorBody.appendf("\tfloat cosAngle = -dot(surfaceToLight, %s);\n", s);
2103 lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosOuter);
2104 lightColorBody.appendf("\t\treturn vec3(0);\n");
2105 lightColorBody.appendf("\t}\n");
2106 lightColorBody.appendf("\tfloat scale = pow(cosAngle, %s);\n", exponent);
2107 lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosInner);
2108 lightColorBody.appendf("\t\treturn %s * scale * (cosAngle - %s) * %s;\n",
2109 color, cosOuter, coneScale);
2110 lightColorBody.appendf("\t}\n");
2111 lightColorBody.appendf("\treturn %s;\n", color);
2112 fragBuilder->emitFunction(kVec3f_GrSLType,
2113 "lightColor",
2114 SK_ARRAY_COUNT(gLightColorArgs),
2115 gLightColorArgs,
2116 lightColorBody.c_str(),
2117 &fLightColorFunc);
2118
2119 fragBuilder->codeAppendf("%s(%s)", fLightColorFunc.c_str(), surfaceToLight);
2120 }
2121
2122 #endif
2123
2124 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingImageFilter)
2125 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDiffuseLightingImageFilter)
2126 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSpecularLightingImageFilter)
2127 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
2128