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(GrGLFPBuilder*,
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"; }
355 virtual bool onIsEqual(const GrFragmentProcessor&) const SK_OVERRIDE;
357 virtual void onComputeInvariantOutput(InvariantOutput* inout) 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_GrSurfaceFlag | kNoStencil_GrSurfaceFlag;
413 desc.fWidth = bounds.width();
414 desc.fHeight = bounds.height();
415 desc.fConfig = kSkia8888_GrPixelConfig;
417 SkAutoTUnref<GrTexture> dst(
418 context->refScratchTexture(desc, GrContext::kApprox_ScratchTexMatch));
424 GrContext::AutoRenderTarget art(context, dst->asRenderTarget());
426 SkVector scale = SkVector::Make(fScale, fScale);
427 ctx.ctm().mapVectors(&scale, 1);
430 SkMatrix offsetMatrix = GrCoordTransform::MakeDivByTextureWHMatrix(displacement);
431 offsetMatrix.preTranslate(SkIntToScalar(colorOffset.fX - displacementOffset.fX),
432 SkIntToScalar(colorOffset.fY - displacementOffset.fY));
434 paint.addColorProcessor(
435 GrDisplacementMapEffect::Create(fXChannelSelector,
441 SkIRect colorBounds = bounds;
442 colorBounds.offset(-colorOffset);
443 GrContext::AutoMatrix am;
444 am.setIdentity(context);
446 matrix.setTranslate(-SkIntToScalar(colorBounds.x()),
447 -SkIntToScalar(colorBounds.y()));
448 context->concatMatrix(matrix);
449 context->drawRect(paint, SkRect::Make(colorBounds));
450 offset->fX = bounds.left();
451 offset->fY = bounds.top();
452 WrapTexture(dst, bounds.width(), bounds.height(), result);
456 ///////////////////////////////////////////////////////////////////////////////
458 GrDisplacementMapEffect::GrDisplacementMapEffect(
459 SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
460 SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
461 const SkVector& scale,
462 GrTexture* displacement,
463 const SkMatrix& offsetMatrix,
465 : fDisplacementTransform(kLocal_GrCoordSet, offsetMatrix, displacement)
466 , fDisplacementAccess(displacement)
467 , fColorTransform(kLocal_GrCoordSet, color)
468 , fColorAccess(color)
469 , fXChannelSelector(xChannelSelector)
470 , fYChannelSelector(yChannelSelector)
472 this->addCoordTransform(&fDisplacementTransform);
473 this->addTextureAccess(&fDisplacementAccess);
474 this->addCoordTransform(&fColorTransform);
475 this->addTextureAccess(&fColorAccess);
478 GrDisplacementMapEffect::~GrDisplacementMapEffect() {
481 bool GrDisplacementMapEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
482 const GrDisplacementMapEffect& s = sBase.cast<GrDisplacementMapEffect>();
483 return fXChannelSelector == s.fXChannelSelector &&
484 fYChannelSelector == s.fYChannelSelector &&
488 const GrBackendFragmentProcessorFactory& GrDisplacementMapEffect::getFactory() const {
489 return GrTBackendFragmentProcessorFactory<GrDisplacementMapEffect>::getInstance();
492 void GrDisplacementMapEffect::onComputeInvariantOutput(InvariantOutput* inout) const {
493 // Any displacement offset bringing a pixel out of bounds will output a color of (0,0,0,0),
494 // so the only way we'd get a constant alpha is if the input color image has a constant alpha
495 // and no displacement offset push any texture coordinates out of bounds OR if the constant
496 // alpha is 0. Since this isn't trivial to compute at this point, let's assume the output is
497 // not of constant color when a displacement effect is applied.
498 inout->setToUnknown(InvariantOutput::kWillNot_ReadInput);
501 ///////////////////////////////////////////////////////////////////////////////
503 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDisplacementMapEffect);
505 GrFragmentProcessor* GrDisplacementMapEffect::TestCreate(SkRandom* random,
507 const GrDrawTargetCaps&,
508 GrTexture* textures[]) {
509 int texIdxDispl = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
510 GrProcessorUnitTest::kAlphaTextureIdx;
511 int texIdxColor = random->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
512 GrProcessorUnitTest::kAlphaTextureIdx;
513 static const int kMaxComponent = 4;
514 SkDisplacementMapEffect::ChannelSelectorType xChannelSelector =
515 static_cast<SkDisplacementMapEffect::ChannelSelectorType>(
516 random->nextRangeU(1, kMaxComponent));
517 SkDisplacementMapEffect::ChannelSelectorType yChannelSelector =
518 static_cast<SkDisplacementMapEffect::ChannelSelectorType>(
519 random->nextRangeU(1, kMaxComponent));
520 SkVector scale = SkVector::Make(random->nextRangeScalar(0, 100.0f),
521 random->nextRangeScalar(0, 100.0f));
523 return GrDisplacementMapEffect::Create(xChannelSelector, yChannelSelector, scale,
524 textures[texIdxDispl], SkMatrix::I(),
525 textures[texIdxColor]);
528 ///////////////////////////////////////////////////////////////////////////////
530 GrGLDisplacementMapEffect::GrGLDisplacementMapEffect(const GrBackendProcessorFactory& factory,
531 const GrProcessor& proc)
533 , fXChannelSelector(proc.cast<GrDisplacementMapEffect>().xChannelSelector())
534 , fYChannelSelector(proc.cast<GrDisplacementMapEffect>().yChannelSelector()) {
537 GrGLDisplacementMapEffect::~GrGLDisplacementMapEffect() {
540 void GrGLDisplacementMapEffect::emitCode(GrGLFPBuilder* builder,
541 const GrFragmentProcessor&,
542 const GrProcessorKey& key,
543 const char* outputColor,
544 const char* inputColor,
545 const TransformedCoordsArray& coords,
546 const TextureSamplerArray& samplers) {
547 sk_ignore_unused_variable(inputColor);
549 fScaleUni = builder->addUniform(GrGLProgramBuilder::kFragment_Visibility,
550 kVec2f_GrSLType, "Scale");
551 const char* scaleUni = builder->getUniformCStr(fScaleUni);
552 const char* dColor = "dColor";
553 const char* cCoords = "cCoords";
554 const char* outOfBounds = "outOfBounds";
555 const char* nearZero = "1e-6"; // Since 6.10352e−5 is the smallest half float, use
556 // a number smaller than that to approximate 0, but
557 // leave room for 32-bit float GPU rounding errors.
559 GrGLFPFragmentBuilder* fsBuilder = builder->getFragmentShaderBuilder();
560 fsBuilder->codeAppendf("\t\tvec4 %s = ", dColor);
561 fsBuilder->appendTextureLookup(samplers[0], coords[0].c_str(), coords[0].getType());
562 fsBuilder->codeAppend(";\n");
564 // Unpremultiply the displacement
565 fsBuilder->codeAppendf("\t\t%s.rgb = (%s.a < %s) ? vec3(0.0) : clamp(%s.rgb / %s.a, 0.0, 1.0);",
566 dColor, dColor, nearZero, dColor, dColor);
568 fsBuilder->codeAppendf("\t\tvec2 %s = %s + %s*(%s.",
569 cCoords, coords[1].c_str(), scaleUni, dColor);
571 switch (fXChannelSelector) {
572 case SkDisplacementMapEffect::kR_ChannelSelectorType:
573 fsBuilder->codeAppend("r");
575 case SkDisplacementMapEffect::kG_ChannelSelectorType:
576 fsBuilder->codeAppend("g");
578 case SkDisplacementMapEffect::kB_ChannelSelectorType:
579 fsBuilder->codeAppend("b");
581 case SkDisplacementMapEffect::kA_ChannelSelectorType:
582 fsBuilder->codeAppend("a");
584 case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
586 SkDEBUGFAIL("Unknown X channel selector");
589 switch (fYChannelSelector) {
590 case SkDisplacementMapEffect::kR_ChannelSelectorType:
591 fsBuilder->codeAppend("r");
593 case SkDisplacementMapEffect::kG_ChannelSelectorType:
594 fsBuilder->codeAppend("g");
596 case SkDisplacementMapEffect::kB_ChannelSelectorType:
597 fsBuilder->codeAppend("b");
599 case SkDisplacementMapEffect::kA_ChannelSelectorType:
600 fsBuilder->codeAppend("a");
602 case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
604 SkDEBUGFAIL("Unknown Y channel selector");
606 fsBuilder->codeAppend("-vec2(0.5));\t\t");
608 // FIXME : This can be achieved with a "clamp to border" texture repeat mode and
609 // a 0 border color instead of computing if cCoords is out of bounds here.
610 fsBuilder->codeAppendf(
611 "bool %s = (%s.x < 0.0) || (%s.y < 0.0) || (%s.x > 1.0) || (%s.y > 1.0);\t\t",
612 outOfBounds, cCoords, cCoords, cCoords, cCoords);
613 fsBuilder->codeAppendf("%s = %s ? vec4(0.0) : ", outputColor, outOfBounds);
614 fsBuilder->appendTextureLookup(samplers[1], cCoords, coords[1].getType());
615 fsBuilder->codeAppend(";\n");
618 void GrGLDisplacementMapEffect::setData(const GrGLProgramDataManager& pdman,
619 const GrProcessor& proc) {
620 const GrDisplacementMapEffect& displacementMap = proc.cast<GrDisplacementMapEffect>();
621 GrTexture* colorTex = displacementMap.texture(1);
622 SkScalar scaleX = SkScalarDiv(displacementMap.scale().fX, SkIntToScalar(colorTex->width()));
623 SkScalar scaleY = SkScalarDiv(displacementMap.scale().fY, SkIntToScalar(colorTex->height()));
624 pdman.set2f(fScaleUni, SkScalarToFloat(scaleX),
625 colorTex->origin() == kTopLeft_GrSurfaceOrigin ?
626 SkScalarToFloat(scaleY) : SkScalarToFloat(-scaleY));
629 void GrGLDisplacementMapEffect::GenKey(const GrProcessor& proc,
630 const GrGLCaps&, GrProcessorKeyBuilder* b) {
631 const GrDisplacementMapEffect& displacementMap = proc.cast<GrDisplacementMapEffect>();
633 uint32_t xKey = displacementMap.xChannelSelector();
634 uint32_t yKey = displacementMap.yChannelSelector() << kChannelSelectorKeyBits;
636 b->add32(xKey | yKey);