1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/effects/SkDisplacementMapEffect.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,611 @@ 1.4 +/* 1.5 + * Copyright 2013 Google Inc. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 + 1.11 +#include "SkDisplacementMapEffect.h" 1.12 +#include "SkReadBuffer.h" 1.13 +#include "SkWriteBuffer.h" 1.14 +#include "SkUnPreMultiply.h" 1.15 +#include "SkColorPriv.h" 1.16 +#if SK_SUPPORT_GPU 1.17 +#include "GrContext.h" 1.18 +#include "GrCoordTransform.h" 1.19 +#include "gl/GrGLEffect.h" 1.20 +#include "GrTBackendEffectFactory.h" 1.21 +#endif 1.22 + 1.23 +namespace { 1.24 + 1.25 +#define kChannelSelectorKeyBits 3; // Max value is 4, so 3 bits are required at most 1.26 + 1.27 +template<SkDisplacementMapEffect::ChannelSelectorType type> 1.28 +uint32_t getValue(SkColor, const SkUnPreMultiply::Scale*) { 1.29 + SkDEBUGFAIL("Unknown channel selector"); 1.30 + return 0; 1.31 +} 1.32 + 1.33 +template<> uint32_t getValue<SkDisplacementMapEffect::kR_ChannelSelectorType>( 1.34 + SkColor l, const SkUnPreMultiply::Scale* table) { 1.35 + return SkUnPreMultiply::ApplyScale(table[SkGetPackedA32(l)], SkGetPackedR32(l)); 1.36 +} 1.37 + 1.38 +template<> uint32_t getValue<SkDisplacementMapEffect::kG_ChannelSelectorType>( 1.39 + SkColor l, const SkUnPreMultiply::Scale* table) { 1.40 + return SkUnPreMultiply::ApplyScale(table[SkGetPackedA32(l)], SkGetPackedG32(l)); 1.41 +} 1.42 + 1.43 +template<> uint32_t getValue<SkDisplacementMapEffect::kB_ChannelSelectorType>( 1.44 + SkColor l, const SkUnPreMultiply::Scale* table) { 1.45 + return SkUnPreMultiply::ApplyScale(table[SkGetPackedA32(l)], SkGetPackedB32(l)); 1.46 +} 1.47 + 1.48 +template<> uint32_t getValue<SkDisplacementMapEffect::kA_ChannelSelectorType>( 1.49 + SkColor l, const SkUnPreMultiply::Scale*) { 1.50 + return SkGetPackedA32(l); 1.51 +} 1.52 + 1.53 +template<SkDisplacementMapEffect::ChannelSelectorType typeX, 1.54 + SkDisplacementMapEffect::ChannelSelectorType typeY> 1.55 +void computeDisplacement(const SkVector& scale, SkBitmap* dst, 1.56 + SkBitmap* displ, const SkIPoint& offset, 1.57 + SkBitmap* src, 1.58 + const SkIRect& bounds) 1.59 +{ 1.60 + static const SkScalar Inv8bit = SkScalarDiv(SK_Scalar1, 255.0f); 1.61 + const int srcW = src->width(); 1.62 + const int srcH = src->height(); 1.63 + const SkVector scaleForColor = SkVector::Make(SkScalarMul(scale.fX, Inv8bit), 1.64 + SkScalarMul(scale.fY, Inv8bit)); 1.65 + const SkVector scaleAdj = SkVector::Make(SK_ScalarHalf - SkScalarMul(scale.fX, SK_ScalarHalf), 1.66 + SK_ScalarHalf - SkScalarMul(scale.fY, SK_ScalarHalf)); 1.67 + const SkUnPreMultiply::Scale* table = SkUnPreMultiply::GetScaleTable(); 1.68 + SkPMColor* dstPtr = dst->getAddr32(0, 0); 1.69 + for (int y = bounds.top(); y < bounds.bottom(); ++y) { 1.70 + const SkPMColor* displPtr = displ->getAddr32(bounds.left() + offset.fX, 1.71 + y + offset.fY); 1.72 + for (int x = bounds.left(); x < bounds.right(); ++x, ++displPtr) { 1.73 + const SkScalar displX = SkScalarMul(scaleForColor.fX, 1.74 + SkIntToScalar(getValue<typeX>(*displPtr, table))) + scaleAdj.fX; 1.75 + const SkScalar displY = SkScalarMul(scaleForColor.fY, 1.76 + SkIntToScalar(getValue<typeY>(*displPtr, table))) + scaleAdj.fY; 1.77 + // Truncate the displacement values 1.78 + const int srcX = x + SkScalarTruncToInt(displX); 1.79 + const int srcY = y + SkScalarTruncToInt(displY); 1.80 + *dstPtr++ = ((srcX < 0) || (srcX >= srcW) || (srcY < 0) || (srcY >= srcH)) ? 1.81 + 0 : *(src->getAddr32(srcX, srcY)); 1.82 + } 1.83 + } 1.84 +} 1.85 + 1.86 +template<SkDisplacementMapEffect::ChannelSelectorType typeX> 1.87 +void computeDisplacement(SkDisplacementMapEffect::ChannelSelectorType yChannelSelector, 1.88 + const SkVector& scale, SkBitmap* dst, 1.89 + SkBitmap* displ, const SkIPoint& offset, 1.90 + SkBitmap* src, 1.91 + const SkIRect& bounds) 1.92 +{ 1.93 + switch (yChannelSelector) { 1.94 + case SkDisplacementMapEffect::kR_ChannelSelectorType: 1.95 + computeDisplacement<typeX, SkDisplacementMapEffect::kR_ChannelSelectorType>( 1.96 + scale, dst, displ, offset, src, bounds); 1.97 + break; 1.98 + case SkDisplacementMapEffect::kG_ChannelSelectorType: 1.99 + computeDisplacement<typeX, SkDisplacementMapEffect::kG_ChannelSelectorType>( 1.100 + scale, dst, displ, offset, src, bounds); 1.101 + break; 1.102 + case SkDisplacementMapEffect::kB_ChannelSelectorType: 1.103 + computeDisplacement<typeX, SkDisplacementMapEffect::kB_ChannelSelectorType>( 1.104 + scale, dst, displ, offset, src, bounds); 1.105 + break; 1.106 + case SkDisplacementMapEffect::kA_ChannelSelectorType: 1.107 + computeDisplacement<typeX, SkDisplacementMapEffect::kA_ChannelSelectorType>( 1.108 + scale, dst, displ, offset, src, bounds); 1.109 + break; 1.110 + case SkDisplacementMapEffect::kUnknown_ChannelSelectorType: 1.111 + default: 1.112 + SkDEBUGFAIL("Unknown Y channel selector"); 1.113 + } 1.114 +} 1.115 + 1.116 +void computeDisplacement(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector, 1.117 + SkDisplacementMapEffect::ChannelSelectorType yChannelSelector, 1.118 + const SkVector& scale, SkBitmap* dst, 1.119 + SkBitmap* displ, const SkIPoint& offset, 1.120 + SkBitmap* src, 1.121 + const SkIRect& bounds) 1.122 +{ 1.123 + switch (xChannelSelector) { 1.124 + case SkDisplacementMapEffect::kR_ChannelSelectorType: 1.125 + computeDisplacement<SkDisplacementMapEffect::kR_ChannelSelectorType>( 1.126 + yChannelSelector, scale, dst, displ, offset, src, bounds); 1.127 + break; 1.128 + case SkDisplacementMapEffect::kG_ChannelSelectorType: 1.129 + computeDisplacement<SkDisplacementMapEffect::kG_ChannelSelectorType>( 1.130 + yChannelSelector, scale, dst, displ, offset, src, bounds); 1.131 + break; 1.132 + case SkDisplacementMapEffect::kB_ChannelSelectorType: 1.133 + computeDisplacement<SkDisplacementMapEffect::kB_ChannelSelectorType>( 1.134 + yChannelSelector, scale, dst, displ, offset, src, bounds); 1.135 + break; 1.136 + case SkDisplacementMapEffect::kA_ChannelSelectorType: 1.137 + computeDisplacement<SkDisplacementMapEffect::kA_ChannelSelectorType>( 1.138 + yChannelSelector, scale, dst, displ, offset, src, bounds); 1.139 + break; 1.140 + case SkDisplacementMapEffect::kUnknown_ChannelSelectorType: 1.141 + default: 1.142 + SkDEBUGFAIL("Unknown X channel selector"); 1.143 + } 1.144 +} 1.145 + 1.146 +bool channel_selector_type_is_valid(SkDisplacementMapEffect::ChannelSelectorType cst) { 1.147 + switch (cst) { 1.148 + case SkDisplacementMapEffect::kUnknown_ChannelSelectorType: 1.149 + case SkDisplacementMapEffect::kR_ChannelSelectorType: 1.150 + case SkDisplacementMapEffect::kG_ChannelSelectorType: 1.151 + case SkDisplacementMapEffect::kB_ChannelSelectorType: 1.152 + case SkDisplacementMapEffect::kA_ChannelSelectorType: 1.153 + return true; 1.154 + default: 1.155 + break; 1.156 + } 1.157 + return false; 1.158 +} 1.159 + 1.160 +} // end namespace 1.161 + 1.162 +/////////////////////////////////////////////////////////////////////////////// 1.163 + 1.164 +SkDisplacementMapEffect::SkDisplacementMapEffect(ChannelSelectorType xChannelSelector, 1.165 + ChannelSelectorType yChannelSelector, 1.166 + SkScalar scale, 1.167 + SkImageFilter* displacement, 1.168 + SkImageFilter* color, 1.169 + const CropRect* cropRect) 1.170 + : INHERITED(displacement, color, cropRect) 1.171 + , fXChannelSelector(xChannelSelector) 1.172 + , fYChannelSelector(yChannelSelector) 1.173 + , fScale(scale) 1.174 +{ 1.175 +} 1.176 + 1.177 +SkDisplacementMapEffect::~SkDisplacementMapEffect() { 1.178 +} 1.179 + 1.180 +SkDisplacementMapEffect::SkDisplacementMapEffect(SkReadBuffer& buffer) 1.181 + : INHERITED(2, buffer) 1.182 +{ 1.183 + fXChannelSelector = (SkDisplacementMapEffect::ChannelSelectorType) buffer.readInt(); 1.184 + fYChannelSelector = (SkDisplacementMapEffect::ChannelSelectorType) buffer.readInt(); 1.185 + fScale = buffer.readScalar(); 1.186 + buffer.validate(channel_selector_type_is_valid(fXChannelSelector) && 1.187 + channel_selector_type_is_valid(fYChannelSelector) && 1.188 + SkScalarIsFinite(fScale)); 1.189 +} 1.190 + 1.191 +void SkDisplacementMapEffect::flatten(SkWriteBuffer& buffer) const { 1.192 + this->INHERITED::flatten(buffer); 1.193 + buffer.writeInt((int) fXChannelSelector); 1.194 + buffer.writeInt((int) fYChannelSelector); 1.195 + buffer.writeScalar(fScale); 1.196 +} 1.197 + 1.198 +bool SkDisplacementMapEffect::onFilterImage(Proxy* proxy, 1.199 + const SkBitmap& src, 1.200 + const Context& ctx, 1.201 + SkBitmap* dst, 1.202 + SkIPoint* offset) const { 1.203 + SkBitmap displ = src, color = src; 1.204 + const SkImageFilter* colorInput = getColorInput(); 1.205 + const SkImageFilter* displInput = getDisplacementInput(); 1.206 + SkIPoint colorOffset = SkIPoint::Make(0, 0), displOffset = SkIPoint::Make(0, 0); 1.207 + if ((colorInput && !colorInput->filterImage(proxy, src, ctx, &color, &colorOffset)) || 1.208 + (displInput && !displInput->filterImage(proxy, src, ctx, &displ, &displOffset))) { 1.209 + return false; 1.210 + } 1.211 + if ((displ.colorType() != kPMColor_SkColorType) || 1.212 + (color.colorType() != kPMColor_SkColorType)) { 1.213 + return false; 1.214 + } 1.215 + SkIRect bounds; 1.216 + // Since computeDisplacement does bounds checking on color pixel access, we don't need to pad 1.217 + // the color bitmap to bounds here. 1.218 + if (!this->applyCropRect(ctx, color, colorOffset, &bounds)) { 1.219 + return false; 1.220 + } 1.221 + SkIRect displBounds; 1.222 + if (!this->applyCropRect(ctx, proxy, displ, &displOffset, &displBounds, &displ)) { 1.223 + return false; 1.224 + } 1.225 + if (!bounds.intersect(displBounds)) { 1.226 + return false; 1.227 + } 1.228 + SkAutoLockPixels alp_displacement(displ), alp_color(color); 1.229 + if (!displ.getPixels() || !color.getPixels()) { 1.230 + return false; 1.231 + } 1.232 + 1.233 + dst->setConfig(color.config(), bounds.width(), bounds.height()); 1.234 + if (!dst->allocPixels()) { 1.235 + return false; 1.236 + } 1.237 + 1.238 + SkVector scale = SkVector::Make(fScale, fScale); 1.239 + ctx.ctm().mapVectors(&scale, 1); 1.240 + SkIRect colorBounds = bounds; 1.241 + colorBounds.offset(-colorOffset); 1.242 + 1.243 + computeDisplacement(fXChannelSelector, fYChannelSelector, scale, dst, 1.244 + &displ, colorOffset - displOffset, &color, colorBounds); 1.245 + 1.246 + offset->fX = bounds.left(); 1.247 + offset->fY = bounds.top(); 1.248 + return true; 1.249 +} 1.250 + 1.251 +void SkDisplacementMapEffect::computeFastBounds(const SkRect& src, SkRect* dst) const { 1.252 + if (getColorInput()) { 1.253 + getColorInput()->computeFastBounds(src, dst); 1.254 + } else { 1.255 + *dst = src; 1.256 + } 1.257 + dst->outset(fScale * SK_ScalarHalf, fScale * SK_ScalarHalf); 1.258 +} 1.259 + 1.260 +bool SkDisplacementMapEffect::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, 1.261 + SkIRect* dst) const { 1.262 + SkIRect bounds = src; 1.263 + if (getColorInput() && !getColorInput()->filterBounds(src, ctm, &bounds)) { 1.264 + return false; 1.265 + } 1.266 + bounds.outset(SkScalarCeilToInt(fScale * SK_ScalarHalf), 1.267 + SkScalarCeilToInt(fScale * SK_ScalarHalf)); 1.268 + *dst = bounds; 1.269 + return true; 1.270 +} 1.271 + 1.272 +/////////////////////////////////////////////////////////////////////////////// 1.273 + 1.274 +#if SK_SUPPORT_GPU 1.275 +class GrGLDisplacementMapEffect : public GrGLEffect { 1.276 +public: 1.277 + GrGLDisplacementMapEffect(const GrBackendEffectFactory& factory, 1.278 + const GrDrawEffect& drawEffect); 1.279 + virtual ~GrGLDisplacementMapEffect(); 1.280 + 1.281 + virtual void emitCode(GrGLShaderBuilder*, 1.282 + const GrDrawEffect&, 1.283 + EffectKey, 1.284 + const char* outputColor, 1.285 + const char* inputColor, 1.286 + const TransformedCoordsArray&, 1.287 + const TextureSamplerArray&) SK_OVERRIDE; 1.288 + 1.289 + static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&); 1.290 + 1.291 + virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE; 1.292 + 1.293 +private: 1.294 + SkDisplacementMapEffect::ChannelSelectorType fXChannelSelector; 1.295 + SkDisplacementMapEffect::ChannelSelectorType fYChannelSelector; 1.296 + GrGLUniformManager::UniformHandle fScaleUni; 1.297 + 1.298 + typedef GrGLEffect INHERITED; 1.299 +}; 1.300 + 1.301 +/////////////////////////////////////////////////////////////////////////////// 1.302 + 1.303 +class GrDisplacementMapEffect : public GrEffect { 1.304 +public: 1.305 + static GrEffectRef* Create(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector, 1.306 + SkDisplacementMapEffect::ChannelSelectorType yChannelSelector, 1.307 + SkVector scale, 1.308 + GrTexture* displacement, const SkMatrix& offsetMatrix, 1.309 + GrTexture* color) { 1.310 + AutoEffectUnref effect(SkNEW_ARGS(GrDisplacementMapEffect, (xChannelSelector, 1.311 + yChannelSelector, 1.312 + scale, 1.313 + displacement, 1.314 + offsetMatrix, 1.315 + color))); 1.316 + return CreateEffectRef(effect); 1.317 + } 1.318 + 1.319 + virtual ~GrDisplacementMapEffect(); 1.320 + 1.321 + virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE; 1.322 + SkDisplacementMapEffect::ChannelSelectorType xChannelSelector() const 1.323 + { return fXChannelSelector; } 1.324 + SkDisplacementMapEffect::ChannelSelectorType yChannelSelector() const 1.325 + { return fYChannelSelector; } 1.326 + const SkVector& scale() const { return fScale; } 1.327 + 1.328 + typedef GrGLDisplacementMapEffect GLEffect; 1.329 + static const char* Name() { return "DisplacementMap"; } 1.330 + 1.331 + virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE; 1.332 + 1.333 +private: 1.334 + virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE; 1.335 + 1.336 + GrDisplacementMapEffect(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector, 1.337 + SkDisplacementMapEffect::ChannelSelectorType yChannelSelector, 1.338 + const SkVector& scale, 1.339 + GrTexture* displacement, const SkMatrix& offsetMatrix, 1.340 + GrTexture* color); 1.341 + 1.342 + GR_DECLARE_EFFECT_TEST; 1.343 + 1.344 + GrCoordTransform fDisplacementTransform; 1.345 + GrTextureAccess fDisplacementAccess; 1.346 + GrCoordTransform fColorTransform; 1.347 + GrTextureAccess fColorAccess; 1.348 + SkDisplacementMapEffect::ChannelSelectorType fXChannelSelector; 1.349 + SkDisplacementMapEffect::ChannelSelectorType fYChannelSelector; 1.350 + SkVector fScale; 1.351 + 1.352 + typedef GrEffect INHERITED; 1.353 +}; 1.354 + 1.355 +bool SkDisplacementMapEffect::filterImageGPU(Proxy* proxy, const SkBitmap& src, const Context& ctx, 1.356 + SkBitmap* result, SkIPoint* offset) const { 1.357 + SkBitmap colorBM = src; 1.358 + SkIPoint colorOffset = SkIPoint::Make(0, 0); 1.359 + if (getColorInput() && !getColorInput()->getInputResultGPU(proxy, src, ctx, &colorBM, 1.360 + &colorOffset)) { 1.361 + return false; 1.362 + } 1.363 + SkBitmap displacementBM = src; 1.364 + SkIPoint displacementOffset = SkIPoint::Make(0, 0); 1.365 + if (getDisplacementInput() && 1.366 + !getDisplacementInput()->getInputResultGPU(proxy, src, ctx, &displacementBM, 1.367 + &displacementOffset)) { 1.368 + return false; 1.369 + } 1.370 + SkIRect bounds; 1.371 + // Since GrDisplacementMapEffect does bounds checking on color pixel access, we don't need to 1.372 + // pad the color bitmap to bounds here. 1.373 + if (!this->applyCropRect(ctx, colorBM, colorOffset, &bounds)) { 1.374 + return false; 1.375 + } 1.376 + SkIRect displBounds; 1.377 + if (!this->applyCropRect(ctx, proxy, displacementBM, 1.378 + &displacementOffset, &displBounds, &displacementBM)) { 1.379 + return false; 1.380 + } 1.381 + if (!bounds.intersect(displBounds)) { 1.382 + return false; 1.383 + } 1.384 + GrTexture* color = colorBM.getTexture(); 1.385 + GrTexture* displacement = displacementBM.getTexture(); 1.386 + GrContext* context = color->getContext(); 1.387 + 1.388 + GrTextureDesc desc; 1.389 + desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit; 1.390 + desc.fWidth = colorBM.width(); 1.391 + desc.fHeight = colorBM.height(); 1.392 + desc.fConfig = kSkia8888_GrPixelConfig; 1.393 + 1.394 + GrAutoScratchTexture ast(context, desc); 1.395 + SkAutoTUnref<GrTexture> dst(ast.detach()); 1.396 + 1.397 + GrContext::AutoRenderTarget art(context, dst->asRenderTarget()); 1.398 + 1.399 + SkVector scale = SkVector::Make(fScale, fScale); 1.400 + ctx.ctm().mapVectors(&scale, 1); 1.401 + 1.402 + GrPaint paint; 1.403 + SkMatrix offsetMatrix = GrEffect::MakeDivByTextureWHMatrix(displacement); 1.404 + offsetMatrix.preTranslate(SkIntToScalar(colorOffset.fX - displacementOffset.fX), 1.405 + SkIntToScalar(colorOffset.fY - displacementOffset.fY)); 1.406 + 1.407 + paint.addColorEffect( 1.408 + GrDisplacementMapEffect::Create(fXChannelSelector, 1.409 + fYChannelSelector, 1.410 + scale, 1.411 + displacement, 1.412 + offsetMatrix, 1.413 + color))->unref(); 1.414 + SkIRect colorBounds = bounds; 1.415 + colorBounds.offset(-colorOffset); 1.416 + SkMatrix matrix; 1.417 + matrix.setTranslate(-SkIntToScalar(colorBounds.x()), 1.418 + -SkIntToScalar(colorBounds.y())); 1.419 + context->concatMatrix(matrix); 1.420 + context->drawRect(paint, SkRect::Make(colorBounds)); 1.421 + offset->fX = bounds.left(); 1.422 + offset->fY = bounds.top(); 1.423 + WrapTexture(dst, bounds.width(), bounds.height(), result); 1.424 + return true; 1.425 +} 1.426 + 1.427 +/////////////////////////////////////////////////////////////////////////////// 1.428 + 1.429 +GrDisplacementMapEffect::GrDisplacementMapEffect( 1.430 + SkDisplacementMapEffect::ChannelSelectorType xChannelSelector, 1.431 + SkDisplacementMapEffect::ChannelSelectorType yChannelSelector, 1.432 + const SkVector& scale, 1.433 + GrTexture* displacement, 1.434 + const SkMatrix& offsetMatrix, 1.435 + GrTexture* color) 1.436 + : fDisplacementTransform(kLocal_GrCoordSet, offsetMatrix, displacement) 1.437 + , fDisplacementAccess(displacement) 1.438 + , fColorTransform(kLocal_GrCoordSet, color) 1.439 + , fColorAccess(color) 1.440 + , fXChannelSelector(xChannelSelector) 1.441 + , fYChannelSelector(yChannelSelector) 1.442 + , fScale(scale) { 1.443 + this->addCoordTransform(&fDisplacementTransform); 1.444 + this->addTextureAccess(&fDisplacementAccess); 1.445 + this->addCoordTransform(&fColorTransform); 1.446 + this->addTextureAccess(&fColorAccess); 1.447 + this->setWillNotUseInputColor(); 1.448 +} 1.449 + 1.450 +GrDisplacementMapEffect::~GrDisplacementMapEffect() { 1.451 +} 1.452 + 1.453 +bool GrDisplacementMapEffect::onIsEqual(const GrEffect& sBase) const { 1.454 + const GrDisplacementMapEffect& s = CastEffect<GrDisplacementMapEffect>(sBase); 1.455 + return fDisplacementAccess.getTexture() == s.fDisplacementAccess.getTexture() && 1.456 + fColorAccess.getTexture() == s.fColorAccess.getTexture() && 1.457 + fXChannelSelector == s.fXChannelSelector && 1.458 + fYChannelSelector == s.fYChannelSelector && 1.459 + fScale == s.fScale; 1.460 +} 1.461 + 1.462 +const GrBackendEffectFactory& GrDisplacementMapEffect::getFactory() const { 1.463 + return GrTBackendEffectFactory<GrDisplacementMapEffect>::getInstance(); 1.464 +} 1.465 + 1.466 +void GrDisplacementMapEffect::getConstantColorComponents(GrColor*, 1.467 + uint32_t* validFlags) const { 1.468 + // Any displacement offset bringing a pixel out of bounds will output a color of (0,0,0,0), 1.469 + // so the only way we'd get a constant alpha is if the input color image has a constant alpha 1.470 + // and no displacement offset push any texture coordinates out of bounds OR if the constant 1.471 + // alpha is 0. Since this isn't trivial to compute at this point, let's assume the output is 1.472 + // not of constant color when a displacement effect is applied. 1.473 + *validFlags = 0; 1.474 +} 1.475 + 1.476 +/////////////////////////////////////////////////////////////////////////////// 1.477 + 1.478 +GR_DEFINE_EFFECT_TEST(GrDisplacementMapEffect); 1.479 + 1.480 +GrEffectRef* GrDisplacementMapEffect::TestCreate(SkRandom* random, 1.481 + GrContext*, 1.482 + const GrDrawTargetCaps&, 1.483 + GrTexture* textures[]) { 1.484 + int texIdxDispl = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx : 1.485 + GrEffectUnitTest::kAlphaTextureIdx; 1.486 + int texIdxColor = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx : 1.487 + GrEffectUnitTest::kAlphaTextureIdx; 1.488 + static const int kMaxComponent = 4; 1.489 + SkDisplacementMapEffect::ChannelSelectorType xChannelSelector = 1.490 + static_cast<SkDisplacementMapEffect::ChannelSelectorType>( 1.491 + random->nextRangeU(1, kMaxComponent)); 1.492 + SkDisplacementMapEffect::ChannelSelectorType yChannelSelector = 1.493 + static_cast<SkDisplacementMapEffect::ChannelSelectorType>( 1.494 + random->nextRangeU(1, kMaxComponent)); 1.495 + SkVector scale = SkVector::Make(random->nextRangeScalar(0, 100.0f), 1.496 + random->nextRangeScalar(0, 100.0f)); 1.497 + 1.498 + return GrDisplacementMapEffect::Create(xChannelSelector, yChannelSelector, scale, 1.499 + textures[texIdxDispl], SkMatrix::I(), 1.500 + textures[texIdxColor]); 1.501 +} 1.502 + 1.503 +/////////////////////////////////////////////////////////////////////////////// 1.504 + 1.505 +GrGLDisplacementMapEffect::GrGLDisplacementMapEffect(const GrBackendEffectFactory& factory, 1.506 + const GrDrawEffect& drawEffect) 1.507 + : INHERITED(factory) 1.508 + , fXChannelSelector(drawEffect.castEffect<GrDisplacementMapEffect>().xChannelSelector()) 1.509 + , fYChannelSelector(drawEffect.castEffect<GrDisplacementMapEffect>().yChannelSelector()) { 1.510 +} 1.511 + 1.512 +GrGLDisplacementMapEffect::~GrGLDisplacementMapEffect() { 1.513 +} 1.514 + 1.515 +void GrGLDisplacementMapEffect::emitCode(GrGLShaderBuilder* builder, 1.516 + const GrDrawEffect&, 1.517 + EffectKey key, 1.518 + const char* outputColor, 1.519 + const char* inputColor, 1.520 + const TransformedCoordsArray& coords, 1.521 + const TextureSamplerArray& samplers) { 1.522 + sk_ignore_unused_variable(inputColor); 1.523 + 1.524 + fScaleUni = builder->addUniform(GrGLShaderBuilder::kFragment_Visibility, 1.525 + kVec2f_GrSLType, "Scale"); 1.526 + const char* scaleUni = builder->getUniformCStr(fScaleUni); 1.527 + const char* dColor = "dColor"; 1.528 + const char* cCoords = "cCoords"; 1.529 + const char* outOfBounds = "outOfBounds"; 1.530 + const char* nearZero = "1e-6"; // Since 6.10352e−5 is the smallest half float, use 1.531 + // a number smaller than that to approximate 0, but 1.532 + // leave room for 32-bit float GPU rounding errors. 1.533 + 1.534 + builder->fsCodeAppendf("\t\tvec4 %s = ", dColor); 1.535 + builder->fsAppendTextureLookup(samplers[0], coords[0].c_str(), coords[0].type()); 1.536 + builder->fsCodeAppend(";\n"); 1.537 + 1.538 + // Unpremultiply the displacement 1.539 + builder->fsCodeAppendf("\t\t%s.rgb = (%s.a < %s) ? vec3(0.0) : clamp(%s.rgb / %s.a, 0.0, 1.0);", 1.540 + dColor, dColor, nearZero, dColor, dColor); 1.541 + 1.542 + builder->fsCodeAppendf("\t\tvec2 %s = %s + %s*(%s.", 1.543 + cCoords, coords[1].c_str(), scaleUni, dColor); 1.544 + 1.545 + switch (fXChannelSelector) { 1.546 + case SkDisplacementMapEffect::kR_ChannelSelectorType: 1.547 + builder->fsCodeAppend("r"); 1.548 + break; 1.549 + case SkDisplacementMapEffect::kG_ChannelSelectorType: 1.550 + builder->fsCodeAppend("g"); 1.551 + break; 1.552 + case SkDisplacementMapEffect::kB_ChannelSelectorType: 1.553 + builder->fsCodeAppend("b"); 1.554 + break; 1.555 + case SkDisplacementMapEffect::kA_ChannelSelectorType: 1.556 + builder->fsCodeAppend("a"); 1.557 + break; 1.558 + case SkDisplacementMapEffect::kUnknown_ChannelSelectorType: 1.559 + default: 1.560 + SkDEBUGFAIL("Unknown X channel selector"); 1.561 + } 1.562 + 1.563 + switch (fYChannelSelector) { 1.564 + case SkDisplacementMapEffect::kR_ChannelSelectorType: 1.565 + builder->fsCodeAppend("r"); 1.566 + break; 1.567 + case SkDisplacementMapEffect::kG_ChannelSelectorType: 1.568 + builder->fsCodeAppend("g"); 1.569 + break; 1.570 + case SkDisplacementMapEffect::kB_ChannelSelectorType: 1.571 + builder->fsCodeAppend("b"); 1.572 + break; 1.573 + case SkDisplacementMapEffect::kA_ChannelSelectorType: 1.574 + builder->fsCodeAppend("a"); 1.575 + break; 1.576 + case SkDisplacementMapEffect::kUnknown_ChannelSelectorType: 1.577 + default: 1.578 + SkDEBUGFAIL("Unknown Y channel selector"); 1.579 + } 1.580 + builder->fsCodeAppend("-vec2(0.5));\t\t"); 1.581 + 1.582 + // FIXME : This can be achieved with a "clamp to border" texture repeat mode and 1.583 + // a 0 border color instead of computing if cCoords is out of bounds here. 1.584 + builder->fsCodeAppendf( 1.585 + "bool %s = (%s.x < 0.0) || (%s.y < 0.0) || (%s.x > 1.0) || (%s.y > 1.0);\t\t", 1.586 + outOfBounds, cCoords, cCoords, cCoords, cCoords); 1.587 + builder->fsCodeAppendf("%s = %s ? vec4(0.0) : ", outputColor, outOfBounds); 1.588 + builder->fsAppendTextureLookup(samplers[1], cCoords, coords[1].type()); 1.589 + builder->fsCodeAppend(";\n"); 1.590 +} 1.591 + 1.592 +void GrGLDisplacementMapEffect::setData(const GrGLUniformManager& uman, 1.593 + const GrDrawEffect& drawEffect) { 1.594 + const GrDisplacementMapEffect& displacementMap = 1.595 + drawEffect.castEffect<GrDisplacementMapEffect>(); 1.596 + GrTexture* colorTex = displacementMap.texture(1); 1.597 + SkScalar scaleX = SkScalarDiv(displacementMap.scale().fX, SkIntToScalar(colorTex->width())); 1.598 + SkScalar scaleY = SkScalarDiv(displacementMap.scale().fY, SkIntToScalar(colorTex->height())); 1.599 + uman.set2f(fScaleUni, SkScalarToFloat(scaleX), 1.600 + colorTex->origin() == kTopLeft_GrSurfaceOrigin ? 1.601 + SkScalarToFloat(scaleY) : SkScalarToFloat(-scaleY)); 1.602 +} 1.603 + 1.604 +GrGLEffect::EffectKey GrGLDisplacementMapEffect::GenKey(const GrDrawEffect& drawEffect, 1.605 + const GrGLCaps&) { 1.606 + const GrDisplacementMapEffect& displacementMap = 1.607 + drawEffect.castEffect<GrDisplacementMapEffect>(); 1.608 + 1.609 + EffectKey xKey = displacementMap.xChannelSelector(); 1.610 + EffectKey yKey = displacementMap.yChannelSelector() << kChannelSelectorKeyBits; 1.611 + 1.612 + return xKey | yKey; 1.613 +} 1.614 +#endif