Home | History | Annotate | Download | only in effects
      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