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