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 "SkReadBuffer.h" 12#include "SkWriteBuffer.h" 13#include "SkReadBuffer.h" 14#include "SkWriteBuffer.h" 15#include "SkTypes.h" 16 17#if SK_SUPPORT_GPU 18#include "effects/GrSingleTextureEffect.h" 19#include "gl/GrGLEffect.h" 20#include "GrEffect.h" 21#include "GrTBackendEffectFactory.h" 22 23class GrGLDiffuseLightingEffect; 24class GrGLSpecularLightingEffect; 25 26// For brevity 27typedef GrGLUniformManager::UniformHandle UniformHandle; 28#endif 29 30namespace { 31 32const SkScalar gOneThird = SkScalarInvert(SkIntToScalar(3)); 33const SkScalar gTwoThirds = SkScalarDiv(SkIntToScalar(2), SkIntToScalar(3)); 34const SkScalar gOneHalf = 0.5f; 35const SkScalar gOneQuarter = 0.25f; 36 37#if SK_SUPPORT_GPU 38void setUniformPoint3(const GrGLUniformManager& uman, UniformHandle uni, const SkPoint3& point) { 39 GR_STATIC_ASSERT(sizeof(SkPoint3) == 3 * sizeof(GrGLfloat)); 40 uman.set3fv(uni, 1, &point.fX); 41} 42 43void setUniformNormal3(const GrGLUniformManager& uman, UniformHandle uni, const SkPoint3& point) { 44 setUniformPoint3(uman, uni, SkPoint3(point.fX, point.fY, point.fZ)); 45} 46#endif 47 48// Shift matrix components to the left, as we advance pixels to the right. 49inline void shiftMatrixLeft(int m[9]) { 50 m[0] = m[1]; 51 m[3] = m[4]; 52 m[6] = m[7]; 53 m[1] = m[2]; 54 m[4] = m[5]; 55 m[7] = m[8]; 56} 57 58class DiffuseLightingType { 59public: 60 DiffuseLightingType(SkScalar kd) 61 : fKD(kd) {} 62 SkPMColor light(const SkPoint3& normal, const SkPoint3& surfaceTolight, const SkPoint3& lightColor) const { 63 SkScalar colorScale = SkScalarMul(fKD, normal.dot(surfaceTolight)); 64 colorScale = SkScalarClampMax(colorScale, SK_Scalar1); 65 SkPoint3 color(lightColor * colorScale); 66 return SkPackARGB32(255, 67 SkClampMax(SkScalarRoundToInt(color.fX), 255), 68 SkClampMax(SkScalarRoundToInt(color.fY), 255), 69 SkClampMax(SkScalarRoundToInt(color.fZ), 255)); 70 } 71private: 72 SkScalar fKD; 73}; 74 75class SpecularLightingType { 76public: 77 SpecularLightingType(SkScalar ks, SkScalar shininess) 78 : fKS(ks), fShininess(shininess) {} 79 SkPMColor light(const SkPoint3& normal, const SkPoint3& surfaceTolight, const SkPoint3& lightColor) const { 80 SkPoint3 halfDir(surfaceTolight); 81 halfDir.fZ += SK_Scalar1; // eye position is always (0, 0, 1) 82 halfDir.normalize(); 83 SkScalar colorScale = SkScalarMul(fKS, 84 SkScalarPow(normal.dot(halfDir), fShininess)); 85 colorScale = SkScalarClampMax(colorScale, SK_Scalar1); 86 SkPoint3 color(lightColor * colorScale); 87 return SkPackARGB32(SkClampMax(SkScalarRoundToInt(color.maxComponent()), 255), 88 SkClampMax(SkScalarRoundToInt(color.fX), 255), 89 SkClampMax(SkScalarRoundToInt(color.fY), 255), 90 SkClampMax(SkScalarRoundToInt(color.fZ), 255)); 91 } 92private: 93 SkScalar fKS; 94 SkScalar fShininess; 95}; 96 97inline SkScalar sobel(int a, int b, int c, int d, int e, int f, SkScalar scale) { 98 return SkScalarMul(SkIntToScalar(-a + b - 2 * c + 2 * d -e + f), scale); 99} 100 101inline SkPoint3 pointToNormal(SkScalar x, SkScalar y, SkScalar surfaceScale) { 102 SkPoint3 vector(SkScalarMul(-x, surfaceScale), 103 SkScalarMul(-y, surfaceScale), 104 SK_Scalar1); 105 vector.normalize(); 106 return vector; 107} 108 109inline SkPoint3 topLeftNormal(int m[9], SkScalar surfaceScale) { 110 return pointToNormal(sobel(0, 0, m[4], m[5], m[7], m[8], gTwoThirds), 111 sobel(0, 0, m[4], m[7], m[5], m[8], gTwoThirds), 112 surfaceScale); 113} 114 115inline SkPoint3 topNormal(int m[9], SkScalar surfaceScale) { 116 return pointToNormal(sobel( 0, 0, m[3], m[5], m[6], m[8], gOneThird), 117 sobel(m[3], m[6], m[4], m[7], m[5], m[8], gOneHalf), 118 surfaceScale); 119} 120 121inline SkPoint3 topRightNormal(int m[9], SkScalar surfaceScale) { 122 return pointToNormal(sobel( 0, 0, m[3], m[4], m[6], m[7], gTwoThirds), 123 sobel(m[3], m[6], m[4], m[7], 0, 0, gTwoThirds), 124 surfaceScale); 125} 126 127inline SkPoint3 leftNormal(int m[9], SkScalar surfaceScale) { 128 return pointToNormal(sobel(m[1], m[2], m[4], m[5], m[7], m[8], gOneHalf), 129 sobel( 0, 0, m[1], m[7], m[2], m[8], gOneThird), 130 surfaceScale); 131} 132 133 134inline SkPoint3 interiorNormal(int m[9], SkScalar surfaceScale) { 135 return pointToNormal(sobel(m[0], m[2], m[3], m[5], m[6], m[8], gOneQuarter), 136 sobel(m[0], m[6], m[1], m[7], m[2], m[8], gOneQuarter), 137 surfaceScale); 138} 139 140inline SkPoint3 rightNormal(int m[9], SkScalar surfaceScale) { 141 return pointToNormal(sobel(m[0], m[1], m[3], m[4], m[6], m[7], gOneHalf), 142 sobel(m[0], m[6], m[1], m[7], 0, 0, gOneThird), 143 surfaceScale); 144} 145 146inline SkPoint3 bottomLeftNormal(int m[9], SkScalar surfaceScale) { 147 return pointToNormal(sobel(m[1], m[2], m[4], m[5], 0, 0, gTwoThirds), 148 sobel( 0, 0, m[1], m[4], m[2], m[5], gTwoThirds), 149 surfaceScale); 150} 151 152inline SkPoint3 bottomNormal(int m[9], SkScalar surfaceScale) { 153 return pointToNormal(sobel(m[0], m[2], m[3], m[5], 0, 0, gOneThird), 154 sobel(m[0], m[3], m[1], m[4], m[2], m[5], gOneHalf), 155 surfaceScale); 156} 157 158inline SkPoint3 bottomRightNormal(int m[9], SkScalar surfaceScale) { 159 return pointToNormal(sobel(m[0], m[1], m[3], m[4], 0, 0, gTwoThirds), 160 sobel(m[0], m[3], m[1], m[4], 0, 0, gTwoThirds), 161 surfaceScale); 162} 163 164template <class LightingType, class LightType> void lightBitmap(const LightingType& lightingType, const SkLight* light, const SkBitmap& src, SkBitmap* dst, SkScalar surfaceScale, const SkIRect& bounds) { 165 SkASSERT(dst->width() == bounds.width() && dst->height() == bounds.height()); 166 const LightType* l = static_cast<const LightType*>(light); 167 int left = bounds.left(), right = bounds.right(); 168 int bottom = bounds.bottom(); 169 int y = bounds.top(); 170 SkPMColor* dptr = dst->getAddr32(0, 0); 171 { 172 int x = left; 173 const SkPMColor* row1 = src.getAddr32(x, y); 174 const SkPMColor* row2 = src.getAddr32(x, y + 1); 175 int m[9]; 176 m[4] = SkGetPackedA32(*row1++); 177 m[5] = SkGetPackedA32(*row1++); 178 m[7] = SkGetPackedA32(*row2++); 179 m[8] = SkGetPackedA32(*row2++); 180 SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); 181 *dptr++ = lightingType.light(topLeftNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight)); 182 for (++x; x < right - 1; ++x) 183 { 184 shiftMatrixLeft(m); 185 m[5] = SkGetPackedA32(*row1++); 186 m[8] = SkGetPackedA32(*row2++); 187 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); 188 *dptr++ = lightingType.light(topNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight)); 189 } 190 shiftMatrixLeft(m); 191 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); 192 *dptr++ = lightingType.light(topRightNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight)); 193 } 194 195 for (++y; y < bottom - 1; ++y) { 196 int x = left; 197 const SkPMColor* row0 = src.getAddr32(x, y - 1); 198 const SkPMColor* row1 = src.getAddr32(x, y); 199 const SkPMColor* row2 = src.getAddr32(x, y + 1); 200 int m[9]; 201 m[1] = SkGetPackedA32(*row0++); 202 m[2] = SkGetPackedA32(*row0++); 203 m[4] = SkGetPackedA32(*row1++); 204 m[5] = SkGetPackedA32(*row1++); 205 m[7] = SkGetPackedA32(*row2++); 206 m[8] = SkGetPackedA32(*row2++); 207 SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); 208 *dptr++ = lightingType.light(leftNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight)); 209 for (++x; x < right - 1; ++x) { 210 shiftMatrixLeft(m); 211 m[2] = SkGetPackedA32(*row0++); 212 m[5] = SkGetPackedA32(*row1++); 213 m[8] = SkGetPackedA32(*row2++); 214 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); 215 *dptr++ = lightingType.light(interiorNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight)); 216 } 217 shiftMatrixLeft(m); 218 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); 219 *dptr++ = lightingType.light(rightNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight)); 220 } 221 222 { 223 int x = left; 224 const SkPMColor* row0 = src.getAddr32(x, bottom - 2); 225 const SkPMColor* row1 = src.getAddr32(x, bottom - 1); 226 int m[9]; 227 m[1] = SkGetPackedA32(*row0++); 228 m[2] = SkGetPackedA32(*row0++); 229 m[4] = SkGetPackedA32(*row1++); 230 m[5] = SkGetPackedA32(*row1++); 231 SkPoint3 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); 232 *dptr++ = lightingType.light(bottomLeftNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight)); 233 for (++x; x < right - 1; ++x) 234 { 235 shiftMatrixLeft(m); 236 m[2] = SkGetPackedA32(*row0++); 237 m[5] = SkGetPackedA32(*row1++); 238 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); 239 *dptr++ = lightingType.light(bottomNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight)); 240 } 241 shiftMatrixLeft(m); 242 surfaceToLight = l->surfaceToLight(x, y, m[4], surfaceScale); 243 *dptr++ = lightingType.light(bottomRightNormal(m, surfaceScale), surfaceToLight, l->lightColor(surfaceToLight)); 244 } 245} 246 247SkPoint3 readPoint3(SkReadBuffer& buffer) { 248 SkPoint3 point; 249 point.fX = buffer.readScalar(); 250 point.fY = buffer.readScalar(); 251 point.fZ = buffer.readScalar(); 252 buffer.validate(SkScalarIsFinite(point.fX) && 253 SkScalarIsFinite(point.fY) && 254 SkScalarIsFinite(point.fZ)); 255 return point; 256}; 257 258void writePoint3(const SkPoint3& point, SkWriteBuffer& buffer) { 259 buffer.writeScalar(point.fX); 260 buffer.writeScalar(point.fY); 261 buffer.writeScalar(point.fZ); 262}; 263 264class SkDiffuseLightingImageFilter : public SkLightingImageFilter { 265public: 266 SkDiffuseLightingImageFilter(SkLight* light, SkScalar surfaceScale, 267 SkScalar kd, SkImageFilter* input, const CropRect* cropRect); 268 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDiffuseLightingImageFilter) 269 SkScalar kd() const { return fKD; } 270 271protected: 272 explicit SkDiffuseLightingImageFilter(SkReadBuffer& buffer); 273 virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE; 274 virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context&, 275 SkBitmap* result, SkIPoint* offset) const SK_OVERRIDE; 276#if SK_SUPPORT_GPU 277 virtual bool asNewEffect(GrEffectRef** effect, GrTexture*, const SkMatrix& matrix, const SkIRect& bounds) const SK_OVERRIDE; 278#endif 279 280private: 281 typedef SkLightingImageFilter INHERITED; 282 SkScalar fKD; 283}; 284 285class SkSpecularLightingImageFilter : public SkLightingImageFilter { 286public: 287 SkSpecularLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess, SkImageFilter* input, const CropRect* cropRect); 288 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSpecularLightingImageFilter) 289 290 SkScalar ks() const { return fKS; } 291 SkScalar shininess() const { return fShininess; } 292 293protected: 294 explicit SkSpecularLightingImageFilter(SkReadBuffer& buffer); 295 virtual void flatten(SkWriteBuffer& buffer) const SK_OVERRIDE; 296 virtual bool onFilterImage(Proxy*, const SkBitmap& src, const Context&, 297 SkBitmap* result, SkIPoint* offset) const SK_OVERRIDE; 298#if SK_SUPPORT_GPU 299 virtual bool asNewEffect(GrEffectRef** effect, GrTexture*, const SkMatrix& matrix, const SkIRect& bounds) const SK_OVERRIDE; 300#endif 301 302private: 303 typedef SkLightingImageFilter INHERITED; 304 SkScalar fKS; 305 SkScalar fShininess; 306}; 307 308#if SK_SUPPORT_GPU 309 310class GrLightingEffect : public GrSingleTextureEffect { 311public: 312 GrLightingEffect(GrTexture* texture, const SkLight* light, SkScalar surfaceScale, const SkMatrix& matrix); 313 virtual ~GrLightingEffect(); 314 315 const SkLight* light() const { return fLight; } 316 SkScalar surfaceScale() const { return fSurfaceScale; } 317 const SkMatrix& filterMatrix() const { return fFilterMatrix; } 318 319 virtual void getConstantColorComponents(GrColor* color, 320 uint32_t* validFlags) const SK_OVERRIDE { 321 // lighting shaders are complicated. We just throw up our hands. 322 *validFlags = 0; 323 } 324 325protected: 326 virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE; 327 328private: 329 typedef GrSingleTextureEffect INHERITED; 330 const SkLight* fLight; 331 SkScalar fSurfaceScale; 332 SkMatrix fFilterMatrix; 333}; 334 335class GrDiffuseLightingEffect : public GrLightingEffect { 336public: 337 static GrEffectRef* Create(GrTexture* texture, 338 const SkLight* light, 339 SkScalar surfaceScale, 340 const SkMatrix& matrix, 341 SkScalar kd) { 342 AutoEffectUnref effect(SkNEW_ARGS(GrDiffuseLightingEffect, (texture, 343 light, 344 surfaceScale, 345 matrix, 346 kd))); 347 return CreateEffectRef(effect); 348 } 349 350 static const char* Name() { return "DiffuseLighting"; } 351 352 typedef GrGLDiffuseLightingEffect GLEffect; 353 354 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; 355 SkScalar kd() const { return fKD; } 356 357private: 358 virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE; 359 360 GrDiffuseLightingEffect(GrTexture* texture, 361 const SkLight* light, 362 SkScalar surfaceScale, 363 const SkMatrix& matrix, 364 SkScalar kd); 365 366 GR_DECLARE_EFFECT_TEST; 367 typedef GrLightingEffect INHERITED; 368 SkScalar fKD; 369}; 370 371class GrSpecularLightingEffect : public GrLightingEffect { 372public: 373 static GrEffectRef* Create(GrTexture* texture, 374 const SkLight* light, 375 SkScalar surfaceScale, 376 const SkMatrix& matrix, 377 SkScalar ks, 378 SkScalar shininess) { 379 AutoEffectUnref effect(SkNEW_ARGS(GrSpecularLightingEffect, (texture, 380 light, 381 surfaceScale, 382 matrix, 383 ks, 384 shininess))); 385 return CreateEffectRef(effect); 386 } 387 static const char* Name() { return "SpecularLighting"; } 388 389 typedef GrGLSpecularLightingEffect GLEffect; 390 391 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; 392 SkScalar ks() const { return fKS; } 393 SkScalar shininess() const { return fShininess; } 394 395private: 396 virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE; 397 398 GrSpecularLightingEffect(GrTexture* texture, 399 const SkLight* light, 400 SkScalar surfaceScale, 401 const SkMatrix& matrix, 402 SkScalar ks, 403 SkScalar shininess); 404 405 GR_DECLARE_EFFECT_TEST; 406 typedef GrLightingEffect INHERITED; 407 SkScalar fKS; 408 SkScalar fShininess; 409}; 410 411/////////////////////////////////////////////////////////////////////////////// 412 413class GrGLLight { 414public: 415 virtual ~GrGLLight() {} 416 417 /** 418 * This is called by GrGLLightingEffect::emitCode() before either of the two virtual functions 419 * below. It adds a vec3f uniform visible in the FS that represents the constant light color. 420 */ 421 void emitLightColorUniform(GrGLShaderBuilder*); 422 423 /** 424 * These two functions are called from GrGLLightingEffect's emitCode() function. 425 * emitSurfaceToLight places an expression in param out that is the vector from the surface to 426 * the light. The expression will be used in the FS. emitLightColor writes an expression into 427 * the FS that is the color of the light. Either function may add functions and/or uniforms to 428 * the FS. The default of emitLightColor appends the name of the constant light color uniform 429 * and so this function only needs to be overridden if the light color varies spatially. 430 */ 431 virtual void emitSurfaceToLight(GrGLShaderBuilder*, const char* z) = 0; 432 virtual void emitLightColor(GrGLShaderBuilder*, const char *surfaceToLight); 433 434 // This is called from GrGLLightingEffect's setData(). Subclasses of GrGLLight must call 435 // INHERITED::setData(). 436 virtual void setData(const GrGLUniformManager&, 437 const SkLight* light) const; 438 439protected: 440 /** 441 * Gets the constant light color uniform. Subclasses can use this in their emitLightColor 442 * function. 443 */ 444 UniformHandle lightColorUni() const { return fColorUni; } 445 446private: 447 UniformHandle fColorUni; 448 449 typedef SkRefCnt INHERITED; 450}; 451 452/////////////////////////////////////////////////////////////////////////////// 453 454class GrGLDistantLight : public GrGLLight { 455public: 456 virtual ~GrGLDistantLight() {} 457 virtual void setData(const GrGLUniformManager&, 458 const SkLight* light) const SK_OVERRIDE; 459 virtual void emitSurfaceToLight(GrGLShaderBuilder*, const char* z) SK_OVERRIDE; 460 461private: 462 typedef GrGLLight INHERITED; 463 UniformHandle fDirectionUni; 464}; 465 466/////////////////////////////////////////////////////////////////////////////// 467 468class GrGLPointLight : public GrGLLight { 469public: 470 virtual ~GrGLPointLight() {} 471 virtual void setData(const GrGLUniformManager&, 472 const SkLight* light) const SK_OVERRIDE; 473 virtual void emitSurfaceToLight(GrGLShaderBuilder*, const char* z) SK_OVERRIDE; 474 475private: 476 typedef GrGLLight INHERITED; 477 UniformHandle fLocationUni; 478}; 479 480/////////////////////////////////////////////////////////////////////////////// 481 482class GrGLSpotLight : public GrGLLight { 483public: 484 virtual ~GrGLSpotLight() {} 485 virtual void setData(const GrGLUniformManager&, 486 const SkLight* light) const SK_OVERRIDE; 487 virtual void emitSurfaceToLight(GrGLShaderBuilder*, const char* z) SK_OVERRIDE; 488 virtual void emitLightColor(GrGLShaderBuilder*, const char *surfaceToLight) SK_OVERRIDE; 489 490private: 491 typedef GrGLLight INHERITED; 492 493 SkString fLightColorFunc; 494 UniformHandle fLocationUni; 495 UniformHandle fExponentUni; 496 UniformHandle fCosOuterConeAngleUni; 497 UniformHandle fCosInnerConeAngleUni; 498 UniformHandle fConeScaleUni; 499 UniformHandle fSUni; 500}; 501#else 502 503class GrGLLight; 504 505#endif 506 507}; 508 509/////////////////////////////////////////////////////////////////////////////// 510 511class SkLight : public SkRefCnt { 512public: 513 SK_DECLARE_INST_COUNT(SkLight) 514 515 enum LightType { 516 kDistant_LightType, 517 kPoint_LightType, 518 kSpot_LightType, 519 }; 520 virtual LightType type() const = 0; 521 const SkPoint3& color() const { return fColor; } 522 virtual GrGLLight* createGLLight() const = 0; 523 virtual bool isEqual(const SkLight& other) const { 524 return fColor == other.fColor; 525 } 526 // Called to know whether the generated GrGLLight will require access to the fragment position. 527 virtual bool requiresFragmentPosition() const = 0; 528 virtual SkLight* transform(const SkMatrix& matrix) const = 0; 529 530 // Defined below SkLight's subclasses. 531 void flattenLight(SkWriteBuffer& buffer) const; 532 static SkLight* UnflattenLight(SkReadBuffer& buffer); 533 534protected: 535 SkLight(SkColor color) 536 : fColor(SkIntToScalar(SkColorGetR(color)), 537 SkIntToScalar(SkColorGetG(color)), 538 SkIntToScalar(SkColorGetB(color))) {} 539 SkLight(const SkPoint3& color) 540 : fColor(color) {} 541 SkLight(SkReadBuffer& buffer) { 542 fColor = readPoint3(buffer); 543 } 544 545 virtual void onFlattenLight(SkWriteBuffer& buffer) const = 0; 546 547 548private: 549 typedef SkRefCnt INHERITED; 550 SkPoint3 fColor; 551}; 552 553/////////////////////////////////////////////////////////////////////////////// 554 555class SkDistantLight : public SkLight { 556public: 557 SkDistantLight(const SkPoint3& direction, SkColor color) 558 : INHERITED(color), fDirection(direction) { 559 } 560 561 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const { 562 return fDirection; 563 }; 564 SkPoint3 lightColor(const SkPoint3&) const { return color(); } 565 virtual LightType type() const { return kDistant_LightType; } 566 const SkPoint3& direction() const { return fDirection; } 567 virtual GrGLLight* createGLLight() const SK_OVERRIDE { 568#if SK_SUPPORT_GPU 569 return SkNEW(GrGLDistantLight); 570#else 571 SkDEBUGFAIL("Should not call in GPU-less build"); 572 return NULL; 573#endif 574 } 575 virtual bool requiresFragmentPosition() const SK_OVERRIDE { return false; } 576 577 virtual bool isEqual(const SkLight& other) const SK_OVERRIDE { 578 if (other.type() != kDistant_LightType) { 579 return false; 580 } 581 582 const SkDistantLight& o = static_cast<const SkDistantLight&>(other); 583 return INHERITED::isEqual(other) && 584 fDirection == o.fDirection; 585 } 586 587 SkDistantLight(SkReadBuffer& buffer) : INHERITED(buffer) { 588 fDirection = readPoint3(buffer); 589 } 590 591protected: 592 SkDistantLight(const SkPoint3& direction, const SkPoint3& color) 593 : INHERITED(color), fDirection(direction) { 594 } 595 virtual SkLight* transform(const SkMatrix& matrix) const { 596 return new SkDistantLight(direction(), color()); 597 } 598 virtual void onFlattenLight(SkWriteBuffer& buffer) const SK_OVERRIDE { 599 writePoint3(fDirection, buffer); 600 } 601 602private: 603 typedef SkLight INHERITED; 604 SkPoint3 fDirection; 605}; 606 607/////////////////////////////////////////////////////////////////////////////// 608 609class SkPointLight : public SkLight { 610public: 611 SkPointLight(const SkPoint3& location, SkColor color) 612 : INHERITED(color), fLocation(location) {} 613 614 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const { 615 SkPoint3 direction(fLocation.fX - SkIntToScalar(x), 616 fLocation.fY - SkIntToScalar(y), 617 fLocation.fZ - SkScalarMul(SkIntToScalar(z), surfaceScale)); 618 direction.normalize(); 619 return direction; 620 }; 621 SkPoint3 lightColor(const SkPoint3&) const { return color(); } 622 virtual LightType type() const { return kPoint_LightType; } 623 const SkPoint3& location() const { return fLocation; } 624 virtual GrGLLight* createGLLight() const SK_OVERRIDE { 625#if SK_SUPPORT_GPU 626 return SkNEW(GrGLPointLight); 627#else 628 SkDEBUGFAIL("Should not call in GPU-less build"); 629 return NULL; 630#endif 631 } 632 virtual bool requiresFragmentPosition() const SK_OVERRIDE { return true; } 633 virtual bool isEqual(const SkLight& other) const SK_OVERRIDE { 634 if (other.type() != kPoint_LightType) { 635 return false; 636 } 637 const SkPointLight& o = static_cast<const SkPointLight&>(other); 638 return INHERITED::isEqual(other) && 639 fLocation == o.fLocation; 640 } 641 virtual SkLight* transform(const SkMatrix& matrix) const { 642 SkPoint location2 = SkPoint::Make(fLocation.fX, fLocation.fY); 643 matrix.mapPoints(&location2, 1); 644 // Use X scale and Y scale on Z and average the result 645 SkPoint locationZ = SkPoint::Make(fLocation.fZ, fLocation.fZ); 646 matrix.mapVectors(&locationZ, 1); 647 SkPoint3 location(location2.fX, location2.fY, SkScalarAve(locationZ.fX, locationZ.fY)); 648 return new SkPointLight(location, color()); 649 } 650 651 SkPointLight(SkReadBuffer& buffer) : INHERITED(buffer) { 652 fLocation = readPoint3(buffer); 653 } 654 655protected: 656 SkPointLight(const SkPoint3& location, const SkPoint3& color) 657 : INHERITED(color), fLocation(location) {} 658 virtual void onFlattenLight(SkWriteBuffer& buffer) const SK_OVERRIDE { 659 writePoint3(fLocation, buffer); 660 } 661 662private: 663 typedef SkLight INHERITED; 664 SkPoint3 fLocation; 665}; 666 667/////////////////////////////////////////////////////////////////////////////// 668 669class SkSpotLight : public SkLight { 670public: 671 SkSpotLight(const SkPoint3& location, const SkPoint3& target, SkScalar specularExponent, SkScalar cutoffAngle, SkColor color) 672 : INHERITED(color), 673 fLocation(location), 674 fTarget(target), 675 fSpecularExponent(SkScalarPin(specularExponent, kSpecularExponentMin, kSpecularExponentMax)) 676 { 677 fS = target - location; 678 fS.normalize(); 679 fCosOuterConeAngle = SkScalarCos(SkDegreesToRadians(cutoffAngle)); 680 const SkScalar antiAliasThreshold = 0.016f; 681 fCosInnerConeAngle = fCosOuterConeAngle + antiAliasThreshold; 682 fConeScale = SkScalarInvert(antiAliasThreshold); 683 } 684 685 virtual SkLight* transform(const SkMatrix& matrix) const { 686 SkPoint location2 = SkPoint::Make(fLocation.fX, fLocation.fY); 687 matrix.mapPoints(&location2, 1); 688 // Use X scale and Y scale on Z and average the result 689 SkPoint locationZ = SkPoint::Make(fLocation.fZ, fLocation.fZ); 690 matrix.mapVectors(&locationZ, 1); 691 SkPoint3 location(location2.fX, location2.fY, SkScalarAve(locationZ.fX, locationZ.fY)); 692 SkPoint target2 = SkPoint::Make(fTarget.fX, fTarget.fY); 693 matrix.mapPoints(&target2, 1); 694 SkPoint targetZ = SkPoint::Make(fTarget.fZ, fTarget.fZ); 695 matrix.mapVectors(&targetZ, 1); 696 SkPoint3 target(target2.fX, target2.fY, SkScalarAve(targetZ.fX, targetZ.fY)); 697 SkPoint3 s = target - location; 698 s.normalize(); 699 return new SkSpotLight(location, target, fSpecularExponent, fCosOuterConeAngle, fCosInnerConeAngle, fConeScale, s, color()); 700 } 701 702 SkPoint3 surfaceToLight(int x, int y, int z, SkScalar surfaceScale) const { 703 SkPoint3 direction(fLocation.fX - SkIntToScalar(x), 704 fLocation.fY - SkIntToScalar(y), 705 fLocation.fZ - SkScalarMul(SkIntToScalar(z), surfaceScale)); 706 direction.normalize(); 707 return direction; 708 }; 709 SkPoint3 lightColor(const SkPoint3& surfaceToLight) const { 710 SkScalar cosAngle = -surfaceToLight.dot(fS); 711 if (cosAngle < fCosOuterConeAngle) { 712 return SkPoint3(0, 0, 0); 713 } 714 SkScalar scale = SkScalarPow(cosAngle, fSpecularExponent); 715 if (cosAngle < fCosInnerConeAngle) { 716 scale = SkScalarMul(scale, cosAngle - fCosOuterConeAngle); 717 return color() * SkScalarMul(scale, fConeScale); 718 } 719 return color() * scale; 720 } 721 virtual GrGLLight* createGLLight() const SK_OVERRIDE { 722#if SK_SUPPORT_GPU 723 return SkNEW(GrGLSpotLight); 724#else 725 SkDEBUGFAIL("Should not call in GPU-less build"); 726 return NULL; 727#endif 728 } 729 virtual bool requiresFragmentPosition() const SK_OVERRIDE { return true; } 730 virtual LightType type() const { return kSpot_LightType; } 731 const SkPoint3& location() const { return fLocation; } 732 const SkPoint3& target() const { return fTarget; } 733 SkScalar specularExponent() const { return fSpecularExponent; } 734 SkScalar cosInnerConeAngle() const { return fCosInnerConeAngle; } 735 SkScalar cosOuterConeAngle() const { return fCosOuterConeAngle; } 736 SkScalar coneScale() const { return fConeScale; } 737 const SkPoint3& s() const { return fS; } 738 739 SkSpotLight(SkReadBuffer& buffer) : INHERITED(buffer) { 740 fLocation = readPoint3(buffer); 741 fTarget = readPoint3(buffer); 742 fSpecularExponent = buffer.readScalar(); 743 fCosOuterConeAngle = buffer.readScalar(); 744 fCosInnerConeAngle = buffer.readScalar(); 745 fConeScale = buffer.readScalar(); 746 fS = readPoint3(buffer); 747 buffer.validate(SkScalarIsFinite(fSpecularExponent) && 748 SkScalarIsFinite(fCosOuterConeAngle) && 749 SkScalarIsFinite(fCosInnerConeAngle) && 750 SkScalarIsFinite(fConeScale)); 751 } 752protected: 753 SkSpotLight(const SkPoint3& location, const SkPoint3& target, SkScalar specularExponent, SkScalar cosOuterConeAngle, SkScalar cosInnerConeAngle, SkScalar coneScale, const SkPoint3& s, const SkPoint3& color) 754 : INHERITED(color), 755 fLocation(location), 756 fTarget(target), 757 fSpecularExponent(specularExponent), 758 fCosOuterConeAngle(cosOuterConeAngle), 759 fCosInnerConeAngle(cosInnerConeAngle), 760 fConeScale(coneScale), 761 fS(s) 762 { 763 } 764 virtual void onFlattenLight(SkWriteBuffer& buffer) const SK_OVERRIDE { 765 writePoint3(fLocation, buffer); 766 writePoint3(fTarget, buffer); 767 buffer.writeScalar(fSpecularExponent); 768 buffer.writeScalar(fCosOuterConeAngle); 769 buffer.writeScalar(fCosInnerConeAngle); 770 buffer.writeScalar(fConeScale); 771 writePoint3(fS, buffer); 772 } 773 774 virtual bool isEqual(const SkLight& other) const SK_OVERRIDE { 775 if (other.type() != kSpot_LightType) { 776 return false; 777 } 778 779 const SkSpotLight& o = static_cast<const SkSpotLight&>(other); 780 return INHERITED::isEqual(other) && 781 fLocation == o.fLocation && 782 fTarget == o.fTarget && 783 fSpecularExponent == o.fSpecularExponent && 784 fCosOuterConeAngle == o.fCosOuterConeAngle; 785 } 786 787private: 788 static const SkScalar kSpecularExponentMin; 789 static const SkScalar kSpecularExponentMax; 790 791 typedef SkLight INHERITED; 792 SkPoint3 fLocation; 793 SkPoint3 fTarget; 794 SkScalar fSpecularExponent; 795 SkScalar fCosOuterConeAngle; 796 SkScalar fCosInnerConeAngle; 797 SkScalar fConeScale; 798 SkPoint3 fS; 799}; 800 801// According to the spec, the specular term should be in the range [1, 128] : 802// http://www.w3.org/TR/SVG/filters.html#feSpecularLightingSpecularExponentAttribute 803const SkScalar SkSpotLight::kSpecularExponentMin = 1.0f; 804const SkScalar SkSpotLight::kSpecularExponentMax = 128.0f; 805 806/////////////////////////////////////////////////////////////////////////////// 807 808void SkLight::flattenLight(SkWriteBuffer& buffer) const { 809 // Write type first, then baseclass, then subclass. 810 buffer.writeInt(this->type()); 811 writePoint3(fColor, buffer); 812 this->onFlattenLight(buffer); 813} 814 815/*static*/ SkLight* SkLight::UnflattenLight(SkReadBuffer& buffer) { 816 // Read type first. 817 const SkLight::LightType type = (SkLight::LightType)buffer.readInt(); 818 switch (type) { 819 // Each of these constructors must first call SkLight's, so we'll read the baseclass 820 // then subclass, same order as flattenLight. 821 case SkLight::kDistant_LightType: return SkNEW_ARGS(SkDistantLight, (buffer)); 822 case SkLight::kPoint_LightType: return SkNEW_ARGS(SkPointLight, (buffer)); 823 case SkLight::kSpot_LightType: return SkNEW_ARGS(SkSpotLight, (buffer)); 824 default: 825 SkDEBUGFAIL("Unknown LightType."); 826 buffer.validate(false); 827 return NULL; 828 } 829} 830/////////////////////////////////////////////////////////////////////////////// 831 832SkLightingImageFilter::SkLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkImageFilter* input, const CropRect* cropRect) 833 : INHERITED(input, cropRect), 834 fLight(light), 835 fSurfaceScale(SkScalarDiv(surfaceScale, SkIntToScalar(255))) 836{ 837 SkASSERT(fLight); 838 // our caller knows that we take ownership of the light, so we don't 839 // need to call ref() here. 840} 841 842SkImageFilter* SkLightingImageFilter::CreateDistantLitDiffuse( 843 const SkPoint3& direction, SkColor lightColor, SkScalar surfaceScale, 844 SkScalar kd, SkImageFilter* input, const CropRect* cropRect) { 845 return SkNEW_ARGS(SkDiffuseLightingImageFilter, 846 (SkNEW_ARGS(SkDistantLight, (direction, lightColor)), surfaceScale, kd, 847 input, cropRect)); 848} 849 850SkImageFilter* SkLightingImageFilter::CreatePointLitDiffuse( 851 const SkPoint3& location, SkColor lightColor, SkScalar surfaceScale, 852 SkScalar kd, SkImageFilter* input, const CropRect* cropRect) { 853 return SkNEW_ARGS(SkDiffuseLightingImageFilter, 854 (SkNEW_ARGS(SkPointLight, (location, lightColor)), surfaceScale, kd, 855 input, cropRect)); 856} 857 858SkImageFilter* SkLightingImageFilter::CreateSpotLitDiffuse( 859 const SkPoint3& location, const SkPoint3& target, 860 SkScalar specularExponent, SkScalar cutoffAngle, 861 SkColor lightColor, SkScalar surfaceScale, SkScalar kd, 862 SkImageFilter* input, const CropRect* cropRect) { 863 return SkNEW_ARGS(SkDiffuseLightingImageFilter, 864 (SkNEW_ARGS(SkSpotLight, (location, target, specularExponent, 865 cutoffAngle, lightColor)), 866 surfaceScale, kd, input, cropRect)); 867} 868 869SkImageFilter* SkLightingImageFilter::CreateDistantLitSpecular( 870 const SkPoint3& direction, SkColor lightColor, SkScalar surfaceScale, 871 SkScalar ks, SkScalar shininess, SkImageFilter* input, const CropRect* cropRect) { 872 return SkNEW_ARGS(SkSpecularLightingImageFilter, 873 (SkNEW_ARGS(SkDistantLight, (direction, lightColor)), 874 surfaceScale, ks, shininess, input, cropRect)); 875} 876 877SkImageFilter* SkLightingImageFilter::CreatePointLitSpecular( 878 const SkPoint3& location, SkColor lightColor, SkScalar surfaceScale, 879 SkScalar ks, SkScalar shininess, SkImageFilter* input, const CropRect* cropRect) { 880 return SkNEW_ARGS(SkSpecularLightingImageFilter, 881 (SkNEW_ARGS(SkPointLight, (location, lightColor)), 882 surfaceScale, ks, shininess, input, cropRect)); 883} 884 885SkImageFilter* SkLightingImageFilter::CreateSpotLitSpecular( 886 const SkPoint3& location, const SkPoint3& target, 887 SkScalar specularExponent, SkScalar cutoffAngle, 888 SkColor lightColor, SkScalar surfaceScale, 889 SkScalar ks, SkScalar shininess, SkImageFilter* input, const CropRect* cropRect) { 890 return SkNEW_ARGS(SkSpecularLightingImageFilter, 891 (SkNEW_ARGS(SkSpotLight, (location, target, specularExponent, cutoffAngle, lightColor)), 892 surfaceScale, ks, shininess, input, cropRect)); 893} 894 895SkLightingImageFilter::~SkLightingImageFilter() { 896 SkSafeUnref(fLight); 897} 898 899SkLightingImageFilter::SkLightingImageFilter(SkReadBuffer& buffer) 900 : INHERITED(1, buffer) { 901 fLight = SkLight::UnflattenLight(buffer); 902 fSurfaceScale = buffer.readScalar(); 903 buffer.validate(SkScalarIsFinite(fSurfaceScale)); 904} 905 906void SkLightingImageFilter::flatten(SkWriteBuffer& buffer) const { 907 this->INHERITED::flatten(buffer); 908 fLight->flattenLight(buffer); 909 buffer.writeScalar(fSurfaceScale); 910} 911 912/////////////////////////////////////////////////////////////////////////////// 913 914SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar kd, SkImageFilter* input, const CropRect* cropRect = NULL) 915 : SkLightingImageFilter(light, surfaceScale, input, cropRect), 916 // According to the spec, kd can be any non-negative number : 917 // http://www.w3.org/TR/SVG/filters.html#feDiffuseLightingElement 918 fKD(kd < 0 ? 0 : kd) 919{ 920} 921 922SkDiffuseLightingImageFilter::SkDiffuseLightingImageFilter(SkReadBuffer& buffer) 923 : INHERITED(buffer) 924{ 925 fKD = buffer.readScalar(); 926 buffer.validate(SkScalarIsFinite(fKD) && (fKD >= 0)); 927} 928 929void SkDiffuseLightingImageFilter::flatten(SkWriteBuffer& buffer) const { 930 this->INHERITED::flatten(buffer); 931 buffer.writeScalar(fKD); 932} 933 934bool SkDiffuseLightingImageFilter::onFilterImage(Proxy* proxy, 935 const SkBitmap& source, 936 const Context& ctx, 937 SkBitmap* dst, 938 SkIPoint* offset) const { 939 SkImageFilter* input = getInput(0); 940 SkBitmap src = source; 941 SkIPoint srcOffset = SkIPoint::Make(0, 0); 942 if (input && !input->filterImage(proxy, source, ctx, &src, &srcOffset)) { 943 return false; 944 } 945 946 if (src.colorType() != kN32_SkColorType) { 947 return false; 948 } 949 SkIRect bounds; 950 if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &bounds, &src)) { 951 return false; 952 } 953 954 if (bounds.width() < 2 || bounds.height() < 2) { 955 return false; 956 } 957 958 SkAutoLockPixels alp(src); 959 if (!src.getPixels()) { 960 return false; 961 } 962 963 if (!dst->allocPixels(src.info().makeWH(bounds.width(), bounds.height()))) { 964 return false; 965 } 966 967 SkAutoTUnref<SkLight> transformedLight(light()->transform(ctx.ctm())); 968 969 DiffuseLightingType lightingType(fKD); 970 offset->fX = bounds.left(); 971 offset->fY = bounds.top(); 972 bounds.offset(-srcOffset); 973 switch (transformedLight->type()) { 974 case SkLight::kDistant_LightType: 975 lightBitmap<DiffuseLightingType, SkDistantLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds); 976 break; 977 case SkLight::kPoint_LightType: 978 lightBitmap<DiffuseLightingType, SkPointLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds); 979 break; 980 case SkLight::kSpot_LightType: 981 lightBitmap<DiffuseLightingType, SkSpotLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds); 982 break; 983 } 984 985 return true; 986} 987 988#if SK_SUPPORT_GPU 989bool SkDiffuseLightingImageFilter::asNewEffect(GrEffectRef** effect, GrTexture* texture, const SkMatrix& matrix, const SkIRect&) const { 990 if (effect) { 991 SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255)); 992 *effect = GrDiffuseLightingEffect::Create(texture, light(), scale, matrix, kd()); 993 } 994 return true; 995} 996#endif 997 998/////////////////////////////////////////////////////////////////////////////// 999 1000SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkLight* light, SkScalar surfaceScale, SkScalar ks, SkScalar shininess, SkImageFilter* input, const CropRect* cropRect) 1001 : SkLightingImageFilter(light, surfaceScale, input, cropRect), 1002 // According to the spec, ks can be any non-negative number : 1003 // http://www.w3.org/TR/SVG/filters.html#feSpecularLightingElement 1004 fKS(ks < 0 ? 0 : ks), 1005 fShininess(shininess) 1006{ 1007} 1008 1009SkSpecularLightingImageFilter::SkSpecularLightingImageFilter(SkReadBuffer& buffer) 1010 : INHERITED(buffer) 1011{ 1012 fKS = buffer.readScalar(); 1013 fShininess = buffer.readScalar(); 1014 buffer.validate(SkScalarIsFinite(fKS) && (fKS >= 0) && 1015 SkScalarIsFinite(fShininess)); 1016} 1017 1018void SkSpecularLightingImageFilter::flatten(SkWriteBuffer& buffer) const { 1019 this->INHERITED::flatten(buffer); 1020 buffer.writeScalar(fKS); 1021 buffer.writeScalar(fShininess); 1022} 1023 1024bool SkSpecularLightingImageFilter::onFilterImage(Proxy* proxy, 1025 const SkBitmap& source, 1026 const Context& ctx, 1027 SkBitmap* dst, 1028 SkIPoint* offset) const { 1029 SkImageFilter* input = getInput(0); 1030 SkBitmap src = source; 1031 SkIPoint srcOffset = SkIPoint::Make(0, 0); 1032 if (input && !input->filterImage(proxy, source, ctx, &src, &srcOffset)) { 1033 return false; 1034 } 1035 1036 if (src.colorType() != kN32_SkColorType) { 1037 return false; 1038 } 1039 1040 SkIRect bounds; 1041 if (!this->applyCropRect(ctx, proxy, src, &srcOffset, &bounds, &src)) { 1042 return false; 1043 } 1044 1045 if (bounds.width() < 2 || bounds.height() < 2) { 1046 return false; 1047 } 1048 1049 SkAutoLockPixels alp(src); 1050 if (!src.getPixels()) { 1051 return false; 1052 } 1053 1054 if (!dst->allocPixels(src.info().makeWH(bounds.width(), bounds.height()))) { 1055 return false; 1056 } 1057 1058 SpecularLightingType lightingType(fKS, fShininess); 1059 offset->fX = bounds.left(); 1060 offset->fY = bounds.top(); 1061 bounds.offset(-srcOffset); 1062 SkAutoTUnref<SkLight> transformedLight(light()->transform(ctx.ctm())); 1063 switch (transformedLight->type()) { 1064 case SkLight::kDistant_LightType: 1065 lightBitmap<SpecularLightingType, SkDistantLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds); 1066 break; 1067 case SkLight::kPoint_LightType: 1068 lightBitmap<SpecularLightingType, SkPointLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds); 1069 break; 1070 case SkLight::kSpot_LightType: 1071 lightBitmap<SpecularLightingType, SkSpotLight>(lightingType, transformedLight, src, dst, surfaceScale(), bounds); 1072 break; 1073 } 1074 return true; 1075} 1076 1077#if SK_SUPPORT_GPU 1078bool SkSpecularLightingImageFilter::asNewEffect(GrEffectRef** effect, GrTexture* texture, const SkMatrix& matrix, const SkIRect&) const { 1079 if (effect) { 1080 SkScalar scale = SkScalarMul(surfaceScale(), SkIntToScalar(255)); 1081 *effect = GrSpecularLightingEffect::Create(texture, light(), scale, matrix, ks(), shininess()); 1082 } 1083 return true; 1084} 1085#endif 1086 1087/////////////////////////////////////////////////////////////////////////////// 1088 1089#if SK_SUPPORT_GPU 1090 1091namespace { 1092SkPoint3 random_point3(SkRandom* random) { 1093 return SkPoint3(SkScalarToFloat(random->nextSScalar1()), 1094 SkScalarToFloat(random->nextSScalar1()), 1095 SkScalarToFloat(random->nextSScalar1())); 1096} 1097 1098SkLight* create_random_light(SkRandom* random) { 1099 int type = random->nextULessThan(3); 1100 switch (type) { 1101 case 0: { 1102 return SkNEW_ARGS(SkDistantLight, (random_point3(random), random->nextU())); 1103 } 1104 case 1: { 1105 return SkNEW_ARGS(SkPointLight, (random_point3(random), random->nextU())); 1106 } 1107 case 2: { 1108 return SkNEW_ARGS(SkSpotLight, (random_point3(random), 1109 random_point3(random), 1110 random->nextUScalar1(), 1111 random->nextUScalar1(), 1112 random->nextU())); 1113 } 1114 default: 1115 SkFAIL("Unexpected value."); 1116 return NULL; 1117 } 1118} 1119 1120} 1121 1122class GrGLLightingEffect : public GrGLEffect { 1123public: 1124 GrGLLightingEffect(const GrBackendEffectFactory& factory, 1125 const GrDrawEffect& effect); 1126 virtual ~GrGLLightingEffect(); 1127 1128 virtual void emitCode(GrGLShaderBuilder*, 1129 const GrDrawEffect&, 1130 EffectKey, 1131 const char* outputColor, 1132 const char* inputColor, 1133 const TransformedCoordsArray&, 1134 const TextureSamplerArray&) SK_OVERRIDE; 1135 1136 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&); 1137 1138 /** 1139 * Subclasses of GrGLLightingEffect must call INHERITED::setData(); 1140 */ 1141 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE; 1142 1143protected: 1144 virtual void emitLightFunc(GrGLShaderBuilder*, SkString* funcName) = 0; 1145 1146private: 1147 typedef GrGLEffect INHERITED; 1148 1149 UniformHandle fImageIncrementUni; 1150 UniformHandle fSurfaceScaleUni; 1151 GrGLLight* fLight; 1152}; 1153 1154/////////////////////////////////////////////////////////////////////////////// 1155 1156class GrGLDiffuseLightingEffect : public GrGLLightingEffect { 1157public: 1158 GrGLDiffuseLightingEffect(const GrBackendEffectFactory& factory, 1159 const GrDrawEffect& drawEffect); 1160 virtual void emitLightFunc(GrGLShaderBuilder*, SkString* funcName) SK_OVERRIDE; 1161 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE; 1162 1163private: 1164 typedef GrGLLightingEffect INHERITED; 1165 1166 UniformHandle fKDUni; 1167}; 1168 1169/////////////////////////////////////////////////////////////////////////////// 1170 1171class GrGLSpecularLightingEffect : public GrGLLightingEffect { 1172public: 1173 GrGLSpecularLightingEffect(const GrBackendEffectFactory& factory, 1174 const GrDrawEffect& effect); 1175 virtual void emitLightFunc(GrGLShaderBuilder*, SkString* funcName) SK_OVERRIDE; 1176 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE; 1177 1178private: 1179 typedef GrGLLightingEffect INHERITED; 1180 1181 UniformHandle fKSUni; 1182 UniformHandle fShininessUni; 1183}; 1184 1185/////////////////////////////////////////////////////////////////////////////// 1186 1187GrLightingEffect::GrLightingEffect(GrTexture* texture, 1188 const SkLight* light, 1189 SkScalar surfaceScale, 1190 const SkMatrix& matrix) 1191 : INHERITED(texture, MakeDivByTextureWHMatrix(texture)) 1192 , fLight(light) 1193 , fSurfaceScale(surfaceScale) 1194 , fFilterMatrix(matrix) { 1195 fLight->ref(); 1196 if (light->requiresFragmentPosition()) { 1197 this->setWillReadFragmentPosition(); 1198 } 1199} 1200 1201GrLightingEffect::~GrLightingEffect() { 1202 fLight->unref(); 1203} 1204 1205bool GrLightingEffect::onIsEqual(const GrEffect& sBase) const { 1206 const GrLightingEffect& s = CastEffect<GrLightingEffect>(sBase); 1207 return this->texture(0) == s.texture(0) && 1208 fLight->isEqual(*s.fLight) && 1209 fSurfaceScale == s.fSurfaceScale; 1210} 1211 1212/////////////////////////////////////////////////////////////////////////////// 1213 1214GrDiffuseLightingEffect::GrDiffuseLightingEffect(GrTexture* texture, 1215 const SkLight* light, 1216 SkScalar surfaceScale, 1217 const SkMatrix& matrix, 1218 SkScalar kd) 1219 : INHERITED(texture, light, surfaceScale, matrix), fKD(kd) { 1220} 1221 1222const GrBackendEffectFactory& GrDiffuseLightingEffect::getFactory() const { 1223 return GrTBackendEffectFactory<GrDiffuseLightingEffect>::getInstance(); 1224} 1225 1226bool GrDiffuseLightingEffect::onIsEqual(const GrEffect& sBase) const { 1227 const GrDiffuseLightingEffect& s = CastEffect<GrDiffuseLightingEffect>(sBase); 1228 return INHERITED::onIsEqual(sBase) && 1229 this->kd() == s.kd(); 1230} 1231 1232GR_DEFINE_EFFECT_TEST(GrDiffuseLightingEffect); 1233 1234GrEffectRef* GrDiffuseLightingEffect::TestCreate(SkRandom* random, 1235 GrContext* context, 1236 const GrDrawTargetCaps&, 1237 GrTexture* textures[]) { 1238 SkScalar surfaceScale = random->nextSScalar1(); 1239 SkScalar kd = random->nextUScalar1(); 1240 SkAutoTUnref<SkLight> light(create_random_light(random)); 1241 SkMatrix matrix; 1242 for (int i = 0; i < 9; i++) { 1243 matrix[i] = random->nextUScalar1(); 1244 } 1245 return GrDiffuseLightingEffect::Create(textures[GrEffectUnitTest::kAlphaTextureIdx], 1246 light, surfaceScale, matrix, kd); 1247} 1248 1249 1250/////////////////////////////////////////////////////////////////////////////// 1251 1252GrGLLightingEffect::GrGLLightingEffect(const GrBackendEffectFactory& factory, 1253 const GrDrawEffect& drawEffect) 1254 : INHERITED(factory) { 1255 const GrLightingEffect& m = drawEffect.castEffect<GrLightingEffect>(); 1256 fLight = m.light()->createGLLight(); 1257} 1258 1259GrGLLightingEffect::~GrGLLightingEffect() { 1260 delete fLight; 1261} 1262 1263void GrGLLightingEffect::emitCode(GrGLShaderBuilder* builder, 1264 const GrDrawEffect&, 1265 EffectKey key, 1266 const char* outputColor, 1267 const char* inputColor, 1268 const TransformedCoordsArray& coords, 1269 const TextureSamplerArray& samplers) { 1270 SkString coords2D = builder->ensureFSCoords2D(coords, 0); 1271 1272 fImageIncrementUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, 1273 kVec2f_GrSLType, 1274 "ImageIncrement"); 1275 fSurfaceScaleUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, 1276 kFloat_GrSLType, 1277 "SurfaceScale"); 1278 fLight->emitLightColorUniform(builder); 1279 SkString lightFunc; 1280 this->emitLightFunc(builder, &lightFunc); 1281 static const GrGLShaderVar gSobelArgs[] = { 1282 GrGLShaderVar("a", kFloat_GrSLType), 1283 GrGLShaderVar("b", kFloat_GrSLType), 1284 GrGLShaderVar("c", kFloat_GrSLType), 1285 GrGLShaderVar("d", kFloat_GrSLType), 1286 GrGLShaderVar("e", kFloat_GrSLType), 1287 GrGLShaderVar("f", kFloat_GrSLType), 1288 GrGLShaderVar("scale", kFloat_GrSLType), 1289 }; 1290 SkString sobelFuncName; 1291 builder->fsEmitFunction(kFloat_GrSLType, 1292 "sobel", 1293 SK_ARRAY_COUNT(gSobelArgs), 1294 gSobelArgs, 1295 "\treturn (-a + b - 2.0 * c + 2.0 * d -e + f) * scale;\n", 1296 &sobelFuncName); 1297 static const GrGLShaderVar gPointToNormalArgs[] = { 1298 GrGLShaderVar("x", kFloat_GrSLType), 1299 GrGLShaderVar("y", kFloat_GrSLType), 1300 GrGLShaderVar("scale", kFloat_GrSLType), 1301 }; 1302 SkString pointToNormalName; 1303 builder->fsEmitFunction(kVec3f_GrSLType, 1304 "pointToNormal", 1305 SK_ARRAY_COUNT(gPointToNormalArgs), 1306 gPointToNormalArgs, 1307 "\treturn normalize(vec3(-x * scale, y * scale, 1));\n", 1308 &pointToNormalName); 1309 1310 static const GrGLShaderVar gInteriorNormalArgs[] = { 1311 GrGLShaderVar("m", kFloat_GrSLType, 9), 1312 GrGLShaderVar("surfaceScale", kFloat_GrSLType), 1313 }; 1314 SkString interiorNormalBody; 1315 interiorNormalBody.appendf("\treturn %s(%s(m[0], m[2], m[3], m[5], m[6], m[8], 0.25),\n" 1316 "\t %s(m[0], m[6], m[1], m[7], m[2], m[8], 0.25),\n" 1317 "\t surfaceScale);\n", 1318 pointToNormalName.c_str(), 1319 sobelFuncName.c_str(), 1320 sobelFuncName.c_str()); 1321 SkString interiorNormalName; 1322 builder->fsEmitFunction(kVec3f_GrSLType, 1323 "interiorNormal", 1324 SK_ARRAY_COUNT(gInteriorNormalArgs), 1325 gInteriorNormalArgs, 1326 interiorNormalBody.c_str(), 1327 &interiorNormalName); 1328 1329 builder->fsCodeAppendf("\t\tvec2 coord = %s;\n", coords2D.c_str()); 1330 builder->fsCodeAppend("\t\tfloat m[9];\n"); 1331 1332 const char* imgInc = builder->getUniformCStr(fImageIncrementUni); 1333 const char* surfScale = builder->getUniformCStr(fSurfaceScaleUni); 1334 1335 int index = 0; 1336 for (int dy = -1; dy <= 1; dy++) { 1337 for (int dx = -1; dx <= 1; dx++) { 1338 SkString texCoords; 1339 texCoords.appendf("coord + vec2(%d, %d) * %s", dx, dy, imgInc); 1340 builder->fsCodeAppendf("\t\tm[%d] = ", index++); 1341 builder->fsAppendTextureLookup(samplers[0], texCoords.c_str()); 1342 builder->fsCodeAppend(".a;\n"); 1343 } 1344 } 1345 builder->fsCodeAppend("\t\tvec3 surfaceToLight = "); 1346 SkString arg; 1347 arg.appendf("%s * m[4]", surfScale); 1348 fLight->emitSurfaceToLight(builder, arg.c_str()); 1349 builder->fsCodeAppend(";\n"); 1350 builder->fsCodeAppendf("\t\t%s = %s(%s(m, %s), surfaceToLight, ", 1351 outputColor, lightFunc.c_str(), interiorNormalName.c_str(), surfScale); 1352 fLight->emitLightColor(builder, "surfaceToLight"); 1353 builder->fsCodeAppend(");\n"); 1354 SkString modulate; 1355 GrGLSLMulVarBy4f(&modulate, 2, outputColor, inputColor); 1356 builder->fsCodeAppend(modulate.c_str()); 1357} 1358 1359GrGLEffect::EffectKey GrGLLightingEffect::GenKey(const GrDrawEffect& drawEffect, 1360 const GrGLCaps& caps) { 1361 return drawEffect.castEffect<GrLightingEffect>().light()->type(); 1362} 1363 1364void GrGLLightingEffect::setData(const GrGLUniformManager& uman, 1365 const GrDrawEffect& drawEffect) { 1366 const GrLightingEffect& lighting = drawEffect.castEffect<GrLightingEffect>(); 1367 GrTexture* texture = lighting.texture(0); 1368 float ySign = texture->origin() == kTopLeft_GrSurfaceOrigin ? -1.0f : 1.0f; 1369 uman.set2f(fImageIncrementUni, 1.0f / texture->width(), ySign / texture->height()); 1370 uman.set1f(fSurfaceScaleUni, lighting.surfaceScale()); 1371 SkAutoTUnref<SkLight> transformedLight(lighting.light()->transform(lighting.filterMatrix())); 1372 fLight->setData(uman, transformedLight); 1373} 1374 1375/////////////////////////////////////////////////////////////////////////////// 1376 1377/////////////////////////////////////////////////////////////////////////////// 1378 1379GrGLDiffuseLightingEffect::GrGLDiffuseLightingEffect(const GrBackendEffectFactory& factory, 1380 const GrDrawEffect& drawEffect) 1381 : INHERITED(factory, drawEffect) { 1382} 1383 1384void GrGLDiffuseLightingEffect::emitLightFunc(GrGLShaderBuilder* builder, SkString* funcName) { 1385 const char* kd; 1386 fKDUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, 1387 kFloat_GrSLType, 1388 "KD", 1389 &kd); 1390 1391 static const GrGLShaderVar gLightArgs[] = { 1392 GrGLShaderVar("normal", kVec3f_GrSLType), 1393 GrGLShaderVar("surfaceToLight", kVec3f_GrSLType), 1394 GrGLShaderVar("lightColor", kVec3f_GrSLType) 1395 }; 1396 SkString lightBody; 1397 lightBody.appendf("\tfloat colorScale = %s * dot(normal, surfaceToLight);\n", kd); 1398 lightBody.appendf("\treturn vec4(lightColor * clamp(colorScale, 0.0, 1.0), 1.0);\n"); 1399 builder->fsEmitFunction(kVec4f_GrSLType, 1400 "light", 1401 SK_ARRAY_COUNT(gLightArgs), 1402 gLightArgs, 1403 lightBody.c_str(), 1404 funcName); 1405} 1406 1407void GrGLDiffuseLightingEffect::setData(const GrGLUniformManager& uman, 1408 const GrDrawEffect& drawEffect) { 1409 INHERITED::setData(uman, drawEffect); 1410 const GrDiffuseLightingEffect& diffuse = drawEffect.castEffect<GrDiffuseLightingEffect>(); 1411 uman.set1f(fKDUni, diffuse.kd()); 1412} 1413 1414/////////////////////////////////////////////////////////////////////////////// 1415 1416GrSpecularLightingEffect::GrSpecularLightingEffect(GrTexture* texture, 1417 const SkLight* light, 1418 SkScalar surfaceScale, 1419 const SkMatrix& matrix, 1420 SkScalar ks, 1421 SkScalar shininess) 1422 : INHERITED(texture, light, surfaceScale, matrix), 1423 fKS(ks), 1424 fShininess(shininess) { 1425} 1426 1427const GrBackendEffectFactory& GrSpecularLightingEffect::getFactory() const { 1428 return GrTBackendEffectFactory<GrSpecularLightingEffect>::getInstance(); 1429} 1430 1431bool GrSpecularLightingEffect::onIsEqual(const GrEffect& sBase) const { 1432 const GrSpecularLightingEffect& s = CastEffect<GrSpecularLightingEffect>(sBase); 1433 return INHERITED::onIsEqual(sBase) && 1434 this->ks() == s.ks() && 1435 this->shininess() == s.shininess(); 1436} 1437 1438GR_DEFINE_EFFECT_TEST(GrSpecularLightingEffect); 1439 1440GrEffectRef* GrSpecularLightingEffect::TestCreate(SkRandom* random, 1441 GrContext* context, 1442 const GrDrawTargetCaps&, 1443 GrTexture* textures[]) { 1444 SkScalar surfaceScale = random->nextSScalar1(); 1445 SkScalar ks = random->nextUScalar1(); 1446 SkScalar shininess = random->nextUScalar1(); 1447 SkAutoTUnref<SkLight> light(create_random_light(random)); 1448 SkMatrix matrix; 1449 for (int i = 0; i < 9; i++) { 1450 matrix[i] = random->nextUScalar1(); 1451 } 1452 return GrSpecularLightingEffect::Create(textures[GrEffectUnitTest::kAlphaTextureIdx], 1453 light, surfaceScale, matrix, ks, shininess); 1454} 1455 1456/////////////////////////////////////////////////////////////////////////////// 1457 1458GrGLSpecularLightingEffect::GrGLSpecularLightingEffect(const GrBackendEffectFactory& factory, 1459 const GrDrawEffect& drawEffect) 1460 : INHERITED(factory, drawEffect) { 1461} 1462 1463void GrGLSpecularLightingEffect::emitLightFunc(GrGLShaderBuilder* builder, SkString* funcName) { 1464 const char* ks; 1465 const char* shininess; 1466 1467 fKSUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, 1468 kFloat_GrSLType, "KS", &ks); 1469 fShininessUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, 1470 kFloat_GrSLType, "Shininess", &shininess); 1471 1472 static const GrGLShaderVar gLightArgs[] = { 1473 GrGLShaderVar("normal", kVec3f_GrSLType), 1474 GrGLShaderVar("surfaceToLight", kVec3f_GrSLType), 1475 GrGLShaderVar("lightColor", kVec3f_GrSLType) 1476 }; 1477 SkString lightBody; 1478 lightBody.appendf("\tvec3 halfDir = vec3(normalize(surfaceToLight + vec3(0, 0, 1)));\n"); 1479 lightBody.appendf("\tfloat colorScale = %s * pow(dot(normal, halfDir), %s);\n", ks, shininess); 1480 lightBody.appendf("\tvec3 color = lightColor * clamp(colorScale, 0.0, 1.0);\n"); 1481 lightBody.appendf("\treturn vec4(color, max(max(color.r, color.g), color.b));\n"); 1482 builder->fsEmitFunction(kVec4f_GrSLType, 1483 "light", 1484 SK_ARRAY_COUNT(gLightArgs), 1485 gLightArgs, 1486 lightBody.c_str(), 1487 funcName); 1488} 1489 1490void GrGLSpecularLightingEffect::setData(const GrGLUniformManager& uman, 1491 const GrDrawEffect& drawEffect) { 1492 INHERITED::setData(uman, drawEffect); 1493 const GrSpecularLightingEffect& spec = drawEffect.castEffect<GrSpecularLightingEffect>(); 1494 uman.set1f(fKSUni, spec.ks()); 1495 uman.set1f(fShininessUni, spec.shininess()); 1496} 1497 1498/////////////////////////////////////////////////////////////////////////////// 1499void GrGLLight::emitLightColorUniform(GrGLShaderBuilder* builder) { 1500 fColorUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, 1501 kVec3f_GrSLType, "LightColor"); 1502} 1503 1504void GrGLLight::emitLightColor(GrGLShaderBuilder* builder, 1505 const char *surfaceToLight) { 1506 builder->fsCodeAppend(builder->getUniformCStr(this->lightColorUni())); 1507} 1508 1509void GrGLLight::setData(const GrGLUniformManager& uman, 1510 const SkLight* light) const { 1511 setUniformPoint3(uman, fColorUni, light->color() * SkScalarInvert(SkIntToScalar(255))); 1512} 1513 1514/////////////////////////////////////////////////////////////////////////////// 1515 1516void GrGLDistantLight::setData(const GrGLUniformManager& uman, 1517 const SkLight* light) const { 1518 INHERITED::setData(uman, light); 1519 SkASSERT(light->type() == SkLight::kDistant_LightType); 1520 const SkDistantLight* distantLight = static_cast<const SkDistantLight*>(light); 1521 setUniformNormal3(uman, fDirectionUni, distantLight->direction()); 1522} 1523 1524void GrGLDistantLight::emitSurfaceToLight(GrGLShaderBuilder* builder, const char* z) { 1525 const char* dir; 1526 fDirectionUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, kVec3f_GrSLType, 1527 "LightDirection", &dir); 1528 builder->fsCodeAppend(dir); 1529} 1530 1531/////////////////////////////////////////////////////////////////////////////// 1532 1533void GrGLPointLight::setData(const GrGLUniformManager& uman, 1534 const SkLight* light) const { 1535 INHERITED::setData(uman, light); 1536 SkASSERT(light->type() == SkLight::kPoint_LightType); 1537 const SkPointLight* pointLight = static_cast<const SkPointLight*>(light); 1538 setUniformPoint3(uman, fLocationUni, pointLight->location()); 1539} 1540 1541void GrGLPointLight::emitSurfaceToLight(GrGLShaderBuilder* builder, const char* z) { 1542 const char* loc; 1543 fLocationUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, kVec3f_GrSLType, 1544 "LightLocation", &loc); 1545 builder->fsCodeAppendf("normalize(%s - vec3(%s.xy, %s))", loc, builder->fragmentPosition(), z); 1546} 1547 1548/////////////////////////////////////////////////////////////////////////////// 1549 1550void GrGLSpotLight::setData(const GrGLUniformManager& uman, 1551 const SkLight* light) const { 1552 INHERITED::setData(uman, light); 1553 SkASSERT(light->type() == SkLight::kSpot_LightType); 1554 const SkSpotLight* spotLight = static_cast<const SkSpotLight *>(light); 1555 setUniformPoint3(uman, fLocationUni, spotLight->location()); 1556 uman.set1f(fExponentUni, spotLight->specularExponent()); 1557 uman.set1f(fCosInnerConeAngleUni, spotLight->cosInnerConeAngle()); 1558 uman.set1f(fCosOuterConeAngleUni, spotLight->cosOuterConeAngle()); 1559 uman.set1f(fConeScaleUni, spotLight->coneScale()); 1560 setUniformNormal3(uman, fSUni, spotLight->s()); 1561} 1562 1563void GrGLSpotLight::emitSurfaceToLight(GrGLShaderBuilder* builder, const char* z) { 1564 const char* location; 1565 fLocationUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, 1566 kVec3f_GrSLType, "LightLocation", &location); 1567 builder->fsCodeAppendf("normalize(%s - vec3(%s.xy, %s))", 1568 location, builder->fragmentPosition(), z); 1569} 1570 1571void GrGLSpotLight::emitLightColor(GrGLShaderBuilder* builder, 1572 const char *surfaceToLight) { 1573 1574 const char* color = builder->getUniformCStr(this->lightColorUni()); // created by parent class. 1575 1576 const char* exponent; 1577 const char* cosInner; 1578 const char* cosOuter; 1579 const char* coneScale; 1580 const char* s; 1581 fExponentUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, 1582 kFloat_GrSLType, "Exponent", &exponent); 1583 fCosInnerConeAngleUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, 1584 kFloat_GrSLType, "CosInnerConeAngle", &cosInner); 1585 fCosOuterConeAngleUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, 1586 kFloat_GrSLType, "CosOuterConeAngle", &cosOuter); 1587 fConeScaleUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, 1588 kFloat_GrSLType, "ConeScale", &coneScale); 1589 fSUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, 1590 kVec3f_GrSLType, "S", &s); 1591 1592 static const GrGLShaderVar gLightColorArgs[] = { 1593 GrGLShaderVar("surfaceToLight", kVec3f_GrSLType) 1594 }; 1595 SkString lightColorBody; 1596 lightColorBody.appendf("\tfloat cosAngle = -dot(surfaceToLight, %s);\n", s); 1597 lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosOuter); 1598 lightColorBody.appendf("\t\treturn vec3(0);\n"); 1599 lightColorBody.appendf("\t}\n"); 1600 lightColorBody.appendf("\tfloat scale = pow(cosAngle, %s);\n", exponent); 1601 lightColorBody.appendf("\tif (cosAngle < %s) {\n", cosInner); 1602 lightColorBody.appendf("\t\treturn %s * scale * (cosAngle - %s) * %s;\n", 1603 color, cosOuter, coneScale); 1604 lightColorBody.appendf("\t}\n"); 1605 lightColorBody.appendf("\treturn %s;\n", color); 1606 builder->fsEmitFunction(kVec3f_GrSLType, 1607 "lightColor", 1608 SK_ARRAY_COUNT(gLightColorArgs), 1609 gLightColorArgs, 1610 lightColorBody.c_str(), 1611 &fLightColorFunc); 1612 1613 builder->fsCodeAppendf("%s(%s)", fLightColorFunc.c_str(), surfaceToLight); 1614} 1615 1616#endif 1617 1618SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkLightingImageFilter) 1619 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDiffuseLightingImageFilter) 1620 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSpecularLightingImageFilter) 1621SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 1622