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"
10 #include "SkReadBuffer.h"
11 #include "SkWriteBuffer.h"
12 #include "SkUnPreMultiply.h"
13 #include "SkColorPriv.h"
15 #include "GrContext.h"
16 #include "GrDrawContext.h"
17 #include "GrCoordTransform.h"
18 #include "GrInvariantOutput.h"
19 #include "effects/GrTextureDomain.h"
20 #include "glsl/GrGLSLFragmentProcessor.h"
21 #include "glsl/GrGLSLFragmentShaderBuilder.h"
22 #include "glsl/GrGLSLProgramBuilder.h"
23 #include "glsl/GrGLSLProgramDataManager.h"
28 #define kChannelSelectorKeyBits 3; // Max value is 4, so 3 bits are required at most
30 template<SkDisplacementMapEffect::ChannelSelectorType type>
31 uint32_t getValue(SkColor, const SkUnPreMultiply::Scale*) {
32 SkDEBUGFAIL("Unknown channel selector");
36 template<> uint32_t getValue<SkDisplacementMapEffect::kR_ChannelSelectorType>(
37 SkColor l, const SkUnPreMultiply::Scale* table) {
38 return SkUnPreMultiply::ApplyScale(table[SkGetPackedA32(l)], SkGetPackedR32(l));
41 template<> uint32_t getValue<SkDisplacementMapEffect::kG_ChannelSelectorType>(
42 SkColor l, const SkUnPreMultiply::Scale* table) {
43 return SkUnPreMultiply::ApplyScale(table[SkGetPackedA32(l)], SkGetPackedG32(l));
46 template<> uint32_t getValue<SkDisplacementMapEffect::kB_ChannelSelectorType>(
47 SkColor l, const SkUnPreMultiply::Scale* table) {
48 return SkUnPreMultiply::ApplyScale(table[SkGetPackedA32(l)], SkGetPackedB32(l));
51 template<> uint32_t getValue<SkDisplacementMapEffect::kA_ChannelSelectorType>(
52 SkColor l, const SkUnPreMultiply::Scale*) {
53 return SkGetPackedA32(l);
56 template<SkDisplacementMapEffect::ChannelSelectorType typeX,
57 SkDisplacementMapEffect::ChannelSelectorType typeY>
58 void computeDisplacement(const SkVector& scale, SkBitmap* dst,
59 SkBitmap* displ, const SkIPoint& offset,
61 const SkIRect& bounds)
63 static const SkScalar Inv8bit = SkScalarInvert(255);
64 const int srcW = src->width();
65 const int srcH = src->height();
66 const SkVector scaleForColor = SkVector::Make(SkScalarMul(scale.fX, Inv8bit),
67 SkScalarMul(scale.fY, Inv8bit));
68 const SkVector scaleAdj = SkVector::Make(SK_ScalarHalf - SkScalarMul(scale.fX, SK_ScalarHalf),
69 SK_ScalarHalf - SkScalarMul(scale.fY, SK_ScalarHalf));
70 const SkUnPreMultiply::Scale* table = SkUnPreMultiply::GetScaleTable();
71 SkPMColor* dstPtr = dst->getAddr32(0, 0);
72 for (int y = bounds.top(); y < bounds.bottom(); ++y) {
73 const SkPMColor* displPtr = displ->getAddr32(bounds.left() + offset.fX,
75 for (int x = bounds.left(); x < bounds.right(); ++x, ++displPtr) {
76 const SkScalar displX = SkScalarMul(scaleForColor.fX,
77 SkIntToScalar(getValue<typeX>(*displPtr, table))) + scaleAdj.fX;
78 const SkScalar displY = SkScalarMul(scaleForColor.fY,
79 SkIntToScalar(getValue<typeY>(*displPtr, table))) + scaleAdj.fY;
80 // Truncate the displacement values
81 const int srcX = x + SkScalarTruncToInt(displX);
82 const int srcY = y + SkScalarTruncToInt(displY);
83 *dstPtr++ = ((srcX < 0) || (srcX >= srcW) || (srcY < 0) || (srcY >= srcH)) ?
84 0 : *(src->getAddr32(srcX, srcY));
89 template<SkDisplacementMapEffect::ChannelSelectorType typeX>
90 void computeDisplacement(SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
91 const SkVector& scale, SkBitmap* dst,
92 SkBitmap* displ, const SkIPoint& offset,
94 const SkIRect& bounds)
96 switch (yChannelSelector) {
97 case SkDisplacementMapEffect::kR_ChannelSelectorType:
98 computeDisplacement<typeX, SkDisplacementMapEffect::kR_ChannelSelectorType>(
99 scale, dst, displ, offset, src, bounds);
101 case SkDisplacementMapEffect::kG_ChannelSelectorType:
102 computeDisplacement<typeX, SkDisplacementMapEffect::kG_ChannelSelectorType>(
103 scale, dst, displ, offset, src, bounds);
105 case SkDisplacementMapEffect::kB_ChannelSelectorType:
106 computeDisplacement<typeX, SkDisplacementMapEffect::kB_ChannelSelectorType>(
107 scale, dst, displ, offset, src, bounds);
109 case SkDisplacementMapEffect::kA_ChannelSelectorType:
110 computeDisplacement<typeX, SkDisplacementMapEffect::kA_ChannelSelectorType>(
111 scale, dst, displ, offset, src, bounds);
113 case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
115 SkDEBUGFAIL("Unknown Y channel selector");
119 void computeDisplacement(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
120 SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
121 const SkVector& scale, SkBitmap* dst,
122 SkBitmap* displ, const SkIPoint& offset,
124 const SkIRect& bounds)
126 switch (xChannelSelector) {
127 case SkDisplacementMapEffect::kR_ChannelSelectorType:
128 computeDisplacement<SkDisplacementMapEffect::kR_ChannelSelectorType>(
129 yChannelSelector, scale, dst, displ, offset, src, bounds);
131 case SkDisplacementMapEffect::kG_ChannelSelectorType:
132 computeDisplacement<SkDisplacementMapEffect::kG_ChannelSelectorType>(
133 yChannelSelector, scale, dst, displ, offset, src, bounds);
135 case SkDisplacementMapEffect::kB_ChannelSelectorType:
136 computeDisplacement<SkDisplacementMapEffect::kB_ChannelSelectorType>(
137 yChannelSelector, scale, dst, displ, offset, src, bounds);
139 case SkDisplacementMapEffect::kA_ChannelSelectorType:
140 computeDisplacement<SkDisplacementMapEffect::kA_ChannelSelectorType>(
141 yChannelSelector, scale, dst, displ, offset, src, bounds);
143 case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
145 SkDEBUGFAIL("Unknown X channel selector");
149 bool channel_selector_type_is_valid(SkDisplacementMapEffect::ChannelSelectorType cst) {
151 case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
152 case SkDisplacementMapEffect::kR_ChannelSelectorType:
153 case SkDisplacementMapEffect::kG_ChannelSelectorType:
154 case SkDisplacementMapEffect::kB_ChannelSelectorType:
155 case SkDisplacementMapEffect::kA_ChannelSelectorType:
165 ///////////////////////////////////////////////////////////////////////////////
167 SkDisplacementMapEffect* SkDisplacementMapEffect::Create(ChannelSelectorType xChannelSelector,
168 ChannelSelectorType yChannelSelector,
170 SkImageFilter* displacement,
171 SkImageFilter* color,
172 const CropRect* cropRect) {
173 if (!channel_selector_type_is_valid(xChannelSelector) ||
174 !channel_selector_type_is_valid(yChannelSelector)) {
178 SkImageFilter* inputs[2] = { displacement, color };
179 return new SkDisplacementMapEffect(xChannelSelector, yChannelSelector, scale, inputs, cropRect);
182 SkDisplacementMapEffect::SkDisplacementMapEffect(ChannelSelectorType xChannelSelector,
183 ChannelSelectorType yChannelSelector,
185 SkImageFilter* inputs[2],
186 const CropRect* cropRect)
187 : INHERITED(2, inputs, cropRect)
188 , fXChannelSelector(xChannelSelector)
189 , fYChannelSelector(yChannelSelector)
194 SkDisplacementMapEffect::~SkDisplacementMapEffect() {
197 SkFlattenable* SkDisplacementMapEffect::CreateProc(SkReadBuffer& buffer) {
198 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 2);
199 ChannelSelectorType xsel = (ChannelSelectorType)buffer.readInt();
200 ChannelSelectorType ysel = (ChannelSelectorType)buffer.readInt();
201 SkScalar scale = buffer.readScalar();
202 return Create(xsel, ysel, scale, common.getInput(0), common.getInput(1), &common.cropRect());
205 void SkDisplacementMapEffect::flatten(SkWriteBuffer& buffer) const {
206 this->INHERITED::flatten(buffer);
207 buffer.writeInt((int) fXChannelSelector);
208 buffer.writeInt((int) fYChannelSelector);
209 buffer.writeScalar(fScale);
212 bool SkDisplacementMapEffect::onFilterImage(Proxy* proxy,
216 SkIPoint* offset) const {
217 SkBitmap displ = src, color = src;
218 SkIPoint colorOffset = SkIPoint::Make(0, 0), displOffset = SkIPoint::Make(0, 0);
219 if (!this->filterInput(1, proxy, src, ctx, &color, &colorOffset) ||
220 !this->filterInput(0, proxy, src, ctx, &displ, &displOffset)) {
223 if ((displ.colorType() != kN32_SkColorType) ||
224 (color.colorType() != kN32_SkColorType)) {
228 // Since computeDisplacement does bounds checking on color pixel access, we don't need to pad
229 // the color bitmap to bounds here.
230 if (!this->applyCropRect(ctx, color, colorOffset, &bounds)) {
234 if (!this->applyCropRect(ctx, proxy, displ, &displOffset, &displBounds, &displ)) {
237 if (!bounds.intersect(displBounds)) {
240 SkAutoLockPixels alp_displacement(displ), alp_color(color);
241 if (!displ.getPixels() || !color.getPixels()) {
245 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
249 *dst = device->accessBitmap(false);
250 SkAutoLockPixels alp_dst(*dst);
252 SkVector scale = SkVector::Make(fScale, fScale);
253 ctx.ctm().mapVectors(&scale, 1);
254 SkIRect colorBounds = bounds;
255 colorBounds.offset(-colorOffset);
257 computeDisplacement(fXChannelSelector, fYChannelSelector, scale, dst,
258 &displ, colorOffset - displOffset, &color, colorBounds);
260 offset->fX = bounds.left();
261 offset->fY = bounds.top();
265 void SkDisplacementMapEffect::computeFastBounds(const SkRect& src, SkRect* dst) const {
266 if (this->getColorInput()) {
267 this->getColorInput()->computeFastBounds(src, dst);
271 dst->outset(fScale * SK_ScalarHalf, fScale * SK_ScalarHalf);
274 bool SkDisplacementMapEffect::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
275 SkIRect* dst) const {
276 SkIRect bounds = src;
277 SkVector scale = SkVector::Make(fScale, fScale);
278 ctm.mapVectors(&scale, 1);
279 bounds.outset(SkScalarCeilToInt(scale.fX * SK_ScalarHalf),
280 SkScalarCeilToInt(scale.fY * SK_ScalarHalf));
281 if (this->getColorInput()) {
282 return this->getColorInput()->filterBounds(bounds, ctm, dst);
288 #ifndef SK_IGNORE_TO_STRING
289 void SkDisplacementMapEffect::toString(SkString* str) const {
290 str->appendf("SkDisplacementMapEffect: (");
291 str->appendf("scale: %f ", fScale);
292 str->appendf("displacement: (");
293 if (this->getDisplacementInput()) {
294 this->getDisplacementInput()->toString(str);
296 str->appendf(") color: (");
297 if (this->getColorInput()) {
298 this->getColorInput()->toString(str);
304 ///////////////////////////////////////////////////////////////////////////////
307 class GrGLDisplacementMapEffect : public GrGLSLFragmentProcessor {
309 GrGLDisplacementMapEffect(const GrProcessor&);
310 virtual ~GrGLDisplacementMapEffect();
312 virtual void emitCode(EmitArgs&) override;
314 static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*);
316 const GrTextureDomain::GLDomain& glDomain() const { return fGLDomain; }
319 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
322 SkDisplacementMapEffect::ChannelSelectorType fXChannelSelector;
323 SkDisplacementMapEffect::ChannelSelectorType fYChannelSelector;
324 GrGLSLProgramDataManager::UniformHandle fScaleUni;
325 GrTextureDomain::GLDomain fGLDomain;
327 typedef GrGLSLFragmentProcessor INHERITED;
330 ///////////////////////////////////////////////////////////////////////////////
332 class GrDisplacementMapEffect : public GrFragmentProcessor {
334 static GrFragmentProcessor* Create(
335 SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
336 SkDisplacementMapEffect::ChannelSelectorType yChannelSelector, SkVector scale,
337 GrTexture* displacement, const SkMatrix& offsetMatrix, GrTexture* color,
338 const SkISize& colorDimensions) {
339 return new GrDisplacementMapEffect(xChannelSelector, yChannelSelector, scale, displacement,
340 offsetMatrix, color, colorDimensions);
343 virtual ~GrDisplacementMapEffect();
345 SkDisplacementMapEffect::ChannelSelectorType xChannelSelector() const
346 { return fXChannelSelector; }
347 SkDisplacementMapEffect::ChannelSelectorType yChannelSelector() const
348 { return fYChannelSelector; }
349 const SkVector& scale() const { return fScale; }
351 const char* name() const override { return "DisplacementMap"; }
352 const GrTextureDomain& domain() const { return fDomain; }
355 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
356 return new GrGLDisplacementMapEffect(*this);
359 virtual void onGetGLSLProcessorKey(const GrGLSLCaps& caps,
360 GrProcessorKeyBuilder* b) const override {
361 GrGLDisplacementMapEffect::GenKey(*this, caps, b);
364 bool onIsEqual(const GrFragmentProcessor&) const override;
366 void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
368 GrDisplacementMapEffect(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
369 SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
370 const SkVector& scale,
371 GrTexture* displacement, const SkMatrix& offsetMatrix,
373 const SkISize& colorDimensions);
375 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
377 GrCoordTransform fDisplacementTransform;
378 GrTextureAccess fDisplacementAccess;
379 GrCoordTransform fColorTransform;
380 GrTextureDomain fDomain;
381 GrTextureAccess fColorAccess;
382 SkDisplacementMapEffect::ChannelSelectorType fXChannelSelector;
383 SkDisplacementMapEffect::ChannelSelectorType fYChannelSelector;
386 typedef GrFragmentProcessor INHERITED;
389 bool SkDisplacementMapEffect::filterImageGPU(Proxy* proxy, const SkBitmap& src, const Context& ctx,
390 SkBitmap* result, SkIPoint* offset) const {
391 SkBitmap colorBM = src;
392 SkIPoint colorOffset = SkIPoint::Make(0, 0);
393 if (!this->filterInputGPU(1, proxy, src, ctx, &colorBM, &colorOffset)) {
396 SkBitmap displacementBM = src;
397 SkIPoint displacementOffset = SkIPoint::Make(0, 0);
398 if (!this->filterInputGPU(0, proxy, src, ctx, &displacementBM, &displacementOffset)) {
402 // Since GrDisplacementMapEffect does bounds checking on color pixel access, we don't need to
403 // pad the color bitmap to bounds here.
404 if (!this->applyCropRect(ctx, colorBM, colorOffset, &bounds)) {
408 if (!this->applyCropRect(ctx, proxy, displacementBM,
409 &displacementOffset, &displBounds, &displacementBM)) {
412 if (!bounds.intersect(displBounds)) {
415 GrTexture* color = colorBM.getTexture();
416 GrTexture* displacement = displacementBM.getTexture();
417 GrContext* context = color->getContext();
420 desc.fFlags = kRenderTarget_GrSurfaceFlag;
421 desc.fWidth = bounds.width();
422 desc.fHeight = bounds.height();
423 desc.fConfig = kSkia8888_GrPixelConfig;
425 auto constraint = GrTextureProvider::FromImageFilter(ctx.sizeConstraint());
426 SkAutoTUnref<GrTexture> dst(context->textureProvider()->createTexture(desc, constraint));
432 SkVector scale = SkVector::Make(fScale, fScale);
433 ctx.ctm().mapVectors(&scale, 1);
436 SkMatrix offsetMatrix = GrCoordTransform::MakeDivByTextureWHMatrix(displacement);
437 offsetMatrix.preTranslate(SkIntToScalar(colorOffset.fX - displacementOffset.fX),
438 SkIntToScalar(colorOffset.fY - displacementOffset.fY));
440 paint.addColorFragmentProcessor(
441 GrDisplacementMapEffect::Create(fXChannelSelector,
447 colorBM.dimensions()))->unref();
448 paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
449 SkIRect colorBounds = bounds;
450 colorBounds.offset(-colorOffset);
452 matrix.setTranslate(-SkIntToScalar(colorBounds.x()),
453 -SkIntToScalar(colorBounds.y()));
455 SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(dst->asRenderTarget()));
460 drawContext->drawRect(GrClip::WideOpen(), paint, matrix, SkRect::Make(colorBounds));
461 offset->fX = bounds.left();
462 offset->fY = bounds.top();
463 WrapTexture(dst, bounds.width(), bounds.height(), result);
467 ///////////////////////////////////////////////////////////////////////////////
469 GrDisplacementMapEffect::GrDisplacementMapEffect(
470 SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
471 SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
472 const SkVector& scale,
473 GrTexture* displacement,
474 const SkMatrix& offsetMatrix,
476 const SkISize& colorDimensions)
477 : fDisplacementTransform(kLocal_GrCoordSet, offsetMatrix, displacement,
478 GrTextureParams::kNone_FilterMode)
479 , fDisplacementAccess(displacement)
480 , fColorTransform(kLocal_GrCoordSet, color, GrTextureParams::kNone_FilterMode)
481 , fDomain(GrTextureDomain::MakeTexelDomain(color, SkIRect::MakeSize(colorDimensions)),
482 GrTextureDomain::kDecal_Mode)
483 , fColorAccess(color)
484 , fXChannelSelector(xChannelSelector)
485 , fYChannelSelector(yChannelSelector)
487 this->initClassID<GrDisplacementMapEffect>();
488 this->addCoordTransform(&fDisplacementTransform);
489 this->addTextureAccess(&fDisplacementAccess);
490 this->addCoordTransform(&fColorTransform);
491 this->addTextureAccess(&fColorAccess);
494 GrDisplacementMapEffect::~GrDisplacementMapEffect() {
497 bool GrDisplacementMapEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
498 const GrDisplacementMapEffect& s = sBase.cast<GrDisplacementMapEffect>();
499 return fXChannelSelector == s.fXChannelSelector &&
500 fYChannelSelector == s.fYChannelSelector &&
504 void GrDisplacementMapEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
505 // Any displacement offset bringing a pixel out of bounds will output a color of (0,0,0,0),
506 // so the only way we'd get a constant alpha is if the input color image has a constant alpha
507 // and no displacement offset push any texture coordinates out of bounds OR if the constant
508 // alpha is 0. Since this isn't trivial to compute at this point, let's assume the output is
509 // not of constant color when a displacement effect is applied.
510 inout->setToUnknown(GrInvariantOutput::kWillNot_ReadInput);
513 ///////////////////////////////////////////////////////////////////////////////
515 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDisplacementMapEffect);
517 const GrFragmentProcessor* GrDisplacementMapEffect::TestCreate(GrProcessorTestData* d) {
518 int texIdxDispl = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
519 GrProcessorUnitTest::kAlphaTextureIdx;
520 int texIdxColor = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
521 GrProcessorUnitTest::kAlphaTextureIdx;
522 static const int kMaxComponent = 4;
523 SkDisplacementMapEffect::ChannelSelectorType xChannelSelector =
524 static_cast<SkDisplacementMapEffect::ChannelSelectorType>(
525 d->fRandom->nextRangeU(1, kMaxComponent));
526 SkDisplacementMapEffect::ChannelSelectorType yChannelSelector =
527 static_cast<SkDisplacementMapEffect::ChannelSelectorType>(
528 d->fRandom->nextRangeU(1, kMaxComponent));
529 SkVector scale = SkVector::Make(d->fRandom->nextRangeScalar(0, 100.0f),
530 d->fRandom->nextRangeScalar(0, 100.0f));
531 SkISize colorDimensions;
532 colorDimensions.fWidth = d->fRandom->nextRangeU(0, d->fTextures[texIdxColor]->width());
533 colorDimensions.fHeight = d->fRandom->nextRangeU(0, d->fTextures[texIdxColor]->height());
534 return GrDisplacementMapEffect::Create(xChannelSelector, yChannelSelector, scale,
535 d->fTextures[texIdxDispl], SkMatrix::I(),
536 d->fTextures[texIdxColor], colorDimensions);
539 ///////////////////////////////////////////////////////////////////////////////
541 GrGLDisplacementMapEffect::GrGLDisplacementMapEffect(const GrProcessor& proc)
542 : fXChannelSelector(proc.cast<GrDisplacementMapEffect>().xChannelSelector())
543 , fYChannelSelector(proc.cast<GrDisplacementMapEffect>().yChannelSelector()) {
546 GrGLDisplacementMapEffect::~GrGLDisplacementMapEffect() {
549 void GrGLDisplacementMapEffect::emitCode(EmitArgs& args) {
550 const GrTextureDomain& domain = args.fFp.cast<GrDisplacementMapEffect>().domain();
552 fScaleUni = args.fBuilder->addUniform(GrGLSLProgramBuilder::kFragment_Visibility,
553 kVec2f_GrSLType, kDefault_GrSLPrecision, "Scale");
554 const char* scaleUni = args.fBuilder->getUniformCStr(fScaleUni);
555 const char* dColor = "dColor";
556 const char* cCoords = "cCoords";
557 const char* nearZero = "1e-6"; // Since 6.10352e−5 is the smallest half float, use
558 // a number smaller than that to approximate 0, but
559 // leave room for 32-bit float GPU rounding errors.
561 GrGLSLFragmentBuilder* fragBuilder = args.fFragBuilder;
562 fragBuilder->codeAppendf("\t\tvec4 %s = ", dColor);
563 fragBuilder->appendTextureLookup(args.fSamplers[0], args.fCoords[0].c_str(),
564 args.fCoords[0].getType());
565 fragBuilder->codeAppend(";\n");
567 // Unpremultiply the displacement
568 fragBuilder->codeAppendf(
569 "\t\t%s.rgb = (%s.a < %s) ? vec3(0.0) : clamp(%s.rgb / %s.a, 0.0, 1.0);",
570 dColor, dColor, nearZero, dColor, dColor);
571 SkString coords2D = fragBuilder->ensureFSCoords2D(args.fCoords, 1);
572 fragBuilder->codeAppendf("\t\tvec2 %s = %s + %s*(%s.",
573 cCoords, coords2D.c_str(), scaleUni, dColor);
575 switch (fXChannelSelector) {
576 case SkDisplacementMapEffect::kR_ChannelSelectorType:
577 fragBuilder->codeAppend("r");
579 case SkDisplacementMapEffect::kG_ChannelSelectorType:
580 fragBuilder->codeAppend("g");
582 case SkDisplacementMapEffect::kB_ChannelSelectorType:
583 fragBuilder->codeAppend("b");
585 case SkDisplacementMapEffect::kA_ChannelSelectorType:
586 fragBuilder->codeAppend("a");
588 case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
590 SkDEBUGFAIL("Unknown X channel selector");
593 switch (fYChannelSelector) {
594 case SkDisplacementMapEffect::kR_ChannelSelectorType:
595 fragBuilder->codeAppend("r");
597 case SkDisplacementMapEffect::kG_ChannelSelectorType:
598 fragBuilder->codeAppend("g");
600 case SkDisplacementMapEffect::kB_ChannelSelectorType:
601 fragBuilder->codeAppend("b");
603 case SkDisplacementMapEffect::kA_ChannelSelectorType:
604 fragBuilder->codeAppend("a");
606 case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
608 SkDEBUGFAIL("Unknown Y channel selector");
610 fragBuilder->codeAppend("-vec2(0.5));\t\t");
612 fGLDomain.sampleTexture(fragBuilder,
618 fragBuilder->codeAppend(";\n");
621 void GrGLDisplacementMapEffect::onSetData(const GrGLSLProgramDataManager& pdman,
622 const GrProcessor& proc) {
623 const GrDisplacementMapEffect& displacementMap = proc.cast<GrDisplacementMapEffect>();
624 GrTexture* colorTex = displacementMap.texture(1);
625 SkScalar scaleX = displacementMap.scale().fX / colorTex->width();
626 SkScalar scaleY = displacementMap.scale().fY / colorTex->height();
627 pdman.set2f(fScaleUni, SkScalarToFloat(scaleX),
628 colorTex->origin() == kTopLeft_GrSurfaceOrigin ?
629 SkScalarToFloat(scaleY) : SkScalarToFloat(-scaleY));
630 fGLDomain.setData(pdman, displacementMap.domain(), colorTex->origin());
633 void GrGLDisplacementMapEffect::GenKey(const GrProcessor& proc,
634 const GrGLSLCaps&, GrProcessorKeyBuilder* b) {
635 const GrDisplacementMapEffect& displacementMap = proc.cast<GrDisplacementMapEffect>();
637 uint32_t xKey = displacementMap.xChannelSelector();
638 uint32_t yKey = displacementMap.yChannelSelector() << kChannelSelectorKeyBits;
640 b->add32(xKey | yKey);