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