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 "SkDevice.h"
10 #include "SkReadBuffer.h"
11 #include "SkWriteBuffer.h"
12 #include "SkUnPreMultiply.h"
13 #include "SkColorPriv.h"
14 #if SK_SUPPORT_GPU
15 #include "GrContext.h"
16 #include "GrDrawContext.h"
17 #include "GrCoordTransform.h"
18 #include "GrInvariantOutput.h"
19 #include "SkGr.h"
20 #include "effects/GrTextureDomain.h"
21 #include "glsl/GrGLSLFragmentProcessor.h"
22 #include "glsl/GrGLSLFragmentShaderBuilder.h"
23 #include "glsl/GrGLSLProgramDataManager.h"
24 #include "glsl/GrGLSLUniformHandler.h"
25 #endif
26
27 namespace {
28
29 #define kChannelSelectorKeyBits 3; // Max value is 4, so 3 bits are required at most
30
31 template<SkDisplacementMapEffect::ChannelSelectorType type>
getValue(SkColor,const SkUnPreMultiply::Scale *)32 uint32_t getValue(SkColor, const SkUnPreMultiply::Scale*) {
33 SkDEBUGFAIL("Unknown channel selector");
34 return 0;
35 }
36
getValue(SkColor l,const SkUnPreMultiply::Scale * table)37 template<> uint32_t getValue<SkDisplacementMapEffect::kR_ChannelSelectorType>(
38 SkColor l, const SkUnPreMultiply::Scale* table) {
39 return SkUnPreMultiply::ApplyScale(table[SkGetPackedA32(l)], SkGetPackedR32(l));
40 }
41
getValue(SkColor l,const SkUnPreMultiply::Scale * table)42 template<> uint32_t getValue<SkDisplacementMapEffect::kG_ChannelSelectorType>(
43 SkColor l, const SkUnPreMultiply::Scale* table) {
44 return SkUnPreMultiply::ApplyScale(table[SkGetPackedA32(l)], SkGetPackedG32(l));
45 }
46
getValue(SkColor l,const SkUnPreMultiply::Scale * table)47 template<> uint32_t getValue<SkDisplacementMapEffect::kB_ChannelSelectorType>(
48 SkColor l, const SkUnPreMultiply::Scale* table) {
49 return SkUnPreMultiply::ApplyScale(table[SkGetPackedA32(l)], SkGetPackedB32(l));
50 }
51
getValue(SkColor l,const SkUnPreMultiply::Scale *)52 template<> uint32_t getValue<SkDisplacementMapEffect::kA_ChannelSelectorType>(
53 SkColor l, const SkUnPreMultiply::Scale*) {
54 return SkGetPackedA32(l);
55 }
56
57 template<SkDisplacementMapEffect::ChannelSelectorType typeX,
58 SkDisplacementMapEffect::ChannelSelectorType typeY>
computeDisplacement(const SkVector & scale,SkBitmap * dst,SkBitmap * displ,const SkIPoint & offset,SkBitmap * src,const SkIRect & bounds)59 void computeDisplacement(const SkVector& scale, SkBitmap* dst,
60 SkBitmap* displ, const SkIPoint& offset,
61 SkBitmap* src,
62 const SkIRect& bounds)
63 {
64 static const SkScalar Inv8bit = SkScalarInvert(255);
65 const int srcW = src->width();
66 const int srcH = src->height();
67 const SkVector scaleForColor = SkVector::Make(SkScalarMul(scale.fX, Inv8bit),
68 SkScalarMul(scale.fY, Inv8bit));
69 const SkVector scaleAdj = SkVector::Make(SK_ScalarHalf - SkScalarMul(scale.fX, SK_ScalarHalf),
70 SK_ScalarHalf - SkScalarMul(scale.fY, SK_ScalarHalf));
71 const SkUnPreMultiply::Scale* table = SkUnPreMultiply::GetScaleTable();
72 SkPMColor* dstPtr = dst->getAddr32(0, 0);
73 for (int y = bounds.top(); y < bounds.bottom(); ++y) {
74 const SkPMColor* displPtr = displ->getAddr32(bounds.left() + offset.fX,
75 y + offset.fY);
76 for (int x = bounds.left(); x < bounds.right(); ++x, ++displPtr) {
77 const SkScalar displX = SkScalarMul(scaleForColor.fX,
78 SkIntToScalar(getValue<typeX>(*displPtr, table))) + scaleAdj.fX;
79 const SkScalar displY = SkScalarMul(scaleForColor.fY,
80 SkIntToScalar(getValue<typeY>(*displPtr, table))) + scaleAdj.fY;
81 // Truncate the displacement values
82 const int srcX = x + SkScalarTruncToInt(displX);
83 const int srcY = y + SkScalarTruncToInt(displY);
84 *dstPtr++ = ((srcX < 0) || (srcX >= srcW) || (srcY < 0) || (srcY >= srcH)) ?
85 0 : *(src->getAddr32(srcX, srcY));
86 }
87 }
88 }
89
90 template<SkDisplacementMapEffect::ChannelSelectorType typeX>
computeDisplacement(SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,const SkVector & scale,SkBitmap * dst,SkBitmap * displ,const SkIPoint & offset,SkBitmap * src,const SkIRect & bounds)91 void computeDisplacement(SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
92 const SkVector& scale, SkBitmap* dst,
93 SkBitmap* displ, const SkIPoint& offset,
94 SkBitmap* src,
95 const SkIRect& bounds)
96 {
97 switch (yChannelSelector) {
98 case SkDisplacementMapEffect::kR_ChannelSelectorType:
99 computeDisplacement<typeX, SkDisplacementMapEffect::kR_ChannelSelectorType>(
100 scale, dst, displ, offset, src, bounds);
101 break;
102 case SkDisplacementMapEffect::kG_ChannelSelectorType:
103 computeDisplacement<typeX, SkDisplacementMapEffect::kG_ChannelSelectorType>(
104 scale, dst, displ, offset, src, bounds);
105 break;
106 case SkDisplacementMapEffect::kB_ChannelSelectorType:
107 computeDisplacement<typeX, SkDisplacementMapEffect::kB_ChannelSelectorType>(
108 scale, dst, displ, offset, src, bounds);
109 break;
110 case SkDisplacementMapEffect::kA_ChannelSelectorType:
111 computeDisplacement<typeX, SkDisplacementMapEffect::kA_ChannelSelectorType>(
112 scale, dst, displ, offset, src, bounds);
113 break;
114 case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
115 default:
116 SkDEBUGFAIL("Unknown Y channel selector");
117 }
118 }
119
computeDisplacement(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,const SkVector & scale,SkBitmap * dst,SkBitmap * displ,const SkIPoint & offset,SkBitmap * src,const SkIRect & bounds)120 void computeDisplacement(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
121 SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
122 const SkVector& scale, SkBitmap* dst,
123 SkBitmap* displ, const SkIPoint& offset,
124 SkBitmap* src,
125 const SkIRect& bounds)
126 {
127 switch (xChannelSelector) {
128 case SkDisplacementMapEffect::kR_ChannelSelectorType:
129 computeDisplacement<SkDisplacementMapEffect::kR_ChannelSelectorType>(
130 yChannelSelector, scale, dst, displ, offset, src, bounds);
131 break;
132 case SkDisplacementMapEffect::kG_ChannelSelectorType:
133 computeDisplacement<SkDisplacementMapEffect::kG_ChannelSelectorType>(
134 yChannelSelector, scale, dst, displ, offset, src, bounds);
135 break;
136 case SkDisplacementMapEffect::kB_ChannelSelectorType:
137 computeDisplacement<SkDisplacementMapEffect::kB_ChannelSelectorType>(
138 yChannelSelector, scale, dst, displ, offset, src, bounds);
139 break;
140 case SkDisplacementMapEffect::kA_ChannelSelectorType:
141 computeDisplacement<SkDisplacementMapEffect::kA_ChannelSelectorType>(
142 yChannelSelector, scale, dst, displ, offset, src, bounds);
143 break;
144 case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
145 default:
146 SkDEBUGFAIL("Unknown X channel selector");
147 }
148 }
149
channel_selector_type_is_valid(SkDisplacementMapEffect::ChannelSelectorType cst)150 bool channel_selector_type_is_valid(SkDisplacementMapEffect::ChannelSelectorType cst) {
151 switch (cst) {
152 case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
153 case SkDisplacementMapEffect::kR_ChannelSelectorType:
154 case SkDisplacementMapEffect::kG_ChannelSelectorType:
155 case SkDisplacementMapEffect::kB_ChannelSelectorType:
156 case SkDisplacementMapEffect::kA_ChannelSelectorType:
157 return true;
158 default:
159 break;
160 }
161 return false;
162 }
163
164 } // end namespace
165
166 ///////////////////////////////////////////////////////////////////////////////
167
Create(ChannelSelectorType xChannelSelector,ChannelSelectorType yChannelSelector,SkScalar scale,SkImageFilter * displacement,SkImageFilter * color,const CropRect * cropRect)168 SkImageFilter* SkDisplacementMapEffect::Create(ChannelSelectorType xChannelSelector,
169 ChannelSelectorType yChannelSelector,
170 SkScalar scale,
171 SkImageFilter* displacement,
172 SkImageFilter* color,
173 const CropRect* cropRect) {
174 if (!channel_selector_type_is_valid(xChannelSelector) ||
175 !channel_selector_type_is_valid(yChannelSelector)) {
176 return nullptr;
177 }
178
179 SkImageFilter* inputs[2] = { displacement, color };
180 return new SkDisplacementMapEffect(xChannelSelector, yChannelSelector, scale, inputs, cropRect);
181 }
182
SkDisplacementMapEffect(ChannelSelectorType xChannelSelector,ChannelSelectorType yChannelSelector,SkScalar scale,SkImageFilter * inputs[2],const CropRect * cropRect)183 SkDisplacementMapEffect::SkDisplacementMapEffect(ChannelSelectorType xChannelSelector,
184 ChannelSelectorType yChannelSelector,
185 SkScalar scale,
186 SkImageFilter* inputs[2],
187 const CropRect* cropRect)
188 : INHERITED(2, inputs, cropRect)
189 , fXChannelSelector(xChannelSelector)
190 , fYChannelSelector(yChannelSelector)
191 , fScale(scale)
192 {
193 }
194
~SkDisplacementMapEffect()195 SkDisplacementMapEffect::~SkDisplacementMapEffect() {
196 }
197
CreateProc(SkReadBuffer & buffer)198 SkFlattenable* SkDisplacementMapEffect::CreateProc(SkReadBuffer& buffer) {
199 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 2);
200 ChannelSelectorType xsel = (ChannelSelectorType)buffer.readInt();
201 ChannelSelectorType ysel = (ChannelSelectorType)buffer.readInt();
202 SkScalar scale = buffer.readScalar();
203 return Create(xsel, ysel, scale, common.getInput(0), common.getInput(1), &common.cropRect());
204 }
205
flatten(SkWriteBuffer & buffer) const206 void SkDisplacementMapEffect::flatten(SkWriteBuffer& buffer) const {
207 this->INHERITED::flatten(buffer);
208 buffer.writeInt((int) fXChannelSelector);
209 buffer.writeInt((int) fYChannelSelector);
210 buffer.writeScalar(fScale);
211 }
212
onFilterImageDeprecated(Proxy * proxy,const SkBitmap & src,const Context & ctx,SkBitmap * dst,SkIPoint * offset) const213 bool SkDisplacementMapEffect::onFilterImageDeprecated(Proxy* proxy,
214 const SkBitmap& src,
215 const Context& ctx,
216 SkBitmap* dst,
217 SkIPoint* offset) const {
218 SkBitmap displ = src, color = src;
219 SkIPoint colorOffset = SkIPoint::Make(0, 0), displOffset = SkIPoint::Make(0, 0);
220 if (!this->filterInputDeprecated(1, proxy, src, ctx, &color, &colorOffset) ||
221 !this->filterInputDeprecated(0, proxy, src, ctx, &displ, &displOffset)) {
222 return false;
223 }
224 if ((displ.colorType() != kN32_SkColorType) ||
225 (color.colorType() != kN32_SkColorType)) {
226 return false;
227 }
228 SkIRect bounds;
229 // Since computeDisplacement does bounds checking on color pixel access, we don't need to pad
230 // the color bitmap to bounds here.
231 SkIRect srcBounds = color.bounds();
232 srcBounds.offset(colorOffset);
233 if (!this->applyCropRect(ctx, srcBounds, &bounds)) {
234 return false;
235 }
236 SkIRect displBounds;
237 if (!this->applyCropRectDeprecated(ctx, proxy, displ, &displOffset, &displBounds, &displ)) {
238 return false;
239 }
240 if (!bounds.intersect(displBounds)) {
241 return false;
242 }
243 SkAutoLockPixels alp_displacement(displ), alp_color(color);
244 if (!displ.getPixels() || !color.getPixels()) {
245 return false;
246 }
247
248 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
249 if (!device) {
250 return false;
251 }
252 *dst = device->accessBitmap(false);
253 SkAutoLockPixels alp_dst(*dst);
254
255 SkVector scale = SkVector::Make(fScale, fScale);
256 ctx.ctm().mapVectors(&scale, 1);
257 SkIRect colorBounds = bounds;
258 colorBounds.offset(-colorOffset);
259
260 computeDisplacement(fXChannelSelector, fYChannelSelector, scale, dst,
261 &displ, colorOffset - displOffset, &color, colorBounds);
262
263 offset->fX = bounds.left();
264 offset->fY = bounds.top();
265 return true;
266 }
267
computeFastBounds(const SkRect & src,SkRect * dst) const268 void SkDisplacementMapEffect::computeFastBounds(const SkRect& src, SkRect* dst) const {
269 if (this->getColorInput()) {
270 this->getColorInput()->computeFastBounds(src, dst);
271 } else {
272 *dst = src;
273 }
274 dst->outset(SkScalarAbs(fScale) * SK_ScalarHalf, SkScalarAbs(fScale) * SK_ScalarHalf);
275 }
276
onFilterNodeBounds(const SkIRect & src,const SkMatrix & ctm,SkIRect * dst,MapDirection) const277 void SkDisplacementMapEffect::onFilterNodeBounds(const SkIRect& src, const SkMatrix& ctm,
278 SkIRect* dst, MapDirection) const {
279 *dst = src;
280 SkVector scale = SkVector::Make(fScale, fScale);
281 ctm.mapVectors(&scale, 1);
282 dst->outset(SkScalarCeilToInt(SkScalarAbs(scale.fX) * SK_ScalarHalf),
283 SkScalarCeilToInt(SkScalarAbs(scale.fY) * SK_ScalarHalf));
284 }
285
onFilterBounds(const SkIRect & src,const SkMatrix & ctm,SkIRect * dst,MapDirection direction) const286 bool SkDisplacementMapEffect::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
287 SkIRect* dst, MapDirection direction) const {
288 // Recurse only into color input.
289 if (this->getColorInput()) {
290 return this->getColorInput()->filterBounds(src, ctm, dst, direction);
291 }
292 *dst = src;
293 return true;
294 }
295
296 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const297 void SkDisplacementMapEffect::toString(SkString* str) const {
298 str->appendf("SkDisplacementMapEffect: (");
299 str->appendf("scale: %f ", fScale);
300 str->appendf("displacement: (");
301 if (this->getDisplacementInput()) {
302 this->getDisplacementInput()->toString(str);
303 }
304 str->appendf(") color: (");
305 if (this->getColorInput()) {
306 this->getColorInput()->toString(str);
307 }
308 str->appendf("))");
309 }
310 #endif
311
312 ///////////////////////////////////////////////////////////////////////////////
313
314 #if SK_SUPPORT_GPU
315 class GrGLDisplacementMapEffect : public GrGLSLFragmentProcessor {
316 public:
317 void emitCode(EmitArgs&) override;
318
319 static inline void GenKey(const GrProcessor&, const GrGLSLCaps&, GrProcessorKeyBuilder*);
320
321 protected:
322 void onSetData(const GrGLSLProgramDataManager&, const GrProcessor&) override;
323
324 private:
325 GrGLSLProgramDataManager::UniformHandle fScaleUni;
326 GrTextureDomain::GLDomain fGLDomain;
327
328 typedef GrGLSLFragmentProcessor INHERITED;
329 };
330
331 ///////////////////////////////////////////////////////////////////////////////
332
333 class GrDisplacementMapEffect : public GrFragmentProcessor {
334 public:
Create(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,SkVector scale,GrTexture * displacement,const SkMatrix & offsetMatrix,GrTexture * color,const SkISize & colorDimensions)335 static GrFragmentProcessor* Create(
336 SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
337 SkDisplacementMapEffect::ChannelSelectorType yChannelSelector, SkVector scale,
338 GrTexture* displacement, const SkMatrix& offsetMatrix, GrTexture* color,
339 const SkISize& colorDimensions) {
340 return new GrDisplacementMapEffect(xChannelSelector, yChannelSelector, scale, displacement,
341 offsetMatrix, color, colorDimensions);
342 }
343
344 virtual ~GrDisplacementMapEffect();
345
xChannelSelector() const346 SkDisplacementMapEffect::ChannelSelectorType xChannelSelector() const
347 { return fXChannelSelector; }
yChannelSelector() const348 SkDisplacementMapEffect::ChannelSelectorType yChannelSelector() const
349 { return fYChannelSelector; }
scale() const350 const SkVector& scale() const { return fScale; }
351
name() const352 const char* name() const override { return "DisplacementMap"; }
domain() const353 const GrTextureDomain& domain() const { return fDomain; }
354
355 private:
onCreateGLSLInstance() const356 GrGLSLFragmentProcessor* onCreateGLSLInstance() const override {
357 return new GrGLDisplacementMapEffect;
358 }
359
onGetGLSLProcessorKey(const GrGLSLCaps & caps,GrProcessorKeyBuilder * b) const360 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) const override {
361 GrGLDisplacementMapEffect::GenKey(*this, caps, b);
362 }
363
364 bool onIsEqual(const GrFragmentProcessor&) const override;
365
366 void onComputeInvariantOutput(GrInvariantOutput* inout) const override;
367
368 GrDisplacementMapEffect(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
369 SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
370 const SkVector& scale,
371 GrTexture* displacement, const SkMatrix& offsetMatrix,
372 GrTexture* color,
373 const SkISize& colorDimensions);
374
375 GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
376
377 GrCoordTransform fDisplacementTransform;
378 GrTextureAccess fDisplacementAccess;
379 GrCoordTransform fColorTransform;
380 GrTextureDomain fDomain;
381 GrTextureAccess fColorAccess;
382 SkDisplacementMapEffect::ChannelSelectorType fXChannelSelector;
383 SkDisplacementMapEffect::ChannelSelectorType fYChannelSelector;
384 SkVector fScale;
385
386 typedef GrFragmentProcessor INHERITED;
387 };
388
filterImageGPUDeprecated(Proxy * proxy,const SkBitmap & src,const Context & ctx,SkBitmap * result,SkIPoint * offset) const389 bool SkDisplacementMapEffect::filterImageGPUDeprecated(Proxy* proxy, const SkBitmap& src,
390 const Context& ctx,
391 SkBitmap* result, SkIPoint* offset) const {
392 SkBitmap colorBM = src;
393 SkIPoint colorOffset = SkIPoint::Make(0, 0);
394 if (!this->filterInputGPUDeprecated(1, proxy, src, ctx, &colorBM, &colorOffset)) {
395 return false;
396 }
397 SkBitmap displacementBM = src;
398 SkIPoint displacementOffset = SkIPoint::Make(0, 0);
399 if (!this->filterInputGPUDeprecated(0, proxy, src, ctx, &displacementBM, &displacementOffset)) {
400 return false;
401 }
402 SkIRect srcBounds = colorBM.bounds();
403 srcBounds.offset(colorOffset);
404 SkIRect bounds;
405 // Since GrDisplacementMapEffect does bounds checking on color pixel access, we don't need to
406 // pad the color bitmap to bounds here.
407 if (!this->applyCropRect(ctx, srcBounds, &bounds)) {
408 return false;
409 }
410 SkIRect displBounds;
411 if (!this->applyCropRectDeprecated(ctx, proxy, displacementBM,
412 &displacementOffset, &displBounds, &displacementBM)) {
413 return false;
414 }
415 if (!bounds.intersect(displBounds)) {
416 return false;
417 }
418 GrTexture* color = colorBM.getTexture();
419 GrTexture* displacement = displacementBM.getTexture();
420 GrContext* context = color->getContext();
421
422 GrSurfaceDesc desc;
423 desc.fFlags = kRenderTarget_GrSurfaceFlag;
424 desc.fWidth = bounds.width();
425 desc.fHeight = bounds.height();
426 desc.fConfig = kSkia8888_GrPixelConfig;
427
428 SkAutoTUnref<GrTexture> dst(context->textureProvider()->createApproxTexture(desc));
429
430 if (!dst) {
431 return false;
432 }
433
434 SkVector scale = SkVector::Make(fScale, fScale);
435 ctx.ctm().mapVectors(&scale, 1);
436
437 GrPaint paint;
438 SkMatrix offsetMatrix = GrCoordTransform::MakeDivByTextureWHMatrix(displacement);
439 offsetMatrix.preTranslate(SkIntToScalar(colorOffset.fX - displacementOffset.fX),
440 SkIntToScalar(colorOffset.fY - displacementOffset.fY));
441
442 paint.addColorFragmentProcessor(
443 GrDisplacementMapEffect::Create(fXChannelSelector,
444 fYChannelSelector,
445 scale,
446 displacement,
447 offsetMatrix,
448 color,
449 colorBM.dimensions()))->unref();
450 paint.setPorterDuffXPFactory(SkXfermode::kSrc_Mode);
451 SkIRect colorBounds = bounds;
452 colorBounds.offset(-colorOffset);
453 SkMatrix matrix;
454 matrix.setTranslate(-SkIntToScalar(colorBounds.x()),
455 -SkIntToScalar(colorBounds.y()));
456
457 SkAutoTUnref<GrDrawContext> drawContext(context->drawContext(dst->asRenderTarget()));
458 if (!drawContext) {
459 return false;
460 }
461
462 drawContext->drawRect(GrClip::WideOpen(), paint, matrix, SkRect::Make(colorBounds));
463 offset->fX = bounds.left();
464 offset->fY = bounds.top();
465 GrWrapTextureInBitmap(dst, bounds.width(), bounds.height(), false, result);
466 return true;
467 }
468
469 ///////////////////////////////////////////////////////////////////////////////
470
GrDisplacementMapEffect(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,const SkVector & scale,GrTexture * displacement,const SkMatrix & offsetMatrix,GrTexture * color,const SkISize & colorDimensions)471 GrDisplacementMapEffect::GrDisplacementMapEffect(
472 SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
473 SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
474 const SkVector& scale,
475 GrTexture* displacement,
476 const SkMatrix& offsetMatrix,
477 GrTexture* color,
478 const SkISize& colorDimensions)
479 : fDisplacementTransform(kLocal_GrCoordSet, offsetMatrix, displacement,
480 GrTextureParams::kNone_FilterMode)
481 , fDisplacementAccess(displacement)
482 , fColorTransform(kLocal_GrCoordSet, color, GrTextureParams::kNone_FilterMode)
483 , fDomain(GrTextureDomain::MakeTexelDomain(color, SkIRect::MakeSize(colorDimensions)),
484 GrTextureDomain::kDecal_Mode)
485 , fColorAccess(color)
486 , fXChannelSelector(xChannelSelector)
487 , fYChannelSelector(yChannelSelector)
488 , fScale(scale) {
489 this->initClassID<GrDisplacementMapEffect>();
490 this->addCoordTransform(&fDisplacementTransform);
491 this->addTextureAccess(&fDisplacementAccess);
492 this->addCoordTransform(&fColorTransform);
493 this->addTextureAccess(&fColorAccess);
494 }
495
~GrDisplacementMapEffect()496 GrDisplacementMapEffect::~GrDisplacementMapEffect() {
497 }
498
onIsEqual(const GrFragmentProcessor & sBase) const499 bool GrDisplacementMapEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
500 const GrDisplacementMapEffect& s = sBase.cast<GrDisplacementMapEffect>();
501 return fXChannelSelector == s.fXChannelSelector &&
502 fYChannelSelector == s.fYChannelSelector &&
503 fScale == s.fScale;
504 }
505
onComputeInvariantOutput(GrInvariantOutput * inout) const506 void GrDisplacementMapEffect::onComputeInvariantOutput(GrInvariantOutput* inout) const {
507 // Any displacement offset bringing a pixel out of bounds will output a color of (0,0,0,0),
508 // so the only way we'd get a constant alpha is if the input color image has a constant alpha
509 // and no displacement offset push any texture coordinates out of bounds OR if the constant
510 // alpha is 0. Since this isn't trivial to compute at this point, let's assume the output is
511 // not of constant color when a displacement effect is applied.
512 inout->setToUnknown(GrInvariantOutput::kWillNot_ReadInput);
513 }
514
515 ///////////////////////////////////////////////////////////////////////////////
516
517 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDisplacementMapEffect);
518
TestCreate(GrProcessorTestData * d)519 const GrFragmentProcessor* GrDisplacementMapEffect::TestCreate(GrProcessorTestData* d) {
520 int texIdxDispl = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
521 GrProcessorUnitTest::kAlphaTextureIdx;
522 int texIdxColor = d->fRandom->nextBool() ? GrProcessorUnitTest::kSkiaPMTextureIdx :
523 GrProcessorUnitTest::kAlphaTextureIdx;
524 static const int kMaxComponent = 4;
525 SkDisplacementMapEffect::ChannelSelectorType xChannelSelector =
526 static_cast<SkDisplacementMapEffect::ChannelSelectorType>(
527 d->fRandom->nextRangeU(1, kMaxComponent));
528 SkDisplacementMapEffect::ChannelSelectorType yChannelSelector =
529 static_cast<SkDisplacementMapEffect::ChannelSelectorType>(
530 d->fRandom->nextRangeU(1, kMaxComponent));
531 SkVector scale = SkVector::Make(d->fRandom->nextRangeScalar(0, 100.0f),
532 d->fRandom->nextRangeScalar(0, 100.0f));
533 SkISize colorDimensions;
534 colorDimensions.fWidth = d->fRandom->nextRangeU(0, d->fTextures[texIdxColor]->width());
535 colorDimensions.fHeight = d->fRandom->nextRangeU(0, d->fTextures[texIdxColor]->height());
536 return GrDisplacementMapEffect::Create(xChannelSelector, yChannelSelector, scale,
537 d->fTextures[texIdxDispl], SkMatrix::I(),
538 d->fTextures[texIdxColor], colorDimensions);
539 }
540
541 ///////////////////////////////////////////////////////////////////////////////
542
emitCode(EmitArgs & args)543 void GrGLDisplacementMapEffect::emitCode(EmitArgs& args) {
544 const GrDisplacementMapEffect& displacementMap = args.fFp.cast<GrDisplacementMapEffect>();
545 const GrTextureDomain& domain = displacementMap.domain();
546
547 fScaleUni = args.fUniformHandler->addUniform(kFragment_GrShaderFlag,
548 kVec2f_GrSLType, kDefault_GrSLPrecision, "Scale");
549 const char* scaleUni = args.fUniformHandler->getUniformCStr(fScaleUni);
550 const char* dColor = "dColor";
551 const char* cCoords = "cCoords";
552 const char* nearZero = "1e-6"; // Since 6.10352e−5 is the smallest half float, use
553 // a number smaller than that to approximate 0, but
554 // leave room for 32-bit float GPU rounding errors.
555
556 GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder;
557 fragBuilder->codeAppendf("\t\tvec4 %s = ", dColor);
558 fragBuilder->appendTextureLookup(args.fSamplers[0], args.fCoords[0].c_str(),
559 args.fCoords[0].getType());
560 fragBuilder->codeAppend(";\n");
561
562 // Unpremultiply the displacement
563 fragBuilder->codeAppendf(
564 "\t\t%s.rgb = (%s.a < %s) ? vec3(0.0) : clamp(%s.rgb / %s.a, 0.0, 1.0);",
565 dColor, dColor, nearZero, dColor, dColor);
566 SkString coords2D = fragBuilder->ensureFSCoords2D(args.fCoords, 1);
567 fragBuilder->codeAppendf("\t\tvec2 %s = %s + %s*(%s.",
568 cCoords, coords2D.c_str(), scaleUni, dColor);
569
570 switch (displacementMap.xChannelSelector()) {
571 case SkDisplacementMapEffect::kR_ChannelSelectorType:
572 fragBuilder->codeAppend("r");
573 break;
574 case SkDisplacementMapEffect::kG_ChannelSelectorType:
575 fragBuilder->codeAppend("g");
576 break;
577 case SkDisplacementMapEffect::kB_ChannelSelectorType:
578 fragBuilder->codeAppend("b");
579 break;
580 case SkDisplacementMapEffect::kA_ChannelSelectorType:
581 fragBuilder->codeAppend("a");
582 break;
583 case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
584 default:
585 SkDEBUGFAIL("Unknown X channel selector");
586 }
587
588 switch (displacementMap.yChannelSelector()) {
589 case SkDisplacementMapEffect::kR_ChannelSelectorType:
590 fragBuilder->codeAppend("r");
591 break;
592 case SkDisplacementMapEffect::kG_ChannelSelectorType:
593 fragBuilder->codeAppend("g");
594 break;
595 case SkDisplacementMapEffect::kB_ChannelSelectorType:
596 fragBuilder->codeAppend("b");
597 break;
598 case SkDisplacementMapEffect::kA_ChannelSelectorType:
599 fragBuilder->codeAppend("a");
600 break;
601 case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
602 default:
603 SkDEBUGFAIL("Unknown Y channel selector");
604 }
605 fragBuilder->codeAppend("-vec2(0.5));\t\t");
606
607 fGLDomain.sampleTexture(fragBuilder,
608 args.fUniformHandler,
609 args.fGLSLCaps,
610 domain,
611 args.fOutputColor,
612 SkString(cCoords),
613 args.fSamplers[1]);
614 fragBuilder->codeAppend(";\n");
615 }
616
onSetData(const GrGLSLProgramDataManager & pdman,const GrProcessor & proc)617 void GrGLDisplacementMapEffect::onSetData(const GrGLSLProgramDataManager& pdman,
618 const GrProcessor& proc) {
619 const GrDisplacementMapEffect& displacementMap = proc.cast<GrDisplacementMapEffect>();
620 GrTexture* colorTex = displacementMap.texture(1);
621 SkScalar scaleX = displacementMap.scale().fX / colorTex->width();
622 SkScalar scaleY = displacementMap.scale().fY / colorTex->height();
623 pdman.set2f(fScaleUni, SkScalarToFloat(scaleX),
624 colorTex->origin() == kTopLeft_GrSurfaceOrigin ?
625 SkScalarToFloat(scaleY) : SkScalarToFloat(-scaleY));
626 fGLDomain.setData(pdman, displacementMap.domain(), colorTex->origin());
627 }
628
GenKey(const GrProcessor & proc,const GrGLSLCaps &,GrProcessorKeyBuilder * b)629 void GrGLDisplacementMapEffect::GenKey(const GrProcessor& proc,
630 const GrGLSLCaps&, GrProcessorKeyBuilder* b) {
631 const GrDisplacementMapEffect& displacementMap = proc.cast<GrDisplacementMapEffect>();
632
633 uint32_t xKey = displacementMap.xChannelSelector();
634 uint32_t yKey = displacementMap.yChannelSelector() << kChannelSelectorKeyBits;
635
636 b->add32(xKey | yKey);
637 }
638 #endif
639
640