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