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.

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

mercurial