gfx/skia/trunk/src/effects/SkDisplacementMapEffect.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial