• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "SkFlattenableBuffers.h"
10 #include "SkUnPreMultiply.h"
11 #include "SkColorPriv.h"
12 #if SK_SUPPORT_GPU
13 #include "GrContext.h"
14 #include "gl/GrGLEffect.h"
15 #include "gl/GrGLEffectMatrix.h"
16 #include "GrTBackendEffectFactory.h"
17 #include "SkImageFilterUtils.h"
18 #endif
19 
20 namespace {
21 
22 template<SkDisplacementMapEffect::ChannelSelectorType type>
getValue(SkColor,const SkUnPreMultiply::Scale *)23 uint32_t getValue(SkColor, const SkUnPreMultiply::Scale*) {
24     SkASSERT(!"Unknown channel selector");
25     return 0;
26 }
27 
getValue(SkColor l,const SkUnPreMultiply::Scale * table)28 template<> uint32_t getValue<SkDisplacementMapEffect::kR_ChannelSelectorType>(
29     SkColor l, const SkUnPreMultiply::Scale* table) {
30     return SkUnPreMultiply::ApplyScale(table[SkGetPackedA32(l)], SkGetPackedR32(l));
31 }
32 
getValue(SkColor l,const SkUnPreMultiply::Scale * table)33 template<> uint32_t getValue<SkDisplacementMapEffect::kG_ChannelSelectorType>(
34     SkColor l, const SkUnPreMultiply::Scale* table) {
35     return SkUnPreMultiply::ApplyScale(table[SkGetPackedA32(l)], SkGetPackedG32(l));
36 }
37 
getValue(SkColor l,const SkUnPreMultiply::Scale * table)38 template<> uint32_t getValue<SkDisplacementMapEffect::kB_ChannelSelectorType>(
39     SkColor l, const SkUnPreMultiply::Scale* table) {
40     return SkUnPreMultiply::ApplyScale(table[SkGetPackedA32(l)], SkGetPackedB32(l));
41 }
42 
getValue(SkColor l,const SkUnPreMultiply::Scale *)43 template<> uint32_t getValue<SkDisplacementMapEffect::kA_ChannelSelectorType>(
44     SkColor l, const SkUnPreMultiply::Scale*) {
45     return SkGetPackedA32(l);
46 }
47 
48 template<SkDisplacementMapEffect::ChannelSelectorType typeX,
49          SkDisplacementMapEffect::ChannelSelectorType typeY>
computeDisplacement(SkScalar scale,SkBitmap * dst,SkBitmap * displ,SkBitmap * src)50 void computeDisplacement(SkScalar scale, SkBitmap* dst, SkBitmap* displ, SkBitmap* src)
51 {
52     static const SkScalar Inv8bit = SkScalarDiv(SK_Scalar1, SkFloatToScalar(255.0f));
53     static const SkScalar Half8bit = SkFloatToScalar(255.0f * 0.5f);
54     const int dstW = displ->width();
55     const int dstH = displ->height();
56     const int srcW = src->width();
57     const int srcH = src->height();
58     const SkScalar scaleX = SkScalarMul(SkScalarMul(scale, SkIntToScalar(dstW)), Inv8bit);
59     const SkScalar scaleY = SkScalarMul(SkScalarMul(scale, SkIntToScalar(dstH)), Inv8bit);
60     const SkUnPreMultiply::Scale* table = SkUnPreMultiply::GetScaleTable();
61     for (int y = 0; y < dstH; ++y) {
62         const SkPMColor* displPtr = displ->getAddr32(0, y);
63         SkPMColor* dstPtr = dst->getAddr32(0, y);
64         for (int x = 0; x < dstW; ++x, ++displPtr, ++dstPtr) {
65             const SkScalar displX =
66                 SkScalarMul(scaleX, SkIntToScalar(getValue<typeX>(*displPtr, table))-Half8bit);
67             const SkScalar displY =
68                 SkScalarMul(scaleY, SkIntToScalar(getValue<typeY>(*displPtr, table))-Half8bit);
69             const int coordX = x + SkScalarRoundToInt(displX);
70             const int coordY = y + SkScalarRoundToInt(displY);
71             *dstPtr = ((coordX < 0) || (coordX >= srcW) || (coordY < 0) || (coordY >= srcH)) ?
72                       0 : *(src->getAddr32(coordX, coordY));
73         }
74     }
75 }
76 
77 template<SkDisplacementMapEffect::ChannelSelectorType typeX>
computeDisplacement(SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,SkScalar scale,SkBitmap * dst,SkBitmap * displ,SkBitmap * src)78 void computeDisplacement(SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
79                          SkScalar scale, SkBitmap* dst, SkBitmap* displ, SkBitmap* src)
80 {
81     switch (yChannelSelector) {
82       case SkDisplacementMapEffect::kR_ChannelSelectorType:
83         computeDisplacement<typeX, SkDisplacementMapEffect::kR_ChannelSelectorType>(
84             scale, dst, displ, src);
85         break;
86       case SkDisplacementMapEffect::kG_ChannelSelectorType:
87         computeDisplacement<typeX, SkDisplacementMapEffect::kG_ChannelSelectorType>(
88             scale, dst, displ, src);
89         break;
90       case SkDisplacementMapEffect::kB_ChannelSelectorType:
91         computeDisplacement<typeX, SkDisplacementMapEffect::kB_ChannelSelectorType>(
92             scale, dst, displ, src);
93         break;
94       case SkDisplacementMapEffect::kA_ChannelSelectorType:
95         computeDisplacement<typeX, SkDisplacementMapEffect::kA_ChannelSelectorType>(
96             scale, dst, displ, src);
97         break;
98       case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
99       default:
100         SkASSERT(!"Unknown Y channel selector");
101     }
102 }
103 
computeDisplacement(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,SkScalar scale,SkBitmap * dst,SkBitmap * displ,SkBitmap * src)104 void computeDisplacement(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
105                          SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
106                          SkScalar scale, SkBitmap* dst, SkBitmap* displ, SkBitmap* src)
107 {
108     switch (xChannelSelector) {
109       case SkDisplacementMapEffect::kR_ChannelSelectorType:
110         computeDisplacement<SkDisplacementMapEffect::kR_ChannelSelectorType>(
111             yChannelSelector, scale, dst, displ, src);
112         break;
113       case SkDisplacementMapEffect::kG_ChannelSelectorType:
114         computeDisplacement<SkDisplacementMapEffect::kG_ChannelSelectorType>(
115             yChannelSelector, scale, dst, displ, src);
116         break;
117       case SkDisplacementMapEffect::kB_ChannelSelectorType:
118         computeDisplacement<SkDisplacementMapEffect::kB_ChannelSelectorType>(
119             yChannelSelector, scale, dst, displ, src);
120         break;
121       case SkDisplacementMapEffect::kA_ChannelSelectorType:
122         computeDisplacement<SkDisplacementMapEffect::kA_ChannelSelectorType>(
123             yChannelSelector, scale, dst, displ, src);
124         break;
125       case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
126       default:
127         SkASSERT(!"Unknown X channel selector");
128     }
129 }
130 
131 } // end namespace
132 
133 ///////////////////////////////////////////////////////////////////////////////
134 
SkDisplacementMapEffect(ChannelSelectorType xChannelSelector,ChannelSelectorType yChannelSelector,SkScalar scale,SkImageFilter * displacement,SkImageFilter * color)135 SkDisplacementMapEffect::SkDisplacementMapEffect(ChannelSelectorType xChannelSelector,
136                                                  ChannelSelectorType yChannelSelector,
137                                                  SkScalar scale,
138                                                  SkImageFilter* displacement,
139                                                  SkImageFilter* color)
140   : INHERITED(displacement, color)
141   , fXChannelSelector(xChannelSelector)
142   , fYChannelSelector(yChannelSelector)
143   , fScale(scale)
144 {
145 }
146 
~SkDisplacementMapEffect()147 SkDisplacementMapEffect::~SkDisplacementMapEffect() {
148 }
149 
SkDisplacementMapEffect(SkFlattenableReadBuffer & buffer)150 SkDisplacementMapEffect::SkDisplacementMapEffect(SkFlattenableReadBuffer& buffer)
151   : INHERITED(buffer)
152 {
153     fXChannelSelector = (SkDisplacementMapEffect::ChannelSelectorType) buffer.readInt();
154     fYChannelSelector = (SkDisplacementMapEffect::ChannelSelectorType) buffer.readInt();
155     fScale            = buffer.readScalar();
156 }
157 
flatten(SkFlattenableWriteBuffer & buffer) const158 void SkDisplacementMapEffect::flatten(SkFlattenableWriteBuffer& buffer) const {
159     this->INHERITED::flatten(buffer);
160     buffer.writeInt((int) fXChannelSelector);
161     buffer.writeInt((int) fYChannelSelector);
162     buffer.writeScalar(fScale);
163 }
164 
onFilterImage(Proxy * proxy,const SkBitmap & src,const SkMatrix & ctm,SkBitmap * dst,SkIPoint * offset)165 bool SkDisplacementMapEffect::onFilterImage(Proxy* proxy,
166                                             const SkBitmap& src,
167                                             const SkMatrix& ctm,
168                                             SkBitmap* dst,
169                                             SkIPoint* offset) {
170     SkBitmap displ, color = src;
171     SkImageFilter* colorInput = getColorInput();
172     SkImageFilter* displacementInput = getDisplacementInput();
173     SkASSERT(NULL != displacementInput);
174     if ((colorInput && !colorInput->filterImage(proxy, src, ctm, &color, offset)) ||
175         !displacementInput->filterImage(proxy, src, ctm, &displ, offset)) {
176         return false;
177     }
178     if ((displ.config() != SkBitmap::kARGB_8888_Config) ||
179         (color.config() != SkBitmap::kARGB_8888_Config)) {
180         return false;
181     }
182 
183     SkAutoLockPixels alp_displacement(displ), alp_color(color);
184     if (!displ.getPixels() || !color.getPixels()) {
185         return false;
186     }
187     dst->setConfig(displ.config(), displ.width(), displ.height());
188     dst->allocPixels();
189     if (!dst->getPixels()) {
190         return false;
191     }
192 
193     computeDisplacement(fXChannelSelector, fYChannelSelector, fScale, dst, &displ, &color);
194 
195     return true;
196 }
197 
198 ///////////////////////////////////////////////////////////////////////////////
199 
200 #if SK_SUPPORT_GPU
201 class GrGLDisplacementMapEffect : public GrGLEffect {
202 public:
203     GrGLDisplacementMapEffect(const GrBackendEffectFactory& factory,
204                               const GrEffectRef& effect);
205     virtual ~GrGLDisplacementMapEffect();
206 
207     virtual void emitCode(GrGLShaderBuilder*,
208                           const GrEffectStage&,
209                           EffectKey,
210                           const char* vertexCoords,
211                           const char* outputColor,
212                           const char* inputColor,
213                           const TextureSamplerArray&) SK_OVERRIDE;
214 
215     static inline EffectKey GenKey(const GrEffectStage&, const GrGLCaps&);
216 
217     virtual void setData(const GrGLUniformManager&, const GrEffectStage&);
218 
219 private:
220     SkDisplacementMapEffect::ChannelSelectorType fXChannelSelector;
221     SkDisplacementMapEffect::ChannelSelectorType fYChannelSelector;
222     GrGLEffectMatrix fDisplacementEffectMatrix;
223     GrGLEffectMatrix fColorEffectMatrix;
224     GrGLUniformManager::UniformHandle fScaleUni;
225     GrGLUniformManager::UniformHandle fYSignColor;
226     GrGLUniformManager::UniformHandle fYSignDispl;
227 
228     typedef GrGLEffect INHERITED;
229 };
230 
231 ///////////////////////////////////////////////////////////////////////////////
232 
233 class GrDisplacementMapEffect : public GrEffect {
234 public:
Create(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,SkScalar scale,GrTexture * displacement,GrTexture * color)235     static GrEffectRef* Create(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
236                                SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
237                                SkScalar scale, GrTexture* displacement, GrTexture* color) {
238         AutoEffectUnref effect(SkNEW_ARGS(GrDisplacementMapEffect, (xChannelSelector,
239                                                                     yChannelSelector,
240                                                                     scale,
241                                                                     displacement,
242                                                                     color)));
243         return CreateEffectRef(effect);
244     }
245 
246     virtual ~GrDisplacementMapEffect();
247 
248     const GrBackendEffectFactory& getFactory() const;
xChannelSelector() const249     SkDisplacementMapEffect::ChannelSelectorType xChannelSelector() const
250         { return fXChannelSelector; }
yChannelSelector() const251     SkDisplacementMapEffect::ChannelSelectorType yChannelSelector() const
252         { return fYChannelSelector; }
scale() const253     SkScalar scale() const { return fScale; }
254 
255     typedef GrGLDisplacementMapEffect GLEffect;
Name()256     static const char* Name() { return "DisplacementMap"; }
257 
258     void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
259 
260 private:
261     virtual bool onIsEqual(const GrEffect&) const SK_OVERRIDE;
262 
263     GrDisplacementMapEffect(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
264                             SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
265                             SkScalar scale, GrTexture* displacement, GrTexture* color);
266 
267     GR_DECLARE_EFFECT_TEST;
268 
269     GrTextureAccess             fDisplacementAccess;
270     GrTextureAccess             fColorAccess;
271     SkDisplacementMapEffect::ChannelSelectorType fXChannelSelector;
272     SkDisplacementMapEffect::ChannelSelectorType fYChannelSelector;
273     SkScalar fScale;
274 
275     typedef GrEffect INHERITED;
276 };
277 
filterImageGPU(Proxy * proxy,const SkBitmap & src,SkBitmap * result)278 bool SkDisplacementMapEffect::filterImageGPU(Proxy* proxy, const SkBitmap& src, SkBitmap* result) {
279     SkBitmap colorBM;
280     if (!SkImageFilterUtils::GetInputResultGPU(getColorInput(), proxy, src, &colorBM)) {
281         return false;
282     }
283     GrTexture* color = (GrTexture*) colorBM.getTexture();
284     SkBitmap displacementBM;
285     if (!SkImageFilterUtils::GetInputResultGPU(getDisplacementInput(), proxy, src, &displacementBM)) {
286         return false;
287     }
288     GrTexture* displacement = (GrTexture*) displacementBM.getTexture();
289     GrContext* context = color->getContext();
290 
291     GrTextureDesc desc;
292     desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
293     desc.fWidth = src.width();
294     desc.fHeight = src.height();
295     desc.fConfig = kSkia8888_GrPixelConfig;
296 
297     GrAutoScratchTexture ast(context, desc);
298     SkAutoTUnref<GrTexture> dst(ast.detach());
299 
300     GrContext::AutoRenderTarget art(context, dst->asRenderTarget());
301 
302     GrPaint paint;
303     paint.colorStage(0)->setEffect(
304         GrDisplacementMapEffect::Create(fXChannelSelector,
305                                         fYChannelSelector,
306                                         fScale,
307                                         displacement,
308                                         color))->unref();
309     SkRect srcRect;
310     src.getBounds(&srcRect);
311     context->drawRect(paint, srcRect);
312     return SkImageFilterUtils::WrapTexture(dst, src.width(), src.height(), result);
313 }
314 
315 ///////////////////////////////////////////////////////////////////////////////
316 
GrDisplacementMapEffect(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,SkScalar scale,GrTexture * displacement,GrTexture * color)317 GrDisplacementMapEffect::GrDisplacementMapEffect(
318                              SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
319                              SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
320                              SkScalar scale,
321                              GrTexture* displacement,
322                              GrTexture* color)
323     : fDisplacementAccess(displacement)
324     , fColorAccess(color)
325     , fXChannelSelector(xChannelSelector)
326     , fYChannelSelector(yChannelSelector)
327     , fScale(scale) {
328     this->addTextureAccess(&fDisplacementAccess);
329     this->addTextureAccess(&fColorAccess);
330 }
331 
~GrDisplacementMapEffect()332 GrDisplacementMapEffect::~GrDisplacementMapEffect() {
333 }
334 
onIsEqual(const GrEffect & sBase) const335 bool GrDisplacementMapEffect::onIsEqual(const GrEffect& sBase) const {
336     const GrDisplacementMapEffect& s = CastEffect<GrDisplacementMapEffect>(sBase);
337     return fDisplacementAccess.getTexture() == s.fDisplacementAccess.getTexture() &&
338            fColorAccess.getTexture() == s.fColorAccess.getTexture() &&
339            fXChannelSelector == s.fXChannelSelector &&
340            fYChannelSelector == s.fYChannelSelector &&
341            fScale == s.fScale;
342 }
343 
getFactory() const344 const GrBackendEffectFactory& GrDisplacementMapEffect::getFactory() const {
345     return GrTBackendEffectFactory<GrDisplacementMapEffect>::getInstance();
346 }
347 
getConstantColorComponents(GrColor * color,uint32_t * validFlags) const348 void GrDisplacementMapEffect::getConstantColorComponents(GrColor* color,
349                                                          uint32_t* validFlags) const {
350     // Any displacement offset bringing a pixel out of bounds will output a color of (0,0,0,0),
351     // so the only way we'd get a constant alpha is if the input color image has a constant alpha
352     // and no displacement offset push any texture coordinates out of bounds OR if the constant
353     // alpha is 0. Since this isn't trivial to compute at this point, let's assume the output is
354     // not of constant color when a displacement effect is applied.
355     *validFlags = 0;
356 }
357 
358 ///////////////////////////////////////////////////////////////////////////////
359 
360 GR_DEFINE_EFFECT_TEST(GrDisplacementMapEffect);
361 
TestCreate(SkRandom * random,GrContext * context,GrTexture * textures[])362 GrEffectRef* GrDisplacementMapEffect::TestCreate(SkRandom* random,
363                                                  GrContext* context,
364                                                  GrTexture* textures[]) {
365     int texIdxDispl = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx :
366                                            GrEffectUnitTest::kAlphaTextureIdx;
367     int texIdxColor = random->nextBool() ? GrEffectUnitTest::kSkiaPMTextureIdx :
368                                            GrEffectUnitTest::kAlphaTextureIdx;
369     static const int kMaxComponent = 4;
370     SkDisplacementMapEffect::ChannelSelectorType xChannelSelector =
371         static_cast<SkDisplacementMapEffect::ChannelSelectorType>(
372         random->nextRangeU(1, kMaxComponent));
373     SkDisplacementMapEffect::ChannelSelectorType yChannelSelector =
374         static_cast<SkDisplacementMapEffect::ChannelSelectorType>(
375         random->nextRangeU(1, kMaxComponent));
376     SkScalar scale = random->nextUScalar1();
377 
378     return GrDisplacementMapEffect::Create(xChannelSelector, yChannelSelector, scale,
379                                            textures[texIdxDispl], textures[texIdxColor]);
380 }
381 
382 ///////////////////////////////////////////////////////////////////////////////
383 
GrGLDisplacementMapEffect(const GrBackendEffectFactory & factory,const GrEffectRef & effect)384 GrGLDisplacementMapEffect::GrGLDisplacementMapEffect(const GrBackendEffectFactory& factory,
385                                                      const GrEffectRef& effect)
386     : INHERITED(factory)
387     , fXChannelSelector(CastEffect<GrDisplacementMapEffect>(effect).xChannelSelector())
388     , fYChannelSelector(CastEffect<GrDisplacementMapEffect>(effect).yChannelSelector()) {
389 }
390 
~GrGLDisplacementMapEffect()391 GrGLDisplacementMapEffect::~GrGLDisplacementMapEffect() {
392 }
393 
emitCode(GrGLShaderBuilder * builder,const GrEffectStage &,EffectKey key,const char * vertexCoords,const char * outputColor,const char * inputColor,const TextureSamplerArray & samplers)394 void GrGLDisplacementMapEffect::emitCode(GrGLShaderBuilder* builder,
395                                const GrEffectStage&,
396                                EffectKey key,
397                                const char* vertexCoords,
398                                const char* outputColor,
399                                const char* inputColor,
400                                const TextureSamplerArray& samplers) {
401     fScaleUni = builder->addUniform(GrGLShaderBuilder::kFragment_ShaderType,
402                                     kVec2f_GrSLType, "Scale");
403     const char* scaleUni = builder->getUniformCStr(fScaleUni);
404 
405     const char* dCoordsIn;
406     GrSLType dCoordsType = fDisplacementEffectMatrix.emitCode(
407                                 builder, key, vertexCoords, &dCoordsIn, NULL, "DISPL");
408     const char* cCoordsIn;
409     GrSLType cCoordsType = fColorEffectMatrix.emitCode(
410                                 builder, key, vertexCoords, &cCoordsIn, NULL, "COLOR");
411 
412     SkString* code = &builder->fFSCode;
413     const char* dColor = "dColor";
414     const char* cCoords = "cCoords";
415     const char* nearZero = "1e-6"; // Since 6.10352e−5 is the smallest half float, use
416                                    // a number smaller than that to approximate 0, but
417                                    // leave room for 32-bit float GPU rounding errors.
418 
419     code->appendf("\t\tvec4 %s = ", dColor);
420     builder->appendTextureLookup(code, samplers[0], dCoordsIn, dCoordsType);
421     code->append(";\n");
422 
423     // Unpremultiply the displacement
424     code->appendf("\t\t%s.rgb = (%s.a < %s) ? vec3(0.0) : clamp(%s.rgb / %s.a, 0.0, 1.0);",
425                   dColor, dColor, nearZero, dColor, dColor);
426 
427     code->appendf("\t\tvec2 %s = %s + %s*(%s.",
428                   cCoords, cCoordsIn, scaleUni, dColor);
429 
430     switch (fXChannelSelector) {
431       case SkDisplacementMapEffect::kR_ChannelSelectorType:
432         code->append("r");
433         break;
434       case SkDisplacementMapEffect::kG_ChannelSelectorType:
435         code->append("g");
436         break;
437       case SkDisplacementMapEffect::kB_ChannelSelectorType:
438         code->append("b");
439         break;
440       case SkDisplacementMapEffect::kA_ChannelSelectorType:
441         code->append("a");
442         break;
443       case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
444       default:
445         SkASSERT(!"Unknown X channel selector");
446     }
447 
448     switch (fYChannelSelector) {
449       case SkDisplacementMapEffect::kR_ChannelSelectorType:
450         code->append("r");
451         break;
452       case SkDisplacementMapEffect::kG_ChannelSelectorType:
453         code->append("g");
454         break;
455       case SkDisplacementMapEffect::kB_ChannelSelectorType:
456         code->append("b");
457         break;
458       case SkDisplacementMapEffect::kA_ChannelSelectorType:
459         code->append("a");
460         break;
461       case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
462       default:
463         SkASSERT(!"Unknown Y channel selector");
464     }
465     code->append("-vec2(0.5));\t\t");
466 
467     // FIXME : This can be achieved with a "clamp to border" texture repeat mode and
468     //         a 0 border color instead of computing if cCoords is out of bounds here.
469     code->appendf(
470         "%s = any(greaterThan(vec4(vec2(0.0), %s), vec4(%s, vec2(1.0)))) ? vec4(0.0) : ",
471         outputColor, cCoords, cCoords);
472     builder->appendTextureLookup(code, samplers[1], cCoords, cCoordsType);
473     code->append(";\n");
474 }
475 
setData(const GrGLUniformManager & uman,const GrEffectStage & stage)476 void GrGLDisplacementMapEffect::setData(const GrGLUniformManager& uman, const GrEffectStage& stage) {
477     const GrDisplacementMapEffect& displacementMap = GetEffectFromStage<GrDisplacementMapEffect>(stage);
478     GrTexture* displTex = displacementMap.texture(0);
479     GrTexture* colorTex = displacementMap.texture(1);
480     fDisplacementEffectMatrix.setData(uman,
481                                      GrEffect::MakeDivByTextureWHMatrix(displTex),
482                                      stage.getCoordChangeMatrix(),
483                                      displTex);
484     fColorEffectMatrix.setData(uman,
485                                GrEffect::MakeDivByTextureWHMatrix(colorTex),
486                                stage.getCoordChangeMatrix(),
487                                colorTex);
488 
489     uman.set2f(fScaleUni, SkScalarToFloat(displacementMap.scale()),
490                 colorTex->origin() == kTopLeft_GrSurfaceOrigin ?
491                 SkScalarToFloat(displacementMap.scale()) :
492                 SkScalarToFloat(-displacementMap.scale()));
493 }
494 
GenKey(const GrEffectStage & stage,const GrGLCaps &)495 GrGLEffect::EffectKey GrGLDisplacementMapEffect::GenKey(const GrEffectStage& stage,
496                                                         const GrGLCaps&) {
497     const GrDisplacementMapEffect& displacementMap =
498         GetEffectFromStage<GrDisplacementMapEffect>(stage);
499 
500     GrTexture* displTex = displacementMap.texture(0);
501     GrTexture* colorTex = displacementMap.texture(1);
502 
503     EffectKey displKey = GrGLEffectMatrix::GenKey(GrEffect::MakeDivByTextureWHMatrix(displTex),
504                                                   stage.getCoordChangeMatrix(),
505                                                   displTex);
506 
507     EffectKey colorKey = GrGLEffectMatrix::GenKey(GrEffect::MakeDivByTextureWHMatrix(colorTex),
508                                                   stage.getCoordChangeMatrix(),
509                                                   colorTex);
510 
511     colorKey <<= GrGLEffectMatrix::kKeyBits;
512     EffectKey xKey = displacementMap.xChannelSelector() << (2 * GrGLEffectMatrix::kKeyBits);
513     EffectKey yKey = displacementMap.yChannelSelector() << (2 * GrGLEffectMatrix::kKeyBits +
514                                                             SkDisplacementMapEffect::kKeyBits);
515 
516     return xKey | yKey | displKey | colorKey;
517 }
518 #endif
519