1 /* 2 * Copyright 2013 Google Inc. 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 "SkDisplacementMapEffect.h" 9 #include "SkDevice.h" 10 #include "SkReadBuffer.h" 11 #include "SkWriteBuffer.h" 12 #include "SkUnPreMultiply.h" 13 #include "SkColorPriv.h" 14 #if SK_SUPPORT_GPU 15 #include "GrContext.h" 16 #include "GrDrawContext.h" 17 #include "GrCoordTransform.h" 18 #include "GrInvariantOutput.h" 19 #include "SkGr.h" 20 #include "effects/GrTextureDomain.h" 21 #include "glsl/GrGLSLFragmentProcessor.h" 22 #include "glsl/GrGLSLFragmentShaderBuilder.h" 23 #include "glsl/GrGLSLProgramDataManager.h" 24 #include "glsl/GrGLSLUniformHandler.h" 25 #endif 26 27 namespace { 28 29 #define kChannelSelectorKeyBits 3; // Max value is 4, so 3 bits are required at most 30 31 template<SkDisplacementMapEffect::ChannelSelectorType type> 32 uint32_t getValue(SkColor, const SkUnPreMultiply::Scale*) { 33 SkDEBUGFAIL("Unknown channel selector"); 34 return 0; 35 } 36 37 template<> uint32_t getValue<SkDisplacementMapEffect::kR_ChannelSelectorType>( 38 SkColor l, const SkUnPreMultiply::Scale* table) { 39 return SkUnPreMultiply::ApplyScale(table[SkGetPackedA32(l)], SkGetPackedR32(l)); 40 } 41 42 template<> uint32_t getValue<SkDisplacementMapEffect::kG_ChannelSelectorType>( 43 SkColor l, const SkUnPreMultiply::Scale* table) { 44 return SkUnPreMultiply::ApplyScale(table[SkGetPackedA32(l)], SkGetPackedG32(l)); 45 } 46 47 template<> uint32_t getValue<SkDisplacementMapEffect::kB_ChannelSelectorType>( 48 SkColor l, const SkUnPreMultiply::Scale* table) { 49 return SkUnPreMultiply::ApplyScale(table[SkGetPackedA32(l)], SkGetPackedB32(l)); 50 } 51 52 template<> uint32_t getValue<SkDisplacementMapEffect::kA_ChannelSelectorType>( 53 SkColor l, const SkUnPreMultiply::Scale*) { 54 return SkGetPackedA32(l); 55 } 56 57 template<SkDisplacementMapEffect::ChannelSelectorType typeX, 58 SkDisplacementMapEffect::ChannelSelectorType typeY> 59 void computeDisplacement(const SkVector& scale, SkBitmap* dst, 60 SkBitmap* displ, const SkIPoint& offset, 61 SkBitmap* src, 62 const SkIRect& bounds) 63 { 64 static const SkScalar Inv8bit = SkScalarInvert(255); 65 const int srcW = src->width(); 66 const int srcH = src->height(); 67 const SkVector scaleForColor = SkVector::Make(SkScalarMul(scale.fX, Inv8bit), 68 SkScalarMul(scale.fY, Inv8bit)); 69 const SkVector scaleAdj = SkVector::Make(SK_ScalarHalf - SkScalarMul(scale.fX, SK_ScalarHalf), 70 SK_ScalarHalf - SkScalarMul(scale.fY, SK_ScalarHalf)); 71 const SkUnPreMultiply::Scale* table = SkUnPreMultiply::GetScaleTable(); 72 SkPMColor* dstPtr = dst->getAddr32(0, 0); 73 for (int y = bounds.top(); y < bounds.bottom(); ++y) { 74 const SkPMColor* displPtr = displ->getAddr32(bounds.left() + offset.fX, 75 y + offset.fY); 76 for (int x = bounds.left(); x < bounds.right(); ++x, ++displPtr) { 77 const SkScalar displX = SkScalarMul(scaleForColor.fX, 78 SkIntToScalar(getValue<typeX>(*displPtr, table))) + scaleAdj.fX; 79 const SkScalar displY = SkScalarMul(scaleForColor.fY, 80 SkIntToScalar(getValue<typeY>(*displPtr, table))) + scaleAdj.fY; 81 // Truncate the displacement values 82 const int srcX = x + SkScalarTruncToInt(displX); 83 const int srcY = y + SkScalarTruncToInt(displY); 84 *dstPtr++ = ((srcX < 0) || (srcX >= srcW) || (srcY < 0) || (srcY >= srcH)) ? 85 0 : *(src->getAddr32(srcX, srcY)); 86 } 87 } 88 } 89 90 template<SkDisplacementMapEffect::ChannelSelectorType typeX> 91 void computeDisplacement(SkDisplacementMapEffect::ChannelSelectorType yChannelSelector, 92 const SkVector& scale, SkBitmap* dst, 93 SkBitmap* displ, const SkIPoint& offset, 94 SkBitmap* src, 95 const SkIRect& bounds) 96 { 97 switch (yChannelSelector) { 98 case SkDisplacementMapEffect::kR_ChannelSelectorType: 99 computeDisplacement<typeX, SkDisplacementMapEffect::kR_ChannelSelectorType>( 100 scale, dst, displ, offset, src, bounds); 101 break; 102 case SkDisplacementMapEffect::kG_ChannelSelectorType: 103 computeDisplacement<typeX, SkDisplacementMapEffect::kG_ChannelSelectorType>( 104 scale, dst, displ, offset, src, bounds); 105 break; 106 case SkDisplacementMapEffect::kB_ChannelSelectorType: 107 computeDisplacement<typeX, SkDisplacementMapEffect::kB_ChannelSelectorType>( 108 scale, dst, displ, offset, src, bounds); 109 break; 110 case SkDisplacementMapEffect::kA_ChannelSelectorType: 111 computeDisplacement<typeX, SkDisplacementMapEffect::kA_ChannelSelectorType>( 112 scale, dst, displ, offset, src, bounds); 113 break; 114 case SkDisplacementMapEffect::kUnknown_ChannelSelectorType: 115 default: 116 SkDEBUGFAIL("Unknown Y channel selector"); 117 } 118 } 119 120 void computeDisplacement(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector, 121 SkDisplacementMapEffect::ChannelSelectorType yChannelSelector, 122 const SkVector& scale, SkBitmap* dst, 123 SkBitmap* displ, const SkIPoint& offset, 124 SkBitmap* src, 125 const SkIRect& bounds) 126 { 127 switch (xChannelSelector) { 128 case SkDisplacementMapEffect::kR_ChannelSelectorType: 129 computeDisplacement<SkDisplacementMapEffect::kR_ChannelSelectorType>( 130 yChannelSelector, scale, dst, displ, offset, src, bounds); 131 break; 132 case SkDisplacementMapEffect::kG_ChannelSelectorType: 133 computeDisplacement<SkDisplacementMapEffect::kG_ChannelSelectorType>( 134 yChannelSelector, scale, dst, displ, offset, src, bounds); 135 break; 136 case SkDisplacementMapEffect::kB_ChannelSelectorType: 137 computeDisplacement<SkDisplacementMapEffect::kB_ChannelSelectorType>( 138 yChannelSelector, scale, dst, displ, offset, src, bounds); 139 break; 140 case SkDisplacementMapEffect::kA_ChannelSelectorType: 141 computeDisplacement<SkDisplacementMapEffect::kA_ChannelSelectorType>( 142 yChannelSelector, scale, dst, displ, offset, src, bounds); 143 break; 144 case SkDisplacementMapEffect::kUnknown_ChannelSelectorType: 145 default: 146 SkDEBUGFAIL("Unknown X channel selector"); 147 } 148 } 149 150 bool channel_selector_type_is_valid(SkDisplacementMapEffect::ChannelSelectorType cst) { 151 switch (cst) { 152 case SkDisplacementMapEffect::kUnknown_ChannelSelectorType: 153 case SkDisplacementMapEffect::kR_ChannelSelectorType: 154 case SkDisplacementMapEffect::kG_ChannelSelectorType: 155 case SkDisplacementMapEffect::kB_ChannelSelectorType: 156 case SkDisplacementMapEffect::kA_ChannelSelectorType: 157 return true; 158 default: 159 break; 160 } 161 return false; 162 } 163 164 } // end namespace 165 166 /////////////////////////////////////////////////////////////////////////////// 167 168 SkImageFilter* SkDisplacementMapEffect::Create(ChannelSelectorType xChannelSelector, 169 ChannelSelectorType yChannelSelector, 170 SkScalar scale, 171 SkImageFilter* displacement, 172 SkImageFilter* color, 173 const CropRect* cropRect) { 174 if (!channel_selector_type_is_valid(xChannelSelector) || 175 !channel_selector_type_is_valid(yChannelSelector)) { 176 return nullptr; 177 } 178 179 SkImageFilter* inputs[2] = { displacement, color }; 180 return new SkDisplacementMapEffect(xChannelSelector, yChannelSelector, scale, inputs, cropRect); 181 } 182 183 SkDisplacementMapEffect::SkDisplacementMapEffect(ChannelSelectorType xChannelSelector, 184 ChannelSelectorType yChannelSelector, 185 SkScalar scale, 186 SkImageFilter* inputs[2], 187 const CropRect* cropRect) 188 : INHERITED(2, inputs, cropRect) 189 , fXChannelSelector(xChannelSelector) 190 , fYChannelSelector(yChannelSelector) 191 , fScale(scale) 192 { 193 } 194 195 SkDisplacementMapEffect::~SkDisplacementMapEffect() { 196 } 197 198 SkFlattenable* SkDisplacementMapEffect::CreateProc(SkReadBuffer& buffer) { 199 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 2); 200 ChannelSelectorType xsel = (ChannelSelectorType)buffer.readInt(); 201 ChannelSelectorType ysel = (ChannelSelectorType)buffer.readInt(); 202 SkScalar scale = buffer.readScalar(); 203 return Create(xsel, ysel, scale, common.getInput(0), common.getInput(1), &common.cropRect()); 204 } 205 206 void SkDisplacementMapEffect::flatten(SkWriteBuffer& buffer) const { 207 this->INHERITED::flatten(buffer); 208 buffer.writeInt((int) fXChannelSelector); 209 buffer.writeInt((int) fYChannelSelector); 210 buffer.writeScalar(fScale); 211 } 212 213 bool SkDisplacementMapEffect::onFilterImageDeprecated(Proxy* proxy, 214 const SkBitmap& src, 215 const Context& ctx, 216 SkBitmap* dst, 217 SkIPoint* offset) const { 218 SkBitmap displ = src, color = src; 219 SkIPoint colorOffset = SkIPoint::Make(0, 0), displOffset = SkIPoint::Make(0, 0); 220 if (!this->filterInputDeprecated(1, proxy, src, ctx, &color, &colorOffset) || 221 !this->filterInputDeprecated(0, proxy, src, ctx, &displ, &displOffset)) { 222 return false; 223 } 224 if ((displ.colorType() != kN32_SkColorType) || 225 (color.colorType() != kN32_SkColorType)) { 226 return false; 227 } 228 SkIRect bounds; 229 // Since computeDisplacement does bounds checking on color pixel access, we don't need to pad 230 // the color bitmap to bounds here. 231 SkIRect srcBounds = color.bounds(); 232 srcBounds.offset(colorOffset); 233 if (!this->applyCropRect(ctx, srcBounds, &bounds)) { 234 return false; 235 } 236 SkIRect displBounds; 237 if (!this->applyCropRectDeprecated(ctx, proxy, displ, &displOffset, &displBounds, &displ)) { 238 return false; 239 } 240 if (!bounds.intersect(displBounds)) { 241 return false; 242 } 243 SkAutoLockPixels alp_displacement(displ), alp_color(color); 244 if (!displ.getPixels() || !color.getPixels()) { 245 return false; 246 } 247 248 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height())); 249 if (!device) { 250 return false; 251 } 252 *dst = device->accessBitmap(false); 253 SkAutoLockPixels alp_dst(*dst); 254 255 SkVector scale = SkVector::Make(fScale, fScale); 256 ctx.ctm().mapVectors(&scale, 1); 257 SkIRect colorBounds = bounds; 258 colorBounds.offset(-colorOffset); 259 260 computeDisplacement(fXChannelSelector, fYChannelSelector, scale, dst, 261 &displ, colorOffset - displOffset, &color, colorBounds); 262 263 offset->fX = bounds.left(); 264 offset->fY = bounds.top(); 265 return true; 266 } 267 268 void SkDisplacementMapEffect::computeFastBounds(const SkRect& src, SkRect* dst) const { 269 if (this->getColorInput()) { 270 this->getColorInput()->computeFastBounds(src, dst); 271 } else { 272 *dst = src; 273 } 274 dst->outset(SkScalarAbs(fScale) * SK_ScalarHalf, SkScalarAbs(fScale) * SK_ScalarHalf); 275 } 276 277 void SkDisplacementMapEffect::onFilterNodeBounds(const SkIRect& src, const SkMatrix& ctm, 278 SkIRect* dst, MapDirection) const { 279 *dst = src; 280 SkVector scale = SkVector::Make(fScale, fScale); 281 ctm.mapVectors(&scale, 1); 282 dst->outset(SkScalarCeilToInt(SkScalarAbs(scale.fX) * SK_ScalarHalf), 283 SkScalarCeilToInt(SkScalarAbs(scale.fY) * SK_ScalarHalf)); 284 } 285 286 bool SkDisplacementMapEffect::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, 287 SkIRect* dst, MapDirection direction) const { 288 // Recurse only into color input. 289 if (this->getColorInput()) { 290 return this->getColorInput()->filterBounds(src, ctm, dst, direction); 291 } 292 *dst = src; 293 return true; 294 } 295 296 #ifndef SK_IGNORE_TO_STRING 297 void SkDisplacementMapEffect::toString(SkString* str) const { 298 str->appendf("SkDisplacementMapEffect: ("); 299 str->appendf("scale: %f ", fScale); 300 str->appendf("displacement: ("); 301 if (this->getDisplacementInput()) { 302 this->getDisplacementInput()->toString(str); 303 } 304 str->appendf(") color: ("); 305 if (this->getColorInput()) { 306 this->getColorInput()->toString(str); 307 } 308 str->appendf("))"); 309 } 310 #endif 311 312 /////////////////////////////////////////////////////////////////////////////// 313 314 #if SK_SUPPORT_GPU 315 class GrGLDisplacementMapEffect : public GrGLSLFragmentProcessor { 316 public: 317 void emitCode(EmitArgs&) override; 318 319 static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*); 320 321 protected: 322 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override; 323 324 private: 325 GrGLSLProgramDataManager::UniformHandle fScaleUni; 326 GrTextureDomain::GLDomain fGLDomain; 327 328 typedef GrGLSLFragmentProcessor INHERITED; 329 }; 330 331 /////////////////////////////////////////////////////////////////////////////// 332 333 class GrDisplacementMapEffect : public GrFragmentProcessor { 334 public: 335 static GrFragmentProcessor* Create( 336 SkDisplacementMapEffect::ChannelSelectorType xChannelSelector, 337 SkDisplacementMapEffect::ChannelSelectorType yChannelSelector, SkVector scale, 338 GrTexture* displacement, const SkMatrix& offsetMatrix, GrTexture* color, 339 const SkISize& colorDimensions) { 340 return new GrDisplacementMapEffect(xChannelSelector, yChannelSelector, scale, displacement, 341 offsetMatrix, color, colorDimensions); 342 } 343 344 virtual ~GrDisplacementMapEffect(); 345 346 SkDisplacementMapEffect::ChannelSelectorType xChannelSelector() const 347 { return fXChannelSelector; } 348 SkDisplacementMapEffect::ChannelSelectorType yChannelSelector() const 349 { return fYChannelSelector; } 350 const SkVector& scale() const { return fScale; } 351 352 const char* name() const override { return "DisplacementMap"; } 353 const GrTextureDomain& domain() const { return fDomain; } 354 355 private: 356 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override { 357 return new GrGLDisplacementMapEffect; 358 } 359 360 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override { 361 GrGLDisplacementMapEffect::GenKey(*this, caps, b); 362 } 363 364 bool onIsEqual(const GrFragmentProcessor&) const override; 365 366 void onComputeInvariantOutput(GrInvariantOutput* inout) const override; 367 368 GrDisplacementMapEffect(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector, 369 SkDisplacementMapEffect::ChannelSelectorType yChannelSelector, 370 const SkVector& scale, 371 GrTexture* displacement, const SkMatrix& offsetMatrix, 372 GrTexture* color, 373 const SkISize& colorDimensions); 374 375 GR_DECLARE_FRAGMENT_PROCESSOR_TEST; 376 377 GrCoordTransform fDisplacementTransform; 378 GrTextureAccess fDisplacementAccess; 379 GrCoordTransform fColorTransform; 380 GrTextureDomain fDomain; 381 GrTextureAccess fColorAccess; 382 SkDisplacementMapEffect::ChannelSelectorType fXChannelSelector; 383 SkDisplacementMapEffect::ChannelSelectorType fYChannelSelector; 384 SkVector fScale; 385 386 typedef GrFragmentProcessor INHERITED; 387 }; 388 389 bool SkDisplacementMapEffect::filterImageGPUDeprecated(Proxy* proxy, const SkBitmap& src, 390 const Context& ctx, 391 SkBitmap* result, SkIPoint* offset) const { 392 SkBitmap colorBM = src; 393 SkIPoint colorOffset = SkIPoint::Make(0, 0); 394 if (!this->filterInputGPUDeprecated(1, proxy, src, ctx, &colorBM, &colorOffset)) { 395 return false; 396 } 397 SkBitmap displacementBM = src; 398 SkIPoint displacementOffset = SkIPoint::Make(0, 0); 399 if (!this->filterInputGPUDeprecated(0, proxy, src, ctx, &displacementBM, &displacementOffset)) { 400 return false; 401 } 402 SkIRect srcBounds = colorBM.bounds(); 403 srcBounds.offset(colorOffset); 404 SkIRect bounds; 405 // Since GrDisplacementMapEffect does bounds checking on color pixel access, we don't need to 406 // pad the color bitmap to bounds here. 407 if (!this->applyCropRect(ctx, srcBounds, &bounds)) { 408 return false; 409 } 410 SkIRect displBounds; 411 if (!this->applyCropRectDeprecated(ctx, proxy, displacementBM, 412 &displacementOffset, &displBounds, &displacementBM)) { 413 return false; 414 } 415 if (!bounds.intersect(displBounds)) { 416 return false; 417 } 418 GrTexture* color = colorBM.getTexture(); 419 GrTexture* displacement = displacementBM.getTexture(); 420 GrContext* context = color->getContext(); 421 422 GrSurfaceDesc desc; 423 desc.fFlags = kRenderTarget_GrSurfaceFlag; 424 desc.fWidth = bounds.width(); 425 desc.fHeight = bounds.height(); 426 desc.fConfig = kSkia8888_GrPixelConfig; 427 428 SkAutoTUnref<GrTexture> dst(context->textureProvider()->createApproxTexture(desc)); 429 430 if (!dst) { 431 return false; 432 } 433 434 SkVector scale = SkVector::Make(fScale, fScale); 435 ctx.ctm().mapVectors(&scale, 1); 436 437 GrPaint paint; 438 SkMatrix offsetMatrix = GrCoordTransform::MakeDivByTextureWHMatrix(displacement); 439 offsetMatrix.preTranslate(SkIntToScalar(colorOffset.fX - displacementOffset.fX), 440 SkIntToScalar(colorOffset.fY - displacementOffset.fY)); 441 442 paint.addColorFragmentProcessor( 443 GrDisplacementMapEffect::Create(fXChannelSelector, 444 fYChannelSelector, 445 scale, 446 displacement, 447 offsetMatrix, 448 color, 449 colorBM.dimensions()))->unref(); 450 paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode); 451 SkIRect colorBounds = bounds; 452 colorBounds.offset(-colorOffset); 453 SkMatrix matrix; 454 matrix.setTranslate(-SkIntToScalar(colorBounds.x()), 455 -SkIntToScalar(colorBounds.y())); 456 457 SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(dst->asRenderTarget())); 458 if (!drawContext) { 459 return false; 460 } 461 462 drawContext->drawRect(GrClip::WideOpen(), paint, matrix, SkRect::Make(colorBounds)); 463 offset->fX = bounds.left(); 464 offset->fY = bounds.top(); 465 GrWrapTextureInBitmap(dst, bounds.width(), bounds.height(), false, result); 466 return true; 467 } 468 469 /////////////////////////////////////////////////////////////////////////////// 470 471 GrDisplacementMapEffect::GrDisplacementMapEffect( 472 SkDisplacementMapEffect::ChannelSelectorType xChannelSelector, 473 SkDisplacementMapEffect::ChannelSelectorType yChannelSelector, 474 const SkVector& scale, 475 GrTexture* displacement, 476 const SkMatrix& offsetMatrix, 477 GrTexture* color, 478 const SkISize& colorDimensions) 479 : fDisplacementTransform(kLocal_GrCoordSet, offsetMatrix, displacement, 480 GrTextureParams::kNone_FilterMode) 481 , fDisplacementAccess(displacement) 482 , fColorTransform(kLocal_GrCoordSet, color, GrTextureParams::kNone_FilterMode) 483 , fDomain(GrTextureDomain::MakeTexelDomain(color, SkIRect::MakeSize(colorDimensions)), 484 GrTextureDomain::kDecal_Mode) 485 , fColorAccess(color) 486 , fXChannelSelector(xChannelSelector) 487 , fYChannelSelector(yChannelSelector) 488 , fScale(scale) { 489 this->initClassID<GrDisplacementMapEffect>(); 490 this->addCoordTransform(&fDisplacementTransform); 491 this->addTextureAccess(&fDisplacementAccess); 492 this->addCoordTransform(&fColorTransform); 493 this->addTextureAccess(&fColorAccess); 494 } 495 496 GrDisplacementMapEffect::~GrDisplacementMapEffect() { 497 } 498 499 bool GrDisplacementMapEffect::onIsEqual(const GrFragmentProcessor& sBase) const { 500 const GrDisplacementMapEffect& s = sBase.cast<GrDisplacementMapEffect>(); 501 return fXChannelSelector == s.fXChannelSelector && 502 fYChannelSelector == s.fYChannelSelector && 503 fScale == s.fScale; 504 } 505 506 void GrDisplacementMapEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const { 507 // Any displacement offset bringing a pixel out of bounds will output a color of (0,0,0,0), 508 // so the only way we'd get a constant alpha is if the input color image has a constant alpha 509 // and no displacement offset push any texture coordinates out of bounds OR if the constant 510 // alpha is 0. Since this isn't trivial to compute at this point, let's assume the output is 511 // not of constant color when a displacement effect is applied. 512 inout->setToUnknown(GrInvariantOutput::kWillNot_ReadInput); 513 } 514 515 /////////////////////////////////////////////////////////////////////////////// 516 517 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDisplacementMapEffect); 518 519 const GrFragmentProcessor* GrDisplacementMapEffect::TestCreate(GrProcessorTestData* d) { 520 int texIdxDispl = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx : 521 GrProcessorUnitTest::kAlphaTextureIdx; 522 int texIdxColor = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx : 523 GrProcessorUnitTest::kAlphaTextureIdx; 524 static const int kMaxComponent = 4; 525 SkDisplacementMapEffect::ChannelSelectorType xChannelSelector = 526 static_cast<SkDisplacementMapEffect::ChannelSelectorType>( 527 d->fRandom->nextRangeU(1, kMaxComponent)); 528 SkDisplacementMapEffect::ChannelSelectorType yChannelSelector = 529 static_cast<SkDisplacementMapEffect::ChannelSelectorType>( 530 d->fRandom->nextRangeU(1, kMaxComponent)); 531 SkVector scale = SkVector::Make(d->fRandom->nextRangeScalar(0, 100.0f), 532 d->fRandom->nextRangeScalar(0, 100.0f)); 533 SkISize colorDimensions; 534 colorDimensions.fWidth = d->fRandom->nextRangeU(0, d->fTextures[texIdxColor]->width()); 535 colorDimensions.fHeight = d->fRandom->nextRangeU(0, d->fTextures[texIdxColor]->height()); 536 return GrDisplacementMapEffect::Create(xChannelSelector, yChannelSelector, scale, 537 d->fTextures[texIdxDispl], SkMatrix::I(), 538 d->fTextures[texIdxColor], colorDimensions); 539 } 540 541 /////////////////////////////////////////////////////////////////////////////// 542 543 void GrGLDisplacementMapEffect::emitCode(EmitArgs& args) { 544 const GrDisplacementMapEffect& displacementMap = args.fFp.cast<GrDisplacementMapEffect>(); 545 const GrTextureDomain& domain = displacementMap.domain(); 546 547 fScaleUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag, 548 kVec2f_GrSLType, kDefault_GrSLPrecision, "Scale"); 549 const char* scaleUni = args.fUniformHandler->getUniformCStr(fScaleUni); 550 const char* dColor = "dColor"; 551 const char* cCoords = "cCoords"; 552 const char* nearZero = "1e-6"; // Since 6.10352e5 is the smallest half float, use 553 // a number smaller than that to approximate 0, but 554 // leave room for 32-bit float GPU rounding errors. 555 556 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; 557 fragBuilder->codeAppendf("\t\tvec4 %s = ", dColor); 558 fragBuilder->appendTextureLookup(args.fSamplers[0], args.fCoords[0].c_str(), 559 args.fCoords[0].getType()); 560 fragBuilder->codeAppend(";\n"); 561 562 // Unpremultiply the displacement 563 fragBuilder->codeAppendf( 564 "\t\t%s.rgb = (%s.a < %s) ? vec3(0.0) : clamp(%s.rgb / %s.a, 0.0, 1.0);", 565 dColor, dColor, nearZero, dColor, dColor); 566 SkString coords2D = fragBuilder->ensureFSCoords2D(args.fCoords, 1); 567 fragBuilder->codeAppendf("\t\tvec2 %s = %s + %s*(%s.", 568 cCoords, coords2D.c_str(), scaleUni, dColor); 569 570 switch (displacementMap.xChannelSelector()) { 571 case SkDisplacementMapEffect::kR_ChannelSelectorType: 572 fragBuilder->codeAppend("r"); 573 break; 574 case SkDisplacementMapEffect::kG_ChannelSelectorType: 575 fragBuilder->codeAppend("g"); 576 break; 577 case SkDisplacementMapEffect::kB_ChannelSelectorType: 578 fragBuilder->codeAppend("b"); 579 break; 580 case SkDisplacementMapEffect::kA_ChannelSelectorType: 581 fragBuilder->codeAppend("a"); 582 break; 583 case SkDisplacementMapEffect::kUnknown_ChannelSelectorType: 584 default: 585 SkDEBUGFAIL("Unknown X channel selector"); 586 } 587 588 switch (displacementMap.yChannelSelector()) { 589 case SkDisplacementMapEffect::kR_ChannelSelectorType: 590 fragBuilder->codeAppend("r"); 591 break; 592 case SkDisplacementMapEffect::kG_ChannelSelectorType: 593 fragBuilder->codeAppend("g"); 594 break; 595 case SkDisplacementMapEffect::kB_ChannelSelectorType: 596 fragBuilder->codeAppend("b"); 597 break; 598 case SkDisplacementMapEffect::kA_ChannelSelectorType: 599 fragBuilder->codeAppend("a"); 600 break; 601 case SkDisplacementMapEffect::kUnknown_ChannelSelectorType: 602 default: 603 SkDEBUGFAIL("Unknown Y channel selector"); 604 } 605 fragBuilder->codeAppend("-vec2(0.5));\t\t"); 606 607 fGLDomain.sampleTexture(fragBuilder, 608 args.fUniformHandler, 609 args.fGLSLCaps, 610 domain, 611 args.fOutputColor, 612 SkString(cCoords), 613 args.fSamplers[1]); 614 fragBuilder->codeAppend(";\n"); 615 } 616 617 void GrGLDisplacementMapEffect::onSetData(const GrGLSLProgramDataManager& pdman, 618 const GrProcessor& proc) { 619 const GrDisplacementMapEffect& displacementMap = proc.cast<GrDisplacementMapEffect>(); 620 GrTexture* colorTex = displacementMap.texture(1); 621 SkScalar scaleX = displacementMap.scale().fX / colorTex->width(); 622 SkScalar scaleY = displacementMap.scale().fY / colorTex->height(); 623 pdman.set2f(fScaleUni, SkScalarToFloat(scaleX), 624 colorTex->origin() == kTopLeft_GrSurfaceOrigin ? 625 SkScalarToFloat(scaleY) : SkScalarToFloat(-scaleY)); 626 fGLDomain.setData(pdman, displacementMap.domain(), colorTex->origin()); 627 } 628 629 void GrGLDisplacementMapEffect::GenKey(const GrProcessor& proc, 630 const GrGLSLCaps&, GrProcessorKeyBuilder* b) { 631 const GrDisplacementMapEffect& displacementMap = proc.cast<GrDisplacementMapEffect>(); 632 633 uint32_t xKey = displacementMap.xChannelSelector(); 634 uint32_t yKey = displacementMap.yChannelSelector() << kChannelSelectorKeyBits; 635 636 b->add32(xKey | yKey); 637 } 638 #endif 639 640