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