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