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