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