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