Update To 11.40.268.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(GrGLFPBuilder*,
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 private:
355     virtual bool onIsEqual(const GrFragmentProcessor&) const SK_OVERRIDE;
356
357     virtual void onComputeInvariantOutput(InvariantOutput* inout) 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     GrSurfaceDesc desc;
412     desc.fFlags = kRenderTarget_GrSurfaceFlag | kNoStencil_GrSurfaceFlag;
413     desc.fWidth = bounds.width();
414     desc.fHeight = bounds.height();
415     desc.fConfig = kSkia8888_GrPixelConfig;
416
417     SkAutoTUnref<GrTexture> dst(
418         context->refScratchTexture(desc, GrContext::kApprox_ScratchTexMatch));
419
420     if (!dst) {
421         return false;
422     }
423
424     GrContext::AutoRenderTarget art(context, dst->asRenderTarget());
425
426     SkVector scale = SkVector::Make(fScale, fScale);
427     ctx.ctm().mapVectors(&scale, 1);
428
429     GrPaint paint;
430     SkMatrix offsetMatrix = GrCoordTransform::MakeDivByTextureWHMatrix(displacement);
431     offsetMatrix.preTranslate(SkIntToScalar(colorOffset.fX - displacementOffset.fX),
432                               SkIntToScalar(colorOffset.fY - displacementOffset.fY));
433
434     paint.addColorProcessor(
435         GrDisplacementMapEffect::Create(fXChannelSelector,
436                                         fYChannelSelector,
437                                         scale,
438                                         displacement,
439                                         offsetMatrix,
440                                         color))->unref();
441     SkIRect colorBounds = bounds;
442     colorBounds.offset(-colorOffset);
443     GrContext::AutoMatrix am;
444     am.setIdentity(context);
445     SkMatrix matrix;
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);
453     return true;
454 }
455
456 ///////////////////////////////////////////////////////////////////////////////
457
458 GrDisplacementMapEffect::GrDisplacementMapEffect(
459                              SkDisplacementMapEffect::ChannelSelectorType xChannelSelector,
460                              SkDisplacementMapEffect::ChannelSelectorType yChannelSelector,
461                              const SkVector& scale,
462                              GrTexture* displacement,
463                              const SkMatrix& offsetMatrix,
464                              GrTexture* color)
465     : fDisplacementTransform(kLocal_GrCoordSet, offsetMatrix, displacement)
466     , fDisplacementAccess(displacement)
467     , fColorTransform(kLocal_GrCoordSet, color)
468     , fColorAccess(color)
469     , fXChannelSelector(xChannelSelector)
470     , fYChannelSelector(yChannelSelector)
471     , fScale(scale) {
472     this->addCoordTransform(&fDisplacementTransform);
473     this->addTextureAccess(&fDisplacementAccess);
474     this->addCoordTransform(&fColorTransform);
475     this->addTextureAccess(&fColorAccess);
476 }
477
478 GrDisplacementMapEffect::~GrDisplacementMapEffect() {
479 }
480
481 bool GrDisplacementMapEffect::onIsEqual(const GrFragmentProcessor& sBase) const {
482     const GrDisplacementMapEffect& s = sBase.cast<GrDisplacementMapEffect>();
483     return fXChannelSelector == s.fXChannelSelector &&
484            fYChannelSelector == s.fYChannelSelector &&
485            fScale == s.fScale;
486 }
487
488 const GrBackendFragmentProcessorFactory& GrDisplacementMapEffect::getFactory() const {
489     return GrTBackendFragmentProcessorFactory<GrDisplacementMapEffect>::getInstance();
490 }
491
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);
499 }
500
501 ///////////////////////////////////////////////////////////////////////////////
502
503 GR_DEFINE_FRAGMENT_PROCESSOR_TEST(GrDisplacementMapEffect);
504
505 GrFragmentProcessor* GrDisplacementMapEffect::TestCreate(SkRandom* random,
506                                               GrContext*,
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));
522
523     return GrDisplacementMapEffect::Create(xChannelSelector, yChannelSelector, scale,
524                                            textures[texIdxDispl], SkMatrix::I(),
525                                            textures[texIdxColor]);
526 }
527
528 ///////////////////////////////////////////////////////////////////////////////
529
530 GrGLDisplacementMapEffect::GrGLDisplacementMapEffect(const GrBackendProcessorFactory& factory,
531                                                      const GrProcessor& proc)
532     : INHERITED(factory)
533     , fXChannelSelector(proc.cast<GrDisplacementMapEffect>().xChannelSelector())
534     , fYChannelSelector(proc.cast<GrDisplacementMapEffect>().yChannelSelector()) {
535 }
536
537 GrGLDisplacementMapEffect::~GrGLDisplacementMapEffect() {
538 }
539
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);
548
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.
558
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");
563
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);
567
568     fsBuilder->codeAppendf("\t\tvec2 %s = %s + %s*(%s.",
569                            cCoords, coords[1].c_str(), scaleUni, dColor);
570
571     switch (fXChannelSelector) {
572       case SkDisplacementMapEffect::kR_ChannelSelectorType:
573         fsBuilder->codeAppend("r");
574         break;
575       case SkDisplacementMapEffect::kG_ChannelSelectorType:
576         fsBuilder->codeAppend("g");
577         break;
578       case SkDisplacementMapEffect::kB_ChannelSelectorType:
579         fsBuilder->codeAppend("b");
580         break;
581       case SkDisplacementMapEffect::kA_ChannelSelectorType:
582         fsBuilder->codeAppend("a");
583         break;
584       case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
585       default:
586         SkDEBUGFAIL("Unknown X channel selector");
587     }
588
589     switch (fYChannelSelector) {
590       case SkDisplacementMapEffect::kR_ChannelSelectorType:
591         fsBuilder->codeAppend("r");
592         break;
593       case SkDisplacementMapEffect::kG_ChannelSelectorType:
594         fsBuilder->codeAppend("g");
595         break;
596       case SkDisplacementMapEffect::kB_ChannelSelectorType:
597         fsBuilder->codeAppend("b");
598         break;
599       case SkDisplacementMapEffect::kA_ChannelSelectorType:
600         fsBuilder->codeAppend("a");
601         break;
602       case SkDisplacementMapEffect::kUnknown_ChannelSelectorType:
603       default:
604         SkDEBUGFAIL("Unknown Y channel selector");
605     }
606     fsBuilder->codeAppend("-vec2(0.5));\t\t");
607
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");
616 }
617
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));
627 }
628
629 void GrGLDisplacementMapEffect::GenKey(const GrProcessor& proc,
630                                        const GrGLCaps&, 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