Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / effects / SkDisplacementMapEffect.cpp
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 "SkReadBuffer.h"
10 #include "SkWriteBuffer.h"
11 #include "SkUnPreMultiply.h"
12 #include "SkColorPriv.h"
13 #if SK_SUPPORT_GPU
14 #include "GrContext.h"
15 #include "GrCoordTransform.h"
16 #include "gl/GrGLProcessor.h"
17 #include "gl/builders/GrGLProgramBuilder.h"
18 #include "GrTBackendProcessorFactory.h"
19 #endif
20
21 namespace {
22
23 #define kChannelSelectorKeyBits 3; // Max value is 4, so 3 bits are required at most
24
25 template<SkDisplacementMapEffect::ChannelSelectorType type>
26 uint32_t getValue(SkColor, const SkUnPreMultiply::Scale*) {
27     SkDEBUGFAIL("Unknown channel selector");
28     return 0;
29 }
30
31 template<> uint32_t getValue<SkDisplacementMapEffect::kR_ChannelSelectorType>(
32     SkColor l, const SkUnPreMultiply::Scale* table) {
33     return SkUnPreMultiply::ApplyScale(table[SkGetPackedA32(l)], SkGetPackedR32(l));
34 }
35
36 template<> uint32_t getValue<SkDisplacementMapEffect::kG_ChannelSelectorType>(
37     SkColor l, const SkUnPreMultiply::Scale* table) {
38     return SkUnPreMultiply::ApplyScale(table[SkGetPackedA32(l)], SkGetPackedG32(l));
39 }
40
41 template<> uint32_t getValue<SkDisplacementMapEffect::kB_ChannelSelectorType>(
42     SkColor l, const SkUnPreMultiply::Scale* table) {
43     return SkUnPreMultiply::ApplyScale(table[SkGetPackedA32(l)], SkGetPackedB32(l));
44 }
45
46 template<> uint32_t getValue<SkDisplacementMapEffect::kA_ChannelSelectorType>(
47     SkColor l, const SkUnPreMultiply::Scale*) {
48     return SkGetPackedA32(l);
49 }
50
51 template<SkDisplacementMapEffect::ChannelSelectorType typeX,
52          SkDisplacementMapEffect::ChannelSelectorType typeY>
53 void computeDisplacement(const SkVector& scale, SkBitmap* dst,
54                          SkBitmap* displ, const SkIPoint& offset,
55                          SkBitmap* src,
56                          const SkIRect& bounds)
57 {
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,
69                                                      y + offset.fY);
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));
80         }
81     }
82 }
83
84 template<SkDisplacementMapEffect::ChannelSelectorType typeX>
85 void computeDisplacement(SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
86                          const SkVector& scale, SkBitmap* dst,
87                          SkBitmap* displ, const SkIPoint& offset,
88                          SkBitmap* src,
89                          const SkIRect& bounds)
90 {
91     switch (yChannelSelector) {
92       case SkDisplacementMapEffect::kR_ChannelSelectorType:
93         computeDisplacement<typeX, SkDisplacementMapEffect::kR_ChannelSelectorType>(
94             scale, dst, displ, offset, src, bounds);
95         break;
96       case SkDisplacementMapEffect::kG_ChannelSelectorType:
97         computeDisplacement<typeX, SkDisplacementMapEffect::kG_ChannelSelectorType>(
98             scale, dst, displ, offset, src, bounds);
99         break;
100       case SkDisplacementMapEffect::kB_ChannelSelectorType:
101         computeDisplacement<typeX, SkDisplacementMapEffect::kB_ChannelSelectorType>(
102             scale, dst, displ, offset, src, bounds);
103         break;
104       case SkDisplacementMapEffect::kA_ChannelSelectorType:
105         computeDisplacement<typeX, SkDisplacementMapEffect::kA_ChannelSelectorType>(
106             scale, dst, displ, offset, src, bounds);
107         break;
108       case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
109       default:
110         SkDEBUGFAIL("Unknown Y channel selector");
111     }
112 }
113
114 void computeDisplacement(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
115                          SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
116                          const SkVector& scale, SkBitmap* dst,
117                          SkBitmap* displ, const SkIPoint& offset,
118                          SkBitmap* src,
119                          const SkIRect& bounds)
120 {
121     switch (xChannelSelector) {
122       case SkDisplacementMapEffect::kR_ChannelSelectorType:
123         computeDisplacement<SkDisplacementMapEffect::kR_ChannelSelectorType>(
124             yChannelSelector, scale, dst, displ, offset, src, bounds);
125         break;
126       case SkDisplacementMapEffect::kG_ChannelSelectorType:
127         computeDisplacement<SkDisplacementMapEffect::kG_ChannelSelectorType>(
128             yChannelSelector, scale, dst, displ, offset, src, bounds);
129         break;
130       case SkDisplacementMapEffect::kB_ChannelSelectorType:
131         computeDisplacement<SkDisplacementMapEffect::kB_ChannelSelectorType>(
132             yChannelSelector, scale, dst, displ, offset, src, bounds);
133         break;
134       case SkDisplacementMapEffect::kA_ChannelSelectorType:
135         computeDisplacement<SkDisplacementMapEffect::kA_ChannelSelectorType>(
136             yChannelSelector, scale, dst, displ, offset, src, bounds);
137         break;
138       case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
139       default:
140         SkDEBUGFAIL("Unknown X channel selector");
141     }
142 }
143
144 bool channel_selector_type_is_valid(SkDisplacementMapEffect::ChannelSelectorType cst) {
145     switch (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:
151         return true;
152     default:
153         break;
154     }
155     return false;
156 }
157
158 } // end namespace
159
160 ///////////////////////////////////////////////////////////////////////////////
161
162 SkDisplacementMapEffect* SkDisplacementMapEffect::Create(ChannelSelectorType xChannelSelector,
163                                                          ChannelSelectorType yChannelSelector,
164                                                          SkScalar scale,
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)) {
170         return NULL;
171     }
172
173     SkImageFilter* inputs[2] = { displacement, color };
174     return SkNEW_ARGS(SkDisplacementMapEffect, (xChannelSelector, yChannelSelector, scale,
175                                                 inputs, cropRect, uniqueID));
176 }
177
178 SkDisplacementMapEffect::SkDisplacementMapEffect(ChannelSelectorType xChannelSelector,
179                                                  ChannelSelectorType yChannelSelector,
180                                                  SkScalar scale,
181                                                  SkImageFilter* inputs[2],
182                                                  const CropRect* cropRect,
183                                                  uint32_t uniqueID)
184   : INHERITED(2, inputs, cropRect, uniqueID)
185   , fXChannelSelector(xChannelSelector)
186   , fYChannelSelector(yChannelSelector)
187   , fScale(scale)
188 {
189 }
190
191 SkDisplacementMapEffect::~SkDisplacementMapEffect() {
192 }
193
194 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
195 SkDisplacementMapEffect::SkDisplacementMapEffect(SkReadBuffer& buffer)
196   : INHERITED(2, buffer)
197 {
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));
204 }
205 #endif
206
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());
213 }
214
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);
220 }
221
222 bool SkDisplacementMapEffect::onFilterImage(Proxy* proxy,
223                                             const SkBitmap& src,
224                                             const Context& ctx,
225                                             SkBitmap* dst,
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))) {
233         return false;
234     }
235     if ((displ.colorType() != kN32_SkColorType) ||
236         (color.colorType() != kN32_SkColorType)) {
237         return false;
238     }
239     SkIRect bounds;
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)) {
243         return false;
244     }
245     SkIRect displBounds;
246     if (!this->applyCropRect(ctx, proxy, displ, &displOffset, &displBounds, &displ)) {
247         return false;
248     }
249     if (!bounds.intersect(displBounds)) {
250         return false;
251     }
252     SkAutoLockPixels alp_displacement(displ), alp_color(color);
253     if (!displ.getPixels() || !color.getPixels()) {
254         return false;
255     }
256
257     if (!dst->tryAllocPixels(color.info().makeWH(bounds.width(), bounds.height()))) {
258         return false;
259     }
260
261     SkVector scale = SkVector::Make(fScale, fScale);
262     ctx.ctm().mapVectors(&scale, 1);
263     SkIRect colorBounds = bounds;
264     colorBounds.offset(-colorOffset);
265
266     computeDisplacement(fXChannelSelector, fYChannelSelector, scale, dst,
267                         &displ, colorOffset - displOffset, &color, colorBounds);
268
269     offset->fX = bounds.left();
270     offset->fY = bounds.top();
271     return true;
272 }
273
274 void SkDisplacementMapEffect::computeFastBounds(const SkRect& src, SkRect* dst) const {
275     if (getColorInput()) {
276         getColorInput()->computeFastBounds(src, dst);
277     } else {
278         *dst = src;
279     }
280     dst->outset(fScale * SK_ScalarHalf, fScale * SK_ScalarHalf);
281 }
282
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);
292     }
293     *dst = bounds;
294     return true;
295 }
296
297 ///////////////////////////////////////////////////////////////////////////////
298
299 #if SK_SUPPORT_GPU
300 class GrGLDisplacementMapEffect : public GrGLFragmentProcessor {
301 public:
302     GrGLDisplacementMapEffect(const GrBackendProcessorFactory&,
303                               const GrProcessor&);
304     virtual ~GrGLDisplacementMapEffect();
305
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;
313
314     static inline void GenKey(const GrProcessor&, const GrGLCaps&, GrProcessorKeyBuilder*);
315
316     virtual void setData(const GrGLProgramDataManager&, const GrProcessor&) SK_OVERRIDE;
317
318 private:
319     SkDisplacementMapEffect::ChannelSelectorType fXChannelSelector;
320     SkDisplacementMapEffect::ChannelSelectorType fYChannelSelector;
321     GrGLProgramDataManager::UniformHandle fScaleUni;
322
323     typedef GrGLFragmentProcessor INHERITED;
324 };
325
326 ///////////////////////////////////////////////////////////////////////////////
327
328 class GrDisplacementMapEffect : public GrFragmentProcessor {
329 public:
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,
335                                                     yChannelSelector,
336                                                     scale,
337                                                     displacement,
338                                                     offsetMatrix,
339                                                     color));
340     }
341
342     virtual ~GrDisplacementMapEffect();
343
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; }
350
351     typedef GrGLDisplacementMapEffect GLProcessor;
352     static const char* Name() { return "DisplacementMap"; }
353
354     virtual void getConstantColorComponents(GrColor* color, uint32_t* validFlags) const SK_OVERRIDE;
355
356 private:
357     virtual bool onIsEqual(const GrProcessor&) const SK_OVERRIDE;
358
359     GrDisplacementMapEffect(SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
360                             SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
361                             const SkVector& scale,
362                             GrTexture* displacement, const SkMatrix& offsetMatrix,
363                             GrTexture* color);
364
365     GR_DECLARE_FRAGMENT_PROCESSOR_TEST;
366
367     GrCoordTransform            fDisplacementTransform;
368     GrTextureAccess             fDisplacementAccess;
369     GrCoordTransform            fColorTransform;
370     GrTextureAccess             fColorAccess;
371     SkDisplacementMapEffect::ChannelSelectorType fXChannelSelector;
372     SkDisplacementMapEffect::ChannelSelectorType fYChannelSelector;
373     SkVector fScale;
374
375     typedef GrFragmentProcessor INHERITED;
376 };
377
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,
383                                                                &colorOffset)) {
384         return false;
385     }
386     SkBitmap displacementBM = src;
387     SkIPoint displacementOffset = SkIPoint::Make(0, 0);
388     if (getDisplacementInput() &&
389         !getDisplacementInput()->getInputResultGPU(proxy, src, ctx, &displacementBM,
390                                                    &displacementOffset)) {
391         return false;
392     }
393     SkIRect bounds;
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)) {
397         return false;
398     }
399     SkIRect displBounds;
400     if (!this->applyCropRect(ctx, proxy, displacementBM,
401                              &displacementOffset, &displBounds, &displacementBM)) {
402         return false;
403     }
404     if (!bounds.intersect(displBounds)) {
405         return false;
406     }
407     GrTexture* color = colorBM.getTexture();
408     GrTexture* displacement = displacementBM.getTexture();
409     GrContext* context = color->getContext();
410
411     GrTextureDesc desc;
412     desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
413     desc.fWidth = bounds.width();
414     desc.fHeight = bounds.height();
415     desc.fConfig = kSkia8888_GrPixelConfig;
416
417     GrAutoScratchTexture ast(context, desc);
418     if (NULL == ast.texture()) {
419         return false;
420     }
421     SkAutoTUnref<GrTexture> dst(ast.detach());
422
423     GrContext::AutoRenderTarget art(context, dst->asRenderTarget());
424
425     SkVector scale = SkVector::Make(fScale, fScale);
426     ctx.ctm().mapVectors(&scale, 1);
427
428     GrPaint paint;
429     SkMatrix offsetMatrix = GrCoordTransform::MakeDivByTextureWHMatrix(displacement);
430     offsetMatrix.preTranslate(SkIntToScalar(colorOffset.fX - displacementOffset.fX),
431                               SkIntToScalar(colorOffset.fY - displacementOffset.fY));
432
433     paint.addColorProcessor(
434         GrDisplacementMapEffect::Create(fXChannelSelector,
435                                         fYChannelSelector,
436                                         scale,
437                                         displacement,
438                                         offsetMatrix,
439                                         color))->unref();
440     SkIRect colorBounds = bounds;
441     colorBounds.offset(-colorOffset);
442     GrContext::AutoMatrix am;
443     am.setIdentity(context);
444     SkMatrix matrix;
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);
452     return true;
453 }
454
455 ///////////////////////////////////////////////////////////////////////////////
456
457 GrDisplacementMapEffect::GrDisplacementMapEffect(
458                              SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
459                              SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
460                              const SkVector& scale,
461                              GrTexture* displacement,
462                              const SkMatrix& offsetMatrix,
463                              GrTexture* color)
464     : fDisplacementTransform(kLocal_GrCoordSet, offsetMatrix, displacement)
465     , fDisplacementAccess(displacement)
466     , fColorTransform(kLocal_GrCoordSet, color)
467     , fColorAccess(color)
468     , fXChannelSelector(xChannelSelector)
469     , fYChannelSelector(yChannelSelector)
470     , fScale(scale) {
471     this->addCoordTransform(&fDisplacementTransform);
472     this->addTextureAccess(&fDisplacementAccess);
473     this->addCoordTransform(&fColorTransform);
474     this->addTextureAccess(&fColorAccess);
475     this->setWillNotUseInputColor();
476 }
477
478 GrDisplacementMapEffect::~GrDisplacementMapEffect() {
479 }
480
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 &&
487            fScale == s.fScale;
488 }
489
490 const GrBackendFragmentProcessorFactory& GrDisplacementMapEffect::getFactory() const {
491     return GrTBackendFragmentProcessorFactory<GrDisplacementMapEffect>::getInstance();
492 }
493
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.
501     *validFlags = 0;
502 }
503
504 ///////////////////////////////////////////////////////////////////////////////
505
506 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDisplacementMapEffect);
507
508 GrFragmentProcessor* GrDisplacementMapEffect::TestCreate(SkRandom* random,
509                                               GrContext*,
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));
525
526     return GrDisplacementMapEffect::Create(xChannelSelector, yChannelSelector, scale,
527                                            textures[texIdxDispl], SkMatrix::I(),
528                                            textures[texIdxColor]);
529 }
530
531 ///////////////////////////////////////////////////////////////////////////////
532
533 GrGLDisplacementMapEffect::GrGLDisplacementMapEffect(const GrBackendProcessorFactory& factory,
534                                                      const GrProcessor& proc)
535     : INHERITED(factory)
536     , fXChannelSelector(proc.cast<GrDisplacementMapEffect>().xChannelSelector())
537     , fYChannelSelector(proc.cast<GrDisplacementMapEffect>().yChannelSelector()) {
538 }
539
540 GrGLDisplacementMapEffect::~GrGLDisplacementMapEffect() {
541 }
542
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);
551
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.
561
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");
566
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);
570
571     fsBuilder->codeAppendf("\t\tvec2 %s = %s + %s*(%s.",
572                            cCoords, coords[1].c_str(), scaleUni, dColor);
573
574     switch (fXChannelSelector) {
575       case SkDisplacementMapEffect::kR_ChannelSelectorType:
576         fsBuilder->codeAppend("r");
577         break;
578       case SkDisplacementMapEffect::kG_ChannelSelectorType:
579         fsBuilder->codeAppend("g");
580         break;
581       case SkDisplacementMapEffect::kB_ChannelSelectorType:
582         fsBuilder->codeAppend("b");
583         break;
584       case SkDisplacementMapEffect::kA_ChannelSelectorType:
585         fsBuilder->codeAppend("a");
586         break;
587       case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
588       default:
589         SkDEBUGFAIL("Unknown X channel selector");
590     }
591
592     switch (fYChannelSelector) {
593       case SkDisplacementMapEffect::kR_ChannelSelectorType:
594         fsBuilder->codeAppend("r");
595         break;
596       case SkDisplacementMapEffect::kG_ChannelSelectorType:
597         fsBuilder->codeAppend("g");
598         break;
599       case SkDisplacementMapEffect::kB_ChannelSelectorType:
600         fsBuilder->codeAppend("b");
601         break;
602       case SkDisplacementMapEffect::kA_ChannelSelectorType:
603         fsBuilder->codeAppend("a");
604         break;
605       case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
606       default:
607         SkDEBUGFAIL("Unknown Y channel selector");
608     }
609     fsBuilder->codeAppend("-vec2(0.5));\t\t");
610
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");
619 }
620
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));
630 }
631
632 void GrGLDisplacementMapEffect::GenKey(const GrProcessor& proc,
633                                        const GrGLCaps&, GrProcessorKeyBuilder* b) {
634     const GrDisplacementMapEffect& displacementMap = proc.cast<GrDisplacementMapEffect>();
635
636     uint32_t xKey = displacementMap.xChannelSelector();
637     uint32_t yKey = displacementMap.yChannelSelector() << kChannelSelectorKeyBits;
638
639     b->add32(xKey | yKey);
640 }
641 #endif