2 * Copyright 2013 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "SkDisplacementMapEffect.h"
9 #include "SkReadBuffer.h"
10 #include "SkWriteBuffer.h"
11 #include "SkUnPreMultiply.h"
12 #include "SkColorPriv.h"
14 #include "GrContext.h"
15 #include "GrCoordTransform.h"
16 #include "gl/GrGLProcessor.h"
17 #include "gl/builders/GrGLProgramBuilder.h"
18 #include "GrTBackendProcessorFactory.h"
23 #define kChannelSelectorKeyBits 3; // Max value is 4, so 3 bits are required at most
25 template<SkDisplacementMapEffect::ChannelSelectorType type>
26 uint32_t getValue(SkColor, const SkUnPreMultiply::Scale*) {
27 SkDEBUGFAIL("Unknown channel selector");
31 template<> uint32_t getValue<SkDisplacementMapEffect::kR_ChannelSelectorType>(
32 SkColor l, const SkUnPreMultiply::Scale* table) {
33 return SkUnPreMultiply::ApplyScale(table[SkGetPackedA32(l)], SkGetPackedR32(l));
36 template<> uint32_t getValue<SkDisplacementMapEffect::kG_ChannelSelectorType>(
37 SkColor l, const SkUnPreMultiply::Scale* table) {
38 return SkUnPreMultiply::ApplyScale(table[SkGetPackedA32(l)], SkGetPackedG32(l));
41 template<> uint32_t getValue<SkDisplacementMapEffect::kB_ChannelSelectorType>(
42 SkColor l, const SkUnPreMultiply::Scale* table) {
43 return SkUnPreMultiply::ApplyScale(table[SkGetPackedA32(l)], SkGetPackedB32(l));
46 template<> uint32_t getValue<SkDisplacementMapEffect::kA_ChannelSelectorType>(
47 SkColor l, const SkUnPreMultiply::Scale*) {
48 return SkGetPackedA32(l);
51 template<SkDisplacementMapEffect::ChannelSelectorType typeX,
52 SkDisplacementMapEffect::ChannelSelectorType typeY>
53 void computeDisplacement(const SkVector& scale, SkBitmap* dst,
54 SkBitmap* displ, const SkIPoint& offset,
56 const SkIRect& bounds)
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,
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));
84 template<SkDisplacementMapEffect::ChannelSelectorType typeX>
85 void computeDisplacement(SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
86 const SkVector& scale, SkBitmap* dst,
87 SkBitmap* displ, const SkIPoint& offset,
89 const SkIRect& bounds)
91 switch (yChannelSelector) {
92 case SkDisplacementMapEffect::kR_ChannelSelectorType:
93 computeDisplacement<typeX, SkDisplacementMapEffect::kR_ChannelSelectorType>(
94 scale, dst, displ, offset, src, bounds);
96 case SkDisplacementMapEffect::kG_ChannelSelectorType:
97 computeDisplacement<typeX, SkDisplacementMapEffect::kG_ChannelSelectorType>(
98 scale, dst, displ, offset, src, bounds);
100 case SkDisplacementMapEffect::kB_ChannelSelectorType:
101 computeDisplacement<typeX, SkDisplacementMapEffect::kB_ChannelSelectorType>(
102 scale, dst, displ, offset, src, bounds);
104 case SkDisplacementMapEffect::kA_ChannelSelectorType:
105 computeDisplacement<typeX, SkDisplacementMapEffect::kA_ChannelSelectorType>(
106 scale, dst, displ, offset, src, bounds);
108 case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
110 SkDEBUGFAIL("Unknown Y channel selector");
114 void computeDisplacement(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
115 SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
116 const SkVector& scale, SkBitmap* dst,
117 SkBitmap* displ, const SkIPoint& offset,
119 const SkIRect& bounds)
121 switch (xChannelSelector) {
122 case SkDisplacementMapEffect::kR_ChannelSelectorType:
123 computeDisplacement<SkDisplacementMapEffect::kR_ChannelSelectorType>(
124 yChannelSelector, scale, dst, displ, offset, src, bounds);
126 case SkDisplacementMapEffect::kG_ChannelSelectorType:
127 computeDisplacement<SkDisplacementMapEffect::kG_ChannelSelectorType>(
128 yChannelSelector, scale, dst, displ, offset, src, bounds);
130 case SkDisplacementMapEffect::kB_ChannelSelectorType:
131 computeDisplacement<SkDisplacementMapEffect::kB_ChannelSelectorType>(
132 yChannelSelector, scale, dst, displ, offset, src, bounds);
134 case SkDisplacementMapEffect::kA_ChannelSelectorType:
135 computeDisplacement<SkDisplacementMapEffect::kA_ChannelSelectorType>(
136 yChannelSelector, scale, dst, displ, offset, src, bounds);
138 case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
140 SkDEBUGFAIL("Unknown X channel selector");
144 bool channel_selector_type_is_valid(SkDisplacementMapEffect::ChannelSelectorType 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:
160 ///////////////////////////////////////////////////////////////////////////////
162 SkDisplacementMapEffect* SkDisplacementMapEffect::Create(ChannelSelectorType xChannelSelector,
163 ChannelSelectorType yChannelSelector,
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)) {
173 SkImageFilter* inputs[2] = { displacement, color };
174 return SkNEW_ARGS(SkDisplacementMapEffect, (xChannelSelector, yChannelSelector, scale,
175 inputs, cropRect, uniqueID));
178 SkDisplacementMapEffect::SkDisplacementMapEffect(ChannelSelectorType xChannelSelector,
179 ChannelSelectorType yChannelSelector,
181 SkImageFilter* inputs[2],
182 const CropRect* cropRect,
184 : INHERITED(2, inputs, cropRect, uniqueID)
185 , fXChannelSelector(xChannelSelector)
186 , fYChannelSelector(yChannelSelector)
191 SkDisplacementMapEffect::~SkDisplacementMapEffect() {
194 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
195 SkDisplacementMapEffect::SkDisplacementMapEffect(SkReadBuffer& buffer)
196 : INHERITED(2, buffer)
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));
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());
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);
222 bool SkDisplacementMapEffect::onFilterImage(Proxy* proxy,
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))) {
235 if ((displ.colorType() != kN32_SkColorType) ||
236 (color.colorType() != kN32_SkColorType)) {
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)) {
246 if (!this->applyCropRect(ctx, proxy, displ, &displOffset, &displBounds, &displ)) {
249 if (!bounds.intersect(displBounds)) {
252 SkAutoLockPixels alp_displacement(displ), alp_color(color);
253 if (!displ.getPixels() || !color.getPixels()) {
257 if (!dst->tryAllocPixels(color.info().makeWH(bounds.width(), bounds.height()))) {
261 SkVector scale = SkVector::Make(fScale, fScale);
262 ctx.ctm().mapVectors(&scale, 1);
263 SkIRect colorBounds = bounds;
264 colorBounds.offset(-colorOffset);
266 computeDisplacement(fXChannelSelector, fYChannelSelector, scale, dst,
267 &displ, colorOffset - displOffset, &color, colorBounds);
269 offset->fX = bounds.left();
270 offset->fY = bounds.top();
274 void SkDisplacementMapEffect::computeFastBounds(const SkRect& src, SkRect* dst) const {
275 if (getColorInput()) {
276 getColorInput()->computeFastBounds(src, dst);
280 dst->outset(fScale * SK_ScalarHalf, fScale * SK_ScalarHalf);
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);
297 ///////////////////////////////////////////////////////////////////////////////
300 class GrGLDisplacementMapEffect : public GrGLFragmentProcessor {
302 GrGLDisplacementMapEffect(const GrBackendProcessorFactory&,
304 virtual ~GrGLDisplacementMapEffect();
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;
314 static inline void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder*);
316 virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE;
319 SkDisplacementMapEffect::ChannelSelectorType fXChannelSelector;
320 SkDisplacementMapEffect::ChannelSelectorType fYChannelSelector;
321 GrGLProgramDataManager::UniformHandle fScaleUni;
323 typedef GrGLFragmentProcessor INHERITED;
326 ///////////////////////////////////////////////////////////////////////////////
328 class GrDisplacementMapEffect : public GrFragmentProcessor {
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,
342 virtual ~GrDisplacementMapEffect();
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; }
351 typedef GrGLDisplacementMapEffect GLProcessor;
352 static const char* Name() { return "DisplacementMap"; }
354 virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
357 virtual bool onIsEqual(const GrProcessor&) const SK_OVERRIDE;
359 GrDisplacementMapEffect(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
360 SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
361 const SkVector& scale,
362 GrTexture* displacement, const SkMatrix& offsetMatrix,
365 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
367 GrCoordTransform fDisplacementTransform;
368 GrTextureAccess fDisplacementAccess;
369 GrCoordTransform fColorTransform;
370 GrTextureAccess fColorAccess;
371 SkDisplacementMapEffect::ChannelSelectorType fXChannelSelector;
372 SkDisplacementMapEffect::ChannelSelectorType fYChannelSelector;
375 typedef GrFragmentProcessor INHERITED;
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,
386 SkBitmap displacementBM = src;
387 SkIPoint displacementOffset = SkIPoint::Make(0, 0);
388 if (getDisplacementInput() &&
389 !getDisplacementInput()->getInputResultGPU(proxy, src, ctx, &displacementBM,
390 &displacementOffset)) {
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)) {
400 if (!this->applyCropRect(ctx, proxy, displacementBM,
401 &displacementOffset, &displBounds, &displacementBM)) {
404 if (!bounds.intersect(displBounds)) {
407 GrTexture* color = colorBM.getTexture();
408 GrTexture* displacement = displacementBM.getTexture();
409 GrContext* context = color->getContext();
412 desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
413 desc.fWidth = bounds.width();
414 desc.fHeight = bounds.height();
415 desc.fConfig = kSkia8888_GrPixelConfig;
417 GrAutoScratchTexture ast(context, desc);
418 if (NULL == ast.texture()) {
421 SkAutoTUnref<GrTexture> dst(ast.detach());
423 GrContext::AutoRenderTarget art(context, dst->asRenderTarget());
425 SkVector scale = SkVector::Make(fScale, fScale);
426 ctx.ctm().mapVectors(&scale, 1);
429 SkMatrix offsetMatrix = GrCoordTransform::MakeDivByTextureWHMatrix(displacement);
430 offsetMatrix.preTranslate(SkIntToScalar(colorOffset.fX - displacementOffset.fX),
431 SkIntToScalar(colorOffset.fY - displacementOffset.fY));
433 paint.addColorProcessor(
434 GrDisplacementMapEffect::Create(fXChannelSelector,
440 SkIRect colorBounds = bounds;
441 colorBounds.offset(-colorOffset);
442 GrContext::AutoMatrix am;
443 am.setIdentity(context);
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);
455 ///////////////////////////////////////////////////////////////////////////////
457 GrDisplacementMapEffect::GrDisplacementMapEffect(
458 SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
459 SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
460 const SkVector& scale,
461 GrTexture* displacement,
462 const SkMatrix& offsetMatrix,
464 : fDisplacementTransform(kLocal_GrCoordSet, offsetMatrix, displacement)
465 , fDisplacementAccess(displacement)
466 , fColorTransform(kLocal_GrCoordSet, color)
467 , fColorAccess(color)
468 , fXChannelSelector(xChannelSelector)
469 , fYChannelSelector(yChannelSelector)
471 this->addCoordTransform(&fDisplacementTransform);
472 this->addTextureAccess(&fDisplacementAccess);
473 this->addCoordTransform(&fColorTransform);
474 this->addTextureAccess(&fColorAccess);
475 this->setWillNotUseInputColor();
478 GrDisplacementMapEffect::~GrDisplacementMapEffect() {
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 &&
490 const GrBackendFragmentProcessorFactory& GrDisplacementMapEffect::getFactory() const {
491 return GrTBackendFragmentProcessorFactory<GrDisplacementMapEffect>::getInstance();
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.
504 ///////////////////////////////////////////////////////////////////////////////
506 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDisplacementMapEffect);
508 GrFragmentProcessor* GrDisplacementMapEffect::TestCreate(SkRandom* random,
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));
526 return GrDisplacementMapEffect::Create(xChannelSelector, yChannelSelector, scale,
527 textures[texIdxDispl], SkMatrix::I(),
528 textures[texIdxColor]);
531 ///////////////////////////////////////////////////////////////////////////////
533 GrGLDisplacementMapEffect::GrGLDisplacementMapEffect(const GrBackendProcessorFactory& factory,
534 const GrProcessor& proc)
536 , fXChannelSelector(proc.cast<GrDisplacementMapEffect>().xChannelSelector())
537 , fYChannelSelector(proc.cast<GrDisplacementMapEffect>().yChannelSelector()) {
540 GrGLDisplacementMapEffect::~GrGLDisplacementMapEffect() {
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);
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.10352e−5 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.
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");
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);
571 fsBuilder->codeAppendf("\t\tvec2 %s = %s + %s*(%s.",
572 cCoords, coords[1].c_str(), scaleUni, dColor);
574 switch (fXChannelSelector) {
575 case SkDisplacementMapEffect::kR_ChannelSelectorType:
576 fsBuilder->codeAppend("r");
578 case SkDisplacementMapEffect::kG_ChannelSelectorType:
579 fsBuilder->codeAppend("g");
581 case SkDisplacementMapEffect::kB_ChannelSelectorType:
582 fsBuilder->codeAppend("b");
584 case SkDisplacementMapEffect::kA_ChannelSelectorType:
585 fsBuilder->codeAppend("a");
587 case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
589 SkDEBUGFAIL("Unknown X channel selector");
592 switch (fYChannelSelector) {
593 case SkDisplacementMapEffect::kR_ChannelSelectorType:
594 fsBuilder->codeAppend("r");
596 case SkDisplacementMapEffect::kG_ChannelSelectorType:
597 fsBuilder->codeAppend("g");
599 case SkDisplacementMapEffect::kB_ChannelSelectorType:
600 fsBuilder->codeAppend("b");
602 case SkDisplacementMapEffect::kA_ChannelSelectorType:
603 fsBuilder->codeAppend("a");
605 case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
607 SkDEBUGFAIL("Unknown Y channel selector");
609 fsBuilder->codeAppend("-vec2(0.5));\t\t");
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");
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));
632 void GrGLDisplacementMapEffect::GenKey(const GrProcessor& proc,
633 const GrGLCaps&, GrProcessorKeyBuilder* b) {
634 const GrDisplacementMapEffect& displacementMap = proc.cast<GrDisplacementMapEffect>();
636 uint32_t xKey = displacementMap.xChannelSelector();
637 uint32_t yKey = displacementMap.yChannelSelector() << kChannelSelectorKeyBits;
639 b->add32(xKey | yKey);