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